/* Amproteq Studio — the motion layer.
 *
 * Keyframes, reveal states and the shimmer, in one file so that no screen
 * invents its own easing curve. The imperative half lives in
 * web/js/ui/motion.js; this file holds only what is cheaper as CSS: infinite
 * loops (a pulse, a shimmer) and states a class can toggle.
 *
 * The site's ease is expo-out, cubic-bezier(.16,1,.3,1) — `--ease` in
 * tokens.css. Everything that appears should arrive; nothing should pop.
 *
 * Every animation here is disabled wholesale in the reduced-motion block at
 * the bottom of the file, so a new keyframe cannot be added without also
 * being covered by it. */

/* ── The cyan pulse ───────────────────────────────────────────────────────
 * The marketing site's navLive keyframe. Live and connected states ONLY —
 * a pulse that means "this is current" stops meaning anything the moment it
 * is spent on decoration. */

@keyframes amp-pulse {
  0%, 100% { opacity: 1;    box-shadow: 0 0 0 0 rgba(60, 204, 252, 0.45); }
  50%      { opacity: 0.72; box-shadow: 0 0 0 5px rgba(60, 204, 252, 0); }
}

.pulse-dot {
  width: 6px;
  height: 6px;
  border-radius: var(--r-full);
  background: var(--cyan);
  flex: none;
  animation: amp-pulse 2.4s var(--ease-in-out) infinite;
}
.pulse-dot.is-idle { background: var(--text-faint); animation: none; box-shadow: none; }

/* ── Shimmer ──────────────────────────────────────────────────────────────
 * The skeleton's travelling highlight. A skeleton is a placeholder of the
 * right SHAPE — never a spinner over an empty pane, and never something that
 * changes size when the data lands. */

@keyframes amp-shimmer {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(220%); }
}

.skeleton { display: grid; gap: var(--sp-3); }
.skeleton-line,
.skeleton-block {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-2);
  background: var(--bg-surface-2);
}
.skeleton-line::after,
.skeleton-block::after {
  content: '';
  position: absolute;
  inset: 0;
  width: 44%;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(150, 190, 255, 0.11),
    transparent
  );
  animation: amp-shimmer 1.45s var(--ease-in-out) infinite;
}

.skeleton.is-grid { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: var(--sp-3); }
.skeleton.is-tiles { grid-auto-flow: column; grid-auto-columns: 1fr; gap: var(--sp-3); }
.skeleton.is-chart { gap: var(--sp-2); align-content: end; grid-auto-flow: column; grid-auto-columns: 1fr; }
.skeleton.is-chart .skeleton-block { align-self: end; }

/* ── Reveal ───────────────────────────────────────────────────────────────
 * motion.js drives reveals through the Web Animations API, so nothing is
 * left on the element afterwards. This class exists for the one case WAAPI
 * cannot cover: content that must be hidden from the very first paint,
 * before any script has run. `revealStagger()` clears it. */

.rv-pending { opacity: 0; }

/* ── Gradient sweep ───────────────────────────────────────────────────────
 * The brand signature moving across a surface on hover. Used by the landing
 * doors and the primary button; spent nowhere else. */

@keyframes amp-sweep {
  0%   { background-position: 180% 0; }
  100% { background-position: -80% 0; }
}

.sweep-text {
  background: linear-gradient(
    100deg,
    var(--text) 0%, var(--text) 38%,
    var(--cyan-lt) 50%,
    var(--text) 62%, var(--text) 100%
  );
  background-size: 260% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: amp-sweep 3.6s var(--ease-in-out) infinite;
}

/* ── Scan line ────────────────────────────────────────────────────────────
 * The door glyphs' one moving part: a hairline that travels the glyph like
 * a scanner bar. Cheap, transform-only, and it stops the two doors reading
 * as static clip-art. */

@keyframes amp-scan {
  0%   { transform: translateY(-2px); opacity: 0; }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { transform: translateY(26px); opacity: 0; }
}

.scan-line { animation: amp-scan 2.8s var(--ease-in-out) infinite; }

/* ── Route pane ───────────────────────────────────────────────────────────
 * transitionPane() animates with WAAPI; these two classes only guarantee the
 * transform origin and that a pane mid-transition cannot capture a click. */

.pane-leaving { pointer-events: none; }
.pane-entering { pointer-events: none; }

/* ══════════════════════════════════════════════════════════════════════════
   REDUCED MOTION
   One block, covering every keyframe above. A new animation added to this
   file must also be named here.
═══════════════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  .pulse-dot,
  .skeleton-line::after,
  .skeleton-block::after,
  .sweep-text,
  .scan-line {
    animation: none !important;
  }
  .sweep-text {
    background: none;
    -webkit-text-fill-color: var(--text);
    color: var(--text);
  }
  .skeleton-line::after,
  .skeleton-block::after { opacity: 0.5; transform: none; width: 100%; }
  .rv-pending { opacity: 1; }
}
