/* =========================================================
   Motion layer: text reveals, word-by-word headings, language
   switch, micro-interactions. Loaded after base.css on every page.
   (Word splitting and counters: js/motion.js. Language fade: js/i18n.js.)
   ========================================================= */

/* ---- Blocks & paragraphs: rise out of a soft blur ---- */
.js .reveal {
  filter: blur(8px);
  transition:
    opacity 1s var(--ease-out) var(--d, 0s),
    transform 1s var(--ease-out) var(--d, 0s),
    filter 1s var(--ease-out) var(--d, 0s);
}
.js .reveal.is-in { filter: none; }

/* A block whose heading is split: the words carry the entrance, the paragraph follows */
.js .reveal.split,
.js .reveal:has(> .split) { opacity: 1; transform: none; filter: none; }
.js .reveal:has(> .split) > .lead {
  opacity: 0;
  transform: translateY(16px);
  filter: blur(6px);
  transition:
    opacity 1s var(--ease-out) calc(var(--d, 0s) + 0.35s),
    transform 1s var(--ease-out) calc(var(--d, 0s) + 0.35s),
    filter 1s var(--ease-out) calc(var(--d, 0s) + 0.35s);
}
.js .reveal.is-in > .lead { opacity: 1; transform: none; filter: none; }

/* Hero entrance (base.css .rise) gains the same blur */
@keyframes vd-rise {
  from { opacity: 0; transform: translateY(18px); filter: blur(8px); }
  to { opacity: 1; transform: none; filter: none; }
}

/* ---- Headings, word by word ---- */
.js .split .w {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.55em) rotate(4deg);
  transform-origin: 0 100%;
  filter: blur(12px);
  transition:
    opacity 0.9s var(--ease-out),
    transform 1.1s var(--ease-out),
    filter 0.9s var(--ease-out);
  transition-delay: calc(var(--d, 0s) + var(--wi, 0) * 70ms);
}
.js .is-in .w { opacity: 1; transform: none; filter: none; }

/* After a language switch the new words replay immediately */
.js .split--replay .w {
  animation: word-in 0.75s var(--ease-out) both;
  animation-delay: calc(var(--wi, 0) * 40ms);
}
@keyframes word-in {
  from { opacity: 0; transform: translateY(0.4em) rotate(3deg); filter: blur(10px); }
  to { opacity: 1; transform: none; filter: none; }
}

/* ---- Language toggle: sliding thumb ---- */
.lang { position: relative; }
.lang::before {
  content: "";
  position: absolute; top: 3px; bottom: 3px; left: 3px;
  width: 40px;
  border-radius: 999px;
  background: rgba(201, 182, 255, 0.18);
  box-shadow: 0 0 18px rgba(201, 182, 255, 0.25);
  transition: transform 0.5s cubic-bezier(0.3, 1.4, 0.5, 1);
}
.lang[data-active="en"]::before { transform: translateX(40px); }
.lang button { position: relative; z-index: 1; width: 40px; min-width: 0; padding: 0; }
.lang button[aria-pressed="true"] { background: transparent; }

/* ---- Scroll progress line under the nav ---- */
.site-nav::after {
  content: "";
  position: absolute; left: 0; bottom: -1px;
  width: 100%; height: 1px;
  background: linear-gradient(90deg, var(--bio), var(--accent));
  box-shadow: 0 0 8px rgba(143, 227, 168, 0.6);
  transform-origin: 0 50%;
  transform: scaleX(var(--progress, 0));
  pointer-events: none;
}

/* ---- Primary button: light sweep on hover ---- */
.btn--primary { position: relative; overflow: hidden; isolation: isolate; }
.btn--primary::after {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(110deg, transparent 30%, rgba(201, 182, 255, 0.55) 50%, transparent 70%);
  transform: translateX(-120%);
  transition: transform 0.9s var(--ease-out);
}
.btn--primary:hover::after { transform: translateX(120%); }

/* ---- Nav links: growing underline (desktop) ---- */
@media (min-width: 861px) {
  .nav-links a:not(.btn) { position: relative; }
  .nav-links a:not(.btn)::after {
    content: "";
    position: absolute; left: 0; right: 0.24em; bottom: -6px;
    height: 1px;
    background: linear-gradient(90deg, var(--bio), var(--accent));
    transform: scaleX(0);
    transform-origin: 0 50%;
    transition: transform 0.45s var(--ease-out);
  }
  .nav-links a:not(.btn):hover::after { transform: scaleX(1); }
}

/* ---- Project cards: lift on hover (translate, so it doesn't fight the reveal transform) ---- */
.js .specimen.reveal {
  filter: none;
  transition:
    opacity 1s var(--ease-out) var(--d, 0s),
    transform 1s var(--ease-out) var(--d, 0s),
    translate 0.5s var(--ease-out),
    box-shadow 0.4s;
}
.specimen:hover { translate: 0 -6px; }
.js .certs.reveal { filter: none; }

/* ---- Form chips: small pop when selected ---- */
.chip input:checked + span { animation: chip-pop 0.35s var(--ease-out); }
@keyframes chip-pop {
  40% { transform: scale(1.06); }
}

@media (prefers-reduced-motion: reduce) {
  .js .reveal,
  .js .reveal > .lead,
  .js .split .w { opacity: 1; transform: none; filter: none; transition: none; animation: none; }
  .lang::before, .btn--primary::after { transition: none; }
}
