/* motion.css -- one motion layer for every outward Rapport HM page (pattern carried from 3G, no 3G data).
 *
 * Depth, weight and dimension: pages that flow rather than snap between states. It ships from the
 * one site chrome, alongside js/motion.js, so every page gets the same layer and no page grows a
 * second copy.
 *
 * THE RULES THIS FILE HOLDS ITSELF TO, every one of them guarded by a test:
 *   1. Content is VISIBLE with no JavaScript and to a crawler. Nothing here hides anything by
 *      default: js/motion.js puts `mo` on <html> and only THEN does .reveal start from hidden,
 *      so a reader with scripts off, an old browser, or a bot sees the finished page.
 *   2. Transform and opacity only. Never top/left/width/height/margin/padding: those are layout,
 *      they cost a reflow per frame and they move the page under the reader (CLS).
 *   3. Nothing longer than 600ms and nothing that loops, except the one busy shimmer.
 *   4. prefers-reduced-motion collapses everything to instant. The audience is owners in their
 *      sixties and seventies on phones, so this is taste and speed, never a show.
 *   5. The watermark tile and the brand line are never animated. They are the thing a screenshot
 *      has to keep.
 *   6. No library. Plain CSS and one small script.
 *   7. NOTHING IN THE SCROLL PATH REPAINTS OR RECALCS PER FRAME (stan-2026-09-02, "like a game
 *      running 20fps... im on mac with 120hz"). The cover's parallax is a scroll-driven animation
 *      on the compositor wherever the browser has one, and a shadow never transitions: box-shadow
 *      is a repaint of the whole card every frame it animates, so the lift animates (transform)
 *      and the shadow arrives with it in one paint.
 */

/* ---------------------------------------------------------------------------------------------
   1. SCROLL REVEAL. The default is FULLY VISIBLE. js/motion.js adds `mo` to <html>, tags the
   blocks it is going to reveal with .reveal, and hands each one .in as it scrolls into view.
   An element already on screen when the page loads is given .in AND .mo-now in the same frame,
   so nothing above the fold ever flashes.
   --------------------------------------------------------------------------------------------- */
.mo .reveal{opacity:0;transform:translate3d(0,14px,0);
  transition:opacity .38s cubic-bezier(.22,.61,.36,1) var(--mo-d,0s),
             transform .38s cubic-bezier(.22,.61,.36,1) var(--mo-d,0s)}
.mo .reveal.in{opacity:1;transform:none}
.mo .reveal.mo-now{transition:none}

/* ---------------------------------------------------------------------------------------------
   2. DEPTH ON THE COVER. The hero's own contents drift and fade as the band leaves the screen, so
   the page reads as layers rather than one flat sheet. Where the browser runs scroll-driven
   animations (Chrome 115+, Safari 26+) this is a view() timeline over the cover's exit, which the
   compositor drives with no script and no style work per frame. Elsewhere --mo-p is 0 at the top
   and 1 by the time the cover is gone; js/motion.js writes it inside a rAF, only when it changed,
   and only on a cover that is neither fixed nor sticky.
   --------------------------------------------------------------------------------------------- */
@supports (animation-timeline: view()){
  .mo .mo-par>*{animation:mo-par linear both;animation-timeline:view();animation-range:exit 0% exit 100%;
    will-change:transform,opacity}
}
@supports not (animation-timeline: view()){
  .mo .mo-par>*{transform:translate3d(0,calc(var(--mo-p,0) * 22px),0);
    opacity:calc(1 - var(--mo-p,0) * .5);will-change:transform,opacity}
}
@keyframes mo-par{to{transform:translate3d(0,22px,0);opacity:.5}}

/* ---------------------------------------------------------------------------------------------
   3. THE STICKY NAV GAINS A SHADOW once the page has moved under it. box-shadow is not layout, so
   no row moves; it is a paint, so it snaps rather than transitions (the nav is its own layer and
   this fires once per scroll, so one paint is all it ever costs).
   --------------------------------------------------------------------------------------------- */
.topnav,.rs-nav{transition:background-color .22s ease}
.topnav.mo-stuck,.rs-nav.mo-stuck{box-shadow:0 6px 18px -8px rgba(16,26,38,.30),0 1px 0 rgba(16,26,38,.06)}

/* ---------------------------------------------------------------------------------------------
   4. WEIGHT UNDER THE FINGER. A control lifts a hair toward the reader on hover and presses down
   when it is tapped. 1px and .98 -- enough that the button feels physical, not enough to notice
   as an animation. :active fires on touch too, which is where most of this audience is.
   The LIFT transitions (transform, compositor); the SHADOW does not: a box-shadow that animates
   repaints the whole control on every frame of the transition, and on a trackpad the pointer
   rests on the page while it scrolls, so a stack of cards passing under it would repaint the
   scroll. It arrives in one paint with the lift, which reads the same and costs one frame.
   --------------------------------------------------------------------------------------------- */
.btn,.cta,a.cta,.doors a,.bd-doors a,#lg-acct a,.picks button,.go,.nav-drawer-acct a{
  transition:transform .16s cubic-bezier(.22,.61,.36,1),background-color .16s ease}
.btn:hover,.cta:hover,a.cta:hover,.doors a:hover,.bd-doors a:hover,#lg-acct a:hover,.go:hover,
.nav-drawer-acct a:hover{transform:translateY(-1px);box-shadow:0 8px 18px -8px rgba(16,26,38,.45)}
.btn:active,.cta:active,a.cta:active,.doors a:active,.bd-doors a:active,#lg-acct a:active,
.picks button:active,.go:active,.nav-drawer-acct a:active{transform:scale(.98);box-shadow:none}
.btn:disabled:hover,.btn[disabled]:hover{transform:none;box-shadow:none}
/* Every other button still gets the press, without the shadow: a bare text button that lifts
   reads as a mistake. #rh-ask-tab and #rh-share-btn own their own transform already. */
button:not(.btn):not(.picks button):not(.go):active{transform:scale(.98)}
#rh-ask-tab,#rh-share-btn{transform:none}
#rh-ask-tab:active,#rh-share-btn:active{transform:none}

/* Cards rise off the page under the pointer. `.chg`/`.std-card`/`.lg-shape` joined 2026-09-02, the
   section-weight pass (stan-2026-09-02): those were cards at rest with no matching lift, which is
   the tell of a component built after this list and never added to it. */
.card,.pubcard,.rcard,.std-list>a,.fc-stat,.chg,.std-card,.lg-shape{
  transition:transform .18s cubic-bezier(.22,.61,.36,1)}
.card:hover,.pubcard:hover,.rcard:hover,.std-list>a:hover,.chg:hover,.std-card:hover{
  transform:translateY(-2px);box-shadow:0 14px 30px -16px rgba(16,26,38,.5)}

/* A link in body copy draws its underline in rather than snapping one on. scaleX, so it is one
   compositor property and the line never reflows the paragraph. */
main p a[href]:not(.btn):not(.cta),.lead a[href]:not(.btn):not(.cta){position:relative;text-decoration:none}
main p a[href]:not(.btn):not(.cta)::after,.lead a[href]:not(.btn):not(.cta)::after{
  content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;background:currentColor;
  transform:scaleX(0);transform-origin:left center;transition:transform .22s cubic-bezier(.22,.61,.36,1)}
main p a[href]:hover::after,main p a[href]:focus-visible::after,
.lead a[href]:hover::after,.lead a[href]:focus-visible::after{transform:scaleX(1)}

/* The focus ring is visible and it arrives, so a keyboard reader can see where they are. */
a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,
summary:focus-visible,[tabindex]:focus-visible{outline:3px solid var(--rhm-link,#1E8C86);outline-offset:2px;
  transition:outline-offset .12s ease}

/* ---------------------------------------------------------------------------------------------
   5. THINGS THAT OPEN. The house modal keeps its markup and its rules;
   this only changes the CURVE and the timing, so every sheet on the site opens with the same
   small spring. The dimmed backdrop fades in with it. The press-kit reader and the dashboard
   sheets are the same component, so they inherit it for nothing.
   --------------------------------------------------------------------------------------------- */
body>.sheet{transition:transform .28s cubic-bezier(.2,.9,.3,1.1),opacity .2s ease-out}
.ov.show{animation:mo-fade .22s ease-out both}
/* The press kit's closable reader is toggled with [hidden], so it opens on an animation
   rather than a transition. Same curve, so every panel on the site opens the one way. */
.pr-reader:not([hidden]){animation:mo-pop .28s cubic-bezier(.2,.9,.3,1.1) both}
@keyframes mo-fade{from{opacity:0}to{opacity:1}}
@keyframes mo-pop{from{opacity:0;transform:scale(.985)}to{opacity:1;transform:none}}
/* The mobile nav drawer is the same gesture, so it gets the same curve. */
.nav-drawer{transition:transform .28s cubic-bezier(.2,.9,.3,1.1)}

/* The consent switch on the account dashboard: the knob travels on the same spring. */
.sw::after{transition:transform .24s cubic-bezier(.2,.9,.3,1.1)}
.sw{transition:background-color .2s ease}

/* A <details> chevron turns rather than jumping. */
.alchev,.mo-chev{transition:transform .2s cubic-bezier(.22,.61,.36,1)}

/* ---------------------------------------------------------------------------------------------
   6. THE ONE THING THAT LOOPS. A control that is waiting on the network wears a shimmer, set by
   js/motion.js on the button it disabled. It is the only continuous animation on the site, and
   it stops the moment the answer lands.
   --------------------------------------------------------------------------------------------- */
.mo-busy{position:relative;overflow:hidden}
.mo-busy::after{content:"";position:absolute;top:0;bottom:0;left:0;width:45%;
  background:linear-gradient(90deg,rgba(255,255,255,0) 0%,rgba(255,255,255,.35) 50%,rgba(255,255,255,0) 100%);
  transform:translateX(-120%);animation:mo-shimmer 1.15s linear infinite;pointer-events:none}
@keyframes mo-shimmer{from{transform:translateX(-120%)}to{transform:translateX(320%)}}

/* ---------------------------------------------------------------------------------------------
   7. PAGE TO PAGE. Same-origin navigations cross-fade with a short slide where the browser has
   cross-document view transitions; everywhere else the page fades in on load instead, which is
   what .mo-enter does. Both are additive: a browser that knows neither shows the page.
   --------------------------------------------------------------------------------------------- */
@view-transition{navigation:auto}
::view-transition-old(root){animation:mo-out .18s ease-in both}
::view-transition-new(root){animation:mo-in .26s cubic-bezier(.22,.61,.36,1) both}
@keyframes mo-out{to{opacity:0;transform:translate3d(0,-6px,0)}}
@keyframes mo-in{from{opacity:0;transform:translate3d(0,10px,0)}}
.mo-enter{animation:mo-enter .26s ease-out both}
@keyframes mo-enter{from{opacity:0;transform:translate3d(0,6px,0)}to{opacity:1;transform:none}}

/* An in-page tab switch slides in the direction the reader moved. js/motion.js sets .mo-slide-l /
   .mo-slide-r on the panel that just became current. */
.mo-slide-l{animation:mo-sl .24s cubic-bezier(.22,.61,.36,1) both}
.mo-slide-r{animation:mo-sr .24s cubic-bezier(.22,.61,.36,1) both}
@keyframes mo-sl{from{opacity:0;transform:translate3d(-14px,0,0)}}
@keyframes mo-sr{from{opacity:0;transform:translate3d(14px,0,0)}}

/* ---------------------------------------------------------------------------------------------
   8. REDUCED MOTION. Everything above collapses. This block is load bearing: it is the whole
   reason the layer is allowed to exist on a site whose readers are mostly on phones and mostly
   not twenty. js/motion.js reads the same media query and never arms the observer or the
   scroll listener.
   --------------------------------------------------------------------------------------------- */
@media(prefers-reduced-motion:reduce){
  .mo .reveal,.mo .reveal.in{opacity:1!important;transform:none!important;transition:none!important}
  .mo .mo-par>*{transform:none!important;opacity:1!important;will-change:auto;animation:none!important}
  .mo-busy::after{animation:none;display:none}
  .mo-enter,.mo-slide-l,.mo-slide-r{animation:none}
  .pr-reader:not([hidden]){animation:none}
  ::view-transition-old(root),::view-transition-new(root){animation:none!important}
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important}
}
