/* ---------------------------------------------------------------
   Homepage banner slider.
   Track is a scroll-snap container: touch swipe, momentum and
   keyboard scrolling come from the browser, not from JavaScript.
   --------------------------------------------------------------- */

.jb-banner {
  position: relative;
  background: transparent;
  overflow: hidden;
  /* Soften the join with the section below: rounded bottom corners break the
     hard rectangle, and the fade underneath melts the photo into the page. */
  border-radius: 0 0 clamp(16px, 2.6vw, 30px) clamp(16px, 2.6vw, 30px);
  /* Pull the hero up so it runs behind the overlay header. The height is
     measured in slider.js because the header's own height depends on the
     wordmark, the top bar and the viewport — a hard-coded guess drifts. */
  margin-top: calc(-1 * var(--jb-header-total, 108px));
}

/* Scrim behind the header: the client can upload any photo, and light text
   on an unknown image is a coin toss. This guarantees the contrast. */
.jb-banner::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: calc(var(--jb-header-total, 108px) + 60px);
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgba(16, 21, 27, .62) 0%,
    rgba(16, 21, 27, .34) 55%,
    rgba(16, 21, 27, 0) 100%
  );
}

.jb-banner__track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;              /* the dots are the affordance */
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;     /* don't trigger browser back-swipe */
}
.jb-banner__track::-webkit-scrollbar { display: none; }

.jb-banner__slide {
  flex: 0 0 100%;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  display: block;
  position: relative;
}

.jb-banner__slide picture,
.jb-banner__slide img {
  display: block;
  width: 100%;
  height: 100%;
}

/* Fixed aspect per breakpoint so the row never jumps as images load.
   Portrait on phones — that's the crop the mobile artwork is cut to. */
.jb-banner__slide img {
  aspect-ratio: 1080 / 1350;
  object-fit: cover;
}
@media (min-width: 768px) {
  .jb-banner__slide img {
    aspect-ratio: 1600 / 600;
    /* A cap, not a target: at typical widths the 1600:600 ratio resolves
       well under this. Making the hero taller means taller artwork (see
       BANNER-IMAGE-PROMPTS.md) — forcing it here would crop the sides off
       the client's banner, and on image-only slides that eats the wording. */
    max-height: 620px;
  }
}

/* Bottom fade.

   Masking the track to transparent — rather than painting a pale colour over
   it — lets the page's own mesh gradient show through. A painted fade has to
   guess the colour behind it, and any mismatch reads as the grey band this
   replaces. The stops approximate an ease-out so the fade has no visible
   starting line. */
.jb-banner__track {
  --jb-fade: clamp(90px, 22%, 190px);
  -webkit-mask-image: linear-gradient(to bottom,
    #000 calc(100% - var(--jb-fade)),
    rgba(0, 0, 0, .92) calc(100% - var(--jb-fade) * .78),
    rgba(0, 0, 0, .72) calc(100% - var(--jb-fade) * .56),
    rgba(0, 0, 0, .44) calc(100% - var(--jb-fade) * .34),
    rgba(0, 0, 0, .18) calc(100% - var(--jb-fade) * .16),
    transparent 100%);
  mask-image: linear-gradient(to bottom,
    #000 calc(100% - var(--jb-fade)),
    rgba(0, 0, 0, .92) calc(100% - var(--jb-fade) * .78),
    rgba(0, 0, 0, .72) calc(100% - var(--jb-fade) * .56),
    rgba(0, 0, 0, .44) calc(100% - var(--jb-fade) * .34),
    rgba(0, 0, 0, .18) calc(100% - var(--jb-fade) * .16),
    transparent 100%);
}

/* Without mask support, fall back to the painted fade rather than a hard cut. */
@supports not ((-webkit-mask-image: linear-gradient(#000, transparent)) or (mask-image: linear-gradient(#000, transparent))) {
  .jb-banner { background: var(--jb-ink); }
  .jb-banner::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    height: 120px;
    z-index: 1;
    pointer-events: none;
    background: linear-gradient(to top, rgba(251, 248, 242, .92), transparent);
  }
}

/* ---------- Dots ---------- */

.jb-banner__dots {
  position: absolute;
  z-index: 2;
  inset-inline: 0;
  /* Clear of the fade, where the image is still solid enough to sit on. */
  bottom: clamp(52px, 12%, 92px);
  z-index: 2;
  display: flex;
  justify-content: center;
  gap: 8px;
}
.jb-banner__dot {
  width: 9px;
  height: 9px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .55);
  box-shadow: 0 1px 3px rgba(16, 21, 27, .4);
  transition: background .18s ease, width .18s ease, border-radius .18s ease;
}
.jb-banner__dot.is-on {
  width: 26px;
  border-radius: 5px;
  background: var(--jb-amber);
}

/* Tap target stays 44px even though the dot is drawn small. */
.jb-banner__dot::after {
  content: "";
  position: absolute;
  width: 40px;
  height: 40px;
  margin: -16px 0 0 -16px;
}

.jb-banner--single .jb-banner__track { scroll-snap-type: none; }

@media (prefers-reduced-motion: reduce) {
  .jb-banner__track { scroll-behavior: auto; }
  .jb-banner__dot { transition: none; }
}
