/* ==========================================================================
   Patient testimonials — department picker, carousel/grid, lightbox
   plus the proof band (third-party scores + story counts).

   The source material is 59 Instagram reels, all 9:16 vertical. "Wide" is not
   available: a vertical video stretched wide is either letterboxed or cropped
   through the speaker's face. What makes the burned-in captions readable is
   HEIGHT, so the player takes the viewport vertically and the frame width is
   derived from that. On a 1080p screen this is roughly 3× the 540 px Instagram
   embed.

   Thumbnails are mirrored locally, so nothing contacts Meta until a visitor
   actually opens a video.
   ========================================================================== */

/* ---- Department picker + carousel head ----------------------------------- */

.tcar__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s4); flex-wrap: wrap; margin-bottom: var(--s5);
}
.tcar__pick { flex: 1 1 240px; max-width: 380px; }
.tcar__pick select {
  width: 100%; min-height: 46px; cursor: pointer;
  padding: 10px var(--s4); font-size: .93rem; font-weight: 500;
  border: 1px solid var(--grey-200); border-radius: var(--r);
  background: var(--white); color: var(--navy);
}
.tcar__pick select:hover { border-color: var(--blue); }
.tcar__nav { display: flex; gap: var(--s2); flex: 0 0 auto; }

/* ---- Carousel ------------------------------------------------------------
   A scroll container, not a transform carousel: swipe works natively on a
   phone, the arrows just call scrollBy, and nothing breaks when the reel count
   changes. Scroll snap keeps cards from stopping half-visible.
   -------------------------------------------------------------------------- */

.tcar__track {
  display: flex; gap: var(--s4);
  overflow-x: auto; scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  padding-bottom: var(--s3);      /* room for the card lift on hover */
  scrollbar-width: thin;
}
.tcar__track > .testi__item {
  flex: 0 0 clamp(150px, 20vw, 208px);
  scroll-snap-align: start;
}

/* ---- Grid (medipol/media.html) ------------------------------------------- */

/* Two per row on a phone, then as many as fit. `auto-fill` with a 168 px
   minimum gave 2 on most phones and 3 on a Pro Max, where the third was half
   off-screen — an explicit 2 is steadier and the cards are bigger. */
.testi {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s3);
}
@media (min-width: 620px) {
  .testi { grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: var(--s4); }
}

/* ---- Card ---------------------------------------------------------------- */

.testi__item {
  position: relative; display: block; padding: 0; border: 0;
  aspect-ratio: 9 / 16;
  border-radius: var(--r-lg); overflow: hidden; cursor: pointer;
  background: var(--grey-100);
  box-shadow: var(--e2, var(--shadow));
  transition: transform .3s var(--ease-out, ease), box-shadow .3s;
}
.testi__item:hover { transform: translateY(-4px); box-shadow: var(--e3, var(--shadow-lg)); }
.testi__item:focus-visible { outline: 3px solid var(--blue); outline-offset: 3px; }

.testi__img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .5s var(--ease-out, ease);
}
.testi__item:hover .testi__img { transform: scale(1.06); }

/* Legibility scrim, so the play button reads on a bright frame. */
.testi__item::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(7,29,61,.05) 40%, rgba(7,29,61,.55));
}

/* Which department this patient was treated in — the single most useful thing
   to know before choosing which story to watch. */
.testi__dept {
  position: absolute; inset-block-start: var(--s3); inset-inline-start: var(--s3);
  inset-inline-end: var(--s3); z-index: 1;
  padding: 4px 9px; border-radius: var(--r-full);
  background: rgba(7,29,61,.72); color: var(--white);
  font-size: .7rem; font-weight: 600; line-height: 1.3;
  backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.testi__play {
  position: absolute; inset-block-end: var(--s3); inset-inline-start: var(--s3);
  z-index: 1;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; border-radius: var(--r-full);
  background: rgba(255,255,255,.92); color: var(--navy);
  font-size: .75rem; font-weight: 600;
}

/* ---- Lightbox ------------------------------------------------------------
   Instagram's embed draws a header above the video and a "View more on
   Instagram" bar under it. The frame is taller than its window by
   (crop-top + crop-bottom) and shifted up by crop-top, which takes the header
   off and leaves the bar at the bottom where it belongs.

   The shape comes from --tbox-ar, which js/testimonials.js measures off the
   mirrored thumbnail. It is never guessed: a reel with no thumbnail does not
   open at all (see lookup() there). Both guesses we tried put that bar across
   somebody's face.

   If Instagram changes their layout, these three numbers are the whole fix.
   -------------------------------------------------------------------------- */
:root { --tbox-ar: .5625; --tbox-crop-top: 0px; --tbox-crop-bottom: 96px; }

.tbox[hidden] { display: none; }
.tbox {
  position: fixed; inset: 0; z-index: 950;
  display: flex; align-items: center; justify-content: center;
  padding: var(--s4);
  background: rgba(7,29,61,.92);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  animation: tboxIn .2s ease;
}
@keyframes tboxIn { from { opacity: 0 } to { opacity: 1 } }

.tbox__stage { position: relative; display: flex; flex-direction: column; align-items: center; }

.tbox__frame {
  position: relative;
  /* Height-led: take the viewport, then derive width from the media's real
     aspect. min() keeps it inside narrow windows where the width would
     otherwise overflow. */
  height: min(88vh, calc((100vw - 150px) / var(--tbox-ar)));
  aspect-ratio: var(--tbox-ar);
  border-radius: var(--r-lg); overflow: hidden;
  background: #000;
  box-shadow: 0 24px 80px rgba(0,0,0,.55);
}
.tbox__frame iframe {
  position: absolute; inset-inline: 0;
  inset-block-start: calc(var(--tbox-crop-top) * -1);
  width: 100%;
  height: calc(100% + var(--tbox-crop-top) + var(--tbox-crop-bottom));
  border: 0; display: block;
}

.tbox__dept {
  margin: var(--s3) 0 0; color: rgba(255,255,255,.9);
  font-size: .85rem; font-weight: 600; text-align: center;
}

.tbox__btn {
  position: absolute; z-index: 2;
  display: inline-flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; padding: 0;
  border: 0; border-radius: var(--r-full); cursor: pointer;
  background: rgba(255,255,255,.94); color: var(--navy);
  font-size: 1.2rem; line-height: 1;
  box-shadow: 0 4px 14px rgba(0,0,0,.3);
  transition: transform .18s, background-color .18s;
}
.tbox__btn:hover { transform: scale(1.08); background: #fff; }
.tbox__btn:focus-visible { outline: 3px solid var(--white); outline-offset: 2px; }

.tbox__close { inset-block-start: var(--s4); inset-inline-end: var(--s4); }
/* Logical inset + a flipped glyph would double-mirror in RTL, so the arrows are
   positioned logically and the glyph is chosen in JS. */
.tbox__prev { inset-inline-start: var(--s4); inset-block-start: 50%; transform: translateY(-50%); }
.tbox__next { inset-inline-end: var(--s4); inset-block-start: 50%; transform: translateY(-50%); }
.tbox__prev:hover, .tbox__next:hover { transform: translateY(-50%) scale(1.08); }

.tbox__count {
  position: absolute; inset-block-end: var(--s3); inset-inline: 0;
  text-align: center; color: rgba(255,255,255,.7); font-size: .8rem;
}

/* Below ~640 px the arrows would sit on top of the video: move them under it. */
@media (max-width: 640px) {
  .tbox { padding: var(--s2); }
  .tbox__frame { height: min(74vh, calc((100vw - 16px) * 16 / 9)); }
  .tbox__prev { inset-block-start: auto; inset-block-end: var(--s4); inset-inline-start: 20%; transform: none; }
  .tbox__next { inset-block-start: auto; inset-block-end: var(--s4); inset-inline-end: 20%; transform: none; }
  .tbox__prev:hover, .tbox__next:hover { transform: scale(1.08); }
  .tbox__count { inset-block-end: calc(var(--s4) + 56px); }
}

/* ==========================================================================
   Proof band — one straight scrolling line.

   Third-party scores and our own story counts on the same rail, the way
   mimitamie runs its ingredients band. Full-bleed navy, teal separators, no
   cards and no links: it is a statement, not a menu.
   ========================================================================== */

.pband {
  overflow: hidden;
  background: var(--navy);
  color: var(--white);
  padding-block: var(--s4);
  /* Fade both ends so items enter and leave instead of being chopped. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
.pband__track {
  display: flex; width: max-content; align-items: center;
  animation: pbandRoll 46s linear infinite;
}
.pband:hover .pband__track { animation-play-state: paused; }

@keyframes pbandRoll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

.pband__item {
  display: inline-flex; align-items: center; gap: 9px;
  padding-inline: var(--s6);
  white-space: nowrap; font-size: .95rem;
}
/* The separator between items — a teal diamond, like mimitamie's ✦ */
.pband__item::after {
  content: '✦'; color: var(--teal);
  margin-inline-start: var(--s6); font-size: .8rem;
}

.pband__mark { display: block; width: 18px; height: 18px; flex: 0 0 auto; }
.pband__mark svg { width: 100%; height: 100%; display: block; }

.pband__src { color: #C6D3E4; font-weight: 500; }
.pband__score, .pband__n {
  font-weight: 700; font-size: 1.15rem; color: var(--white);
  font-variant-numeric: tabular-nums;
}
.pband__score small { font-size: .78rem; font-weight: 500; color: #8FA6C4; }
.pband__n { color: var(--teal); }

.pband__stars { position: relative; display: inline-block; letter-spacing: 1px; font-size: .82rem; }
.pband__stars-bg { color: rgba(255,255,255,.22); }
.pband__stars-fg {
  position: absolute; inset-block-start: 0; inset-inline-start: 0;
  overflow: hidden; white-space: nowrap; color: #E8A317;
}

.pband__count { color: #8FA6C4; font-size: .82rem; }
/* A high score from a handful of reviews is weak evidence — say so quietly
   rather than letting it read like the 3,498-review one. */
.pband__count--thin { font-style: italic; opacity: .8; }

.pband__note {
  margin: var(--s3) 0 0; text-align: center;
  font-size: .78rem; color: var(--grey-400);
}

@media (prefers-reduced-motion: reduce) {
  /* Stop the roll and lay the items out statically instead. */
  .pband__track { animation: none; flex-wrap: wrap; width: auto; justify-content: center; }
  .pband { -webkit-mask-image: none; mask-image: none; }
  .pband__item { padding-block: var(--s2); }
  .tbox { animation: none; }
  .testi__item, .testi__img, .tbox__btn { transition: none; }
  .testi__item:hover { transform: none; }
  .testi__item:hover .testi__img { transform: none; }
  .tcar__track { scroll-behavior: auto; }
}
