/**
 * Long reviews on the home page carousel.
 *
 * Cards in a marquee stretch to the height of the tallest, so a single two or
 * three paragraph review made every card as tall as it and left the short ones
 * as mostly empty space. Clamping fixes that, but a clamp on its own is a
 * customer's words cut off with no way to finish them, so every clipped review
 * carries a button that opens the whole thing.
 *
 * The clamp is presentation only. The full text is in the HTML of every card,
 * which is what matters for crawlers that do not run JavaScript: they read the
 * review, the visitor reads eight lines and clicks if they want the rest.
 *
 * Loaded by the two home pages only, because they are the only pages with a
 * carousel on them.
 */

/* Eight lines is enough to judge a review by. Both home pages set their own
   line-height on .review p, 1.58 and 1.62, so this splits the difference: a
   clamp landing a few pixels into the ninth line is invisible under the fade.

   Two classes beats the `.review p` in each home page's inline CSS, which
   comes later in the document and would otherwise win the tie. */
.carousel .review p {
  --review-lines: 8;
  position: relative;
  max-height: calc(var(--review-lines) * 1.6em);
  overflow: hidden;
}

/* Only on the ones actually cut. On a short review this would fade out the
   last line of something that was never clipped, so reviews.js measures first
   and adds the class. Same reason the button is added there rather than built
   into every card. */
.carousel .review p.is-clipped::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2.6em;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0), var(--navy));
  pointer-events: none;
}

/* The track already pauses on hover, which is what makes the button hittable
   with a mouse. Tabbing to it needs the same, or focus lands on a control that
   is sliding out from under the pointer. */
.carousel:focus-within .carousel-track { animation-play-state: paused; }

.review-more {
  align-self: flex-start;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
  background: none;
  border: 0;
  /* A touch screen has no hover, so on a phone this is a moving target. The
     full 44px makes it one worth aiming at. */
  min-height: 44px;
  padding: 0;
  cursor: pointer;
  text-align: left;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.review-more:hover { color: var(--accent-hi, var(--accent)); }
.review-more:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* The marquee behind an open dialog is a distraction, and a card sliding out
   from under the button that opened it is worse. */
.reviews-open .carousel-track { animation-play-state: paused; }

.review-dialog {
  width: min(560px, calc(100vw - 32px));
  max-height: min(80vh, 720px);
  padding: 0;
  border: 1px solid var(--line-strong, var(--line));
  border-radius: var(--radius, 16px);
  background: var(--navy);
  color: var(--text);
}
.review-dialog::backdrop { background: rgba(0, 0, 0, .6); }

.review-dialog-body { padding: 26px 26px 22px; }
.review-dialog .stars { color: var(--accent); letter-spacing: 2px; font-size: 15px; }

/* Scrolls on its own when somebody has written a great deal, so the attribution
   and the close button stay where they are. */
.review-dialog-text {
  margin: 14px 0 18px;
  font-size: 15.5px;
  line-height: 1.65;
  max-height: 46vh;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.review-dialog .review-attr { margin-top: 0; }

.review-close {
  margin-top: 18px;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  min-height: 44px;
  padding: 0 20px;
  border: 1px solid var(--line-strong, var(--line));
  border-radius: 999px;
  background: none;
  color: var(--text);
  cursor: pointer;
}
.review-close:hover { border-color: var(--accent); color: var(--accent); }
.review-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Somebody who has asked for less movement is not helped by a clamp they have
   to click through, and the marquee is already still for them. */
@media (prefers-reduced-motion: reduce) {
  .carousel .review p { max-height: none; }
  .carousel .review p.is-clipped::after { content: none; }
  .review-more { display: none; }
}

/* The carousel itself, for the generated home pages (Verge Roofing and
   CoolRight). The two damp home pages carry these rules inline, so they are
   scoped to .reviews-wall, a class only the generated section has, and the
   damp pages are untouched. Same marquee, same cards, in each brand's colours. */
.reviews-wall .carousel{position:relative;overflow:hidden;margin-top:22px;
  mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent)}
.reviews-wall .carousel+.carousel{margin-top:20px}
.reviews-wall .review{flex:0 0 330px;background:var(--card);border:1px solid var(--line);border-radius:14px;
  padding:22px;display:flex;flex-direction:column;gap:11px;min-height:180px}
.reviews-wall .review .stars{color:var(--accent);letter-spacing:2px;font-size:14px}
.reviews-wall .review p{font-size:14.5px;line-height:1.58;color:var(--text)}
.reviews-wall .review--stars-only .stars{margin-top:auto;font-size:19px;letter-spacing:4px}
.reviews-wall .review-attr{font-size:13px;color:var(--muted-2);margin-top:auto;display:flex;justify-content:space-between;
  align-items:center;gap:10px;padding-top:12px;border-top:1px solid var(--line)}
.reviews-wall .src{font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--accent);
  border:1px solid var(--accent);border-radius:999px;padding:3px 9px;white-space:nowrap}
.reviews-wall .reviews-source{margin-top:16px;font-size:13px;color:var(--muted-2)}

/* ---------- The rows, on all four home pages ----------
   reviews.js fills each row with copies and sets --shift (one set's width) and
   --dur (that width at a fixed speed), then adds .is-looping. Until then, and
   always for anyone who asked for less motion, a row is a still strip that
   can be swiped, so nothing ever depends on the animation running. Cards
   stretch to the row, so every card in it is the same height. */
.carousel-track{display:flex;gap:20px;width:max-content;align-items:stretch}
.carousel-track.is-looping{will-change:transform;
  animation:reviews-loop var(--dur,60s) linear infinite}
.carousel-track.rev.is-looping{animation-direction:reverse}
@keyframes reviews-loop{from{transform:translate3d(0,0,0)}
  to{transform:translate3d(calc(-1 * var(--shift,0px)),0,0)}}
.carousel:hover .carousel-track,.carousel.is-held .carousel-track{animation-play-state:paused}
.carousel:not(:has(.is-looping)){overflow-x:auto;scroll-snap-type:x mandatory;
  overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch;scrollbar-width:none}
.carousel:not(:has(.is-looping)) .review{scroll-snap-align:start}
.carousel .review{flex:0 0 min(330px,82vw)}
@media (prefers-reduced-motion:reduce){
  .carousel-track.is-looping{animation:none}
  .carousel{-webkit-mask-image:none;mask-image:none;padding-inline:16px}
}
