/* ==========================================================================
   Component · Reviews
   Quotations from the App Store. Nothing here is editorial: the words are the
   reviewer's, so the design gets out of their way.
   ========================================================================== */

.reviews {
  padding-block: var(--section-pad);
}

/* ---- The rail -------------------------------------------------------------
   A drifting rail you can also drive yourself.

   Two earlier attempts were wrong in instructive ways. The first drove
   `scrollLeft` and wrapped at `scrollWidth / 2`, which is half a gap short of
   one copy, so every loop jumped backwards by a few pixels. The second fixed
   the seam with a CSS transform marquee, which is perfectly smooth and
   completely un-driveable: `overflow: hidden` means no drag, no swipe, no
   trackpad, no keyboard.

   This keeps native scrolling, so touch inertia, trackpads, shift-wheel and
   arrow keys all work for free, and adds the drift on top of it. The wrap is
   exact, so it is invisible. See js/modules/reviews-carousel.js.
   -------------------------------------------------------------------------- */

.reviews {
  --review-gap: 0.75rem;
}

/* The edge feather.
 *
 * Kept deliberately slight. The rail's own box now ends on the site margin
 * (see below), so the clip line already agrees with every other section and
 * the feather has only one job: stop that line being a razor edge.
 *
 * Eased rather than linear. A linear alpha ramp spends most of its length
 * half-visible and reads as a grey band laid over the cards, which is what
 * made the first attempt look harsh.
 */
.review-rail {
  --review-fade: clamp(0.75rem, 1.2vw, 1.15rem);
  --review-edge-mask: linear-gradient(
    to right,
    rgba(0, 0, 0, 0) 0,
    rgba(0, 0, 0, 0.45) calc(var(--review-fade) * 0.45),
    rgba(0, 0, 0, 0.85) calc(var(--review-fade) * 0.75),
    rgba(0, 0, 0, 1) var(--review-fade),
    rgba(0, 0, 0, 1) calc(100% - var(--review-fade)),
    rgba(0, 0, 0, 0.85) calc(100% - var(--review-fade) * 0.75),
    rgba(0, 0, 0, 0.45) calc(100% - var(--review-fade) * 0.45),
    rgba(0, 0, 0, 0) 100%
  );
}

.review-rail {
  /* The box ends exactly on the site margin at every width, so the overflow
     clips where every other section stops. Padding cannot do this: it sits
     inside the scroll container, so content scrolls through it. */
  width: min(calc(100% - 2 * var(--gutter)), var(--container-wide));
  margin-top: clamp(2rem, 1.5rem + 1.5vw, 3rem);
  margin-inline: auto;
  padding-block: 0.5rem;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  /* Stops this scroller's layout overflow from reaching the page canvas.
     Without it Chrome grows the initial containing block to the rail's full
     width, and a position: fixed nav sizing against `100%` is then wider than
     the screen and centred on the wrong midpoint. `overflow: auto` alone does
     not prevent that; `contain: paint` does. */
  contain: paint;

  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  /* `html` sets scroll-behavior: smooth, which would animate every one-pixel
     step of the drift and fight the wrap. This scroller wants neither. */
  scroll-behavior: auto;
  cursor: grab;
  /* A soft edge, not a grey band.

     The first version ramped linearly across the whole gutter, which reads as
     a hard fade: a linear alpha ramp spends most of its length half-visible,
     so the cards under it looked washed out rather than passing under the
     margin. This is narrower and eased. CSS gradients interpolate linearly
     between stops, so the curve is drawn with stops rather than asked for. */
  -webkit-mask-image: var(--review-edge-mask);
  mask-image: var(--review-edge-mask);
}

.review-rail::-webkit-scrollbar {
  display: none;
}

.review-rail.is-dragging {
  cursor: grabbing;
  /* Stop a drag from selecting the quotations it passes over. */
  user-select: none;
}

/* Only when nothing is drifting: snapping mid-drift would drag the rail back
   to the nearest card every frame. */
.review-rail[data-drift="off"] {
  scroll-snap-type: x proximity;
}

.review-track {
  display: flex;
  gap: var(--review-gap);
  width: max-content;
  align-items: stretch;
}

.review {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  flex: 0 0 auto;
  width: min(21rem, 78vw);
  padding: clamp(1.25rem, 1rem + 1vw, 1.75rem);
  border: 1px solid var(--color-border);
  border-radius: 24px;
  background: var(--color-surface);
  scroll-snap-align: start;
}

.review-rail:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 4px;
  border-radius: 24px;
}

.review__stars {
  color: var(--color-accent);
  font-size: 0.9375rem;
  letter-spacing: 0.1em;
  line-height: 1;
}

.review__quote {
  flex: 1 1 auto;
}

.review__title {
  color: var(--color-text-primary);
  font-weight: 600;
  line-height: 1.3;
  text-wrap: pretty;
}

.review__body {
  margin-top: 0.5rem;
  font-size: var(--text-caption);
  color: var(--color-text-secondary);
  line-height: 1.6;
  text-wrap: pretty;
  /* Clamped so one long review cannot set the height of every card. Without
     it the rail was as tall as its wordiest entry and the short ones were
     mostly empty box. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 7;
  line-clamp: 7;
  overflow: hidden;
}

.review__meta {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--color-hairline);
}

.review__author {
  font-size: var(--text-caption);
  font-weight: 600;
  color: var(--color-text-primary);
}

.review__origin {
  font-size: 0.75rem;
  color: var(--color-text-tertiary);
}

.reviews__more {
  margin-top: clamp(1.75rem, 1.5rem + 1vw, 2.5rem);
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

/* The showcase scene above this ends with a tall stretch of dark room below
   the shelf. That space is part of the artwork, not the layout, so the section
   pulls up into it rather than stacking its own padding on top. The pull is in
   vw because the dead space scales with the image. The artwork's blacks blend
   into the page background, so there is nothing to overlap. */
.cta--scene + .reviews {
  margin-top: min(-5rem, -12vw);
  padding-top: 0;
}
