/* ==========================================================================
   Site-wide entrance animations, in the style of the home "About" section.
   - Hidden start states only apply under html.motion-ready (set in base.html before first paint), so content is
     always visible without JavaScript; main.js adds .is-in to each element as it scrolls into view.
   - Effects play as keyframes with fill-mode "backwards", so once finished they leave no transform behind and
     hover effects (card lifts etc.) keep working.
   - Keep the selector lists in sync with MOTION in static/js/main.js.
   - Blocks with their own animation (home hero, About collage, How we work, service page blocks, carousel,
     testimonials, header, footer) are excluded.
   ========================================================================== */
:root { --mo-ease: cubic-bezier(.2, .7, .2, 1); --mo-pop: cubic-bezier(.3, 1.6, .5, 1); }

/* ---- 1. Page banners: content cascades in on load (main.js sets --d per item) ---- */
html.motion-ready :is(
  .page-hero :is(.breadcrumb, .eyebrow, h1, .meta, .lead, .btn-row, .page-hero__aside),
  .cs-hero__copy > *, .article-header > *, .ab-hero__copy > *
):not(:is(.home-hero, [data-svc]) *):not(.is-in) { opacity: 0; }
html.motion-ready :is(
  .page-hero :is(.breadcrumb, .eyebrow, h1, .meta, .lead, .btn-row, .page-hero__aside),
  .cs-hero__copy > *, .article-header > *, .ab-hero__copy > *
).is-in { animation: mo-up .8s var(--mo-ease) var(--d, 0s) backwards; }

/* ---- 2. Blocks of text: fade up as they scroll in ---- */
html.motion-ready :is(
  .section-head, .prose, .story > *, .detail-layout__main > section, .facts, .form-panel, .contact-details,
  .ab-who__copy, .ab-offer__copy, .ab-journey .ab-eyebrow, .ab-journey h2, .next-case, .empty-state,
  .newsletter-band .container > *, .booking-embed, .filter-bar, .chip-nav, .testimonial:not(.testimonial-slide), .cs-group__title,
  .cs-glance, .faq-search, .faq-help
):not(.rv, .accordion__body):not(:is(.home-hero, .ha, .hww, [data-svc], .ht-grid, .site-top, .site-footer, .accordion) *):not(.is-in) { opacity: 0; }
html.motion-ready :is(
  .section-head, .prose, .story > *, .detail-layout__main > section, .facts, .form-panel, .contact-details,
  .ab-who__copy, .ab-offer__copy, .ab-journey .ab-eyebrow, .ab-journey h2, .next-case, .empty-state,
  .newsletter-band .container > *, .booking-embed, .filter-bar, .chip-nav, .testimonial:not(.testimonial-slide), .cs-group__title,
  .cs-glance, .faq-search, .faq-help
).is-in { animation: mo-up .85s var(--mo-ease) var(--d, 0s) backwards; }

/* ---- 3. Pictures: a soft wipe from the left while the photo settles from a slight zoom ---- */
html.motion-ready :is(.ab-hero__frame, .cs-hero__frame, .about-hero-media, .ab-who__card, .story .media, .gallery figure):not(.is-in) {
  clip-path: inset(0 100% 0 0 round 22px);
}
html.motion-ready :is(.ab-hero__frame, .cs-hero__frame, .about-hero-media, .ab-who__card, .story .media, .gallery figure).is-in {
  animation: mo-wipe 1.1s cubic-bezier(.7, 0, .2, 1) var(--d, .1s) backwards;
}
html.motion-ready :is(.ab-hero__frame, .cs-hero__frame, .about-hero-media, .ab-who__card, .story .media, .gallery figure).is-in img {
  animation: mo-settle 1.8s var(--mo-ease) var(--d, .1s) backwards;
}

/* ---- 4. Grids and lists: items rise one after another ---- */
html.motion-ready :is(
  .cards, .team-grid, .stats, .service-rows, .benefits, .jobs, .service-cards, .timeline, .accordion,
  .ab-badges, .ab-highlights, .ab-offers, .ab-timeline, .cs-cards, .cs-flow, .cs-glance__list, .faq-nav ul, .cx-points
):not(:is(.home-hero, .ha, .hww, [data-svc], .site-top, .site-footer) *):not(.is-in) > * { opacity: 0; }
html.motion-ready :is(
  .cards, .team-grid, .stats, .service-rows, .benefits, .jobs, .service-cards, .timeline, .accordion,
  .ab-badges, .ab-highlights, .ab-offers, .ab-timeline, .cs-cards, .cs-flow, .cs-glance__list, .faq-nav ul, .cx-points
).is-in > * { animation: mo-up .7s var(--mo-ease) calc(var(--i, 0) * 90ms + var(--d, 0s)) backwards; }
/* Milestone dots pop like the home page ring badge */
html.motion-ready .ab-timeline.is-in .ab-timeline__dot { animation: mo-pop .55s var(--mo-pop) calc(var(--i, 0) * 90ms + .25s) backwards; }

/* ---- 5. Closing call-to-action band: the box lifts in, then its button follows ---- */
html.motion-ready .cta-band__box:not(.is-in) { opacity: 0; }
html.motion-ready .cta-band__box.is-in { animation: mo-rise .9s var(--mo-ease) backwards; }
html.motion-ready .cta-band__box.is-in .btn-row { animation: mo-up .7s var(--mo-ease) .35s backwards; }

@keyframes mo-up { from { opacity: 0; transform: translateY(24px); } }
@keyframes mo-rise { from { opacity: 0; transform: translateY(40px) scale(.98); } }
@keyframes mo-wipe { from { clip-path: inset(0 100% 0 0 round 22px); } to { clip-path: inset(0 0 0 0 round 22px); } }
@keyframes mo-settle { from { transform: scale(1.12); } }
@keyframes mo-pop { from { opacity: 0; transform: scale(.4); } }

/* ---- Page to page: a soft cross-fade between pages (Chrome / Edge; other browsers navigate as usual) ---- */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .35s; animation-timing-function: ease; }

/* ---- Reduced motion: no hidden states, no animations, no page transitions ---- */
@media (prefers-reduced-motion: reduce) {
  html.motion-ready * { animation: none !important; }
  html.motion-ready :not(.is-in), html.motion-ready :not(.is-in) > * { opacity: 1 !important; clip-path: none !important; }
  @view-transition { navigation: none; }
}

/* ---- 6. About hero showcase: glow swells, rings draw in, the logo plate pops with a sheen, chips fly in ----
   Individual translate/scale properties are used so the entrance doesn't clash with the orbit spin or chip bob. */
html.motion-ready .ab-show:not(.is-in) :is(.ab-show__glow, .ab-show__dots, .ab-show__ring, .ab-show__orbit, .ab-show__plate, .ab-chip) { opacity: 0; }
html.motion-ready .ab-show.is-in .ab-show__glow { animation: mo-swell 1.2s var(--mo-ease) backwards; }
html.motion-ready .ab-show.is-in .ab-show__dots { animation: mo-fade .9s ease .2s backwards; }
html.motion-ready .ab-show.is-in .ab-show__ring { animation: mo-ring 1s var(--mo-ease) .15s backwards; }
html.motion-ready .ab-show.is-in .ab-show__orbit { animation: mo-ring 1.1s var(--mo-ease) .3s backwards, ab-orbit 40s linear 1.4s infinite; }
html.motion-ready .ab-show.is-in .ab-show__orbit i { animation: mo-pop .6s var(--mo-pop) .9s backwards; }
html.motion-ready .ab-show.is-in .ab-show__plate { animation: mo-plate .9s var(--mo-pop) .35s backwards; }
html.motion-ready .ab-show.is-in .ab-show__plate img { animation: mo-settle 1.6s var(--mo-ease) .35s backwards; }
html.motion-ready .ab-show.is-in .ab-show__plate::after { animation: mo-sheen 1.1s ease 1.1s; }
html.motion-ready .ab-show.is-in .ab-chip--1 { animation: mo-chip-left .8s var(--mo-pop) .8s backwards, ab-bob 6s ease-in-out 1.6s infinite; }
html.motion-ready .ab-show.is-in .ab-chip--2 { animation: mo-chip-right .8s var(--mo-pop) .95s backwards, ab-bob 6s ease-in-out -.4s infinite; }
html.motion-ready .ab-show.is-in .ab-chip--3 { animation: mo-chip-right .8s var(--mo-pop) 1.1s backwards, ab-bob 6s ease-in-out -2.4s infinite; }
@keyframes mo-fade { from { opacity: 0; } }
@keyframes mo-swell { from { opacity: 0; scale: .6; } }
@keyframes mo-ring { from { opacity: 0; scale: .7; } }
@keyframes mo-plate { from { opacity: 0; translate: 0 30px; scale: .88; } }
@keyframes mo-chip-left { from { opacity: 0; translate: -40px 0; scale: .85; } }
@keyframes mo-chip-right { from { opacity: 0; translate: 40px 0; scale: .85; } }
@keyframes mo-sheen { from { translate: -120% 0; } to { translate: 120% 0; } }

/* ---- 7. Contact illustrations slide up from behind the form card after it appears ---- */
html.motion-ready .contact-stage:not(:has(.form-panel.is-in)) .contact-art { opacity: 0; }
html.motion-ready .contact-stage:has(.form-panel.is-in) .contact-art { animation: mo-art-up .9s cubic-bezier(.3, 1.4, .5, 1) .5s backwards, contact-sway 7s ease-in-out 1.4s infinite; }
html.motion-ready .contact-stage:has(.form-panel.is-in) .contact-art--right { animation-delay: .65s, -2.1s; }
@keyframes mo-art-up { from { opacity: 0; translate: 0 60px; } }

/* ---- 8. Careers benefits: the heading block fades up (the written entries rise in turn, section 4) ---- */
html.motion-ready .cx-perks__head:not(.is-in) { opacity: 0; }
html.motion-ready .cx-perks__head.is-in { animation: mo-up .85s var(--mo-ease) backwards; }
html.motion-ready .cs-cards.is-in .cs-card__icon { animation: mo-pop .6s var(--mo-pop) calc(var(--i, 0) * 90ms + .35s) backwards; }

/* ---- 9. Case study banner: the badge pops in after the picture; At a glance rows follow the card ---- */
html.motion-ready .cs-hero__frame.is-in ~ .cs-hero__badge { animation: mo-pop .7s var(--mo-pop) .9s backwards; }
html.motion-ready .cs-hero__visual:has(.cs-hero__frame:not(.is-in)) :is(.cs-hero__badge, .cs-hero__outline, .cs-hero__dots) { opacity: 0; }
html.motion-ready .cs-hero__visual:has(.cs-hero__frame.is-in) :is(.cs-hero__outline, .cs-hero__dots) { animation: mo-fade 1s ease .5s backwards; }
html.motion-ready .cs-glance__list.is-in > * { animation-delay: calc(var(--i, 0) * 90ms + .25s); }

/* ---- 10. FAQ: topic headings slide in from the left with their icon popping; answers fade up as they open ---- */
html.motion-ready .faq-group__head:not(.is-in) { opacity: 0; }
html.motion-ready .faq-group__head.is-in { animation: mo-left .8s var(--mo-ease) backwards; }
html.motion-ready .faq-group__head.is-in .faq-group__icon { animation: mo-pop .6s var(--mo-pop) .25s backwards; }
html.motion-ready .faq-group__head.is-in .faq-group__count { animation: mo-fade .6s ease .45s backwards; }
.faq-page details[open] .accordion__body > * { animation: mo-up .5s var(--mo-ease) backwards; }
.faq-page details[open] .accordion__body > :nth-child(2) { animation-delay: .06s; }
.faq-page details[open] .accordion__body > :nth-child(n+3) { animation-delay: .12s; }
@keyframes mo-left { from { opacity: 0; transform: translateX(-28px); } }
@media (prefers-reduced-motion: reduce) { .faq-page details[open] .accordion__body > * { animation: none; } }

/* ---- 11. Careers headings: the pill fades in, the heading rises, then a sheen sweeps across the gradient words ---- */
html.motion-ready .cx-head:not(.is-in) { opacity: 0; }
html.motion-ready .cx-head.is-in { animation: mo-fade .4s ease backwards; }
html.motion-ready .cx-head.is-in .cx-head__pill { animation: mo-up .6s var(--mo-ease) backwards; }
html.motion-ready .cx-head.is-in h2 { animation: mo-up .8s var(--mo-ease) .12s backwards; }
html.motion-ready .cx-head.is-in .hl { animation: cx-sheen 1.6s ease .5s backwards; }
html.motion-ready .cx-head.is-in .cx-head__aside { animation: mo-up .8s var(--mo-ease) .25s backwards; }
@keyframes cx-sheen { from { background-position: 100% 0; } to { background-position: 0 0; } }
