/* ============================================================
   VIVTAG — motion + depth layer
   Design thesis: this product turns paper into something live.
   So the motion language is paper: things STAMP, cards are DEALT,
   plates are PUNCHED character by character, and expiry counts
   down where you can see it. Nothing floats for decoration.
   Still zero dependencies.
   ============================================================ */

/* ---------- 1. reveal on scroll ---------------------------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity .62s cubic-bezier(.16, 1, .3, 1),
    transform .62s cubic-bezier(.16, 1, .3, 1);
  transition-delay: calc(var(--i, 0) * 70ms);
  will-change: opacity, transform;
}
[data-reveal].is-in { opacity: 1; transform: none; }

[data-reveal="left"]  { transform: translateX(-22px); }
[data-reveal="right"] { transform: translateX(22px); }
[data-reveal="scale"] { transform: scale(.955); }
[data-reveal="blur"]  { filter: blur(7px); transition: opacity .7s ease, filter .7s ease, transform .7s cubic-bezier(.16,1,.3,1); }
[data-reveal].is-in   { filter: none; }

/* ---------- 2. the stamp -----------------------------------
   A verification verdict lands like a rubber stamp, because
   that is exactly what it is.                                 */
@keyframes vt-stamp {
  0%   { opacity: 0; transform: scale(1.75) rotate(-13deg); }
  55%  { opacity: 1; transform: scale(.94) rotate(1.5deg); }
  75%  { transform: scale(1.03) rotate(-.8deg); }
  100% { opacity: 1; transform: scale(1) rotate(0); }
}
.is-stamped { animation: vt-stamp .52s cubic-bezier(.3, 1.3, .4, 1) both; }

@keyframes vt-stamp-ink {
  0%   { box-shadow: 0 0 0 0 currentColor; opacity: .35; }
  100% { box-shadow: 0 0 0 14px transparent; opacity: 0; }
}
.is-stamped::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  animation: vt-stamp-ink .6s ease-out both; pointer-events: none;
}

/* ---------- 3. the plate punches itself in ------------------ */
.plate__chars > .ch {
  display: inline-block;
  opacity: 0;
  transform: translateY(-9px) scale(1.22);
  animation: vt-punch .34s cubic-bezier(.2, 1.4, .35, 1) forwards;
  animation-delay: calc(var(--n) * 52ms);
}
@keyframes vt-punch {
  60%  { opacity: 1; transform: translateY(2px) scale(.97); }
  100% { opacity: 1; transform: none; }
}
.plate__chars > .sp { display: inline-block; width: .3em; }

/* the IND strip lights only once the number resolves */
.plate[data-state="valid"] .plate__ind { animation: vt-ind .5s ease both .18s; }
@keyframes vt-ind {
  from { filter: brightness(.55) saturate(.5); }
  to   { filter: none; }
}

/* ---------- 4. compliance ring ------------------------------
   One number a driver actually cares about: days until the next
   thing on this vehicle lapses.                                */
.vt-ring { position: relative; width: 76px; height: 76px; flex: 0 0 76px; }
.vt-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); display: block; }
.vt-ring circle { fill: none; stroke-width: 6; stroke-linecap: round; }
.vt-ring .track { stroke: var(--line); }
.vt-ring .bar {
  stroke: var(--stamp);
  stroke-dasharray: var(--circ);
  stroke-dashoffset: var(--circ);
  transition: stroke-dashoffset 1.1s cubic-bezier(.16, 1, .3, 1), stroke .4s ease;
}
.vt-ring[data-tone="hold"] .bar { stroke: var(--hold); }
.vt-ring[data-tone="bad"]  .bar { stroke: var(--void); }
.vt-ring[data-tone="idle"] .bar { stroke: var(--ink-300); }
.vt-ring__mid {
  position: absolute; inset: 0;
  display: grid; place-content: center; text-align: center; line-height: 1.05;
}
.vt-ring__num { font-family: var(--data); font-size: 19px; font-weight: 700; }
.vt-ring__lbl { font-size: 8.5px; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-500); }
.vt-ring--sm { width: 46px; height: 46px; flex-basis: 46px; }
.vt-ring--sm circle { stroke-width: 5; }
.vt-ring--sm .vt-ring__num { font-size: 13px; }
.vt-ring--sm .vt-ring__lbl { font-size: 7px; }

/* ---------- 5. counting numbers ----------------------------- */
.vt-count { font-variant-numeric: tabular-nums; }

/* ---------- 6. dealt cards ---------------------------------- */
@keyframes vt-deal {
  from { opacity: 0; transform: translateY(20px) rotate(var(--tilt, -1.5deg)) scale(.97); }
  to   { opacity: 1; transform: none; }
}
.is-dealt { animation: vt-deal .5s cubic-bezier(.16, 1, .3, 1) both; animation-delay: calc(var(--i, 0) * 80ms); }

/* ---------- 7. press + lift --------------------------------- */
.vt-btn, .vp-veh, .vs-tile, .vt-doc {
  transition:
    transform .22s cubic-bezier(.16, 1, .3, 1),
    box-shadow .22s ease,
    border-color .18s ease,
    background .16s ease;
}
.vt-btn:active { transform: translateY(1px) scale(.985); }
.vt-btn--go, .vt-btn--ok {
  position: relative; overflow: hidden;
}
.vt-btn--go::after, .vt-btn--ok::after {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(circle at var(--rx, 50%) var(--ry, 50%), rgba(255,255,255,.4), transparent 55%);
  opacity: 0; transition: opacity .5s ease;
}
.vt-btn--go:hover::after, .vt-btn--ok:hover::after { opacity: 1; }

/* ---------- 8. sticky headers gain a shadow on scroll ------- */
.vt-top, .vs-nav { transition: box-shadow .3s ease, background .3s ease; }
.vt-top.is-stuck, .vs-nav.is-stuck { box-shadow: 0 1px 0 var(--line), 0 8px 24px rgba(18,20,26,.07); }

/* ---------- 9. skeletons ------------------------------------ */
.vt-skel {
  background: linear-gradient(90deg, var(--line-2) 25%, #e6e9ee 37%, var(--line-2) 63%);
  background-size: 400% 100%;
  animation: vt-shimmer 1.35s ease-in-out infinite;
  border-radius: 6px; color: transparent !important;
}
@keyframes vt-shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }

/* ---------- 10. page transition ----------------------------- */
@keyframes vt-page-in {
  from { opacity: 0; transform: translateY(9px); }
  to   { opacity: 1; transform: none; }
}
main, .vp-page, .vs-hero { animation: vt-page-in .42s cubic-bezier(.16, 1, .3, 1) both; }

/* ---------- 11. sparkline ----------------------------------- */
.vt-spark { display: block; width: 100%; height: 38px; overflow: visible; }
.vt-spark path.line {
  fill: none; stroke: var(--ind); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: var(--len); stroke-dashoffset: var(--len);
  animation: vt-draw 1.2s cubic-bezier(.16, 1, .3, 1) forwards .2s;
}
.vt-spark path.fill { fill: var(--ind-100); opacity: 0; animation: vt-fade .8s ease forwards .8s; }
@keyframes vt-draw { to { stroke-dashoffset: 0; } }
@keyframes vt-fade { to { opacity: 1; } }

/* ---------- 12. hero scan demo ------------------------------ */
.vs-card { position: relative; overflow: hidden; }
.vs-card__scan {
  position: absolute; left: 0; right: 0; height: 34%;
  background: linear-gradient(180deg, transparent, rgba(27,63,160,.14), transparent);
  animation: vt-scan 2.6s cubic-bezier(.5,0,.5,1) infinite;
  pointer-events: none;
}
@keyframes vt-scan {
  0%   { top: -34%; opacity: 0; }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { top: 100%; opacity: 0; }
}
.vs-row { transition: background .3s ease; }
.vs-row.is-hit { background: var(--ind-100); }

/* ---------- 13. numbered process rail ----------------------- */
.vs-steps { position: relative; }
.vs-steps::before {
  content: ""; position: absolute; left: 15px; top: 26px; bottom: 26px; width: 2px;
  background: linear-gradient(180deg, var(--ind), var(--ind-300));
  transform-origin: top; transform: scaleY(0);
  transition: transform 1.1s cubic-bezier(.16, 1, .3, 1);
}
.vs-steps.is-in::before { transform: scaleY(1); }
.vs-step::before {
  position: relative; z-index: 1;
  background: var(--card); border-radius: 50%;
  width: 32px; height: 32px; display: grid; place-items: center;
  border: 2px solid var(--ind-300);
}
.vs-sec--tint .vs-step::before { background: var(--paper); }

/* ---------- 14. reduced motion ------------------------------ */
@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1 !important; transform: none !important; filter: none !important; }
  .plate__chars > .ch { opacity: 1; transform: none; animation: none; }
  .vs-card__scan { display: none; }
  .vt-ring .bar { transition: none; }
  .vs-steps::before { transform: scaleY(1); }
  main, .vp-page, .vs-hero { animation: none; }
}
