/*
Motion system.

One set of duration and easing tokens so every transition on the site shares
a rhythm, plus the page-entrance animations moved out of the layout's inline
<style> block and retimed. No colours are introduced here: everything is
transform, opacity, or a shadow derived from the existing brand navy.

Everything is disabled wholesale by the prefers-reduced-motion block at the
foot of this file.
*/

:root {
  /* 150ms for a press or a colour change, 250ms for the common case,
     400ms for something entering the viewport. Nothing over 400ms. */
  --dur-fast: 150ms;
  --dur: 250ms;
  --dur-slow: 400ms;

  /* Decelerating curve for entrances, accelerating for exits. */
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-in: cubic-bezier(.4, 0, 1, 1);

  --lift-shadow: 0 6px 24px rgba(45, 46, 130, .12);
}

/* ---------------------------------------------------------------
   Page entrances

   These were 2s each in the layout's inline styles, which reads as a
   stall rather than as polish. 400ms, and bounce-in-right no longer
   starts 2000px off-screen -- that pushed the document wide enough to
   flash a horizontal scrollbar on phones mid-animation.
   --------------------------------------------------------------- */

.fade-in-down {
  animation: fade-in-down var(--dur-slow) var(--ease-out) both;
}

@keyframes fade-in-down {
  from { opacity: 0; transform: translateY(-16px); }
  to   { opacity: 1; transform: translateY(0); }
}

.bounce-in-right {
  animation: bounce-in-right var(--dur-slow) var(--ease-out) both;
}

@keyframes bounce-in-right {
  from { opacity: 0; transform: translateX(40px); }
  to   { opacity: 1; transform: translateX(0); }
}

.gelatine {
  animation: gelatine var(--dur-slow) var(--ease-out);
}

@keyframes gelatine {
  from, to { transform: scale(1, 1); }
  25% { transform: scale(.96, 1.04); }
  50% { transform: scale(1.04, .96); }
  75% { transform: scale(.98, 1.02); }
}

/* ---------------------------------------------------------------
   Scroll reveal

   Driven by an IntersectionObserver in the layout rather than a
   scroll-animation library. Elements are only hidden once the script
   confirms it is running, so with JavaScript off nothing is invisible.
   --------------------------------------------------------------- */

.js-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--dur-slow) var(--ease-out),
              transform var(--dur-slow) var(--ease-out);
  /* Set per item by the observer to stagger a row or grid. */
  transition-delay: var(--reveal-delay, 0ms);
}

.js-reveal [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}

/* ---------------------------------------------------------------
   Interaction states

   The stylesheet already carried ~50 transitions; these fill the gaps
   where a state changed instantly.
   --------------------------------------------------------------- */

/* Nav submenus appeared and vanished with no transition at all. */
.main-nav ul.nav li.has-sub ul.sub-menu {
  transition: opacity var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out),
              visibility var(--dur-fast) linear;
}

/* Buttons had no press feedback. */
.main-button-gradient a,
.white-button a,
.text-button a,
.btn {
  transition: background-color var(--dur) var(--ease-out),
              color var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}

.main-button-gradient a:active,
.white-button a:active,
.btn:active {
  transform: scale(.98);
}

/* A consistent lift for the card-like surfaces across the site. */
.practice-card,
.album-card,
.gallery-tile,
.card-blog {
  transition: transform var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out);
}

.album-card:hover,
.album-card:focus-visible,
.gallery-tile:hover,
.gallery-tile:focus-visible,
.card-blog:hover {
  transform: translateY(-3px);
  box-shadow: var(--lift-shadow);
}

/* Images inside a lifting tile should not jitter the tile's bounds. */
.album-card img,
.gallery-tile img {
  transition: transform var(--dur-slow) var(--ease-out);
}

.album-card:hover img,
.gallery-tile:hover img {
  transform: scale(1.03);
}

/* ---------------------------------------------------------------
   Focus visibility

   Only the two page-specific stylesheets defined focus rings; these
   cover the shared components.
   --------------------------------------------------------------- */

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid #2d2e82;
  outline-offset: 2px;
  border-radius: 2px;
}

/* ---------------------------------------------------------------
   Smooth in-page jumps, but never fight an explicit preference.
   --------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

/* ---------------------------------------------------------------
   One switch for everything above.
   --------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }

  /* Revealed content must still be readable, not stuck at opacity 0. */
  .js-reveal [data-reveal] {
    opacity: 1;
    transform: none;
  }
}
