/* Micro-interactions layered on top of site.css / header.css (driven by js/interactions.js and,
   for the moon, js/header.js). Loaded after css/header.css so its rules can extend the header's.
   Everything that follows the pointer runs only where a fine pointer can hover; under reduced
   motion the decorative motion is switched off and only colour/opacity feedback remains. */

:root {
  --ix-ease: cubic-bezier(.16,1,.3,1);      /* long, soft settle */
  --ix-ease-io: cubic-bezier(.65,0,.35,1);  /* symmetric, for there-and-back moves */
}

/* ============ SMOOTHER BASE MOTION ============
   Same properties site.css and the pages already transition, eased out over longer. */
.rp-btn, .rp-header .rp-btn, .rp-fbtn, .rp-case__cta { transition-duration: .45s; transition-timing-function: var(--ix-ease); }
.back, .back__arrow, .next-link, .next-link__arrow, .rp-ext, .rp-header .rp-ext, .rp-footer__name {
  transition-duration: .55s; transition-timing-function: var(--ix-ease);
}
.rp-tl-card, .rp-case__img, .rp-case__laptop-stage, .img-hover, .cs-img, .feat-card {
  transition-duration: .8s; transition-timing-function: var(--ix-ease);
}
.rp-header { transition-duration: .7s; transition-timing-function: var(--ix-ease); }
@media (prefers-reduced-motion: no-preference) {
  .reveal, [data-reveal], .reveal-group > *, [data-reveal-group] > * { transition-duration: 1.1s; transition-timing-function: var(--ix-ease); }
  .rv, .rv2, .rv3 { animation-duration: 1.2s; animation-timing-function: var(--ix-ease); }
}

/* ============ RIPPLE (buttons) ============ */
.ix-ripple-host { overflow: hidden; isolation: isolate; }
.ix-ripple {
  position: absolute; z-index: -1; pointer-events: none;
  width: 8px; height: 8px; margin: -4px 0 0 -4px; border-radius: 50%;
  background: currentColor; opacity: .18;
  animation: ixRipple 1s var(--ix-ease) forwards;
}
@keyframes ixRipple { to { transform: scale(var(--ix-r, 40)); opacity: 0; } }

/* ============ HERO ============ */
/* .ix-play is added by js and removed when the animation ends, so leaving the element never restarts it */
/* the 👋 waves after the name has typed in, and again on hover */
.rp-hello span { display: inline-block; transform-origin: 70% 80%; }
.rp-hello span.ix-play { animation: ixWave 1.8s var(--ix-ease-io); }
@keyframes ixWave {
  0%, 100% { transform: rotate(0); }
  15% { transform: rotate(14deg); }
  30% { transform: rotate(-6deg); }
  45% { transform: rotate(12deg); }
  60% { transform: rotate(-3deg); }
  75% { transform: rotate(5deg); }
}

/* the main line appears letter by letter (js wraps each word in .ix-word and each letter in .ix-ch, --i = its order) */
.ix-word { white-space: nowrap; }
.ix-ch {
  display: inline-block; opacity: 0; transform: translateY(.35em); filter: blur(8px);
  animation: ixLetter 1s var(--ix-ease) forwards;
  animation-delay: calc(var(--i) * 45ms + 150ms);
}
@keyframes ixLetter { to { opacity: 1; transform: none; filter: none; } }
/* each gradient letter carries its own slice of the name's gradient (--gw / --gx set by js), since a
   transformed child would drop out of its parent's background-clip: text. The padding keeps descenders
   inside the clip; the matching negative margin keeps the layout unchanged. */
.rp-h1 .grad.ix-split { background: none; }
.rp-h1 .grad.ix-split .ix-ch {
  background-image: linear-gradient(100deg,#105666 5%,#839958 55%,#D4714A 110%);
  background-repeat: no-repeat; background-size: var(--gw, 100%) 100%; background-position: var(--gx, 0) 0;
  -webkit-background-clip: text; background-clip: text;
  padding: 0 .06em .22em; margin: 0 -.06em -.22em;
}

/* ============ HEADER ============ */
/* the moon turns toward the cursor (js/header.js draws it on a canvas) */
.rp-header .rp-moon { transition-duration: .55s; transition-timing-function: var(--ix-ease); }
.rp-header .rp-moon canvas { display: block; width: 100%; height: 100%; }
.rp-header .rp-moon:hover { transform: scale(1.1); }
.rp-header .rp-moon:active { transform: scale(.92); transition-duration: .18s; }
.rp-header .rp-btn:active { transform: scale(.95); transition-duration: .18s; }

/* ============ TIMELINE ============ */
/* the current role's dot breathes */
.rp-timeline__grid > div:first-child .rp-tl-dot::after {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  background: inherit; animation: ixPulse 3s var(--ix-ease) infinite;
}
@keyframes ixPulse { 0% { transform: scale(1); opacity: .5; } 85%, 100% { transform: scale(2.6); opacity: 0; } }
.rp-tl-dot { transition: transform .6s var(--ix-ease); }
@media (hover: hover) { .rp-timeline__grid > div:hover .rp-tl-dot { transform: scale(1.25); } }

/* ============ CASE CARDS ============ */
/* the tape label peels up a little when the card is hovered */
.tape-tag { transition: transform .7s var(--ix-ease); }
@media (hover: hover) {
  .rp-case__frame:hover .tape-tag, .showcase:hover .tape-tag { transform: rotate(-6deg) translate(-2px,-3px); }
}
/* the arrow in "View Project" glides out and back in */
.rp-case__cta span { display: inline-block; }
.rp-case__cta span.ix-play { animation: ixArrow .9s var(--ix-ease-io); }
@keyframes ixArrow {
  0% { transform: none; opacity: 1; }
  45% { transform: translateX(10px); opacity: 0; }
  46% { transform: translateX(-8px); opacity: 0; }
  100% { transform: none; opacity: 1; }
}

/* ============ INLINE LINKS ============ */
/* underline that redraws itself on hover */
.body-text a, .body-lg a, .lead a, .body-sm a {
  text-decoration: none;
  background: linear-gradient(currentColor, currentColor) 0 100% / 100% 1px no-repeat;
  padding-bottom: 1px;
}
@media (hover: hover) {
  .body-text a:hover, .body-lg a:hover, .lead a:hover, .body-sm a:hover { animation: ixUnderline .9s var(--ix-ease-io); }
}
@keyframes ixUnderline {
  0% { background-size: 100% 1px; background-position: 100% 100%; }
  50% { background-size: 0 1px; background-position: 100% 100%; }
  51% { background-size: 0 1px; background-position: 0 100%; }
  100% { background-size: 100% 1px; background-position: 0 100%; }
}

/* ============ BACK TO TOP (with a scroll-progress ring) ============ */
.ix-top {
  position: fixed; right: 20px; bottom: 20px; z-index: 70;
  width: 48px; height: 48px; padding: 0; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer;
  color: var(--ink); background: rgba(245,242,232,.72);
  -webkit-backdrop-filter: blur(16px) saturate(180%); backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(10,51,35,.08);
  box-shadow: 0 10px 26px -12px rgba(10,51,35,.35);
  opacity: 0; transform: translateY(12px) scale(.9); pointer-events: none;
  transition: opacity .6s var(--ix-ease), transform .6s var(--ix-ease), box-shadow .4s var(--ix-ease);
}
.ix-top.is-shown { opacity: 1; transform: none; pointer-events: auto; }
.ix-top svg { position: absolute; inset: 3px; width: calc(100% - 6px); height: calc(100% - 6px); transform: rotate(-90deg); }
.ix-top circle { fill: none; stroke-width: 2; }
.ix-top .ix-top__track { stroke: rgba(10,51,35,.1); }
.ix-top .ix-top__bar { stroke: var(--teal); stroke-linecap: round; transition: stroke-dashoffset .35s ease-out; }
.ix-top__arrow { position: relative; font-size: 16px; line-height: 1; transition: transform .5s var(--ix-ease); }
@media (hover: hover) {
  .ix-top.is-shown:hover { box-shadow: 0 16px 32px -12px rgba(10,51,35,.45); }
  .ix-top:hover .ix-top__arrow { transform: translateY(-3px); }
}
.ix-top.is-shown:active { transform: scale(.92); transition-duration: .18s; }

/* ============ PASSWORD PAGE ============ */
.wake-button { position: relative; }

/* ============ REDUCED MOTION ============ */
@media (prefers-reduced-motion: reduce) {
  .rp-timeline__grid > div:first-child .rp-tl-dot::after,
  .body-text a:hover, .body-lg a:hover, .lead a:hover, .body-sm a:hover { animation: none; }
  .ix-ripple { display: none; }
  .rp-header .rp-moon:hover, .rp-header .rp-moon:active { transform: none; }
  .ix-top { transform: none; }
}
