/* ============================================
   Soukanzu — Motion System
   Soft, spring-y motion tokens & utilities.

   Philosophy:
     1. Soft landings    — no linear, no snap. Default: cubic-bezier(.2,.7,.2,1).
     2. Short travel     — 6–16px displacement. Meaning comes from timing, not distance.
     3. Stagger, always  — reveal in waves of 40–80ms.
     4. Respect users    — honor prefers-reduced-motion.
     5. No jitter        — compose with transform + opacity only.
   ============================================ */

:root {
  /* ── Easings (named like hyperframes / GSAP custom curves) ── */
  --ease-soft:        cubic-bezier(.2,.7,.2,1);     /* default — gentle ease out */
  --ease-soft-in:     cubic-bezier(.55,.08,.25,1);  /* quick settle */
  --ease-soft-out:    cubic-bezier(.16,1,.3,1);     /* out-expo-ish, luxurious */
  --ease-spring:      cubic-bezier(.34,1.56,.64,1); /* 1 overshoot */
  --ease-spring-loose:cubic-bezier(.2,1.9,.4,1);    /* 2 overshoots, bouncy */
  --ease-hover:       cubic-bezier(.2,.7,.2,1);

  /* ── Durations ── */
  --dur-inst:   120ms;
  --dur-fast:   220ms;
  --dur-base:   380ms;
  --dur-slow:   620ms;
  --dur-heavy:  900ms;
  --dur-reveal: 720ms;  /* hero / section entrance */
  --dur-draw:   1200ms; /* SVG stroke-dashoffset reveals */

  /* ── Stagger steps ── */
  --stag-tight: 40ms;
  --stag-base:  60ms;
  --stag-loose: 90ms;

  /* ── Travel distances ── */
  --rise-sm: 6px;
  --rise:    12px;
  --rise-lg: 20px;

  /* ── Shadow lifts for hover ── */
  --lift-shadow: 0 10px 30px -12px rgba(15,23,42,.22),
                 0 2px 6px -2px rgba(15,23,42,.08);
}

/* ============================================
   A. Utility classes — declarative entrances
   ============================================ */

/* Base state: out */
[data-anim] {
  opacity: 0;
  will-change: transform, opacity;
  transition:
    opacity var(--dur-reveal) var(--ease-soft-out),
    transform var(--dur-reveal) var(--ease-soft-out);
}

/* Variants (entering direction) */
[data-anim="fade"]       { }
[data-anim="rise"]       { transform: translate3d(0, var(--rise), 0); }
[data-anim="rise-lg"]    { transform: translate3d(0, var(--rise-lg), 0); }
[data-anim="fall"]       { transform: translate3d(0, calc(var(--rise) * -1), 0); }
[data-anim="left"]       { transform: translate3d(calc(var(--rise) * -1), 0, 0); }
[data-anim="right"]      { transform: translate3d(var(--rise), 0, 0); }
[data-anim="scale"]      { transform: scale(.96); }
[data-anim="blur"]       { filter: blur(6px); }

/* In state */
[data-anim].is-in {
  opacity: 1;
  transform: translate3d(0,0,0) scale(1);
  filter: blur(0);
}

/* Stagger children via custom index */
[data-stagger] > * {
  transition-delay: calc(var(--i, 0) * var(--stag-base));
}

/* ============================================
   B. Text split — per-line rise (pretext-driven)
   The JS splits text into <span class="pt-line"><span>…</span></span>;
   each inner <span> starts below its clip line and rises into place.
   ============================================ */
.pt-line {
  display: block;
  overflow: hidden;
  line-height: inherit;
}
.pt-line > span {
  display: inline-block;
  transform: translate3d(0, 110%, 0);
  opacity: 0;
  transition:
    transform var(--dur-reveal) var(--ease-soft-out),
    opacity  var(--dur-reveal) var(--ease-soft-out);
  transition-delay: calc(var(--i, 0) * var(--stag-base));
  will-change: transform, opacity;
}
.pt-split.is-in .pt-line > span {
  transform: translate3d(0,0,0);
  opacity: 1;
}

/* ============================================
   C. Micro-interactions — spring hover
   ============================================ */

.soft-hover {
  transition:
    transform var(--dur-fast) var(--ease-spring),
    box-shadow var(--dur-fast) var(--ease-soft),
    background-color var(--dur-fast) var(--ease-soft),
    border-color var(--dur-fast) var(--ease-soft),
    color var(--dur-fast) var(--ease-soft);
}
.soft-hover:hover {
  transform: translate3d(0, -2px, 0);
  box-shadow: var(--lift-shadow);
}
.soft-hover:active {
  transform: translate3d(0, 0, 0) scale(.985);
  transition-duration: var(--dur-inst);
}

/* Press ripple — subtle scale breath (used on primary CTAs) */
@keyframes softBreath {
  0%,100% { transform: translate3d(0,0,0) scale(1); }
  50%     { transform: translate3d(0,-1px,0) scale(1.012); }
}
.breathe {
  animation: softBreath 4.8s var(--ease-soft) infinite;
}

/* ============================================
   D. Idle floats — calm continuous motion
   ============================================ */

@keyframes floatY {
  0%,100% { transform: translate3d(0,0,0); }
  50%     { transform: translate3d(0,-6px,0); }
}
@keyframes floatSlow {
  0%,100% { transform: translate3d(0,0,0) rotate(0deg); }
  50%     { transform: translate3d(0,-8px,0) rotate(.6deg); }
}
.float        { animation: floatY   5.5s var(--ease-soft) infinite; }
.float-slow   { animation: floatSlow 9s   var(--ease-soft) infinite; }

/* Per-element phase — set --phase on children for offset */
[style*="--phase"] { animation-delay: var(--phase); }

/* ============================================
   E. SVG draw-on — strokes reveal as if hand-drawn
   ============================================ */
.draw-line {
  stroke-dasharray: var(--len, 300);
  stroke-dashoffset: var(--len, 300);
  transition: stroke-dashoffset var(--dur-draw) var(--ease-soft-out);
  transition-delay: calc(var(--i, 0) * var(--stag-loose));
}
.is-in .draw-line,
.draw-line.is-in {
  stroke-dashoffset: 0;
}

/* Pop-in nodes — for circle/rect motifs */
.pop-node {
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(.2);
  opacity: 0;
  transition:
    transform var(--dur-base) var(--ease-spring),
    opacity  var(--dur-base) var(--ease-soft-out);
  transition-delay: calc(var(--i, 0) * var(--stag-base) + 200ms);
}
.is-in .pop-node,
.pop-node.is-in {
  transform: scale(1);
  opacity: 1;
}

/* ============================================
   F. Respect motion preferences
   ============================================ */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  [data-anim],
  .pt-line > span,
  .pop-node,
  .draw-line {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    stroke-dashoffset: 0 !important;
  }
}
