/* Scroll-driven motion, CSS only.
   Every reveal is bound to a scroll timeline rather than a JS rAF loop: the page runs inside
   an embedded frame whose timers are frozen while unfocused, which silently disabled all
   JS-driven motion. Progress here is owned by the scroller, so it works regardless.
   Where scroll timelines are unavailable the same keyframes run once on load, and reduced
   motion drops straight to the finished state. */

@keyframes vl-rise{from{opacity:0;transform:translateY(var(--vl-dist,82px))}to{opacity:1;transform:none}}
@keyframes vl-blur{from{opacity:.22;filter:blur(var(--vl-blur,30px));transform:translateY(var(--vl-rise,56px))}to{opacity:1;filter:blur(0);transform:none}}
@keyframes vl-stair{from{opacity:0;transform:translate3d(-.42em,1.45em,0) rotate(6.5deg)}to{opacity:1;transform:translate3d(0,0,0) rotate(0deg)}}
@keyframes vl-iso{from{opacity:0;transform:translate3d(1.1em,-.8em,0)}to{opacity:1;transform:translate3d(0,0,0)}}
@keyframes vl-uncover{from{clip-path:inset(0 0 100% 0);transform:scale(1.13)}to{clip-path:inset(0 0 0 0);transform:scale(1)}}
@keyframes vl-clip{from{clip-path:inset(0 0 100% 0)}to{clip-path:inset(0 0 0 0)}}
@keyframes vl-spot{0%{opacity:.12;filter:blur(4px)}42%,58%{opacity:1;filter:blur(0)}100%{opacity:.12;filter:blur(4px)}}
@keyframes vl-drift{from{transform:translateY(-50%) translateY(var(--vl-drift,90px))}to{transform:translateY(-50%) translateY(calc(var(--vl-drift,90px) * -1))}}
@keyframes vl-marker{0%{opacity:0}18%{opacity:1}100%{opacity:1}}

/* Fallback: no scroll timelines — play once on load so nothing is ever stuck hidden. */
.vl-rise{animation:vl-rise var(--dur-reveal) var(--ease-out) both;animation-delay:calc(var(--i,0) * 90ms)}
.vl-blur{animation:vl-blur 900ms var(--ease-out) both}
.vl-stair{animation:vl-stair 1000ms var(--ease-out) both;animation-delay:calc(var(--i,0) * 130ms)}.vl-iso{animation:vl-iso 900ms var(--ease-out) both;animation-delay:calc(var(--i,0) * 150ms)}
.vl-uncover{animation:vl-uncover 1000ms var(--ease-in-out) both}
.vl-pin-img{animation:vl-clip 1000ms var(--ease-in-out) both}
.vl-pin-copy{animation:vl-blur 900ms var(--ease-out) both}
.vl-spot{opacity:1}
.vl-drift{animation:none}
.vl-marker{opacity:1}

@supports (animation-timeline:view()){
  .vl-rise,.vl-blur,.vl-stair,.vl-iso,.vl-uncover,.vl-spot,.vl-drift,.vl-marker,
  .vl-pin-img,.vl-pin-copy{animation-duration:1ms;animation-delay:0s;animation-fill-mode:both;animation-timing-function:linear}

  .vl-rise{animation-name:vl-rise;animation-timeline:view();
    animation-range:entry calc(0% + var(--i,0) * 6%) entry calc(48% + var(--i,0) * 6%)}
  /* blur is tied to scroll position, so the reader controls the focus */
  .vl-blur{animation-name:vl-blur;animation-timeline:view();animation-range:entry 0% entry 70%}
  /* each word arrives one step later down the diagonal — a wide per-word offset so the
     cascade reads as separate arrivals, not one block */
  .vl-stair{animation-name:vl-stair;animation-timeline:view();
    animation-range:entry calc(0% + var(--i,0) * 7%) entry calc(30% + var(--i,0) * 7%)}
  .vl-iso{animation-name:vl-iso;animation-timeline:view();
    animation-range:entry calc(2% + var(--i,0) * 8%) entry calc(44% + var(--i,0) * 8%)}
  .vl-uncover{animation-name:vl-uncover;animation-timeline:view();animation-range:entry 6% cover 36%}
  /* spotlight: brightest as the line passes the middle of the viewport */
  .vl-spot{animation-name:vl-spot;animation-timeline:view();animation-range:cover 8% cover 92%}
  .vl-drift{animation-name:vl-drift;animation-timeline:view();animation-range:cover}
  .vl-marker{animation-name:vl-marker;animation-timeline:view();animation-range:entry 0% entry 40%}
  /* the wordmark types itself as the footer arrives */
  .vl-type{animation-name:vl-type;animation-timeline:view();animation-range:entry 8% entry 96%;
    animation-duration:1ms;animation-delay:0s;animation-timing-function:steps(14,end);animation-fill-mode:both}

  /* Staged reveal for the portrait section: the image uncovers first, the copy comes into
     focus after it. Both run on their own view timeline — named timelines are avoided
     deliberately, they do not resolve against this page's scroll container. */
  /* The uncover runs on the clipping wrapper, not the image: an overflow:hidden element is
     itself a scroll container, and a view timeline inside one never activates. */
  .vl-pin-img{animation-name:vl-clip;animation-timeline:view();animation-range:entry 4% entry 62%}
  .vl-pin-copy{animation-name:vl-blur;animation-timeline:view();animation-range:entry 18% entry 74%}
}

@keyframes vl-type{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 -.04em 0 0)}}
@keyframes vl-caret{0%,48%{opacity:1}49%,100%{opacity:0}}
.vl-type{clip-path:inset(0 -.04em 0 0);animation:vl-type 1800ms steps(14,end) both;will-change:clip-path}
.vl-caret{animation:vl-caret 900ms steps(1,end) infinite}

/* Ecosystem marks: each name arrives a step behind the last as the row scrolls in, and
   lifts over a gold rule on hover. */
#dc-root .vl-mark{transition:transform 220ms var(--ease-out)}
#dc-root .vl-mark::after{content:"";position:absolute;left:0;right:0;bottom:-8px;height:1px;background:var(--gold-500);
  transform:scaleX(0);transform-origin:0 50%;transition:transform 320ms var(--ease-out)}
#dc-root .vl-mark:hover{transform:translateY(-3px)}
#dc-root .vl-mark:hover::after{transform:scaleX(1)}

/* Page transition and audit-step motion are the only click-driven animations here, and a
   click-driven clock can be frozen in an embedded frame. So they animate TRANSFORM ONLY,
   never opacity: a frozen clock leaves the element fully legible (merely offset) instead
   of blank. The finished state is also the default. */
@keyframes vl-page{from{transform:translate3d(0,26px,0)}to{transform:none}}
.vl-page{opacity:1;animation:vl-page 780ms var(--ease-out)}

/* Buttons: a gold wave sweeps across the face. It runs on hover and on press for every
   button, and loops slowly on the primary calls to action (.vl-wave) so the motion is
   visible without a pointer. The sweep is a pseudo-element, so it composes with the
   components' own inline styles. */
@keyframes vl-wave{0%{transform:translateX(-130%) skewX(-14deg)}100%{transform:translateX(130%) skewX(-14deg)}}
@keyframes vl-wave-loop{0%{transform:translateX(-130%) skewX(-14deg)}26%{transform:translateX(130%) skewX(-14deg)}100%{transform:translateX(130%) skewX(-14deg)}}
/* position:relative is load-bearing: without it the absolutely-positioned sweep resolves
   against the nearest positioned ancestor (a whole section) and paints a huge diagonal
   band over the content instead of across the button face. */
#dc-root button{position:relative;overflow:hidden}
#dc-root button::after{content:"";position:absolute;top:0;bottom:0;left:0;width:100%;pointer-events:none;
  background:linear-gradient(100deg,transparent 18%,rgba(201,162,74,.42) 46%,rgba(255,255,255,.34) 52%,transparent 84%);
  transform:translateX(-130%) skewX(-14deg)}
/* The sweep is CLICK-driven: a delegated listener adds .vl-fire for the length of the run.
   Hover never triggers it — hover has its own animation below. */
#dc-root button.vl-wave::after{animation:vl-wave-loop 3200ms var(--ease-out) infinite;animation-delay:700ms}
#dc-root button.vl-fire::after{animation:vl-wave 820ms var(--ease-out)!important}
#dc-root button:hover::after{animation:vl-wave 820ms var(--ease-out)}

/* Hover: a single gold thread leaves the top-left corner and runs the whole perimeter —
   along the top, down the right, back along the bottom, up the left — then holds as a
   hairline frame while the pointer stays. The label's tracking opens up behind it. */
@keyframes vl-trace{
  0%{opacity:1;background-size:0 1px,1px 0,0 1px,1px 0}
  28%{background-size:100% 1px,1px 0,0 1px,1px 0}
  52%{background-size:100% 1px,1px 100%,0 1px,1px 0}
  78%{background-size:100% 1px,1px 100%,100% 1px,1px 0}
  100%{opacity:1;background-size:100% 1px,1px 100%,100% 1px,1px 100%}}
#dc-root button::before{content:"";position:absolute;inset:3px;pointer-events:none;z-index:1;opacity:0;
  background:
    linear-gradient(var(--gold-500),var(--gold-500)) 0 0/0 1px no-repeat,
    linear-gradient(var(--gold-500),var(--gold-500)) 100% 0/1px 0 no-repeat,
    linear-gradient(var(--gold-500),var(--gold-500)) 100% 100%/0 1px no-repeat,
    linear-gradient(var(--gold-500),var(--gold-500)) 0 100%/1px 0 no-repeat;
  background-position:0 0,100% 0,100% 100%,0 100%}
#dc-root button:not(.vl-wave)::before{content:none}
#dc-root button.vl-wave:hover::before{animation:vl-trace 720ms var(--ease-out) forwards}
#dc-root button.vl-wave>span{transition:letter-spacing 420ms var(--ease-out)}


/* Non-scroll motion: the audit flow. Enter and exit share one path, so going back is the
   mirror of going forward. Press feedback is a 1px translate, never a scale. */
@keyframes vl-in-fwd{from{transform:translate3d(34px,0,0)}to{transform:none}}
@keyframes vl-in-back{from{transform:translate3d(-34px,0,0)}to{transform:none}}
@keyframes vl-bar{from{transform:scaleX(0)}to{transform:scaleX(var(--v,1))}}
.vl-in-fwd{opacity:1;animation:vl-in-fwd 420ms var(--ease-out)}
.vl-in-back{opacity:1;animation:vl-in-back 420ms var(--ease-out)}
.vl-bar{transform-origin:0 50%;animation:vl-bar 820ms var(--ease-out) both;animation-delay:calc(var(--i,0) * 90ms)}
.vl-press{transition:transform var(--dur-instant,110ms) var(--ease-out)}
@media (max-width:640px){:root{--vl-line-hide:none}}
.vl-press:active{transform:translateY(1px)}

@media (prefers-reduced-motion:reduce){
  .vl-in-fwd,.vl-in-back{animation:none!important;opacity:1;transform:none}
  .vl-bar{animation:none!important;transform:scaleX(var(--v,1))}
  .vl-press,.vl-press:active{transition:none;transform:none}
  .vl-type{animation:none!important;clip-path:none}
  .vl-caret{animation:none!important;opacity:1}
  .vl-page{animation:none!important;transform:none}
  #dc-root button::after,#dc-root button.vl-wave::after,#dc-root button.vl-fire::after{animation:none!important;opacity:0}
  #dc-root button::before,#dc-root button.vl-wave:hover::before{animation:none!important;opacity:0}
  #dc-root button.vl-wave>span,#dc-root button.vl-wave:hover>span{transition:none;letter-spacing:inherit}
  #dc-root .vl-mark,#dc-root .vl-mark:hover{transition:none;transform:none}
}

@media (prefers-reduced-motion:reduce){
  .vl-rise,.vl-blur,.vl-stair,.vl-iso,.vl-uncover,.vl-spot,.vl-drift,.vl-marker,
  .vl-pin-img,.vl-pin-copy{animation:none!important;opacity:1;filter:none;transform:none;clip-path:none}
}



@keyframes vlWheelFade{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.vl-wheel-fade{animation:vlWheelFade .6s cubic-bezier(.22,1,.36,1) both}
@media (prefers-reduced-motion: reduce){.vl-wheel-fade{animation:none}}

#dc-root button.vl-nosheen::after,#dc-root button.vl-nosheen::before{content:none!important}

@keyframes vlLogoTap{0%{transform:none}28%{transform:scale(.82) rotate(-10deg)}62%{transform:scale(1.1) rotate(4deg)}100%{transform:none}}
@keyframes vlWordTap{0%{opacity:1;transform:none}30%{opacity:.35;transform:translateX(-4px)}100%{opacity:1;transform:none}}
.vl-logo-tap .vl-logo-mark{animation:vlLogoTap .6s cubic-bezier(.2,.7,.2,1)}
.vl-logo-tap .vl-logo-word{display:inline-block;animation:vlWordTap .6s cubic-bezier(.2,.7,.2,1)}
@media (prefers-reduced-motion:reduce){.vl-logo-tap .vl-logo-mark,.vl-logo-tap .vl-logo-word{animation:none}}

#dc-root .vl-textcta,#root .vl-textcta{all:unset;cursor:pointer;align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:4px;padding:6px 0;
  font:var(--fw-medium) 13px/1 var(--font-core);letter-spacing:var(--ls-eyebrow);text-transform:uppercase;color:var(--gold-300);-webkit-tap-highlight-color:transparent}
.vl-textcta .vl-textcta-label{background:linear-gradient(currentColor,currentColor) 0 100%/0% 1px no-repeat;padding-bottom:6px;transition:background-size .45s cubic-bezier(.2,.7,.2,1),color .3s}
.vl-textcta .vl-textcta-arrow{display:inline-block;padding-bottom:6px;transition:transform .45s cubic-bezier(.2,.7,.2,1)}
.vl-textcta:hover .vl-textcta-label,.vl-textcta:focus-visible .vl-textcta-label{background-size:100% 1px;color:var(--paper-000)}
.vl-textcta:hover .vl-textcta-arrow,.vl-textcta:focus-visible .vl-textcta-arrow{transform:translateX(6px)}
.vl-textcta:active .vl-textcta-arrow{transform:translateX(10px)}
.vl-textcta:focus-visible{outline:1px solid var(--gold-500);outline-offset:4px}
