/* ============================================================================
   uxjo 2.0 — motion system.
   CSS-first and fail-safe: content is VISIBLE by default. Entrance motion is
   layered on only where scroll-driven timelines are supported, so nothing can
   ever be left invisible by a stalled observer, a paused frame loop or a
   blocked script.
   Every animation reveals a relationship, directs attention, or confirms an
   action. Easing is --ease-out. No springs, no overshoot.
   ============================================================================ */

/* ---------- 1. headline: plays once on load, no scroll dependency ---------- */
.rv-lines{display:grid}
.rv-lines .ln{display:block;overflow:hidden;padding-block:.04em}
.rv-lines .ln>span{display:block}
@media (prefers-reduced-motion:no-preference){
  .rv-lines .ln>span{animation:uxLineUp 900ms var(--ease-out) both;animation-delay:calc(var(--i,0) * 95ms)}
}
@keyframes uxLineUp{from{transform:translateY(105%)}to{transform:none}}

/* on-load entrance for above-the-fold content: always plays, no scroll needed */
@media (prefers-reduced-motion:no-preference){
  .rv-load{animation:uxRise 820ms var(--ease-out) both;animation-delay:calc(var(--i,0) * 110ms)}
  .rv-load.rv-sc{animation-name:uxRiseSc}
  .rv-load.rv-settle{animation-name:uxSettle}
}

/* ---------- 2. scroll-driven entrances ----------
   No support, or reduced motion, means the element simply renders. */
@keyframes uxRise{from{opacity:0;transform:translateY(30px)}to{opacity:1;transform:none}}
@keyframes uxRiseL{from{opacity:0;transform:translateX(-32px)}to{opacity:1;transform:none}}
@keyframes uxRiseR{from{opacity:0;transform:translateX(32px)}to{opacity:1;transform:none}}
@keyframes uxRiseSc{from{opacity:0;transform:scale(.94)}to{opacity:1;transform:none}}
@keyframes uxRiseBl{from{opacity:0;filter:blur(12px);transform:translateY(16px)}to{opacity:1;filter:none;transform:none}}
@keyframes uxSettle{from{opacity:0;transform:perspective(1600px) rotateX(8deg) translateY(30px) scale(.96)}to{opacity:1;transform:none}}
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    .rv{animation:uxRise both linear;animation-timeline:view();animation-range:entry calc(2% + var(--i,0) * 3%) cover calc(24% + var(--i,0) * 3%)}
    .rv-l{animation-name:uxRiseL}
    .rv-r{animation-name:uxRiseR}
    .rv-sc{animation-name:uxRiseSc}
    .rv-bl{animation-name:uxRiseBl}
    /* a settling tilt for large product panels */
    .rv-settle{animation-name:uxSettle}
  }
}

/* ---------- 3. proportion meters ---------- */
.meter{--v:0;height:6px;border-radius:99px;background:var(--neutral-200);overflow:hidden}
.section--ink .meter{background:rgba(255,255,255,.12)}
.meter>i{display:block;height:100%;width:calc(var(--v) * 1%);border-radius:99px;background:var(--fill,var(--sky))}
@keyframes uxFill{from{width:0}to{width:calc(var(--v) * 1%)}}
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    .meter>i{animation:uxFill both linear;animation-timeline:view();animation-range:entry 12% cover 34%}
  }
}

/* ---------- 4. connector draw-on: shows the path a signal takes ---------- */
.draw{stroke-dasharray:var(--len,420);stroke-dashoffset:0}
@keyframes uxDraw{from{stroke-dashoffset:var(--len,420)}to{stroke-dashoffset:0}}
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    .draw{animation:uxDraw both linear;animation-timeline:view();animation-range:entry calc(6% + var(--i,0) * 2%) cover calc(38% + var(--i,0) * 2%)}
  }
}

/* ---------- 5. ambient loops ---------- */
@keyframes uxPulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.84)}}
@keyframes uxDash{to{stroke-dashoffset:-28}}
@keyframes uxFloat{0%,100%{transform:translate3d(0,0,0)}50%{transform:translate3d(0,-9px,0)}}
@keyframes uxCaret{0%,45%{opacity:1}46%,100%{opacity:0}}
@keyframes uxMsgIn{from{opacity:0;transform:translateY(14px) scale(.97)}to{opacity:1;transform:none}}
.pulse{animation:uxPulse 2.4s var(--ease-inout) infinite}
.flowline{stroke-dasharray:3 11;stroke-linecap:round}
.caret{opacity:1}
@media (prefers-reduced-motion:no-preference){
  .flowline{animation:uxDash 1.4s linear infinite}
  .float{animation:uxFloat 7s var(--ease-inout) infinite;animation-delay:calc(var(--i,0) * -1.4s)}
  .caret{animation:uxCaret 1.05s steps(1) infinite}
}

/* ---------- 6. hover and press ---------- */
.z-lift{transition:transform var(--t-base) var(--ease-out),box-shadow var(--t-base)}
.z-lift:hover{transform:translateY(-4px);box-shadow:var(--sh-lg)}

/* ---------- 7. pointer depth (JS writes --pan-x / --pan-y) ---------- */
.stage{perspective:var(--persp,1500px);perspective-origin:50% 45%}
.par{transform:translate3d(calc(var(--pan-x,0) * var(--k,1) * 1px),calc(var(--pan-y,0) * var(--k,1) * 1px),0);transition:transform 220ms var(--ease-out)}

/* ---------- 8. reduced motion: nothing moves, everything shows ---------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;scroll-behavior:auto!important}
  .par{transform:none!important}
}
