/* RLR motion layer.
   Hooks are DATA ATTRIBUTES, not classes, so this whole file can be pasted into
   Webflow's site-wide custom code without creating a single Webflow class.
   Compositor-only properties. Fully disabled under prefers-reduced-motion. */

/* ---------- fixed header ---------- */
[data-rlr-header]{position:fixed;top:0;left:0;right:0;z-index:50;
  border-bottom:1px solid rgba(255,255,255,0);
  transition:background-color .32s ease, backdrop-filter .32s ease, border-color .32s ease}
[data-rlr-header][data-stuck]{background-color:rgba(13,20,42,.78);
  backdrop-filter:blur(14px) saturate(140%);-webkit-backdrop-filter:blur(14px) saturate(140%);
  border-bottom-color:rgba(255,255,255,.09)}
[data-rlr-header][data-stuck] .rlr-logo-img{width:150px}
.rlr-logo-img{transition:width .32s ease}

/* ---------- entrance ---------- */
@keyframes rlr-zoom{from{transform:scale(1.08)}to{transform:scale(1)}}
[data-rlr-enter]{opacity:0;animation:rlr-rise .9s cubic-bezier(.22,.68,.28,1) forwards}
[data-rlr-enter="1"]{animation-delay:.06s}
[data-rlr-enter="2"]{animation-delay:.16s}
[data-rlr-enter="3"]{animation-delay:.26s}
[data-rlr-enter="4"]{animation-delay:.36s}
[data-rlr-zoom]{animation:rlr-zoom 3.2s cubic-bezier(.22,.68,.28,1) both}

/* ---------- scroll reveal: JS fallback path ---------- */
[data-rlr-reveal]{opacity:0;transform:translate3d(0,26px,0)}
[data-rlr-reveal][data-in]{opacity:1;transform:none;
  transition:opacity .72s cubic-bezier(.22,.68,.28,1), transform .72s cubic-bezier(.22,.68,.28,1)}
[data-rlr-stagger] > *{opacity:0;transform:translate3d(0,26px,0)}
[data-rlr-stagger][data-in] > *{opacity:1;transform:none;
  transition:opacity .68s cubic-bezier(.22,.68,.28,1), transform .68s cubic-bezier(.22,.68,.28,1)}
[data-rlr-stagger][data-in] > *:nth-child(2){transition-delay:.09s}
[data-rlr-stagger][data-in] > *:nth-child(3){transition-delay:.18s}
[data-rlr-stagger][data-in] > *:nth-child(4){transition-delay:.27s}
[data-rlr-stagger][data-in] > *:nth-child(5){transition-delay:.36s}

/* ---------- scroll reveal: native path, no JS, runs on the compositor ---------- */
@supports (animation-timeline: view()){
  [data-rlr-reveal]{opacity:1;transform:none;animation:rlr-rise linear both;
    animation-timeline:view();animation-range:entry 2% entry 42%}
  [data-rlr-stagger] > *{opacity:1;transform:none;animation:rlr-rise linear both;
    animation-timeline:view();animation-range:entry 2% entry 46%}
  [data-rlr-reveal][data-in],[data-rlr-stagger][data-in] > *{transition:none}
  @keyframes rlr-drift{from{transform:translate3d(0,46px,0)}to{transform:translate3d(0,-26px,0)}}
  [data-rlr-drift]{animation:rlr-drift linear both;animation-timeline:view();
    animation-range:cover 6% cover 88%}
}


/* ---------- captures keep moving while they are on screen ----------
   Twice now the note back has been that it is too subtle, so this is a real
   step up rather than another nudge: about 150px of travel on a capture, and
   the two columns of a paired block now move in OPPOSITE directions.

   The opposite directions are the part that matters. Everything drifting the
   same way at the same rate reads as the page scrolling, which is what a page
   does anyway. A capture rising while the copy beside it eases down is a
   difference you notice without being able to say why.

   Still the card that moves and never the picture inside it. These screenshots
   were cropped so every axis label and column header survives, and pushing the
   image around inside a clipped frame would eat exactly those edges. Transform
   does not affect layout, so nothing below reflows no matter how far it goes. */
@keyframes rlr-shot-drift{
  0%   {opacity:0; transform:translate3d(0,92px,0) scale(.965)}
  18%  {opacity:1; transform:translate3d(0,58px,0) scale(1)}
  100% {opacity:1; transform:translate3d(0,-58px,0) scale(1)}
}
/* the copy goes the other way, and more gently -- it is text, and text that
   moves as much as a picture is hard to read */
@keyframes rlr-copy-counter{
  0%   {opacity:0; transform:translate3d(0,-14px,0)}
  16%  {opacity:1; transform:translate3d(0,-8px,0)}
  100% {opacity:1; transform:translate3d(0,34px,0)}
}
@keyframes rlr-rise{from{opacity:0;transform:translate3d(0,38px,0)}to{opacity:1;transform:none}}

@supports (animation-timeline: view()){
  .rlr-shot[data-rlr-reveal]{
    animation:rlr-shot-drift linear both;
    animation-timeline:view();
    animation-range:cover 0% cover 100%;
  }
  /* :not(.rlr-shot) matters. The capture is also a direct child, so without it
     this rule matches the figure as well, and at equal specificity the later
     rule wins -- which had the capture running the copy's animation and both
     columns drifting together, the exact opposite of the intent. */
  .rlr-headshot > [data-rlr-reveal]:not(.rlr-shot),
  .rlr-situation-grid > [data-rlr-reveal]:not(.rlr-shot){
    animation:rlr-copy-counter linear both;
    animation-timeline:view();
    animation-range:cover 0% cover 100%;
  }
  [data-rlr-reveal]{animation-range:entry 0% cover 22%}
  [data-rlr-stagger] > *{animation-range:entry 0% cover 24%}
}
@media (prefers-reduced-motion: reduce){
  .rlr-shot[data-rlr-reveal],
  .rlr-headshot > [data-rlr-reveal]:not(.rlr-shot),
  .rlr-situation-grid > [data-rlr-reveal]:not(.rlr-shot){
    animation:none!important;opacity:1!important;transform:none!important}
}

/* ---------- marquee ---------- */
@keyframes rlr-marquee{from{transform:translate3d(0,0,0)}to{transform:translate3d(-50%,0,0)}}
[data-rlr-marquee]{overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent)}
[data-rlr-marquee-track]{display:flex;align-items:center;width:max-content;column-gap:var(--space-7);
  animation:rlr-marquee 34s linear infinite}
[data-rlr-marquee]:hover [data-rlr-marquee-track]{animation-play-state:paused}

/* ---------- smooth anchors ---------- */
html{scroll-behavior:smooth;scroll-padding-top:104px}

/* ---------- respect the user ---------- */
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  [data-rlr-enter],[data-rlr-zoom],[data-rlr-drift],[data-rlr-marquee-track]{animation:none!important}
  [data-rlr-enter]{opacity:1}
  [data-rlr-reveal],[data-rlr-stagger] > *{opacity:1!important;transform:none!important;
    animation:none!important;transition:none!important}
}

/* ---------- scroll progress ---------- */
[data-rlr-progress]{position:fixed;top:0;left:0;height:3px;width:100%;transform-origin:0 50%;
  background-color:var(--green-glow);z-index:60;transform:scaleX(0);pointer-events:none}
@supports (animation-timeline: scroll()){
  [data-rlr-progress]{animation:rlr-progress linear;animation-timeline:scroll(root block)}
  @keyframes rlr-progress{from{transform:scaleX(0)}to{transform:scaleX(1)}}
}
@media (prefers-reduced-motion:reduce){
  [data-rlr-progress]{display:none}
}

/* ---------- cross-document view transitions ----------
   Opting in removes the white flash between pages, so moving platform ->
   framework -> cities reads as one application rather than five separate
   documents. One declaration; browsers without support navigate exactly as they
   do today and lose nothing.

   The header is named so it holds still while the page beneath it changes.
   Without that the nav crossfades against itself, which is worse than no
   transition at all: the eye catches the one element that should be the anchor. */
@view-transition{navigation:auto}

::view-transition-old(root),::view-transition-new(root){
  animation-duration:200ms;animation-timing-function:cubic-bezier(.2,0,.2,1)}

.rlr-header{view-transition-name:rlr-header}
::view-transition-old(rlr-header),::view-transition-new(rlr-header){animation:none}

/* A transition is motion, and the same people who asked not to see the marquee
   move did not ask to see pages dissolve either. */
@media (prefers-reduced-motion:reduce){
  @view-transition{navigation:none}
}
