/* interaction-kit.css — the 12 feedback patterns (scroll · reveal · hover · click).
   Pair with interaction-kit.js. Behavior only: colors/fonts come from the host site via the vars below.
   Everything degrades to "content visible, nothing moving" without JS or under reduced motion. */

:root {
  --ik-accent: #3b5bfd;
  --ik-ease-out: cubic-bezier(.22, 1, .36, 1);   /* entrances, hovers */
  --ik-spring: cubic-bezier(.34, 1.56, .64, 1);  /* release after press: small overshoot */
  --ik-dur: .7s;
  --ik-lift: 24px;
  --ik-stagger: 70ms;
}

/* ───────── 02 · REVEAL — entrance builds hierarchy ───────── */

/* FADE + LIFT: simple, reliable, premium */
.ik-js [data-reveal="fade-lift"],
.ik-js [data-stagger] > * {
  opacity: 0;
  transform: translateY(var(--ik-lift));
  transition: opacity var(--ik-dur) var(--ik-ease-out), transform var(--ik-dur) var(--ik-ease-out);
  transition-delay: calc(var(--i, 0) * var(--ik-stagger));
}
.ik-js [data-reveal="fade-lift"].is-in,
.ik-js [data-stagger].is-in > * { opacity: 1; transform: none; }

/* STAGGER: children enter one after another (--i is set by JS) */

/* CLIP REVEAL: content gets uncovered from the reading-start edge */
.ik-js [data-reveal="clip"] {
  clip-path: inset(0 100% 0 0);
  transition: clip-path 1s var(--ik-ease-out);
}
.ik-js [data-reveal="clip"]:dir(rtl) { clip-path: inset(0 0 0 100%); }
.ik-js [data-reveal="clip"].is-in { clip-path: inset(0 0 0 0); }

/* WIPE: an accent block sweeps across, the text is there when it leaves */
.ik-js [data-reveal="wipe"] { position: relative; display: inline-block; }
.ik-js [data-reveal="wipe"]:not(.is-in) { color: transparent; }
.ik-js [data-reveal="wipe"].is-in { animation: ik-text-in 0s linear .45s both; }
.ik-js [data-reveal="wipe"]::after {
  content: ""; position: absolute; inset: 0;
  background: var(--ik-accent);
  transform: scaleX(0); pointer-events: none;
}
.ik-js [data-reveal="wipe"].is-in::after { animation: ik-wipe .9s var(--ik-ease-out) both; }
.ik-js [data-reveal="wipe"].is-in:dir(rtl)::after { animation-name: ik-wipe-rtl; }
@keyframes ik-text-in { from { color: transparent; } }
@keyframes ik-wipe {
  0%    { transform: scaleX(0); transform-origin: left; }
  50%   { transform: scaleX(1); transform-origin: left; }
  50.1% { transform: scaleX(1); transform-origin: right; }
  100%  { transform: scaleX(0); transform-origin: right; }
}
@keyframes ik-wipe-rtl {
  0%    { transform: scaleX(0); transform-origin: right; }
  50%   { transform: scaleX(1); transform-origin: right; }
  50.1% { transform: scaleX(1); transform-origin: left; }
  100%  { transform: scaleX(0); transform-origin: left; }
}

/* ───────── 01 · SCROLL — the page moves with you ───────── */

/* PARALLAX: JS writes transform on [data-parallax]. Put it on an inner layer,
   never on an element that owns other transforms. */
[data-parallax] { will-change: transform; }

/* SCRUB: JS writes --p (0→1) as the element crosses the viewport. Use it in CSS: */
.ik-scrub-track { position: relative; height: 2px; background: color-mix(in srgb, currentColor 25%, transparent); }
.ik-scrub-dot {
  position: absolute; inset-block-start: 50%; inset-inline-start: 0;
  width: 18px; height: 18px; border-radius: 50%; background: var(--ik-accent);
  translate: calc(var(--p, 0) * (var(--track-w, 300px) - 18px)) -50%;
}
.ik-scrub-dot:dir(rtl) { translate: calc(var(--p, 0) * (18px - var(--track-w, 300px))) -50%; }

/* PIN + TRANSFORM: section stays, content changes.
   <section data-pin="3"> gets 3 screens of scroll; its first child sticks. JS sets data-step. */
.ik-js [data-pin] { position: relative; height: calc(var(--ik-pin-steps, 3) * 100svh); }
.ik-js [data-pin] > :first-child { position: sticky; top: 0; height: 100svh; overflow: clip; }
.ik-js [data-pin] [data-step-show] { opacity: 0; transition: opacity .5s var(--ik-ease-out), transform .5s var(--ik-ease-out); transform: translateY(12px); }
.ik-js [data-pin][data-step="0"] [data-step-show~="0"],
.ik-js [data-pin][data-step="1"] [data-step-show~="1"],
.ik-js [data-pin][data-step="2"] [data-step-show~="2"],
.ik-js [data-pin][data-step="3"] [data-step-show~="3"],
.ik-js [data-pin][data-step="4"] [data-step-show~="4"] { opacity: 1; transform: none; }

/* ───────── 03 · HOVER — the cursor should feel something ───────── */

/* MAGNETIC CTA: JS moves [data-magnetic] with the independent `translate` property,
   so it composes with press/scale transforms. */
[data-magnetic] { will-change: translate; }

/* IMAGE ZOOM: the image moves, not the layout */
.ik-zoom { overflow: hidden; }
.ik-zoom > img, .ik-zoom > video, .ik-zoom > svg, .ik-zoom > picture { display: block; width: 100%; transition: transform .9s var(--ik-ease-out); }
@media (hover: hover) and (pointer: fine) {
  .ik-zoom:hover > img, .ik-zoom:hover > video, .ik-zoom:hover > svg, .ik-zoom:hover > picture { transform: scale(1.06); }
}

/* TEXT SHIFT: underline draws from the reading-start edge, label tints, arrow nudges */
.ik-link {
  display: inline-flex; align-items: baseline; gap: .45em;
  color: inherit; text-decoration: none;
  background: linear-gradient(currentColor, currentColor) no-repeat;
  background-size: 100% 1px; background-position: 0 100%;
  padding-block-end: .15em;
  transition: color .3s var(--ik-ease-out), background-size .45s var(--ik-ease-out);
}
.ik-link:dir(rtl) { background-position: 100% 100%; }
.ik-link .ik-arrow { display: inline-block; transition: transform .35s var(--ik-ease-out); }
.ik-link:dir(rtl) .ik-arrow { scale: -1 1; }
@media (hover: hover) and (pointer: fine) {
  .ik-link { background-size: 0% 1px; }
  .ik-link:hover, .ik-link:focus-visible { color: var(--ik-accent); background-size: 100% 1px; }
  .ik-link:hover .ik-arrow, .ik-link:focus-visible .ik-arrow { transform: translateX(4px); }
  .ik-link:dir(rtl):hover .ik-arrow, .ik-link:dir(rtl):focus-visible .ik-arrow { transform: translateX(-4px); }
}

/* ───────── 04 · CLICK — every click gets a response ───────── */

/* PRESS + SPRING: compress fast, spring back with overshoot */
.ik-press { transition: transform .5s var(--ik-spring); }
.ik-press:active { transform: scale(.95); transition: transform .08s ease-out; }

/* STATE CHANGE: idle → busy → done (or error). JS drives data-state. */
[data-state-button] { position: relative; transition: background-color .3s, color .3s, transform .5s var(--ik-spring); }
[data-state-button][data-state="busy"] { cursor: progress; }
[data-state-button][data-state="busy"] .ik-label::before {
  content: ""; display: inline-block; width: .9em; height: .9em; margin-inline-end: .5em;
  border: 2px solid currentColor; border-inline-end-color: transparent; border-radius: 50%;
  vertical-align: -.12em; animation: ik-spin .7s linear infinite;
}
[data-state-button] .ik-label { display: inline-block; }
[data-state-button][data-state="done"] .ik-label { animation: ik-pop .45s var(--ik-spring); }
@keyframes ik-spin { to { rotate: 1turn; } }
@keyframes ik-pop { from { transform: scale(.85); opacity: .4; } }

/* ───────── Reduced motion: content in place, state still communicated ───────── */
@media (prefers-reduced-motion: reduce) {
  .ik-js [data-reveal], .ik-js [data-stagger] > * {
    opacity: 1 !important; transform: none !important; clip-path: none !important;
    color: inherit; transition: none !important; animation: none !important;
  }
  .ik-js [data-reveal="wipe"]::after { display: none; }
  .ik-js [data-pin] [data-step-show] { transition-duration: .01s; transform: none; }
  .ik-zoom > *, .ik-link .ik-arrow, .ik-press, [data-state-button] { transition: none !important; }
  .ik-press:active { transform: none; }
  [data-state-button][data-state="busy"] .ik-label::before { animation-duration: 2s; }
  [data-state-button][data-state="done"] .ik-label { animation: none; }
}
