/* Site-wide motion, shared by the editorial, interior and guide templates and driven
   by motion.js: hero entrances, scroll reveals, image parallax, particle fields and
   hover lift. It is all decoration, so reduced motion and print get the static page. */
:root{--fx-ease:cubic-bezier(.16,1,.3,1)}

/* Particle fields: a canvas behind the hero copy and the call-to-action band. */
.fx-host{position:relative;isolation:isolate}
.fx-field{position:absolute;inset:0;z-index:-1;pointer-events:none;opacity:0;transition:opacity 1.8s ease}
.fx-field.is-live{opacity:1}
.fx-field>canvas{display:block;width:100%;height:100%}
.fx-field--hero{-webkit-mask-image:linear-gradient(180deg,#000 55%,transparent);mask-image:linear-gradient(180deg,#000 55%,transparent)}
/* Heroes inside the page shell get a full-width field behind them, sized by motion.js. */
.fx-field--page{inset:0 0 auto;z-index:0;-webkit-mask-image:linear-gradient(180deg,transparent 40px,#000 170px,#000 68%,transparent);mask-image:linear-gradient(180deg,transparent 40px,#000 170px,#000 68%,transparent)}
.fx-field--band{-webkit-mask-image:linear-gradient(90deg,transparent 10%,#000 60%);mask-image:linear-gradient(90deg,transparent 10%,#000 60%)}
.fx-lift{position:relative;z-index:1}

/* Pause control for the background animation (the home hero keeps its own button). */
.fx-toggle{position:absolute;z-index:2;right:var(--gutter,24px);bottom:28px;width:36px;height:36px;display:grid;place-items:center;padding:0;border:1px solid rgba(206,224,230,.45);border-radius:50%;background:rgba(16,35,49,.45);color:#f4f8f9;font:500 12px/1 'DM Sans',system-ui,sans-serif;cursor:pointer;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);transition:background .2s,border-color .2s,color .2s}
.fx-toggle:hover{background:#66d9ef;border-color:#66d9ef;color:#141719}
.fx-toggle:focus-visible{outline:2px solid #66d9ef;outline-offset:4px}
.contact-page>.fx-toggle{right:auto;left:var(--gutter);bottom:34px}
.hero--subpage>.fx-toggle{right:5vw}
.site-top~main>.hero>.fx-toggle{top:20px;right:24px;bottom:auto}
@media(max-width:680px){.hero--subpage>.fx-toggle{right:24px}}

/* Page entrance: hero copy rises in; headline lines slide up from their baseline. */
@keyframes fx-in{from{opacity:0;translate:0 24px}to{opacity:1;translate:0 0}}
@keyframes fx-line{from{opacity:0;translate:0 100%;clip-path:inset(-40% -4% 100% -4%)}to{opacity:1;translate:0 0;clip-path:inset(-40% -4% -40% -4%)}}
@keyframes fx-fade{from{opacity:0}to{opacity:1}}
.hero-focus .eyebrow{animation:fx-in .9s var(--fx-ease) .05s both}
.hero-focus h1>span{animation:fx-line 1.15s var(--fx-ease) .14s both}
.hero-focus h1>span+span{animation-delay:.28s}
.hero-focus .hero-description{animation:fx-in 1s var(--fx-ease) .44s both}
.hero-focus .hero-actions{animation:fx-in 1s var(--fx-ease) .58s both}
.hero-focus .hero-bottom,.hero-focus .motion-toggle{animation:fx-fade 1.4s ease .9s both}
.services-hero>*{animation:fx-in 1s var(--fx-ease) .04s both}
.services-hero>.eyebrow{animation-delay:.1s}
.services-hero>h1{animation:fx-line 1.2s var(--fx-ease) .18s both}
.services-hero>.services-lead{animation-delay:.4s}
.services-hero>.hero-actions{animation-delay:.54s}
.contact-intro>*{animation:fx-in 1s var(--fx-ease) .04s both}
.contact-intro>h1{animation:fx-line 1.2s var(--fx-ease) .12s both}
.contact-intro>:nth-child(3){animation-delay:.32s}
.contact-intro>:nth-child(4){animation-delay:.42s}
.contact-intro>:nth-child(5){animation-delay:.52s}
.contact-intro>:nth-child(6){animation-delay:.6s}
.contact-form-panel{animation:fx-in 1.1s var(--fx-ease) .3s both}
.site-top~main>.hero>*{animation:fx-in 1s var(--fx-ease) .04s both}
.site-top~main>.hero>h1{animation:fx-line 1.2s var(--fx-ease) .12s both}
.site-top~main>.hero>.lead{animation-delay:.34s}
.site-top~main>.hero>.cta-row{animation-delay:.46s}
.site-top~main>.hero>.note{animation-delay:.56s}
.services-hero>.fx-toggle,.contact-page>.fx-toggle,.site-top~main>.hero>.fx-toggle{animation:fx-fade 1.2s ease 1s both}

/* Scroll reveals: motion.js marks blocks that start below the fold. */
@keyframes fx-rise{from{opacity:0;translate:0 34px}to{opacity:1;translate:0 0}}
@keyframes fx-frame{from{opacity:0;clip-path:inset(14% 9% 14% 9%)}25%{opacity:1}to{opacity:1;clip-path:inset(0 0 0 0)}}
@keyframes fx-settle{from{transform:scale(1.2)}to{transform:none}}
@keyframes fx-pop{from{scale:0;rotate:-90deg}to{scale:1;rotate:0deg}}
.fx-r{opacity:0;translate:0 34px}
.fx-r.fx-frame{translate:none;clip-path:inset(14% 9% 14% 9%)}
.fx-r.fx-on{animation:fx-rise 1s var(--fx-ease) var(--fx-delay,0s) both}
.fx-r.fx-frame.fx-on{animation:fx-frame 1.4s var(--fx-ease) var(--fx-delay,0s) both}
.fx-frame.fx-on>img{animation:fx-settle 1.4s var(--fx-ease) var(--fx-delay,0s) both}
.fx-r.fx-on.eyebrow::before,.fx-r.fx-on .eyebrow::before{animation:fx-pop .7s var(--fx-ease) calc(var(--fx-delay,0s) + .2s) both}

/* Figures drift against the scroll where scroll-driven animations exist. */
@supports (animation-timeline:view()){
  @keyframes fx-par{from{translate:0 -5%}to{translate:0 5%}}
  @keyframes fx-hero-par{from{translate:0 0}to{translate:0 26%}}
  .fx-par-host{view-timeline:--fx-par block;view-timeline-inset:0px}
  .fx-par{scale:1.14;animation:fx-par linear both;animation-timeline:--fx-par;animation-range:cover}
  .fx-frame.fx-on>.fx-par{animation:fx-settle 1.4s var(--fx-ease) var(--fx-delay,0s) both,fx-par linear both;animation-timeline:auto,--fx-par;animation-range:normal,cover}
  .hero-focus{view-timeline:--fx-hero block;view-timeline-inset:0px}
  .hero-focus .hero-image{animation:hero-drift 16s ease-in-out infinite alternate,fx-hero-par linear both;animation-timeline:auto,--fx-hero;animation-range:normal,exit}
}

/* Numbers, funnel bars and workflow steps play once they scroll into view. */
@keyframes fx-bar{from{scale:0 1}to{scale:1 1}}
@keyframes fx-dot{0%{scale:0}55%{scale:1.8}100%{scale:1}}
@keyframes fx-blink{0%,100%{opacity:1}50%{opacity:.3}}
.fx-counting{font-variant-numeric:tabular-nums}
.fx-bars .funnel-track>span{transform-origin:0 50%;scale:0 1}
.fx-bars.fx-go .funnel-track>span{animation:fx-bar 1.6s var(--fx-ease) calc(var(--i,0) * .14s + .1s) both}
.fx-steps>li::before{scale:0}
.fx-steps.fx-go>li::before{animation:fx-dot .8s var(--fx-ease) calc(var(--i,0) * .16s + .25s) both}
.hero-place i{animation:fx-blink 2.6s ease-in-out 1.2s infinite}
.hero.is-paused .hero-place i{animation-play-state:paused}

/* Hover lift for cards and buttons on pointer devices. */
@media(hover:hover) and (pointer:fine){
  .case-preview,.solution-directory>article{transition:transform .5s var(--fx-ease),box-shadow .5s var(--fx-ease)}
  .case-preview:hover,.solution-directory>article:hover{transform:translateY(-6px);box-shadow:0 28px 48px -30px rgba(0,0,0,.9)}
  .case-preview-image>img{transition:transform 1s var(--fx-ease)}
  .case-preview:hover .case-preview-image>img{transform:scale(1.04)}
  /* Product screens float free of their captions, so only the screen lifts. */
  .product-shot>svg,.product-shot>img{transition:transform .9s var(--fx-ease),box-shadow .9s var(--fx-ease)}
  .product-shot:hover>svg,.product-shot:hover>img{transform:translateY(-8px);box-shadow:0 0 0 1px rgba(102,217,239,.35),0 60px 90px -44px rgba(0,0,0,.95)}
  .button:hover{transform:translateY(-2px)}
}

@media(prefers-reduced-motion:reduce){
  .fx-r,.fx-r.fx-frame{opacity:1!important;translate:none!important;clip-path:none!important}
  .fx-r,.fx-r *,.fx-r::before,.fx-r *::before,.fx-bars *,.fx-steps>li::before,.hero-focus *,.services-hero>*,.contact-intro>*,.contact-form-panel,.site-top~main>.hero>*,.hero-place i{animation:none!important}
  .fx-par{scale:none!important;animation:none!important}
  .fx-bars .funnel-track>span,.fx-steps>li::before{scale:none!important}
  .fx-field{transition:none}
  .fx-toggle{display:none}
}
@media print{
  .fx-field,.fx-toggle{display:none!important}
  .fx-r,.fx-r.fx-frame{opacity:1!important;translate:none!important;clip-path:none!important}
  .fx-bars .funnel-track>span,.fx-steps>li::before{scale:none!important}
}
