/* BioSonic Product Visuals — warm "paper & dusk" animated visual system.
   Catalogue of 50 looping CSS visuals that show what BioSonic does, one per
   product capability. Ported from the design handoff (high-fidelity).

   Usage: add class "bs-visuals" to a container; tiles use inline styles + the
   bs* keyframes below. Accent is themable via --bs-acc; page tone via --bs-bg.
   Honours prefers-reduced-motion (pauses every loop). */

:root {
  --bs-acc: #C8714D;        /* primary terracotta (signature) */
  --bs-bg: #EFEAE0;         /* warm cream page tone */
  --bs-card: #FBF9F4;       /* tile surface */
  --bs-ink: #33302B;        /* primary text */
  --bs-ink-muted: #6B6459;  /* body text */
  --bs-ink-dim: #8A8275;    /* captions */
  --bs-hairline: rgba(60,50,40,0.10);

  /* species colour language */
  --bs-pipistrelle: #C8714D; /* terracotta */
  --bs-serotine:    #A65C72; /* berry */
  --bs-noctule:     #D9A24A; /* amber */
  --bs-myotis:      #7FA3B5; /* sky (Daubenton's / Myotis) */
  --bs-blong:       #6F8B5C; /* moss (brown long-eared) */
  --bs-barbastelle: #5D5B8D; /* plum */
}

.bs-visuals * { box-sizing: border-box; }

/* ── Keyframe library (all prefixed bs) ── */
@keyframes bsWave{0%,100%{transform:scaleY(.34)}50%{transform:scaleY(1)}}
@keyframes bsSlot5{0%,14%{transform:translateY(0)}20%,34%{transform:translateY(-20%)}40%,54%{transform:translateY(-40%)}60%,74%{transform:translateY(-60%)}80%,100%{transform:translateY(-80%)}}
@keyframes bsBreathe{0%,100%{transform:scale(1)}50%{transform:scale(1.06)}}
@keyframes bsFloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-8px)}}
@keyframes bsFloat2{0%,100%{transform:translateY(0)}50%{transform:translateY(-14px)}}
@keyframes bsRipple{0%{transform:scale(.12);opacity:.5}70%{opacity:0}100%{transform:scale(2.9);opacity:0}}
@keyframes bsTwinkle{0%,100%{opacity:.18}50%{opacity:.95}}
@keyframes bsFlapL{0%,100%{transform:rotate(7deg)}50%{transform:rotate(-27deg)}}
@keyframes bsFlapR{0%,100%{transform:rotate(-7deg)}50%{transform:rotate(27deg)}}
@keyframes bsInLeft{0%,6%{transform:translateX(-26px);opacity:0}16%{transform:translateX(0);opacity:1}30%{transform:translateX(30px);opacity:0}31%,100%{opacity:0}}
@keyframes bsOutRight{0%,42%{transform:translateX(-12px);opacity:0}50%{transform:translateX(0);opacity:1}74%{opacity:1}82%{transform:translateX(16px);opacity:0}83%,100%{opacity:0}}
@keyframes bsFly{0%{left:-16%;top:58%}25%{top:30%}50%{top:52%}75%{top:26%}100%{left:114%;top:46%}}
@keyframes bsFly2{0%{left:-18%;top:32%}30%{top:58%}60%{top:34%}100%{left:116%;top:60%}}
@keyframes bsFly3{0%{left:-14%;top:74%}40%{top:42%}80%{top:66%}100%{left:112%;top:38%}}
@keyframes bsSway{0%,100%{transform:rotate(-3.5deg)}50%{transform:rotate(3.5deg)}}
@keyframes bsSway2{0%,100%{transform:rotate(2.6deg)}50%{transform:rotate(-2.6deg)}}
@keyframes bsBar{0%,7%{transform:scaleY(0)}22%{transform:scaleY(1)}82%{transform:scaleY(1)}96%,100%{transform:scaleY(0)}}
@keyframes bsDrop{0%{transform:translateY(-110px);opacity:0}12%{opacity:1}40%,100%{transform:translateY(0);opacity:1}}
@keyframes bsNeedle{0%,12%{top:70%}22%,34%{top:46%}44%,56%{top:22%}66%,78%{top:54%}88%,100%{top:70%}}
@keyframes bsSweep{0%{transform:translateX(-160%)}100%{transform:translateX(160%)}}
@keyframes bsDraw{0%{stroke-dashoffset:200;opacity:0}24%{opacity:1}46%{stroke-dashoffset:0}84%{stroke-dashoffset:0;opacity:1}100%{stroke-dashoffset:200;opacity:0}}
@keyframes bsPop{0%,8%{transform:scale(.4);opacity:0}18%{transform:scale(1.08);opacity:1}30%{transform:scale(1)}80%{opacity:1;transform:scale(1)}90%,100%{transform:scale(.6);opacity:0}}
@keyframes bsSpin{to{transform:rotate(360deg)}}
@keyframes bsBlip1{0%{transform:translate(-66px,-42px) scale(.7);opacity:0}25%{opacity:1}100%{transform:translate(0,0) scale(.2);opacity:0}}
@keyframes bsBlip2{0%{transform:translate(68px,-34px) scale(.7);opacity:0}25%{opacity:1}100%{transform:translate(0,0) scale(.2);opacity:0}}
@keyframes bsBlip3{0%{transform:translate(-58px,46px) scale(.7);opacity:0}25%{opacity:1}100%{transform:translate(0,0) scale(.2);opacity:0}}
@keyframes bsBlip4{0%{transform:translate(64px,42px) scale(.7);opacity:0}25%{opacity:1}100%{transform:translate(0,0) scale(.2);opacity:0}}
@keyframes bsRise{0%,10%{transform:translateY(0);opacity:0}24%{opacity:1}55%{transform:translateY(-36px);opacity:1}80%{transform:translateY(-70px);opacity:0}100%{opacity:0}}
@keyframes bsGlow{0%,100%{opacity:.4;transform:scale(1)}50%{opacity:.78;transform:scale(1.12)}}
@keyframes bsDash{to{stroke-dashoffset:-40}}
@keyframes bsPulse{0%{transform:scale(.5);opacity:.85}70%{opacity:0}100%{transform:scale(2.6);opacity:0}}
@keyframes bsHeat{0%,100%{transform:scale(.8);opacity:.4}50%{transform:scale(1.18);opacity:.82}}
@keyframes bsType{0%,70%,100%{transform:translateY(0);opacity:.45}35%{transform:translateY(-6px);opacity:1}}
@keyframes bsSlide{0%,100%{left:16%}50%{left:78%}}
@keyframes bsCheck{0%,15%{transform:scale(0);opacity:0}32%{transform:scale(1.25);opacity:1}46%,100%{transform:scale(1);opacity:1}}
@keyframes bsDial{0%,12%{stroke-dashoffset:283}48%,78%{stroke-dashoffset:74}96%,100%{stroke-dashoffset:283}}
@keyframes bsForkUp{0%,28%{transform:translate(-38px,0);opacity:0}42%{opacity:1}70%{transform:translate(34px,-24px);opacity:1}84%{opacity:0}100%{opacity:0}}
@keyframes bsForkDn{0%,28%{transform:translate(-38px,0);opacity:0}42%{opacity:1}70%{transform:translate(34px,24px);opacity:1}84%{opacity:0}100%{opacity:0}}
@keyframes bsCloudUp{0%{transform:translateY(54px);opacity:0}20%{opacity:1}80%{opacity:1}100%{transform:translateY(-18px);opacity:0}}
@keyframes bsFlip{0%,40%{transform:rotateY(0)}50%,90%{transform:rotateY(180deg)}100%{transform:rotateY(360deg)}}
@keyframes bsConfetti{0%{transform:translateY(0) scale(0);opacity:0}25%{opacity:1;transform:translateY(-16px) scale(1)}100%{transform:translateY(10px) scale(.5);opacity:0}}
@keyframes bsScanBox{0%,100%{left:4%}50%{left:60%}}
@keyframes bsBounce{0%,100%{transform:translateY(0)}50%{transform:translateY(-7px)}}
@keyframes bsWiggle{0%,100%{transform:rotate(-8deg)}50%{transform:rotate(8deg)}}

/* ── Reduced motion: pause every loop ── */
@media (prefers-reduced-motion: reduce) {
  .bs-visuals *,
  .bs-visuals *::before,
  .bs-visuals *::after { animation-play-state: paused !important; }
}

/* ── Layout helpers for dropping visuals onto site pages ──
   .bsv-card = warm card chrome (wrap a bare stage to frame it on dark pages)
   .bsv-fig  = centre one framed visual inside a wide feature column
   .bsv-grid = responsive grid of full tiles (card + caption) */
.bsv-card {
  background: var(--bs-card);
  border: 1px solid var(--bs-hairline);
  border-radius: 18px;
  padding: 14px;
  box-shadow: 0 1px 2px rgba(60,40,20,.05), 0 16px 34px -28px rgba(60,40,20,.4);
}
.bsv-fig { max-width: 520px; margin-left: auto; margin-right: auto; }
/* feature-row visuals: framed tile, enlarged ~1.55x (uniform scale keeps the composition) */
.bs-feat .bsv-fig { max-width: 412px; transform: scale(1.55); transform-origin: center; margin: 46px auto; }
/* never scale on stacked/mobile layouts — it would overflow the viewport */
@media (max-width: 900px) { .bs-feat .bsv-fig { transform: none; margin: 0 auto; } }
.bsv-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 22px;
  max-width: 1180px;
  margin: 0 auto;
}
.bsv-grid > * { margin: 0; }
@media (max-width: 640px) { .bsv-fig { max-width: 440px; } }
