/* ============================================================
   BACIO — animations.css
   MOTION LAYER — additive only; never fights layout or the
   static design defined in style.css.

   Gating strategy:
     .js  — set on <html> by js/main.js as its first statement.
            Every "hidden until revealed" state lives behind it,
            so content stays fully visible if JS never runs.
     @media (prefers-reduced-motion: reduce) — the block at the
            end neutralizes every continuous or decorative
            animation declared here (JS handles particles, dust,
            parallax, cursor and instant reveals).

   Contents:
     1.  Scroll-reveal system ([data-reveal] / [data-delay])
     2.  Hero letter entrance + per-letter gold sheen
     3.  Unmask reveals (despre media, gallery curtain wipes)
     4.  Gold shimmer sweep (.contact-title / .phone-cta)
     5.  Play affordances (pulse + ping)
     6.  Row sheen sweep on hover (services)
     7.  Ornament draw-in (line — diamond — spark)
     8.  Statement word cascade
     9.  Ambient: stage beams sway, equalizer bars, orb drift
     10. Entrances & cues (mobile menu, lightbox, hero scroll)
     11. Reduced-motion neutralization
   ============================================================ */

/* ------------------------------------------------------------
   1. SCROLL REVEAL — MIRRORED
   Rich time-based entrances, and TRUE visible reverses: the JS
   engine toggles .is-visible on a fixed trigger line (~88% of
   the viewport, small hysteresis). Cross it scrolling down →
   the entrance plays; push an element back across it scrolling
   up → the SAME transition runs backwards on screen (sinks +
   fades), because the line sits well above the fold. Elements
   arriving from the top are simply visible — no re-entrance.
   Entrances cascade via --d; exits react immediately (delay 0).
   ------------------------------------------------------------ */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(26px);
  /* base transition = the EXIT (class removal reads these):
     quicker than the entrance so the reverse completes while
     the element is still well inside the viewport */
  transition:
    opacity .45s cubic-bezier(.3, .6, .4, 1),
    transform .45s cubic-bezier(.3, .6, .4, 1);
  transition-delay: 0s;
}
.js [data-reveal].is-visible {
  opacity: 1;
  transform: none;
  /* entrance: a touch slower + cascaded */
  transition-duration: .6s, .6s;
  transition-delay: var(--d, 0s);
}

.js [data-reveal][data-delay="1"] { --d: .08s; }
.js [data-reveal][data-delay="2"] { --d: .16s; }
.js [data-reveal][data-delay="3"] { --d: .24s; }
.js [data-reveal][data-delay="4"] { --d: .32s; }

/* Video-wall thumbs: opacity-only reveal — their transform
   belongs to the column-parallax engine (instant, untransitioned
   via the --par custom property). */
.js .vw-item[data-reveal] {
  transform: translate3d(0, var(--par, 0px), 0);
  transition: opacity .55s cubic-bezier(.2, .7, .2, 1);
}
.js .vw-item[data-reveal].is-visible {
  transform: translate3d(0, var(--par, 0px), 0);
}

/* ------------------------------------------------------------
   2. HERO LETTERS
   The wordmark container never hides as a whole — its letters
   carry the entrance (rise + slight rotate, staggered by --i).
   Each letter also carries a narrow gold glint that crosses the
   word left→right (same keyframes, per-letter delay), reading
   as one light sweep across metal.
   ------------------------------------------------------------ */
/* The wordmark container never hides — its letters carry the
   entrance (and the visible reverse on the way out). */
.js .wordmark[data-reveal] { opacity: 1; transform: none; }

.js .wordmark[data-reveal] .wl {
  opacity: 0;
  transform: translateY(.38em) rotate(5deg) scale(.94);
  transition:
    opacity .8s cubic-bezier(.2, .7, .2, 1),
    transform .8s cubic-bezier(.2, .7, .2, 1);
  transition-delay: calc(.08s + var(--i) * .075s);
}
.js .wordmark[data-reveal].is-visible .wl {
  opacity: 1;
  transform: none;
}

.js .wl {
  background-image:
    linear-gradient(115deg,
      rgba(255, 250, 234, 0) 44%,
      rgba(255, 250, 234, .85) 50%,
      rgba(255, 250, 234, 0) 56%),
    var(--grad-gold-v);
  background-size: 300% 100%, 100% 100%;
  background-position: 140% 0, 0 0;
  animation: gold-sheen 7.5s cubic-bezier(.4, .08, .3, 1) infinite;
  animation-delay: calc(1.4s + var(--i) * .13s);
}

/* ------------------------------------------------------------
   3. UNMASK REVEALS
   Media enters behind a curtain wipe instead of a slide: the
   despre portrait wipes from the left; gallery pieces alternate
   top-down / bottom-up. Images settle from a slight overzoom
   via a one-shot keyframe so hover transitions stay untouched.
   ------------------------------------------------------------ */
.js .despre-media[data-reveal] {
  transform: none;                     /* curtain carries the motion */
  clip-path: inset(0 100% 0 0 round var(--r-lg));
  transition:
    opacity .35s ease,
    clip-path 1s cubic-bezier(.6, .05, .2, 1);
}
.js .despre-media[data-reveal].is-visible {
  clip-path: inset(0 0 0 0 round var(--r-lg));
}

.js .g-item[data-reveal] {
  transform: none;                     /* curtain carries the motion */
  clip-path: inset(0 0 100% 0 round var(--r));
  transition:
    opacity .35s ease,
    clip-path .9s cubic-bezier(.6, .05, .2, 1);
  transition-delay: var(--d, 0s);
}
.js .g-item[data-reveal]:nth-child(even) {
  clip-path: inset(100% 0 0 0 round var(--r));
}
.js .g-item[data-reveal].is-visible {
  clip-path: inset(0 0 0 0 round var(--r));
}
.js .g-item[data-reveal].is-visible img {
  animation: g-zoom 1.15s cubic-bezier(.2, .7, .2, 1) both;
  animation-delay: var(--d, 0s);
}
@keyframes g-zoom {
  from { transform: scale(1.14); }
  to   { transform: scale(1); }
}

/* ------------------------------------------------------------
   4. GOLD SHIMMER SWEEP (large gold display text)
   A narrow warm highlight layered above the existing gradient,
   both clipped to the glyphs. Parked off-glyph most of the
   cycle — an occasional glint, not a loop. Desynced via
   negative delays.
   ------------------------------------------------------------ */
.js .contact-title {
  background-image:
    linear-gradient(115deg,
      rgba(255, 250, 234, 0) 44%,
      rgba(255, 250, 234, .8) 50%,
      rgba(255, 250, 234, 0) 56%),
    var(--grad-gold-v);
  background-size: 260% 100%, 100% 100%;
  background-position: 130% 0, 0 0;
  animation: gold-sheen 8s cubic-bezier(.4, .08, .3, 1) infinite;
  animation-delay: -2.6s;
}

@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .js .phone-cta {
    background-image:
      linear-gradient(115deg,
        rgba(248, 236, 192, 0) 44%,
        rgba(248, 236, 192, .9) 50%,
        rgba(248, 236, 192, 0) 56%),
      linear-gradient(180deg, var(--text), var(--text));
    background-size: 260% 100%, 100% 100%;
    background-position: 130% 0, 0 0;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: gold-sheen 8s cubic-bezier(.4, .08, .3, 1) infinite;
    animation-delay: -5.2s;
  }
  .js .phone-cta:hover,
  .js .phone-cta:focus-visible {
    background-image:
      linear-gradient(115deg,
        rgba(248, 236, 192, 0) 44%,
        rgba(248, 236, 192, .9) 50%,
        rgba(248, 236, 192, 0) 56%),
      var(--grad-gold);
  }
}

@keyframes gold-sheen {
  0%, 58%   { background-position: 130% 0, 0 0; }
  88%, 100% { background-position: -30% 0, 0 0; }
}

/* ------------------------------------------------------------
   5. PLAY AFFORDANCES
   One focal pulse on the feature play button; thumbnails answer
   hover / keyboard focus with a single soft ping.
   ------------------------------------------------------------ */
.js .play-btn::before {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 999px;
  border: 1.5px solid rgba(248, 236, 192, .8);
  opacity: 0;
  pointer-events: none;
  animation: play-pulse 3s cubic-bezier(.25, .55, .35, 1) infinite;
}
@keyframes play-pulse {
  0%        { transform: scale(.9);  opacity: 0;  }
  12%       { opacity: .75; }
  60%, 100% { transform: scale(1.5); opacity: 0;  }
}

.js .play-dot::before {
  content: "";
  position: absolute;
  inset: -2px;
  border-radius: 999px;
  border: 1.5px solid rgba(248, 236, 192, .85);
  opacity: 0;
  pointer-events: none;
}
.js .vw-item:hover .play-dot::before,
.js .vw-item:focus-visible .play-dot::before {
  animation: dot-ping 1s cubic-bezier(.2, .6, .3, 1) both;
}
@keyframes dot-ping {
  0%   { transform: scale(.85); opacity: .9; }
  100% { transform: scale(1.7); opacity: 0;  }
}

/* ------------------------------------------------------------
   6. ROW SHEEN (services, on hover)
   A skewed light band crosses the row once per hover —
   transform/opacity only, clipped by the row's overflow:hidden.
   ------------------------------------------------------------ */
.js .srv-row::after {
  content: "";
  position: absolute;
  top: -20%;
  bottom: -20%;
  left: 0;
  width: 45%;
  background: linear-gradient(100deg,
    rgba(248, 236, 192, 0) 0%,
    rgba(248, 236, 192, .04) 45%,
    rgba(248, 236, 192, .1) 50%,
    rgba(248, 236, 192, .04) 55%,
    rgba(248, 236, 192, 0) 100%);
  transform: translateX(-140%) skewX(-16deg);
  opacity: 0;
  pointer-events: none;
}
.js .srv-row:hover::after {
  animation: row-sheen 1.1s cubic-bezier(.25, .6, .3, 1) forwards;
}
@keyframes row-sheen {
  0%   { transform: translateX(-140%) skewX(-16deg); opacity: 0; }
  15%  { opacity: 1; }
  100% { transform: translateX(340%) skewX(-16deg); opacity: 0; }
}

/* ------------------------------------------------------------
   7. ORNAMENT DRAW-IN
   Lines draw outward from the diamond, the diamond traces
   itself, then the blue spark ignites — the logo motif.
   ------------------------------------------------------------ */
.js .ornament[data-reveal] { opacity: 1; transform: none; }

.js .ornament .orn-line,
.js .ornament .orn-diamond {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 1s cubic-bezier(.4, .1, .2, 1);
}
.js .ornament .orn-line { transition-delay: .25s; }
.js .ornament .orn-diamond { transition-delay: .05s; }
.js .ornament .orn-star {
  opacity: 0;
  transition: opacity .5s ease .95s;
}
.js .ornament.is-visible .orn-line,
.js .ornament.is-visible .orn-diamond { stroke-dashoffset: 0; }
.js .ornament.is-visible .orn-star { opacity: 1; }

/* ------------------------------------------------------------
   8. STATEMENT WORD CASCADE
   The container reveals as a whole (observer), each word rises
   in sequence. Gold words land last in reading order anyway.
   ------------------------------------------------------------ */
.js .statement-line[data-reveal] { opacity: 1; transform: none; }
.js .statement-line .w {
  opacity: 0;
  transform: translateY(.55em);
  transition:
    opacity .6s cubic-bezier(.2, .7, .2, 1),
    transform .6s cubic-bezier(.2, .7, .2, 1);
  transition-delay: calc(var(--i) * .06s);
}
.js .statement-line.is-visible .w {
  opacity: 1;
  transform: none;
}

/* ------------------------------------------------------------
   9. AMBIENT — beams, equalizer, orbs
   ------------------------------------------------------------ */
.beam { animation: beam-sway 11s ease-in-out infinite alternate; }
.beam.b1 { animation-delay: 0s; }
.beam.b2 { animation-duration: 9s;  animation-delay: -3s; }
.beam.b3 { animation-duration: 13s; animation-delay: -6s; }
@keyframes beam-sway {
  0%   { transform: rotate(14deg);  opacity: .32; }
  50%  { opacity: .6; }
  100% { transform: rotate(8deg);   opacity: .42; }
}
.beam.b2 { --sway: -3deg; }
@keyframes beam-sway-2 {
  0%   { transform: rotate(-3deg); opacity: .3; }
  100% { transform: rotate(3deg);  opacity: .55; }
}
.beam.b2 { animation-name: beam-sway-2; }
@keyframes beam-sway-3 {
  0%   { transform: rotate(-15deg); opacity: .35; }
  100% { transform: rotate(-8deg);  opacity: .55; }
}
.beam.b3 { animation-name: beam-sway-3; }

.eq i { animation: eq-bounce 1.15s ease-in-out infinite; }
.eq i:nth-child(1) { animation-delay: 0s;    animation-duration: 1.05s; }
.eq i:nth-child(2) { animation-delay: -.35s; animation-duration: 1.25s; }
.eq i:nth-child(3) { animation-delay: -.7s;  animation-duration: .95s; }
.eq i:nth-child(4) { animation-delay: -.2s;  animation-duration: 1.35s; }
.eq i:nth-child(5) { animation-delay: -.55s; animation-duration: 1.1s; }
@keyframes eq-bounce {
  0%, 100% { transform: scaleY(.3); }
  50%      { transform: scaleY(1); }
}

.orb { animation: orb-drift 16s ease-in-out infinite alternate; }
.orb-blue { animation-duration: 20s; animation-delay: -7s; }
@keyframes orb-drift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(42px, -30px, 0); }
}

/* Ken Burns — a very slow cinematic push-in on the hero image.
   The wrap carries the scroll parallax; the img carries the zoom,
   so the two never fight over one transform. */
.hero-img { animation: kb-zoom 34s ease-in-out infinite alternate; }
@keyframes kb-zoom {
  from { transform: scale(1.06); }
  to   { transform: scale(1.13) translate3d(0, -0.8%, 0); }
}

/* Brand intro — the logo condenses into focus, the gold rule
   draws beneath it, then the whole curtain lifts (JS-timed). */
.preloader-logo {
  opacity: 0;
  animation: pre-logo 1s cubic-bezier(.2, .7, .2, 1) .15s forwards;
}
@keyframes pre-logo {
  from { opacity: 0; transform: scale(.94) translateY(10px); filter: blur(8px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}
.preloader::after { animation: pre-rule .9s cubic-bezier(.2, .7, .2, 1) .55s forwards; }
@keyframes pre-rule {
  to { transform: translateX(-50%) scaleX(1); }
}
.preloader.lift .preloader-logo {
  animation: pre-out .45s cubic-bezier(.6, .05, .4, 1) forwards;
}
@keyframes pre-out {
  to { opacity: 0; transform: translateY(-14px) scale(.97); }
}

/* WhatsApp bubble — an occasional soft ping, not a nag. */
.wa-float::before {
  content: "";
  position: absolute; inset: -3px;
  border-radius: 999px;
  border: 1.5px solid rgba(37, 211, 102, .7);
  opacity: 0; pointer-events: none;
  animation: wa-ping 4.6s cubic-bezier(.25, .55, .35, 1) infinite;
  animation-delay: 2.2s;
}
@keyframes wa-ping {
  0%, 74% { transform: scale(.9);  opacity: 0; }
  80%     { opacity: .8; }
  100%    { transform: scale(1.5); opacity: 0; }
}

/* ------------------------------------------------------------
   10. ENTRANCES & CUES
   ------------------------------------------------------------ */
/* Mobile menu: panel slides down, links cascade in. */
.js .mobile-menu:not([hidden]) { animation: menu-in .35s cubic-bezier(.2, .7, .2, 1) both; }
@keyframes menu-in {
  from { opacity: 0; transform: translateY(-12px); }
  to   { opacity: 1; transform: none; }
}
.js .mobile-menu:not([hidden]) > * { animation: menu-link-in .45s cubic-bezier(.2, .7, .2, 1) both; }
.js .mobile-menu:not([hidden]) > *:nth-child(1) { animation-delay: .03s; }
.js .mobile-menu:not([hidden]) > *:nth-child(2) { animation-delay: .07s; }
.js .mobile-menu:not([hidden]) > *:nth-child(3) { animation-delay: .11s; }
.js .mobile-menu:not([hidden]) > *:nth-child(4) { animation-delay: .15s; }
.js .mobile-menu:not([hidden]) > *:nth-child(5) { animation-delay: .19s; }
.js .mobile-menu:not([hidden]) > *:nth-child(6) { animation-delay: .25s; }
@keyframes menu-link-in {
  from { opacity: 0; transform: translateX(-14px); }
  to   { opacity: 1; transform: none; }
}

/* Lightbox: backdrop fades, frame rises. */
.js .lightbox:not([hidden]) { animation: lb-fade .3s ease both; }
.js .lightbox:not([hidden]) .lightbox-frame { animation: lb-rise .45s cubic-bezier(.2, .7, .2, 1) both; }
@keyframes lb-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes lb-rise {
  from { opacity: 0; transform: translateY(26px) scale(.97); }
  to   { opacity: 1; transform: none; }
}

/* Hero scroll cue: gentle bob (preserves centering transform). */
.js .hero-scroll { animation: cue-bob 2.6s ease-in-out infinite; }
@keyframes cue-bob {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 7px; }
}

/* ------------------------------------------------------------
   11. REDUCED MOTION — neutralize everything this layer owns.
   (style.css also zeroes all durations globally.)
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal],
  .js .wordmark[data-reveal] .wl,
  .js .statement-line .w {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .preloader { display: none !important; }
  .js .despre-media[data-reveal],
  .js .g-item[data-reveal] {
    clip-path: none !important;
  }
  .js .ornament .orn-line,
  .js .ornament .orn-diamond { stroke-dashoffset: 0 !important; }
  .js .ornament .orn-star { opacity: 1 !important; }
  .js .wl,
  .js .contact-title,
  .js .phone-cta,
  .js .play-btn::before,
  .eq i, .orb, .beam,
  .hero-img,
  .wa-float::before,
  .js .hero-scroll { animation: none !important; }
}
