/* Revolution Film Core — front-end styles for shortcode sections.
   Namespaced with .rf- so it never collides with your theme or Elementor.
   This is a plain, editable stylesheet — not logic baked into PHP. Change
   colors/spacing here, or override site-wide via
   Appearance → Additional CSS (no Elementor Pro required for either). */

:root{
  --rf-black:#000; --rf-white:#fff; --rf-red:#d60303;
  --rf-line: rgba(255,255,255,.12); --rf-off: rgba(255,255,255,.72);
  --rf-ease: cubic-bezier(.16,.84,.44,1);
}

.rf-hero, .rf-work, .rf-test-marquee, .rf-marquee{ font-family:'Inter', sans-serif; }

/* ---- Focus states (accessibility) ---- */
.rf-hero-cta:focus-visible,
.rf-featured:focus-visible,
.rf-video-block:focus-visible,
.rf-play-btn:focus-visible,
.rf-modal-close:focus-visible,
.rf-logo-slot a:focus-visible{
  outline:2px solid var(--rf-red); outline-offset:3px;
}

/* ---- Hero slider ---- */
.rf-hero{ position:relative; height:88vh; min-height:520px; overflow:hidden; background:#0a0a0a; }
.rf-hero-slide{ position:absolute; inset:0; opacity:0; visibility:hidden; transition:opacity 1.4s var(--rf-ease), visibility 0s linear 1.4s; }
.rf-hero-slide.active{ opacity:1; visibility:visible; z-index:2; transition:opacity 1.4s var(--rf-ease), visibility 0s; }
/* v1.13 — layered crossfade. The OUTGOING slide stays fully opaque (.rf-leaving)
   underneath while the INCOMING slide fades in on top, so the picture never
   dips toward the dark background mid-transition. rf-core.js only starts the
   swap once the incoming video is ready (.rf-priming = loading while hidden). */
.rf-hero-slide.rf-priming{ visibility:visible; z-index:0; pointer-events:none; transition:none; }
.rf-hero-slide.rf-leaving{ opacity:1; visibility:visible; z-index:1; pointer-events:none; transition:none; }
.rf-hero-ph{ position:absolute; inset:0; background-size:cover; background-position:center; background-color:#111; overflow:hidden; }
.rf-hero-video{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:0; }
.rf-hero-ph::before{ content:''; position:absolute; inset:0; z-index:1;
  background:linear-gradient(180deg, rgba(0,0,0,.35) 0%, rgba(0,0,0,.15) 40%, rgba(0,0,0,.85) 100%); }
.rf-hero-content{ position:relative; z-index:3; height:100%; display:flex; flex-direction:column; justify-content:flex-end;
  padding:0 48px 96px; max-width:1320px; margin:0 auto; }
.rf-hero-slogan{ color:var(--rf-white); font-weight:900; text-transform:uppercase; font-size:clamp(34px,7vw,84px); line-height:1.02; max-width:16ch; overflow:hidden; margin:0; }
.rf-hero-slogan span{ display:block; transform:translateY(110%); }
.rf-hero-slide.active .rf-hero-slogan span{ transform:translateY(0); }
.rf-hero-cta{ margin-top:38px; display:inline-block; color:var(--rf-white); font-weight:700; font-size:14px; letter-spacing:.14em;
  text-transform:uppercase; padding-bottom:8px; border-bottom:1px solid var(--rf-white); text-decoration:none;
  transition:color .3s, border-color .3s; }
.rf-hero-cta:hover{ color:var(--rf-red); border-color:var(--rf-red); }
/* v1.13 — hover AND pressed state are #d60303 (desktop + touch). Three classes of
   specificity so Astra/Elementor link colours can't override it; scoped to the hero. */
.rf-hero .rf-hero-cta:hover,
.rf-hero .rf-hero-cta:active{ color:#d60303; border-color:#d60303; }
@media (max-width:700px){ .rf-hero-content{ padding:0 22px 64px; } }

/* ---- Our Work ---- */
.rf-work, .rf-all-projects-wrap{ background:var(--rf-black); padding:48px 24px; }
.rf-featured-wrap{ margin-bottom:48px; }
.rf-featured{ position:relative; aspect-ratio:16/8; width:100%; background:#0f0f0f; cursor:pointer; overflow:hidden; }
.rf-featured img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.rf-featured::before{ content:''; position:absolute; inset:0; z-index:1; background:linear-gradient(0deg, rgba(15,15,15,.45), rgba(15,15,15,.05) 55%); }
.rf-play-btn{ position:absolute; inset:0; margin:auto; width:78px; height:78px; z-index:2; border-radius:50%; border:1px solid var(--rf-white);
  display:flex; align-items:center; justify-content:center; transition:transform .35s var(--rf-ease), background .35s, border-color .35s; }
.rf-play-btn.small{ width:58px; height:58px; }
.rf-play-btn svg{ width:20px; height:20px; fill:var(--rf-white); margin-left:3px; }
.rf-play-btn.small svg{ width:16px; height:16px; }
.rf-featured:hover .rf-play-btn, .rf-video-item:hover .rf-play-btn, .rf-works-card:hover .rf-play-btn{ transform:scale(1.12); background:var(--rf-red); border-color:var(--rf-red); }
.rf-featured.rf-no-video, .rf-video-block.rf-no-video{ cursor:default; }
.rf-no-video .rf-no-video-label{
  position:absolute; left:50%; bottom:16px; transform:translateX(-50%); z-index:2;
  font-size:11px; letter-spacing:.12em; text-transform:uppercase; color:var(--rf-off);
  border:1px solid var(--rf-line); padding:6px 14px; background:rgba(0,0,0,.5); white-space:nowrap;
}
.rf-video-caption{ margin-top:20px; display:flex; flex-direction:column; gap:6px; }
.rf-video-caption .rf-cat{ font-size:12px; letter-spacing:.14em; text-transform:uppercase; color:var(--rf-red); font-weight:700; }
.rf-video-caption .rf-name{ color:var(--rf-white); font-weight:800; font-size:clamp(18px,2.4vw,26px); text-transform:uppercase; }
.rf-video-caption .rf-meta{ color:var(--rf-off); font-size:13px; letter-spacing:.02em; }
.rf-video-item .rf-video-caption .rf-meta{ font-size:12.5px; }

.rf-all-projects-grid{ display:flex; flex-wrap:wrap; gap:24px; }
.rf-video-item{ flex:0 0 auto; width:min(380px,82vw); }

/* Recent Projects row: fixed number of cards fully visible (no partial/cut
   card), continuously animated right-to-left, looping seamlessly via a
   duplicated (aria-hidden) second set. Card widths and animation speed are
   computed in JS to match the container's actual width and item count —
   see rf-core.js. */
.rf-project-carousel{ overflow:hidden; width:100%; }
.rf-project-carousel-track{
  display:flex; gap:24px; width:max-content;
  animation: rf-carousel-loop 30s linear infinite;
}
.rf-project-carousel-clone{ display:contents; } /* keeps clones as direct flex items, not a nested box */
.rf-project-carousel:hover .rf-project-carousel-track,
.rf-project-carousel-track.rf-paused{ animation-play-state:paused; }
@keyframes rf-carousel-loop{ from{ transform:translateX(0); } to{ transform:translateX(-50%); } }

/* Accessible fallback for prefers-reduced-motion (applied via JS, which
   also removes the duplicate set so nothing appears twice): a plain,
   manually-scrollable row instead of the auto-animating one. */
.rf-project-carousel.rf-carousel-static{ overflow-x:auto; -ms-overflow-style:none; scrollbar-width:none; }
.rf-project-carousel.rf-carousel-static::-webkit-scrollbar{ display:none; }
.rf-project-carousel.rf-carousel-static .rf-project-carousel-track{ animation:none; }
.rf-project-carousel.rf-carousel-static .rf-video-item{ flex:0 0 min(380px,82vw) !important; width:auto !important; }
.rf-video-block{ position:relative; aspect-ratio:16/9; width:100%; background:#0f0f0f; overflow:hidden; cursor:pointer; }
.rf-video-block img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.rf-video-block::before{ content:''; position:absolute; inset:0; z-index:1; background:linear-gradient(0deg, rgba(15,15,15,.4), rgba(15,15,15,.05) 55%); }
.rf-video-item .rf-video-caption{ margin-top:16px; }
.rf-video-item .rf-video-caption .rf-name{ font-size:16px; }

/* ---- Video modal ---- */
.rf-video-modal{ position:fixed; inset:0; z-index:9999; background:rgba(0,0,0,.94); display:flex; align-items:center; justify-content:center;
  opacity:0; visibility:hidden; transition:opacity .35s var(--rf-ease); padding:24px; }
.rf-video-modal.open{ opacity:1; visibility:visible; }
.rf-modal-box{ width:min(1100px,100%); aspect-ratio:16/9; background:#000; position:relative; border:1px solid var(--rf-line); }
.rf-modal-box video, .rf-modal-box iframe{ width:100%; height:100%; border:0; }
.rf-modal-close{
  position:absolute; top:12px; right:12px; z-index:10;
  width:44px; height:44px; border-radius:50%;
  background:rgba(0,0,0,.72); border:1px solid rgba(255,255,255,.35);
  color:var(--rf-white); display:flex; align-items:center; justify-content:center;
  cursor:pointer; font-family:inherit; padding:0;
  transition:background .25s, border-color .25s, transform .2s;
}
.rf-modal-close:hover{ background:var(--rf-red); border-color:var(--rf-red); transform:scale(1.06); }
.rf-modal-close svg{ width:20px; height:20px; pointer-events:none; }
.rf-modal-close .rf-modal-close-label{
  position:absolute; right:52px; top:50%; transform:translateY(-50%);
  font-size:12px; letter-spacing:.1em; text-transform:uppercase; white-space:nowrap;
  opacity:0; transition:opacity .25s; pointer-events:none;
}
.rf-modal-close:hover .rf-modal-close-label,
.rf-modal-close:focus-visible .rf-modal-close-label{ opacity:1; }
body.rf-modal-open{ overflow:hidden; }

/* ---- Testimonials: bordered cards, continuous right-to-left loop
   (same pattern as the Partners marquee — a duplicated set + a CSS
   keyframe animation, no JS needed). ---- */
.rf-test-marquee{ overflow:hidden; position:relative; }
.rf-test-track{ display:flex; gap:24px; width:max-content; animation:rf-scroll 42s linear infinite; align-items:stretch; }
.rf-test-marquee:hover .rf-test-track{ animation-play-state:paused; }
.rf-test-card{
  flex:0 0 auto; width:min(380px,80vw); background:#0f0f0f; border:1px solid var(--rf-line);
  padding:34px 30px; display:flex; flex-direction:column; justify-content:space-between; min-height:230px;
}
.rf-test-card blockquote{
  color:var(--rf-white) !important; font-size:17px !important; line-height:1.65 !important;
  font-style:italic !important; font-weight:400 !important; text-transform:none !important;
  margin:0; border:0 !important; padding:0 !important; background:none !important;
}
.rf-test-card blockquote::before, .rf-test-card blockquote::after{ content:none !important; }
.rf-test-attribution{ margin-top:26px; display:flex; flex-direction:column; gap:4px; }
.rf-test-attribution .rf-test-name{
  color:var(--rf-red) !important; font-weight:700; text-transform:uppercase; letter-spacing:.05em; font-size:14px;
}
.rf-test-attribution .rf-test-role{ color:var(--rf-off) !important; font-size:13px; }

/* ---- Partners marquee ---- */
.rf-marquee-group .rf-marquee + .rf-marquee{ border-top:0; margin-top:-1px; }
.rf-marquee{ overflow:hidden; position:relative; border-top:1px solid var(--rf-line); border-bottom:1px solid var(--rf-line); padding:34px 0; }
.rf-marquee-track{ display:flex; gap:64px; width:max-content; animation:rf-scroll 34s linear infinite; align-items:center; }
.rf-marquee.rf-marquee-reverse .rf-marquee-track{ animation-direction:reverse; }
.rf-marquee:hover .rf-marquee-track{ animation-play-state:paused; }
@keyframes rf-scroll{ from{ transform:translateX(0); } to{ transform:translateX(-50%); } }
.rf-logo-slot{ flex:0 0 auto; height:56px; display:flex; align-items:center; filter:grayscale(1); opacity:.65; transition:opacity .3s, filter .3s; }
.rf-logo-slot:hover{ opacity:1; filter:grayscale(0); }
.rf-logo-slot img{ max-height:56px; width:auto; }

@media (prefers-reduced-motion: reduce){
  .rf-hero-slide, .rf-hero-slogan, .rf-hero-slogan span, .rf-hero-cta, .rf-works-hero-title, .rf-play-btn, .rf-video-modal{
    transition-duration:.01ms !important; animation-duration:.01ms !important; animation-delay:0s !important;
  }
  /* Infinite loops can't just be sped to .01ms like the transitions above —
     that would strobe rather than stop — so each is disabled outright here
     and given a plain scrollable/static fallback instead. */
  .rf-project-carousel-track, .rf-test-track, .rf-marquee-track{ animation:none !important; }
  .rf-project-carousel, .rf-test-marquee, .rf-marquee{ overflow-x:auto; }
}

/* ---- Responsive ---- */
@media (max-width:900px){
  .rf-project-carousel-track, .rf-all-projects-grid{ gap:16px; }
  .rf-video-item{ width:min(320px,80vw); }
}
@media (max-width:600px){
  .rf-test-card{ padding:26px 22px; min-height:200px; }
  .rf-video-caption .rf-name{ font-size:15px; }
}

/* ==========================================================================
   WORKS PAGE
   New, namespaced classes only (rf-works-*) — nothing above this point was
   touched. Reuses the same design tokens (--rf-black/white/red, Inter,
   --rf-ease) already defined at the top of this file, so it matches the
   rest of the site automatically rather than inventing a new look.
   ========================================================================== */

/* ---- Hero ----
   The Works hero slider deliberately has no CSS of its own here — it
   reuses .rf-hero / .rf-hero-slide / .rf-hero-ph / .rf-hero-video /
   .rf-hero-content / .rf-hero-slogan verbatim from the Home page's own
   hero (defined earlier in this file), so it automatically matches the
   same cinematic treatment, transitions, and responsive behavior with
   zero duplicated rules. Content is still fully separate — different
   post type, edited independently. The one new piece is the small
   optional label shown above the slogan: */
.rf-works-hero-title{
  display:block; color:var(--rf-red); font-weight:700; font-size:13px;
  letter-spacing:.18em; text-transform:uppercase; margin-bottom:14px;
}

/* ---- Featured project (same caption system as the grid below) ----
   Shares the exact same max-width, centering, and side padding as the
   grid below, so the featured video's edges line up with the grid
   cards' edges regardless of how the surrounding Elementor section/
   column is configured. */
.rf-works-featured-wrap{
  background:var(--rf-black); padding:48px 24px;
  max-width:1400px; margin:0 auto; box-sizing:border-box;
}

/* ---- Grid ----
   Flexbox with justify-content:center rather than CSS Grid — Grid leaves
   a partial last row flush to the left when the project count doesn't
   divide evenly into full rows (e.g. 7 projects in a 3-per-row layout),
   which reads as uneven/off-center. Flexbox centers that partial row
   too, so spacing stays even on both sides regardless of project count. */
.rf-works-grid{
  background:var(--rf-black); padding:24px 24px 64px;
  max-width:1400px; margin:0 auto; box-sizing:border-box;
  display:flex; flex-wrap:wrap; justify-content:center; gap:40px 32px;
}
.rf-works-card{ display:flex; flex-direction:column; flex:0 1 360px; max-width:360px; }

/* ---- Caption: title prominent, metadata secondary, script title distinct ---- */
.rf-works-caption{ margin-top:20px; display:flex; flex-direction:column; gap:10px; font-family:'Inter', sans-serif; }
.rf-works-title{
  color:var(--rf-white); font-weight:800; font-size:clamp(15px,1.7vw,19px); text-transform:uppercase; letter-spacing:.01em;
}
.rf-works-meta{ display:flex; flex-direction:column; gap:3px; }
.rf-works-meta-line{ color:var(--rf-off); font-size:13px; letter-spacing:.02em; }
.rf-works-meta-label{ color:var(--rf-white); font-weight:600; }
.rf-works-script{ color:var(--rf-red); font-style:italic; font-size:13px; letter-spacing:.02em; }

/* ---- Scroll reveal for grid cards (fade/slide in, not everything dumped
   on the page at once). Purely visual — thumbnails already lazy-load via
   loading="lazy" regardless of this, and videos never load until clicked. ---- */
.rf-reveal{ opacity:0; transform:translateY(24px); transition:opacity .7s var(--rf-ease), transform .7s var(--rf-ease); }
.rf-reveal.rf-in{ opacity:1; transform:translateY(0); }

@media (prefers-reduced-motion: reduce){
  /* No CSS override needed here: rf-core.js already skips autoplay for
     reduced-motion visitors, so the <video> element just sits paused and
     shows its own poster attribute as a static image — same pattern as
     the Hero Slides background video. */
  .rf-reveal{ opacity:1; transform:none; transition:none; }
}

@media (max-width:900px){
  .rf-works-grid{ gap:32px 20px; }
  .rf-works-card{ flex-basis:300px; max-width:300px; }
}
@media (max-width:600px){
  .rf-works-grid{ padding:16px 16px 48px; }
  .rf-works-card{ flex-basis:100%; max-width:100%; }
}

/* ==========================================================================
   v1.11 / v1.12 ADDITIONS
   Everything above this line is unchanged except where noted in the
   changelog. Rules here are additive; every mobile rule sits inside
   @media (max-width:767px) — Elementor's default Mobile breakpoint and the
   SAME value as RF_MOBILE_MAX in rf-core.js (keep both in sync). 768px and
   up behaves exactly as before.
   ========================================================================== */

/* ---- Hero video: if a video errors on a device, rf-core.js adds this
   class and the poster image behind it (set on .rf-hero-ph) shows. ---- */
.rf-hero-video.rf-video-failed{ display:none; }

/* ---- Recent Projects: Client and Director on separate lines (desktop +
   mobile). Same type size/colour as the old single line. ---- */
.rf-meta-stacked{ display:flex; flex-direction:column; gap:3px; min-width:0; }
.rf-meta-line{ display:block; overflow-wrap:anywhere; }

/* ==== MOBILE (max-width:767px) ==== */
@media (max-width:767px){

  /* Defensive sizing for the plugin's own wrappers only (a theme without a
     global border-box reset would otherwise add padding on top of 100%
     widths/heights and push content past the screen edge). */
  .rf-hero-content, .rf-work, .rf-all-projects-wrap, .rf-featured-wrap,
  .rf-works-featured-wrap, .rf-works-grid, .rf-test-card{ box-sizing:border-box; }
  .rf-hero-content{ padding:0 22px 64px; }

  /* Hero height: 88vh is measured against the LARGEST phone viewport (browser
     toolbar hidden), so on a real phone it ends up taller than the visible
     screen, while the Elementor editor preview measures it against the
     preview frame. svh = the visible viewport, stable as the toolbar
     shows/hides. Browsers without svh keep the 88vh above. */
  @supports (height:1svh){ .rf-hero{ height:88svh; } }

  /* Recent Projects: all real cards share ONE grid cell, so the video stays
     in a fixed position and the area is the same width everywhere; the swap
     is a cross-fade in place (nothing slides). The duplicate (loop) set is
     hidden and the marquee animation is off. No arrows or controls. */
  .rf-project-carousel{ touch-action:pan-y; overflow:hidden; }
  .rf-project-carousel .rf-project-carousel-track{ display:grid; grid-template-columns:minmax(0,1fr); width:100%; gap:0; transform:none; animation:none !important; }
  .rf-project-carousel .rf-project-carousel-clone{ display:none; }
  .rf-project-carousel .rf-project-carousel-track > .rf-video-item{
    grid-area:1 / 1; width:100% !important; max-width:100%; flex:none !important; min-width:0; box-sizing:border-box;
    opacity:0; visibility:hidden; pointer-events:none;
    transition:opacity .45s var(--rf-ease), visibility 0s linear .45s;
  }
  .rf-project-carousel .rf-project-carousel-track > .rf-video-item.rf-is-current{
    opacity:1; visibility:visible; pointer-events:auto;
    transition:opacity .45s var(--rf-ease), visibility 0s;
  }
  /* whole frame visible (no cover-crop) inside the same 16:9 box, so every
     card keeps an identical video size and position */
  .rf-project-carousel .rf-video-block img{ object-fit:contain; }
  .rf-project-carousel .rf-video-caption{ min-width:0; }
  .rf-project-carousel .rf-video-caption .rf-name,
  .rf-project-carousel .rf-video-caption .rf-meta{ overflow-wrap:anywhere; }

  /* Testimonials: same technique — one grid cell, cross-fade, area grows to
     the tallest quote (no cut-off, no page jump). Duplicate set hidden. */
  .rf-test-marquee{ overflow:hidden; touch-action:pan-y; }
  .rf-test-track{ display:grid; grid-template-columns:minmax(0,1fr); width:100%; gap:0; transform:none; animation:none !important; }
  .rf-test-card{
    grid-area:1 / 1; width:auto; min-width:0;
    opacity:0; visibility:hidden; pointer-events:none;
    transition:opacity .45s var(--rf-ease), visibility 0s linear .45s;
  }
  .rf-test-card.rf-is-current{ opacity:1; visibility:visible; pointer-events:auto; transition:opacity .45s var(--rf-ease), visibility 0s; }
  .rf-test-card-dup{ display:none; }
  .rf-test-card blockquote{ overflow-wrap:anywhere; }
}

@media (max-width:767px) and (prefers-reduced-motion: reduce){
  .rf-project-carousel .rf-project-carousel-track > .rf-video-item,
  .rf-project-carousel .rf-project-carousel-track > .rf-video-item.rf-is-current,
  .rf-test-card, .rf-test-card.rf-is-current{ transition:none; }
}

/* ==========================================================================
   v1.12.1 — HERO HARDENING
   Additive only. Desktop look is unchanged; these rules only make the hero
   video harder for site-wide CSS to break, and remove the "dark gap" while
   a video is still starting.
   ========================================================================== */

/* 1. Fill the hero no matter what generic rules the theme / Elementor /
   Additional CSS apply to <video> (e.g. `.elementor video{height:auto}`),
   which otherwise shrinks the video to its intrinsic 16:9 height and leaves
   the dark background showing below it on phones. Three classes of
   specificity beats those rules without needing !important. */
.rf-hero .rf-hero-ph > .rf-hero-video{
  position:absolute; inset:0; width:100%; height:100%; max-width:none;
  object-fit:cover; object-position:center; z-index:0;
  /* 2. Stay invisible until the browser reports it is really playing. The
     identical still image sits on .rf-hero-ph underneath, so the visitor sees
     the poster, then the video fades in — never a black/blank video box. */
  opacity:0; transition:opacity .5s ease;
}
.rf-hero .rf-hero-ph > .rf-hero-video.rf-is-playing{ opacity:1; }

/* 3. Touch devices only: enlarge the CTA's tappable area without changing how
   it looks (the visible underline/size stay as they were). */
@media (pointer:coarse){
  .rf-hero-cta{ position:relative; }
  .rf-hero-cta::after{ content:''; position:absolute; inset:-14px -10px; }
}

/* 4. Mobile: a word longer than the line wraps instead of being clipped by the
   slogan's overflow:hidden (no effect when every word already fits). */
@media (max-width:767px){
  .rf-hero-slogan{ overflow-wrap:anywhere; }
}


/* ==========================================================================
   v1.13 — HERO TEXT ANIMATION, TIED TO THE SLIDE'S STATE
   Why: the old reveal was a CSS *transition*, and transitions never run for a
   slide that is already .active on first paint — so slide 1 had no entrance,
   and extra `animation:` rules in Additional CSS (run once at page load, for
   every slide, filled forward) were standing in for it. These are CSS
   *animations* keyed to .active / .rf-leaving, so they play on first load AND
   on every slide change, in step with the video crossfade. Same motion as
   before: mask slide-up for the slogan, fade-rise for the slogan block and the
   CTA (the timings from your Additional CSS).
   You can now delete the .rf-hero-slogan / .rf-hero-cta `animation:` rules and
   the rf-slogan-in / rf-button-in keyframes from Additional CSS.
   ========================================================================== */
@keyframes rf-hero-reveal  { from{ transform:translateY(110%); } to{ transform:translateY(0); } }
@keyframes rf-hero-hide    { from{ transform:translateY(0); }    to{ transform:translateY(110%); } }
@keyframes rf-hero-rise    { from{ opacity:0; transform:translateY(25px); } to{ opacity:1; transform:translateY(0); } }
@keyframes rf-hero-cta-in  { from{ opacity:0; transform:translateY(15px); } to{ opacity:1; transform:translateY(0); } }
@keyframes rf-hero-fade-in { from{ opacity:0; } to{ opacity:1; } }
@keyframes rf-hero-fade-out{ from{ opacity:1; } to{ opacity:0; } }

/* Neutralise stray site-wide animation rules so a slide's text can't restart
   itself when the slide stops being active (specificity 0,2,0 beats 0,1,0). */
.rf-hero .rf-hero-slogan,
.rf-hero .rf-hero-cta{ animation:none; }

/* Entrance — starts the instant the slide becomes .active (page load, or the swap) */
.rf-hero-slide.active .rf-hero-slogan{ animation:rf-hero-rise 2s ease-out both; }
.rf-hero-slide.active .rf-hero-slogan span{ animation:rf-hero-reveal .9s var(--rf-ease) .3s both; }
.rf-hero-slide.active .rf-hero-cta{ animation:rf-hero-cta-in 1s ease-out .5s both; }
.rf-hero-slide.active .rf-works-hero-title{ animation:rf-hero-fade-in .8s ease-out .15s both; }

/* Exit — the outgoing slide's text leaves quickly while its video is still
   showing underneath, so two slogans never sit on top of each other */
.rf-hero-slide.rf-leaving .rf-hero-slogan span{ animation:rf-hero-hide .45s ease-in both; }
.rf-hero-slide.rf-leaving .rf-hero-cta,
.rf-hero-slide.rf-leaving .rf-works-hero-title{ animation:rf-hero-fade-out .4s ease-in both; }
