/* Teachmint X digital board page (/products/digital-board-for-teaching).

   Loaded AFTER teachmint-v4.0/home.css, which owns every section reused from the
   homepage (.rv-hero .rv-trust .rv-eac .rv-wb .rv-cc .rv-vx .rv-hw .rv-tm .rv-sp
   .rv-nav .rv-ft) plus the shared .rv-reveal primitive. This file adds only the
   sections that page does not have, and one rule for the lede that
   macros/support.html gained.

   Colour tokens in home.css are SECTION-SCOPED, not global, so each section
   below redeclares the ones it uses — an unresolved var() invalidates the whole
   declaration and fails silently on screen. */

/* Type scale and radius, mirroring the :where() block in home.css so the new
   sections cannot drift from the homepage's sizes. Zero specificity, same as
   there, so any section can still override locally. */
:where(.rv-pt, .rv-sr, .rv-cg, .rv-sb, .rv-fq, .rv-ac, .rv-bk,
        .rv-in, .rv-sh, .rv-qt, .rv-ig) {
  --rv-fs-h2: clamp(1.9rem, 3.6vw, 2.5rem);
  --rv-fw-h2: 500;
  --rv-fs-title: clamp(1.15rem, 1.75vw, 1.6rem);
  --rv-fw-title: 600;
  --rv-fs-body: clamp(0.9rem, 1.1vw, 1rem);
  --rv-radius-card: 18px;
  --rv-radius-media: 12px;
  /* Heading/subtext rhythm, one value each so no section can drift:
     gap under a section head, gap between a title and its sub-copy, and the
     reading measure for sub-copy. The measure is applied to the sub-copy
     ELEMENT, not its head — ch resolves against the element's own font-size, so
     capping the 16px head at 72ch let the 18.4px body inside run to 79ch. */
  --rv-head-gap: 40px;
  --rv-title-gap: 16px;
  --rv-measure: 65ch;
  /* Tighter relatives of --rv-title-gap: inside a card, and under a figure. */
  --rv-card-gap: 12px;
  --rv-caption-gap: 10px;
}

/* Sub-copy: ONE size and leading for every descriptive paragraph on the page,
   section ledes and card descriptions alike, so none can drift from another.
   On :root and not in the :where() block above, because the split hero is a
   home.css section and is not in that selector list — a var() it cannot see
   invalidates the whole declaration and fails silently on screen. */
:root {
  --rv-fs-sub: 18px;
  --rv-lh-sub: 1.6;
}

/* Must follow the block above — both use :where(), so source order decides. */
@media (max-width: 640px) {
  :where(.rv-pt, .rv-sr, .rv-cg, .rv-sb, .rv-fq, .rv-ac, .rv-bk, .rv-ig,
          .rv-in, .rv-sh, .rv-qt) {
    --rv-fs-h2: 24px;
    /* The heading drops 40px -> 24px here, so the gap under the head comes down
       with it; 40px against a 24px heading reads as a hole on a phone. */
    --rv-head-gap: 32px;
  }
}

/* ===========================================================================
   Shared primitives
   home.css has no pill of its own; this is the v4 spec. No section calls it
   today — v4SplitRow's `chips` argument is its only route in.
   =========================================================================== */
.rv-pill {
  display: inline-block;
  padding: 0.42em 0.85em;
  border-radius: 999px;
  background: #ffffff;
  color: #14284d;
  font-size: 0.95em;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}

:where(.rv-pt, .rv-sr, .rv-cg, .rv-sb, .rv-fq, .rv-ac, .rv-bk, .rv-ig) :focus-visible {
  outline: 2px solid #1f3965;
  outline-offset: 3px;
  border-radius: 4px;
}

/* ===========================================================================
   .rv-pt — tabbed row (feature pillars, and the audio/video specs)
   =========================================================================== */
.rv-pt {
  --rv-navy: #14284d;
  --rv-muted: #4c6389;
  --rv-rule: #dbe3ef;
  --rv-accent: #1da1f2;
  padding: 64px 24px 72px;
  background: #ffffff;
}
.rv-pt__inner {
  max-width: 1200px;
  margin-inline: auto;
}
.rv-pt__head {
  margin-bottom: var(--rv-head-gap);
  text-align: center;
}
.rv-pt__eyebrow {
  margin: 0 0 12px;
  color: var(--rv-muted);
  font-size: var(--rv-fs-body);
  font-weight: 600;
  letter-spacing: 0.02em;
}
.rv-pt__title {
  margin: 0;
  color: var(--rv-navy);
  font-size: var(--rv-fs-h2);
  font-weight: var(--rv-fw-h2);
  /* 1.14, which is what home.css actually renders (45.6px on a 40px h2). The
     design system doc says 1.2; the stylesheet wins per its own rule. */
  line-height: 1.14;
  text-wrap: balance;
}
.rv-pt__lede {
  max-width: var(--rv-measure);
  margin: var(--rv-title-gap) auto 0;
  color: var(--rv-muted);
  font-size: var(--rv-fs-sub);
  line-height: var(--rv-lh-sub);
}

/* Segmented control: a tinted track with the active tab lifted out of it as a
   white pill. This is the shape the approved reference for this section shows,
   and it replaces an underlined text row. The active state is carried by FILL +
   ELEVATION rather than accent colour — the same choice the design system makes
   for a recommended pricing card, which keeps the page's accent budget intact. */
.rv-pt__tabs {
  display: flex;
  justify-content: flex-start;
  gap: 4px;
  width: max-content;
  max-width: 100%;
  margin: 0 auto 40px;
  padding: 6px;
  border-radius: 999px;
  background: #f0f5fd;
  /* Five labels do not fit a phone; the track scrolls rather than wrapping into
     a block that would push the panel down. */
  overflow-x: auto;
  scrollbar-width: none;
}
.rv-pt__tabs::-webkit-scrollbar {
  display: none;
}
.rv-pt__tab {
  flex: 0 0 auto;
  /* 44px for the WCAG 2.5.8 target. */
  min-height: 44px;
  padding: 10px 18px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--rv-muted);
  font-family: inherit;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.18s ease, color 0.18s ease,
    box-shadow 0.18s ease;
}
@media (hover: hover) {
  .rv-pt__tab:hover:not(.is-active) {
    color: var(--rv-navy);
  }
}
.rv-pt__tab.is-active {
  background: #ffffff;
  color: var(--rv-navy);
  box-shadow: 0 10px 34px rgba(20, 40, 77, 0.09);
}

.rv-pt__panel {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
  /* Centred on the media, which only holds because .rv-pt__media img caps at
     420px — uncapped, a 580px image strands the copy mid-column. */
  align-items: center;
}
.rv-pt__panel:not(.is-active) {
  display: none;
}
/* Product brand lockup above the panel title. Height in em off the title, which
   is how home.css sizes the EduAI and VisionX lockups, so the mark keeps its
   proportion to the copy at every breakpoint. width:auto holds each lockup's own
   aspect; only two of the five pillars have one. */
.rv-pt__logo {
  display: block;
  height: 1.9em;
  width: auto;
  margin: 0 0 16px;
  font-size: var(--rv-fs-title);
}
.rv-pt__panel-title {
  margin: 0;
  color: var(--rv-navy);
  font-size: var(--rv-fs-title);
  font-weight: var(--rv-fw-title);
  line-height: 1.3;
  text-wrap: balance;
}
.rv-pt__panel-desc {
  max-width: var(--rv-measure);
  margin: var(--rv-title-gap) 0 0;
  color: var(--rv-muted);
  font-size: var(--rv-fs-sub);
  line-height: var(--rv-lh-sub);
}
.rv-pt__media {
  display: flex;
  justify-content: center;
  border-radius: var(--rv-radius-card);
  overflow: hidden;
}
/* Fit inside a bounded box rather than filling the column. Media here ranges
   from 1.0 to 1.78 aspect; uncapped, the square ones rendered 580px tall beside
   123px of copy. width:auto + max-width + max-height shrinks and centres while
   preserving the intrinsic aspect exactly — no crop, no letterbox. */
.rv-pt__media img {
  display: block;
  width: auto;
  max-width: 100%;
  max-height: var(--rv-media-max, 420px);
  height: auto;
}

@media (max-width: 1024px) {
  .rv-pt__panel {
    grid-template-columns: 1fr;
    gap: 28px;
    text-align: center;
  }
  /* Media first at this width, matching the homepage's split sections. */
  .rv-pt__media {
    order: -1;
  }
  .rv-pt__panel-desc {
    margin-inline: auto;
  }
  .rv-pt__logo {
    margin-inline: auto;
  }
}
/* Five pillar labels measure ~1002px at 16px, so they overflow the 976px inner
   width at 1024 and would clip the last tab behind a hidden scrollbar. Tightening
   the gap and padding fits all five down to ~1000px; below that the strip
   legitimately scrolls. */
/* Five labels plus the pill padding measure past the 976px inner width at 1024,
   which would clip the last tab behind a hidden scrollbar. Tightening the pill
   padding fits all five down to ~1000px; below that the track scrolls. */
@media (max-width: 1200px) {
  .rv-pt__tabs {
    gap: 2px;
  }
  .rv-pt__tab {
    padding: 10px 12px;
  }
}
@media (max-width: 640px) {
  .rv-pt {
    padding: 48px 20px 56px;
  }
}

/* ===========================================================================
   Reused homepage sections, re-banded for this page
   The tint is reserved for the pillar intros here — it is how a visitor sees
   one product chapter end and the next begin — so every other band is white.
   home.css gives .rv-tm the tint; this file loads after it at the same
   specificity, so source order wins. Only this page is affected.
   =========================================================================== */
.rv-tm {
  background: #ffffff;
}

/* ===========================================================================
   .rv-in — pillar intro: the opening section of a product chapter. Centred and
   symmetrical, against the split rows that support it further down, so the two
   never read as the same layout.
   =========================================================================== */
.rv-in {
  --rv-navy: #14284d;
  --rv-muted: #4c6389;
  --rv-border: #c9d6ee;
  padding: 64px 24px 72px;
  background: #ffffff;
}
.rv-in--tint {
  background: #f4f8fd;
}
/* --- Full-bleed photograph variant ---------------------------------------
   The copy sits on the empty background each photograph carries above its
   subject — no scrim and no crop, so nothing is veiled and nothing is cut.
   Stacked below 1200px: that background scales with width, and narrower than
   this it is too short to hold the copy without reaching the subject. */
.rv-in--shot {
  padding-bottom: 0;
  overflow: hidden;
}
.rv-in__shot {
  position: relative;
  /* Negative inline margin cancels the section's 24px padding, so the
     photograph runs edge to edge while the copy stays in the 1200px column. */
  margin: 32px -24px 0;
  line-height: 0;
}
.rv-in__shot img {
  display: block;
  width: 100%;
  height: auto;
}
/* Stacked, the copy sits above the photograph rather than on it, so the
   background manufactured for the overlay is just dead space — a third of the
   picture on a phone. Crop it back to the frame as shot. --rv-in-frame is
   width / (height - ext), set by the macro. */
@media (max-width: 1199px) {
  /* The container takes the frame's aspect and the photograph is over-scaled
     inside it and pinned to the foot, so the background manufactured for the
     desktop overlay overflows the top and is clipped. object-fit cannot do
     this: once a floor makes the box taller than the frame, cover scales by
     height and the whole image — extension and all — comes back into view. */
  .rv-in--shot-fit .rv-in__shot {
    position: relative;
    /* Explicit, or the aspect-ratio drives the WIDTH off min-height and the
       box grows past the viewport instead of growing taller. +48px is the
       bleed the -24px inline margins open up — keep the two in step. */
    width: calc(100% + 48px);
    aspect-ratio: var(--rv-in-frame);
    /* A floor for frames so wide they would render as a strip. The crop
       tightens by as much as the extra height needs; the aspect wins again
       once it is the taller of the two. */
    min-height: var(--rv-in-floor, 0px);
    overflow: hidden;
  }
  .rv-in--shot-fit .rv-in__shot img {
    position: absolute;
    bottom: 0;
    left: 50%;
    width: auto;
    max-width: none;
    /* shot_h / (shot_h - ext): exactly enough to put the frame over the box. */
    height: calc(100% * var(--rv-in-overscan, 1));
    transform: translateX(-50%);
  }
}
/* Phones only, and only for the two frames wide enough to read as a strip
   there: crop the sides in to the subject. Falls back to the frame as shot. */
@media (max-width: 640px) {
  .rv-in--shot-fit .rv-in__shot {
    aspect-ratio: var(--rv-in-frame-sm, var(--rv-in-frame));
  }
}

@media (min-width: 1200px) {
  /* The image becomes the band; the copy is lifted onto its extension. */
  .rv-in--shot {
    position: relative;
    padding: 0;
  }
  .rv-in--shot .rv-in__inner {
    position: absolute;
    top: 64px;
    right: 0;
    left: 0;
    z-index: 1;
    padding-inline: 24px;
  }
  .rv-in__shot {
    /* The section's padding is 0 in this branch, so the bleed needs no
       negative margin — at -24px the image ran 48px wider than the band. */
    margin: 0;
  }
  /* Only inside the overlay: below this width the same copy sits on the light
     tint, where white would vanish. The badge is its own white pill, so its
     label keeps the navy. */
  .rv-in--on-dark .rv-in__title,
  .rv-in--on-dark .rv-in__body {
    color: #ffffff;
  }
  /* The muted tone is a mid-tone, so it loses against both ends of a
     photograph — 3.8:1 on the VisionX backdrop. Not blanket across
     .rv-in--shot: the Connected Classroom copy crosses the board's black bezel
     AND its white screen, where navy measures worse than muted. */
  .rv-in--on-light .rv-in__body {
    color: var(--rv-navy);
  }
  /* Content-driven variant. The default overlay positions the copy from the
     band's top, so the gap beneath it is whatever the photograph's background
     has left over — and that grows with viewport width (88px at 1440, 219px at
     1920). Here the band is the copy plus the subject's own share of the width,
     so the gap stays 24px at every size and the band is ~70px shorter. The
     photograph is pinned to the foot and its surplus background is cropped off
     the TOP. --rv-in-subject is (shot_h - shot_safe) / shot_w, set by the macro
     because it is a property of the photograph, not of the layout. */
  .rv-in--shot-fit {
    padding: 56px 24px calc(var(--rv-in-subject) + 24px);
  }
  .rv-in--shot-fit .rv-in__inner {
    position: relative;
    top: auto;
    z-index: 1;
    padding-inline: 0;
  }
  .rv-in--shot-fit .rv-in__shot {
    position: absolute;
    inset: 0;
    z-index: 0;
  }
  .rv-in--shot-fit .rv-in__shot img {
    height: 100%;
    object-fit: cover;
    object-position: center bottom;
  }
}
.rv-in__inner {
  position: relative;
  z-index: 1;
  max-width: 1200px;
  margin-inline: auto;
}
.rv-in__head {
  text-align: center;
}
/* The .rv-pill treatment, sized for a brand mark rather than a word: white and
   lifted, so the lockup reads as the badge of the product being introduced. */
.rv-in__badge {
  --rv-in-badge-pad: 12px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 24px;
  padding: var(--rv-in-badge-pad) 24px;
  /* One chip height across every pillar intro, whatever it holds: a lockup at
     1.9em of the title size, or a smaller icon beside a text label. The em
     needs font-size set here, which no child inherits — each sets its own.
     Without this the icon-and-label badge came out 23px shorter and took its
     whole section's height down with it. */
  font-size: var(--rv-fs-title);
  min-height: calc(1.9em + var(--rv-in-badge-pad) * 2);
  border-radius: 999px;
  background: #ffffff;
  box-shadow: 0 10px 34px rgba(20, 40, 77, 0.09);
}
.rv-in__badge.rv-in__badge--bare {
  padding: 0;
  background: none;
  box-shadow: none;
}
/* 2.85em, not the lockup's 1.9em: with no chip padding around it the artwork
   has to carry the chip's own 72px height, or it reads smaller than the badge
   on every other pillar intro. */
.rv-in__badge--bare .rv-in__logo {
  height: 2.85em;
}
.rv-in__logo {
  display: block;
  width: auto;
  height: 1.9em;
  /* Sized in em off the title, the way the pillar tabs size theirs, so the mark
     keeps its proportion to the copy at every breakpoint. */
  font-size: var(--rv-fs-title);
}
/* Icon-plus-label badge, for a product with no lockup drawn. */
.rv-in__badge-icon {
  display: block;
  width: auto;
  height: 1.4em;
  font-size: var(--rv-fs-sub);
}
.rv-in__badge-label {
  color: var(--rv-navy);
  font-size: var(--rv-fs-sub);
  font-weight: 600;
  line-height: 1.2;
}
.rv-in__title {
  margin: 0;
  color: var(--rv-navy);
  font-size: var(--rv-fs-h2);
  font-weight: var(--rv-fw-h2);
  line-height: 1.14;
  text-wrap: balance;
}
.rv-in__body {
  max-width: var(--rv-measure);
  margin: var(--rv-title-gap) auto 0;
  color: var(--rv-muted);
  font-size: var(--rv-fs-sub);
  line-height: var(--rv-lh-sub);
}
/* The gap lives here, not as the head's margin-bottom: an intro with no media
   has nothing to separate, and that margin would strand 40px at the foot. */
.rv-in__media {
  display: flex;
  justify-content: center;
  margin-top: var(--rv-head-gap);
}
/* Taller cap than the split rows' 420px: this is the chapter's showcase, and
   width:auto + max-height holds the render's aspect exactly. */
.rv-in__media img {
  display: block;
  width: auto;
  max-width: 100%;
  max-height: var(--rv-in-media-max, 480px);
  height: auto;
}

@media (max-width: 640px) {
  .rv-in__badge {
    --rv-in-badge-pad: 10px;
    margin-bottom: 20px;
    padding-inline: 20px;
  }
  .rv-in__shot {
    /* .rv-in keeps its 24px inline padding at this width, so the bleed margin
       stays -24px — at -20px the photograph left 4px of tint down each side. */
    margin: 28px -24px 0;
  }
}

/* ===========================================================================
   .rv-sr — split row (pillar intro, display fold)
   =========================================================================== */
.rv-sr {
  --rv-navy: #14284d;
  --rv-muted: #4c6389;
  padding: 64px 24px 72px;
  background: #ffffff;
}
.rv-sr--tint {
  background: #f4f8fd;
}
.rv-sr__inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
  /* See the note on .rv-pt__panel — same reason. */
  align-items: center;
  max-width: 1200px;
  margin-inline: auto;
}
.rv-sr--media-left .rv-sr__media {
  order: -1;
}
.rv-sr__eyebrow {
  margin: 0 0 12px;
  color: var(--rv-muted);
  font-size: var(--rv-fs-body);
  font-weight: 600;
  letter-spacing: 0.02em;
}
.rv-sr__title {
  margin: 0;
  color: var(--rv-navy);
  font-size: var(--rv-fs-h2);
  font-weight: var(--rv-fw-h2);
  /* 1.14, which is what home.css actually renders (45.6px on a 40px h2). The
     design system doc says 1.2; the stylesheet wins per its own rule. */
  line-height: 1.14;
  text-wrap: balance;
}
.rv-sr__body {
  max-width: var(--rv-measure);
  margin: var(--rv-title-gap) 0 0;
  color: var(--rv-muted);
  font-size: var(--rv-fs-sub);
  line-height: var(--rv-lh-sub);
}
.rv-sr__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
}
/* The chips sit on white here, so they need an outline to read as chips. */
.rv-sr__chip {
  border: 1px solid #c9d6ee;
}
.rv-sr__media {
  display: flex;
  justify-content: center;
  border-radius: var(--rv-radius-card);
  overflow: hidden;
}
.rv-sr__media img {
  display: block;
  width: auto;
  max-width: 100%;
  max-height: var(--rv-media-max, 420px);
  height: auto;
}

@media (max-width: 1024px) {
  .rv-sr__inner {
    grid-template-columns: 1fr;
    gap: 28px;
    text-align: center;
  }
  .rv-sr__media,
  .rv-sr--media-left .rv-sr__media {
    order: -1;
  }
  .rv-sr__body {
    margin-inline: auto;
  }
  .rv-sr__chips {
    justify-content: center;
  }
}
@media (max-width: 640px) {
  .rv-sr {
    padding: 48px 20px 56px;
  }
}

/* ===========================================================================
   .rv-cg — card grid (buyer segments)
   =========================================================================== */
.rv-cg {
  --rv-navy: #14284d;
  --rv-muted: #4c6389;
  padding: 64px 24px 72px;
  background: #ffffff;
}
/* The cards stay white, so on a tinted band they read as cards rather than
   relying on their elevation alone. */
.rv-cg--tint {
  background: #f4f8fd;
}
.rv-cg__inner {
  max-width: 1200px;
  margin-inline: auto;
}
.rv-cg__head {
  margin-bottom: var(--rv-head-gap);
  text-align: center;
}
.rv-cg__eyebrow {
  margin: 0 0 12px;
  color: var(--rv-muted);
  font-size: var(--rv-fs-body);
  font-weight: 600;
}
.rv-cg__title {
  margin: 0;
  color: var(--rv-navy);
  font-size: var(--rv-fs-h2);
  font-weight: var(--rv-fw-h2);
  /* 1.14, which is what home.css actually renders (45.6px on a 40px h2). The
     design system doc says 1.2; the stylesheet wins per its own rule. */
  line-height: 1.14;
  text-wrap: balance;
}
.rv-cg__lede {
  max-width: var(--rv-measure);
  margin: var(--rv-title-gap) auto 0;
  color: var(--rv-muted);
  font-size: var(--rv-fs-sub);
  line-height: var(--rv-lh-sub);
}
.rv-cg__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.rv-cg__card {
  padding: 26px;
  border-radius: var(--rv-radius-card);
  background: #ffffff;
  box-shadow: 0 18px 44px rgba(20, 40, 77, 0.1);
}
.rv-cg__link {
  display: block;
  color: inherit;
  text-decoration: none;
}
.rv-cg__media {
  margin-bottom: 20px;
  border-radius: var(--rv-radius-media);
  overflow: hidden;
}
.rv-cg__media img {
  display: block;
  width: 100%;
  height: auto;
}
.rv-cg__card-title {
  margin: 0;
  color: var(--rv-navy);
  font-size: var(--rv-fs-title);
  font-weight: var(--rv-fw-title);
  line-height: 1.3;
}
.rv-cg__card-desc {
  margin: var(--rv-card-gap) 0 0;
  color: var(--rv-muted);
  font-size: var(--rv-fs-sub);
  line-height: var(--rv-lh-sub);
}

@media (max-width: 1023px) {
  .rv-cg__grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 640px) {
  .rv-cg {
    padding: 48px 20px 56px;
  }
  .rv-cg__grid {
    grid-template-columns: 1fr;
  }
}

/* ===========================================================================
   .rv-sb — stat band (hardware specs, warranty, service commitments)
   =========================================================================== */
.rv-sb {
  --rv-navy: #14284d;
  --rv-muted: #4c6389;
  padding: 64px 24px 72px;
  background: #ffffff;
}
.rv-sb--tint {
  background: #f4f8fd;
}
.rv-sb__inner {
  max-width: 1200px;
  margin-inline: auto;
}
.rv-sb__head {
  margin-inline: auto;
  text-align: center;
}
.rv-sb__eyebrow {
  margin: 0 0 12px;
  color: var(--rv-muted);
  font-size: var(--rv-fs-body);
  font-weight: 600;
}
.rv-sb__title {
  margin: 0;
  color: var(--rv-navy);
  font-size: var(--rv-fs-h2);
  font-weight: var(--rv-fw-h2);
  /* 1.14, which is what home.css actually renders (45.6px on a 40px h2). The
     design system doc says 1.2; the stylesheet wins per its own rule. */
  line-height: 1.14;
  text-wrap: balance;
}
.rv-sb__body {
  max-width: var(--rv-measure);
  margin: var(--rv-title-gap) auto 0;
  color: var(--rv-muted);
  font-size: var(--rv-fs-sub);
  line-height: var(--rv-lh-sub);
}
.rv-sb__stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  margin: var(--rv-head-gap) 0 0;
}
.rv-sb__stat {
  text-align: center;
}
/* The figure is the one piece of type on this page outside the shared scale,
   for the same reason the hero H1 and a price are. */
.rv-sb__stat-value {
  color: var(--rv-navy);
  font-size: clamp(1.75rem, 3.2vw, 2.25rem);
  font-weight: 600;
  line-height: 1.1;
}
.rv-sb__stat-label {
  margin: var(--rv-caption-gap) 0 0;
  color: var(--rv-muted);
  font-size: var(--rv-fs-body);
  line-height: 1.5;
}

@media (max-width: 640px) {
  .rv-sb {
    padding: 48px 20px 56px;
  }
  .rv-sb__stats {
    grid-template-columns: 1fr;
    gap: 28px;
  }
}

/* ===========================================================================
   .rv-fq — FAQ. <details>/<summary>, no JS.
   =========================================================================== */
.rv-fq {
  --rv-navy: #14284d;
  --rv-muted: #4c6389;
  --rv-rule: #dbe3ef;
  padding: 64px 24px 72px;
  background: #ffffff;
}
.rv-fq__inner {
  max-width: 860px;
  margin-inline: auto;
}
.rv-fq__title {
  margin: 0 0 var(--rv-head-gap);
  color: var(--rv-navy);
  font-size: var(--rv-fs-h2);
  font-weight: var(--rv-fw-h2);
  /* 1.14, which is what home.css actually renders (45.6px on a 40px h2). The
     design system doc says 1.2; the stylesheet wins per its own rule. */
  line-height: 1.14;
  text-align: center;
  text-wrap: balance;
}
.rv-fq__row {
  border-top: 1px solid var(--rv-rule);
}
.rv-fq__row:last-child {
  border-bottom: 1px solid var(--rv-rule);
}
.rv-fq__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  /* 20px block padding keeps the row over the 44px touch target. */
  padding: 20px 0;
  color: var(--rv-navy);
  font-size: var(--rv-fs-title);
  font-weight: var(--rv-fw-title);
  line-height: 1.3;
  cursor: pointer;
  list-style: none;
}
.rv-fq__q::-webkit-details-marker {
  display: none;
}
.rv-fq__chevron {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  color: var(--rv-muted);
  transition: transform 0.24s ease;
}
.rv-fq__row[open] .rv-fq__chevron {
  transform: rotate(180deg);
}
.rv-fq__a {
  max-width: var(--rv-measure);
  padding: 0 0 24px;
  color: var(--rv-muted);
  font-size: var(--rv-fs-sub);
  line-height: var(--rv-lh-sub);
}
/* The answers carry their own markup (ul / ol / br) from the FAQ data. */
.rv-fq__a ul,
.rv-fq__a ol {
  margin: 12px 0 0;
  padding-left: 20px;
}
.rv-fq__a li {
  margin-bottom: 8px;
}

@media (max-width: 640px) {
  .rv-fq {
    padding: 48px 20px 56px;
  }
}

/* ===========================================================================
   Reduced motion. home.css already flattens .rv-reveal; this covers the
   transitions declared above.
   =========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .rv-pt__tab,
  .rv-fq__chevron {
    transition: none;
  }
}

/* ===========================================================================
   .rv-hero--shot — copy and CTAs centred over a full-bleed photograph.
   home.css's .rv-hero reserves bottom padding for the room photo's furniture
   band and paints a grey safety net behind it; there is no room photo here, so
   both are reset. Loaded after home.css at equal specificity, so source order
   wins, including over its breakpoint overrides.
   =========================================================================== */
.rv-hero--shot {
  padding: calc(var(--rv-nav-space) + 40px) 24px 0;
  background-color: #ffffff;
  text-align: center;
  overflow: hidden;
}
.rv-hero--shot .rv-hero__inner {
  max-width: 1200px;
  margin-inline: auto;
  padding: 0;
}
.rv-hero--shot .rv-hero__title {
  margin: 0;
  /* Smaller than the homepage hero on purpose: the copy has to clear the
     board, and the wall above it is only 21.6% of the rendered width. */
  font-size: clamp(2rem, 3.4vw, 2.75rem);
  line-height: 1.12;
}
.rv-hero--shot .rv-hero__accent {
  text-wrap: balance;
}
.rv-hero--shot .rv-hero__subhead {
  max-width: 62ch;
  margin: 14px auto 0;
  font-size: var(--rv-fs-sub);
  line-height: var(--rv-lh-sub);
}
.rv-hero--shot .rv-hero__cta {
  justify-content: center;
  margin-top: 20px;
}
/* Its own class, not .rv-hero__shot: the split variant already owns that name
   for its right-hand column. */
.rv-hero__bleed {
  position: relative;
  /* Negative inline margin cancels the section padding so the photograph runs
     edge to edge while the copy stays in the 1200px column. */
  margin: 32px -24px 0;
  line-height: 0;
}
/* Natural aspect, no crop — see the note on .rv-in__shot img. */
.rv-hero__bleed img {
  display: block;
  width: 100%;
  height: auto;
}

/* 1360, not 1200: the overlay box is the wall above the board, and below this
   width that wall is shorter than the nav guard + copy + clearance it has to
   hold. Narrower viewports get the stacked layout instead. */
@media (min-width: 1360px) {
  .rv-hero--shot {
    position: relative;
    padding: 0;
  }
  /* The bezel's top edge sits at y=392 of the 1448px-wide photograph, so the
     wall is 27.07vw — change the photograph and this must follow, or the copy
     rides onto the board. The copy centres in what is left after the nav guard,
     so both gaps shrink together as the wall does. */
  .rv-hero--shot .rv-hero__inner {
    position: absolute;
    top: 0;
    right: 0;
    left: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 27.07vw;
    padding: calc(var(--rv-nav-space) + 24px) 24px 20px;
  }
  /* Only over the photograph: the muted tone measures 3.8:1 on the wall at
     18px, under AA. On white below this breakpoint it passes, so it stays. */
  .rv-hero--shot .rv-hero__subhead {
    color: var(--rv-navy);
  }
  .rv-hero__bleed {
    margin: 0;
  }
}

/* Phone and small tablet: the copy sits over the photograph here too, but the
   other way round from the desktop overlay — the wall stretches to fit the copy
   instead of the copy centring in a fixed wall. The portrait crop is pinned to
   the band's foot, so surplus wall is cropped off the TOP and the subject is
   never cut. Must match the <source media> in the hero macro.

   900px, because that is the crop's own width: past it the portrait asset would
   be upscaled, so wider viewports fall back to the stacked layout. */
@media (max-width: 900px) {
  .rv-hero--shot {
    position: relative;
    /* The crop carries its subject in the bottom 86% of its own width, so that
       is the room the copy has to leave beneath itself, plus 20px clear. */
    /* +26px, not the desktop +24px: --rv-nav-space is 70px here, and the nav's
       visible bar ends 72px into the band. */
    padding: calc(var(--rv-nav-space) + 26px) 20px calc(86vw + 20px);
  }
  .rv-hero--shot .rv-hero__inner {
    position: relative;
    z-index: 1;
  }
  .rv-hero__bleed {
    position: absolute;
    inset: 0;
    z-index: 0;
    margin: 0;
  }
  .rv-hero__bleed img {
    height: 100%;
    object-fit: cover;
    object-position: center bottom;
  }
  /* Over the photograph the muted tone drops under AA, as it does on desktop. */
  .rv-hero--shot .rv-hero__subhead {
    color: var(--rv-navy);
  }
}

/* ===========================================================================
   .rv-ac — card carousel: one card centred and playing, the rest waiting on
   either side. Scroll-snap does the centring, so the layout survives a resize
   and a touch swipe with no JS involved.
   =========================================================================== */
.rv-ac {
  --rv-navy: #14284d;
  --rv-muted: #4c6389;
  --rv-border: #c9d6ee;
  /* A DEFINITE width, never a percentage: the card is a flex item of a track
     that is itself sized by its content inside the scroll port, so a
     percentage basis resolves against the track's own max-content width and
     runs away — calc(100% - 16px) rendered a 1166px card at 390px. */
  /* Three cards across: the scroll port is capped at 1080px, and the card is a
     third of it less the two 24px gaps. min() against vw keeps it DEFINITE at
     every width — a percentage resolves against the content-sized track and
     runs away. */
  --rv-ac-gap: 24px;
  --rv-ac-card: calc((min(1080px, 100vw - 48px) - var(--rv-ac-gap) * 2) / 3);
  padding: 64px 24px 72px;
  background: #ffffff;
}
.rv-ac__inner {
  max-width: 1200px;
  margin-inline: auto;
}
.rv-ac__head {
  margin-bottom: var(--rv-head-gap);
  text-align: center;
}
.rv-ac__eyebrow {
  margin: 0 0 12px;
  color: var(--rv-muted);
  font-size: var(--rv-fs-body);
  font-weight: 600;
}
.rv-ac__title {
  margin: 0;
  color: var(--rv-navy);
  font-size: var(--rv-fs-h2);
  font-weight: var(--rv-fw-h2);
  line-height: 1.14;
  text-wrap: balance;
}
.rv-ac__stage {
  position: relative;
}
/* Exactly three cards wide, so nothing is ever half-cut and the edge fade this
   used to need is gone with it. */
.rv-ac__viewport {
  display: flex;
  max-width: calc(var(--rv-ac-card) * 3 + var(--rv-ac-gap) * 2);
  margin-inline: auto;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  /* No visible scrollbar: the arrows and indicators are the affordance. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.rv-ac__viewport::-webkit-scrollbar {
  display: none;
}
@media (prefers-reduced-motion: reduce) {
  .rv-ac__viewport {
    scroll-behavior: auto;
  }
}
.rv-ac__track {
  display: flex;
  gap: var(--rv-ac-gap);
  /* No side padding: with three across, room for the first card to sit dead
     centre would mean a card-wide hole at each end of the run. The first and
     last card align to their edge instead, which is what centre-snapping
     clamps to anyway. */
  padding: 8px 0;
  margin: 0;
  list-style: none;
}
.rv-ac__card {
  display: flex;
  flex: 0 0 var(--rv-ac-card);
  flex-direction: column;
  scroll-snap-align: center;
  padding: 20px;
  border: 1px solid var(--rv-border);
  border-radius: var(--rv-radius-card);
  /* Tinted while waiting, white when live — the contrast now lives between the
     cards rather than between card and band, so the band can stay white and the
     tint can mean "new chapter" and nothing else.
     No box-shadow: overflow-x on the scroll port forces overflow-y with it, so
     a lift would be clipped at the card's top and bottom edges anyway. */
  background: #f4f8fd;
  opacity: 0.7;
  transition: opacity 0.32s var(--rv-ease, ease);
}
/* The accent marks state and nothing else on this page, which is the budget the
   design system sets for it. The inset ring doubles the border's weight without
   changing the card's box, so nothing reflows as the live card changes. */
.rv-ac__card.is-active {
  background: #ffffff;
  border-color: #1da1f2;
  box-shadow: inset 0 0 0 1px #1da1f2;
  opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
  .rv-ac__card {
    opacity: 1;
    transition: none;
  }
}
.rv-ac__card-title {
  margin: 0;
  color: var(--rv-navy);
  font-size: var(--rv-fs-title);
  font-weight: var(--rv-fw-title);
  line-height: 1.3;
}
/* auto bottom margin: the cards are equal height, so one two-line description
   stretches all seven. The slack belongs above the clip, not under it. */
.rv-ac__card-desc {
  max-width: var(--rv-measure);
  margin: var(--rv-card-gap) 0 auto;
  color: var(--rv-muted);
  font-size: var(--rv-fs-sub);
  line-height: var(--rv-lh-sub);
}
/* The clips carry a baked-in WHITE background — no alpha, because WebKit cannot
   composite it in WebM — so this box must stay on the card's #ffffff. */
.rv-ac__card-clip {
  margin-top: 24px;
  border: 1px solid var(--rv-border);
  border-radius: var(--rv-radius-media);
  overflow: hidden;
  background: #ffffff;
}
.rv-ac__clip {
  display: block;
  width: 100%;
  height: auto;
}
.rv-ac__arrow {
  position: absolute;
  top: 50%;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  margin-top: -24px;
  padding: 0;
  border: 1px solid var(--rv-border);
  border-radius: 999px;
  background: #ffffff;
  color: var(--rv-navy);
  cursor: pointer;
  box-shadow: 0 10px 34px rgba(20, 40, 77, 0.09);
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.rv-ac__arrow--prev {
  left: 0;
}
.rv-ac__arrow--next {
  right: 0;
}
.rv-ac__arrow svg {
  width: 24px;
  height: 24px;
}
@media (hover: hover) {
  .rv-ac__arrow:hover {
    border-color: #1da1f2;
    box-shadow: 0 14px 38px rgba(20, 40, 77, 0.14);
  }
}
.rv-ac__controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  margin-top: 32px;
}
.rv-ac__bars {
  display: flex;
  align-items: center;
  gap: 8px;
}
/* Indicator and dwell meter in one: 28px wide when waiting, 56px when live, and
   the fill inside is scaled from the playing clip's own currentTime. */
.rv-ac__bar {
  position: relative;
  width: 28px;
  height: 6px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: var(--rv-border);
  cursor: pointer;
  overflow: hidden;
  transition: width 0.28s var(--rv-ease, ease), background-color 0.18s ease;
}
.rv-ac__bar.is-active {
  width: 56px;
}
.rv-ac__bar-fill {
  position: absolute;
  inset: 0;
  transform: scaleX(0);
  transform-origin: left center;
  border-radius: 999px;
  background: #1da1f2;
}
.rv-ac__toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--rv-border);
  border-radius: 999px;
  background: #ffffff;
  color: var(--rv-muted);
  cursor: pointer;
}
.rv-ac__toggle svg {
  width: 18px;
  height: 18px;
}
@media (hover: hover) {
  .rv-ac__toggle:hover {
    border-color: #1da1f2;
    color: var(--rv-navy);
  }
}

/* Below this the inner is too narrow to flank a 760px card with arrows. */
@media (max-width: 1024px) {
  .rv-ac {
    /* 48px of section padding plus a little air. vw, not %, for the reason on
       the base value above. */
    --rv-ac-card: calc(100vw - 80px);
  }
  /* No room to flank the card here, so the arrows wrap under it: the viewport
     takes a full row and both buttons land centred on the next one. */
  .rv-ac__stage {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 20px 16px;
  }
  .rv-ac__viewport {
    flex: 0 0 100%;
    order: 1;
  }
  .rv-ac__arrow {
    position: static;
    order: 2;
    margin-top: 0;
    width: 44px;
    height: 44px;
  }
  .rv-ac__controls {
    margin-top: 24px;
  }
}

/* Nothing plays itself under reduced motion, so a pause control would be a
   button that does nothing. Set by initCardCarousel. */
.rv-ac.is-static .rv-ac__toggle {
  display: none;
}

/* ===========================================================================
   .rv-bk — spec blocks: three hardware figures with the middle one emphasised,
   the shape the approved reference uses for this fold.
   =========================================================================== */
.rv-bk {
  --rv-navy: #14284d;
  --rv-muted: #4c6389;
  --rv-border: #c9d6ee;
  padding: 64px 24px 72px;
  background: #ffffff;
}
.rv-bk--tint {
  background: #f4f8fd;
}
/* One supplied figure in place of the blocks. It carries its own labels, so
   showing both would print every value twice; instead each covers the widths
   the other cannot. The figure runs edge to edge because its smallest caption
   is 27px of a 3007px frame — 10px inside the 1200px column, 13px full-bleed. */
.rv-bk__figure {
  display: none;
}
.rv-bk__figure img {
  display: block;
  width: 100%;
  height: auto;
}
@media (min-width: 1200px) {
  /* The figure IS the fold at this width: it runs edge to edge and the copy
     sits over the empty background its artwork was extended upward to hold. */
  .rv-bk--has-figure {
    position: relative;
    padding: 0;
  }
  .rv-bk--has-figure .rv-bk__inner {
    position: absolute;
    inset: 0 24px auto;
    padding-top: 64px;
  }
  .rv-bk--has-figure .rv-bk__row {
    display: none;
  }
  .rv-bk--has-figure .rv-bk__figure {
    display: block;
  }
}
.rv-bk__inner {
  max-width: 1200px;
  margin-inline: auto;
}
.rv-bk__head {
  margin-inline: auto;
  text-align: center;
}
.rv-bk__title {
  margin: 0;
  color: var(--rv-navy);
  font-size: var(--rv-fs-h2);
  font-weight: var(--rv-fw-h2);
  /* 1.14, which is what home.css actually renders (45.6px on a 40px h2). The
     design system doc says 1.2; the stylesheet wins per its own rule. */
  line-height: 1.14;
  text-wrap: balance;
}
.rv-bk__body {
  max-width: var(--rv-measure);
  margin: var(--rv-title-gap) auto 0;
  color: var(--rv-muted);
  font-size: var(--rv-fs-sub);
  line-height: var(--rv-lh-sub);
}
.rv-bk__row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  align-items: center;
  gap: 24px;
  margin: 0;
}
/* The gap belongs to the pair, not the row: this band is also used with no
   heading of its own, where a top margin would strand 40px above the cards. */
.rv-bk__head + .rv-bk__row {
  margin-top: var(--rv-head-gap);
}
.rv-bk__block {
  padding: 32px 24px;
  border-radius: var(--rv-radius-card);
  background: #ffffff;
  box-shadow: 0 18px 44px rgba(20, 40, 77, 0.1);
  text-align: center;
}
/* The emphasised block is marked by elevation and height, never a coloured
   fill — the design system's rule for a featured card. Its value used to be
   set larger too; all three now share one size on request. */
.rv-bk__block--lead {
  padding: 44px 24px;
  box-shadow: 0 28px 60px rgba(20, 40, 77, 0.17);
}
/* The part renders sit above the figure. Square artwork, so a height cap keeps
   the three blocks the same size whatever each render's own dimensions are. */
.rv-bk__media {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 112px;
  margin-bottom: 20px;
}
.rv-bk__media img {
  display: block;
  width: auto;
  max-width: 100%;
  max-height: 100%;
  height: auto;
}
.rv-bk__block--lead .rv-bk__media {
  height: 132px;
}
/* Marked stand-in, not a silent gap. */
.rv-bk__media--pending {
  flex-direction: column;
  gap: 8px;
  border: 1px dashed var(--rv-border);
  border-radius: var(--rv-radius-media);
  color: var(--rv-muted);
  font-size: var(--rv-fs-body);
}
.rv-bk__media--pending svg {
  width: 26px;
  height: 26px;
}
.rv-bk__value {
  color: var(--rv-navy);
  font-size: clamp(1.6rem, 2.8vw, 2.1rem);
  font-weight: 600;
  line-height: 1.1;
}
.rv-bk__label {
  margin: var(--rv-caption-gap) 0 0;
  color: var(--rv-muted);
  font-size: var(--rv-fs-body);
  line-height: 1.5;
}

@media (max-width: 640px) {
  .rv-bk {
    padding: 48px 20px 56px;
  }
  /* Three small boxes abreast, not full-width slabs. Stretch so all three
     match whatever each label wraps to. */
  .rv-bk__row {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: stretch;
    gap: 8px;
  }
  .rv-bk__block,
  .rv-bk__block--lead {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    padding: 18px 10px;
    border-radius: var(--rv-radius-media);
    box-shadow: 0 10px 26px rgba(20, 40, 77, 0.09);
  }
  .rv-bk__value {
    font-size: clamp(0.875rem, 4.2vw, 1.125rem);
  }
  .rv-bk__label {
    margin-top: 0;
  }
}
/* A 320px screen leaves 88px a column; the side padding is what decides
   whether "Octa-Core" and "8 / 128 GB" hold one line. */
@media (max-width: 360px) {
  .rv-bk__block,
  .rv-bk__block--lead {
    padding: 16px 6px;
  }
  /* The value's clamp bottoms out at 14px here, which would leave it smaller
     than its own label; 13.6px keeps the order and stays over the 13.5px floor. */
  .rv-bk__label {
    font-size: 0.85rem;
  }
}

/* ===========================================================================
   .rv-sh — showcase: a centred head over a two-column row. Two shapes from one
   block: --specs puts a cut-out product shot beside an icon-and-label list,
   --compare puts two captioned photographs side by side. They stack at 900px,
   which is where the spec labels start to wrap mid-phrase.
   =========================================================================== */
.rv-sh {
  --rv-navy: #14284d;
  --rv-muted: #4c6389;
  --rv-border: #c9d6ee;
  padding: 64px 24px 72px;
  background: #ffffff;
}
.rv-sh--tint {
  background: #f4f8fd;
}
.rv-sh__inner {
  max-width: 1200px;
  margin-inline: auto;
}
.rv-sh__head {
  text-align: center;
}
.rv-sh__title {
  margin: 0;
  color: var(--rv-navy);
  font-size: var(--rv-fs-h2);
  font-weight: var(--rv-fw-h2);
  line-height: 1.14;
  text-wrap: balance;
}
.rv-sh__body {
  max-width: var(--rv-measure);
  margin: var(--rv-title-gap) auto 0;
  color: var(--rv-muted);
  font-size: var(--rv-fs-sub);
  line-height: var(--rv-lh-sub);
}
.rv-sh__row {
  display: grid;
  gap: 48px;
  align-items: center;
  margin-top: var(--rv-head-gap);
}
@media (min-width: 901px) {
  /* The product shot earns the wider column; the labels set short. */
  .rv-sh--specs .rv-sh__row {
    grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
  }
  .rv-sh--compare .rv-sh__row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
  }
}
.rv-sh__figure {
  margin: 0;
}
.rv-sh__figure img {
  display: block;
  width: 100%;
  height: auto;
}
/* Only the compare pair: those two are opaque rectangles. The colour shot is a
   cut-out on transparency, where a radius would clip nothing and show nothing. */
.rv-sh--compare .rv-sh__figure img {
  border-radius: var(--rv-radius-media);
}
.rv-sh__caption {
  margin-top: var(--rv-caption-gap);
  color: var(--rv-muted);
  font-size: var(--rv-fs-sub);
  line-height: 1.4;
  text-align: center;
}
.rv-sh__specs {
  display: grid;
  gap: 30px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.rv-sh__spec {
  display: flex;
  gap: 20px;
  align-items: center;
}
/* A fixed slot, so every label starts at the same x whatever the artwork is.
   The five are all 65x65 now; contain keeps that true if one is ever redrawn
   to another ratio. */
.rv-sh__spec-icon {
  flex: none;
  width: 48px;
  height: 48px;
  object-fit: contain;
}
.rv-sh__spec-label {
  color: var(--rv-navy);
  font-size: clamp(1.05rem, 1.55vw, 1.4rem);
  font-weight: 500;
  line-height: 1.3;
}

@media (max-width: 900px) {
  .rv-sh__row {
    gap: 36px;
  }
  /* Stacked, a figure would otherwise run the full 851px of a tablet and take
     the compare fold past 1500px. Below this cap the phone is unaffected. */
  .rv-sh__figure {
    width: 100%;
    max-width: 560px;
    margin-inline: auto;
  }
  .rv-sh__specs {
    gap: 24px;
  }
  .rv-sh__spec-icon {
    width: 40px;
    height: 40px;
  }
  /* Centre the stacked list under the shot rather than leaving it hard left
     against a centred head. */
  .rv-sh__specs {
    max-width: 30rem;
    margin-inline: auto;
  }
}
@media (max-width: 640px) {
  .rv-sh {
    padding: 48px 20px 56px;
  }
  .rv-sh__row {
    gap: 28px;
  }
  .rv-sh__spec {
    gap: 16px;
  }
  .rv-sh__spec-icon {
    width: 36px;
    height: 36px;
  }
}

/* ===========================================================================
   .rv-qt — written testimonials on a horizontal scroll track. Native
   scroll-snap does the scrolling, so it works with JS off; the arrows are
   progressive enhancement. v4Testimonials stays the homepage's video carousel.
   =========================================================================== */
.rv-qt {
  --rv-navy: #14284d;
  --rv-muted: #4c6389;
  --rv-border: #c9d6ee;
  --rv-qt-card: clamp(280px, 33%, 400px);
  padding: 64px 24px 72px;
  background: #ffffff;
  /* The track bleeds to the viewport edge; nothing may scroll the page. */
  overflow: hidden;
}
.rv-qt--tint {
  background: #f4f8fd;
}
.rv-qt__inner {
  max-width: 1200px;
  margin-inline: auto;
}
.rv-qt__title {
  margin: 0;
  color: var(--rv-navy);
  font-size: var(--rv-fs-h2);
  font-weight: var(--rv-fw-h2);
  line-height: 1.14;
  text-align: center;
  text-wrap: balance;
}
/* Under the track and to the right, the same place .rv-tm puts its pair. */
.rv-qt__nav {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
  margin-top: 24px;
}
.rv-qt__arrow {
  display: grid;
  width: 44px;
  height: 44px;
  padding: 0;
  place-items: center;
  border: 1px solid var(--rv-border);
  border-radius: 999px;
  background: #ffffff;
  color: var(--rv-navy);
  cursor: pointer;
}
.rv-qt__arrow:hover:not(:disabled) {
  border-color: #1da1f2;
  color: #1da1f2;
}
.rv-qt__arrow:disabled {
  opacity: 0.35;
  cursor: default;
}

.rv-qt__track {
  /* Two rows shared by every card, not a row of independent flex columns: the
     quote takes the slack and the caption row is as tall as the tallest
     caption, so the rule above the names lands at one height whether a role
     runs to one line or two. */
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: var(--rv-qt-card);
  grid-template-rows: 1fr auto;
  column-gap: var(--rv-card-gap);
  margin: var(--rv-head-gap) 0 0;
  /* -24px cancels the section padding so a card can sit against the edge as
     it scrolls past; the padding puts the first one back on the grid. */
  padding: 4px 24px 4px;
  margin-inline: -24px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: 24px;
  list-style: none;
  scrollbar-width: none;
}
.rv-qt__track::-webkit-scrollbar {
  display: none;
}
.rv-qt__item {
  display: grid;
  grid-row: span 2;
  grid-template-rows: subgrid;
  scroll-snap-align: start;
}
/* One quote has nothing to scroll past, so it sets wide and centred instead
   of sitting as a lone narrow card against the left edge. */
.rv-qt__track:has(> :only-child) {
  justify-content: center;
}
.rv-qt__track:has(> :only-child) {
  grid-auto-columns: min(760px, 100%);
}

.rv-qt__card {
  position: relative;
  display: grid;
  grid-row: span 2;
  grid-template-rows: subgrid;
  row-gap: 20px;
  margin: 0;
  padding: 32px 28px 28px;
  overflow: hidden;
  border-radius: var(--rv-radius-card);
  background: #f4f8fd;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.rv-qt--tint .rv-qt__card {
  background: #ffffff;
}
/* A rule across the card's head, clipped to its corners by the overflow above
   — as a short tab it read as a dash floating free of the card. */
.rv-qt__card::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  height: 4px;
  background: #1da1f2;
}
@media (hover: hover) {
  .rv-qt__card:hover {
    transform: translateY(-4px);
    box-shadow: 0 14px 34px rgba(20, 40, 77, 0.1);
  }
}
.rv-qt__quote {
  margin: 0;
}
.rv-qt__quote::before {
  content: "\201C";
  display: block;
  margin-bottom: -10px;
  color: var(--rv-border);
  font-size: 56px;
  font-weight: 700;
  line-height: 1;
}
.rv-qt__quote p {
  margin: 0;
  color: var(--rv-navy);
  font-size: var(--rv-fs-sub);
  line-height: var(--rv-lh-sub);
}
.rv-qt__person {
  display: grid;
  gap: 2px;
  padding-top: 20px;
  border-top: 1px solid var(--rv-border);
}
.rv-qt__name {
  color: var(--rv-navy);
  font-size: var(--rv-fs-sub);
  font-weight: 600;
  line-height: 1.35;
}
.rv-qt__role {
  color: var(--rv-muted);
  font-size: var(--rv-fs-body);
  line-height: 1.45;
}

@media (max-width: 900px) {
  .rv-qt {
    --rv-qt-card: min(78%, 420px);
  }
}
@media (max-width: 640px) {
  .rv-qt {
    --rv-qt-card: min(84%, 340px);
    padding: 48px 20px 56px;
  }
  .rv-qt__track {
    padding-inline: 20px;
    margin-inline: -20px;
    scroll-padding-inline: 20px;
  }
  .rv-qt__card {
    padding: 28px 22px 24px;
  }
}

/* ===========================================================================
   Fold grouping. Several folds are built from more than one <section> — a
   centred copy band and its content rows — so the standard 72px+64px section
   boundary was appearing INSIDE a single fold, six times over. A section that
   continues the fold above it drops its top padding; the one it continues
   trims its bottom padding.

   Applied per call site from the page template rather than by a sibling
   selector, because the same class pair occurs both within a fold and between
   folds: .rv-sr + .rv-sr is intra-fold for the audio/video rows but a real
   fold boundary between Speakers and Display. Utility classes, not ids —
   ids on this page are analytics hooks.
   =========================================================================== */
.rv-flush-top {
  padding-top: 0;
}
.rv-flush-bottom {
  padding-bottom: 32px;
}
@media (max-width: 640px) {
  .rv-flush-bottom {
    padding-bottom: 24px;
  }
}

/* ===========================================================================
   .rv-ig — icon grid: a mark over a title and a line of copy, three across.
   Ported from the homepage's US VisionX grid (.rv-vx__grid in home.css), which
   this page does not load a section for. Same metrics, page-scoped name so the
   two cannot collide if that section ever lands here.
   =========================================================================== */
.rv-ig {
  --rv-navy: #14284d;
  --rv-muted: #4c6389;
  padding: 64px 24px 72px;
  background: #ffffff;
}
.rv-ig--tint {
  background: #f4f8fd;
}
.rv-ig__inner {
  max-width: 1200px;
  margin-inline: auto;
}
.rv-ig__head {
  margin-inline: auto;
  margin-bottom: var(--rv-head-gap);
  text-align: center;
}
.rv-ig__title {
  margin: 0;
  color: var(--rv-navy);
  font-size: var(--rv-fs-h2);
  font-weight: var(--rv-fw-h2);
  line-height: 1.14;
  text-wrap: balance;
}
.rv-ig__lede {
  max-width: var(--rv-measure);
  margin: var(--rv-title-gap) auto 0;
  color: var(--rv-muted);
}
.rv-ig__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 40px 32px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.rv-ig__icon {
  display: block;
  width: 40px;
  height: 40px;
  margin-bottom: 16px;
}
.rv-ig__card-title {
  margin: 0;
  color: var(--rv-navy);
  font-size: var(--rv-fs-title);
  font-weight: var(--rv-fw-title);
  line-height: 1.3;
}
.rv-ig__card-desc {
  margin-top: 8px;
  color: var(--rv-muted);
  line-height: 1.5;
}
@media (max-width: 1024px) {
  .rv-ig {
    padding: 48px 24px 56px;
  }
  .rv-ig__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 640px) {
  .rv-ig__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
  }
  .rv-ig__icon {
    width: 36px;
    height: 36px;
    margin-bottom: 12px;
  }
}
