/* ============================================================
   MOTION LAYER
   Loaded after clay.css. Two jobs:

   1. Give the existing reveals clay physics - things rise, land
      slightly past their mark, and settle, with their shadow
      blooming from flat to lifted as they arrive.
   2. Cover the parts of the page that had no motion at all:
      the nav on load, the training slabs, the FAQ, the contact
      block and the footer.

   The hidden states below are applied by js/motion.js, never in
   the markup, so the page is fully readable with JS disabled.
   ============================================================ */

:root{
  /* lands a little past the mark, then settles - clay has weight */
  --ease-settle: cubic-bezier(.21, 1.14, .36, 1);
  --clay-flat:
    4px 5px 12px -8px rgba(120,96,84,.28),
    -3px -3px 9px -8px rgba(255,255,255,.7);
  --clay-flat-d:
    5px 6px 14px -10px rgba(0,0,0,.45),
    -3px -3px 9px -10px rgba(255,255,255,.05);
}

/* ============================================================
   EXISTING REVEALS, RETUNED
   The core stylesheet fades these in on opacity alone. Give them
   the same rise-and-settle as everything else.
   ============================================================ */
[data-reveal]{ transform: translateY(22px); }
[data-reveal].revealed{
  transform: translateY(0);
  transition: opacity .95s var(--ease-silk), transform 1s var(--ease-settle);
}
h2[data-reveal], .h2[data-reveal]{ transform: translateY(26px); }
h2[data-reveal].revealed, .h2[data-reveal].revealed{
  transition: opacity 1.05s var(--ease-silk),
              transform 1.15s var(--ease-settle),
              filter .95s var(--ease-silk);
}
.premium-fade-heading.is-visible{
  transition: opacity 1.05s var(--ease-silk),
              transform 1.15s var(--ease-settle),
              filter .95s var(--ease-silk);
}

/* the sticky about portrait must not carry a transform of its own -
   it would fight position:sticky on some engines */
.about-portrait[data-reveal],
.about-portrait[data-reveal].revealed{ transform: none; }

/* stat tiles land with a little bounce now that they are objects */
.highlight-item{ transform: translateY(30px) scale(.96); }
.highlight-item.is-visible{
  transform: translateY(0) scale(1);
  transition: opacity .85s var(--ease-silk), transform .95s var(--ease-settle);
}

/* timeline dots pop rather than fade */
.timeline-dot{
  transform: scale(.6);
  opacity: 0;
  transition: transform .6s var(--ease-settle), opacity .5s ease, box-shadow .5s ease;
}
.timeline-item.in-view .timeline-dot{ transform: scale(1); opacity: 1; }

/* ============================================================
   THE SHARED VOCABULARY  (js/motion.js applies these)
   rise - copy blocks and list rows
   pop  - small round objects
   slab - large clay panels, whose shadow blooms as they land
   ============================================================ */
.m-rise,
.m-pop,
.m-slab{ will-change: transform, opacity; }

.m-rise{
  opacity: 0;
  transform: translateY(26px) scale(.985);
  transition: opacity .8s var(--ease-silk), transform .9s var(--ease-settle);
}
.m-pop{
  opacity: 0;
  transform: scale(.72);
  transition: opacity .5s ease, transform .7s var(--ease-settle);
}
.m-slab{
  opacity: 0;
  transform: translateY(40px) scale(.975);
  transition: opacity .9s var(--ease-silk),
              transform 1.05s var(--ease-settle),
              box-shadow 1.05s var(--ease-silk);
}
/* flat while airborne, full clay shadow once it lands */
.m-slab.training-panel.ivory,
.m-slab.contact-form{ box-shadow: var(--clay-flat); }
.m-slab.training-panel.teal{ box-shadow: var(--clay-flat-d); }

.m-rise.m-in,
.m-pop.m-in,
.m-slab.m-in{ opacity: 1; transform: none; }

.m-slab.m-in.training-panel.ivory{ box-shadow: var(--clay-lift), var(--clay-in); }
.m-slab.m-in.training-panel.teal{ box-shadow: var(--clay-lift-d), var(--clay-in-d); }
/* the contact form is the page's most raised object */
.m-slab.m-in.contact-form{ box-shadow: var(--clay-lift-hi), var(--clay-in); }

/* clear will-change once the element has arrived */
.m-in{ will-change: auto; }

/* ============================================================
   NAV - drops in once, on load
   ============================================================ */
/* guarded on .js-motion so the nav is never hidden if the script fails */
.js-motion .site-nav{
  transform: translateY(calc(-100% - 1.5rem));
  opacity: 0;
}
.js-motion .site-nav.nav-in{
  transform: none;   /* must be none, not translateY(0): any transform here
                        would become the containing block for the fixed
                        fullscreen .nav-links menu at <=860px */
  opacity: 1;
  transition: transform 1s var(--ease-settle), opacity .6s ease,
              top .45s var(--ease-soft), padding .45s var(--ease-soft),
              box-shadow .45s var(--ease-soft);
}

/* ============================================================
   REDUCED MOTION - everything arrives already seated
   ============================================================ */
@media (prefers-reduced-motion: reduce){
  [data-reveal], [data-reveal].revealed,
  h2[data-reveal], .h2[data-reveal],
  .highlight-item, .timeline-dot,
  .m-rise, .m-pop, .m-slab{
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
  }
  .js-motion .site-nav{ opacity: 1; transform: none; }
  .m-slab.training-panel.ivory, .m-slab.contact-form{ box-shadow: var(--clay-lift), var(--clay-in); }
  .m-slab.training-panel.teal{ box-shadow: var(--clay-lift-d), var(--clay-in-d); }
}

/* ============================================================
   ARRIVAL vs INTERACTION
   .m-in sets transform:none, which ties with the hover and press
   rules in clay.css and wins on source order. Restate those here
   so a seated element still lifts and presses.
   ============================================================ */
.m-in.contact-submit:hover,
.m-in.back-to-top:hover{ transform: translateY(-3px); }
.m-in.contact-submit:active,
.m-in.back-to-top:active{ transform: translateY(0); }

/* ============================================================
   PER-SECTION SIGNATURES
   Each section arrives in a way that suits what it contains,
   rather than every band sharing one rise.

   Icon entrances use the standalone `scale` property, not
   `transform`. `scale` composes with the hover transforms in
   clay.css instead of overwriting them, so an icon can pop on
   arrival and still lift on hover.
   ============================================================ */

/* ---- STAT COUNTERS: the numeral resolves as the count runs ---- */
.js-motion .highlight-value{
  opacity: 0;
  scale: .88;
  filter: blur(7px);
  transition: opacity .7s var(--ease-silk),
              scale .9s var(--ease-settle),
              filter .8s var(--ease-silk);
}
.js-motion .highlight-item.is-visible .highlight-value{
  opacity: 1;
  scale: 1;
  filter: blur(0);
  transition-delay: .12s;
}

/* ---- ABOUT: the portrait opens from its base, image un-zooming ---- */
.js-motion .about-portrait-frame{
  clip-path: inset(100% 0 0 0);
  transition: clip-path .95s var(--ease-silk);
}
.js-motion .about-portrait-frame.sig-in{ clip-path: inset(0 0 0 0); }
.js-motion .about-portrait-frame img{
  scale: 1.07;
  transition: scale 1.2s var(--ease-silk);
}
.js-motion .about-portrait-frame.sig-in img{ scale: 1; }

/* ---- ABOUT: the timeline draws its own spine ---- */
.js-motion .timeline-track{
  transform: scaleY(0);
  transform-origin: 50% 0;
  transition: transform 1.6s var(--ease-silk);
}
.js-motion .timeline-track.sig-in{ transform: scaleY(1); }

/* ---- TRAINING: the two slabs close in from opposite edges ---- */
.js-motion .m-slab.training-panel.teal{ transform: translateX(-5%) translateY(28px) scale(.98); }
.js-motion .m-slab.training-panel.ivory{ transform: translateX(5%) translateY(28px) scale(.98); }
.js-motion .m-slab.m-in.training-panel{ transform: none; }
/* the etched glyph settles out of a slow turn */
.js-motion .training-glyph{
  rotate: -14deg;
  opacity: 0;
  transition: rotate 2.4s var(--ease-silk), opacity 1.4s var(--ease-silk);
}
.js-motion .m-in .training-glyph,
.js-motion .training-panel.m-in .training-glyph{ rotate: 0deg; opacity: .14; }

/* ---- FERTILITY: icons land after their card ---- */
.js-motion .factor-icon{
  opacity: 0;
  scale: .55;
  transition: opacity .5s ease, scale .75s var(--ease-settle),
              color .35s, background-color .35s, box-shadow .35s;
}
.js-motion #factor-grid.sig-in .factor-icon{ opacity: 1; scale: 1; }

/* ---- TREATMENTS: icons land after their row wipes open ---- */
.js-motion .treatment-icon{
  opacity: 0;
  scale: .6;
  transition: opacity .5s ease, scale .7s var(--ease-settle),
              color .4s, background-color .4s, box-shadow .4s;
}
.js-motion .treatments-grid.sig-in .treatment-icon{ opacity: 1; scale: 1; }

/* ---- JOURNEY: each pinned panel builds itself as it slides in ----
   The track moves horizontally under scrub; this is the vertical
   settle layered on top of it, so a panel assembles rather than
   simply arriving whole. Keyed to .js-journey (set by animations.js
   only when GSAP is driving and motion is on) so the copy is never
   left hidden by a script that did not run. */
/* The numeral and the icon animate with the standalone `scale`
   property, never `transform`: .journey-num carries a
   translateY(-50%) that does its centring, and overwriting it would
   drop the numeral out of position. */
.js-journey .journey-panel .journey-num{
  opacity: 0;
  scale: 1.14;
  transition: opacity 1.1s var(--ease-silk), scale 1.3s var(--ease-silk);
}
.js-journey .journey-panel .journey-icon{
  opacity: 0;
  scale: .55;
  transition: opacity .55s ease, scale .8s var(--ease-settle);
}
.js-journey .journey-panel .eyebrow,
.js-journey .journey-panel h3,
.js-journey .journey-panel > p:last-child{
  opacity: 0;
  transform: translateY(30px);
  transition: opacity .8s var(--ease-silk), transform .95s var(--ease-settle);
}

.js-journey .journey-panel.journey-live .journey-num{ opacity: .9; scale: 1; }
.js-journey .journey-panel.journey-live .journey-icon{ opacity: 1; scale: 1; }
.js-journey .journey-panel.journey-live .eyebrow,
.js-journey .journey-panel.journey-live h3,
.js-journey .journey-panel.journey-live > p:last-child{
  opacity: 1;
  transform: none;
}
/* the stagger, in the order the eye reads the panel */
.js-journey .journey-panel.journey-live .journey-icon{ transition-delay: .10s; }
.js-journey .journey-panel.journey-live .eyebrow{ transition-delay: .18s; }
.js-journey .journey-panel.journey-live h3{ transition-delay: .26s; }
.js-journey .journey-panel.journey-live > p:last-child{ transition-delay: .36s; }

/* ---- SEQUENCE: the stage copy settles before the frames start ---- */
/* handled by the m-rise group in motion.js; nothing extra needed here */

/* ---- FAQ: the plus turns into place as its row lands ---- */
.js-motion .faq-q .plus{
  rotate: -45deg;
  opacity: 0;
  transition: rotate .8s var(--ease-settle), opacity .5s ease,
              background-color .45s, box-shadow .45s;
}
.js-motion .faq-item.m-in .faq-q .plus{ rotate: 0deg; opacity: 1; }

/* ---- CONTACT: branch pins drop in ---- */
.js-motion .contact-icon{
  opacity: 0;
  scale: .5;
  transition: opacity .45s ease, scale .7s var(--ease-settle);
}
.js-motion .branch-item.m-in .contact-icon{ opacity: 1; scale: 1; transition-delay: .18s; }

@media (prefers-reduced-motion: reduce){
  .js-motion .highlight-value,
  .js-motion .factor-icon,
  .js-motion .treatment-icon,
  .js-motion .contact-icon,
  .js-motion .training-glyph{
    opacity: 1; scale: 1; rotate: 0deg; filter: none;
  }
  .js-motion .training-glyph{ opacity: .14; }
  .js-motion .about-portrait-frame{ clip-path: none; }
  .js-motion .about-portrait-frame img{ scale: 1; }
  .js-motion .timeline-track{ transform: none; }
  .js-motion .faq-q .plus{ rotate: 0deg; opacity: 1; }
  /* animations.js will not add .js-journey under reduced motion, but
     seat the panels regardless in case the preference flips mid-visit */
  .js-journey .journey-panel .journey-num{ opacity: .9; scale: 1; }
  .js-journey .journey-panel .journey-icon,
  .js-journey .journey-panel .eyebrow,
  .js-journey .journey-panel h3,
  .js-journey .journey-panel > p:last-child{
    opacity: 1; scale: 1; transform: none;
  }
}

/* ============================================================
   MOTION OFF
   Set by js/motion.js when the observer is unavailable or the
   visitor asked for reduced motion. Everything sits seated.
   ============================================================ */
.motion-off .m-rise,
.motion-off .m-pop,
.motion-off .m-slab,
.motion-off .highlight-value,
.motion-off .factor-icon,
.motion-off .treatment-icon,
.motion-off .contact-icon{
  opacity: 1;
  transform: none;
  scale: 1;
  filter: none;
}
.motion-off .training-glyph{ opacity: .14; rotate: 0deg; }
.motion-off .about-portrait-frame{ clip-path: none; }
.motion-off .about-portrait-frame img{ scale: 1; }
.motion-off .timeline-track{ transform: none; }
.motion-off .faq-q .plus{ rotate: 0deg; opacity: 1; }
.motion-off .site-nav{ opacity: 1; transform: none; }

