/* jcamd.com — motion layer.
 *
 * Personality: Corporate / rigid material. The drafting-board theme is a
 * different palette from the vector-X family but the same construction:
 * 2px ink borders and hard offset block shadows with no blur. Motion is
 * therefore decisive and lands flat — zero overshoot. Elastic or bouncy
 * easing would read as a softer material than the borders imply.
 *
 * Three layers:
 *   primary   — the element rises and fades into place.
 *   secondary — the block shadow lifts on hover and presses in on click,
 *               which is physically coherent with a hard offset shadow.
 *   ambient   — only the existing loading shimmer, which is a status signal
 *               rather than decoration.
 *
 * Colour, type and layout are untouched by this file. It is loaded last so
 * its easing wins ties against the bare `100ms` transitions in site.css.
 */

:root{
  /* Signature curves. One standard, one emphasized, one exit. */
  --ease-standard:   cubic-bezier(.2, 0, 0, 1);   /* interaction, on-screen */
  --ease-emphasized: cubic-bezier(.16, 1, .3, 1); /* expo.out — entrances */
  --ease-exit:       cubic-bezier(.3, 0, 1, 1);   /* accelerate — dismissal */

  /* Duration palette. */
  --dur-quick: 90ms;   /* hover + press, under the 100ms feedback floor */
  --dur-base:  260ms;  /* cards and panels */
  --dur-slow:  420ms;  /* modals and page-level reveals */

  /* Choreography. */
  --vx-stagger: 50ms;  /* 6 steps = 300ms, inside the 500ms budget */
  --vx-rise:    12px;  /* entrance travel */
  --vx-lift:     2px;  /* hover displacement */
}

/* ---------- primary: entrance ----------
 * Opacity is never the only channel; position carries the change too. */
@keyframes vx-rise{
  from{ opacity:0; transform:translateY(var(--vx-rise)); }
  to  { opacity:1; transform:none; }
}

.vx-rise{ animation: vx-rise var(--dur-base) var(--ease-emphasized) both; }

/* Cascade. Capped at six steps so the tail never outruns the budget. */
[data-vx-stagger] > *{
  animation: vx-rise var(--dur-base) var(--ease-emphasized) both;
}
[data-vx-stagger] > :nth-child(1){ animation-delay: 0ms; }
[data-vx-stagger] > :nth-child(2){ animation-delay: calc(var(--vx-stagger) * 1); }
[data-vx-stagger] > :nth-child(3){ animation-delay: calc(var(--vx-stagger) * 2); }
[data-vx-stagger] > :nth-child(4){ animation-delay: calc(var(--vx-stagger) * 3); }
[data-vx-stagger] > :nth-child(5){ animation-delay: calc(var(--vx-stagger) * 4); }
[data-vx-stagger] > :nth-child(n+6){ animation-delay: calc(var(--vx-stagger) * 5); }

/* ---------- secondary: lift and press ----------
 * site.css already had this shape on .btn and .repo-card; this only
 * replaces the bare `100ms` with the signature curve and duration token,
 * and extends the same treatment to the other card surfaces. */
.btn,
.repo-card,
.job-card,
.service-card,
.card{
  transition: transform  var(--dur-quick) var(--ease-standard),
              box-shadow var(--dur-quick) var(--ease-standard);
}

/* Colour-only changes get a colour-only transition. */
.site-nav a,
.site-nav .nav-cta,
.site-footer__list a{
  transition: color            var(--dur-quick) var(--ease-standard),
              background-color var(--dur-quick) var(--ease-standard);
}

/* Focus rings must not ease in — a keyboard user needs the ring immediately. */
a:focus-visible,
button:focus-visible{ transition: none; }

/* ---------- reduced motion ----------
 * site.css gated three named selectors. This widens the gate to everything,
 * including the infinite `shimmer` loop and anything added later. */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .vx-rise,
  [data-vx-stagger] > *{ opacity:1; transform:none; }
}
