/* SERVICE HERO DRAWINGS (2026-09-25): AI Jumpstart, AI Deployment Studio, Diligence Jumpstart.
   The SVGs are generated by scripts/art/service_heroes.py; this sheet sizes them and moves them.
   Self-contained on purpose (diligence.html does not load site.css).

   How the motion is built, for all three:
   - Every base style is the finished frame. All motion sits inside prefers-reduced-motion:
     no-preference, so reduced motion shows the complete picture. The only things hidden at rest
     are transient marks that exist only while moving (the Jumpstart rider, ping and ripple, the
     Diligence riders).
   - Each drawing plays a short intro once (about 3s, expo-out, staggered in the order the story
     reads), then settles into ONE loop clock per drawing, so every moving part stays in step.
   - An element never carries an intro and a loop on the same property: the loop goes on an
     inner wrapper (js-okp inside js-ok, st-you inside st-yours).
   - Every delayed loop uses `backwards` fill so it holds its first keyframe while it waits.
   - Anything scaled sets transform-box: fill-box. Offset-path riders do not (they sit at 0,0 and
     their path string is the drawn d, copied by the generator). */
.hx-fig { margin: 0; width: 100%; }
.hx-art { display: block; width: 100%; height: auto; overflow: visible; }
.hx-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* transient marks, hidden at rest */
.js-rider, .js-ping, .js-ripple, .dl-ride { opacity: 0; }
.js-rider, .dl-ride { offset-rotate: 0deg; offset-distance: 100%; }

/* the pop-in things all scale about their own centre */
.js-person, .js-b, .js-glyph, .js-zone, .js-ping, .js-ok, .js-okp, .js-btn, .js-cursor, .js-ripple, .js-bar,
.st-tag, .st-star, .st-pulse, .st-you, .st-yours, .st-livepill, .st-okd, .st-fill,
.dl-ev, .dl-ok, .dl-q, .dl-tpin, .dl-stamp, .dl-before, .dl-after, .dl-find { transform-box: fill-box; transform-origin: center; }
.dl-before, .dl-after, .dl-find, .st-fill { transform-origin: 0 50%; }
.js-bar { transform-origin: 50% 100%; }
.js-axis, .js-link { stroke-dasharray: var(--len); }
.dl-ev { transform-origin: 50% 0; }
.dl-str:not(.dl-str--ask) { stroke-dasharray: var(--len); }

/* Studio: the seam and the clip on the built half share two numbers, the intro (--sa) and the
   drag loop (--sb), both in user units measured from the seam's rest (x 240 in the viewBox).
   209.25 is that rest measured from the left edge of the built layer's box (x 30.75), S_CLIP in
   the generator. The static clipPath attribute on .st-built is the fallback where CSS clip-path
   is unsupported. The seam group carries our team, so they ride it. */
@property --sa { syntax: '<number>'; inherits: true; initial-value: 0; }
@property --sb { syntax: '<number>'; inherits: true; initial-value: 0; }
.hx-art--studio { --sa: 0; --sb: 0; }
.st-seam { transform: translateX(calc((var(--sa) + var(--sb)) * 1px)); }
.st-built { clip-path: inset(0 0 0 calc((209.25 + var(--sa) + var(--sb)) * 1px)); }

/* Held on the first frame until the drawing is on screen (components/svc-hero.js adds .is-on). */
.hx-js .hx-fig:not(.is-on) .hx-art, .hx-js .hx-fig:not(.is-on) .hx-art * { animation-play-state: paused !important; }

@keyframes hx-fade { from { opacity: 0; } }
@keyframes hx-pop { from { opacity: 0; transform: translateY(9px) scale(.92); } }
@keyframes hx-rise { from { opacity: 0; transform: translateY(16px); } }
@keyframes hx-drop { from { opacity: 0; transform: translateY(-14px); } }
@keyframes hx-badge { 0% { opacity: 0; transform: scale(.2); } 60% { opacity: 1; transform: scale(1.14); } 100% { transform: scale(1); } }
@keyframes hx-grow { from { transform: scaleX(0); } }
@keyframes hx-breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.14); } }

@media (prefers-reduced-motion: no-preference) {

  /* ---------------------------------------------------------------- Jumpstart
     Intro: the axes draw, the people interviewed appear, and every finding flies out of the
     person who raised it and settles on the chart (size is how much it hurts, across is how
     often); the three in the corner show their kind of fix, a line draws from the strongest to
     the prototype. Loop (9s from 3.4s): the strongest pings, its work rides the line in, a cursor
     taps the prototype, its chart fills and the check lands. */
  .js-axis { animation: js-draw .9s cubic-bezier(.65,0,.35,1) both; }
  .js-axlab { animation: hx-fade .5s ease-out .6s both; }
  .js-person { animation: hx-pop .6s cubic-bezier(.16,1,.3,1) both; animation-delay: calc(.15s + var(--i) * .08s); }
  .js-b { animation: js-fly 1.15s cubic-bezier(.16,1,.3,1) both; animation-delay: calc(.6s + var(--i) * .065s); }
  .js-zone { animation: js-zone 1s cubic-bezier(.16,1,.3,1) 1.45s both; }
  .js-glyph { animation: hx-badge .55s cubic-bezier(.3,1.3,.5,1) both; animation-delay: calc(1.8s + var(--i) * .12s); }
  .js-link { animation: js-draw .8s cubic-bezier(.65,0,.35,1) 2.15s both; }
  .js-linkhead { animation: hx-fade .3s ease-out 2.85s both; }
  .js-proto { animation: hx-rise .9s cubic-bezier(.16,1,.3,1) 2.35s both; }

  .js-ping { animation: js-ping 9s ease-out 3.4s infinite backwards; }
  .js-rider { animation: js-ride 9s cubic-bezier(.45,0,.25,1) 3.4s infinite backwards; }
  .js-cursor { animation: js-cursor 9s cubic-bezier(.65,0,.35,1) 3.4s infinite backwards; }
  .js-btn { animation: js-press 9s ease-out 3.4s infinite backwards; }
  .js-ripple { animation: js-ripple 9s ease-out 3.4s infinite backwards; }
  .js-bar { animation: js-bar 9s cubic-bezier(.16,1,.3,1) infinite backwards; animation-delay: calc(3.4s + var(--k) * .06s); }
  .js-okp { animation: js-okp 9s ease-out 3.4s infinite backwards; }

  /* ---------------------------------------------------------------- Studio
     Intro: the wireframe draws in on its dotted page, then the seam sweeps across from the right
     and the built screen appears behind it, our team riding the seam. Loop (10s from 2.9s): the
     work moves down the four rows (each row's bar fills in its colour, then its tag lights: the AI
     star turns, the agent keeps pulsing, the approval gets its tick), the screen's Live pill
     answers, your team looks up, and the seam glides a little further and back before it resets. */
  .st-frame { animation: hx-fade .5s ease-out both; }
  .st-sk { animation: hx-fade .5s ease-out both; animation-delay: calc(.15s + var(--i) * .07s); }
  .st-crew { animation: hx-fade .6s ease-out .6s both; }
  .st-yours { animation: hx-pop .7s cubic-bezier(.16,1,.3,1) 2.5s both; }
  .hx-art--studio { animation: st-in 1.8s cubic-bezier(.65,0,.35,1) .8s both, st-drag 10s cubic-bezier(.65,0,.35,1) 2.9s infinite backwards; }
  .st-fill--0 { animation: st-fill0 10s cubic-bezier(.45,0,.25,1) 2.9s infinite backwards; }
  .st-tag--0 { animation: st-tag0 10s ease-out 2.9s infinite backwards; }
  .st-fill--1 { animation: st-fill1 10s cubic-bezier(.45,0,.25,1) 2.9s infinite backwards; }
  .st-tag--1 { animation: st-tag1 10s ease-out 2.9s infinite backwards; }
  .st-fill--2 { animation: st-fill2 10s cubic-bezier(.45,0,.25,1) 2.9s infinite backwards; }
  .st-tag--2 { animation: st-tag2 10s ease-out 2.9s infinite backwards; }
  .st-fill--3 { animation: st-fill3 10s cubic-bezier(.45,0,.25,1) 2.9s infinite backwards; }
  .st-tag--3 { animation: st-tag3 10s ease-out 2.9s infinite backwards; }
  .st-star { animation: st-star 10s cubic-bezier(.3,1.3,.5,1) 2.9s infinite backwards; }
  .st-okd { animation: st-okd 10s cubic-bezier(.3,1.3,.5,1) 2.9s infinite backwards; }
  .st-pulse { animation: st-pulse 2.2s ease-out 2.6s infinite backwards; }
  .st-livepill { animation: st-livepill 10s ease-out 2.9s infinite backwards; }
  .st-live { animation: st-live 2.4s ease-in-out 2.6s infinite; }
  .st-you { animation: st-you 10s ease-out infinite backwards; animation-delay: calc(2.9s + var(--k) * .07s); }

  /* ---------------------------------------------------------------- Diligence
     Intro: the board, the thesis pinned, each piece of evidence pinned and strung to it, the checks,
     SUPPORTED stamped, the open question, the exhibit. Loop: evidence rides each string up to the
     thesis in turn (9s, 3s apart) and the thesis pin answers each arrival; the question breathes;
     on the exhibit the new bar shrinks from the old one's length to its own (8s). */
  .dl-board { animation: hx-fade .5s ease-out both; }
  .dl-thesis { animation: hx-drop .75s cubic-bezier(.16,1,.3,1) .15s both; }
  .dl-ev { animation: dl-pin .75s cubic-bezier(.16,1,.3,1) both; animation-delay: calc(.5s + var(--i) * .16s); }
  .dl-str:not(.dl-str--ask) { animation: dl-draw .7s ease-out both; animation-delay: calc(.8s + var(--i) * .16s); }
  .dl-str--ask { animation: hx-fade .6s ease-out 1.45s both; }
  .dl-find { animation: hx-grow .5s cubic-bezier(.16,1,.3,1) both; animation-delay: 1.2s; }
  .dl-ok { animation: hx-badge .5s cubic-bezier(.3,1.3,.5,1) both; animation-delay: calc(1.35s + var(--i) * .15s); }
  .dl-stamp { animation: dl-stamp .55s cubic-bezier(.2,.8,.3,1.2) 2s both; }
  .dl-q { animation: hx-breathe 4.8s ease-in-out 2.4s infinite; }
  .dl-exhibit { animation: hx-rise .85s cubic-bezier(.16,1,.3,1) 2.3s both; }
  .dl-before { animation: hx-grow .7s cubic-bezier(.16,1,.3,1) 2.7s both; }
  .dl-after { animation: dl-after 8s cubic-bezier(.65,0,.35,1) 3s infinite backwards; }
  .dl-ride { animation: dl-ride 9s cubic-bezier(.45,0,.25,1) infinite backwards; animation-delay: calc(3.1s + var(--i) * 3s); }
  .dl-tpin { animation: dl-tpin 3s ease-out 4.54s infinite backwards; }
}

/* Jumpstart keyframes. The cursor rests at x 524 y 256, right of the button; it taps at x 486. */
@keyframes js-draw { from { stroke-dashoffset: var(--len); } to { stroke-dashoffset: 0; } }
@keyframes js-fly { 0% { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(.35); } 18% { opacity: 1; } 100% { transform: none; } }
@keyframes js-zone { from { opacity: 0; transform: scale(.94); } }
@keyframes js-ping { 0% { opacity: 0; transform: scale(1); } 2% { opacity: .75; transform: scale(1); } 22%, 100% { opacity: 0; transform: scale(1.9); } }
@keyframes js-ride {
  0%, 6% { offset-distance: 0%; opacity: 0; }
  9% { opacity: 1; }
  24% { offset-distance: 100%; opacity: 1; }
  27%, 100% { offset-distance: 100%; opacity: 0; }
}
@keyframes js-cursor {
  0%, 26% { opacity: 0; transform: translate(34px, 26px); }
  32% { opacity: 1; }
  42% { transform: translate(-38px, -2px); }
  45% { transform: translate(-38px, -2px) scale(.84); }
  48%, 70% { opacity: 1; transform: translate(-38px, -2px); }
  84%, 100% { opacity: 0; transform: translate(34px, 26px); }
}
@keyframes js-press { 0%, 44.5% { transform: scale(1); } 46.5% { transform: scale(.92); } 50%, 100% { transform: scale(1); } }
@keyframes js-ripple { 0%, 45% { opacity: 0; transform: scale(1); } 46% { opacity: .8; } 58%, 100% { opacity: 0; transform: scale(2.3); } }
@keyframes js-bar { 0%, 47% { transform: scaleY(.3); } 60%, 90% { transform: scaleY(1); } 97%, 100% { transform: scaleY(.3); } }
@keyframes js-okp { 0%, 48% { transform: scale(0); } 53% { transform: scale(1.25); } 57%, 90% { transform: scale(1); } 95%, 100% { transform: scale(0); } }

/* Studio keyframes. Row r fills from 8 + 13r% to 17 + 13r% and its tag lights as it finishes. */
@keyframes st-in { from { --sa: 318; } to { --sa: 0; } }
@keyframes st-drag { 0%, 66% { --sb: 0; } 76%, 82% { --sb: -60; } 90%, 100% { --sb: 0; } }
@keyframes st-fill0 { 0%, 8% { transform: scaleX(0); opacity: 1; } 17%, 90% { transform: scaleX(1); opacity: 1; } 96% { transform: scaleX(1); opacity: 0; } 97%, 100% { transform: scaleX(0); opacity: 0; } }
@keyframes st-tag0 { 0%, 16.5% { opacity: .38; transform: scale(1); } 19% { opacity: 1; transform: scale(1.08); } 22%, 90% { opacity: 1; transform: scale(1); } 97%, 100% { opacity: .38; transform: scale(1); } }
@keyframes st-fill1 { 0%, 21% { transform: scaleX(0); opacity: 1; } 30%, 90% { transform: scaleX(1); opacity: 1; } 96% { transform: scaleX(1); opacity: 0; } 97%, 100% { transform: scaleX(0); opacity: 0; } }
@keyframes st-tag1 { 0%, 29.5% { opacity: .38; transform: scale(1); } 32% { opacity: 1; transform: scale(1.08); } 35%, 90% { opacity: 1; transform: scale(1); } 97%, 100% { opacity: .38; transform: scale(1); } }
@keyframes st-fill2 { 0%, 34% { transform: scaleX(0); opacity: 1; } 43%, 90% { transform: scaleX(1); opacity: 1; } 96% { transform: scaleX(1); opacity: 0; } 97%, 100% { transform: scaleX(0); opacity: 0; } }
@keyframes st-tag2 { 0%, 42.5% { opacity: .38; transform: scale(1); } 45% { opacity: 1; transform: scale(1.08); } 48%, 90% { opacity: 1; transform: scale(1); } 97%, 100% { opacity: .38; transform: scale(1); } }
@keyframes st-fill3 { 0%, 47% { transform: scaleX(0); opacity: 1; } 56%, 90% { transform: scaleX(1); opacity: 1; } 96% { transform: scaleX(1); opacity: 0; } 97%, 100% { transform: scaleX(0); opacity: 0; } }
@keyframes st-tag3 { 0%, 55.5% { opacity: .38; transform: scale(1); } 58% { opacity: 1; transform: scale(1.08); } 61%, 90% { opacity: 1; transform: scale(1); } 97%, 100% { opacity: .38; transform: scale(1); } }
@keyframes st-star { 0%, 29% { transform: rotate(0) scale(1); } 33% { transform: rotate(90deg) scale(1.35); } 38%, 100% { transform: rotate(90deg) scale(1); } }
@keyframes st-okd { 0%, 56% { transform: scale(0); } 60% { transform: scale(1.2); } 63%, 90% { transform: scale(1); } 96%, 100% { transform: scale(0); } }
@keyframes st-pulse { 0% { transform: scale(1); opacity: .8; } 100% { transform: scale(2.2); opacity: 0; } }
@keyframes st-livepill { 0%, 58% { transform: scale(1); } 61% { transform: scale(1.12); } 65%, 100% { transform: scale(1); } }
@keyframes st-live { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@keyframes st-you { 0%, 62% { transform: none; } 64.5% { transform: translateY(-3px); } 67%, 100% { transform: none; } }

/* Diligence loop keyframes */
@keyframes dl-pin { from { opacity: 0; transform: translateY(-16px) rotate(-4deg); } }
@keyframes dl-draw { from { stroke-dashoffset: var(--len); } to { stroke-dashoffset: 0; } }
@keyframes dl-stamp { 0% { opacity: 0; transform: scale(1.9); } 65% { opacity: 1; transform: scale(.95); } 100% { transform: scale(1); } }
@keyframes dl-after {
  0% { opacity: 0; transform: scaleX(1.5625); }
  6%, 16% { opacity: 1; transform: scaleX(1.5625); }
  36%, 88% { opacity: 1; transform: scaleX(1); }
  95%, 100% { opacity: 0; transform: scaleX(1); }
}
@keyframes dl-ride {
  0% { offset-distance: 0%; opacity: 0; }
  3% { opacity: 1; }
  16% { offset-distance: 100%; opacity: 1; }
  19%, 100% { offset-distance: 100%; opacity: 0; }
}
@keyframes dl-tpin { 0% { transform: scale(1); } 9% { transform: scale(1.7); } 28%, 100% { transform: scale(1); } }
