/* ==========================================================================
   ZM Dental Studio — Animations: preloader, scroll reveal, micro-interactions
   ========================================================================== */

/* ---- Preloader ---- */
.preloader {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  transition: opacity 0.5s var(--ease-out), visibility 0.5s var(--ease-out);
}

.preloader__mark {
  width: 84px;
  height: 84px;
  display: grid;
  place-items: center;
  animation: preloader-pulse 1.1s var(--ease-in-out) infinite;
}

.preloader__mark img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

@keyframes preloader-pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(0.86); opacity: 0.7; }
}

.preloader.is-hidden {
  opacity: 0;
  transform: scale(1.06);
  visibility: hidden;
  pointer-events: none;
}

body.is-loading {
  overflow: hidden;
}

/* Content becomes visible once the preloader clears; the actual motion
   comes from the staggered [data-reveal-onload] elements within it, not
   from fading the whole shell (that would double up the animation). */
.page-shell {
  opacity: 0;
}

.is-ready .page-shell {
  opacity: 1;
}

/* ---- Scroll reveal ---- */
[data-reveal] {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.8s var(--ease-out), transform 0.8s var(--ease-out), filter 1s var(--ease-out);
  will-change: transform, opacity, filter;
}

[data-reveal].is-revealed {
  opacity: 1;
  transform: translateY(0);
}

[data-reveal="fade"] {
  transform: none;
}

[data-reveal="scale"] {
  transform: scale(0.94);
}

[data-reveal="scale"].is-revealed {
  transform: scale(1);
}

[data-reveal="left"] {
  transform: translateX(-32px);
}

[data-reveal="left"].is-revealed {
  transform: translateX(0);
}

[data-reveal="right"] {
  transform: translateX(32px);
}

[data-reveal="right"].is-revealed {
  transform: translateX(0);
}

/* Photo reveal: starts soft/blurred and resolves into focus — used for
   the hero image and, later, real clinic/doctor photos as they're added. */
[data-reveal="blur"] {
  opacity: 0;
  transform: scale(1.06);
  filter: blur(18px);
}

[data-reveal="blur"].is-revealed {
  opacity: 1;
  transform: scale(1);
  filter: blur(0);
}

/* Stagger children helper: JS sets --d (delay index) per child */
[data-reveal] {
  transition-delay: calc(var(--d, 0) * 90ms);
}

/* Above-the-fold elements revealed right as the preloader clears
   (not on scroll) — a deliberate, staggered "wow" entrance instead of
   a flat fade. See main.js revealOnload(). */
[data-reveal-onload] {
  transition-delay: calc(var(--d, 0) * 130ms);
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .preloader {
    display: none;
  }
}

/* ---- Hero image subtle parallax wrapper (transform set via JS, throttled) ---- */
.parallax {
  will-change: transform;
}

/* ---- Count-up numbers ---- */
.stat__value {
  font-variant-numeric: tabular-nums;
}

/* ---- Marquee / logo-less ticker for trust strip ---- */
.ticker {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.ticker__track {
  display: flex;
  gap: var(--space-8);
  width: max-content;
  animation: ticker-scroll 28s linear infinite;
}

.ticker:hover .ticker__track {
  animation-play-state: paused;
}

@keyframes ticker-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* ---- Ripple for buttons ---- */
.ripple {
  position: absolute;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.55);
  transform: scale(0);
  animation: ripple-anim 0.6s var(--ease-out);
  pointer-events: none;
}

@keyframes ripple-anim {
  to {
    transform: scale(3.2);
    opacity: 0;
  }
}

/* ---- Ambient "life" touches ----
   Subtle, slow, low-contrast motion so the page never feels frozen.
   All of it is killed by the global prefers-reduced-motion rule. */

/* Soft accent blobs drifting behind the hero text */
.hero {
  position: relative;
}

.hero::before,
.hero::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
}

.hero::before {
  width: 340px;
  height: 340px;
  top: -80px;
  left: -100px;
  background: radial-gradient(circle, rgba(47, 143, 138, 0.16), transparent 70%);
  animation: blob-float 9s var(--ease-in-out) infinite alternate;
}

.hero::after {
  width: 260px;
  height: 260px;
  bottom: -60px;
  left: 32%;
  background: radial-gradient(circle, rgba(47, 143, 138, 0.1), transparent 70%);
  animation: blob-float 13s var(--ease-in-out) infinite alternate-reverse;
}

@keyframes blob-float {
  from { transform: translate(0, 0) scale(1); }
  to { transform: translate(42px, 26px) scale(1.12); }
}

/* The accent dot in section eyebrows quietly "breathes" */
.eyebrow::before {
  animation: dot-pulse 2.6s var(--ease-in-out) infinite;
}

@keyframes dot-pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.55); opacity: 0.55; }
}

/* Primary CTAs emit a soft expanding ring every few seconds */
.hero__actions .btn--primary,
.cta-banner__text .btn--primary,
.main-nav__panel-footer .btn--primary {
  animation: cta-pulse 3.2s var(--ease-out) infinite;
}

@keyframes cta-pulse {
  0% { box-shadow: 0 0 0 0 rgba(47, 143, 138, 0.35); }
  55% { box-shadow: 0 0 0 12px rgba(47, 143, 138, 0); }
  100% { box-shadow: 0 0 0 0 rgba(47, 143, 138, 0); }
}

/* Decorative tooth badge (features-head): orbit rings slowly spin in
   opposite directions, the tooth itself gently bobs, the two accent
   dots breathe — a quiet bit of life next to a section heading. */
.features-decor svg ellipse {
  transform-box: fill-box;
  transform-origin: center;
  animation: decor-orbit 18s linear infinite;
}

.features-decor svg ellipse:nth-of-type(2) {
  animation-duration: 24s;
  animation-direction: reverse;
}

.features-decor svg path {
  transform-box: fill-box;
  transform-origin: center;
  animation: float-y 4s var(--ease-in-out) infinite;
}

.features-decor svg circle {
  transform-box: fill-box;
  transform-origin: center;
  animation: dot-pulse 2.4s var(--ease-in-out) infinite;
}

@keyframes decor-orbit {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* Thin reading-progress line pinned above the header */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  background: linear-gradient(90deg, var(--accent), var(--accent-dark));
  transform: scaleX(0);
  transform-origin: left;
  z-index: 600;
  pointer-events: none;
}

/* On touch devices (no hover zoom to conflict with) the placeholder
   teeth bob gently until real photos replace them */
@media (hover: none) {
  .card__media .placeholder-media img,
  .about-teaser__media .placeholder-media img,
  .cta-banner__media .placeholder-media img {
    animation: float-y 3.6s var(--ease-in-out) infinite;
  }
}

@keyframes float-y {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}

/* Header tooth mark does a tiny wiggle once in a while */
.brand__mark {
  animation: brand-wiggle 8s var(--ease-in-out) infinite;
}

@keyframes brand-wiggle {
  0%, 86%, 100% { transform: rotate(0); }
  89% { transform: rotate(-8deg); }
  93% { transform: rotate(6deg); }
  97% { transform: rotate(-3deg); }
}

/* ---- Skeleton shimmer (used while async content loads, e.g. slots) ---- */
.skeleton {
  position: relative;
  overflow: hidden;
  background: var(--line-soft);
}

.skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.7), transparent);
  animation: skeleton-shimmer 1.4s infinite;
}

@keyframes skeleton-shimmer {
  100% { transform: translateX(100%); }
}
