/* ==========================================================================
   Testimonial page — responsive layers
   Breakpoints mirror the two Figma frames: the 1920 desktop comp
   (9569:9161) down to 1200, then the 402 mobile comp (9733:5914) below
   992. Load AFTER testimonial.css.
   ========================================================================== */

@media (max-width: 1699px) {
  .tst-page { --tst-gutter: 100px; }
}

/* --- 1400–1549: the feedback panel's squeeze zone -------------------------
   Everything in the right-hand form is a fixed width, so as the viewport drops
   the left column is what shrinks. Below ~1550 it can no longer hold the comp's
   96px title on three lines ("We'd Love / to Hear Your / Experience") or the
   563px bubble cluster, and the panel's `overflow: hidden` clips the second
   bubble rather than showing the damage. This tier eases the title, the cluster
   and the form together so the desktop composition survives intact. */
@media (max-width: 1549px) {
  .tst-feedback__panel { padding: 72px; gap: 56px; }
  .tst-feedback__left { gap: 56px; }
  .tst-feedback__title { font-size: 80px; line-height: 90px; }
  .tst-bubbles { --k: .88; }
  .tst-form { flex-basis: 540px; }
}

/* --- 1400–1699: scale the type down, keep the desktop structure ---------- */
@media (max-width: 1399px) {
  .tst-hero { padding: 120px 0 120px; }
  .tst-hero__copy { width: 480px; gap: 32px; }
  .tst-hero__title { font-size: 40px; line-height: 51px; }
  .tst-chat { width: 560px; }
  .tst-chat__viewport { height: 520px; }
  .tst-chat__row { max-width: 82%; }
  .tst-btn { font-size: 20px; padding: 17px 22px; }
  .tst-hero__review-link { font-size: 20px; }

  .tst-h2 { font-size: 32px; }
  .tst-sec-head__sub { font-size: 20px; }

  .tst-slider { border-radius: 60px; }
  .tst-slider__media { flex-basis: 400px; height: 540px; padding: 32px; }
  .tst-slider__body { padding: 48px 40px 32px; }
  .tst-transcript { height: 340px; }
  .tst-transcript .tst-cue { font-size: 20px; line-height: 25px; margin-bottom: 25px; }
  .tst-transcript .tst-cue.is-active { font-size: 27px; line-height: 33px; }

  /* 56px padding / 44px gap rather than the comp's 80/71: at 1200 (the bottom
     of this tier, just before the panel stacks) that is what keeps the left
     column wider than the cluster instead of clipping it by a few px. */
  .tst-feedback__panel { padding: 56px; border-radius: 60px; gap: 44px; }
  .tst-feedback__left { gap: 44px; }
  .tst-feedback__title { font-size: 64px; line-height: 74px; }
  .tst-bubbles { --k: .8; }
  .tst-form { flex-basis: 480px; }

  .tst-cta { padding: 120px var(--tst-gutter); border-radius: 60px 60px 0 0; }
  .tst-cta__title { font-size: 30px; line-height: 40px; }
}

/* --- tablet: hero stacks, grid drops to two columns ---------------------- */
@media (max-width: 1199px) {
  .tst-container { width: min(var(--tst-container), 100% - 48px); }
  .tst-page { --tst-gutter: 48px; }

  .tst-hero { padding: 80px 0 96px; }
  .tst-hero__inner { flex-direction: column; align-items: stretch; gap: 56px; }
  .tst-hero__copy { width: 100%; }
  .tst-chat { width: 100%; max-width: 640px; }

  .tst-slider { flex-direction: column; }
  .tst-slider__media { flex-basis: auto; width: 100%; height: 460px; }
  .tst-slider__body { padding: 40px; }
  .tst-transcript { height: 300px; }

  .tst-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 32px; }

  .tst-feedback__panel { flex-direction: column; align-items: stretch; }
  .tst-feedback__left { align-items: center; text-align: center; }
  .tst-bubbles { align-self: center; }
  .tst-form { flex-basis: auto; width: 100%; max-width: 583px; align-self: center; }

  .tst-cta { flex-direction: column; align-items: flex-start; gap: 40px; padding: 90px var(--tst-gutter); }
}

/* --- mobile: mirrors the 402px Figma frame ------------------------------- */
@media (max-width: 991px) {
  .tst-page { --tst-gutter: 20px; }
  .tst-container { width: min(100% - 22px, 640px); }

  /* 1. hero */
  .tst-hero { padding: 40px 0 0; }
  .tst-hero__grid { top: -60px; width: 876px; height: 876px; }
  .tst-hero__inner { gap: 80px; }
  .tst-hero__copy { gap: 20px; padding: 0 29px; }
  .tst-hero__eyebrow { gap: 6px; font-size: 10px; }
  .tst-hero__eyebrow img { width: 8px; height: 8px; }
  .tst-hero__title { font-size: 24px; line-height: 31px; letter-spacing: -0.12px; }
  .tst-hero__actions { gap: 8px; }
  .tst-btn { font-size: 14px; padding: 14px 18px; letter-spacing: -0.07px; border-radius: 30px; }
  .tst-hero__review-link { font-size: 16px; gap: 8px; }
  .tst-hero__review-link img { width: 12px; height: 12.5px; }

  .tst-chat { max-width: none; margin: 0 0px; border-radius: 24px; }
  .tst-chat__head { gap: 12px; padding: 16.4px; }
  .tst-chat__id { gap: 12.75px; }
  .tst-chat__avatar { width: 40px; height: 40px; border-radius: 8px; font-size: 12px; }
  .tst-chat__name { font-size: 14px; }
  .tst-chat__role { margin-top: 4px; font-size: 11px; }
  .tst-chat__nav { gap: 7.3px; }
  .tst-chat__nav-btn { width: 25.5px; height: 25.5px; border-radius: 8px; }
  .tst-chat__nav-btn svg { width: 9px; height: 9px; }
  .tst-chat__viewport { height: 367px; }
  .tst-chat__body { padding: 14px; }
  .tst-chat__row { max-width: 78%; margin-top: 7px; }
  .tst-chat__row.is-start { margin-top: 12px; }
  .tst-chat__sender { margin-bottom: 5px; font-size: 9px; line-height: 14px; }
  .tst-chat__bubble { padding: 6px 9px; font-size: 11px; line-height: 17px; border-radius: 9px 9px 9px 0; }
  .tst-chat__bubble--out { border-radius: 9px 9px 0 9px; }
  .tst-chat__reaction { margin-top: -3px; padding: 1px 6px; font-size: 11px; }
  .tst-chat__typing { margin-top: 12px; }
  .tst-chat__typing span { gap: 3px; padding: 9px 11px; border-radius: 9px 9px 9px 0; }
  .tst-chat__typing--out span { border-radius: 9px 9px 0 9px; }
  .tst-chat__typing i { width: 5px; height: 5px; }

  /* section rhythm */
  .tst-compliments { padding-top: 80px; padding-bottom: 0; }
  .tst-wall { padding-top: 80px; padding-bottom: 0; }
  .tst-feedback { padding-top: 80px; padding-bottom: 80px; }

  .tst-br-sm { display: inline; }
  .tst-eyebrow { font-size: 9px; }
  .tst-h2 { font-size: 18px; line-height: 23px; letter-spacing: -0.09px; }
  .tst-sec-head { gap: 12px; }
  .tst-sec-head--wall { gap: 12px; }
  .tst-sec-head__stack { gap: 12px; }
  .tst-sec-head__sub { font-size: 12px; }

  /* 2. compliments */
  .tst-slider { flex-direction: column; margin-top: 36px; border-radius: 36px; }
  .tst-slider__media { width: 100%; height: 468.75px; padding: 20px; }
  .tst-glass { gap: 8px; padding: 16px 20px; border-radius: 28px; -webkit-backdrop-filter: blur(3.125px); backdrop-filter: blur(3.125px); }
  .tst-glass__name { font-size: 14px; letter-spacing: -0.07px; }
  .tst-glass__role { margin-top: 8px; font-size: 12px; }
  .tst-glass__play { width: 56px; height: 56px; }
  .tst-slider__body { gap: 28px; padding: 20px; }
  .tst-transcript { height: 144px; }
  .tst-transcript .tst-cue { font-size: 12px; line-height: 15px; margin-bottom: 15px; }
  .tst-transcript .tst-cue.is-active { font-size: 16px; line-height: 20px; }
  .tst-dots { justify-content: center; gap: 8px; }
  .tst-dots button { width: 24px; height: 4px; }

  /* 3. wall — stacked card deck (mobile frames 9738:6079 / 6097 / 9740:6203).
     This static deck is what shows when GSAP is unavailable; when it loads,
     testimonial-wall.js adds .is-stack and drives the same cards on scroll. */
  .tst-grid {
    display: block;
    position: relative;
    margin-top: 36px;
    height: 678px;
  }
  .tst-grid > * {
    position: absolute;
    left: 0;
    right: 0;
    height: 400px;
  }
  .tst-grid:not(.is-stack) > :nth-child(1) { top: 0; z-index: 1; }
  .tst-grid:not(.is-stack) > :nth-child(2) { top: 139px; z-index: 2; }
  .tst-grid:not(.is-stack) > :nth-child(3) { top: 278px; z-index: 3; }

  /* Scroll-driven stack: every card sits in the same slot and the script
     deals them. Height comes from JS so it matches the measured card. */
  /* Clipping is what makes the deal read as one card covering another: the
     incoming card is parked below the box until its turn, and the cards that
     have receded are trimmed at the top edge. */
  .tst-grid.is-stack { margin-top: 24px; overflow: hidden; }
  .tst-grid.is-stack > * { top: 0; }
  /* Promotion is scoped to the handful of cards actually on stage, not to the
     whole deck. Promoting every card held one composited layer per card for as
     long as the page was open — 45+ cards at ~325x400 is a quarter of a gigabyte
     of GPU texture, far past what a phone gives Chrome, so it starts dropping
     raster tiles. A dropped tile paints as a white rectangle, and it lands
     wherever the tile happens to be — which is why the feedback form far below
     the wall was losing its heading and stars to white boxes. `is-live` follows
     the card being dealt and is set by testimonial-wall.js. */
  .tst-grid.is-stack > .is-live {
    will-change: transform, opacity;
    backface-visibility: hidden;
  }
  /* The pinned stage must not clip the cards as they slide up into it. */
  .tst-wall__stage { position: relative; }

  .tst-card,
  .tst-vcard { border-radius: 28px; background: var(--tst-white); }
  .tst-card:hover,
  .tst-vcard:hover { transform: none; box-shadow: none; border-color: var(--tst-light-grey); }
  .tst-card { height: 400px; padding: 28px; overflow: hidden; }
  .tst-card__top { gap: 24px; }
  .tst-card__source { font-size: 14px; }
  .tst-stars--lg { width: 94px; height: 14px; }
  .tst-card__quote {
    font-size: 14px;
    line-height: 23px;
    display: -webkit-box;
    -webkit-line-clamp: 7;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .tst-card__bottom { gap: 24px; }
  .tst-person { gap: 18px; }
  .tst-person__pic { width: 41px; height: 41px; }
  .tst-person__name { font-size: 14px; }
  .tst-person__role { margin-top: 6px; font-size: 12px; }

  .tst-vcard { height: 400px; }
  .tst-vcard__media { padding: 19px; }
  .tst-vcard__pill { gap: 12px; padding: 14px 18px; border-radius: 16px; }
  .tst-vcard__name { font-size: 14px; }
  .tst-stars--sm { width: 76px; height: 12.7px; }
  .tst-vcard__role { margin-top: 6px; font-size: 12px; }
  .tst-vcard__play { width: 28.5px; height: 28.5px; }
  .tst-vcard__foot { gap: 8px; padding: 20px; }
  .tst-vcard__foot img { width: 10px; height: 8px; margin-top: 4px; }
  .tst-vcard__foot p { font-size: 14px; line-height: 21px; }

  .tst-wall__more { margin-top: 24px; }
  .tst-wall__more .tst-btn { font-size: 14px; padding: 14px 18px; }
  .tst-person__pic--initials { font-size: 15px; }

  /* 4. feedback */
  .tst-feedback__panel { gap: 28px; padding: 28px 20px; border-radius: 36px; }
  .tst-feedback__left { gap: 24px; }
  .tst-feedback__title { font-size: 24px; line-height: 30px; letter-spacing: -0.12px; text-align: center; }
  .tst-feedback__left { flex-direction: column-reverse; }

  /* Fixed 340px box that stays centred and is scaled down (not clamped) on
     narrow screens — the bubbles inside are absolutely positioned, so
     max-width would push the right-hand one out of the panel. */
  .tst-bubbles { width: 340px; height: 82px; transform-origin: 50% 50%; }
  .tst-bubble { transform-origin: 0 0; }
  .tst-bubble--1 { left: -2px;   top: 4px;  transform: rotate(-10.93deg) scale(.458); }
  .tst-bubble--3 { left: 108px;  top: -4px; transform: rotate(4.71deg) scale(.458); }
  .tst-bubble--2 { left: 214px;  top: -2px; transform: rotate(-2.5deg) scale(.458); }

  .tst-form { width: 100%; max-width: none; gap: 28px; padding: 24.7px; border-radius: 24px; }
  .tst-rate { gap: 16px; }
  .tst-rate__title { font-size: 14px; }
  .tst-rate__stars { gap: 10px; }
  .tst-rate__btn { position: relative; width: 37px; height: 37px; border-radius: 7px; }
  .tst-rate__btn svg { width: 18px; height: 18px; }
  /* The comp draws these at 37px, which is under the 44px minimum for a touch
     target — and rating is required, so a missed tap blocks the whole form.
     This grows the hit area to 44px without touching the drawn size: the
     buttons sit on a 47px pitch (37 + 10 gap), so the targets still do not
     overlap. */
  .tst-rate__btn::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }
  .tst-rate__scale { font-size: 10px; }
  /* Slightly under the 13px input text so a message reads as an annotation
     rather than competing with the value the user typed. */
  .tst-field__msg { font-size: 12px; }
  .tst-fields { gap: 20px; }
  .tst-field { gap: 8px; }
  .tst-field label { font-size: 12px; }
  .tst-field input,
  .tst-field textarea { padding: 15px 14px; font-size: 13px; }
  .tst-field textarea { min-height: 50px; }
  /* Mirrors the mobile step on `.ate-modal-submit` in style.css. */
  .tst-submit { padding: 12px; font-size: 15px; }

  /* 5. cta */
  .tst-cta {
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 40px;
    padding: 50px 36px;
    border-radius: 36px 36px 0 0;
  }
  .tst-cta__title { font-size: 20px; line-height: 26px; letter-spacing: -0.1px; }
  .tst-cta__actions { gap: 8px; }
}

/* --- 576–991: tablet band ------------------------------------------------
   The mobile rules above are drawn from the 402px frame, but the container
   caps at 640px here — so the card is ~60% wider while the message type is
   still phone-sized. Step the chat back up and stop bubbles running the full
   width of the card. Must stay after the max-width:991 block. */
@media (min-width: 576px) and (max-width: 991px) {
  .tst-chat { margin: 0; }
  .tst-chat__head { gap: 16px; padding: 20px; }
  .tst-chat__id { gap: 16px; }
  .tst-chat__avatar { width: 48px; height: 48px; border-radius: 10px; font-size: 14px; }
  .tst-chat__name { font-size: 15px; }
  .tst-chat__role { margin-top: 6px; font-size: 12px; }
  .tst-chat__nav { gap: 10px; }
  .tst-chat__nav-btn { width: 36px; height: 36px; border-radius: 11px; }
  .tst-chat__nav-btn svg { width: 12px; height: 12px; }

  .tst-chat__viewport { height: 460px; }
  .tst-chat__body { padding: 24px; }
  .tst-chat__row { max-width: 74%; margin-top: 9px; }
  .tst-chat__row.is-start { margin-top: 16px; }
  .tst-chat__sender { margin-bottom: 6px; font-size: 11px; line-height: 18px; }
  .tst-chat__bubble { padding: 8px 12px; font-size: 14px; line-height: 21px; border-radius: 11px 11px 11px 0; }
  .tst-chat__bubble--out { border-radius: 11px 11px 0 11px; }
  .tst-chat__reaction { margin-top: -3px; padding: 2px 7px; font-size: 13px; }
  .tst-chat__typing { margin-top: 16px; }
  .tst-chat__typing span { gap: 4px; padding: 11px 13px; border-radius: 11px 11px 11px 0; }
  .tst-chat__typing--out span { border-radius: 11px 11px 0 11px; }
  .tst-chat__typing i { width: 6px; height: 6px; }

  /* The compliments frame goes wide here while the clip stays portrait, so the
     media box needs height or cover crops the speaker off at both sides — and
     the transcript needs readable type in a 640px panel. */
  .tst-slider__media { height: 560px; }
  .tst-glass { padding: 20px 24px; border-radius: 32px; }
  .tst-glass__name { font-size: 16px; }
  .tst-glass__role { margin-top: 8px; font-size: 13px; }
  .tst-glass__play { width: 64px; height: 64px; }
  .tst-slider__body { gap: 32px; padding: 32px; }
  .tst-transcript { height: 240px; }
  .tst-transcript .tst-cue { font-size: 16px; line-height: 22px; margin-bottom: 22px; }
  .tst-transcript .tst-cue.is-active { font-size: 21px; line-height: 27px; }
  .tst-dots button { width: 30px; height: 5px; }

  /* The overlapping card deck is a 402px-frame pattern — at 640px the offsets
     stop reading and the video card shows only a sliver of its poster. Tablets
     get a real grid instead, on the same fixed card box as desktop so the two
     card types stay level with each other in every row. */
  .tst-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 24px;
    position: static;
    height: auto;
  }
  .tst-grid > * { position: static; }
  .tst-card { height: 500px; padding: 32px; overflow: hidden; }
  .tst-card__quote { font-size: 15px; line-height: 25px; -webkit-line-clamp: 9; }
  .tst-card__source { font-size: 16px; }
  .tst-stars--lg { width: 104px; height: 16px; }
  .tst-person__pic { width: 52px; height: 52px; }
  .tst-person__name { font-size: 15px; }
  .tst-person__role { font-size: 13px; }

  .tst-vcard { height: 500px; }
  .tst-vcard__media { flex: 1 1 auto; min-height: 0; }
  .tst-vcard__pill { padding: 16px 20px; border-radius: 18px; }
  .tst-vcard__name { font-size: 15px; }
  .tst-stars--sm { width: 88px; height: 14px; }
  .tst-vcard__role { font-size: 13px; }
  .tst-vcard__play { width: 32px; height: 32px; }
  .tst-vcard__foot p { font-size: 15px; line-height: 23px; }
  .tst-person__pic--initials { font-size: 18px; }
}

/* Tablet portrait upward has room for two columns; one full-width card per row
   left the wall reading as a very long phone list. */
@media (min-width: 768px) and (max-width: 991px) {
  .tst-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px; }
  .tst-card { padding: 28px; }
  .tst-card__quote { font-size: 14px; line-height: 23px; -webkit-line-clamp: 10; }
}

/* The overlapping deck is a phone pattern only. Above 576px the wall is a real
   grid, so the "first three cards" cap gives way to the Read More paging that
   testimonial.js drives, and the no-JS "View All" link steps aside for it. */
@media (max-width: 575px) {
  /* Only the static fallback deck caps itself at three cards — the scroll
     stack deals every card it has been given. */
  .tst-grid:not(.is-stack) > :nth-child(n + 4) { display: none; }
  .tst-grid:not(.is-stack) ~ .tst-wall__more [data-tst-more] { display: none; }

  /* The phone stack keeps its own footer: "Read More" fades in on the last
     card of the batch, so the no-JS "View All" link steps aside. The button
     and the end notice share one grid cell — GSAP hides the inactive one with
     visibility, which still holds layout space, and side by side in a flex row
     that pushed whichever was showing off centre. */
  .tst-grid.is-stack ~ .tst-wall__more {
    display: grid;
    justify-items: center;
    align-items: center;
    margin-top: 20px;
    min-height: 52px;
  }
  .tst-grid.is-stack ~ .tst-wall__more > * { grid-area: 1 / 1; }
  .tst-grid.is-stack ~ .tst-wall__more [data-tst-more-fallback] { display: none; }

  /* Fill the viewport while pinned, so the next section does not sit in the
     frame watching the cards deal. */
  .tst-wall__stage.is-stack {
    min-height: calc(100vh - 140px);
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
}

@media (max-width: 420px) {
  .tst-chat__row { max-width: 84%; }
  .tst-bubbles { transform: scale(.9); }
}

/* The bubble cluster is 340px wide; the blue panel only offers
   (viewport - 22px container gutter - 40px panel padding). Step the scale
   down so all three stay inside it on small handsets. */
@media (max-width: 380px) { .tst-bubbles { transform: scale(.8); } }
@media (max-width: 345px) { .tst-bubbles { transform: scale(.7); } }

/* --- motion preferences -------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .tst-page *,
  .tst-page *::before,
  .tst-page *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .tst-chat__body { scroll-behavior: auto; }
}
