/*
  VigaTech motion layer — keyframes, scroll-reveal states, entrance choreography,
  marquee motion, the maple leaf's signature animation, page-transition veil,
  and the prefers-reduced-motion fallback. Component structure/base styles
  live in styles.css; this file only ever adds motion on top of it.
*/

/* ---------- Keyframes ---------- */
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(22px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes spinSlow {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
@keyframes leafSway {
  0%, 100% { transform: rotate(-6deg); }
  50% { transform: rotate(6deg); }
}
@keyframes marqueeScroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
@keyframes ringPulse {
  0% { opacity: 0.9; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.5); }
}
@keyframes dotBounce {
  0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
  30% { transform: translateY(-6px); opacity: 1; }
}
@keyframes scrollLine {
  0% { transform: scaleY(0); transform-origin: top; }
  50% { transform: scaleY(1); transform-origin: top; }
  51% { transform: scaleY(1); transform-origin: bottom; }
  100% { transform: scaleY(0); transform-origin: bottom; }
}
@keyframes heroGlow {
  0%, 100% { opacity: 0.55; transform: translate(-50%, -50%) scale(1); }
  50% { opacity: 1; transform: translate(-50%, -50%) scale(1.08); }
}
@keyframes preWordIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes preWordWrite {
  from { clip-path: inset(0 100% 0 0); }
  to { clip-path: inset(0 0% 0 0); }
}
@keyframes preWordOut {
  from { opacity: 1; }
  to { opacity: 0; }
}
@keyframes preDraw {
  from { stroke-dashoffset: var(--dash); }
  to { stroke-dashoffset: 0; }
}
@keyframes preOuterDim {
  0% { opacity: 1; }
  20% { opacity: 0.15; }
  75% { opacity: 0.15; }
  100% { opacity: 1; }
}
@keyframes preLetterIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes preLeafPop {
  0% { opacity: 0; transform: scale(0.5) rotate(-15deg); }
  70% { opacity: 1; transform: scale(1.2) rotate(6deg); }
  100% { opacity: 1; transform: scale(1) rotate(0deg); }
}
@keyframes preFadeOut {
  from { opacity: 1; visibility: visible; }
  to { opacity: 0; visibility: hidden; }
}

/* ---------- Hero entrance choreography ---------- */
.hero-tag, .hero-h1, .hero-sub, .hero-btns { opacity: 0; }
.hero-tag { animation: fadeUp 0.8s 0.15s var(--ease) forwards; }
.hero-h1 { animation: fadeUp 0.8s 0.32s var(--ease) forwards; }
.hero-sub { animation: fadeUp 0.8s 0.5s var(--ease) forwards; }
.hero-btns { animation: fadeUp 0.8s 0.68s var(--ease) forwards; }

.hero-glow {
  position: absolute;
  top: 32%; left: 50%;
  width: 760px; height: 760px;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.05) 0%, transparent 70%);
  pointer-events: none;
  animation: heroGlow 7s ease-in-out infinite;
}

.hero-scroll { animation: fadeIn 1s 1s var(--ease) forwards; opacity: 0; }
.hero-scroll-line { animation: scrollLine 2.2s ease-in-out infinite; }

.nav .brand { opacity: 0; transform: translateY(-8px); transition: opacity 0.6s var(--ease), transform 0.6s var(--ease); }
.nav .brand.is-visible { opacity: 1; transform: translateY(0); }

/* ---------- Scroll reveal ---------- */
.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}
.reveal.is-visible { opacity: 1; transform: translateY(0); }

/* staggered children inside a revealed grid */
.reveal-stagger > * {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}
.reveal-stagger.is-visible > * { opacity: 1; transform: translateY(0); }
.reveal-stagger.is-visible > *:nth-child(1) { transition-delay: 0.02s; }
.reveal-stagger.is-visible > *:nth-child(2) { transition-delay: 0.09s; }
.reveal-stagger.is-visible > *:nth-child(3) { transition-delay: 0.16s; }
.reveal-stagger.is-visible > *:nth-child(4) { transition-delay: 0.23s; }
.reveal-stagger.is-visible > *:nth-child(5) { transition-delay: 0.3s; }
.reveal-stagger.is-visible > *:nth-child(6) { transition-delay: 0.37s; }

/* ---------- Marquee motion ---------- */
.marquee-track {
  animation: marqueeScroll 26s linear infinite;
}
.marquee:hover .marquee-track,
.marquee-track:focus-within {
  animation-play-state: paused;
}

/* ---------- Maple leaf — the single spot of color, always alive ---------- */
.maple-leaf {
  animation: leafSway 5s ease-in-out infinite;
  transform-origin: 50% 85%;
  transition: transform 0.3s var(--ease);
}
.maple-leaf:hover,
.tag-pill:hover .maple-leaf {
  animation-play-state: paused;
  transform: rotate(18deg) scale(1.15);
}
.maple-leaf--spin {
  animation: spinSlow 9s linear infinite;
}

/* ---------- Chat widget motion ---------- */
.pulse-ring { animation: ringPulse 2.4s ease-out infinite; }
.typing-dots span { animation: dotBounce 1.4s infinite; }
.typing-dots span:nth-child(2) { animation-delay: 0.2s; }
.typing-dots span:nth-child(3) { animation-delay: 0.4s; }

/* ---------- Preloader timeline ---------- */
/* Vision writes on left-to-right, holds, then fades out as the outer V draws
   in its place; Value writes on, holds, then fades out as the inner V draws
   in nested inside it; VigaTech types in letter by letter; the maple leaf
   pops in as the accent. Total runtime must match TOTAL_MS in preloader.js. */
.preloader-word--vision {
  animation: preWordWrite 0.7s var(--ease) forwards 0.15s,
             preWordOut 0.4s var(--ease) forwards 1.1s;
}
.preloader-word--value {
  animation: preWordWrite 0.7s var(--ease) forwards 2s,
             preWordOut 0.4s var(--ease) forwards 2.9s;
}
.preloader-stroke--outer {
  /* dasharray/dashoffset alone hides the undrawn line, so this needs full
     opacity — the base .preloader-stroke{opacity:0} is for elements that
     don't animate their own visibility another way. Static dashoffset:var(--dash)
     is the "undrawn" starting point — without it the line renders fully drawn
     during the delay, since stroke-dashoffset's initial value is 0. */
  opacity: 1;
  --dash: 135;
  stroke-dasharray: var(--dash);
  stroke-dashoffset: var(--dash);
  /* dims while "Value" is written on top of it (same spot, same white),
     so the two don't visually collide, then brightens back up in sync
     with the inner V completing. */
  animation: preDraw 0.8s var(--ease) forwards 1.1s,
             preOuterDim 1.6s var(--ease) forwards 2s;
}
.preloader-stroke--inner {
  opacity: 1;
  --dash: 78;
  stroke-dasharray: var(--dash);
  stroke-dashoffset: var(--dash);
  animation: preDraw 0.7s var(--ease) forwards 2.9s;
}
/* nth-child resets inside each of .pl-viga / .pl-tech, so the 8-letter
   stagger is split across both groups rather than one flat selector. */
.preloader-brand-text .pl-viga span,
.preloader-brand-text .pl-tech span {
  animation: preLetterIn 0.35s var(--ease) forwards;
}
.pl-viga span:nth-child(1) { animation-delay: 3.7s; }
.pl-viga span:nth-child(2) { animation-delay: 3.78s; }
.pl-viga span:nth-child(3) { animation-delay: 3.86s; }
.pl-viga span:nth-child(4) { animation-delay: 3.94s; }
.pl-tech span:nth-child(1) { animation-delay: 4.02s; }
.pl-tech span:nth-child(2) { animation-delay: 4.1s; }
.pl-tech span:nth-child(3) { animation-delay: 4.18s; }
.pl-tech span:nth-child(4) { animation-delay: 4.26s; }
.preloader .maple-leaf {
  /* explicit opacity:0 base — the site-wide .maple-leaf rule defaults to
     visible, and an animation's keyframe "from" state only applies once its
     delay has elapsed, so without this the leaf would flash visible early */
  opacity: 0;
  font-size: clamp(30px, 4vw, 52px);
  animation: preLeafPop 0.5s var(--ease) forwards 4.3s,
             leafSway 5s ease-in-out 4.8s infinite;
}
.preloader.is-done { animation: preFadeOut 0.5s var(--ease) forwards; }

/* ---------- Page transition veil ---------- */
.page-veil { transition: opacity 0.35s var(--ease); }
.page-veil.is-active { opacity: 1; }
body.is-entering { animation: fadeIn 0.5s var(--ease); }

/* ---------- Reduced motion fallback ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  /* js/preloader.js already skips the intro for reduced-motion before it can
     render; this is just a safety net in case that check is ever bypassed. */
  .preloader { display: none !important; }

  .hero-tag, .hero-h1, .hero-sub, .hero-btns, .hero-scroll, .nav .brand {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }

  .reveal, .reveal-stagger > * {
    transition: opacity 0.3s ease !important;
    transform: none !important;
  }

  .hero-glow,
  .marquee-track,
  .maple-leaf,
  .pulse-ring,
  .typing-dots span,
  .hero-scroll-line,
  body.is-entering {
    animation: none !important;
  }

  .maple-leaf:hover { transform: none; }

  * {
    transition-duration: 0.001ms !important;
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
  }
}
