/* ============================================================
   Aspect V3 - COA hero, vial scan stage (markup coa-hero.mjs {stage:"vial"}, timeline coa-vial.js)
   Loaded after coa-hero.css (intro, copy, ticker, segments shared).
   PER LOT (7.4s, states added by JS on .vs):
     0     s-in      vial rises onto the plinth (600ms, out-expo)
     450   s-scan    laser sweeps the label top to bottom and back to the name band (1300ms)
     1650  s-read    reticle locks on name + dose, "Label read" tag (320ms)
     1950  s-unfold  certificate slides out from behind the vial and unfolds (700ms + fold 520ms)
     2900  s-lock    beam runs down the certificate to the printed purity, box locks (900ms),
                     readout plate rises, purity counts up to the printed value (1100ms)
     6900  s-out     vial and certificate leave (450ms), next lot
   Reduced motion: final state, no laser, no auto-advance.
   Label geometry (shared vial silhouette, % of the 345x760 cutout): label 35-92%, name + dose 50-73%.
   ============================================================ */
.ch-vial .ch-stage.vs { padding-top: 0; }
.vs-scene { position: relative; height: 560px; perspective: 1400px; }
.vs-floor { position: absolute; left: -4%; bottom: 6px; width: 62%; height: 90px; border-radius: 50%;
  background: radial-gradient(closest-side, rgba(79, 141, 255, .55), rgba(21, 97, 220, .22) 55%, transparent 100%); filter: blur(2px); }
.vs-floor::after { content: ""; position: absolute; inset: 26% 14%; border-radius: 50%; border: 1px solid rgba(140, 192, 255, .45); box-shadow: 0 0 24px rgba(79, 141, 255, .5), inset 0 0 18px rgba(79, 141, 255, .35); }
.vs-vial { position: absolute; z-index: 3; left: 6%; bottom: 44px; height: 470px; aspect-ratio: 345 / 760; }
.vs-vial-img { display: block; width: 100%; height: 100%; filter: drop-shadow(0 26px 26px rgba(0, 0, 0, .55)); }
.vs-glare { position: absolute; inset: 35% 4% 8% 4%; border-radius: 6px; pointer-events: none; opacity: 0; mix-blend-mode: screen;
  background: linear-gradient(180deg, transparent, rgba(140, 192, 255, .35) 50%, transparent); }
.vs-ret { position: absolute; left: 4%; right: 4%; top: 49%; height: 25%; opacity: 0; }
.vs-ret i { position: absolute; width: 18px; height: 18px; border: 0 solid #4f8dff; filter: drop-shadow(0 0 5px rgba(79, 141, 255, .9)); }
.vs-ret i:nth-child(1) { left: -6px; top: -6px; border-left-width: 2px; border-top-width: 2px; }
.vs-ret i:nth-child(2) { right: -6px; top: -6px; border-right-width: 2px; border-top-width: 2px; }
.vs-ret i:nth-child(3) { left: -6px; bottom: -6px; border-left-width: 2px; border-bottom-width: 2px; }
.vs-ret i:nth-child(4) { right: -6px; bottom: -6px; border-right-width: 2px; border-bottom-width: 2px; }
.vs-laser { position: absolute; left: -18%; right: -18%; top: 0; bottom: 0; pointer-events: none; opacity: 0; }
.vs-laser i { position: absolute; left: 0; right: 0; top: 0; height: 100%; translate: 0 34%; }
.vs-laser i::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, transparent, #4f8dff 12%, #e6f0ff 50%, #4f8dff 88%, transparent); box-shadow: 0 0 14px 3px rgba(79, 141, 255, .85); }
.vs-laser i::after { content: ""; position: absolute; left: 12%; right: 12%; top: -46px; height: 46px; background: linear-gradient(180deg, transparent, rgba(79, 141, 255, .22)); }
.vs-tag { position: absolute; left: 92%; top: 52%; display: grid; gap: 2px; padding: 7px 11px; border-radius: 10px; white-space: nowrap; opacity: 0;
  background: rgba(6, 17, 46, .85); border: 1px solid rgba(140, 192, 255, .35); box-shadow: 0 10px 24px -10px rgba(0, 0, 0, .7);
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase; color: #c3cde0; }
.vs-tag b { color: #7cf0b5; font-weight: 600; }
.vs-tag::before { content: ""; position: absolute; right: 100%; top: 50%; width: 26px; height: 1px; background: rgba(140, 192, 255, .6); }

.vs-cert { position: absolute; z-index: 2; left: 40%; top: 14px; width: 290px; aspect-ratio: 612 / 792; transform-style: preserve-3d; rotate: 4deg; }
.vs-half { position: absolute; left: 0; right: 0; height: 50%; background-color: #fff; background-repeat: no-repeat; background-size: 100% 200%; backface-visibility: hidden; }
.vs-top { top: 0; background-position: 0 0; border-radius: 4px 4px 0 0; box-shadow: 0 30px 60px -24px rgba(0, 0, 0, .7); }
.vs-bot { top: 50%; background-position: 0 100%; border-radius: 0 0 4px 4px; transform-origin: 50% 0; box-shadow: 0 30px 60px -24px rgba(0, 0, 0, .7); }
.vs-bot::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(4, 12, 34, .28), transparent 30%); opacity: 1; transition: opacity 500ms; }
.vs-hl { position: absolute; z-index: 2; left: calc(var(--x) * 100%); top: calc(var(--y) * 100%); width: calc(var(--w) * 100%); height: calc(var(--h) * 100%); border-radius: 3px; opacity: 0;
  box-shadow: 0 0 0 2px #1561dc, 0 0 0 6px rgba(21, 97, 220, .22), 0 0 18px 4px rgba(21, 97, 220, .45); background: rgba(21, 97, 220, .1); }
.vs-cbeam { position: absolute; z-index: 2; inset: 0; overflow: hidden; pointer-events: none; }
.vs-cbeam i { position: absolute; left: 0; right: 0; top: 0; height: 100%; translate: 0 0; opacity: 0; }
.vs-cbeam i::before { content: ""; position: absolute; left: -4%; right: -4%; top: 0; height: 2px; background: linear-gradient(90deg, transparent, #1561dc 15%, #8cc0ff 50%, #1561dc 85%, transparent); box-shadow: 0 0 12px 2px rgba(21, 97, 220, .6); }
.vs-cbeam i::after { content: ""; position: absolute; left: 0; right: 0; top: -60px; height: 60px; background: linear-gradient(180deg, transparent, rgba(21, 97, 220, .14)); }

.vs-read { position: absolute; z-index: 4; right: -2%; top: 300px; width: 250px; padding: 16px 18px; border-radius: 18px; opacity: 0;
  background: linear-gradient(160deg, rgba(24, 56, 128, .88), rgba(8, 20, 52, .94)); border: 1px solid rgba(140, 192, 255, .3);
  box-shadow: 0 30px 60px -24px rgba(0, 0, 0, .8), inset 0 1px 0 rgba(255, 255, 255, .1); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); }
.vs-pur { margin: 8px 0 0; font-size: 3.1rem; font-weight: 600; letter-spacing: -.05em; line-height: .95; color: #7cf0b5; font-variant-numeric: tabular-nums; text-shadow: 0 0 30px rgba(94, 230, 166, .4); }
.vs-pass { display: flex; align-items: center; gap: 6px; margin: 10px 0 0; font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: #7cf0b5; }
.vs-pass svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }

.vs-info { display: flex; align-items: center; gap: 14px; margin-top: 8px; padding: 12px 12px 12px 14px; border-radius: 18px; background: rgba(255, 255, 255, .05); border: 1px solid rgba(140, 192, 255, .16); }
.vs-who { flex: 1; min-width: 0; }
.vs-name { margin: 0; font-size: 1.15rem; font-weight: 600; letter-spacing: -.02em; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vs-z { color: #c3cde0; font-weight: 500; }
.vs-lot { margin: 3px 0 0; font-family: var(--font-mono); font-size: 11px; letter-spacing: .03em; color: #93a1bd; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vs-info [data-f] { transition: opacity 260ms, filter 260ms; }
.vs.is-swap .vs-info [data-f], .vs.is-swap .vs-info .ch-lablogo img { opacity: 0; filter: blur(5px); }
.vs .ch-ctl { margin-top: 14px; }

/* ---------- states (motion) ---------- */
@media (prefers-reduced-motion: no-preference) {
  .vs-vial { opacity: 0; translate: 0 26px; transition: opacity 600ms cubic-bezier(.16, 1, .3, 1), translate 600ms cubic-bezier(.16, 1, .3, 1); }
  .vs-floor { opacity: .35; transition: opacity 600ms; }
  .vs-cert { opacity: 0; transform: translate(-150px, 40px) scale(.42) rotateY(-28deg); transition: opacity 500ms, transform 700ms cubic-bezier(.2, .8, .2, 1); }
  .vs-bot { transform: rotateX(-178deg); transition: transform 520ms cubic-bezier(.3, .7, .2, 1) 420ms; }
  .vs-read { translate: 0 14px; transition: opacity 420ms 250ms, translate 520ms cubic-bezier(.16, 1, .3, 1) 250ms; }
  .vs-ret { scale: 1.35; transition: opacity 260ms, scale 360ms cubic-bezier(.16, 1, .3, 1); }
  .vs-tag { translate: -8px 0; transition: opacity 280ms 120ms, translate 380ms cubic-bezier(.16, 1, .3, 1) 120ms; }
  .vs-hl { scale: 1.6; transition: opacity 240ms 900ms, scale 380ms cubic-bezier(.2, .7, .2, 1) 900ms; }

  .vs.s-in .vs-vial { opacity: 1; translate: 0 0; }
  .vs.s-in .vs-floor { opacity: 1; }
  .vs.s-scan .vs-laser { opacity: 1; animation: vs-laser-fade 1300ms linear both; }
  .vs.s-scan .vs-laser i { animation: vs-laser 1300ms cubic-bezier(.45, 0, .25, 1) both; }
  .vs.s-scan .vs-glare { animation: vs-glare 1300ms cubic-bezier(.45, 0, .25, 1) both; }
  .vs.s-read .vs-ret, .vs.s-read .vs-tag { opacity: 1; scale: 1; translate: 0 0; }
  .vs.s-unfold .vs-cert { opacity: 1; transform: none; }
  .vs.s-unfold .vs-bot { transform: rotateX(0deg); }
  .vs.s-unfold .vs-bot::after { opacity: 0; }
  .vs.s-lock .vs-cbeam i { animation: vs-cbeam 900ms cubic-bezier(.45, 0, .25, 1) both; }
  .vs.s-lock .vs-hl { opacity: 1; scale: 1; }
  .vs.s-lock .vs-read { opacity: 1; translate: 0 0; }
  .vs.s-out .vs-vial { opacity: 0; translate: -24px 0; transition-duration: 420ms; }
  .vs.s-out .vs-cert { opacity: 0; transform: translate(30px, -10px) scale(.94); transition-duration: 420ms; }
  .vs.s-out .vs-read, .vs.s-out .vs-ret, .vs.s-out .vs-tag, .vs.s-out .vs-hl { opacity: 0; transition-delay: 0ms; transition-duration: 260ms; }
  .vs.s-reset *, .vs.s-reset *::after { transition: none !important; animation: none !important; }
}
@keyframes vs-laser { 0% { translate: 0 34%; } 62% { translate: 0 92%; } 100% { translate: 0 61%; } }
@keyframes vs-laser-fade { 0% { opacity: 0; } 8% { opacity: 1; } 88% { opacity: 1; } 100% { opacity: 0; } }
@keyframes vs-glare { 0% { opacity: 0; } 20% { opacity: 1; } 80% { opacity: .6; } 100% { opacity: 0; } }
@keyframes vs-cbeam { 0% { translate: 0 0; opacity: 0; } 10% { opacity: 1; } 85% { opacity: 1; } 100% { translate: 0 calc(var(--by) * 100%); opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  .vs-ret, .vs-tag, .vs-hl, .vs-read { opacity: 1; }
  .vs-laser, .vs-glare { display: none; }
}

/* ---------- tablet / phone ---------- */
@media (max-width: 1023px) { .ch-vial .ch-stage.vs { max-width: 620px; } }
@media (max-width: 599px) {
  .vs-scene { height: 420px; }
  .vs-floor { left: -6%; width: 64%; height: 64px; }
  .vs-vial { left: 2%; bottom: 30px; height: 350px; }
  .vs-cert { left: 44%; top: 6px; width: 54%; }
  .vs-read { right: -2%; top: 228px; width: 60%; padding: 12px 14px; border-radius: 14px; }
  .vs-pur { font-size: 2.3rem; }
  .vs-tag { left: 70%; top: 76%; font-size: 9px; }
  .vs-tag::before { display: none; }
  .vs-info { flex-wrap: wrap; }
  .vs-info .ch-open { width: 100%; justify-content: center; }
}
/* the label tag has done its job once the reading locks; the readout takes that space */
@media (prefers-reduced-motion: no-preference) { .vs.s-lock .vs-tag { opacity: 0; translate: 6px 0; transition-delay: 0ms; } }
@media (prefers-reduced-motion: reduce) { .vs-tag { display: none; } }
@media (max-width: 599px) { .vs-read { width: 50%; right: -2%; } .vs-pur { font-size: 2.1rem; } }
@media (min-width: 600px) { .vs-read { right: 0; } }
