/* A small ensemble: ten instruments, ten distinct motion signatures. */
.buddy-band{max-width:1180px;column-gap:24px;row-gap:18px;padding-top:24px}
.buddy-band .buddy-name{font:400 clamp(17px,1.65vw,25px)/1.3 Pax,Arial,sans-serif;letter-spacing:.035em;text-transform:none;margin-top:-7px;opacity:1}
.bandmate-selection h2,.buddy-panel h2{font:400 clamp(28px,2.6vw,40px)/1.3 Pax,Arial,sans-serif;letter-spacing:.035em}
.bandmate-selection>div{min-width:230px}
.buddy-band .buddy-option{opacity:.88;padding-bottom:24px}
.buddy-character{overflow:visible;animation:none;isolation:isolate}
.buddy-performer{position:absolute;inset:0;display:block;transform-origin:50% 86%;animation-timing-function:cubic-bezier(.45,0,.3,1);animation-iteration-count:infinite;animation-delay:var(--buddy-delay,0s);will-change:transform}
.buddy-performance{position:absolute;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none;fill:none;stroke:currentColor;stroke-width:1.65;stroke-linecap:round;stroke-linejoin:round;opacity:.55;transition:opacity .4s}
.buddy-option:has(input:checked) .buddy-performance,.buddy-option:hover .buddy-performance{opacity:.95}
.buddy-performance *{transform-box:view-box;transform-origin:120px 120px;animation-delay:var(--buddy-delay,0s);animation-iteration-count:infinite;animation-timing-function:ease-in-out}
.buddy-launch .buddy-performance{display:none}
/* Pulse compresses into the downbeat; a quiet ripple marks the kick. */
.buddy-pulse .buddy-performer{animation-name:buddy-pulse-play;animation-duration:2.4s}
@keyframes buddy-pulse-play{0%,25%,50%,75%,100%{transform:translateY(0) scale(1)}6%,56%{transform:translateY(2px) scale(1.045,.94)}14%,64%{transform:translateY(-6px) scale(.98,1.025)}31%,81%{transform:rotate(-2deg) scale(1.02,.97)}39%,89%{transform:rotate(2deg)}}
.pulse-rings ellipse{transform-origin:120px 194px;animation:buddy-kick 2.4s ease-out infinite;animation-delay:var(--buddy-delay)}
.pulse-rings ellipse+ellipse{animation-delay:calc(var(--buddy-delay) + .2s)}
@keyframes buddy-kick{0%,48%,100%{transform:scale(.6);opacity:0}7%,55%{opacity:.6}28%,78%{transform:scale(1.4);opacity:0}}
.pulse-meter{animation-name:buddy-meter;animation-duration:1.2s}
@keyframes buddy-meter{0%,100%{opacity:.12}20%,65%{opacity:.85}40%,80%{opacity:.25}}
/* Loop returns to exactly the same place; its playhead completes a circuit. */
.buddy-loop .buddy-performer{animation-name:buddy-loop-play;animation-duration:5.6s}
@keyframes buddy-loop-play{0%,100%{transform:rotate(-3deg) translateY(0)}25%{transform:rotate(4deg) translate(3px,-3px)}50%{transform:rotate(-1deg) translateY(-6px)}75%{transform:rotate(-5deg) translate(-3px,-2px)}}
.loop-trail{stroke-dasharray:3 6;opacity:.45}
.loop-cursor{transform-origin:120px 67px;animation-name:buddy-loop-spin;animation-duration:5.6s;animation-timing-function:linear}
@keyframes buddy-loop-spin{to{transform:rotate(360deg)}}
.loop-repeat{animation-name:buddy-loop-return;animation-duration:5.6s}
@keyframes buddy-loop-return{0%,85%,100%{opacity:0}10%,60%{opacity:.8}}
/* Grain breaks a texture into small drifting fragments. */
.buddy-grain .buddy-performer{animation-name:buddy-grain-play;animation-duration:6.8s}
@keyframes buddy-grain-play{0%,100%{transform:rotate(-1deg)}20%{transform:translateY(-3px) rotate(1deg)}39%,44%{transform:translateX(-1.5px) rotate(-1deg)}41%,46%{transform:translateX(1.5px) rotate(1deg)}70%{transform:translateY(-5px) rotate(-1deg)}}
.grain-cloud circle{fill:currentColor;stroke:0;animation-name:buddy-grain-rise;animation-duration:4.7s}
.grain-cloud circle:nth-child(2n){animation-delay:calc(var(--buddy-delay) - 1.6s);animation-duration:5.3s}
.grain-cloud circle:nth-child(3n){animation-delay:calc(var(--buddy-delay) - 3.2s);animation-duration:6.1s}
@keyframes buddy-grain-rise{0%,100%{opacity:0;transform:translate(0,18px) scale(.7)}30%{opacity:.85}75%{opacity:0;transform:translate(9px,-22px) scale(1.2)}}
.grain-scan{stroke-dasharray:2 5;animation-name:buddy-grain-scan;animation-duration:4.7s}
@keyframes buddy-grain-scan{0%,100%{transform:translateY(0);opacity:0}40%{opacity:.7}75%{transform:translateY(20px);opacity:0}}
/* Patch leans between connections while a signal travels through its cable. */
.buddy-patch .buddy-performer{animation-name:buddy-patch-play;animation-duration:7.2s}
@keyframes buddy-patch-play{0%,100%{transform:rotate(0)}20%,30%{transform:rotate(-4deg) translateX(-2px)}47%{transform:translateY(-4px) rotate(1deg)}67%,78%{transform:rotate(4deg) translateX(2px)}}
.patch-cable{stroke-dasharray:10 290;animation-name:buddy-patch-flow;animation-duration:7.2s;animation-timing-function:linear;opacity:.85}
@keyframes buddy-patch-flow{from{stroke-dashoffset:310}to{stroke-dashoffset:-310}}
.patch-signal circle{animation-name:buddy-patch-port;animation-duration:7.2s;fill:currentColor}
.patch-signal circle+circle{animation-delay:calc(var(--buddy-delay) + 3.6s)}
@keyframes buddy-patch-port{0%,44%,65%,100%{opacity:.15}48%,58%{opacity:1}}
.patch-ping{animation-name:buddy-patch-ping;animation-duration:7.2s}
@keyframes buddy-patch-ping{0%,45%,70%,100%{opacity:0;transform:scale(.8)}51%,61%{opacity:1;transform:scale(1)}}
/* Wave stretches and settles like a low oscillator. */
.buddy-wave .buddy-performer{animation-name:buddy-wave-play;animation-duration:6.4s}
@keyframes buddy-wave-play{0%,100%{transform:scale(1.025,.98) rotate(-1deg)}25%{transform:scale(.98,1.03) translateY(-3px) rotate(2deg)}50%{transform:scale(1.04,.96) rotate(1deg)}75%{transform:scale(.99,1.02) translateY(-5px) rotate(-2deg)}}
.wave-ribbon path{animation-name:buddy-wave-flow;animation-duration:6.4s;stroke-dasharray:52 30}
.wave-ribbon path+path{animation-delay:calc(var(--buddy-delay) - 2s);opacity:.35}
@keyframes buddy-wave-flow{0%{stroke-dashoffset:0;transform:translateX(-3px);opacity:.25}50%{transform:translate(3px,-5px);opacity:.8}100%{stroke-dashoffset:-164;transform:translateX(-3px);opacity:.25}}
/* Keys sways in three; notes rise at different points in the phrase. */
.buddy-keys .buddy-performer{animation-name:buddy-keys-play;animation-duration:3.6s}
@keyframes buddy-keys-play{0%,100%{transform:rotate(-3deg)}16%{transform:rotate(-1deg) translateY(-3px)}33%{transform:rotate(3deg)}50%{transform:rotate(1deg) translateY(-4px)}66%{transform:rotate(-2deg)}83%{transform:rotate(2deg) translateY(-3px)}}
.keys-notes path{animation-name:buddy-note-rise;animation-duration:3.6s}
.keys-notes path:nth-child(2){animation-delay:calc(var(--buddy-delay) - 1.2s)}
.keys-notes path:nth-child(3){animation-delay:calc(var(--buddy-delay) - 2.4s)}
@keyframes buddy-note-rise{0%,100%{opacity:0;transform:translateY(18px) rotate(-4deg)}25%{opacity:.85}75%{opacity:0;transform:translate(5px,-8px) rotate(5deg)}}
.keys-playing{stroke-dasharray:4 12;animation-name:buddy-key-tap;animation-duration:1.2s}
@keyframes buddy-key-tap{50%{transform:translateY(2px);opacity:.3}}
/* Drift floats in an oval, with a slowly precessing orbit. */
.buddy-drift .buddy-performer{animation-name:buddy-drift-play;animation-duration:9.2s}
@keyframes buddy-drift-play{0%,100%{transform:translate(-3px,-3px) rotate(-3deg)}25%{transform:translate(3px,-11px) rotate(2deg)}50%{transform:translate(5px,-5px) rotate(4deg)}75%{transform:translate(-2px,0) rotate(-1deg)}}
.drift-orbit{transform-origin:120px 162px;animation-name:buddy-drift-orbit;animation-duration:12s;opacity:.45}
@keyframes buddy-drift-orbit{0%,100%{transform:rotate(-9deg) scaleX(.9)}50%{transform:rotate(10deg) scaleX(1.02)}}
.drift-stars{animation-name:buddy-drift-stars;animation-duration:7s}
@keyframes buddy-drift-stars{0%,100%{opacity:.15;transform:translateY(4px)}50%{opacity:.9;transform:translateY(-5px)}}
/* Step rocks heel-to-toe on four discrete sequencer beats. */
.buddy-step .buddy-performer{animation-name:buddy-step-play;animation-duration:3.2s}
@keyframes buddy-step-play{0%,100%{transform:translateX(-3px) rotate(-4deg)}12%,62%{transform:translateY(-7px) rotate(0)}25%,50%{transform:translateX(3px) rotate(4deg)}37%,87%{transform:translateY(-3px) rotate(0)}75%{transform:translateX(-3px) rotate(-4deg)}}
.step-sequence rect{fill:currentColor;stroke:0;opacity:.1;animation-name:buddy-step-light;animation-duration:3.2s;animation-timing-function:steps(1,end)}
.step-sequence rect:nth-child(2){animation-delay:calc(var(--buddy-delay) + .8s)}
.step-sequence rect:nth-child(3){animation-delay:calc(var(--buddy-delay) + 1.6s)}
.step-sequence rect:nth-child(4){animation-delay:calc(var(--buddy-delay) + 2.4s)}
@keyframes buddy-step-light{0%,24%{opacity:.9}25%,100%{opacity:.12}}
.step-scan{animation-name:buddy-step-scan;animation-duration:3.2s;animation-timing-function:steps(3,end);opacity:.6}
@keyframes buddy-step-scan{0%{transform:translateY(0)}99%{transform:translateY(56px)}100%{transform:translateY(0)}}
/* Echo answers one nod with two smaller repeats. */
.buddy-echo .buddy-performer{animation-name:buddy-echo-play;animation-duration:6s}
@keyframes buddy-echo-play{0%,12%,35%,57%,100%{transform:rotate(0)}20%{transform:translateY(-5px) rotate(4deg)}41%{transform:translateY(-3px) rotate(2.5deg)}63%{transform:translateY(-1px) rotate(1deg)}76%{transform:rotate(0)}}
.echo-rings path{transform-origin:120px 120px;animation-name:buddy-echo-repeat;animation-duration:6s}
.echo-rings path:nth-child(2){animation-delay:calc(var(--buddy-delay) + .5s)}
.echo-rings path:nth-child(3){animation-delay:calc(var(--buddy-delay) + 1s)}
@keyframes buddy-echo-repeat{0%,14%,65%,100%{opacity:0;transform:scale(.88)}24%{opacity:.65}54%{opacity:0;transform:scale(1.07)}}
/* Spark anticipates, springs up, then settles; the idea appears at the apex. */
.buddy-spark .buddy-performer{animation-name:buddy-spark-play;animation-duration:7.8s}
@keyframes buddy-spark-play{0%,35%,72%,100%{transform:translateY(0) rotate(-1deg)}42%{transform:scale(1.04,.94) rotate(-4deg)}49%{transform:translateY(-13px) rotate(6deg) scale(.98,1.03)}56%{transform:translateY(1px) rotate(2deg) scale(1.03,.96)}63%{transform:translateY(-3px) rotate(-2deg)}}
.spark-burst{animation-name:buddy-spark-burst;animation-duration:7.8s;transform-origin:120px 100px}
@keyframes buddy-spark-burst{0%,43%,64%,100%{opacity:0;transform:scale(.75)}49%{opacity:1;transform:scale(1)}59%{opacity:0;transform:scale(1.15)}}
.spark-flash{animation-name:buddy-spark-flash;animation-duration:7.8s;fill:currentColor;stroke:0}
@keyframes buddy-spark-flash{0%,44%,64%,100%{opacity:0}49%,56%{opacity:1}}
/* Pause is global and respects the visitor's system motion preference. */
.buddy-still .buddy-character *,.buddy-offscreen *,.buddy-panel[hidden] .buddy-character *{animation-play-state:paused!important}
@media(max-width:1000px) and (min-width:761px){.buddy-band{column-gap:12px}.buddy-band .buddy-name{font-size:17px;letter-spacing:.015em}}
@media(max-width:760px){.buddy-band{grid-template-columns:repeat(3,minmax(0,1fr));gap:18px 12px;max-width:540px}.buddy-band .buddy-option:nth-child(-n+5){translate:0;scale:1}.buddy-band .buddy-option:last-child{grid-column:2}.buddy-band .buddy-name{font-size:clamp(14px,3.25vw,19px);letter-spacing:.025em;margin-top:-6px}.bandmate-selection h2{font-size:29px}.bandmate-selection>div{min-width:150px}.buddy-performance{stroke-width:1.9}}
@media(max-width:420px){.buddy-band{grid-template-columns:repeat(2,minmax(0,1fr));gap:18px}.buddy-band .buddy-option:last-child{grid-column:auto}.buddy-band .buddy-name{font-size:19px}.bandmate-selection{gap:14px}}
@media(prefers-reduced-motion:reduce){.buddy-character *{animation:none!important;transition:none!important}.buddy-frame-0{opacity:1}.buddy-frame-1,.buddy-frame-2{opacity:0}.buddy-performance{display:none}.buddy-band .buddy-option{transition:none}}
.buddy-page-hidden .buddy-character *{animation-play-state:paused!important}
