/* ---- Reviews page — divider between stacked split-content-section reviews ----
   Sits on the shared .grid so it can be centered to the same 8-column span
   the review content itself uses (3/span3 heading + 6/span5 body = columns
   3-10) — full-width below 1024px, where the two columns stack anyway.
   Extra margin-block on top of .split-content-section's own padding-block
   adds more breathing room between rows without changing that shared
   component's spacing (which the News article page also relies on). */
.reviews-divider {
  grid-column: 1 / -1;
  border: none;
  border-top: 1px solid var(--color-border);
  margin-block: var(--space-12);
}

@media (min-width: 1024px) {
  .reviews-divider {
    grid-column: 3 / span 8;
    margin-block: var(--space-16);
  }
}

/* Extra clearance below the hero for the first review only — the intro
   copy + divider that used to provide this gap were removed, and
   .split-content-section's own top padding (shared with the News article
   page) is too tight to sit directly under the hero on its own. */
.reviews-first-review {
  padding-top: var(--space-24);
}

@media (min-width: 1024px) {
  .reviews-first-review {
    padding-top: var(--space-32);
  }
}

/* ---- Truncation + "Read more" (assets/js/reviews.js) ----
   Clamped to 3 lines by default via line-clamp on .review-text (the
   paragraphs' own wrapper, nested inside .split-content-section__body) —
   this works across multiple sibling <p> tags (not just a single block),
   unlike most other uses of line-clamp in this codebase (e.g.
   .journal-card__excerpt, always one paragraph). The clamp lives on this
   inner wrapper rather than .split-content-section__body itself so the
   "Read more" button — inserted as body's last child, after .review-text —
   sits outside the clamped/clipped box and is never truncated along with
   the text. JS measures whether .review-text is actually being truncated
   and only then inserts the button — a one-sentence review has nothing to
   hide, so it gets no button at all. */
.review-text {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}

/* Added by reviews.js the moment it's measured the clamped height and
   frozen it as an explicit inline max-height (see the JS) —
   -webkit-line-clamp itself can't be transitioned, so this swaps to a
   plain max-height + overflow: hidden box instead: same visual truncation
   at rest, but now something JS can animate for the expand/collapse. */
.review-text--js-ready {
  display: block;
  -webkit-line-clamp: unset;
  line-clamp: unset;
  transition: max-height var(--duration-slow) var(--ease-standard);
}

@media (prefers-reduced-motion: reduce) {
  .review-text--js-ready {
    transition: none;
  }
}

.review-read-more {
  display: block;
  margin-top: var(--space-4);
  color: var(--color-accent);
}

/* ---- Blur fade-in stagger (assets/js/scroll-reveal.js) ----
   Heading, rating and author each carry a bare data-reveal and sit as
   plain 1st/2nd/3rd children of .split-content-section__meta, so the
   generic nth-child(2)/(3) stagger in layout.css already cascades them
   in one after another with no extra rule needed here. The quote
   (.split-content-section__body) is its own data-reveal target one level
   up, as the 2nd child of .split-content-section__grid — the same
   generic rule would only give it one stagger step (tying it to the
   rating line), so it's bumped to a 4th step here to read as "after" the
   left column's three lines rather than alongside them. Equal selector
   specificity to the generic rule; wins on cascade order since this
   sheet loads after layout.css. */
.split-content-section__grid .split-content-section__body[data-reveal] {
  transition-delay: calc(var(--duration-fast) * 3);
}

/* ---- Star rating — reveals left to right, one star at a time, after the
   quote finishes ----
   Each star is its own data-reveal target (span, not the whole line as
   one block) so they can fan in individually. inline-block so the
   translateY/blur transform (layout.css) renders reliably — plain inline
   elements are more inconsistent across browsers for transforms. Delays
   start once the quote (.split-content-section__body, 3x duration-fast
   delay above) has finished its own 0.9s reveal transition — 0.9s is
   hardcoded here to match the transition duration set generically in
   layout.css, which isn't itself a token — then step by a third of
   duration-fast between stars. Same specificity as the generic nth-child
   rule in layout.css; wins on cascade order since this sheet loads after
   it. */
.split-content-section__star {
  display: inline-block;
}

/* Blur/opacity only, no rise — the generic hidden state (layout.css) also
   sets translateY(48px), which reads as an odd vertical "jump" on a
   single glyph this small. Overrides just the transform, leaving the
   opacity/blur fade intact so it's still the same reveal, just without
   the lift. */
.split-content-section__star[data-reveal=""] {
  transform: none;
}

.split-content-section__rating [data-reveal]:nth-child(1) {
  transition-delay: calc(var(--duration-fast) * 3 + 0.9s);
}

.split-content-section__rating [data-reveal]:nth-child(2) {
  transition-delay: calc(var(--duration-fast) * 3 + 0.9s + (var(--duration-fast) / 3));
}

.split-content-section__rating [data-reveal]:nth-child(3) {
  transition-delay: calc(var(--duration-fast) * 3 + 0.9s + (var(--duration-fast) * 2 / 3));
}

.split-content-section__rating [data-reveal]:nth-child(4) {
  transition-delay: calc(var(--duration-fast) * 3 + 0.9s + var(--duration-fast));
}

.split-content-section__rating [data-reveal]:nth-child(5) {
  transition-delay: calc(var(--duration-fast) * 3 + 0.9s + (var(--duration-fast) * 4 / 3));
}
