/* One cinematic frame: full bleed where it fits, a glow taken from the film itself where it cannot. */
.hero--cinematic {
  padding-top: 0;
  height: 100svh;
  overflow: clip;
  background: var(--rc-page, #e0e6ed);
  color: #fffaf0;
}
.hero-stage {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  container-type: size;
  background: var(--rc-page, #e0e6ed);
}
/* 140svh of travel: the descent from the clouds to the city, then a short hold while the city bleeds out. */
.hero--cinematic[data-scroll-cinematic="true"] {
  height: 240svh;
  aspect-ratio: auto;
}
.hero--cinematic[data-scroll-cinematic="true"] .hero-stage {
  position: sticky;
  inset: auto;
  top: 0;
  height: 100svh;
}
/* The bleed now lives on the stage (below the claim), so the old hero-level veil is retired. */
.hero--cinematic::after { content: none; }
/* Bleed into the page colour: eased alpha, fully solid at the stage's bottom edge, so the city flows into the next
   section with no seam. --hero-veil (hero-transition.js) brings it in as the descent lands; still states keep it on. */
.hero-stage::after {
  content: "";
  position: absolute;
  z-index: 3;
  inset: auto 0 0;
  height: min(40%, 460px);
  background: linear-gradient(180deg, var(--rc-page-clear, #e0e6ed00), #e0e6ed17 20%, #e0e6ed4d 40%, #e0e6ed94 60%, #e0e6edd6 80%, var(--rc-page, #e0e6ed));
  background: linear-gradient(180deg,
    var(--rc-page-clear, #e0e6ed00),
    color-mix(in srgb, var(--rc-page, #e0e6ed) 9%, transparent) 20%,
    color-mix(in srgb, var(--rc-page, #e0e6ed) 30%, transparent) 40%,
    color-mix(in srgb, var(--rc-page, #e0e6ed) 58%, transparent) 60%,
    color-mix(in srgb, var(--rc-page, #e0e6ed) 84%, transparent) 80%,
    var(--rc-page, #e0e6ed));
  opacity: var(--hero-veil, 0);
  pointer-events: none;
}
.hero--cinematic[data-cinematic-state="poster"] .hero-stage::after { opacity: 1; }

/* 4:3 and wider: the film covers the whole stage, so nothing sits behind it. */
.hero-poster,
.hero-film {
  position: absolute;
  top: 50%;
  left: 50%;
  display: block;
  width: 100%;
  width: max(100cqw, 100cqh * 16 / 9);
  max-width: none;
  height: auto;
  aspect-ratio: 16 / 9;
  transform: translate(-50%, -50%);
  object-fit: cover;
  object-position: center;
  pointer-events: none;
}
/* The poster is the cloud frame the page opens on. It shows while the film loads and stays a moment under the
   film's fade-in, then drops away so it can never show through the film's feathered edges. */
.hero-poster { z-index: 1; opacity: 0; transition: opacity 0s linear .4s; }
.hero--cinematic:is([data-cinematic-state="poster"], [data-cinematic-state="loading"]) .hero-poster { opacity: 1; transition: none; }
.hero-film {
  z-index: 2;
  opacity: 0;
  transition: opacity .35s ease;
}
.hero--cinematic:is([data-cinematic-state="scrubbing"], [data-cinematic-state="held"], [data-cinematic-state="ambient"], [data-cinematic-state="ambient-paused"]) [data-hero-film] { opacity: 1; }
/* Frame-blend twin (added by hero-motion.js on wide layouts with a mouse): it sits just above the film and shows the
   neighbouring frame at --hero-blend, which follows the scroll position every refresh, so it has no transition. */
.hero-film-twin { transition: none; }
.hero--cinematic:is([data-cinematic-state="scrubbing"], [data-cinematic-state="held"], [data-cinematic-state="ambient"], [data-cinematic-state="ambient-paused"]) .hero-film-twin { opacity: var(--hero-blend, 0); }
.hero-ambient { z-index: 3; }
.hero--cinematic:is([data-cinematic-state="ambient"], [data-cinematic-state="ambient-paused"]) .hero-ambient { opacity: 1; }

/* Fly-in (hero-motion.js, data-hero-intro): the page opens on RingCentral alone in the clouds (the clip's poster), the
   Winspeed W streaks in and lands, and the cloud loop takes over from the landing frame. pending → playing → landed →
   done, or skipped (reduced motion, a slow or failed clip, or a reader who scrolls first: today's opening). */
.hero-flyin { z-index: 3; }
.hero--cinematic:is([data-hero-intro="pending"], [data-hero-intro="playing"], [data-hero-intro="landed"]) .hero-flyin { opacity: 1; transition: none; }
.hero--cinematic[data-hero-intro="skipped"] .hero-flyin { transition-duration: .2s; }
/* The W poster stays hidden under the clip, so it can never flash before the start frame paints. */
.hero--cinematic:is([data-hero-intro="pending"], [data-hero-intro="playing"], [data-hero-intro="landed"]) .hero-poster { opacity: 0; transition: none; }
.hero--cinematic:is([data-hero-intro="pending"], [data-hero-intro="playing"]) .hero-stage::before { background-image: url("assets/city-flyin-start.webp?v=3"); }
/* The claim arrives once the W has landed. */
.hero--cinematic[data-hero-intro] .hero-claim { transition: opacity .6s ease, transform .6s cubic-bezier(.2, .7, .2, 1); }
.hero--cinematic:is([data-hero-intro="pending"], [data-hero-intro="playing"]) .hero-claim { opacity: 0; transform: translate3d(-50%, 18px, 0); }
/* If the script never runs, the opening still resolves to the W poster and the claim. */
.hero--cinematic[data-hero-intro="pending"] .hero-flyin { animation: hero-intro-fallback-out .4s ease 5s forwards; }
.hero--cinematic[data-hero-intro="pending"] :is(.hero-poster, .hero-claim) { animation: hero-intro-fallback-in .4s ease 5s forwards; }
@keyframes hero-intro-fallback-out { to { opacity: 0; } }
@keyframes hero-intro-fallback-in { to { opacity: 1; } }

/* Claim: real text under the logos (frame y ≈ 35–64 %), measured on the covered frame so it tracks the crop at every
   aspect ratio. Visible from the first paint at the top; --hero-claim (controller) fades it out early in the descent,
   drifting up with the page, and back in on the climb. */
.hero-claim {
  position: absolute;
  z-index: 4;
  top: calc(50cqh + .14 * max(100cqh, 56.25cqw) + 2.2cqh);
  left: 50%;
  box-sizing: border-box;
  width: max-content;
  max-width: min(92cqw, 980px);
  margin: 0;
  padding: clamp(16px, 1.35vw, 24px) clamp(24px, 2.5vw, 46px);
  border-radius: var(--rc-radius-lg, 28px);
  background: #ffffffd9;
  box-shadow: var(--rc-shadow-lift, 0 2px 4px #2b29260d, 0 18px 40px #2b292617);
  color: var(--rc-ink, #2b2926);
  font-family: var(--font, NeueHaasGroteskDisplayPro, Helvetica, Arial, sans-serif);
  text-align: center;
  opacity: var(--hero-claim, 1);
  transform: translate3d(-50%, calc((var(--hero-claim, 1) - 1) * 22px), 0);
  pointer-events: none;
}
.hero-claim-title {
  margin: 0;
  color: inherit;
  font: 500 clamp(30px, 2.3vw, 44px) / 1.08 var(--font, NeueHaasGroteskDisplayPro, Helvetica, Arial, sans-serif);
  letter-spacing: -.015em;
  text-wrap: balance;
}
.hero-claim-basis {
  margin: .55em 0 0;
  color: var(--rc-ink-2, #2b2926b3);
  font: 500 clamp(16px, .95vw, 18px) / 1.3 var(--font, NeueHaasGroteskDisplayPro, Helvetica, Arial, sans-serif);
}
/* Same treatment as "20 – 50": orange gradient clipped to the glyphs with one soft glow. */
.hero-claim-rank {
  display: inline-block;
  color: var(--rc-orange, #ff7a00);
  background: linear-gradient(180deg, #ffa451 0%, #ff7a00 56%, #f06200 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 2px 16px #ff8a3d80);
}
/* The poster is the cloud frame, so still states show the claim in place. */
.hero--cinematic[data-cinematic-state="poster"] .hero-claim {
  opacity: 1;
  transform: translate3d(-50%, 0, 0);
}

/* Glow layers: a blurred copy of the visible still, then the live 48 × 27 canvas drawn from the film. */
.hero-stage::before,
.hero-glow {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: none;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: blur(26px) saturate(1.06);
  transform: scale(1.2);
  /* Fade into the page colour before the stage edge (the layer is scaled 1.2×, so 90 % lands at ~98 % of the stage). */
  -webkit-mask-image: linear-gradient(180deg, #000 52%, transparent 90%);
  mask-image: linear-gradient(180deg, #000 52%, transparent 90%);
  pointer-events: none;
}
.hero-stage::before {
  content: "";
  background: var(--rc-page, #e0e6ed) url("assets/city-flight-hero.webp?v=2") center / cover no-repeat;
}
.hero-glow {
  opacity: 0;
  transition: opacity .4s ease;
}
.hero-glow[data-painted] { opacity: 1; }
.hero--cinematic[data-cinematic-state="poster"] .hero-glow { opacity: 0; }

/* Narrower than 4:3: keep both logos whole, enlarge the film slightly and feather it into its own glow. */
@media (max-aspect-ratio: 1279/960) {
  /* Room under the film for the claim; the film and claim are centred together. */
  .hero--cinematic { --hero-claim-room: 132px; height: min(100svh, calc(67.5vw + var(--hero-claim-room) + 48px)); }
  .hero-stage::after { height: min(20%, 120px); }
  /* The descent lands on the city: below the logos, the film and the glow under it bleed into the page colour,
     solid just past the film's bottom edge, so the stage leaves on the page colour (no murky band before the next section). */
  .hero--cinematic[data-scroll-cinematic="true"] .hero-stage::after {
    --hero-bleed: calc(23.75vw + 28px);
    top: calc(50% - var(--hero-claim-room) / 2 + 10vw);
    height: auto;
    background: linear-gradient(180deg, var(--rc-page-clear, #e0e6ed00), #e0e6ed17 calc(var(--hero-bleed) * .2), #e0e6ed4d calc(var(--hero-bleed) * .4), #e0e6ed94 calc(var(--hero-bleed) * .6), #e0e6edd6 calc(var(--hero-bleed) * .8), var(--rc-page, #e0e6ed) var(--hero-bleed));
  }
  .hero-glow,
  .hero--cinematic:is([data-cinematic-state="poster"], [data-cinematic-state="loading"]) .hero-stage::before { display: block; }
  .hero-poster,
  .hero-film {
    top: calc(50% - var(--hero-claim-room) / 2);
    width: 100%;
    width: 120cqw;
    -webkit-mask-image: linear-gradient(180deg, transparent, #000 12%, #000 88%, transparent);
    mask-image: linear-gradient(180deg, transparent, #000 12%, #000 88%, transparent);
  }
  .hero-claim {
    top: calc(50cqh - var(--hero-claim-room) / 2 + 33.75cqw + 14px);
    max-width: calc(100cqw - 32px);
    padding: 14px 20px 15px;
    border-radius: var(--rc-radius-md, 20px);
  }
  .hero-claim-title { font-size: clamp(21px, 6.2vw, 30px); line-height: 1.1; }
  .hero-claim-basis { margin-top: .45em; font-size: 15px; }
}
@media (prefers-reduced-motion: reduce) {
  html:not([data-motion="full"]) .hero-film,
  html:not([data-motion="full"]) .hero-glow { transition: none; }
  /* The still (cloud poster, claim, bleed) from the first paint, before the controller settles the poster state. */
  html:not([data-motion="full"]) .hero--cinematic[data-cinematic-state="loading"] .hero-claim { opacity: 1; transform: translate3d(-50%, 0, 0); }
  html:not([data-motion="full"]) .hero--cinematic[data-cinematic-state="loading"] .hero-stage::after { opacity: 1; }
  /* No fly-in: today's still (W poster and claim) from the first paint. */
  html:not([data-motion="full"]) .hero-flyin { display: none; }
  html:not([data-motion="full"]) .hero--cinematic[data-hero-intro] .hero-poster { opacity: 1; animation: none; }
  html:not([data-motion="full"]) .hero--cinematic[data-hero-intro] .hero-stage::before { background-image: url("assets/city-flight-hero.webp?v=2"); }
  html:not([data-motion="full"]) .hero--cinematic[data-hero-intro] .hero-claim { opacity: 1; transform: translate3d(-50%, 0, 0); transition: none; animation: none; }
}

/* Handoff: the first block of whichever section follows the hero rises in as the hero releases
   (values from hero-transition.js; reduced motion leaves it in place). */
.hero--cinematic + section > .wrap > :first-child {
  transform: translate3d(0, var(--hero-handoff-rise, 0px), 0);
  opacity: var(--hero-handoff-reveal, 1);
}
