/* ============================================================================
   VALERON RESEARCH -- motion layer: entrance + hover.
   CC_BRIEF_article_page.md section 8. Read the scroll-motion skill before
   changing this file (per the brief) -- summarizing its hard rules here so
   they stay visible next to the rules that implement them:

     - transform and opacity only. Never filter, width, top, height, or
       box-shadow directly.
     - No parallax on the article body. Text that moves while being read
       is hostile.
     - No custom cursor.
     - prefers-reduced-motion honored live, in both directions -- the
       @media block below zeroes every transition; motion.js additionally
       skips the IntersectionObserver entirely under that query (see its
       own comment for why a CSS-only opt-out is not enough for stagger
       delays already in flight).
     - One living element per section. Never five competing.
   ============================================================================ */

/* -------------------------------------------------------------- ENTRANCE -- */
/* The hidden starting state is gated on .v-js, set on <html> by a
   synchronous inline script in wp_head (functions.php). Motion is
   therefore opted INTO by JavaScript rather than opted out of: with
   JS unavailable, .v-motion-in never acquires an opacity of 0 in the
   first place, so there is no way for the article body to end up
   invisible to a reader or to a crawler that does not execute JS.
   (The earlier shape had the opposite default and a <noscript>
   override undoing it, which works but fails open only if you
   remember the override.)

   The gate must be set before first paint, which is why it is an
   inline head script and not motion.js -- motion.js is deferred to
   the footer, and adding the class there would paint the content
   visible and then snap it to hidden, a visible flash. */
.v-js .v-motion-in{
  opacity:0;
  transform:translateY(8px);
  transition:opacity var(--v-motion-base) var(--v-motion-ease),
             transform var(--v-motion-base) var(--v-motion-ease);
}
.v-js .v-motion-in.is-in{
  opacity:1;
  transform:translateY(0);
}

/* Grid stagger: motion.js sets `transition-delay` inline per sibling
   (60ms * index) before adding .is-in, then strips that inline delay on
   transitionend -- "delays must retire after the entrance" (brief),
   otherwise a later, unrelated transition on the same element (a hover
   state) would inherit a stale delay. Nothing else needed here; the
   delay is applied and removed entirely from JS, not from CSS selectors. */

/* ------------------------------------------------------------ CARD HOVER -- */
/* Applied to the hero cluster graphic panel. Border read from --v-rule
   at rest; a color-mix step darker on hover reads as "the same rule,
   focused" rather than a new color, keeping the state legible without
   encoding meaning in color alone (brief section 1, rule 4 -- this is a
   hover affordance, not a status). */
.v-motion-card{
  transition:border-color var(--v-motion-fast) var(--v-motion-ease);
}
.v-motion-card:hover{
  border-color:color-mix(in srgb, var(--v-rule) 55%, var(--v-ink-3));
}
.v-motion-card__graphic{
  transform:scale(1);
  transition:transform var(--v-motion-fast) var(--v-motion-ease);
}
.v-motion-card:hover .v-motion-card__graphic{
  transform:scale(1.02);
}

/* ------------------------------------------------------- RELATED HOVER -- */
/* The underline drawn by .v-art-related__link::after in research.css
   thickens via a transform (scaleY), never a color or width change. */
.v-art-related__link::after{
  transition:transform var(--v-motion-fast) var(--v-motion-ease);
}
.v-art-related__link:hover::after{
  transform:scaleY(3);
}

/* ----------------------------------------------------------- MASTHEAD -- */
/* The compact bar's reveal (opacity + translateY) lives in research.css
   next to the rest of its structural rules, since it is two states of
   one element rather than a reusable pattern applied elsewhere -- see
   that file's own note on why this is two elements (an in-flow big
   masthead, a fixed compact bar) rather than one animated height.
   No FILTER rule is added here on purpose -- transform and opacity are
   the entire budget for this file.
   ---------------------------------------------------------------------- */

/* ==================================================== MOTION OPT-OUT ==== */
@media (prefers-reduced-motion:reduce){
  .v-js .v-motion-in,
  .v-js .v-motion-in.is-in{
    opacity:1;
    transform:none;
    transition:none;
  }
  .v-motion-card,
  .v-motion-card__graphic,
  .v-art-related__link::after{
    transition:none;
  }
  .v-motion-card:hover .v-motion-card__graphic{
    transform:none;
  }
  .v-art-related__link:hover::after{
    transform:scaleY(1);
  }
}
