/* LUXLAB v2 — animations (@keyframes) — estratto da index.html monolite, contenuto invariato */
@keyframes forceShowContent {
    to {
        opacity: 1 !important;
        visibility: visible !important;
    }
}
@keyframes forceHideLoading {
    to {
        opacity: 0 !important;
        visibility: hidden !important;
        pointer-events: none !important;
    }
}
@keyframes subtitleBreath {
    0%, 100% { 
        color: rgba(212, 175, 55, 0.5);
        text-shadow: 0 0 8px rgba(212, 175, 55, 0.1);
    }
    50% { 
        color: rgba(212, 175, 55, 0.7);
        text-shadow: 0 0 12px rgba(212, 175, 55, 0.25);
    }
}
@keyframes quoteAppear {
    0% { opacity: 0; transform: translateY(10px); }
    100% { opacity: 1; transform: translateY(0); }
}
@keyframes quoteBreath {
    0%, 100% { 
        color: rgba(212, 175, 55, 0.3);
        text-shadow: none;
    }
    50% { 
        color: rgba(212, 175, 55, 0.45);
        text-shadow: 0 0 5px rgba(212, 175, 55, 0.1);
    }
}
@keyframes loadTextAppear {
    0% { opacity: 0; }
    100% { opacity: 0.6; } /* Resta discreto */
}
@keyframes textAppear {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}
@keyframes letterHighlight {
    0% {
        background-position: -6% center;
    }
    8% {
        background-position: 3% center;
    }
    12% {
        background-position: 8% center;
    }
    18% {
        background-position: 12% center;
    }
    25% {
        background-position: 18% center;
    }
    32% {
        background-position: 25% center;
    }
    40% {
        background-position: 32% center;
    }
    48% {
        background-position: 38% center;
    }
    55% {
        background-position: 45% center;
    }
    63% {
        background-position: 52% center;
    }
    70% {
        background-position: 58% center;
    }
    78% {
        background-position: 65% center;
    }
    85% {
        background-position: 72% center;
    }
    92% {
        background-position: 80% center;
    }
    100% {
        background-position: 106% center;
    }
}
@keyframes fillFromLeft {
    from {
        background-size: 0% 100%;
    }
    to {
        background-size: 100% 100%;
    }
}
@keyframes ledDelicateAppear {
    0% {
        opacity: 0;
        filter: drop-shadow(0 0 2px rgba(255,215,0,0.6)) 
                drop-shadow(0 0 4px rgba(212,175,55,0.4));
    }
    50% {
        opacity: 0.3;
        filter: drop-shadow(0 0 4px rgba(255,215,0,0.8)) 
                drop-shadow(0 0 8px rgba(212,175,55,0.6));
    }
    100% {
        opacity: 0.6;
        filter: drop-shadow(0 0 2px rgba(255,215,0,0.6)) 
                drop-shadow(0 0 4px rgba(212,175,55,0.4));
    }
}
@keyframes fadeInUp {
    from {
        opacity: 0;
        transform: translateY(30px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}
@keyframes loadingProgress {
    0% {
        width: 0%;
        box-shadow: 
            0 0 10px rgba(212, 175, 55, 0.5),
            0 0 20px rgba(212, 175, 55, 0.2);
    }
    25% {
        width: 25%;
        box-shadow: 
            0 0 15px rgba(212, 175, 55, 0.7),
            0 0 30px rgba(212, 175, 55, 0.3);
    }
    50% {
        width: 50%;
        box-shadow: 
            0 0 20px rgba(212, 175, 55, 0.8),
            0 0 40px rgba(212, 175, 55, 0.4);
    }
    75% {
        width: 75%;
        box-shadow: 
            0 0 25px rgba(212, 175, 55, 0.9),
            0 0 50px rgba(212, 175, 55, 0.5);
    }
    100% {
        width: 100%;
        box-shadow: 
            0 0 30px rgba(212, 175, 55, 1),
            0 0 60px rgba(212, 175, 55, 0.6),
            inset 0 1px 0 rgba(255, 255, 255, 0.3);
    }
}
@keyframes luxLabZoom {
    0% {
        transform: scale(1);
    }
    50% {
        transform: scale(1.05);
    }
    100% {
        transform: scale(1.03);
    }
}
@keyframes mobileTextFill {
    0% {
        opacity: 0;
        transform: scale(0.95);
    }
    30% {
        opacity: 1;
        transform: scale(1);
    }
    100% {
        opacity: 1;
        transform: scale(1.02);
    }
}
@keyframes slideUp {
            from {
                transform: translateY(100%);
            }
            to {
                transform: translateY(0);
            }
        }
@keyframes floatUp {
  0% {
    transform: translateY(100vh) scale(0);
    opacity: 0;
  }
  10% {
    opacity: 1;
  }
  90% {
    opacity: 1;
  }
  100% {
    transform: translateY(-100px) scale(1);
    opacity: 0;
  }
}
@keyframes teleportFlash {
  0% { opacity: 1; }
  50% { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes logoGlow {
  0%, 70% { 
    filter: drop-shadow(0 0 15px rgba(212,175,55,0.5));
    transform: scale(1);
  }
  85% { 
    filter: drop-shadow(0 0 25px rgba(212,175,55,0.8));
    transform: scale(1.02);
  }
  100% { 
    filter: drop-shadow(0 0 15px rgba(212,175,55,0.5));
    transform: scale(1);
  }
}
@keyframes drawText {
  0% {
    stroke-dashoffset: 400;
    fill: transparent;
    stroke-width: 1.5;
    filter: drop-shadow(0 0 5px rgba(212,175,55,0.3));
  }
  30% {
    stroke-dashoffset: 0;
    fill: transparent;
    stroke-width: 1.5;
    filter: drop-shadow(0 0 10px rgba(212,175,55,0.5));
  }
  60% {
    stroke-dashoffset: 0;
    fill: rgba(212,175,55,0.3);
    stroke-width: 1.2;
    filter: drop-shadow(0 0 15px rgba(212,175,55,0.7));
  }
  80% {
    stroke-dashoffset: 0;
    fill: var(--gold);
    stroke-width: 1;
    filter: drop-shadow(0 0 20px rgba(212,175,55,0.9));
  }
  90% {
    stroke-dashoffset: 0;
    fill: var(--gold);
    stroke-width: 0.8;
    filter: drop-shadow(0 0 25px rgba(212,175,55,1));
  }
  100% {
    stroke-dashoffset: 0;
    fill: transparent;
    stroke-width: 1.5;
    filter: drop-shadow(0 0 5px rgba(212,175,55,0.3));
  }
}
@keyframes lineGlow {
  0%, 70% { opacity: 0.7; }
  85% { opacity: 1; }
  100% { opacity: 0.7; }
}
@keyframes subtitlePulse {
  0%, 100% { 
    opacity: 0.8;
    transform: scale(1);
  }
  50% { 
    opacity: 1;
    transform: scale(1.05);
  }
}
@keyframes gradientFlow {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}
@keyframes fadeInOut {
  0% { opacity: 0; transform: translateX(-50%) translateY(5px); }
  50% { opacity: 1; transform: translateX(-50%) translateY(0); }
  100% { opacity: 0; transform: translateX(-50%) translateY(-5px); }
}
@keyframes checkpointGlow {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.5);
  }
  50% {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(1.5);
  }
}
@keyframes svgDrawLoop {
    0% {
        stroke-dashoffset: 1000;
        stroke-opacity: 0.3;
    }
    40% {
        stroke-dashoffset: 0;
        stroke-opacity: 1;
    }
    /* PAUSA 1 SECONDO (40% - 60% = 20% di 4s = 0.8s circa) */
    60% {
        stroke-dashoffset: 0;
        stroke-opacity: 1;
    }
    100% {
        stroke-dashoffset: 1000;
        stroke-opacity: 0.3;
    }
}
/* v2: solo transform/opacity. blur(0.5px) su linea 2px = impercettibile; box-shadow di picco
   (50%) reso statico su #navbar::before per non perdere l'alone. Resa identica. */
@keyframes goldWave {
    0% {
        opacity: 0.6;
        transform: scaleX(0.92);
    }
    25% {
        opacity: 0.8;
        transform: scaleX(0.96);
    }
    50% {
        opacity: 1;
        transform: scaleX(1);
    }
    75% {
        opacity: 0.8;
        transform: scaleX(0.96);
    }
    100% {
        opacity: 0.6;
        transform: scaleX(0.92);
    }
}
/* v2: box-shadow rimosso dai keyframe; l'alone resta come radial-gradient statico
   (#navbar::after ha già background radial + filter:blur(1px) statico). transform/opacity invariati. */
@keyframes centerPulse {
    0%, 100% {
        opacity: 0.5;
        transform: translateX(-50%) scaleX(0.8);
    }
    50% {
        opacity: 1;
        transform: translateX(-50%) scaleX(1.2);
    }
}
@keyframes unlockHamburger {
    to {
        pointer-events: auto;
        opacity: 1;
    }
}
/* v2: il "respiro" (color/text-shadow/brightness per-frame) -> opacity-only.
   Il glow diventa text-shadow STATICO sul .logo-mobile (valore di picco) e qui pulsa solo
   l'opacity (0.95<->1), equivalente al brightness 0.97<->1.04. Resa visiva equivalente. */
@keyframes logoBreath {
    0%, 100% { opacity: 0.95; }
    50%      { opacity: 1; }
}
/* v2: puff click -> scale invece di width/height (compositor, niente reflow).
   translate(-50%,-50%) ripetuto in ogni frame perché il transform del keyframe
   sovrascrive quello base. scale(0)->scale(1) == crescita 0->200px centrata. */
@keyframes vipPuff {
    0% {
        transform: translate(-50%, -50%) scale(0);
        opacity: 1;
    }
    50% {
        opacity: 0.8;
    }
    100% {
        transform: translate(-50%, -50%) scale(1);
        opacity: 0;
    }
}
@keyframes storiaPuff {
    0% {
        transform: translate(-50%, -50%) scale(0);
        opacity: 1;
    }
    50% {
        opacity: 0.8;
    }
    100% {
        transform: translate(-50%, -50%) scale(1);
        opacity: 0;
    }
}
/* v2: scia che scorre -> translateX (l'overlay è largo 100% del contenitore, quindi
   translateX(%) == left(%): resa identica, ma su compositor). Elemento ora con left:0. */
@keyframes shimmer {
    0% { transform: translateX(-100%); }
    50% { transform: translateX(0); }
    100% { transform: translateX(100%); }
}
/* v2: respiro del glow su layer .menu-logo::after. opacity 0 (frame 0% = nessun glow extra) -> 1 (picco). compositor-only. */
@keyframes menuLogoBreath {
    0%, 100% { opacity: 0; }
    50%      { opacity: 1; }
}
@keyframes globeRotate {
    0%, 100% { transform: rotateY(0deg); }
    50% { transform: rotateY(15deg); }
}
@keyframes zoom{0%{transform:scale(1)}100%{transform:scale(2.5)}}
@keyframes hue{0%,100%{filter:hue-rotate(0deg)}50%{filter:hue-rotate(100deg)}}
/* v2: drift di luminosità -> opacity di un layer nero (#hero .content::after).
   Un overlay nero (blend normale) a opacity a dà risultato=originale*(1-a): opacity .2 == brightness(.8) ESATTO.
   La componente contrast(1.3) (secondaria, al picco dei 200s) è approssimata: non ha equivalente compositor. */
@keyframes brightness{0%{opacity:0}100%{opacity:.2}}
/* v2: marquee -> translateX (era margin-left, che fa reflow per-frame). Il contenitore .cube
   è largo 1050px fisso: margin-left:100%==1050px, -200%==-2100px -> stessa corsa, su compositor. */
@keyframes slide{0%{transform:translateX(1050px)}100%{transform:translateX(-2100px)}}
@keyframes floatingParticles{
  0%,100%{transform:translate(0,0) rotate(0deg)}
  33%{transform:translate(50px,-30px) rotate(120deg)}
  66%{transform:translate(-30px,50px) rotate(240deg)}
}
@keyframes floatingDiamond{
  0%,100%{transform:rotate(0deg) scale(1)}
  50%{transform:rotate(180deg) scale(1.2)}
}
@keyframes vogueShine {
  0%, 100% { filter: drop-shadow(2px 2px 4px rgba(212,175,55,0.3)); }
  50% { filter: drop-shadow(2px 2px 8px rgba(212,175,55,0.6)); }
}
@keyframes typewriterFade{
  to{opacity:1}
}
@keyframes svgDraw {
    0% {
        stroke-dashoffset: 1500;
        stroke-opacity: 0.3;
    }
    50% {
        stroke-opacity: 0.8;
    }
    100% {
        stroke-dashoffset: 0;
        stroke-opacity: 1;
    }
}
@keyframes svgGlowPulse {
    0%, 100% {
        filter: drop-shadow(0 0 5px rgba(212, 175, 55, 0.3));
    }
    50% {
        filter: drop-shadow(0 0 12px rgba(212, 175, 55, 0.6));
    }
}
@keyframes paragraphFadeUp {
    to {
        opacity: 1;
        transform: translateY(0);
    }
}
/* v2: morphingGradient rimosso — il layer .service-item:before è opacity:0 permanente,
   l'animazione non produceva output visibile (vedi sections.css). */
@keyframes pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.1); }
}
@keyframes borderGlow {
  0%, 100% { opacity: 0; }
  50% { opacity: 0.8; }
}
/* v2 ECCEZIONE documentata: glow box-shadow outset su .slider-dot.active (12px, overflow:hidden).
   Un layer figlio ::after verrebbe clippato dall'overflow del dot -> niente equivalente
   compositor pulito. Mantenuto originale (paint trascurabile su un solo dot attivo). */
@keyframes dotPulse {
  0%, 100% {
    box-shadow: 0 0 20px rgba(212, 175, 55, 0.6);
    transform: scale(1.3);
  }
  50% {
    box-shadow: 0 0 30px rgba(212, 175, 55, 0.8);
    transform: scale(1.4);
  }
}
/* v2: shimmerButton -> oscillazione translateX del layer ::after largo 200%.
   0/100% translateX(0) (crop sinistro = stato a riposo), 50% translateX(-50%)
   (= offset -W, come background-position 100%). Compositor, niente repaint. */
@keyframes shimmerButton {
    0%, 100% { transform: translateX(0); }
    50%      { transform: translateX(-50%); }
}
@keyframes logoBreathFooter {
    0%, 100% { 
        filter: drop-shadow(0 0 10px rgba(212, 175, 55, 0.3));
        transform: scale(1);
    }
    50% { 
        filter: drop-shadow(0 0 25px rgba(212, 175, 55, 0.6));
        transform: scale(1.02);
    }
}
@keyframes pulseRing {
    0% { transform: scale(1); opacity: 1; }
    100% { transform: scale(1.3); opacity: 0; }
}
/* v2: progressShimmer -> translateX di un tile (50% del layer ::before largo 400%).
   Loop seamless perché il gradiente è ripetuto; resa identica al pan background-position
   200%->-200% (movimento verso destra), ma su compositor. */
@keyframes progressShimmer {
    0%   { transform: translateX(-50%); }
    100% { transform: translateX(0); }
}
