/* ============================================================
   Family & Lifestyle Medicine — Motion: view transitions, arched bands, photo wipes, parallax, entrances, reduced-motion
   Part 11 of 11. The cascade depends on load order:
   these files must stay linked in numeric sequence (see any page <head>).
   ============================================================ */

/* ============================================================
   Polish
   Four effects, all additive: if a browser doesn't support one,
   the page simply renders without it.
   ============================================================ */

/* --- 1. Cross-document view transitions ---------------------------------
   Turns the 8-page site from hard reloads into a soft cross-fade.
   Deliberately NOT naming .site-header: view-transition-name creates a
   containing block, which is the same trap that broke the fixed drawer
   when backdrop-filter sat on the header. A root cross-fade is enough. */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation-duration: .26s; }
::view-transition-new(root) { animation-duration: .36s; }

/* --- 2. Arched band transitions -----------------------------------------
   Colour bands curve over the section above instead of butting into it.
   Only applied to bands that always follow an ivory/cream section, so the
   exposed corners match the page background. */
.stats,
.section--dark,
.cta-band {
  border-start-start-radius: clamp(28px, 4vw, 56px);
  border-start-end-radius: clamp(28px, 4vw, 56px);
}

/* The stats band takes a full sweeping curve instead of two corner radii.
   Giving each top corner a horizontal radius of 50% makes the two arcs meet at
   the centre, so the entire top edge reads as one arc rising out of the hero.
   Extra top padding keeps the figures clear of where the curve dips at the
   left and right edges. */
.stats {
  border-start-start-radius: 50% clamp(26px, 4.5vw, 64px);
  border-start-end-radius: 50% clamp(26px, 4.5vw, 64px);
  padding-top: clamp(3rem, 6vw, 5rem);
}

/* Ride up over the hero so its hard bottom edge — where the bleed photo and the
   crimson panel are cut flat — is covered, leaving the curve as the only
   transition. The pull must exceed the curve depth, or the corners where the arc
   dips lowest would still expose that cut.

   Only above the stacking breakpoint: once the hero stacks, the photo sits at the
   top and the hero ends on plain background, so there is nothing to hide and the
   overlap would just crowd the feature pills. */
@media (min-width: 1151px) {
  .stats {
    position: relative;
    z-index: 3;
    margin-top: calc(-1 * (clamp(26px, 4.5vw, 64px) + 1.5rem));
  }
}

/* --- 3. Photo wipe reveals ----------------------------------------------
   Images wipe open from the left as they scroll in. transform stays in
   each transition list so the existing hover zooms keep working.

   Gated on html.js for the same reason as .reveal itself in 09: the closed
   state waits on .is-visible, so without JS every one of these photos would
   stay clipped to nothing. See the note in 09-reveal.css. */
.js :where(.reveal .service__media img),
.js :where(.reveal .doctor-card__photo img),
.js :where(.reveal .staff-card__photo img),
.js :where(.reveal.mission__figure img),
.js :where(.reveal.hours__media img) {
  clip-path: inset(0 100% 0 0);
  transition: clip-path .9s var(--ease) var(--reveal-delay, 0ms),
              transform .8s var(--ease);
}
/* The reversed mission row sits on the other side of its copy, so open that
   photo from the edge nearest the text too — wiping both rows from the left
   makes the second one travel back towards the paragraph it belongs to. */
.js :where(.mission__row--reverse .reveal.mission__figure img) { clip-path: inset(0 0 0 100%); }

.reveal.is-visible .service__media img,
.reveal.is-visible .doctor-card__photo img,
.reveal.is-visible .staff-card__photo img,
.reveal.is-visible.mission__figure img,
.reveal.is-visible.hours__media img {
  clip-path: inset(0 0 0 0);
}

/* --- 4. Hero parallax ----------------------------------------------------
   Scroll-driven, so no JS and no scroll listener. Browsers without
   scroll timelines just skip it. */
@keyframes hero-drift      { to { translate: 0 -58px; } }
@keyframes hero-drift-slow { to { translate: 0 24px; } }

@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .hero__figure img {
      animation: kenburns 22s ease-in-out infinite alternate, hero-drift linear both;
      animation-timeline: auto, scroll(root block);
      animation-range: normal, 0 100vh;
    }
    .hero__content {
      animation: hero-drift-slow linear both;
      animation-timeline: scroll(root block);
      animation-range: 0 100vh;
    }
  }
}

/* --- 5. Interior banner entrance -----------------------------------------
   The home page hero has a hand-timed cascade; the interior banners had none,
   so every other page opened dead still. Same `rise` keyframe walked down the
   copy block, on a slightly quicker cadence than the hero's — an interior page
   is a stop on the journey, not a curtain-up. Guarded rather than left to the
   reduced-motion block below, so `both` never holds the copy at opacity 0. */
@media (prefers-reduced-motion: no-preference) {
  .page-hero--banner .breadcrumb         { animation: rise .7s var(--ease) .05s both; }
  .page-hero--banner .eyebrow            { animation: rise .7s var(--ease) .14s both; }
  .page-hero--banner h1                  { animation: rise .8s var(--ease) .22s both; }
  .page-hero--banner .page-hero__lead    { animation: rise .8s var(--ease) .34s both; }
  .page-hero--banner .page-hero__actions { animation: rise .8s var(--ease) .46s both; }
}

/* --- 6. Stats band -------------------------------------------------------
   The four blocks already cascade on --reveal-delay. The rules between them
   now draw down on that same beat instead of being there from the start, and
   main.js holds each count-up until its own block lands. */
.js :where(.stat + .stat)::before {
  transform: scaleY(0);
  transform-origin: center;
  transition: transform .7s var(--ease);
  transition-delay: var(--reveal-delay, 0ms);
}
.stat + .stat.is-visible::before { transform: scaleY(1); }

/* ---------- Motion preferences ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1; transform: none; }

  /* Polish effects off: photos fully open, no drift, no page cross-fade. */
    .reveal .service__media img,
  .reveal .doctor-card__photo img,
  .reveal .staff-card__photo img,
  .reveal.mission__figure img,
  .reveal.hours__media img { clip-path: none; }
  .hero__figure img, .hero__content { animation: none; translate: none; }
  @view-transition { navigation: none; }
}

/* ---------- Print ---------- */
@media print {
  .utility-bar, .site-header, .tabbar, .sheet, .cta-band__actions, .footer__top { display: none; }
  /* The bar is gone on paper, so the space reserved for it would print as a
     blank strip under the footer. */
  body { padding-bottom: 0; }
  body { background: #fff; color: #000; }
  .reveal { opacity: 1; transform: none; }
}
