/* motion.css, VerifAIer premium motion system. Loaded after site.css, before page CSS.
 *
 * PRINCIPLES
 *   Motion is slow, heavy and deliberate. It exists to communicate that infrastructure is
 *   operating, never to decorate. Nothing here is required for the page to be usable or legible.
 *
 * THE HARD RULE
 *   Content is visible by default. The scroll-reveal base state applies ONLY under
 *   html[data-motion], a flag js/motion.js sets exclusively when motion is permitted. With no
 *   JavaScript, or under prefers-reduced-motion, the flag is never set and every element keeps its
 *   natural, visible state. site.css already carries a global reduced-motion killswitch, so this
 *   file is belt and braces: every animation here also degrades on its own.
 */

:root{
  --ease-out: cubic-bezier(.22, 1, .36, 1);   /* the site's existing curve, named */
  --ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --dur-1: 240ms;   /* microinteraction */
  --dur-2: 520ms;   /* reveal */
  --dur-3: 800ms;   /* deliberate reveal */
}
/* ── ambient background ──────────────────────────────────────────────────────
   A fixed layer behind everything. Two large, soft fields drift across minutes, not seconds. The
   movement is a few percent of the viewport: felt more than seen. */
body::before{
  content:'';
  position:fixed;
  inset:-20vmax;
  z-index:-2;
  pointer-events:none;
  background:
    radial-gradient(38vmax 38vmax at 18% 8%, rgba(0,229,160,.055), transparent 60%),
    radial-gradient(32vmax 32vmax at 88% 22%, rgba(96,165,250,.045), transparent 62%),
    radial-gradient(40vmax 40vmax at 60% 108%, rgba(167,139,250,.035), transparent 60%);
  animation: st-atmosphere 64s ease-in-out infinite alternate;
  will-change: transform;
}
@keyframes st-atmosphere{
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(1.5%, -1.5%, 0) scale(1.04); }
  100% { transform: translate3d(-1.5%, 1%, 0) scale(1.02); }
}
/* ── scroll reveal ───────────────────────────────────────────────────────────
   Inert until html[data-motion] is present. Elements the script marks as already-visible skip the
   hidden state entirely (is-in from the start), so nothing above the fold flashes. */
html[data-motion] .st-reveal{
  opacity:0;
  transform: translateY(14px);
  transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
  will-change: opacity, transform;
}
html[data-motion] .st-reveal.is-in{
  opacity:1;
  transform:none;
}
/* A short stagger inside a group, set by the script as a custom property. */
html[data-motion] .st-reveal{ transition-delay: var(--st-reveal-delay, 0ms); }
/* Once revealed, drop will-change so a long page does not hold dozens of layers. */
html[data-motion] .st-reveal.is-settled{ will-change:auto; }
/* ── microinteractions ───────────────────────────────────────────────────────
   Small, slow, and only on interactive things. */

/* Cards: a heavier, more expensive lift than the default, with a faint brand edge. */
.st-card{ transition: transform var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out); }
.st-card:hover{ transform: translateY(-3px); border-color: var(--line-strong); }
.st-card__link{ transition: gap var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out); }
.st-card__link svg{ transition: transform var(--dur-1) var(--ease-out); }
.st-card__link:hover svg{ transform: translateX(3px); }
/* Buttons: press has weight; the primary carries a slow, single sheen on hover. */
.st-btn{ transition: transform var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out); position:relative; overflow:hidden; }
.st-btn--primary::after{
  content:'';
  position:absolute; inset:0;
  background: linear-gradient(115deg, transparent 30%, rgba(255,255,255,.14) 50%, transparent 70%);
  transform: translateX(-120%);
  transition: transform var(--dur-3) var(--ease-out);
  pointer-events:none;
}
.st-btn--primary:hover::after{ transform: translateX(120%); }
.st-btn:active{ transform: translateY(0) scale(.985); }
/* Primary nav: a measured underline that grows from the left. */
.st-nav__menu > a{ position:relative; }
.st-nav__menu > a::after{
  content:''; position:absolute; left:0; right:0; bottom:-3px; height:1.5px;
  background: var(--brand); transform: scaleX(0); transform-origin:left;
  transition: transform var(--dur-1) var(--ease-out);
}
.st-nav__menu > a:hover::after,
.st-nav__menu > a[aria-current="page"]::after{ transform: scaleX(1); }
/* Table rows: a calm wash, not a flash. */
.st-cmp tbody tr,.st-eval tbody tr,.st-fieldtable tbody tr{ transition: background var(--dur-1) var(--ease-out); }
/* Code blocks: lift the border on hover so a long page of code still feels tactile. */
.st-code,.st-endpoint{ transition: border-color var(--dur-1) var(--ease-out); }
.st-code:hover,.st-endpoint:hover{ border-color: var(--line-strong); }
/* Trace tabs (from the demonstrations phase): the panel arrives, it does not just appear. */
html[data-motion] .st-trace.is-enhanced .st-trace__panel.is-shown{
  animation: st-panel-in var(--dur-2) var(--ease-out) both;
}
@keyframes st-panel-in{ from{ opacity:0; transform: translateY(6px); } to{ opacity:1; transform:none; } }
@keyframes st-breathe{ 0%,100%{ fill-opacity:.35; } 50%{ fill-opacity:.7; } }
@keyframes st-ring{ 0%,100%{ transform: scale(1); opacity:.3; } 50%{ transform: scale(1.35); opacity:0; } }
@keyframes st-signal{ 0%{ stroke-dashoffset:224; } 100%{ stroke-dashoffset:0; } }
/* ── reduced motion ──────────────────────────────────────────────────────────
   site.css already forces animation/transition off globally. This block additionally guarantees
   the two things that could leave a WRONG static state: the ambient layer is stilled, and the
   hero graph settles at its resting opacity rather than mid-keyframe. Reveal targets are never
   hidden here because html[data-motion] is not set under reduced motion in the first place. */

@media (prefers-reduced-motion: reduce){
  body::before{ animation:none; transform:none; }
}
