:root {
  --content-font: "Google Sans", "Google Sans Text", "Product Sans",
                  "Helvetica Neue", Inter, system-ui, -apple-system, sans-serif;
}

.below {
  min-height: 0;
  color: #f5f5f7;
  font-family: var(--content-font);
}

.content-page {
  --page-gutter: clamp(22px, 5vw, 72px);
  background: #000;
}

.audience-strip {
  width: min(1120px, calc(100% - var(--page-gutter) * 2));
  margin: 0 auto;
  padding: 46px 0 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  color: #8d8d96;
  font-size: 13px;
  letter-spacing: 0.01em;
}

.audience-strip strong {
  color: #d5d5da;
  font-weight: 500;
}

.audience-strip a {
  color: #a99cff;
  text-decoration: none;
}

.content-group {
  --accent: #9f8cff;
  position: relative;
  /* Skip layout and paint for sections that are off screen. `auto` on the
     intrinsic size means each one remembers its real height after being shown
     once, so the scrollbar does not jump around. */
  content-visibility: auto;
  contain-intrinsic-size: auto 895px;
  width: min(1240px, calc(100% - var(--page-gutter) * 2));
  min-height: min(920px, 94svh);
  margin: 0 auto;
  padding: clamp(90px, 12vw, 170px) 0 clamp(80px, 10vw, 140px);
  overflow: hidden;
}

.content-group + .content-group {
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.content-copy {
  position: relative;
  z-index: 2;
  width: min(940px, 100%);
  margin: 0 auto clamp(56px, 8vw, 104px);
  text-align: center;
}

.content-eyebrow {
  margin-bottom: 20px;
  color: var(--accent);
  font-size: clamp(18px, 2vw, 25px);
  font-weight: 600;
  letter-spacing: -0.015em;
}

.content-title {
  max-width: 980px;
  margin: 0 auto;
  color: #f5f5f7;
  font-size: clamp(48px, 7.4vw, 106px);
  font-weight: 600;
  line-height: 0.97;
  letter-spacing: -0.062em;
  text-wrap: balance;
}

.content-body {
  max-width: 760px;
  margin: clamp(28px, 4vw, 48px) auto 0;
  color: #92929b;
  font-size: clamp(19px, 2.1vw, 28px);
  font-weight: 500;
  line-height: 1.42;
  letter-spacing: -0.028em;
  text-wrap: balance;
}

.content-visual {
  position: relative;
  width: min(1100px, 100%);
  min-height: 430px;
  margin: 0 auto;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: clamp(26px, 3.4vw, 48px);
  background:
    radial-gradient(circle at 50% 0%, color-mix(in srgb, var(--accent) 20%, transparent), transparent 46%),
    linear-gradient(150deg, #131318, #070708 68%);
  box-shadow: inset 0 1px rgba(255, 255, 255, 0.06), 0 40px 100px rgba(0, 0, 0, 0.45);
  overflow: hidden;
}

.fact-row {
  position: absolute;
  left: clamp(22px, 4vw, 54px);
  right: clamp(22px, 4vw, 54px);
  bottom: clamp(22px, 3.4vw, 42px);
  z-index: 3;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border: 1px solid rgba(255, 255, 255, 0.09);
  border-radius: 22px;
  background: rgba(13, 13, 17, 0.7);
  backdrop-filter: blur(24px) saturate(150%);
  -webkit-backdrop-filter: blur(24px) saturate(150%);
}

.fact {
  min-width: 0;
  padding: 22px clamp(16px, 3vw, 34px);
}

.fact + .fact { border-left: 1px solid rgba(255, 255, 255, 0.08); }

.fact-value,
.fact-label { display: block; }

.fact-value {
  color: #fff;
  font-size: clamp(20px, 2.5vw, 34px);
  font-weight: 600;
  letter-spacing: -0.04em;
}

.fact-label {
  margin-top: 4px;
  color: #8e8e97;
  font-size: clamp(12px, 1.3vw, 15px);
}

/* Protection: a soft scanner made from concentric rings. */
.stealth-orbit {
  position: absolute;
  left: 50%;
  top: 43%;
  width: min(58vw, 510px);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border: 1px solid color-mix(in srgb, var(--accent) 34%, transparent);
  border-radius: 50%;
  box-shadow:
    0 0 0 54px color-mix(in srgb, var(--accent) 5%, transparent),
    0 0 0 108px color-mix(in srgb, var(--accent) 3%, transparent),
    0 0 100px color-mix(in srgb, var(--accent) 20%, transparent);
}

.stealth-orbit::before,
.stealth-orbit::after {
  content: "";
  position: absolute;
  border-radius: 50%;
}

.stealth-orbit::before {
  inset: 18%;
  border: 1px dashed color-mix(in srgb, var(--accent) 54%, transparent);
}

.stealth-orbit::after {
  inset: 41%;
  background: var(--accent);
  box-shadow: 0 0 32px var(--accent), 0 0 100px var(--accent);
}

.stealth-state {
  position: absolute;
  left: 50%;
  top: 42%;
  z-index: 2;
  transform: translate(-50%, -50%);
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* Combat: an abstract target reticle, deliberately product-like rather than game UI. */
.combat-grid {
  position: absolute;
  inset: 0;
  opacity: 0.42;
  background-image:
    linear-gradient(rgba(255,255,255,.055) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.055) 1px, transparent 1px);
  background-size: 54px 54px;
  mask-image: radial-gradient(circle at 50% 38%, black, transparent 68%);
}

.reticle {
  position: absolute;
  left: 50%;
  top: 42%;
  width: min(50vw, 350px);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border: 1px solid color-mix(in srgb, var(--accent) 60%, transparent);
  border-radius: 50%;
  box-shadow: 0 0 80px color-mix(in srgb, var(--accent) 15%, transparent);
}

.reticle::before,
.reticle::after {
  content: "";
  position: absolute;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
}

.reticle::before { left: -22%; top: 50%; width: 144%; height: 1px; }
.reticle::after { top: -22%; left: 50%; height: 144%; width: 1px; }

.reticle-core {
  position: absolute;
  inset: 34%;
  border: 2px solid #fff;
  border-radius: 50%;
  box-shadow: 0 0 22px var(--accent);
}

/* Movement: luminous route with stepped markers. */
.route {
  position: absolute;
  left: 8%;
  right: 8%;
  top: 41%;
  height: 150px;
  transform: translateY(-50%) skewX(-12deg);
}

.route::before {
  content: "";
  position: absolute;
  left: 3%;
  right: 3%;
  top: 50%;
  height: 8px;
  border-radius: 99px;
  background: linear-gradient(90deg, transparent, var(--accent) 18%, #fff 52%, var(--accent) 82%, transparent);
  box-shadow: 0 0 22px var(--accent), 0 0 70px color-mix(in srgb, var(--accent) 45%, transparent);
}

.route-node {
  position: absolute;
  top: 50%;
  width: 30px;
  height: 30px;
  transform: translate(-50%, -50%);
  border: 5px solid #fff;
  border-radius: 50%;
  background: #090a0d;
  box-shadow: 0 0 0 1px var(--accent), 0 0 24px var(--accent);
}

.route-node:nth-child(1) { left: 18%; }
.route-node:nth-child(2) { left: 49%; top: 30%; }
.route-node:nth-child(3) { left: 82%; top: 67%; }

/* Interface: use the real current Rise GUI artwork already in the project. */
.interface-window {
  position: absolute;
  left: 7%;
  right: 7%;
  top: 8%;
  height: 74%;
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 24px 24px 0 0;
  background: #0d0d12;
  box-shadow: 0 22px 90px color-mix(in srgb, var(--accent) 22%, transparent);
  overflow: hidden;
}

.interface-window::before {
  content: "Rise / Your setup";
  display: flex;
  align-items: center;
  height: 38px;
  padding: 0 16px;
  border-bottom: 1px solid rgba(255,255,255,.08);
  color: #777782;
  font: 11px/1 var(--content-font);
  letter-spacing: .04em;
}

.interface-window img {
  display: block;
  width: 100%;
  height: calc(100% - 38px);
  object-fit: cover;
  object-position: top center;
  opacity: .9;
}

/* Community: oversized proof points floating behind the shared fact row. */
.proof-cloud {
  position: absolute;
  inset: 8% 5% 27%;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  align-items: center;
  gap: 16px;
}

.proof-card {
  padding: 42px 18px;
  border: 1px solid rgba(255,255,255,.1);
  border-radius: 28px;
  background: rgba(255,255,255,.035);
  color: #fff;
  text-align: center;
}

.proof-card:nth-child(2) { transform: translateY(-28px); }
.proof-card span { display: block; }
.proof-card .proof-big { color: var(--accent); font-size: clamp(34px, 5vw, 66px); font-weight: 600; letter-spacing: -.06em; }
.proof-card .proof-small { margin-top: 8px; color: #888892; font-size: 13px; }

.content-empty,
.content-error {
  width: min(760px, calc(100% - 44px));
  margin: 0 auto;
  padding: 120px 0;
  color: #9a9aa3;
  text-align: center;
  font-family: var(--content-font);
  font-size: 20px;
  line-height: 1.5;
}

.content-error a { color: #b4a9ff; }

body.is-content-preview .bg,
body.is-content-preview .scrim,
body.is-content-preview .stage,
body.is-content-preview .topbar { display: none; }

body.is-content-preview .audience-strip { padding-top: 24px; }

body.is-editor-preview .topbar { display: none; }

body.is-map-preview .topbar { display: none; }

/* The editor's minimap renders the real page inside a very tall virtual
   viewport. Fixed heights prevent svh-based sections from growing when that
   iframe is expanded to the document's full scroll height. */
body.is-map-preview .bg,
body.is-map-preview .scrim,
body.is-map-preview .stage { height: 720px; }

body.is-map-preview .audience-strip { height: 82px; padding: 0; }
body.is-map-preview .content-group { height: 1200px; min-height: 0; }
body.is-map-preview .content-copy,
body.is-map-preview .content-visual { animation: none !important; }
body.is-map-preview .is-map-hidden { opacity: .22; filter: grayscale(.75); }

/* Each editor minimap row is a real responsive render of its page section.
   The iframe keeps a 1280px desktop canvas and varies only its height so the
   preview and its drag target always have the exact same aspect ratio. */
body.is-map-card {
  width: 1280px;
  min-width: 1280px;
  height: 100vh;
  overflow: hidden;
}

body.is-map-card .topbar { display: none; }
body.is-map-card .content-copy,
body.is-map-card .content-visual { animation: none !important; }
body.is-map-card .is-map-hidden { opacity: .22; filter: grayscale(.75); }

body.is-map-card-landing .bg,
body.is-map-card-landing .scrim,
body.is-map-card-landing .stage { height: 100vh; }
body.is-map-card-landing .below { display: none; }
body.is-map-card-landing { --logo-w: min(56vw, 640px); }

body.is-map-card-section .bg,
body.is-map-card-section .scrim,
body.is-map-card-section .stage { display: none; }
body.is-map-card-section .below,
body.is-map-card-section .content-page {
  height: 100vh;
  min-height: 0;
  overflow: hidden;
}
body.is-map-card-section .audience-strip { display: none; }
body.is-map-card-section .content-group {
  width: min(1160px, calc(100% - 96px));
  height: 100vh;
  min-height: 0;
  margin: 0 auto;
  padding: clamp(38px, 7vh, 68px) 0 clamp(28px, 5vh, 48px);
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  overflow: hidden;
}
body.is-map-card-section .content-copy {
  width: min(1000px, 100%);
  margin: 0 auto clamp(22px, 4vh, 40px);
}
body.is-map-card-section .content-eyebrow {
  margin-bottom: clamp(10px, 2vh, 16px);
  font-size: clamp(17px, 3vh, 23px);
}
body.is-map-card-section .content-title {
  font-size: clamp(46px, 8vh, 78px);
  line-height: .96;
}
body.is-map-card-section .content-body {
  margin-top: clamp(18px, 3vh, 30px);
  font-size: clamp(17px, 3vh, 23px);
  line-height: 1.35;
}
body.is-map-card-section .content-visual {
  width: min(1100px, 100%);
  height: 100%;
  min-height: 0;
  border-radius: clamp(20px, 4vh, 38px);
}

body.is-landing-hidden .bg,
body.is-landing-hidden .scrim,
body.is-landing-hidden .stage { display: none; }

body.is-landing-hidden .audience-strip { padding-top: 34px; }

@media (max-width: 700px) {
  .content-page { --page-gutter: 18px; }
  .audience-strip { align-items: flex-start; flex-direction: column; gap: 8px; }
  .content-group { min-height: 0; padding: 84px 0; }
  .content-copy { margin-bottom: 48px; }
  .content-title { font-size: clamp(44px, 13vw, 70px); }
  .content-body { font-size: 19px; }
  .content-visual { min-height: 490px; }
  .fact-row { grid-template-columns: 1fr; }
  .fact + .fact { border-left: 0; border-top: 1px solid rgba(255,255,255,.08); }
  .fact { padding: 14px 18px; }
  .stealth-orbit, .reticle { width: 270px; }
  .proof-cloud { grid-template-columns: 1fr 1fr; align-content: start; }
  .proof-card { padding: 24px 12px; }
  .proof-card:nth-child(2) { transform: none; }
  .proof-card:nth-child(3) { grid-column: 1 / -1; }
}

@media (prefers-reduced-motion: no-preference) {
  .content-group .content-copy,
  .content-group .content-visual {
    animation: contentReveal .7s cubic-bezier(.2,.7,.2,1) both;
    animation-timeline: view();
    animation-range: entry 8% cover 32%;
  }

  @keyframes contentReveal {
    from { opacity: .2; transform: translateY(38px); }
    to { opacity: 1; transform: none; }
  }
}

/* ---- Translator: drag-to-compare between two identical captures ---- */
/* Full-bleed and a single screenful: the frame, background and padding every
   other visual gets are dropped so the capture itself is the section, and the
   copy sits over it rather than above it. The group clips its children, so
   that has to be reopened for the break-out to escape the text column. */
.is-showcase {
  overflow: visible;
  min-height: 0;
  padding: clamp(26px, 4.5vh, 60px) 0;
}

/* A capture whose copy sits above it rather than over it wants the same frame
   and the same full-bleed treatment — just not the overlay. */
.is-media {
  overflow: visible;
}

.is-showcase .content-visual,
.is-media .content-visual {
  --bleed: clamp(16px, 2.6vw, 44px);
  width: calc(100vw - var(--bleed) * 2);
  max-width: none;
  min-height: 0;
  /* Margin rather than a transform: the scroll-reveal animation on
     .content-visual sets transform, and an animation overrides a declared
     value, so a translate here would be silently discarded. */
  margin-left: calc(50% - 50vw + var(--bleed));
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  overflow: visible;
}

.compare-wrap { width: 100%; }

.compare {
  position: relative;
  /* Widest that still fits the viewport height at the capture's aspect, with
     room left for the section padding so the whole thing is one screenful.
     The cap is deliberately a fixed ratio rather than each frame's own: capping
     by --frame-ratio makes a taller clip come out narrower than the captures
     beside it, and every frame in the column should share one width. Only the
     height varies with the footage. */
  --frame-ratio: 1.7356;
  --frame-cap-ratio: 1.7356;
  width: min(100%, calc(82svh * var(--frame-cap-ratio)));
  margin-inline: auto;
  aspect-ratio: var(--frame-ratio);
  /* Copy laid over a capture should scale with the capture, not the viewport:
     the frame is height-capped on short windows, so vw-based type drifts out
     of proportion with the image it sits on. */
  container-type: inline-size;
  container-name: showcase;
  border-radius: clamp(18px, 2vw, 30px);
  overflow: hidden;
  background: #05050a;
  box-shadow: 0 22px 60px rgba(0, 0, 0, 0.5);
  cursor: ew-resize;
  touch-action: none;          /* own the horizontal drag on touch */
  user-select: none;
  outline: none;
}

.compare:focus-visible {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 70%, transparent),
              0 22px 60px rgba(0, 0, 0, 0.5);
}

.compare img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  /* contain, not cover: the frame's aspect is hard-coded to the current pair,
     so cover would quietly crop the edges off any capture with a slightly
     different shape. */
  object-fit: contain;
  pointer-events: none;
  -webkit-user-drag: none;
}

/* Revealed from the left edge across to the handle. */
.compare .compare-top {
  clip-path: inset(0 calc(100% - var(--split)) 0 0);
}

/* The divider. Nothing here transitions or animates — it must sit exactly
   where the cursor is on the same frame, with no easing or catch-up. */
.compare-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--split);
  z-index: 4;
  width: 2px;
  margin-left: -1px;
  background: rgba(255, 255, 255, 0.92);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.28);
  pointer-events: none;
  transition: none;
}

.compare-knob {
  position: absolute;
  top: 50%;
  left: 50%;
  width: clamp(34px, 3.4vw, 44px);
  height: clamp(34px, 3.4vw, 44px);
  margin: calc(clamp(34px, 3.4vw, 44px) / -2) 0 0 calc(clamp(34px, 3.4vw, 44px) / -2);
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.96);
  color: #16161a;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45);
  transition: none;
}

.compare-knob svg { width: 58%; height: 58%; }

.compare-tag {
  position: absolute;
  /* Along the bottom now that the copy occupies the top of the frame. */
  bottom: clamp(12px, 1.6vw, 20px);
  z-index: 2;
  padding: 7px 14px;
  border-radius: 980px;
  background: rgba(12, 12, 16, 0.62);
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  color: #f5f5f7;
  font-size: clamp(12px, 1.2vw, 15px);
  letter-spacing: 0.01em;
  pointer-events: none;
}

.compare-tag-left  { left: clamp(12px, 1.6vw, 20px); }
.compare-tag-right { right: clamp(12px, 1.6vw, 20px); }

.compare-hint {
  position: absolute;
  left: 50%;
  bottom: clamp(12px, 1.6vw, 20px);
  transform: translateX(-50%);
  z-index: 2;
  padding: 6px 13px;
  border-radius: 980px;
  background: rgba(12, 12, 16, 0.6);
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  color: #c9c9d1;
  font-size: clamp(11px, 1.1vw, 13px);
  white-space: nowrap;
  pointer-events: none;
  transition: opacity 0.24s ease;
}

.compare:hover .compare-hint,
.compare:focus-within .compare-hint { opacity: 0; }

.compare-caption {
  margin: clamp(14px, 1.8vw, 20px) auto 0;
  max-width: 720px;
  color: #8b8b94;
  font-size: clamp(13px, 1.3vw, 16px);
  line-height: 1.45;
  text-align: center;
}

@media (max-width: 720px) {
  .compare-hint { display: none; }
}

/* ---- Copy laid over the bottom of the capture ---- */
.is-showcase .content-copy {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: 5;
  width: auto;
  margin: 0;
  /* Roomier below the text than above it, so the scrim has somewhere to fade
     out before it reaches the scene. */
  padding: clamp(20px, 3vh, 34px) clamp(26px, 5vw, 76px) clamp(34px, 5.5vh, 62px);
  text-align: center;
  pointer-events: none;
  /* The blur is a separate layer underneath (.compare-blur); this only
     darkens, so the text stays legible over whatever is behind it. */
  background: linear-gradient(to bottom,
    rgba(0, 0, 0, 0.72) 0%,
    rgba(0, 0, 0, 0.45) 45%,
    rgba(0, 0, 0, 0.12) 78%,
    transparent 100%);
  /* Feather out at the bottom so there is no hard edge across the shot. */
  mask-image: linear-gradient(to bottom, #000 62%, transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, #000 62%, transparent 100%);
}

/* Scaled right down from the full-section sizes, which are built for a
   headline standing on its own. */
.is-showcase .content-eyebrow {
  margin-bottom: clamp(6px, 0.9vh, 12px);
  font-size: clamp(13px, 1.35vw, 17px);
}

.is-showcase .content-title {
  font-size: clamp(24px, 3.3vw, 46px);
  line-height: 1.04;
  letter-spacing: -0.035em;
}

.is-showcase .content-body {
  max-width: min(1000px, 100%);
  margin: clamp(8px, 1.3vh, 16px) auto 0;
  font-size: clamp(11px, 1.15vw, 15px);
  font-weight: 400;
  line-height: 1.55;
  letter-spacing: -0.005em;
  color: #e9e9ef;
}

/* The tags would collide with the copy on a short viewport. */
@media (max-height: 620px) {
  .is-showcase .content-body { display: none; }
}

/* Blurred copy of the capture, confined to a strip along the bottom. Sitting
   under the copy, above the sharp images. */
.compare-blur {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 42%;
  z-index: 4;
  overflow: hidden;
  pointer-events: none;
  /* Carries the frame's corners itself: the mask below establishes its own
     paint context, which can escape the parent's rounded overflow clip and
     square off the corners it touches. */
  border-top-left-radius: clamp(18px, 2vw, 30px);
  border-top-right-radius: clamp(18px, 2vw, 30px);
  /* Feathers the bottom of the blur so there is no hard line across the shot. */
  mask-image: linear-gradient(to bottom, #000 58%, transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, #000 58%, transparent 100%);
}

/* Full-frame and bottom-anchored so it lines up with the sharp images, then
   oversized slightly: a blurred element fades out at its own edges, and the
   overhang keeps that fade outside the strip. */
.compare-blur-inner {
  position: absolute;
  left: -4%;
  top: -6%;
  width: 108%;
  aspect-ratio: var(--frame-ratio);
  filter: blur(20px) saturate(1.15);
}

.compare-blur-inner img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Where the ClickGUI's top edge falls in this capture. The copy is centred in
   the band above it and the blurred band stops just short of it, so re-cropping
   the screenshot means changing this one number. */
.content-units { --gui-top: 28.5%; }

.content-units .compare-blur { height: calc(var(--gui-top) - 1.5%); }

.content-units .content-copy {
  /* Occupy the band between the top of the capture and the top of the GUI,
     and centre the lines in it, rather than hanging them off the top edge with
     a fixed padding that has to be re-tuned whenever the crop changes. */
  height: var(--gui-top);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 5%;
  /* No scrim: the copy is black and sits on the blurred sky, which is light
     enough to carry it on its own. The mask existed only to feather that
     scrim, and with it gone it was just fading the lower lines out. */
  background: none;
  mask-image: none;
  -webkit-mask-image: none;
}

/* Sized against the frame (cqw), not the viewport. The frame's width is
   min(100%, 82svh x ratio), so it stops tracking the viewport as soon as the
   window is short or very wide — viewport-based type then drifts out of
   proportion and the gap down to the GUI, which sits at a fixed 28.5% of the
   image, changes with the window. The px floors only engage on phones. */
.content-units .content-eyebrow {
  margin-bottom: 0.4em;
  font-size: max(11px, 1.5cqw);
}

.content-units .content-title {
  font-size: max(18px, 3.6cqw);
  line-height: 1.03;
}

.content-units .content-body {
  margin-top: 0.55em;
  font-size: max(11px, 1.3cqw);
  line-height: 1.5;
}

.content-units .content-eyebrow,
.content-units .content-title,
.content-units .content-body {
  color: #0c0c11;
  opacity: 1;
}

/* A word singled out in a title, so the point lands before the sentence is
   finished reading. */
.title-mark {
  font-style: italic;
  font-weight: 700;
}

/* ---- Units: the same frame with and without unit labels ---- */
/* Only this box differs between the two captures, so it is the only thing
   that animates. Everything else in the frame comes from a single image and
   cannot flicker. */
.units-off {
  position: absolute;
  z-index: 3;
  opacity: 0;
  pointer-events: none;
  object-fit: fill;
}

/* Paused until the section is near the screen. */
.compare.is-live .units-off {
  animation: unitsFade 1.5s linear infinite;
}

/* Sampled from 0.85 x (0.5 - 0.5cos(2*pi*t)) and played linearly, so the curve
   really is a sine rather than a bezier that looks like one. Peaking at 0.85
   leaves the units at 15% at their faintest rather than vanishing. */
@keyframes unitsFade {
  0% { opacity: 0.0000; }
  5% { opacity: 0.0208; }
  10% { opacity: 0.0812; }
  15% { opacity: 0.1752; }
  20% { opacity: 0.2937; }
  25% { opacity: 0.4250; }
  30% { opacity: 0.5563; }
  35% { opacity: 0.6748; }
  40% { opacity: 0.7688; }
  45% { opacity: 0.8292; }
  50% { opacity: 0.8500; }
  55% { opacity: 0.8292; }
  60% { opacity: 0.7688; }
  65% { opacity: 0.6748; }
  70% { opacity: 0.5563; }
  75% { opacity: 0.4250; }
  80% { opacity: 0.2937; }
  85% { opacity: 0.1752; }
  90% { opacity: 0.0812; }
  95% { opacity: 0.0208; }
  100% { opacity: 0.0000; }
}

@media (prefers-reduced-motion: reduce) {
  .compare.is-live .units-off { animation: none; opacity: 0; }
}

/* ---- Vulkan ---- */
/* The fps badge, rebuilt rather than left in the capture so it stays sharp
   over the blur and crisp at any size. Every value below was measured off the
   original: the panel spans 25.7%..37.3% across and 44.7%..55.3% down, and the
   cap height of the text is 4.0% of the frame height. Sizes are in cqw so the
   badge scales with the frame, exactly as it would in game. */
.vk-fps {
  position: absolute;
  /* Every number here is fitted to the original capture rather than eyeballed:
     the sky behind the badge is a flat rgb(182, 209, 255), so a least-squares
     fit of "rounded rect, softened by a gaussian, composited over that sky"
     recovers the panel exactly (rms 3.65/255 over 112k pixels). */
  left: 25.08%;
  top: 44.66%;
  width: 12.04%;
  height: 10.62%;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  /* The ink gap between "FPS" and "408" is 25px in the original; flex spaces the
     advance boxes, so the two sidebearings come off that. */
  gap: 0.616cqw;
  font-family: var(--content-font);
  /* Tuned by differencing this badge against the capture and minimising what
     was left over: 2.61 nulls the glyphs where 2.54 and 2.73 both ghost. */
  font-size: 2.61cqw;
  line-height: 1;
  letter-spacing: normal;
  white-space: nowrap;
  pointer-events: none;
}

/* The panel has no hard edge: its alpha falls off as a gaussian with sigma
   0.292% of the frame width. CSS blur() takes a standard deviation, so blurring
   this layer reproduces that falloff, and keeping the panel on a layer of its
   own leaves the text sharp. Solving the fitted colour against the sky for a
   black overlay gives alpha 0.440, 0.437 and 0.439 on R, G and B — the same
   number three times over, so the panel really is plain black at 44%.
   Everything the panel is made of lives here, below the spans in tree order;
   a second pseudo-element would paint above them and blur the text. */
.vk-fps::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 1.58cqw;
  background: rgba(0, 0, 0, 0.44);
  backdrop-filter: blur(0.42cqw);
  -webkit-backdrop-filter: blur(0.42cqw);
  filter: blur(0.292cqw);
}

/* Positioned so the spans paint above the panel layer. Centring an em box puts
   the caps slightly high of where Rise draws them, so they come back down by
   the 4.95px the capture is off by. */
.vk-fps > span {
  position: relative;
  transform: translateY(0.164cqw);
}

/* The label is set heavier than the value. Measured against the capture, "FPS"
   matches the bold face's width-to-cap ratio (2.254 against 2.246) while "408"
   matches the regular face's (2.362 against 2.369) — both inside half a
   percent, and the two faces' differing cap ratios also explain why the label's
   caps are 59px tall where the digits' are 57px. */
.vk-fps-label { color: #f29ab1; font-weight: 700; }
.vk-fps-value { color: #fdfdfe; font-weight: 400; }

/* Copy sits over the top of the frame, as in the other showcase sections.
   Unlike those, the legibility scrim here is a plain gradient rather than a
   blurred copy of the image: the frame beneath is a live canvas being warped
   every frame, and a static blurred duplicate would visibly desync from it. */
.content-vulkan { --copy-band: 32%; }

.content-vulkan .content-copy {
  height: var(--copy-band);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 5%;
  background: linear-gradient(to bottom,
    rgba(0, 0, 0, 0.58) 0%,
    rgba(0, 0, 0, 0.34) 52%,
    rgba(0, 0, 0, 0.10) 82%,
    transparent 100%);
  mask-image: none;
  -webkit-mask-image: none;
}

.content-vulkan .content-title,
.content-vulkan .content-body,
.content-vulkan .content-eyebrow {
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.5);
}

.content-vulkan .content-eyebrow {
  margin-bottom: 0.4em;
  font-size: max(11px, 1.5cqw);
}

.content-vulkan .content-title {
  font-size: max(18px, 3.6cqw);
  line-height: 1.03;
}

.content-vulkan .content-body {
  margin-top: 0.55em;
  font-size: max(11px, 1.3cqw);
  line-height: 1.5;
}

/* Below this the frame is a few hundred pixels wide and the copy band is only
   ~60px tall: the body line neither fits nor reads at that size, and it was
   spilling out of the band onto the image. The eyebrow and headline carry the
   section on a phone. Keyed to the frame's own width, not the viewport, since
   the frame is height-capped on short windows. */
@container showcase (max-width: 560px) {
  .content-units .content-body,
  .content-vulkan .content-body { display: none; }
}

/* ---- Updates: two clear compatibility endpoints ---- */
.content-updates .content-visual {
  min-height: clamp(330px, 38vw, 430px);
  background:
    radial-gradient(circle at 50% 18%, color-mix(in srgb, var(--accent) 18%, transparent), transparent 54%),
    linear-gradient(145deg, #151722, #07080c 72%);
}

.updates-display {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(14px, 2.6vw, 34px);
  padding: clamp(28px, 5vw, 62px);
}

.version-card {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  min-height: clamp(150px, 18vw, 220px);
  padding: clamp(20px, 3vw, 34px);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: clamp(20px, 2.5vw, 30px);
  background: rgba(9, 10, 16, 0.72);
  box-shadow: inset 0 1px rgba(255, 255, 255, 0.07), 0 22px 55px rgba(0, 0, 0, 0.26);
  font-family: var(--content-font);
}

.version-card::after {
  content: "";
  position: absolute;
  width: 90px;
  height: 90px;
  right: -28px;
  bottom: -36px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 22%, transparent);
  filter: blur(26px);
  pointer-events: none;
}

.version-card-kicker,
.version-card-note {
  color: #858894;
  font-size: clamp(11px, 1.1vw, 14px);
  letter-spacing: 0.02em;
}

.version-card-kicker { text-transform: uppercase; }

.version-card-version {
  color: #f5f5f7;
  font-size: clamp(36px, 5vw, 68px);
  font-weight: 600;
  letter-spacing: -0.075em;
  line-height: 0.95;
  white-space: nowrap;
}

.version-card-current {
  border-color: color-mix(in srgb, var(--accent) 58%, rgba(255, 255, 255, 0.12));
  background: linear-gradient(145deg, color-mix(in srgb, var(--accent) 14%, #0d0f18), rgba(9, 10, 16, 0.86));
  box-shadow: inset 0 1px rgba(255, 255, 255, 0.12), 0 24px 70px color-mix(in srgb, var(--accent) 16%, transparent);
}

.version-card-current .version-card-kicker,
.version-card-current .version-card-note { color: color-mix(in srgb, var(--accent) 76%, #fff); }

.version-bridge {
  position: relative;
  flex: 0 0 clamp(44px, 7vw, 92px);
  color: rgba(255, 255, 255, 0.48);
  font-size: clamp(10px, 1vw, 13px);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-align: center;
}

.version-bridge::before,
.version-bridge::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 20px;
  height: 1px;
  background: color-mix(in srgb, var(--accent) 60%, transparent);
}

.version-bridge::before { right: calc(100% - 4px); }
.version-bridge::after { left: calc(100% - 4px); }

@media (max-width: 560px) {
  .updates-display { gap: 8px; padding: 22px 14px; }
  .version-card { padding: 16px; min-height: 142px; border-radius: 18px; }
  .version-card-version { font-size: clamp(28px, 10vw, 42px); }
  .version-card-kicker, .version-card-note { font-size: 10px; }
  .version-bridge { flex-basis: 28px; font-size: 9px; letter-spacing: 0.08em; }
  .version-bridge::before, .version-bridge::after { width: 10px; }
}

/* ---- A clip in a section frame ---- */
/* Same frame as the captures, so a video and a still sit identically in the
   page. object-fit covers the rare case of footage whose aspect does not match
   the ratio the section declares. */
.compare.is-video video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  background: #08080b;
}

/* With reduced motion the browser draws its own controls, which need to sit
   above the copy laid over the frame rather than under it. */
.compare.is-video video[controls] {
  z-index: 4;
}

/* The clip sits as close to the copy as the body sits to the title, so the
   three read as one block rather than a caption and a separate slab. This is
   the same clamp .content-body uses for its top margin, deliberately — sharing
   the expression is what keeps the two gaps equal at every width rather than
   only at the one they were eyeballed at. */
.is-media .content-copy {
  margin-bottom: clamp(28px, 4vw, 48px);
}

/* ---- Sound toggle on a clip ---- */
/* Bottom-right of the frame, out of the way of anything the footage is showing
   in the middle. Only rendered when the clip has an audio track. */
.vid-sound {
  position: absolute;
  /* Offset from the picture, not the frame: the inset variables carry the
     clip's own black border, so the same gap shows on both edges of the image
     itself. They default to zero for footage that fills its frame. */
  --vid-sound-gap: clamp(12px, 1.6vw, 22px);
  right: calc(var(--media-inset-right, 0%) + var(--vid-sound-gap));
  bottom: calc(var(--media-inset-bottom, 0%) + var(--vid-sound-gap));
  z-index: 6;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: clamp(38px, 3.4vw, 46px);
  height: clamp(38px, 3.4vw, 46px);
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 50%;
  background: rgba(16, 16, 20, 0.55);
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  color: #fff;
  cursor: pointer;
  transition: background 0.2s ease, border-color 0.2s ease, transform 0.15s ease;
}

.vid-sound svg { width: 56%; height: 56%; }

.vid-sound:hover {
  background: rgba(24, 24, 30, 0.72);
  border-color: rgba(255, 255, 255, 0.32);
}

.vid-sound:active { transform: scale(0.94); }

.vid-sound:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 3px;
}

/* Lit while the sound is actually on. */
.vid-sound.is-on {
  border-color: color-mix(in srgb, var(--accent) 60%, transparent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 14%, transparent);
}

[dir="rtl"] .vid-sound {
  right: auto;
  left: calc(var(--media-inset-left, 0%) + var(--vid-sound-gap));
}

/* ---- Agent sequence: prompt, then the client acting, then the result ---- */
.compare.is-agent { background: #08080b; }

/* Every stage occupies the same box and is crossfaded, so the frame never
   resizes between a recording and the finished still. */
.agent-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.5s ease;
}

.agent-layer.is-on { opacity: 1; }

/* Thinking indicator, bottom-left, clear of the HUD card the footage shows. */
.agent-think {
  position: absolute;
  left: clamp(14px, 2vw, 26px);
  bottom: clamp(14px, 2vw, 26px);
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 14px;
  border-radius: 980px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(12, 12, 16, 0.62);
  opacity: 0;
  transition: opacity 0.35s ease;
}

.agent-think.is-on { opacity: 1; }

.agent-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  animation: agentPulse 1.2s ease-in-out infinite;
}

.agent-dot:nth-child(2) { animation-delay: 0.18s; }
.agent-dot:nth-child(3) { animation-delay: 0.36s; }

@keyframes agentPulse {
  0%, 100% { opacity: 0.28; transform: translateY(0); }
  50%      { opacity: 1;    transform: translateY(-3px); }
}

/* The running commentary, sat beside the dots. */
.agent-caption {
  position: absolute;
  left: clamp(14px, 2vw, 26px);
  bottom: calc(clamp(14px, 2vw, 26px) + 52px);
  z-index: 3;
  max-width: 70%;
  padding: 10px 16px;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(12, 12, 16, 0.66);
  color: #fff;
  font-family: var(--content-font);
  font-size: clamp(14px, 1.5vw, 19px);
  font-weight: 500;
  letter-spacing: -0.015em;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.35s ease, transform 0.35s ease;
}

.agent-caption.is-on { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .agent-dot { animation: none; opacity: 0.8; }
  .agent-layer, .agent-caption, .agent-think { transition-duration: 0.01ms; }
}

[dir="rtl"] .agent-think,
[dir="rtl"] .agent-caption {
  left: auto;
  right: clamp(14px, 2vw, 26px);
}
