/* ============================================================================
   MOTION — the one file that does NOT go through the Webflow builder.

   Everything here uses @keyframes, which data_whtml_builder rejects. At transfer
   time this file's contents go into Webflow's custom code (Site settings or the
   page's own head), which needs a paid Workspace or an active Site plan. Since
   publishing to manelink.ai needs a paid Site plan anyway, that costs nothing.

   Every other css/ file stays builder-safe. Keep it that way: if a rule needs a
   keyframe it belongs in here, not there.

   Nothing in this file is load-bearing. With it removed the page is complete and
   static, which is the standard we keep whether or not the platform forces it.
   ========================================================================== */

/* ---- HERO: the screenshot settles in, then the Office acts out the headline ----
   Once:  the shot rises and tilts flat (1s), a blue glow comes up under it,
          the two chart lines draw in left to right.
   Loop (18s, from 2.8s): three items queue in the Inbox. For each, the cursor
          comes in and clicks Approve, the row turns green and the counts step
          down (3, 2, 1); after the third the Inbox empties and a toast confirms. 0% of every loop keyframe
          is the resting frame in hero.css, so the start and the delay are seamless. */
@keyframes shot-in   { from{opacity:0;transform:perspective(1800px) rotateX(12deg) translateY(48px) scale(.97)} to{opacity:1;transform:none} }
@keyframes shot-glow { from{box-shadow:var(--shadow)} to{box-shadow:var(--shadow),0 40px 90px -30px rgba(41,70,182,.38)} }
@keyframes hs-draw   { from{transform:scaleX(1)} to{transform:scaleX(0)} }
@keyframes hs-p1    { 0%,15.6%{opacity:1;transform:none} 16.7%,96.7%{opacity:0;transform:translateY(6px)} 100%{opacity:1;transform:none} }
@keyframes hs-p2    { 0%,27.8%{opacity:0;transform:translateY(6px)} 30%,43.3%{opacity:1;transform:none} 44.4%,100%{opacity:0;transform:translateY(6px)} }
@keyframes hs-p3    { 0%,55.6%{opacity:0;transform:translateY(6px)} 57.8%,71.1%{opacity:1;transform:none} 72.2%,100%{opacity:0;transform:translateY(6px)} }
@keyframes hs-done  { 0%,16%{opacity:0} 17.2%,24.4%{opacity:1} 25.6%,44%{opacity:0} 45%,52.2%{opacity:1} 53.3%,71.7%{opacity:0} 72.8%,80%{opacity:1} 81.1%,100%{opacity:0} }
@keyframes hs-empty { 0%,82%{opacity:0} 84%,95%{opacity:1} 97%,100%{opacity:0} }
@keyframes hs-n3    { 0%,15.6%{opacity:1} 16.7%,96.7%{opacity:0} 100%{opacity:1} }
@keyframes hs-n2    { 0%,15.6%{opacity:0} 16.7%,43.3%{opacity:1} 44.4%,100%{opacity:0} }
@keyframes hs-n1    { 0%,43.3%{opacity:0} 44.4%,71.1%{opacity:1} 72.2%,100%{opacity:0} }
@keyframes hs-n0    { 0%,71.1%{opacity:0} 72.2%,96.7%{opacity:1} 100%{opacity:0} }
@keyframes hs-cur   { 0%,5%{opacity:0;transform:translate(150px,130px)} 6.7%{opacity:1;transform:translate(130px,112px)} 14.4%{opacity:1;transform:none}
                      15.6%{transform:scale(.82)} 16.7%{opacity:1;transform:none} 20%{opacity:0;transform:translate(24px,40px)}
                      20.1%,32.7%{opacity:0;transform:translate(150px,130px)} 34.4%{opacity:1;transform:translate(130px,112px)} 42.2%{opacity:1;transform:none}
                      43.3%{transform:scale(.82)} 44.4%{opacity:1;transform:none} 47.8%{opacity:0;transform:translate(24px,40px)}
                      47.9%,60.5%{opacity:0;transform:translate(150px,130px)} 62.2%{opacity:1;transform:translate(130px,112px)} 70%{opacity:1;transform:none}
                      71.1%{transform:scale(.82)} 72.2%{opacity:1;transform:none} 75.6%,100%{opacity:0;transform:translate(24px,40px)} }
@keyframes hs-toast { 0%,73%{opacity:0;transform:translateY(10px)} 76%,92%{opacity:1;transform:none} 95%,100%{opacity:0;transform:translateY(-4px)} }
@keyframes hs-live   { from{box-shadow:0 0 0 1.5px #fff,0 0 0 1.5px rgba(31,157,107,.55)} to{box-shadow:0 0 0 1.5px #fff,0 0 0 9px rgba(31,157,107,0)} }
.hero .shot,.shot-sec .shot{animation:shot-in 1s cubic-bezier(.2,.8,.2,1) .1s both,shot-glow 1.4s ease .7s both}
/* phones: the portrait shot is tall, so the tilt would push its near edge past the
   screen for a moment and flash a sideways scrollbar. A plain rise instead. */
@keyframes shot-rise { from{opacity:0;transform:translateY(32px)} to{opacity:1;transform:none} }
@media (max-width:767px){ .hero .shot,.shot-sec .shot{animation-name:shot-rise,shot-glow} }
.js .hs-mask{animation:hs-draw 1.6s cubic-bezier(.45,0,.2,1) 1s both}
.js .hs-m2{animation-delay:1.25s}
.js .hs-p1{animation:hs-p1 18s ease 2.8s infinite both}
.js .hs-p2{animation:hs-p2 18s ease 2.8s infinite both}
.js .hs-p3{animation:hs-p3 18s ease 2.8s infinite both}
.js .hs-done{animation:hs-done 18s ease 2.8s infinite both}
.js .hs-empty{animation:hs-empty 18s ease 2.8s infinite both}
.js .hs-n3,.js .hs-q3{animation:hs-n3 18s ease 2.8s infinite both}
.js .hs-n2,.js .hs-q2{animation:hs-n2 18s ease 2.8s infinite both}
.js .hs-n1,.js .hs-q1{animation:hs-n1 18s ease 2.8s infinite both}
.js .hs-q0{animation:hs-n0 18s ease 2.8s infinite both}
.js .hs-cur{animation:hs-cur 18s cubic-bezier(.45,0,.25,1) 2.8s infinite both}
.js .hs-toast{animation:hs-toast 18s ease 2.8s infinite both}
.js .hs-live{animation:hs-live 1.8s ease-out infinite}

/* ---- TOUR (product page): five Office pages take turns, 5s each ----------------
   One 25s timeline. Page i is on screen for [5i, 5i+5); the negative delays put
   each element at its place on that timeline from the first frame, so page 0
   (Inbox, the resting state in office-tour.css) is the one showing at the start.
   Hovering the tour pauses it, so a page can be read. */
@keyframes tr-pane { 0%{opacity:0;visibility:visible;transform:translateY(8px)} 2.4%,18%{opacity:1;visibility:visible;transform:none}
                     20%,100%{opacity:0;visibility:visible;transform:translateY(-4px)} }
@keyframes tr-cap  { 0%{opacity:0;visibility:visible} 2.4%,18%{opacity:1;visibility:visible} 20%,100%{opacity:0;visibility:visible} }
@keyframes tr-tab  { 0%,19%{background-color:#eaf0f8;color:var(--navy)} 20%,100%{background-color:var(--tr-off);color:var(--tr-offc)} }
.tr.go .tr-p{animation:tr-pane 25s ease infinite both}
.tr.go .tr-c{animation:tr-cap 25s ease infinite both}
.tr.go .tr-t{animation:tr-tab 25s ease infinite both}
.tr.go .tr-p1,.tr.go .tr-c1,.tr.go .tr-t1{animation-delay:-20s}
.tr.go .tr-p2,.tr.go .tr-c2,.tr.go .tr-t2{animation-delay:-15s}
.tr.go .tr-p3,.tr.go .tr-c3,.tr.go .tr-t3{animation-delay:-10s}
.tr.go .tr-p4,.tr.go .tr-c4,.tr.go .tr-t4{animation-delay:-5s}
/* each page's action, one second into its turn: before fades, after lands, a
   toast confirms; the bar on Progress grows. Same 25s timeline and delays. */
@keyframes tr-sa    { 0%,7%{opacity:1} 8.5%,19.5%{opacity:0} 20%,100%{opacity:1} }
@keyframes tr-sb    { 0%,7%{opacity:0;transform:scale(.92)} 8.5%,19%{opacity:1;transform:none} 20%,100%{opacity:0} }
@keyframes tr-toast { 0%,8.5%{opacity:0;transform:translateY(10px)} 10.5%,17%{opacity:1;transform:none} 18.5%,100%{opacity:0;transform:translateY(-4px)} }
@keyframes tr-grow  { 0%,7%{width:72%} 10%,19.5%{width:84%} 20%,100%{width:72%} }
.tr.go .tr-sa{animation:tr-sa 25s ease infinite both}
.tr.go .tr-sb{animation:tr-sb 25s ease infinite both}
.tr.go .tr-toast{animation:tr-toast 25s cubic-bezier(.2,.7,.2,1) infinite both}
.tr.go .tr-grow{animation:tr-grow 25s cubic-bezier(.3,.7,.2,1) infinite both}
.tr.go .tr-p1 .tr-sa,.tr.go .tr-p1 .tr-sb,.tr.go .tr-p1 .tr-toast,.tr.go .tr-p1 .tr-grow{animation-delay:-20s}
.tr.go .tr-p2 .tr-sa,.tr.go .tr-p2 .tr-sb,.tr.go .tr-p2 .tr-toast,.tr.go .tr-p2 .tr-grow{animation-delay:-15s}
.tr.go .tr-p3 .tr-sa,.tr.go .tr-p3 .tr-sb,.tr.go .tr-p3 .tr-toast,.tr.go .tr-p3 .tr-grow{animation-delay:-10s}
.tr.go .tr-p4 .tr-sa,.tr.go .tr-p4 .tr-sb,.tr.go .tr-p4 .tr-toast,.tr.go .tr-p4 .tr-grow{animation-delay:-5s}
.tr.go:hover .tr-p,.tr.go:hover .tr-c,.tr.go:hover .tr-t,.tr.go:hover .tr-sa,.tr.go:hover .tr-sb,.tr.go:hover .tr-toast,.tr.go:hover .tr-grow{animation-play-state:paused}

/* ---- CONNECTIONS (pricing page): the orb behind the name. A blue-to-purple lava
   ring flows continuously round the white middle.
   The name does not move. */
/* the lava: two connected bands, each turning and changing shape on its own rhythm */
@keyframes cn-lava1 { 0%{transform:rotate(0deg);border-radius:62% 38% 54% 46% / 44% 58% 42% 56%}
                      33%{border-radius:40% 60% 64% 36% / 58% 40% 60% 42%}
                      66%{border-radius:56% 44% 38% 62% / 38% 62% 44% 56%}
                      100%{transform:rotate(360deg);border-radius:62% 38% 54% 46% / 44% 58% 42% 56%} }
@keyframes cn-lava2 { 0%{transform:rotate(0deg) scale(1);border-radius:40% 60% 46% 54% / 60% 40% 58% 42%}
                      50%{transform:rotate(-180deg) scale(1.08);border-radius:62% 38% 60% 40% / 40% 62% 38% 60%}
                      100%{transform:rotate(-360deg) scale(1);border-radius:40% 60% 46% 54% / 60% 40% 58% 42%} }
.cn-l1{animation:cn-lava1 18s ease-in-out infinite}
.cn-l2{animation:cn-lava2 23s ease-in-out infinite}
@keyframes cn-mote { 0%{opacity:0;transform:translate(0,14px) scale(.5)} 20%{opacity:.95} 70%{opacity:.8}
  100%{opacity:0;transform:translate(10px,-46px) scale(1.1)} }
.cn-pt{animation-name:cn-mote;animation-timing-function:ease-in-out;animation-iteration-count:infinite}
.cn-pt:nth-of-type(even){animation-name:cn-mote2}
@keyframes cn-mote2 { 0%{opacity:0;transform:translate(0,12px) scale(.5)} 25%{opacity:.9} 70%{opacity:.75}
  100%{opacity:0;transform:translate(-12px,-40px) scale(1)} }

/* ---- approval flow: the dashes march toward each node ------------------- */
/* A dashed border cannot animate. Every connector is a striped background, so
   shifting background-position slides the dashes along the line, always in the
   direction the work travels: down out of the tools, inward to the engine, down
   through the gate. */
@keyframes dash-down{ to{background-position:0 6px} }
@keyframes dash-right{ to{background-position:6px 0} }

.br-up,.br-dn,.br-c,.dg-stem,.dg-mid::before,.dg-mid::after{animation:dash-down 600ms linear infinite}
.br-h,.dg-wire{animation:dash-right 600ms linear infinite}
/* below the gate the dashes crawl: nothing moves quickly past your approval
   (set in full with the draw-in, further down) */

/* the gate breathes, so the eye lands on the one node that can stop the flow */
@keyframes gate-breathe{
  0%,100%{box-shadow:0 0 0 7px rgba(41,70,182,.09); border-color:rgba(166,179,229,.5)}
  50%    {box-shadow:0 0 0 14px rgba(41,70,182,.15); border-color:rgba(190,220,255,.8)}
}
.dg-gate{animation:gate-breathe 3.6s ease-in-out infinite}

/* the empty slots pulse gently, because they are an invitation */
@keyframes slot-pulse{
  0%,100%{border-color:rgba(255,255,255,.18)}
  50%    {border-color:rgba(255,255,255,.34)}
}
.dg-ghost,.dg-add{animation:slot-pulse 4.2s ease-in-out infinite}
.dg-acts .dg-ghost:last-child{animation-delay:1.4s}
.dg-add{animation-delay:.7s}

@media (max-width:767px){
  .dg-wire{animation-name:dash-down}
}


/* ---- tool boxes turn to show what each tool may do ---------------------- */
/* Staggered, so the row ripples rather than flipping as a block. */
@keyframes fx-front{ 0%,28%{transform:rotateX(0deg)} 40%,70%{transform:rotateX(-180deg)} 82%,100%{transform:rotateX(0deg)} }
@keyframes fx-back { 0%,28%{transform:rotateX(180deg)} 40%,70%{transform:rotateX(0deg)} 82%,100%{transform:rotateX(180deg)} }
/* Stripe's flip curve, cubic-bezier(.9,0,.1,1): it holds, then snaps over */
.fx-f{animation:fx-front 12s cubic-bezier(.9,0,.1,1) infinite}
.fx-b{animation:fx-back  12s cubic-bezier(.9,0,.1,1) infinite}
.dg-group>.dg-flip:nth-child(1) .fx-f,.dg-group>.dg-flip:nth-child(1) .fx-b{animation-delay:0s}
.dg-group>.dg-flip:nth-child(2) .fx-f,.dg-group>.dg-flip:nth-child(2) .fx-b{animation-delay:.7s}
.dg-group>.dg-flip:nth-child(4) .fx-f,.dg-group>.dg-flip:nth-child(4) .fx-b{animation-delay:1.4s}
.dg-group>.dg-flip:nth-child(5) .fx-f,.dg-group>.dg-flip:nth-child(5) .fx-b{animation-delay:2.1s}

/* ---- the ribbon on the seats card --------------------------------------- */
/* The twist. Both halves pivot on the waist, in opposite phase: as the left
   lobe collapses the right one opens, which is what the eye reads as a ribbon
   turning over. A shared period keeps the pinch in step; the skew adds the
   tilt a turning band would have. */
/* A SHEAR, not a scale. skewY leaves the pivot column untouched — same position
   and same thickness — so the two halves stay welded at the waist. Counter-phase
   scaleY did not: it met the seam at 0.56 on one side and 1.12 on the other and
   left a visible notch. Any scaleY here is applied equally to both halves. */
@keyframes rib-twist-l{ 0%,100%{transform:skewY(-3.4deg) scaleY(1.12)}
                        50%    {transform:skewY(3.4deg)  scaleY(.88)} }
@keyframes rib-twist-r{ 0%,100%{transform:skewY(3.4deg)  scaleY(1.12)}
                        50%    {transform:skewY(-3.4deg) scaleY(.88)} }
@keyframes rib-lit    { from{transform:translate3d(-14%,4%,0) scale(.94)}
                        to  {transform:translate3d(14%,-4%,0) scale(1.08)} }
@keyframes rib-wave  { from{transform:translate3d(0,0,0)} to{transform:translate3d(-50%,0,0)} }
@keyframes rib-wave2 { from{transform:translate3d(0,0,0)} to{transform:translate3d(-62.5%,0,0)} }
.rib-w  {animation:rib-wave 16s linear infinite}
.rib-w2 {animation:rib-wave2 26s linear infinite}
.rib-l  {animation:rib-twist-l 24s ease-in-out infinite}
.rib-r  {animation:rib-twist-r 24s ease-in-out infinite}
.rib-lit{animation:rib-lit 17s ease-in-out infinite alternate}

/* ---- the sun on the cost card -------------------------------------------- */
/* The two structures move differently, because they are different things. The
   rim is a ring of points with no angular feature, so it can turn — that is the
   orbit. The flames are rays, and a spinning starburst reads as a wheel, so
   they travel outward instead: expand and fade, returning to the rim. */
@keyframes orb-cw   { to{transform:rotate(360deg)} }
@keyframes orb-ccw  { to{transform:rotate(-360deg)} }
/* never reaches 0: there is only one flame layer, so a keyframe that fades out
   completely blinks the prominences off once a cycle instead of pulsing them */
@keyframes orb-flare{ 0%,100%{transform:scale(.955);opacity:.44}
                      48%    {transform:scale(1.075);opacity:1} }
@keyframes orb-breathe{ 0%,100%{transform:scale(1);opacity:.82} 50%{transform:scale(1.06);opacity:1} }
.orb-1{animation:orb-cw  150s linear infinite}
.orb-3{animation:orb-ccw  96s linear infinite}
.orb-2{animation:orb-flare 7s ease-in-out infinite}
.orb-h{animation:orb-breathe 9s ease-in-out infinite}

/* ---- the globe on the journey card -------------------------------------- */
/* The dots are a fixed image, so nothing here rotates them. What travels is the
   light across them, west to east, the way the surface of a turning globe moves. */
/* -25%..125% keeps the band on the disc: a wider travel spends most of the
   cycle lighting empty space beside the globe */
@keyframes glb-sweep  { from{background-position:-25% 0} to{background-position:125% 0} }
@keyframes glb-breathe{ 0%,100%{transform:scale(1);opacity:.84} 50%{transform:scale(1.05);opacity:1} }
.glb-lit {animation:glb-sweep 13s linear infinite}
.glb-haze{animation:glb-breathe 11s ease-in-out infinite}

/* ---- PLAN TOUR (pricing page) -------------------------------------------- */
/* Stripe's Billing hero runs on a script timeline; this is the same idea as one
   11s loop of keyframes on a fixed 1024x522 stage, so every value is an exact
   pixel and nothing is measured at runtime. Three frames:
     A  0-26%   the pricing page; One workspace is picked
     B 26-51%   the two outer cards morph into the Office it installs
     C 51-90%   the first approval arrives, is approved, and leaves the Inbox
   then everything fades and the loop starts again from A. Staggers are plain
   animation delays: every element shares the 11s period (sped up from 18s, 2026-09-22), so a delay only shifts
   its own phase and the frames stay in step. */
@keyframes pt-a-in { 0%{opacity:0;transform:translateY(34px)} 5%,24%{opacity:1;transform:none}
                     26.5%,100%{opacity:0;transform:translateY(-6px)} }
@keyframes pt-pick { 0%,18%{transform:none;background:#2946b6} 19.5%{transform:scale(.95);background:#1e39a3}
                     21%,100%{transform:none;background:#2946b6} }
@keyframes pt-nav  { 0%,24%{opacity:1} 26.5%,95%{opacity:0} 100%{opacity:1} }
@keyframes pt-ua   { 0%,25%{opacity:1} 27%,95%{opacity:0} 97%,100%{opacity:1} }
@keyframes pt-ub   { 0%,25%{opacity:0} 27%,51%{opacity:1} 53%,100%{opacity:0} }
@keyframes pt-uc   { 0%,51%{opacity:0} 53%,93%{opacity:1} 95%,100%{opacity:0} }
/* the morph: the surfaces are empty cards, so resizing them distorts nothing,
   and Stripe's counter-scaled inner layer is not needed */
@keyframes pt-sl { 0%{left:30px;top:106px;width:310.67px;height:340px;opacity:0} 3%{opacity:1}
                   26%{left:30px;top:106px;width:310.67px;height:340px}
                   34%,91%{left:20px;top:100px;width:484px;height:356px;opacity:1}
                   95%{left:20px;top:100px;width:484px;height:356px;opacity:0}
                   95.5%,100%{left:30px;top:106px;width:310.67px;height:340px;opacity:0} }
@keyframes pt-sr { 0%{left:683.33px;top:106px;width:310.67px;height:340px;opacity:0} 3%{opacity:1}
                   26%{left:683.33px;top:106px;width:310.67px;height:340px}
                   34%,91%{left:520px;top:100px;width:484px;height:356px;opacity:1}
                   95%{left:520px;top:100px;width:484px;height:356px;opacity:0}
                   95.5%,100%{left:683.33px;top:106px;width:310.67px;height:340px;opacity:0} }
@keyframes pt-sc { 0%{opacity:0} 3%,24%{opacity:1;transform:none} 27%,100%{opacity:0;transform:scale(.96)} }
@keyframes pt-tb { 0%,31%{opacity:0;transform:translateY(10px)} 34%,90%{opacity:1;transform:none} 93.5%,100%{opacity:0;transform:none} }
@keyframes pt-in { 0%,32%{opacity:0;transform:translateY(22px)} 36%,90%{opacity:1;transform:none} 93.5%,100%{opacity:0;transform:none} }
@keyframes pt-hot{ 0%,47%{background:#fff;border-color:#e4ecf5} 49.5%,83%{background:#eceffb;border-color:#2946b6}
                   85%,100%{background:#fff;border-color:#e4ecf5} }
@keyframes pt-q1 { 0%,80%{height:50px;opacity:1;margin-bottom:0} 84%,93%{height:0;opacity:0;margin-bottom:-8px}
                   94%,100%{height:50px;opacity:1;margin-bottom:0} }
@keyframes pt-n4 { 0%,81%{opacity:1} 83.5%,100%{opacity:0} }
@keyframes pt-n3 { 0%,81%{opacity:0} 83.5%,100%{opacity:1} }
@keyframes pt-scrim{ 0%,51%{opacity:0} 54%,78%{opacity:1} 81.5%,100%{opacity:0} }
@keyframes pt-card { 0%,52%{opacity:0;transform:translateY(26px) scale(.98)} 56%,78%{opacity:1;transform:none}
                     81.5%,100%{opacity:0;transform:translateY(-10px)} }
@keyframes pt-yes  { 0%,66%{transform:none;background:#2946b6} 67.5%{transform:scale(.95);background:#1e39a3}
                     69%,100%{transform:none;background:#2946b6} }
@keyframes pt-cb   { 0%,69%{opacity:1} 71%,99%{opacity:0} 100%{opacity:1} }
@keyframes pt-ca   { 0%,69%{opacity:0;transform:scale(.94)} 71.5%,99%{opacity:1;transform:none} 100%{opacity:0} }

.pt-plan,.pt-ta{animation:pt-a-in 11s ease both infinite}
.pt-p2{animation-delay:0.08s} .pt-p3{animation-delay:0.14s}
.pt-pick{animation:pt-pick 11s ease infinite}
.pt-nav{animation:pt-nav 11s ease infinite}
.pt-ua{animation:pt-ua 11s ease infinite}
.pt-ub{animation:pt-ub 11s ease infinite}
.pt-uc{animation:pt-uc 11s ease infinite}
.pt-sl{animation:pt-sl 11s cubic-bezier(.65,0,.35,1) infinite}
.pt-sr{animation:pt-sr 11s cubic-bezier(.65,0,.35,1) infinite}
.pt-sc{animation:pt-sc 11s ease infinite}
.pt-tb{animation:pt-tb 11s ease infinite}
.pt-in{animation:pt-in 11s cubic-bezier(.2,.7,.2,1) both infinite}
.pt-bl>.pt-in:nth-child(2){animation-delay:0.08s} .pt-bl>.pt-in:nth-child(3){animation-delay:0.14s}
.pt-bl>.pt-in:nth-child(4){animation-delay:0.22s} .pt-bl>.pt-in:nth-child(5){animation-delay:0.30s}
.pt-bl>.pt-in:nth-child(6){animation-delay:0.36s}
.pt-br>.pt-hd{animation-delay:0.03s}
.pt-br>.pt-in:nth-child(3){animation-delay:0.19s} .pt-br>.pt-in:nth-child(4){animation-delay:0.25s}
.pt-br>.pt-in:nth-child(5){animation-delay:0.33s}
/* row one fades in with the rest, lights up when its approval opens, and then
   leaves the list once approved: two animations on two different properties */
.pt-q1 .pt-q{animation:pt-in 11s cubic-bezier(.2,.7,.2,1) .11s both infinite,pt-hot 11s ease infinite}
.pt-q1{animation:pt-q1 11s ease infinite}
.pt-n4{animation:pt-n4 11s ease infinite}
.pt-n3{animation:pt-n3 11s ease infinite}
.pt-scrim{animation:pt-scrim 11s ease infinite}
.pt-card{animation:pt-card 11s cubic-bezier(.2,.7,.2,1) infinite}
.pt-yes{animation:pt-yes 11s ease infinite}
.pt-cb{animation:pt-cb 11s ease infinite}
.pt-ca{animation:pt-ca 11s ease infinite}
/* hold at the start until it is on screen, so nobody arrives mid-loop. Gated on
   .js: without the reveal script there is nothing to add .in, so it just runs */
.js .pt:not(.in) .pt-stage *{animation-play-state:paused}

/* ---- GATE (office page) ----------------------------------------------------- */
/* After Stripe Radar's hero. Radar keyframes only its small loops (dashes,
   pulses, a loading ring) and scripts the scenario; here the scenario is a 16s
   loop of keyframes too. Timeline:
     0-24%   three checks run, one after another; the second one flags
    22-37%   APPROVAL REQUIRED fills, and the action's recipients turn amber: Held
    38-72%   the action profile builds, then its analysis and rules land
    76-90%   the approval field reads Waiting in your Inbox
    90-100%  everything settles back for the next pass
   The resting state in gate.css is the finished frame, so every keyframe here
   starts from "not yet" and ends back at it. Staggers are delays on a shared
   16s period; each off-time stays inside the cycle so nothing wraps. */
@keyframes gt-rot     { to{transform:rotate(360deg)} }
@keyframes gt-spin-on { 0%,1%{opacity:0} 2%,8%{opacity:1} 9.5%,100%{opacity:0} }
@keyframes gt-ok-on   { 0%,8%{opacity:0;transform:scale(.5)} 10%,84%{opacity:1;transform:none} 86%,100%{opacity:0} }
@keyframes gt-pulse   { 0%{box-shadow:0 0 0 0 rgba(102,124,210,.55)} 70%,100%{box-shadow:0 0 0 9px rgba(102,124,210,0)} }
@keyframes gt-dash-x  { to{background-position:8px 0} }
@keyframes gt-dash-y  { to{background-position:0 8px} }
@keyframes gt-lit     { 0%,9%{opacity:.6} 11%,84%{opacity:1} 87%,100%{opacity:.6} }
@keyframes gt-lit-bus { 0%,23%{opacity:.6} 25%,84%{opacity:1} 87%,100%{opacity:.6} }
@keyframes gt-lit2    { 0%,37%{opacity:.6} 39%,88%{opacity:1} 91%,100%{opacity:.6} }
@keyframes gt-v0      { 0%,22%{opacity:1} 24%,90%{opacity:0} 93%,100%{opacity:1} }
@keyframes gt-v1      { 0%,22%{opacity:0} 24%,90%{opacity:1} 93%,100%{opacity:0} }
@keyframes gt-fill-l  { 0%,22%{transform:scaleX(0);opacity:1} 34%,88%{transform:scaleX(1);opacity:1}
                        92%{transform:scaleX(1);opacity:0} 93%,100%{transform:scaleX(0);opacity:0} }
@keyframes gt-held    { 0%,35%{opacity:0} 37.5%,90%{opacity:1} 93%,100%{opacity:0} }
@keyframes gt-fto     { 0%,35%{color:#040d1c} 37.5%,90%{color:#2946b6} 93%,100%{color:#040d1c} }
@keyframes gt-p0      { 0%,56%{opacity:1} 58%,90%{opacity:0} 93%,100%{opacity:1} }
@keyframes gt-p1      { 0%,56%{opacity:0} 58%,90%{opacity:1} 93%,100%{opacity:0} }
@keyframes gt-fill-r  { 0%,40%{transform:scaleX(0);opacity:1} 56%,88%{transform:scaleX(1);opacity:1}
                        92%{transform:scaleX(1);opacity:0} 93%,100%{transform:scaleX(0);opacity:0} }
@keyframes gt-t0      { 0%,57%{opacity:1} 59%,86%{opacity:0} 88%,100%{opacity:1} }
@keyframes gt-t1      { 0%,57%{opacity:0;transform:scale(.9)} 59%,86%{opacity:1;transform:none} 88%,100%{opacity:0} }
@keyframes gt-rule-on { 0%,68%{opacity:0;transform:translateY(8px)} 71%,86%{opacity:1;transform:none} 88%,100%{opacity:0} }
@keyframes gt-a0      { 0%,76%{opacity:1} 78%,90%{opacity:0} 93%,100%{opacity:1} }
@keyframes gt-a1      { 0%,76%{opacity:0} 78%,90%{opacity:1} 93%,100%{opacity:0} }
@keyframes gt-run-x   { from{transform:translateX(-200px)} to{transform:translateX(1100px)} }
@keyframes gt-run-y   { from{transform:translateY(-200px)} to{transform:translateY(620px)} }

.gt-spin{animation:gt-spin-on 16s both infinite,gt-rot 1s linear infinite}
.gt-ok{animation:gt-ok-on 16s cubic-bezier(.2,.9,.3,1.3) both infinite}
.gt-c2 img{animation-delay:.96s,0s} .gt-c3 img{animation-delay:1.92s,0s}
.gt-c2 .gt-ok{animation-delay:.96s} .gt-c3 .gt-ok{animation-delay:1.92s}
.gt-dot{animation:gt-pulse 1.8s cubic-bezier(.65,.05,.36,1) infinite}
.gt-c2 .gt-dot{animation-delay:.6s} .gt-c3 .gt-dot{animation-delay:1.2s}
.gt-lh{animation:gt-dash-x .8s linear infinite,gt-lit 16s ease infinite}
.gt-lv{animation:gt-dash-y .8s linear infinite,gt-lit 16s ease infinite}
.gt-l2{animation-delay:0s,.96s} .gt-l3{animation-delay:0s,1.92s}
/* its own keyframe rather than a 2.24s delay, which pushed its dim-out past 100% */
.gt-lbus,.gt-lin{animation-name:gt-dash-y,gt-lit-bus}
.gt-lin{animation-name:gt-dash-x,gt-lit-bus}
.gt-lout,.gt-lp1,.gt-lp2{animation-name:gt-dash-x,gt-lit2}
.gt-lbus2{animation-name:gt-dash-y,gt-lit2}
.gt-v0{animation:gt-v0 16s ease infinite}
.gt-v1{animation:gt-v1 16s ease infinite}
.gt-fill-l{animation:gt-fill-l 16s cubic-bezier(.4,0,.2,1) infinite}
.gt-held,.gt-tint{animation:gt-held 16s ease infinite}
.gt-fto{animation:gt-fto 16s ease infinite}
.gt-p0{animation:gt-p0 16s ease infinite}
.gt-p1,.gt-pct{animation:gt-p1 16s ease infinite}
.gt-fill-r{animation:gt-fill-r 16s cubic-bezier(.4,0,.2,1) infinite}
.gt-t0{animation:gt-t0 16s ease infinite}
.gt-t1{animation:gt-t1 16s cubic-bezier(.2,.9,.3,1.2) infinite}
.gt-side>.gt-row:nth-of-type(4) .gt-tag>*{animation-delay:.64s}
.gt-side>.gt-row:nth-of-type(5) .gt-tag>*{animation-delay:1.28s}
.gt-r{animation:gt-rule-on 16s ease infinite}
.gt-side>.gt-r:nth-of-type(8){animation-delay:.64s}
.gt-a0{animation:gt-a0 16s ease infinite}
.gt-a1,.gt-tint2{animation:gt-a1 16s ease infinite}
.gt-run1{animation:gt-run-x 6s linear infinite}
.gt-run2{animation:gt-run-x 7.5s linear 2.6s infinite reverse}
.gt-run3{animation:gt-run-y 5s linear 1.2s infinite}
/* the resting state is the FINISHED frame, so anything waiting out a stagger
   delay would show "done" early (the third tag read None at 0.9s). backwards
   fill holds each element on its 0% frame until its delay is up. Declared last
   so it outranks the shorthands above, which reset fill-mode to none. */
.gt-stage *{animation-fill-mode:both}
/* hold at the start until on screen; without the reveal script it just runs */
.js .gt:not(.in) .gt-stage *{animation-play-state:paused}

/* ---- HOOD (office page) ------------------------------------------------------ */
/* After Stripe's homepage platform graphic, which plays ONCE on arrival and then
   offers replay. So: no infinite loops here. The page script adds .go when the
   graphic is on screen (and again on replay); everything below keys off it and
   fills both ways, so each part holds its first frame until its turn.
     0.0s   the browser rises in
     0.7s   Inbox banner, then its card at 1.1s, and the banner rings
     1.6s   Agents, card at 2.0s
     2.5s   Progress, card at 2.9s
     3.4s   Outputs and its rows, card at 3.8s
     4.8s   replay appears */
@keyframes cx-rise { from{opacity:0;transform:translateY(22px)} to{opacity:1;transform:none} }
@keyframes cx-fade { from{opacity:0} to{opacity:1} }
@keyframes cx-in-r { from{opacity:0;transform:translateX(28px) scale(.97)} to{opacity:1;transform:none} }
@keyframes cx-in-l { from{opacity:0;transform:translateX(-28px) scale(.97)} to{opacity:1;transform:none} }
@keyframes cx-ring { 0%{box-shadow:0 0 0 0 rgba(41,70,182,0)} 28%{box-shadow:0 0 0 5px rgba(41,70,182,.22)}
                     100%{box-shadow:0 0 0 0 rgba(41,70,182,0)} }
.cx.go .cx-win{animation:cx-rise .7s cubic-bezier(.2,.7,.2,1) both}
.cx.go .cx-hi {animation:cx-fade .45s ease .45s both}
.cx.go .cx-r1{animation:cx-rise .55s cubic-bezier(.2,.7,.2,1) .7s both,cx-ring 1.5s ease 1.15s both}
.cx.go .cx-r2{animation:cx-rise .55s cubic-bezier(.2,.7,.2,1) 1.6s both,cx-ring 1.5s ease 2.05s both}
.cx.go .cx-r3{animation:cx-rise .55s cubic-bezier(.2,.7,.2,1) 2.5s both,cx-ring 1.5s ease 2.95s both}
.cx.go .cx-r4{animation:cx-rise .55s cubic-bezier(.2,.7,.2,1) 3.4s both,cx-ring 1.5s ease 3.85s both}
.cx.go .cx-r4 .cx-tr{animation:cx-fade .35s ease 3.7s both}
.cx.go .cx-r4 .cx-tr:nth-child(3){animation-delay:3.8s}
.cx.go .cx-r4 .cx-tr:nth-child(4){animation-delay:3.9s}
.cx.go .cx-r4 .cx-tr:nth-child(5){animation-delay:4.0s}
.cx.go .cx-r4 .cx-tr:nth-child(6){animation-delay:4.1s}
.cx.go .cx-c1{animation:cx-in-r .55s cubic-bezier(.2,.8,.2,1) 1.1s both}
.cx.go .cx-c2{animation:cx-in-l .55s cubic-bezier(.2,.8,.2,1) 2.0s both}
.cx.go .cx-c3{animation:cx-in-r .55s cubic-bezier(.2,.8,.2,1) 2.9s both}
.cx.go .cx-c4{animation:cx-in-l .55s cubic-bezier(.2,.8,.2,1) 3.8s both}
.js .cx.go .cx-replay{animation:cx-fade .4s ease 4.8s both}

/* ---- SWITCH (pricing page) --------------------------------------------------- */
/* After Stripe's "Embed payments in your platform" card. 8s loop (sped up from 12s, 2026-09-22):
     0-4%    the workspace's approval slides into the card
    30-38%   Approve is pressed; the card turns to Approved
    42-55%   the Approved pill travels the dotted line to the Office
    53-64%   a ring flashes on the Office's mark
    55-60%   that workspace's row lights, its counts tick (3 to 2, 11 to 12)
    88-96%   the card slides out and the row settles, for the next pass
   Resting state (switch.css) is the finished frame. */
@keyframes sw-cc   { 0%{opacity:0;transform:translateX(-36px)} 4%,88%{opacity:1;transform:none}
                     94%,100%{opacity:0;transform:translateX(36px)} }
@keyframes sw-s1   { 0%,34%{opacity:1} 37%,100%{opacity:0} }
@keyframes sw-s2   { 0%,35%{opacity:0;transform:translateY(6px)} 38%,100%{opacity:1;transform:none} }
@keyframes sw-go   { 0%,30%{transform:none;background:#2946b6} 31.5%{transform:scale(.95);background:#1e39a3}
                     33%,100%{transform:none;background:#2946b6} }
@keyframes sw-pill { 0%,40%{opacity:0;transform:none} 43%,44%{opacity:1;transform:none}
                     53%{opacity:1;transform:translateX(90px)} 55.5%,100%{opacity:0;transform:translateX(90px)} }
@keyframes sw-ring { 0%,53%{opacity:0;transform:scale(.6)} 55%{opacity:1;transform:scale(1)} 64%,100%{opacity:0;transform:scale(1.5)} }
@keyframes sw-bg   { 0%,55%{opacity:0} 58%,88%{opacity:1} 93%,100%{opacity:0} }
@keyframes sw-o    { 0%,56%{opacity:1} 58.5%,93%{opacity:0} 96%,100%{opacity:1} }
@keyframes sw-x    { 0%,56%{opacity:0} 58.5%,93%{opacity:1} 96%,100%{opacity:0} }
@keyframes sw-dash-x { to{background-position:5px 0} }
@keyframes sw-dash-y { to{background-position:0 5px} }
.sw-cc  {animation:sw-cc 8s cubic-bezier(.2,.7,.2,1) both infinite}
.sw-s1  {animation:sw-s1 8s ease both infinite}
.sw-s2  {animation:sw-s2 8s ease both infinite}
.sw-go  {animation:sw-go 8s ease both infinite}
.sw-pill{animation:sw-pill 8s cubic-bezier(.45,0,.2,1) both infinite}
.sw-ring{animation:sw-ring 8s ease-out both infinite}
.sw-bg  {animation:sw-bg 8s ease both infinite}
.sw-o   {animation:sw-o 8s ease both infinite}
.sw-x   {animation:sw-x 8s ease both infinite}
.sw-lh  {animation:sw-dash-x .9s linear infinite}
.sw-lv  {animation:sw-dash-y .9s linear infinite}
.js .sw:not(.in) .sw-stage *{animation-play-state:paused}

/* ---- approval flow: Stripe's developer-systems mechanics ------------------- */
/* Read from Stripe's own CSS for this diagram: slots whose dashed border fades
   as a label pops in from .75 scale; PSP lines drawn in with stroke-dashoffset,
   each PSP popping in as its line lands; a turning gradient ring around the
   hub while it is busy. One shared 12s cycle, so the hub lights exactly when a
   tool connects. */
@keyframes dg-slot  { 0%,14%{border-color:rgba(255,255,255,.22)} 16%,44%{border-color:transparent}
                      46%,54%{border-color:rgba(255,255,255,.22)} 56%,84%{border-color:transparent}
                      86%,100%{border-color:rgba(255,255,255,.22)} }
@keyframes dg-fa    { 0%,14%{opacity:0;transform:scale(.75)} 17%,43%{opacity:1;transform:none} 46%,100%{opacity:0;transform:scale(.75)} }
@keyframes dg-fb    { 0%,54%{opacity:0;transform:scale(.75)} 57%,83%{opacity:1;transform:none} 86%,100%{opacity:0;transform:scale(.75)} }
@keyframes dg-glow  { 0%,15%{opacity:0} 18%,32%{opacity:1} 36%,55%{opacity:0} 58%,72%{opacity:1} 76%,100%{opacity:0} }
@keyframes dg-spin  { to{transform:rotate(360deg)} }
/* a line drawing itself: the stroke grows from the gate downward */
@keyframes dg-draw  { 0%,2%{clip-path:inset(0 0 100% 0)} 10%,92%{clip-path:inset(0 0 0 0)} 96%,100%{clip-path:inset(0 0 100% 0)} }
@keyframes dg-act   { 0%,9%{opacity:0;transform:scale(.75)} 13%,88%{opacity:1;transform:none} 92%,100%{opacity:0;transform:scale(.75)} }

.dg-group .dg-slot{animation:dg-slot 12s ease infinite}
.dg-fa{animation:dg-fa 12s cubic-bezier(.4,0,.2,1) infinite}
.dg-fb{animation:dg-fb 12s cubic-bezier(.4,0,.2,1) infinite}
.dg-glow{animation:dg-glow 12s ease infinite}
.dg-glow i{animation:dg-spin 1.5s linear infinite}
.dg-gate + .dg-stem{animation:dash-down 2.4s linear infinite,dg-draw 12s cubic-bezier(.66,0,.34,1) both infinite}
.dg-acts>.dg-box:not(.dg-ghost){animation:dg-act 12s cubic-bezier(.4,0,.2,1) both infinite}
.dg-acts>.dg-box:nth-child(3){animation-delay:.25s}
.dg-acts>.dg-box:nth-child(4){animation-delay:.5s}
.dg-acts>.dg-box:nth-child(5){animation-delay:.75s}

/* ---- SCALE (home page, under the flow diagram) ------------------------------ */
/* Stripe's wave is a three.js canvas. Here a ray burst breathes, and a brighter
   copy seen through a ring mask that grows from the origin sends light out along
   the rays, twice per 4s cycle. */

/* ---- HEALTH (office page): smarter work, fewer tokens, as a 14s loop --------
   (1s = 7.14%). Starts once on screen (.go from the page script), then repeats.
     0.6s   both charts draw; "before" figures ($0.52, 91%) on the cards
     1.6s   "Correction saved as a preference" where cost first dips
     3.2s   cost crosses the dashed median: "Under the median" (the first marker has gone)
     3.6s   the figures land: $0.43 down 18%, 96% up 3 pts
     4.6s   the notification: 21% under the median, efficiency bonus
     6.2s   the seat card; its progress fills, "Unlocked" lands at 8.2s
     12.8s  all fade and it starts over
   The resting frame in health.css is the end of the story. */
@keyframes mt-draw  { 0%,4%{clip-path:inset(0 100% 0 0)} 26%,92%{clip-path:inset(0 0 0 0)} 97%,100%{clip-path:inset(0 0 0 100%)} }
@keyframes mt-sa    { 0%,24%{opacity:1} 26%,100%{opacity:0} }
@keyframes mt-sb    { 0%,24%{opacity:0;transform:translateY(4px)} 26%,92%{opacity:1;transform:none} 96%,100%{opacity:0} }
@keyframes mt-late  { 0%,25%{opacity:0;transform:scale(.9)} 28%,92%{opacity:1;transform:none} 96%,100%{opacity:0} }
@keyframes mt-a1    { 0%,11%{opacity:0;transform:translateY(6px)} 13.5%,19.5%{opacity:1;transform:none} 21.5%,100%{opacity:0} }
@keyframes mt-a2    { 0%,22%{opacity:0;transform:translateY(6px)} 24.5%,92%{opacity:1;transform:none} 96%,100%{opacity:0} }
@keyframes mt-endin { 0%,24%{opacity:0} 27%,92%{opacity:1} 96%,100%{opacity:0} }
@keyframes mt-note  { 0%,32%{opacity:0;transform:translateY(16px)} 36%,91%{opacity:1;transform:none} 95%,100%{opacity:0;transform:translateY(-6px)} }
@keyframes mt-donut { 0%,34%{opacity:0;transform:rotate(-120deg) scale(.8)} 40%,100%{opacity:1;transform:none} }
@keyframes mt-seat  { 0%,43%{opacity:0;transform:translateY(16px)} 47%,91%{opacity:1;transform:none} 95%,100%{opacity:0;transform:translateY(-6px)} }
@keyframes mt-fill  { 0%,48%{width:64%} 57%,100%{width:100%} }
@keyframes mt-unl   { 0%,58%{opacity:0;transform:scale(.9)} 61%,100%{opacity:1;transform:none} }
@keyframes mt-prg   { 0%,58%{opacity:1} 60%,100%{opacity:0} }
@keyframes mt-dot   { 0%{box-shadow:0 0 0 0 rgba(41,70,182,.45)} 70%,100%{box-shadow:0 0 0 10px rgba(41,70,182,0)} }
@keyframes mt-drift { 0%,100%{transform:translate(0,0) scale(1)} 33%{transform:translate(-3%,2%) scale(1.04)} 66%{transform:translate(2%,-2%) scale(1.02)} }
.mt.go .mt-plot{animation:mt-draw 14s cubic-bezier(.45,0,.2,1) infinite both}
.mt.go .mt-cost{animation-delay:.2s}
.mt.go .mt-kpi .mt-sa{animation:mt-sa 14s ease infinite both}
.mt.go .mt-kpi .mt-sb{animation:mt-sb 14s ease infinite both}
.mt.go .mt-late{animation:mt-late 14s cubic-bezier(.2,.8,.2,1) infinite both}
.mt.go .mt-a1{animation:mt-a1 14s cubic-bezier(.2,.7,.2,1) infinite both}
.mt.go .mt-a2{animation:mt-a2 14s cubic-bezier(.2,.7,.2,1) infinite both}
.mt.go .mt-end{animation:mt-endin 14s ease infinite both,mt-dot 2s ease-out infinite}
.mt.go .mt-note{animation:mt-note 14s cubic-bezier(.2,.7,.2,1) infinite both}
.mt.go .mt-donut{animation:mt-donut 14s cubic-bezier(.2,.8,.2,1) infinite both}
.mt.go .mt-seat{animation:mt-seat 14s cubic-bezier(.2,.7,.2,1) infinite both}
.mt.go .mt-prog i{animation:mt-fill 14s cubic-bezier(.4,0,.2,1) infinite both}
.mt.go .mt-tile .mt-sb{animation:mt-unl 14s cubic-bezier(.2,.8,.2,1) infinite both}
.mt.go .mt-tile .mt-sa{animation:mt-prg 14s ease infinite both}
.mt-bg{animation:mt-drift 24s ease-in-out infinite}

/* ---- GALLERY (office page) --------------------------------------------------- */
/* After Webflow's #MadeinWebflow, which moves its planes with scroll. The track
   holds the cards twice, so sliding it half its width returns it exactly to the
   start: a seamless loop. It pauses under the pointer, so a hovered card holds. */
@keyframes gl-slide { to{transform:translateX(-50%)} }
.gl-track{animation:gl-slide 70s linear infinite}
.gl:hover .gl-track{animation-play-state:paused}

/* ---- ORBIT (company page) ---------------------------------------------------- */
/* After the Webflow Community hero, whose script does this every frame. Three
   keyframes, one 64s period:
     cg-spin  the space turns once around the vertical axis
     cg-face  each card turns back by the same amount, so it always faces you
     cg-far   blur and fade by depth. Written for a card at azimuth 0; each card's
              negative delay shifts it by its own azimuth, so it blurs exactly while
              it passes behind. The depth curve is Webflow's: sharp in the front
              quarter, up to 2.2px blur and 75% opacity at the back. */
@keyframes cg-spin { from{transform:rotateX(-10deg) rotateY(0deg)} to{transform:rotateX(-10deg) rotateY(360deg)} }
@keyframes cg-face { from{transform:rotateY(0deg) rotateX(10deg)} to{transform:rotateY(-360deg) rotateX(10deg)} }
@keyframes cg-far  { 0%{filter:blur(.73px);opacity:.92} 8.33%{filter:blur(1.47px);opacity:.83} 16.67%{filter:blur(2px);opacity:.77}
                      25%{filter:blur(2.2px);opacity:.75} 33.33%{filter:blur(2px);opacity:.77} 41.67%{filter:blur(1.47px);opacity:.83}
                      50%{filter:blur(.73px);opacity:.92} 58.33%,91.67%{filter:blur(0);opacity:1} 100%{filter:blur(.73px);opacity:.92} }
.cg-space{animation:cg-spin 64s linear infinite}
.cg-card{animation:cg-face 64s linear infinite,cg-far 64s linear infinite}
.cg-w1 .cg-card{animation-delay:0s,-64.0s}
.cg-w2 .cg-card{animation-delay:0s,-24.45s}
.cg-w3 .cg-card{animation-delay:0s,-48.89s}
.cg-w4 .cg-card{animation-delay:0s,-9.34s}
.cg-w5 .cg-card{animation-delay:0s,-33.78s}
.cg-w6 .cg-card{animation-delay:0s,-58.23s}
.cg-w7 .cg-card{animation-delay:0s,-18.67s}
.cg-w8 .cg-card{animation-delay:0s,-43.12s}

/* ---- ROADMAP (company page, business journey) --------------------------------- */
/* Progress climbs the journey on a 12s loop: each rule fills blue in 1s and the next
   stage lights with a small pulse, Startup through Industry Leader; it holds, then
   everything past stage 1 fades back and it starts again. Stage 1 stays lit (every
   workspace starts there), so reduced motion keeps that resting frame. One keyframe
   per dot and per rule, since they all reset together. */
@keyframes co-d2 { 0%,11.25%{border-color:#cdd7e3;background:#fff;box-shadow:0 0 0 0 rgba(41,70,182,0);transform:scale(1)} 11.67%{border-color:var(--blue);background:var(--blue);box-shadow:0 0 0 7px rgba(41,70,182,.18);transform:scale(1.2)} 14.58%,90%{border-color:var(--blue);background:var(--blue);box-shadow:0 0 0 4px rgba(41,70,182,.14);transform:scale(1)} 95%,100%{border-color:#cdd7e3;background:#fff;box-shadow:0 0 0 0 rgba(41,70,182,0);transform:scale(1)} }
@keyframes co-d3 { 0%,19.58%{border-color:#cdd7e3;background:#fff;box-shadow:0 0 0 0 rgba(41,70,182,0);transform:scale(1)} 20.0%{border-color:var(--blue);background:var(--blue);box-shadow:0 0 0 7px rgba(41,70,182,.18);transform:scale(1.2)} 22.92%,90%{border-color:var(--blue);background:var(--blue);box-shadow:0 0 0 4px rgba(41,70,182,.14);transform:scale(1)} 95%,100%{border-color:#cdd7e3;background:#fff;box-shadow:0 0 0 0 rgba(41,70,182,0);transform:scale(1)} }
@keyframes co-d4 { 0%,27.92%{border-color:#cdd7e3;background:#fff;box-shadow:0 0 0 0 rgba(41,70,182,0);transform:scale(1)} 28.33%{border-color:var(--blue);background:var(--blue);box-shadow:0 0 0 7px rgba(41,70,182,.18);transform:scale(1.2)} 31.25%,90%{border-color:var(--blue);background:var(--blue);box-shadow:0 0 0 4px rgba(41,70,182,.14);transform:scale(1)} 95%,100%{border-color:#cdd7e3;background:#fff;box-shadow:0 0 0 0 rgba(41,70,182,0);transform:scale(1)} }
@keyframes co-d5 { 0%,36.25%{border-color:#cdd7e3;background:#fff;box-shadow:0 0 0 0 rgba(41,70,182,0);transform:scale(1)} 36.67%{border-color:var(--blue);background:var(--blue);box-shadow:0 0 0 7px rgba(41,70,182,.18);transform:scale(1.2)} 39.58%,90%{border-color:var(--blue);background:var(--blue);box-shadow:0 0 0 4px rgba(41,70,182,.14);transform:scale(1)} 95%,100%{border-color:#cdd7e3;background:#fff;box-shadow:0 0 0 0 rgba(41,70,182,0);transform:scale(1)} }
@keyframes co-d6 { 0%,44.58%{border-color:#cdd7e3;background:#fff;box-shadow:0 0 0 0 rgba(41,70,182,0);transform:scale(1)} 45.0%{border-color:var(--blue);background:var(--blue);box-shadow:0 0 0 7px rgba(41,70,182,.18);transform:scale(1.2)} 47.92%,90%{border-color:var(--blue);background:var(--blue);box-shadow:0 0 0 4px rgba(41,70,182,.14);transform:scale(1)} 95%,100%{border-color:#cdd7e3;background:#fff;box-shadow:0 0 0 0 rgba(41,70,182,0);transform:scale(1)} }
@keyframes co-d7 { 0%,52.92%{border-color:#cdd7e3;background:#fff;box-shadow:0 0 0 0 rgba(41,70,182,0);transform:scale(1)} 53.33%{border-color:var(--blue);background:var(--blue);box-shadow:0 0 0 7px rgba(41,70,182,.18);transform:scale(1.2)} 56.25%,90%{border-color:var(--blue);background:var(--blue);box-shadow:0 0 0 4px rgba(41,70,182,.14);transform:scale(1)} 95%,100%{border-color:#cdd7e3;background:#fff;box-shadow:0 0 0 0 rgba(41,70,182,0);transform:scale(1)} }
@keyframes co-d8 { 0%,61.25%{border-color:#cdd7e3;background:#fff;box-shadow:0 0 0 0 rgba(41,70,182,0);transform:scale(1)} 61.67%{border-color:var(--blue);background:var(--blue);box-shadow:0 0 0 7px rgba(41,70,182,.18);transform:scale(1.2)} 64.58%,90%{border-color:var(--blue);background:var(--blue);box-shadow:0 0 0 4px rgba(41,70,182,.14);transform:scale(1)} 95%,100%{border-color:#cdd7e3;background:#fff;box-shadow:0 0 0 0 rgba(41,70,182,0);transform:scale(1)} }
@keyframes co-l1 { 0%,3.33%{background-size:2px 0} 11.67%,90%{background-size:2px 100%} 95%,100%{background-size:2px 0} }
@keyframes co-l2 { 0%,11.67%{background-size:2px 0} 20.0%,90%{background-size:2px 100%} 95%,100%{background-size:2px 0} }
@keyframes co-l3 { 0%,20.0%{background-size:2px 0} 28.33%,90%{background-size:2px 100%} 95%,100%{background-size:2px 0} }
@keyframes co-l4 { 0%,28.33%{background-size:2px 0} 36.67%,90%{background-size:2px 100%} 95%,100%{background-size:2px 0} }
@keyframes co-l5 { 0%,36.67%{background-size:2px 0} 45.0%,90%{background-size:2px 100%} 95%,100%{background-size:2px 0} }
@keyframes co-l6 { 0%,45.0%{background-size:2px 0} 53.33%,90%{background-size:2px 100%} 95%,100%{background-size:2px 0} }
@keyframes co-l7 { 0%,53.33%{background-size:2px 0} 61.67%,90%{background-size:2px 100%} 95%,100%{background-size:2px 0} }
.co-st:nth-child(2):after{animation:co-d2 12s ease-out infinite}
.co-st:nth-child(3):after{animation:co-d3 12s ease-out infinite}
.co-st:nth-child(4):after{animation:co-d4 12s ease-out infinite}
.co-st:nth-child(5):after{animation:co-d5 12s ease-out infinite}
.co-st:nth-child(6):after{animation:co-d6 12s ease-out infinite}
.co-st:nth-child(7):after{animation:co-d7 12s ease-out infinite}
.co-st:nth-child(8):after{animation:co-d8 12s ease-out infinite}
.co-st:nth-child(1):before{animation:co-l1 12s linear infinite}
.co-st:nth-child(2):before{animation:co-l2 12s linear infinite}
.co-st:nth-child(3):before{animation:co-l3 12s linear infinite}
.co-st:nth-child(4):before{animation:co-l4 12s linear infinite}
.co-st:nth-child(5):before{animation:co-l5 12s linear infinite}
.co-st:nth-child(6):before{animation:co-l6 12s linear infinite}
.co-st:nth-child(7):before{animation:co-l7 12s linear infinite}

/* ---- SERVICES HERO (services page) -------------------------------------------- */
/* The line-art board breathes: the seats drift up and down on their own rhythms and
   the two chips bob, so the hero is alive without anything moving far. Resting
   frame (reduced motion) is the drawing as laid out. */
@keyframes sv-float { 0%,100%{transform:translateY(0)} 50%{transform:translateY(-8px)} }
@keyframes sv-bob   { 0%,100%{transform:translateY(0)} 50%{transform:translateY(-5px)} }
.sv-seat{animation:sv-float 6s ease-in-out infinite}
.sv-s2{animation-duration:7s;animation-delay:-2s}
.sv-s3{animation-duration:5.5s;animation-delay:-4s}
.sv-s4{animation-duration:6.5s;animation-delay:-1s}
.sv-s5{animation-duration:7.5s;animation-delay:-3s}
.sv-chip{animation:sv-bob 5s ease-in-out infinite}
.sv-c2{animation-delay:-2.5s}

/* ---- RESEARCH HERO (research page) -------------------------------------------- */
/* The featured slides are alive: their cards float gently and the Approve button
   breathes, the moment the essay is about. Resting frame (reduced
   motion) is the card as laid out. */
@keyframes rs-float { 0%,100%{transform:translateY(0)} 50%{transform:translateY(-8px)} }
@keyframes rs-glow  { 0%,100%{box-shadow:0 0 0 0 rgba(41,70,182,0)} 50%{box-shadow:0 0 0 6px rgba(41,70,182,.22)} }
.rz-slide .rs-card{animation:rs-float 6s ease-in-out infinite}
.rz-slide .rs-yes{animation:rs-glow 2.4s ease-in-out infinite}
/* research articles: the figure under the title floats the same way */
.ar-fig .rs-fig>*{animation:rs-float 6s ease-in-out infinite}
.ar-fig .rs-yes{animation:rs-glow 2.4s ease-in-out infinite}

/* ---- PREFS (home page) -------------------------------------------------------- */
/* Zip's Lottie timeline, beat for beat, on a 7s loop (sped up from 8s, 2026-09-22;
   the percentages below are unchanged, so every beat simply arrives sooner):
     0.2s  greeting            1.1s  Alex's request, the draft attached
     2.6s  "Reading the draft", the outline comes in line by line
     3.9s  the scan sweeps     4.4s  one line lifts and glows
     4.5s  "Checking it against your preferences"
     5.1s  the seat appears    5.6s  the conversation clears
     6.0s  the reply           7.0s  Option A, then B, then the accept buttons
   then everything fades and it starts over. */
@keyframes zp-greet { 0%,2.5%{opacity:0;transform:translateY(8px)} 5%,61%{opacity:1;transform:none} 65%,100%{opacity:0;transform:translateY(-16px)} }
@keyframes zp-ask   { 0%,12%{opacity:0;transform:translateY(8px)} 15%,61%{opacity:1;transform:none} 65%,100%{opacity:0;transform:translateY(-16px)} }
@keyframes zp-s1    { 0%,28%{opacity:0} 30%,47%{opacity:1} 49%,100%{opacity:0} }
@keyframes zp-s2    { 0%,48%{opacity:0} 50%,60%{opacity:1} 63%,100%{opacity:0} }
@keyframes zp-doc   { 0%,28%{opacity:0;transform:translateX(-10px)} 32%,95%{opacity:1;transform:none} 99%,100%{opacity:0} }
@keyframes zp-scan  { 0%,41%{opacity:0;transform:translateY(-40px)} 43%{opacity:1;transform:translateY(-40px)}
                      60%{opacity:1;transform:translateY(330px)} 62%,100%{opacity:0;transform:translateY(330px)} }
@keyframes zp-hi    { 0%,47%{opacity:0;transform:scale(.96)} 50%,95%{opacity:1;transform:none} 99%,100%{opacity:0} }
@keyframes zp-who   { 0%,54%{opacity:0;transform:scale(.8)} 57%,95%{opacity:1;transform:none} 99%,100%{opacity:0} }
@keyframes zp-reply { 0%,65%{opacity:0;transform:translateY(12px)} 68%,95%{opacity:1;transform:none} 99%,100%{opacity:0} }
@keyframes zp-opts  { 0%,74%{opacity:0;transform:translateY(12px)} 77%,95%{opacity:1;transform:none} 99%,100%{opacity:0} }
@keyframes zp-part  { 0%,76%{opacity:0} 79%,95%{opacity:1} 99%,100%{opacity:0} }
.zp-greet{animation:zp-greet 7s ease both infinite}
.zp-me{animation:zp-ask 7s ease both infinite}
.zp-s1{animation:zp-s1 7s ease both infinite}
.zp-s2{animation:zp-s2 7s ease both infinite}
.zp-dh,.zp-l{animation:zp-doc 7s ease both infinite}
.zp-d2{animation-delay:0.09s} .zp-d3{animation-delay:0.20s}
.zp-scan{animation:zp-scan 7s cubic-bezier(.45,0,.55,1) both infinite}
.zp-hi{animation:zp-hi 7s ease both infinite}
.zp-who{animation:zp-who 7s cubic-bezier(.2,.9,.3,1.2) both infinite}
.zp-reply{animation:zp-reply 7s ease both infinite}
.zp-opts{animation:zp-opts 7s ease both infinite}
.zp-oa,.zp-ob,.zp-acts{animation:zp-part 7s ease both infinite}
.zp-ob{animation-delay:0.10s} .zp-acts{animation-delay:0.20s}
.js .zp:not(.in) .zp-stage *{animation-play-state:paused}

/* ---- REQUEST (contact page) --------------------------------------------------- */
/* Zip's 34s procurement video, condensed to a 16s loop (1s = 6.25%):
     A  0.3-3.7s  the ask is typed
     B  3.8-9.4s  the seat's questions; answers land, Submit
     C  9.5-15s   the workflow: steps complete in turn; your approval waits on
                  "Needs you", then goes through; then Send
     D  14-15.5s  Request complete
   Items inside a scene only ever turn ON; the scene's own fade hides them again,
   so their loops can wrap freely while the scene is invisible. */
@keyframes rq-a     { 0%{opacity:0} 2%,21%{opacity:1} 23.5%,100%{opacity:0} }
@keyframes rq-type  { 0%,6%{max-width:0;animation-timing-function:steps(44,end)} 19%,100%{max-width:430px} }
@keyframes rq-blink { 50%{opacity:0} }
@keyframes rq-b     { 0%,22.5%{opacity:0} 25%,56.5%{opacity:1} 59%,100%{opacity:0} }
@keyframes rq-rise  { 0%,23%{opacity:0;transform:translateY(10px)} 25.5%,100%{opacity:1;transform:none} }
@keyframes rq-pick  { 0%,34.4%{background:#fff;border-color:#e4ecf5;color:#040d1c} 35.6%,100%{background:#2946b6;border-color:#2946b6;color:#fff} }
@keyframes rq-on    { 0%,43%{opacity:0} 45%,100%{opacity:1} }
@keyframes rq-fill  { 0%,48%{opacity:0} 50%,100%{opacity:1} }
@keyframes rq-ph    { 0%,48%{opacity:1} 50%,100%{opacity:0} }
@keyframes rq-press { 0%,53%{transform:none;background:#2946b6} 54.5%{transform:scale(.94);background:#1e39a3} 56%,100%{transform:none;background:#2946b6} }
@keyframes rq-c     { 0%,58%{opacity:0} 60.5%,92%{opacity:1} 94.5%,100%{opacity:0} }
@keyframes rq-card  { 0%,59%{opacity:0;transform:translateY(12px)} 62%,100%{opacity:1;transform:none} }
@keyframes rq-out   { 0%,64%{opacity:1} 65.5%,100%{opacity:0} }
@keyframes rq-in    { 0%,64%{opacity:0} 65.5%,100%{opacity:1} }
@keyframes rq-need  { 0%,76.5%{opacity:0} 78%,81.5%{opacity:1} 83%,100%{opacity:0} }
@keyframes rq-wait  { 0%,76.5%{border-color:#e4ecf5;box-shadow:none} 78%,81.5%{border-color:#f0c77a;box-shadow:0 0 0 3px rgba(217,119,6,.14)}
                      83%,100%{border-color:#e4ecf5;box-shadow:none} }
@keyframes rq-d     { 0%,88%{opacity:0;transform:scale(.97)} 90%,97%{opacity:1;transform:none} 99.5%,100%{opacity:0} }
.rq-a{animation:rq-a 16s ease both infinite}
.rq-type{animation:rq-type 16s both infinite}
.rq-caret{animation:rq-blink 1s steps(1) infinite}
.rq-b{animation:rq-b 16s ease both infinite}
.rq-me{animation:rq-rise 16s ease both infinite}
.rq-say{animation:rq-rise 16s ease 1s both infinite}
.rq-form{animation:rq-rise 16s ease 1.5s both infinite}
.rq-k1{animation:rq-pick 16s ease both infinite}
.rq-k2{animation:rq-pick 16s ease .8s both infinite}
.rq-file{animation:rq-on 16s ease both infinite}
.rq-fill{animation:rq-fill 16s ease both infinite}
.rq-ph{animation:rq-ph 16s ease both infinite}
.rq-submit{animation:rq-press 16s ease both infinite}
.rq-c{animation:rq-c 16s ease both infinite}
.rq-step{animation:rq-card 16s cubic-bezier(.2,.7,.2,1) both infinite}
.rq-t2{animation-delay:.08s} .rq-t3{animation-delay:.16s} .rq-t5{animation-delay:.32s}
.rq-t4{animation:rq-card 16s cubic-bezier(.2,.7,.2,1) .24s both infinite,rq-wait 16s ease both infinite}
.rq-ready{animation:rq-out 16s ease both infinite}
.rq-ok{animation:rq-in 16s ease both infinite}
.rq-need{animation:rq-need 16s ease both infinite}
.rq-t2 .rq-p{animation-delay:.8s} .rq-t3 .rq-p{animation-delay:1.6s} .rq-t5 .rq-p{animation-delay:3.4s}
.rq-t4 .rq-ready{animation-delay:2s} .rq-t4 .rq-ok{animation-delay:2.8s} .rq-t4 .rq-need{animation-delay:0s}
.rq-ev{animation:rq-in 16s ease both infinite}
.rq-e2{animation-delay:.8s} .rq-e3{animation-delay:1.6s} .rq-e4{animation-delay:2s} .rq-e5{animation-delay:2.8s} .rq-e6{animation-delay:3.4s}
.rq-d{animation:rq-d 16s ease both infinite}
.js .rq:not(.in) .rq-stage *{animation-play-state:paused}

/* ---- FILL (office page) -------------------------------------------------------- */
/* Zip's accounts-payable clip as a 16s loop (1s = 6.25%). The report stays on
   screen throughout; there is no hand-off screen:
     0.6s   "Filling in the report" over the source
     3.5s   the fields fill, then the line items, each marked as the seat's
     7.0s   one account is corrected; the preference toast confirms it
     10.5s  "Report ready for your approval" drops in under Approve
     12.2s  Approve is pressed and the card closes
     14.6s  the fields fall back to placeholders and the next report begins
   Between them: the seat's reading bubble (0.3s), the budget meter filling (3.8s),
   "3 checks passed" (4.2s), a cursor that clicks the account (7.0s) and then
   Approve (12.3s), the Draft tag turning Approved and a logged-in-Activity note.
   The values carry staggered delays (up to 1.6s), so each one empties and refills
   a little after the one before it. */
@keyframes iv-load  { 0%,3%{opacity:0} 5%,19%{opacity:1} 22%,100%{opacity:0} }
@keyframes iv-page  { 0%,19%{opacity:.4;filter:blur(1.5px)} 23%,90%{opacity:1;filter:none} 94%,100%{opacity:.4;filter:blur(1.5px)} }
@keyframes iv-sk    { 0%,21%{opacity:1} 23%,90%{opacity:0} 93%,100%{opacity:1} }
@keyframes iv-val   { 0%,21%{opacity:0;transform:translateY(3px)} 23%,90%{opacity:1;transform:none} 93%,100%{opacity:0;transform:translateY(3px)} }
@keyframes iv-shim  { to{background-position:-200% 0} }
@keyframes iv-edit  { 0%,43%{background:transparent;box-shadow:none} 45%,58%{background:#eceffb;box-shadow:0 0 0 2px #2946b6}
                       61%,100%{background:transparent;box-shadow:none} }
@keyframes iv-toast { 0%,44%{opacity:0;transform:translateY(10px)} 47%,62%{opacity:1;transform:none} 65%,100%{opacity:0} }
@keyframes iv-press { 0%,75.5%{transform:none} 77%{transform:scale(.94)} 78.5%,100%{transform:none} }
@keyframes iv-who   { 0%,1.5%{opacity:0;transform:translateY(8px)} 4%,19%{opacity:1;transform:none} 21.5%,100%{opacity:0;transform:translateY(-4px)} }
@keyframes iv-meter { 0%,23%{transform:scaleX(0)} 30%,92%{transform:scaleX(1)} 96%,100%{transform:scaleX(0)} }
@keyframes iv-chk   { 0%,25%{opacity:0;transform:translateY(10px) scale(.98)} 27.5%,40%{opacity:1;transform:none} 42.5%,100%{opacity:0} }
@keyframes iv-ck    { 0%,26.5%{opacity:0;transform:translateX(-4px)} 28.5%,100%{opacity:1;transform:none} }
@keyframes iv-cur   { 0%,38%{opacity:0;transform:translate(120px,110px)} 40%{opacity:1;transform:translate(90px,80px)}
                      43.5%{opacity:1;transform:none} 44.5%{transform:scale(.82)} 45.5%,68%{opacity:1;transform:none}
                      75.5%{opacity:1;transform:translate(279px,-424px)} 77%{transform:translate(279px,-424px) scale(.82)}
                      78.5%{opacity:1;transform:translate(279px,-424px)} 82%,100%{opacity:0;transform:translate(300px,-400px)} }
@keyframes iv-appr  { 0%,78%{opacity:0;transform:scale(.9)} 80%,92%{opacity:1;transform:none} 94%,100%{opacity:0} }
@keyframes iv-sent  { 0%,79%{opacity:0;transform:translateY(10px)} 81.5%,91%{opacity:1;transform:none} 93.5%,100%{opacity:0} }
@keyframes iv-ready { 0%,64%{opacity:0;transform:translateY(-8px)} 66.5%,77%{opacity:1;transform:none} 79.5%,100%{opacity:0;transform:translateY(-4px)} }
.iv-load{animation:iv-load 16s ease both infinite}
.iv-page{animation:iv-page 16s ease both infinite}
.iv-sk{animation:iv-sk 16s ease both infinite,iv-shim 1.4s linear infinite}
.iv-val{animation:iv-val 16s ease both infinite}
.iv-f1 .iv-sk,.iv-f1 .iv-val{animation-delay:0s,0s}
.iv-f2 .iv-sk,.iv-f2 .iv-val{animation-delay:0.2s,0s}
.iv-f3 .iv-sk,.iv-f3 .iv-val{animation-delay:0.4s,0s}
.iv-f4 .iv-sk,.iv-f4 .iv-val{animation-delay:0.6s,0s}
.iv-f5 .iv-sk,.iv-f5 .iv-val{animation-delay:0.8s,0s}
.iv-f6 .iv-sk,.iv-f6 .iv-val{animation-delay:1.0s,0s}
.iv-r1 .iv-sk,.iv-r1 .iv-val{animation-delay:0.8s,0s}
.iv-r2 .iv-sk,.iv-r2 .iv-val{animation-delay:1.0s,0s}
.iv-r3 .iv-sk,.iv-r3 .iv-val{animation-delay:1.2s,0s}
.iv-r4 .iv-sk,.iv-r4 .iv-val{animation-delay:1.4s,0s}
.iv-r5 .iv-sk,.iv-r5 .iv-val{animation-delay:1.6s,0s}
.iv-edit{animation:iv-edit 16s ease both infinite}
.iv-toast{animation:iv-toast 16s cubic-bezier(.2,.7,.2,1) both infinite}
.iv-yes{animation:iv-press 16s ease both infinite}
.iv-ready{animation:iv-ready 16s cubic-bezier(.2,.7,.2,1) both infinite}
.iv-who{animation:iv-who 16s cubic-bezier(.2,.7,.2,1) both infinite}
.iv-bar i{transform-origin:left center;animation:iv-meter 16s cubic-bezier(.3,.7,.2,1) both infinite}
.iv-chk{animation:iv-chk 16s cubic-bezier(.2,.7,.2,1) both infinite}
.iv-ck{animation:iv-ck 16s ease both infinite}
.iv-k2{animation-delay:.3s} .iv-k3{animation-delay:.6s}
.iv-cur{animation:iv-cur 16s cubic-bezier(.45,0,.25,1) both infinite}
.iv-appr{animation:iv-appr 16s ease both infinite}
.iv-sent{animation:iv-sent 16s cubic-bezier(.2,.7,.2,1) both infinite}
.js .iv:not(.in) .iv-stage *{animation-play-state:paused}

/* ---- ROTATE (home page) ------------------------------------------------------- */
/* After Clay's rotator, which cycles its tabs with a script. One 25s timeline, a
   5s window per department (1s = 4%). Every keyframe below is written for the
   FIRST window (0-20%); each department's elements carry a negative delay that
   shifts them onto their own window, so the whole rotation is five copies of one
   choreography:
     0.1s  the card rises        0.8s  the popover
     2.0s  step one ticks        2.8s  step two
     3.2s  the loading cell fills   3.9s  step three
     2.8s  the dotted line draws up, then across; 3.4s the pill */
@keyframes cl-card { 0%{opacity:0;transform:translateY(12px)} 2%,18%{opacity:1;transform:none} 20%,100%{opacity:0;transform:none} }
@keyframes cl-fade { 0%{opacity:0} 2%,18%{opacity:1} 20%,100%{opacity:0} }
@keyframes cl-tab  { 0%,18.5%{background:#dbe8fb;color:#02254f;box-shadow:0 0 0 1px #c5dbf6 inset}
                     20%,98.5%{background:#f3f5f8;color:#627187;box-shadow:0 0 0 1px transparent inset}
                     100%{background:#dbe8fb;color:#02254f;box-shadow:0 0 0 1px #c5dbf6 inset} }
@keyframes cl-pop  { 0%,3%{opacity:0;transform:translateY(12px)} 6%,100%{opacity:1;transform:none} }
@keyframes cl-sp1  { 0%,7.5%{opacity:1} 8.5%,100%{opacity:0} }
@keyframes cl-ok1  { 0%,7.5%{opacity:0;transform:scale(.5)} 9%,100%{opacity:1;transform:none} }
@keyframes cl-sp2  { 0%,10.5%{opacity:1} 11.5%,100%{opacity:0} }
@keyframes cl-ok2  { 0%,10.5%{opacity:0;transform:scale(.5)} 12%,100%{opacity:1;transform:none} }
@keyframes cl-sp3  { 0%,15%{opacity:1} 16%,100%{opacity:0} }
@keyframes cl-ok3  { 0%,15%{opacity:0;transform:scale(.5)} 16.5%,100%{opacity:1;transform:none} }
@keyframes cl-load { 0%,12.5%{opacity:1} 13.5%,100%{opacity:0} }
@keyframes cl-got  { 0%,12.5%{opacity:0} 14%,100%{opacity:1} }
@keyframes cl-wv   { 0%,10.5%{clip-path:inset(100% 0 0 0)} 12.5%,100%{clip-path:inset(0 0 0 0)} }
@keyframes cl-wh   { 0%,12.5%{clip-path:inset(0 100% 0 0)} 13.5%,100%{clip-path:inset(0 0 0 0)} }
@keyframes cl-pill { 0%,13%{opacity:0;transform:scale(.92)} 14.5%,100%{opacity:1;transform:none} }
@keyframes cl-rot  { to{transform:rotate(360deg)} }
.cl-card{animation:cl-card 25s cubic-bezier(.2,.7,.2,1) both infinite}
.cl-d,.cl-band{animation:cl-fade 25s ease both infinite}
.cl-tab{animation:cl-tab 25s ease both infinite}
.cl-pop{animation:cl-pop 25s cubic-bezier(.2,.7,.2,1) both infinite}
.cl-s1 .cl-spin{animation:cl-sp1 25s ease both infinite,cl-rot .9s linear infinite}
.cl-s1 .cl-ok{animation:cl-ok1 25s cubic-bezier(.2,.9,.3,1.3) both infinite}
.cl-s2 .cl-spin{animation:cl-sp2 25s ease both infinite,cl-rot .9s linear infinite}
.cl-s2 .cl-ok{animation:cl-ok2 25s cubic-bezier(.2,.9,.3,1.3) both infinite}
.cl-s3 .cl-spin{animation:cl-sp3 25s ease both infinite,cl-rot .9s linear infinite}
.cl-s3 .cl-ok{animation:cl-ok3 25s cubic-bezier(.2,.9,.3,1.3) both infinite}
.cl-load{animation:cl-load 25s ease both infinite}
.cl-load .cl-spin{animation:cl-rot .9s linear infinite}
.cl-got{animation:cl-got 25s ease both infinite}
.cl-wv{animation:cl-wv 25s ease both infinite}
.cl-wh{animation:cl-wh 25s ease both infinite}
.cl-pill{animation:cl-pill 25s cubic-bezier(.2,.9,.3,1.2) both infinite}
/* each department onto its own 5s window: delays of 0, -20, -15, -10, -5 seconds */
/* (0,2,0)+ and declared last, or the step rules above (.cl-s1 .cl-spin, 0,2,0) keep
   their own zero delay and every card ticks on the first card's clock */
.cl .cl-c1,.cl .cl-c1 *{animation-delay:-20s} .cl .cl-c2,.cl .cl-c2 *{animation-delay:-15s}
.cl .cl-c3,.cl .cl-c3 *{animation-delay:-10s} .cl .cl-c4,.cl .cl-c4 *{animation-delay:-5s}
.js .cl:not(.in) .cl-stage *{animation-play-state:paused}

/* ---- bento panels: the contents arrive in order ------------------------- */
/* :target adds the rule, so the animation restarts every time a panel opens.
   Re-opening the same panel replays it, which a transition cannot do. */
@keyframes panel-rise{
  from {opacity:0; transform:translateY(12px)}
  to   {opacity:1; transform:none}
}
.panel:target .panel-hd>div:first-child{animation:panel-rise .40s ease .04s both}
.panel:target .panel-list div{animation:panel-rise .34s ease both}
.panel:target .panel-list div:nth-child(1){animation-delay:.10s}
.panel:target .panel-list div:nth-child(2){animation-delay:.16s}
.panel:target .panel-list div:nth-child(3){animation-delay:.22s}
.panel:target .panel-list div:nth-child(4){animation-delay:.28s}
.panel:target .panel-list div:nth-child(5){animation-delay:.34s}
.panel:target .panel-list div:nth-child(6){animation-delay:.40s}
.panel:target .panel-body{animation:panel-rise .44s ease .24s both}

/* ---- motion is always optional ----------------------------------------- */
/* ---- ONE STACK (home page, css/stack.css) ------------------------------------
   The pale slabs rise into place from the bottom when the section arrives (.in).
   Then a 19.8s loop, 2.2s per capability: each row is lit for its turn, its icon shows
   on the royal slab, and the slab settles down into view at each turn. Negative delays
   start every row mid-loop, so row 1 is lit the moment the loop begins. */
@keyframes stk-rise { 0%{opacity:0;transform:translateY(14px)} 100%{opacity:.95;transform:none} }
@keyframes stk-lift { 0%{opacity:0;transform:translateY(-10%)} 16%,84%{opacity:1;transform:none} 100%{opacity:0;transform:translateY(6%)} }
@keyframes stk-glow { 0%,100%{opacity:.35} 16%,84%{opacity:1} }
@keyframes stk-row  { 0%,10.4%{background-color:#eef2fc;box-shadow:inset 0 0 0 1px rgba(41,70,182,.12);color:#2946b6}
                      11.1%,100%{background-color:rgba(238,242,252,0);box-shadow:inset 0 0 0 1px rgba(41,70,182,0);color:#02254f} }
@keyframes stk-ico  { 0%,11%{opacity:1} 11.11%,100%{opacity:0} }
.js .stk:not(.in) .stk-g{opacity:0}
.js .stk.in .stk-g{animation:stk-rise .7s cubic-bezier(.2,.7,.2,1) both}
.js .stk.in .stk-g1{animation-delay:0s}   .js .stk.in .stk-g2{animation-delay:.08s} .js .stk.in .stk-g3{animation-delay:.16s}
.js .stk.in .stk-g4{animation-delay:.24s} .js .stk.in .stk-g5{animation-delay:.32s} .js .stk.in .stk-g6{animation-delay:.4s}
.js .stk.in .stk-g7{animation-delay:.48s} .js .stk.in .stk-g8{animation-delay:.56s}
.js .stk.in .stk-lift{animation:stk-lift 2.2s cubic-bezier(.3,.7,.3,1) .7s infinite both}
.js .stk.in .stk-glow{animation:stk-glow 2.2s ease-in-out .7s infinite both}
.js .stk.in .stk-row{animation:stk-row 19.8s linear infinite}
.js .stk.in .stk-i{animation:stk-ico 19.8s linear infinite}
.js .stk.in .stk-r1,.js .stk.in .stk-i1{animation-delay:-19.1s}
.js .stk.in .stk-r2,.js .stk.in .stk-i2{animation-delay:-16.9s}
.js .stk.in .stk-r3,.js .stk.in .stk-i3{animation-delay:-14.7s}
.js .stk.in .stk-r4,.js .stk.in .stk-i4{animation-delay:-12.5s}
.js .stk.in .stk-r5,.js .stk.in .stk-i5{animation-delay:-10.3s}
.js .stk.in .stk-r6,.js .stk.in .stk-i6{animation-delay:-8.1s}
.js .stk.in .stk-r7,.js .stk.in .stk-i7{animation-delay:-5.9s}
.js .stk.in .stk-r8,.js .stk.in .stk-i8{animation-delay:-3.7s}
.js .stk.in .stk-r9,.js .stk.in .stk-i9{animation-delay:-1.5s}

@media (prefers-reduced-motion:reduce){
  .br-up,.br-dn,.br-c,.br-h,.dg-stem,.dg-wire,.dg-gate,.dg-ghost,.dg-add,.dg-mid::before,.dg-mid::after{animation:none}
  .fx-f,.fx-b,.rib-l,.rib-r,.rib-w,.rib-lit{animation:none}
  .dg-group .dg-slot,.dg-fa,.dg-fb,.dg-glow,.dg-glow i,.dg-gate + .dg-stem,.dg-acts>.dg-box:not(.dg-ghost){animation:none}
  .orb-1,.orb-2,.orb-3,.orb-h,.glb-lit,.glb-haze{animation:none}
  .pt-stage *{animation:none}
  .gt-stage *{animation:none}
  /* as specific as the rules they cancel, and later, or they lose */
  .cx.go .cx-stage *,.cx.go .cx-r4 .cx-tr,.js .cx.go .cx-replay{animation:none}
  .pt-q1 .pt-q{animation:none}
  .sw-stage *{animation:none}
  .gl-track{animation:none}
  .rz-slide .rs-card,.rz-slide .rs-yes,.ar-fig .rs-fig>*,.ar-fig .rs-yes{animation:none}
  .sv-seat,.sv-chip{animation:none}
  .co-st:nth-child(n):before,.co-st:nth-child(n):after{animation:none}
  .iv-bar i{animation:none}
  .cg-space,.cg-card,.cg-w .cg-card{animation:none}
  .zp-stage *{animation:none}
  .hero .shot,.shot-sec .shot,.js .hs-stage *{animation:none}
  .tr.go .tr-p,.tr.go .tr-c,.tr.go .tr-t,.tr.go .tr-sa,.tr.go .tr-sb,.tr.go .tr-toast,.tr.go .tr-grow{animation:none}
  .iv-stage *,.iv-stage .iv-sk,.iv-stage .iv-val{animation:none}
  .cl-stage *,.cl-stage .cl-st i,.cl-stage .cl-load .cl-spin{animation:none}
  .rq-stage *,.rq-t4,.rq-t4 .rq-p,.rq-e2,.rq-e3,.rq-e4,.rq-e5,.rq-e6,.rq-t2 .rq-p,.rq-t3 .rq-p,.rq-t5 .rq-p{animation:none}
  .cn-lava,.cn-pt{animation:none}
  .mt.go .mt-plot,.mt.go .mt-seat,.mt.go .mt-prog i,.mt.go .mt-note,.mt.go .mt-donut,.mt.go .mt-end,.mt-end,.mt-bg,.mt.go .mt-sa,.mt.go .mt-sb,.mt.go .mt-late,.mt.go .mt-a1,.mt.go .mt-a2,.mt.go .mt-kpi .mt-sa,.mt.go .mt-kpi .mt-sb,.mt.go .mt-tile .mt-sa,.mt.go .mt-tile .mt-sb{animation:none}
  .stk-g,.stk-lift,.stk-glow,.stk-row,.stk-i{animation:none}
  .panel:target .panel-hd>div:first-child,
  .panel:target .panel-list div,
  .panel:target .panel-body{animation:none}
}
