/* ==========================================================================
   VIDEO TESTIMONIALS  ·  .hp2-vt__*
   Loaded only on the v2 page templates, alongside homepage-v2.css.
   Markup: template-parts/hp2-video-testimonials.php
   Behaviour: assets/js/video-testimonials.js
   ==========================================================================

   PALETTE NOTE
   The brief specified gold stars (#FFD700), a green verified tick (#27AE60)
   and blue pagination (#4A90E2). This block sits directly above the written
   review wall, which is deliberately monochrome — homepage-v2.css even says
   so at .hp2-tes__stars ("solid glyphs kept black to honour the B&W
   system"). Dropping three saturated hues in would have made the video row
   read as a bolted-on widget rather than part of the same section.
   So the brief's palette is mapped onto the existing tokens below. Every
   value is a one-line switch — the literal brief colours are kept in the
   comments if you want them.

   ASPECT RATIO NOTE
   The brief assumed 16:9 media. All three source clips are 9:16 vertical
   selfies, so a 16:9 frame would have pillarboxed them into slivers. The
   frame here is 4:5 — see testimonials/build-media.sh for the full
   reasoning and the per-clip crop geometry.
   ========================================================================== */

.hp2-vt {
  --vt-card-bg:      #fff;
  --vt-text:         var(--hp2-dark, #0a0a0f);   /* brief: #1a1a1a  */
  --vt-text-soft:    var(--hp2-mid, #555);       /* brief: #666666  */
  --vt-border:       rgba(10, 10, 15, 0.1);      /* brief: #E8E8E8  */

  --vt-play-bg:      rgba(10, 10, 15, 0.5);      /* brief: rgba(0,0,0,.5)  */
  --vt-play-bg-hov:  rgba(10, 10, 15, 0.72);     /* brief: rgba(0,0,0,.7)  */
  --vt-play-icon:    #fff;

  --vt-star:         var(--hp2-dark, #0a0a0f);   /* brief: #FFD700  */
  --vt-verified:     var(--hp2-dark, #0a0a0f);   /* brief: #27AE60  */

  --vt-arrow:        var(--hp2-dark, #0a0a0f);   /* brief: #333333  */
  --vt-dot:          rgba(10, 10, 15, 0.18);     /* brief: #D0D0D0  */
  --vt-dot-active:   var(--hp2-dark, #0a0a0f);   /* brief: #4A90E2  */

  --vt-shadow-hover: 0 18px 40px -18px rgba(10, 10, 15, 0.32);
  --vt-ease:         cubic-bezier(0.4, 0, 0.2, 1);

  /*max-width: 1180px;*/
  margin: 0 auto clamp(30px, 3.4vw, 46px);
}

/* --------------------------------------------------------------------------
   Sub-header — sits under the section's main header, so it is an h3 at a
   deliberately quieter weight than .hp2-tes__h2. Arrows live up here rather
   than floating over the cards: at 3-up they would otherwise overlap faces.
   -------------------------------------------------------------------------- */
.hp2-vt__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: clamp(16px, 1.8vw, 22px);
}
.hp2-vt__h3 {
  font-size: clamp(16px, 1.5vw, 19px);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.015em;
  color: var(--vt-text);
  margin: 0;
  max-width: 34ch;
  text-wrap: pretty;
}

.hp2-vt__nav {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}
.hp2-vt__arrow {
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--vt-border);
  border-radius: 50%;
  background: #fff;
  color: var(--vt-arrow);
  cursor: pointer;
  transition: background .25s var(--vt-ease), color .25s var(--vt-ease),
              border-color .25s var(--vt-ease), transform .25s var(--vt-ease),
              opacity .25s var(--vt-ease);
}
.hp2-vt__arrow svg { width: 17px; height: 17px; display: block; }
.hp2-vt__arrow:hover {
  background: var(--vt-text);
  border-color: var(--vt-text);
  color: #fff;
  transform: scale(1.06);
}
/* At a boundary. Swiper sets BOTH the class and — since these are real
   <button> elements — the native `disabled` property, so clicks are already
   dead at the DOM level; this rule only has to make that legible.

   Deliberately NO `pointer-events: none`: it would stop the element being a
   hit-test target at all, and the browser would then paint whatever cursor
   sits underneath instead of `not-allowed`. The two cancel out, and the
   native `disabled` already does the blocking that pointer-events was being
   asked for. Keeping the element hit-testable is also what lets the cursor
   explain *why* nothing happened. */
.hp2-vt__arrow:disabled,
.hp2-vt__arrow.swiper-button-disabled {
  opacity: 0.28;
  cursor: not-allowed;
  transform: none;
  background: #fff;
  color: var(--vt-arrow);
  border-color: var(--vt-border);
}
/* Kill the hover treatment at a boundary — :hover still fires on a disabled
   button, and this selector must outrank .hp2-vt__arrow:hover above. */
.hp2-vt__arrow:disabled:hover,
.hp2-vt__arrow.swiper-button-disabled:hover {
  background: #fff;
  border-color: var(--vt-border);
  color: var(--vt-arrow);
  transform: none;
}
/* Swiper adds -lock when every slide already fits (desktop, 3 videos), and
   the JS mirrors that onto the whole nav so the empty row collapses. */
.hp2-vt__nav.is-locked { display: none; }

/* --------------------------------------------------------------------------
   Carousel shell. Swiper clips at the container edge, so the vertical
   padding buys room for the card's -8px hover lift and its shadow, and the
   bottom band holds the pagination.
   -------------------------------------------------------------------------- */
.hp2-vt__swiper {
  overflow: hidden;
  padding: 10px 0 40px;
  margin: -10px 0 -10px;
}
/* Equal-height cards regardless of quote length. */
.hp2-vt__swiper .swiper-wrapper { align-items: stretch; }
.hp2-vt__slide { height: auto; display: flex; }

/* --------------------------------------------------------------------------
   Pre-init slide sizing — prevents a full-width first card on page load.

   Swiper's own stylesheet sets `.swiper-slide { width: 100% }` and the real
   per-slide widths only arrive as INLINE styles once its JS has run. So the
   browser's first paint puts slide 1 at the full container width: measured
   1180x1671 on desktop, which then snapped to 377x700 on init — a ~970px
   layout shift and a briefly enormous first testimonial.

   These rules mirror Swiper's own arithmetic — (container - gap*(n-1))/n with
   a matching margin-right — so the first paint is already correct. They stop
   applying the instant .swiper-initialized lands, leaving Swiper's measured
   values untouched, and they double as the fallback layout if its JS never
   runs at all. Keep the numbers in step with the `breakpoints` object in
   video-testimonials.js.
   -------------------------------------------------------------------------- */
.hp2-vt__swiper:not(.swiper-initialized) .hp2-vt__slide {
  width: 100%;
  margin-right: 16px;
}
@media (min-width: 768px) {
  .hp2-vt__swiper:not(.swiper-initialized) .hp2-vt__slide {
    width: calc((100% - 20px) / 2);
    margin-right: 20px;
  }
}
@media (min-width: 1024px) {
  .hp2-vt__swiper:not(.swiper-initialized) .hp2-vt__slide {
    width: calc((100% - 48px) / 3);
    margin-right: 24px;
  }
}
@media (min-width: 1280px) {
  .hp2-vt__swiper:not(.swiper-initialized) .hp2-vt__slide {
    width: calc((100% - 60px) / 4);
    margin-right: 20px;
  }
}

/* --------------------------------------------------------------------------
   Card
   -------------------------------------------------------------------------- */
.hp2-vt__card {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--vt-card-bg);
  border: 1px solid var(--vt-border);
  border-radius: 16px;                 /* matches .hp2-tes__card, brief said 12px */
  overflow: hidden;                    /* clips the media's hover zoom */
  transition: transform .4s var(--vt-ease),
              box-shadow .4s var(--vt-ease),
              border-color .4s var(--vt-ease);
}

/* --------------------------------------------------------------------------
   Media frame — 3:4, the poster and the video stacked in the same box.
   Taller than the original 4:5 so the video reads as the lead element and
   the card body (name/quote) reads as a caption underneath, not a peer.
   The poster is pre-cropped to the 4:5 window the build script baked, so
   it needs no focus or zoom; the video is the raw 9:16 clip, so it gets
   both — going taller here just shows more of the same crop, no re-crop
   needed.
   -------------------------------------------------------------------------- */
.hp2-vt__media {
  position: relative;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  background: #0a0a0f;                 /* letterbox colour before first paint */
  flex-shrink: 0;
}

.hp2-vt__poster,
.hp2-vt__vid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.hp2-vt__poster {
  object-position: center center;
  transition: transform .4s var(--vt-ease);
}
.hp2-vt__vid {
  object-position: center var(--vt-focus, 50%);
  transform: scale(var(--vt-zoom, 1));
  transition: transform .4s var(--vt-ease), opacity .3s linear;
  opacity: 0;                          /* revealed once playback truly starts */
}
.hp2-vt__card.is-playing .hp2-vt__vid { opacity: 1; }

/* Duration chip */
.hp2-vt__dur {
  position: absolute;
  right: 10px;
  bottom: 10px;
  z-index: 3;
  padding: 3px 7px;
  border-radius: 6px;
  background: rgba(10, 10, 15, 0.6);
  backdrop-filter: blur(4px);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1.4;
  transition: opacity .3s var(--vt-ease);
}
.hp2-vt__card.is-playing .hp2-vt__dur { opacity: 0; pointer-events: none; }

/* --------------------------------------------------------------------------
   Play button — centred overlay, idle pulse, grows on hover.
   -------------------------------------------------------------------------- */
.hp2-vt__play {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 4;
  width: 64px;
  height: 64px;
  margin: -32px 0 0 -32px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: var(--vt-play-bg);
  color: var(--vt-play-icon);
  cursor: pointer;
  opacity: 0.85;
  transition: opacity .4s var(--vt-ease), transform .4s var(--vt-ease),
              background .4s var(--vt-ease);
  animation: hp2-vt-pulse 2s ease-in-out infinite;
}
.hp2-vt__play-icon {
  width: 26px;
  height: 26px;
  margin-left: 3px;                    /* optical centring of the triangle */
  display: block;
}
/* Expanding halo, purely decorative. */
.hp2-vt__play-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.55);
  animation: hp2-vt-ring 2.4s ease-out infinite;
  pointer-events: none;
}
@keyframes hp2-vt-pulse {
  0%, 100% { opacity: 0.72; }
  50%      { opacity: 0.92; }
}
@keyframes hp2-vt-ring {
  0%   { transform: scale(1);    opacity: 0.55; }
  70%  { transform: scale(1.45); opacity: 0; }
  100% { transform: scale(1.45); opacity: 0; }
}
.hp2-vt__card.is-playing .hp2-vt__play,
.hp2-vt__card.is-loading .hp2-vt__play {
  opacity: 0;
  pointer-events: none;
  transform: scale(0.8);
  animation: none;
}

/* Buffering spinner, shown between the click and the first frame. */
.hp2-vt__card.is-loading .hp2-vt__media::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 34px;
  height: 34px;
  margin: -17px 0 0 -17px;
  z-index: 4;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-top-color: #fff;
  border-radius: 50%;
  animation: hp2-vt-spin .7s linear infinite;
}
@keyframes hp2-vt-spin { to { transform: rotate(360deg); } }

/* --------------------------------------------------------------------------
   Custom control bar.
   Native <video controls> is not usable here: the video element carries a
   scale() transform for per-clip framing, and native controls are painted
   inside that transformed box, so on the zoomed clip they would render
   partly outside the visible frame. These controls live on the media
   wrapper instead, so framing and chrome stay independent.
   -------------------------------------------------------------------------- */
.hp2-vt__controls {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 22px 11px 10px;
  background: linear-gradient(to top, rgba(10, 10, 15, 0.78), rgba(10, 10, 15, 0));
  opacity: 0;
  transform: translateY(6px);
  transition: opacity .25s var(--vt-ease), transform .25s var(--vt-ease);
  pointer-events: none;
}
.hp2-vt__card.is-playing .hp2-vt__controls,
.hp2-vt__card.is-paused  .hp2-vt__controls {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
/* Keep them up while anything inside has keyboard focus. */
.hp2-vt__controls:focus-within { opacity: 1; transform: none; pointer-events: auto; }

.hp2-vt__ctl {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: #fff;
  cursor: pointer;
  transition: background .2s var(--vt-ease);
}
.hp2-vt__ctl:hover { background: rgba(255, 255, 255, 0.18); }
.hp2-vt__ctl svg { width: 16px; height: 16px; display: block; }
/* Icon swapping is driven by state classes on the card / button. */
.hp2-vt__ctl .hp2-vt__ico--pause,
.hp2-vt__card.is-playing .hp2-vt__ctl .hp2-vt__ico--play { display: none; }
.hp2-vt__card.is-playing .hp2-vt__ctl .hp2-vt__ico--pause { display: block; }
.hp2-vt__ctl--mute .hp2-vt__ico--muted { display: none; }
.hp2-vt__ctl--mute.is-muted .hp2-vt__ico--muted { display: block; }
.hp2-vt__ctl--mute.is-muted .hp2-vt__ico--loud  { display: none; }

.hp2-vt__seek {
  flex: 1 1 auto;
  min-width: 0;
  height: 16px;
  margin: 0;
  padding: 0;
  background: transparent;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
.hp2-vt__seek::-webkit-slider-runnable-track {
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(to right, #fff var(--vt-progress, 0%), rgba(255, 255, 255, 0.32) var(--vt-progress, 0%));
}
.hp2-vt__seek::-moz-range-track {
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(to right, #fff var(--vt-progress, 0%), rgba(255, 255, 255, 0.32) var(--vt-progress, 0%));
}
.hp2-vt__seek::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 10px;
  height: 10px;
  margin-top: -3.5px;
  border: 0;
  border-radius: 50%;
  background: #fff;
}
.hp2-vt__seek::-moz-range-thumb {
  width: 10px;
  height: 10px;
  border: 0;
  border-radius: 50%;
  background: #fff;
}

.hp2-vt__time {
  flex-shrink: 0;
  color: #fff;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  opacity: 0.9;
}

/* --------------------------------------------------------------------------
   Card body
   -------------------------------------------------------------------------- */
.hp2-vt__body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: clamp(18px, 1.6vw, 22px) clamp(18px, 1.7vw, 24px) clamp(18px, 1.7vw, 24px);
}

.hp2-vt__who-row {
  display: flex;
  align-items: center;
  gap: 11px;
}
.hp2-vt__avatar {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--hp2-dark, #0a0a0f);
  border: 1px solid rgba(10, 10, 15, 0.08);
}
.hp2-vt__who {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.hp2-vt__name {
  font-size: 14.5px;
  font-weight: 700;
  color: var(--vt-text);
  letter-spacing: -0.005em;
}
/* Two lines, not the single nowrap line the written cards use: those have
   short roles ("Founder"), whereas these run to "Tech Solutions Inc. ·
   Business Development Manager", which ellipsed away the actual job title.
   min-height reserves that 2-line box even when a brand name is short
   enough to sit on one line (most of them) — otherwise a short brand
   pulls its own quote up while a long one (e.g. "ScrubsUnlimited.com &
   FindScrubs.com") pushes its quote down, and the row of cards reads as
   misaligned even though every card is the same overall height. Using em
   (not px) keeps this correct at the ≤479px breakpoint, which shrinks
   this font-size to 11px. */
.hp2-vt__brand-line {
  font-size: 12px;
  line-height: 1.35;
  min-height: 2.7em;
  color: var(--vt-text-soft);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
.hp2-vt__date {
  margin-left: auto;
  align-self: flex-start;
  font-size: 11.5px;
  color: #9a9a97;
  white-space: nowrap;
  flex-shrink: 0;
}

.hp2-vt__rate-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.hp2-vt__stars {
  color: var(--vt-star);
  font-size: 14px;
  line-height: 1;
  letter-spacing: 2px;
  white-space: nowrap;
}
.hp2-vt__verified {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  font-weight: 600;
  color: var(--vt-text-soft);
}
.hp2-vt__verified svg {
  width: 13px;
  height: 13px;
  flex-shrink: 0;
  color: var(--vt-verified);
}

/* Clamped to 3 lines (ellipsis beyond) with min-height reserving that same
   3-line box: holding every card to one fixed text height is what makes a
   row of 4 read as even regardless of how long each quote naturally runs.
   3, not 2 — the longest current quote (Farmon's, ~103 characters) needs
   all 3 lines at this card width, and clamping to 2 would ellipsis off
   its ending. em units keep the reserved height correct at the ≤479px
   breakpoint, which drops this font-size to 13.5px. */
.hp2-vt__text {
  font-size: 14.5px;
  line-height: 1.58;
  min-height: 4.74em;
  color: #1a1a1f;
  margin: 0;
  text-wrap: pretty;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  line-clamp: 4;
  /*overflow: hidden;*/
}

.hp2-vt__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: auto;                    /* pins metrics to the card foot */
  padding-top: 2px;
}
.hp2-vt__chip {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  padding: 5px 9px;
  border: 1px solid var(--vt-border);
  border-radius: 999px;
  font-size: 11.5px;
  color: var(--vt-text-soft);
  white-space: nowrap;
}
.hp2-vt__chip b {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--vt-text);
}

/* --------------------------------------------------------------------------
   Pagination
   -------------------------------------------------------------------------- */
.hp2-vt__dots {
  position: absolute;
  bottom: 8px !important;
  left: 0;
  width: 100%;
  text-align: center;
  line-height: 0;
}
.hp2-vt__dots .swiper-pagination-bullet {
  width: 8px;
  height: 8px;
  margin: 0 4px !important;
  background: var(--vt-dot);
  opacity: 1;
  transition: transform .25s var(--vt-ease), background .25s var(--vt-ease);
}
.hp2-vt__dots .swiper-pagination-bullet:hover { transform: scale(1.25); }
.hp2-vt__dots .swiper-pagination-bullet-active { background: var(--vt-dot-active); }
.hp2-vt__dots.swiper-pagination-lock { display: none; }

/* --------------------------------------------------------------------------
   Focus visibility (WCAG 2.4.7). Two-tone ring so it reads on both the
   white card and the dark video frame.
   -------------------------------------------------------------------------- */
.hp2-vt__play:focus-visible,
.hp2-vt__ctl:focus-visible,
.hp2-vt__seek:focus-visible,
.hp2-vt__arrow:focus-visible,
.hp2-vt__dots .swiper-pagination-bullet:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
  box-shadow: 0 0 0 4px rgba(10, 10, 15, 0.85);
}
.hp2-vt__arrow:focus-visible {
  outline-color: var(--vt-text);
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.9);
}

/* --------------------------------------------------------------------------
   Hover — pointer devices only. Gated on (hover: hover) rather than a width
   breakpoint so a touch tablet never gets a stuck hover state, which is
   what the brief's "disable hover on tablet/mobile" is really guarding
   against. Suppressed during playback so the frame cannot drift mid-clip.
   -------------------------------------------------------------------------- */
@media (hover: hover) and (pointer: fine) {
  /* Every rule here is gated on the card being idle. Without the :not()s
     these tie on specificity with the .is-playing rules above and, being
     later in the file, would win — putting the play button back on top of a
     video that is already running and nudging the frame mid-sentence. */
  .hp2-vt__card:not(.is-playing):not(.is-paused):not(.is-loading):hover {
    transform: translateY(-8px);
    border-color: rgba(10, 10, 15, 0.2);
    box-shadow: var(--vt-shadow-hover);
  }
  /* A card mid-playback still earns the shadow, just not the movement. */
  .hp2-vt__card.is-playing:hover,
  .hp2-vt__card.is-paused:hover {
    border-color: rgba(10, 10, 15, 0.2);
    box-shadow: var(--vt-shadow-hover);
  }
  .hp2-vt__card:not(.is-playing):not(.is-paused):not(.is-loading):hover .hp2-vt__poster {
    transform: scale(1.05);
  }
  .hp2-vt__card:not(.is-playing):not(.is-paused):not(.is-loading):hover .hp2-vt__vid {
    transform: scale(calc(var(--vt-zoom, 1) * 1.05));
  }
  .hp2-vt__card:not(.is-playing):not(.is-loading):hover .hp2-vt__play {
    opacity: 1;
    transform: scale(1.15);
    background: var(--vt-play-bg-hov);
    animation: none;
  }
  /* Keyboard parity: focusing the play button gets the same emphasis. */
  .hp2-vt__card:not(.is-playing):not(.is-loading) .hp2-vt__play:focus-visible {
    opacity: 1;
    transform: scale(1.15);
    background: var(--vt-play-bg-hov);
    animation: none;
  }
}

/* Touch feedback in place of hover. */
@media (hover: none) {
  .hp2-vt__play:active { transform: scale(0.92); opacity: 1; }
  .hp2-vt__card:active { border-color: rgba(10, 10, 15, 0.2); }
}

/* --------------------------------------------------------------------------
   Breakpoints. Column counts are Swiper's job (see video-testimonials.js);
   what changes here is only what CSS owns — control sizing and padding.
   -------------------------------------------------------------------------- */

/* Tablet — 768px to 1023px */
@media (max-width: 1023px) {
  .hp2-vt__play {
    width: 56px;
    height: 56px;
    margin: -28px 0 0 -28px;
  }
  .hp2-vt__play-icon { width: 23px; height: 23px; }
  .hp2-vt__body { padding: 18px 20px 20px; }
}

/* Mobile — under 768px. One card per view, so the play target grows. */
@media (max-width: 767px) {
  .hp2-vt__head {
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
  }
  .hp2-vt__nav { display: none; }      /* swipe + dots carry navigation here */
  .hp2-vt__play {
    width: 68px;
    height: 68px;
    margin: -34px 0 0 -34px;
  }
  .hp2-vt__play-icon { width: 27px; height: 27px; }
  .hp2-vt__body { padding: 16px; gap: 11px; }
  .hp2-vt__swiper { padding-bottom: 36px; }
  /* 48px minimum touch target (WCAG 2.5.5). */
  .hp2-vt__ctl { width: 34px; height: 34px; }
  .hp2-vt__seek { height: 22px; }
  .hp2-vt__dots .swiper-pagination-bullet { width: 9px; height: 9px; margin: 0 5px !important; }
}

/* Extra small — under 480px */
@media (max-width: 479px) {
  .hp2-vt__h3 { font-size: 15px; }
  .hp2-vt__play {
    width: 56px;
    height: 56px;
    margin: -28px 0 0 -28px;
  }
  .hp2-vt__play-icon { width: 22px; height: 22px; }
  .hp2-vt__body { padding: 12px; gap: 10px; }
  .hp2-vt__avatar { width: 40px; height: 40px; }
  .hp2-vt__name { font-size: 13.5px; }
  .hp2-vt__brand-line { font-size: 11px; }
  .hp2-vt__date { font-size: 10.5px; }
  .hp2-vt__text { font-size: 13.5px; }
  .hp2-vt__chip { font-size: 10.5px; padding: 4px 8px; }
  .hp2-vt__chip b { font-size: 11.5px; }
  .hp2-vt__time { font-size: 10px; }
}

/* --------------------------------------------------------------------------
   Reduced motion — kill the decorative loops and the zoom/lift, keep every
   state change legible (opacity only).
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .hp2-vt__play,
  .hp2-vt__play-ring,
  .hp2-vt__card.is-loading .hp2-vt__media::after {
    animation: none !important;
  }
  .hp2-vt__play { opacity: 1; }
  .hp2-vt__card,
  .hp2-vt__poster,
  .hp2-vt__vid,
  .hp2-vt__arrow,
  .hp2-vt__controls {
    transition-duration: .01ms !important;
  }
  .hp2-vt__card:hover { transform: none; }
  .hp2-vt__card:hover .hp2-vt__poster { transform: none; }
  .hp2-vt__card:hover .hp2-vt__vid { transform: scale(var(--vt-zoom, 1)); }
  .hp2-vt__card:hover .hp2-vt__play { transform: scale(1.15); }
}

/* Forced-colours / high-contrast: make sure the overlay chrome survives. */
@media (forced-colors: active) {
  .hp2-vt__play,
  .hp2-vt__arrow { border: 1px solid ButtonText; }
  .hp2-vt__controls { background: Canvas; }
}
