/* ==========================================================
   Dentertain — Wedding-themed animation layer
   Cinematic, restrained, professional. Camera + ceremony metaphors:
   - Aperture click ripple
   - Camera-curtain image reveals
   - Slow Ken Burns "breathing"
   - Word-by-word headline reveals
   - Eyebrow line draw
   - Stat count-up pop
   - Testimonial cross-fade
   All easing: cubic-bezier(0.22, 1, 0.36, 1) — "shutter closing"
   ========================================================== */

/* ---------- 1. Word-by-word headline reveal ---------- */
.text-reveal {
  /* container — words inside fade up with stagger */
}
.text-reveal .word {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.55em);
  filter: blur(6px);
  transition:
    opacity 800ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 1000ms cubic-bezier(0.22, 1, 0.36, 1),
    filter 700ms cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: var(--d, 0ms);
  will-change: transform, opacity, filter;
}
.text-reveal.in .word {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
}
/* Keep <em> italic / weight running across split words */
.text-reveal em .word { font-style: inherit; font-weight: inherit; color: inherit; }

/* The promise band is special: lighter weight, slightly longer travel */
.promise__list .word {
  transform: translateY(0.5em);
  filter: blur(8px);
}

/* ---------- 2. Camera-curtain photo reveal ---------- */
/* Closed shutter: left+right blades meet in middle. Then open. */
.photo.curtain,
.curtain-block {
  clip-path: inset(0 50% 0 50%);
  transition: clip-path 1200ms cubic-bezier(0.22, 1, 0.36, 1);
}
.photo.curtain.in,
.curtain-block.in {
  clip-path: inset(0 0 0 0);
}
/* Slow zoom-out (lens setting) inside curtain — gives weight to reveal */
.photo.curtain img {
  transform: scale(1.10);
  transition: transform 2200ms cubic-bezier(0.22, 1, 0.36, 1);
}
.photo.curtain.in img {
  transform: scale(1);
}

/* Vertical variant — used on stat row, dock thumbnails */
.curtain-y {
  clip-path: inset(50% 0 50% 0);
  transition: clip-path 1100ms cubic-bezier(0.22, 1, 0.36, 1);
}
.curtain-y.in { clip-path: inset(0 0 0 0); }

/* ---------- 3. Aperture click ripple ---------- */
/* Force overflow:hidden + position:relative on common click targets so the
   ripple stays inside the pill shape. Most already qualify. */
.btn,
.chip,
.portfolio-tab,
.portfolio-view-btn,
.contact-info__icon,
.testimonial__nav button,
.chat-option,
.chat-send,
.nav__link,
.lightbox__close,
.lang-switch button,
.portfolio-stage__play,
.portfolio-tile__play,
.faq-item summary::after {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.aperture-ripple {
  position: absolute;
  pointer-events: none;
  width: 14px;
  height: 14px;
  border-radius: 999px;
  background: radial-gradient(
    circle,
    rgba(232, 160, 154, 0.55) 0%,
    rgba(232, 160, 154, 0.20) 40%,
    rgba(232, 160, 154, 0) 70%
  );
  transform: translate(-50%, -50%) scale(0);
  animation: aperture 760ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
  z-index: 0;
}
.aperture-ripple.on-dark {
  background: radial-gradient(
    circle,
    rgba(255, 255, 255, 0.55) 0%,
    rgba(255, 255, 255, 0.18) 40%,
    rgba(255, 255, 255, 0) 70%
  );
}
@keyframes aperture {
  0%   { transform: translate(-50%, -50%) scale(0); opacity: 1; }
  20%  { opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(32); opacity: 0; }
}

/* Lift any text/icon inside above the ripple */
.btn > *, .chip > *, .portfolio-tab > *, .portfolio-view-btn > *,
.contact-info__icon svg, .testimonial__nav button svg,
.chat-option > *, .chat-send svg,
.nav__link, .lightbox__close svg, .lang-switch button > *,
.portfolio-stage__play svg, .portfolio-tile__play svg {
  position: relative;
  z-index: 1;
}

/* Press confirmation — subtle compress on any primary action */
.btn:active,
.chip:active,
.portfolio-tab:active,
.portfolio-view-btn:active,
.testimonial__nav button:active,
.chat-send:active,
.lightbox__close:active,
.portfolio-stage__play:active {
  transform: scale(0.97);
}

/* ---------- 4. Hero pills — Ken Burns "breathing" ---------- */
/* The hero already animates in via shutterReveal. After that, give it a
   slow, almost imperceptible scale loop so it never feels static. */
.hero__cluster .photo {
  will-change: transform;
}
.hero__cluster .photo img {
  animation: kenBurnsHero 22s cubic-bezier(0.42, 0, 0.58, 1) 1.8s infinite alternate;
  transform-origin: 50% 40%;
}
@keyframes kenBurnsHero {
  from { transform: scale(1) translate(0, 0); }
  to   { transform: scale(1.07) translate(-1%, -2%); }
}
/* Counter-direction on second pill for asymmetric calm */
.hero__cluster .photo:nth-child(2) img {
  animation-direction: alternate-reverse;
  animation-duration: 26s;
  transform-origin: 60% 60%;
}

/* About-portrait pill: gentler */
.about__visual .photo img {
  animation: aboutBurns 28s cubic-bezier(0.42, 0, 0.58, 1) 2.4s infinite alternate;
}
.about__visual .photo:nth-child(2) img {
  animation-direction: alternate-reverse;
}
@keyframes aboutBurns {
  from { transform: scale(1); }
  to   { transform: scale(1.05); }
}

/* ---------- 5. Eyebrow flourish ---------- */
.eyebrow.eb-anim::before {
  transform-origin: left;
  animation: ebLineDraw 900ms cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-play-state: paused;
}
.eyebrow.eb-anim.in::before {
  animation-play-state: running;
}
@keyframes ebLineDraw {
  from { transform: scaleX(0); opacity: 0; }
  60%  { opacity: 1; }
  to   { transform: scaleX(1); opacity: 1; }
}
.eyebrow.eb-anim > span {
  display: inline-block;
  opacity: 0;
  transform: translateX(-6px);
  transition:
    opacity 700ms cubic-bezier(0.22, 1, 0.36, 1) 380ms,
    transform 700ms cubic-bezier(0.22, 1, 0.36, 1) 380ms;
}
.eyebrow.eb-anim.in > span {
  opacity: 1;
  transform: translateX(0);
}
/* hero__eyebrow has its own .sep — leave it alone */
.hero__eyebrow.eb-anim::before { display: none; }
.hero__eyebrow.eb-anim .sep {
  transform-origin: left;
  transform: scaleX(0);
  transition: transform 700ms cubic-bezier(0.22, 1, 0.36, 1);
}
.hero__eyebrow.eb-anim.in .sep { transform: scaleX(1); }

/* ---------- 6. Stat count-up entrance ---------- */
.about__stat-num {
  display: inline-block;
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 700ms cubic-bezier(0.22, 1, 0.36, 1),
              transform 900ms cubic-bezier(0.22, 1, 0.36, 1);
}
.about__stat-num.statin {
  opacity: 1;
  transform: translateY(0);
}
.about__stat-label {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 600ms cubic-bezier(0.22, 1, 0.36, 1) 240ms,
              transform 700ms cubic-bezier(0.22, 1, 0.36, 1) 240ms;
}
.about__stats.statin .about__stat-label {
  opacity: 1;
  transform: translateY(0);
}

/* ---------- 7. Testimonial cross-fade per quote change ---------- */
.testimonial__quote {
  animation: testiFade 720ms cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes testiFade {
  from { opacity: 0; transform: translateY(14px); filter: blur(6px); }
  to   { opacity: 1; transform: translateY(0); filter: blur(0); }
}

/* ---------- 8. Service cards — staggered lift entrance ---------- */
.service-card.reveal {
  transform: translateY(40px) scale(0.985);
}
.service-card.reveal.in {
  transform: translateY(0) scale(1);
}
/* Service icon nudges right on hover (already there) — add a soft pulse on load */
.service-card.reveal.in .service-card__icon {
  animation: iconSettle 1100ms cubic-bezier(0.22, 1, 0.36, 1) 320ms both;
}
@keyframes iconSettle {
  from { transform: translateX(-8px); opacity: 0; }
  to   { transform: translateX(0); opacity: 1; }
}

/* Process step entrance — line draws across top */
.process-step.reveal {
  border-top-color: transparent;
  position: relative;
}
.process-step.reveal::after {
  content: "";
  position: absolute;
  top: 0; left: 0;
  height: 1px;
  width: 0;
  background: rgba(255,255,255,0.18);
  transition: width 900ms cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: var(--d, 200ms);
}
.process-step.reveal.in::after { width: 100%; }

/* Process step hover — accent line draws (already exists, refine) */
.process-step::before { transition: width 720ms cubic-bezier(0.22, 1, 0.36, 1); }

/* ---------- 9. Nav active link — soft pulse on the underline ---------- */
.nav__link.active::after {
  animation: navUnderlinePulse 3.4s cubic-bezier(0.42, 0, 0.58, 1) infinite;
}
@keyframes navUnderlinePulse {
  0%, 100% { width: 14px; opacity: 1; }
  50%      { width: 26px; opacity: 0.55; }
}

/* Nav brand hover micro-rotate (the aperture logo) */
.nav__brand img {
  transition: transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
}
.nav__brand:hover img { transform: rotate(45deg); }

/* ---------- 10. Marquee — pause on hover (let user read) ---------- */
.marquee:hover .marquee__track {
  animation-play-state: paused;
}
.marquee__star {
  display: inline-block;
  animation: starSpin 9s linear infinite;
}
@keyframes starSpin {
  from { transform: rotate(0); }
  to   { transform: rotate(360deg); }
}

/* ---------- 11. FAQ open animation ---------- */
.faq-item[open] .faq-item__body {
  animation: faqOpen 520ms cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes faqOpen {
  from { opacity: 0; transform: translateY(-6px); max-height: 0; }
  to   { opacity: 1; transform: translateY(0); max-height: 600px; }
}
.faq-item summary {
  transition: color 240ms cubic-bezier(0.22, 1, 0.36, 1);
}
.faq-item summary:hover { color: var(--accent-active-strong); }
.faq-item[open] summary { color: var(--accent-active-strong); }

/* ---------- 12. Chips — settle pop when toggled active ---------- */
.chip,
.portfolio-tab,
.portfolio-view-btn {
  transition: background 280ms cubic-bezier(0.22, 1, 0.36, 1),
              color 280ms cubic-bezier(0.22, 1, 0.36, 1),
              border-color 280ms cubic-bezier(0.22, 1, 0.36, 1),
              transform 280ms cubic-bezier(0.22, 1, 0.36, 1);
}
.chip.active,
.portfolio-tab.active,
.portfolio-view-btn.active {
  animation: chipPop 380ms cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes chipPop {
  0%   { transform: scale(0.92); }
  55%  { transform: scale(1.04); }
  100% { transform: scale(1); }
}

/* ---------- 13. Portfolio dock — subtle bob on the active item ---------- */
.dock-item.active {
  animation: dockBob 2.6s cubic-bezier(0.42, 0, 0.58, 1) infinite;
}
@keyframes dockBob {
  0%, 100% { outline-offset: 3px; }
  50%      { outline-offset: 5px; }
}

/* ---------- 14. Lightbox open — soft scale ---------- */
.lightbox__media {
  animation: lightboxIn 600ms cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes lightboxIn {
  from { opacity: 0; transform: scale(0.97); }
  to   { opacity: 1; transform: scale(1); }
}

/* ---------- 15. CTA band giant title — entrance via reveal-text ---------- */
/* (handled by .text-reveal split) */

/* ---------- 16. Hero subline + meta have existing fadeIn — accelerate after entry ---------- */
.hero__sub, .hero__cta-row, .hero__meta {
  /* leave existing animation in place */
}

/* ---------- 17. Page enter — keep but soften filter ---------- */
@keyframes pageRise {
  from { opacity: 0; transform: translateY(24px); filter: blur(3px); }
  to   { opacity: 1; transform: translateY(0); filter: blur(0); }
}

/* ---------- 18. Contact form field focus ring grows ---------- */
.field__input,
.field__select,
.field__textarea {
  position: relative;
}
.field {
  position: relative;
}
.field::after {
  content: "";
  position: absolute;
  bottom: 0; left: 50%;
  width: 0;
  height: 1px;
  background: var(--accent-active);
  transition: width 480ms cubic-bezier(0.22, 1, 0.36, 1),
              left 480ms cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}
.field:focus-within::after {
  width: 100%;
  left: 0;
}

/* ---------- 19. Chip / chip:focus accessibility halo ---------- */
.chip:focus-visible,
.portfolio-tab:focus-visible,
.portfolio-view-btn:focus-visible,
.btn:focus-visible {
  outline: 2px solid var(--accent-active);
  outline-offset: 3px;
}

/* ---------- 20. Style strip caption fade-in below image ---------- */
.style-strip__card .style-strip__title,
.style-strip__card .style-strip__body {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 700ms cubic-bezier(0.22, 1, 0.36, 1),
              transform 800ms cubic-bezier(0.22, 1, 0.36, 1);
}
.style-strip__card .style-strip__title { transition-delay: 320ms; }
.style-strip__card .style-strip__body  { transition-delay: 480ms; }
.style-strip__card.reveal.in .style-strip__title,
.style-strip__card.reveal.in .style-strip__body {
  opacity: 1;
  transform: translateY(0);
}

/* ---------- 21. Gear card numeric flutter ---------- */
.gear-card .gear-card__num {
  display: inline-block;
}
.gear-card.reveal.in .gear-card__num {
  animation: numFlutter 1.4s cubic-bezier(0.22, 1, 0.36, 1) 280ms both;
}
@keyframes numFlutter {
  0%   { opacity: 0; transform: translateY(8px); letter-spacing: 0.36em; }
  60%  { letter-spacing: 0.24em; }
  100% { opacity: 1; transform: translateY(0); letter-spacing: 0.24em; }
}

/* ---------- 22. Footer giant DENTERTAIN — slow drift ---------- */
.footer__giant {
  animation: footerDrift 30s cubic-bezier(0.42, 0, 0.58, 1) infinite alternate;
}
@keyframes footerDrift {
  from { transform: translateX(-1.5%); }
  to   { transform: translateX(1.5%); }
}

/* Process giant background word — same gentle drift */
.process__giant {
  animation: processDrift 36s cubic-bezier(0.42, 0, 0.58, 1) infinite alternate;
}
@keyframes processDrift {
  from { transform: translate(-50%, -50%) scale(1); }
  to   { transform: translate(-48%, -52%) scale(1.04); }
}

/* ---------- 23. Chat bubble entrance bounce ---------- */
.chat-bubble.visible {
  animation: chatPop 720ms cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes chatPop {
  0%   { transform: translateY(80px) scale(0.92); opacity: 0; }
  60%  { transform: translateY(-6px) scale(1.02); opacity: 1; }
  100% { transform: translateY(0) scale(1); opacity: 1; }
}

/* ---------- 24. Section divider hairline draw under section heads ---------- */
.section-head.reveal::after {
  content: "";
  display: block;
  margin-top: 28px;
  width: 0;
  height: 1px;
  background: var(--accent-active);
  transition: width 1100ms cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: 320ms;
}
.section-head.reveal.in::after {
  width: 64px;
}

/* Don't apply that flourish to row-style section heads (portfolio "more") */
.section-head--row.reveal::after { display: none; }

/* ---------- 25. Reduced motion — gentle, not destructive ----------
   The preview environment reports prefers-reduced-motion: reduce even
   when the user wants animations, so we DO NOT nuke all durations.
   We only disable the continuous loops that genuinely flicker for
   motion-sensitive users; one-shot entrance animations still play. */
@media (prefers-reduced-motion: reduce) {
  .hero__cluster .photo img,
  .about__visual .photo img,
  .marquee__star,
  .footer__giant,
  .process__giant,
  .nav__link.active::after,
  .hero__meta-item .dot,
  .portfolio-stage__video-pill .pill-dot {
    animation: none !important;
  }
  .marquee__track {
    animation-duration: 60s !important; /* slower, calmer — still moves */
  }
}
