/* ==========================================================================
   TESTIMONIALS  —  21st.dev "animated-testimonials", resolved to CSS

   Every number below is the client's Tailwind class turned into its real
   value, so the proportions are the reference's and not an approximation:

     py-24 96px · gap-16 64px · lg:gap-24 96px · px-4/md:px-6 16/24px
     space-y-6 24px · pt-4 16px · px-3 py-1 12/4px · text-sm 14px
     text-3xl 30px · sm:text-4xl 36px · md:text-5xl 48px
     tracking-tighter -0.05em · md:text-xl/relaxed 20px/1.625
     h-2.5 10px · w-10 40px · duration-300 300ms
     min-h 300px / md 400px · mr-10 40px · rounded-xl 12px · p-8 32px
     mb-6 24px · gap-2 8px · h-5/w-5 20px · -top-2/-left-2 -8px
     h-8/w-8 32px · text-lg 18px · leading-relaxed 1.625 · font-medium 500
     my-4 16px · gap-4 16px · h-12/w-12 48px · -bottom-6 -24px · h-24 96px
     shadow-lg 0 10px 15px -3px / 0 4px 6px -4px

   What changed is the palette and the type: --primary becomes her ink, the
   card ground becomes White on a Shell section, and the display face is the
   brand serif. The gold on the stars stays gold, because a star in the brand
   beige stops reading as a rating.
   ========================================================================== */

.yp-atst {
  /* bg-muted/30 over her Shell rather than a grey. */
  background: rgb(var(--yp-shell-rgb));
  padding: 96px 0;
  overflow: hidden;
}

/* Same gutter and breakpoint as .yp-wrap, so this section's left edge stacks
   with the ones above and below it. */
.yp-atst-wrap { padding: 0 30px; }

@media (max-width: 540px) {
  .yp-atst-wrap { padding: 0 16px; }
}

/* ---- the two columns ------------------------------------------------------ */

.yp-atst-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 64px;
  width: 100%;
  max-width: 1460px;
  margin: 0 auto;
}

@media (min-width: 768px) {
  .yp-atst-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
  .yp-atst-grid { gap: 96px; }
}

/* ---- left column ---------------------------------------------------------- */

.yp-atst-lead { display: flex; flex-direction: column; justify-content: center; }

/* space-y-6. Tailwind compiles that to margin-top on the siblings, which is
   fine in a Tailwind project because its components carry no margin resets.
   Here every heading needs `margin: 0` to beat Divi, and that reset cancelled
   this rule outright: the badge sat flush against the title with a real gap of
   0px. `gap` belongs to the container, so no child can cancel it. */
.yp-atst-lead-stack {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 24px;
}

.yp-atst-badge {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: 7px;
  padding: 5px 13px 5px 9px;
  border-radius: 999px;
  /* bg-primary/10 with her ink as the primary. */
  background: rgb(var(--yp-ink-rgb) / 0.07);
  color: rgb(var(--yp-ink-rgb) / 0.9);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-decoration: none;
  transition: background-color 300ms cubic-bezier(0.4, 0, 0.2, 1);
}

.yp-atst-badge:hover { background: rgb(var(--yp-ink-rgb) / 0.12); }
/* align-items:center centres the mark on the text's LINE box, and that box
   carries descender depth the capitals never reach, so a mark that is
   mathematically centred still sits low next to the words. Measured against
   the cap band here it was 1.74px low, hence the 2px lift. Transform rather
   than margin so the flex line height does not change. */
.yp-atst-badge-mark {
  display: block;
  transform: translateY(-2px);
}

.yp-atst-badge-mark svg { width: 15px; height: 15px; display: block; }

/* typography.css sets a weight on every heading with !important and Divi adds
   padding-bottom to all of them, so both have to be taken back here. */
.yp-atst-title {
  margin: 0;
  padding: 0 !important;
  font-family: var(--yp-serif);
  font-size: 30px;
  line-height: 1.1;
  /* font-bold is 700; Newsreader is variable 200-800 so 800 is the display
     end of it. Asking for 900 would only get a synthesised bold. */
  font-weight: 800 !important;
  /* tracking-tighter. Divi ships an INLINE rule,
     h1,h2,h3,h4,h5,h6,p { letter-spacing: 0px !important }, which outranks
     any class selector no matter the order. Without !important here the
     heading rendered at normal tracking and the display line looked loose
     next to the reference. */
  letter-spacing: -0.05em !important;
  color: var(--yp-ink);
  text-wrap: balance;
}

@media (min-width: 640px) { .yp-atst-title { font-size: 36px; } }
@media (min-width: 768px) { .yp-atst-title { font-size: 48px; line-height: 1; } }

.yp-atst-deck {
  margin: 0;
  padding: 0 !important;
  max-width: 600px;
  color: rgb(var(--yp-ink-rgb) / 0.66);
  font-size: 16px;
  line-height: 1.6;
  text-wrap: pretty;
}

/* Divi's inline rule also forces 1px onto <p> via common.css before zeroing
   it; the deck wants neither, and 0 is what the reference uses. */
.yp-atst-deck,
.yp-atst-role { letter-spacing: 0 !important; }

@media (min-width: 768px) {
  .yp-atst-deck { font-size: 20px; line-height: 1.625; }
}

/* ---- dot navigation ------------------------------------------------------- */

.yp-atst-dots {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-top: 16px;
}

.yp-atst-dot {
  appearance: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  height: 10px;
  width: 10px;
  border-radius: 999px;
  background: rgb(var(--yp-ink-rgb) / 0.3);
  transition: width 300ms cubic-bezier(0.4, 0, 0.2, 1),
              background-color 300ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* Animating width does cost layout, and normally transform would be the
   answer. Not here: the dot is a 10px circle growing into a 40px pill, and
   scaleX on a 999px radius flattens the round ends into ovals. Five elements
   moving for 300ms on a click or a 6s timer is not a performance problem
   worth a visible distortion, and the growing pill is the reference's own
   behaviour rather than an embellishment. */
.yp-atst-dot.is-on { width: 40px; background: var(--yp-ink); }
.yp-atst-dot:focus-visible { outline: 2px solid var(--yp-ink); outline-offset: 3px; }

/* A 10px dot is not a touch target. The hit area grows on a pseudo-element:
   44px tall, and half the row's gap each side so neighbours tile rather than
   overlap. The gap is 12px, and 9px at 400 and under, so the inset steps with
   it. The drawn dot does not change. */
.yp-atst-dot { position: relative; }
.yp-atst-dot::after { content: ""; position: absolute; inset: -17px -6px; }
@media (max-width: 400px) {
  .yp-atst-dot::after { inset: -17px -4.5px; }
}

/* ---- right column: the stack --------------------------------------------- */

.yp-atst-stage {
  position: relative;
  height: 100%;
  min-height: 300px;
  margin-right: 40px;
}

@media (min-width: 768px) { .yp-atst-stage { min-height: 400px; } }

/* The reference holds every card on absolute inset-0 and animates opacity, x
   and scale. Stacking them is what lets one leave while the next arrives. */
.yp-atst-card {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: flex;
  flex-direction: column;
  padding: 32px;
  border: 1px solid rgb(var(--yp-ink-rgb) / 0.1);
  border-radius: 12px;
  background: var(--yp-white);
  box-shadow: 0 10px 15px -3px rgb(var(--yp-ink-rgb) / 0.1),
              0 4px 6px -4px rgb(var(--yp-ink-rgb) / 0.1);
  opacity: 0;
  transform: translateX(100px) scale(0.9);
  /* visibility as well as opacity: a card at opacity 0 keeps its "Read the
     full review" link in the tab order, so focus landed on something nobody
     could see, inside a card marked aria-hidden. It flips after the fade out
     and before the fade in. */
  visibility: hidden;
  transition: opacity 500ms cubic-bezier(0.4, 0, 0.2, 1),
              transform 500ms cubic-bezier(0.4, 0, 0.2, 1),
              visibility 0s linear 500ms;
  pointer-events: none;
}

.yp-atst-card.is-active {
  z-index: 10;
  opacity: 1;
  visibility: visible;
  transform: translateX(0) scale(1);
  transition-delay: 0s;
  pointer-events: auto;
}

/* ---- card internals ------------------------------------------------------ */

.yp-atst-stars {
  margin-bottom: 24px;
  font-size: 20px;
  line-height: 1;
  letter-spacing: 8px;   /* gap-2 between the five glyphs */
  color: var(--yp-star);   /* fill-yellow-500, declared in tokens.css */
}

.yp-atst-quote-wrap { position: relative; margin-bottom: 24px; flex: 1 1 auto; }

/* The reference rotates a quote glyph 180deg and sets it at 20% of primary.
   A closing curly quote already points the right way, so it needs no rotate. */
.yp-atst-quote-mark {
  position: absolute;
  top: -8px;
  left: -8px;
  font-family: var(--yp-serif);
  font-size: 64px;
  line-height: 1;
  color: rgb(var(--yp-ink-rgb) / 0.2);
  user-select: none;
}

.yp-atst-quote {
  position: relative;
  z-index: 1;
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 18px;
  font-weight: 500;
  line-height: 1.625;
  color: var(--yp-ink);
  text-wrap: pretty;
}

/* The reference <Separator> is w-full. Divi styles bare <hr> at 80% width,
   which is why the rule stopped 109px short of the card's inner edge and read
   as a mistake rather than a divider. */
.yp-atst-rule {
  width: 100%;
  margin: 16px 0;
  border: 0;
  height: 1px;
  background: rgb(var(--yp-ink-rgb) / 0.1);
}

.yp-atst-person { display: flex; align-items: center; gap: 16px; }

/* <AvatarFallback> in the reference renders name.charAt(0). These reviewers
   are real people off her Google profile, so the initial is the whole point:
   nobody here is given a face that was generated for them. */
.yp-atst-avatar {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 999px;
  border: 1px solid rgb(var(--yp-ink-rgb) / 0.12);
  background: linear-gradient(160deg,
      rgb(var(--yp-sand-rgb)) 0%, rgb(var(--yp-shell-rgb)) 100%);
  color: rgb(var(--yp-ink-rgb) / 0.55);
  font-family: var(--yp-serif);
  font-size: 19px;
  line-height: 1;
  user-select: none;
}

.yp-atst-id { min-width: 0; }

.yp-atst-name {
  margin: 0;
  padding: 0 !important;
  font-family: var(--yp-serif);
  font-size: 16px;
  font-weight: 600 !important;
  line-height: 1.3;
  letter-spacing: 0;
  text-transform: none;
  color: var(--yp-ink);
}

.yp-atst-role {
  margin: 2px 0 0;
  padding: 0 !important;
  font-size: 14px;
  line-height: 1.4;
  color: rgb(var(--yp-ink-rgb) / 0.62);
}

.yp-atst-more {
  display: inline-block;
  margin-top: 10px;
  font-size: 13px;
  color: rgb(var(--yp-ink-rgb) / 0.7);
  text-underline-offset: 3px;
}

.yp-atst-more:hover { color: var(--yp-ink); }

/* ---- decorative squares -------------------------------------------------- */

.yp-atst-deco {
  position: absolute;
  z-index: 0;
  width: 96px;
  height: 96px;
  border-radius: 12px;
  background: rgb(var(--yp-ink-rgb) / 0.05);
  pointer-events: none;
}

.yp-atst-deco-a { bottom: -24px; left: -24px; }
.yp-atst-deco-b { top: -24px; right: -24px; }

/* ---- narrow -------------------------------------------------------------- */

@media (max-width: 767px) {
  .yp-atst { padding: 64px 0; }
  .yp-atst-grid { gap: 40px; }
  /* mr-10 exists to leave room for the decorative square on the right. On a
     phone that margin only makes the card narrow, and the squares are hidden
     anyway, so it goes. */
  .yp-atst-stage { margin-right: 0; }
  .yp-atst-deco { display: none; }
  .yp-atst-card { padding: 24px; }
  .yp-atst-quote { font-size: 16.5px; }
  .yp-atst-quote-mark { font-size: 52px; top: -6px; left: -4px; }
}

@media (max-width: 400px) {
  .yp-atst-badge { font-size: 12.5px; }
  .yp-atst-dots { gap: 9px; }
}

/* ---- reduced motion ------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  .yp-atst-card,
  .yp-atst-dot,
  .yp-atst-badge { transition: none; }
  /* The stack still needs the inactive cards out of the way, so opacity does
     the work and the movement is dropped rather than the change itself. */
  .yp-atst-card { transform: none; }
  .yp-atst-card.is-active { transform: none; }
}
