/* ========== AUTH SLIDER ========== */
/*
 * The video slider, shared by /login, /signup and the auth modal.
 *
 * Extracted from bn_login.css when the modal grew a right-hand panel: three
 * copies of a container-query composition tuned to one frame size is three
 * chances for them to drift.
 *
 * What stayed behind in bn_login.css is anything about the PAGE — the
 * `.login-slider` column and the phone rules that turn it into a dimmed
 * backdrop. Those describe where the slider sits in that layout, which is
 * exactly what differs between a page and a modal. This file is the slider
 * itself.
 *
 * ORDER MATTERS on the pages: load this BEFORE bn_login.css. Its 900px block
 * overrides .slider-frame, and a media query adds no specificity — whichever
 * comes last wins. Loaded after, these base rules would undo the phone layout.
 */

/* The frame is fluid (viewport minus the login form), so every decoration on it
   is scaled from a single unit rather than pinned in px. `--u` is one "design
   pixel": the layout was authored at a 1440px viewport, which yields a frame of
   roughly 850x884, so 1 design px = 100/850 cqw = 100/884 cqh.

   The unit takes the SMALLER of the width- and height-derived values so the
   composition also fits on wide-but-short displays (e.g. 3840x1080), where
   scaling on width alone would push the lower bubbles off the bottom. The cqh
   term is deliberately looser than the true reference (0.16 rather than 0.113)
   because the artwork only occupies the upper ~625 design px of the frame.

   `--u` is declared on .slide, not .slider-frame: container query units resolve
   against an ANCESTOR container, so the container element cannot use its own. */
.slider-frame {
  position: relative;
  container-type: size;
  container-name: slider;
  width: 100%;
  /* dvh, so mobile browser chrome appearing does not crop the dots. */
  height: 100%;
  border-radius: 24px;
  overflow: hidden;
  background: var(--neutral-800);
}

.slide {
  --u: min(0.1176cqw, 0.16cqh);
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 0.6s;
}

/* Safety net for engines without container query units. A custom property
   holding an unparseable value still parses, so it fails later at substitution
   time and would resolve each property to `initial` rather than falling back to
   the px declarations above it. Pinning --u to 1px here makes the whole overlay
   render at exactly its authored design-pixel size instead. */
@supports not (width: 1cqw) {
  .slide {
    --u: 1px;
  }
}

.slide.active {
  opacity: 1;
}

.slide img.bg,
.slide .bg-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}

/* The <video> paints its own poster until the first frame is decoded, so a
   slow or missing clip shows the still image rather than a hole. The <img>
   underneath stays as the fallback for a browser that shows nothing at all. */
.slide .bg-video {
  pointer-events: none;
  background: #000 center / cover no-repeat;
}

/* A slide can be split into parts; only the one playing is on screen. The
   others stay in the DOM so their download can run ahead of time. */
.slide .bg-video:not(.is-current) {
  display: none;
}

/* The still is the slide until a frame is really playing, then it fades out
   from under the clip. A slide with no clip keeps its still forever. */
.slide img.bg {
  transition: opacity 0.4s;
}
.slide.video-on img.bg {
  opacity: 0;
}

.slide-caption {
  position: absolute;
  bottom: 48px;
  bottom: calc(48 * var(--u));
  left: 0;
  right: 0;
  text-align: center;
  font-size: 12px;
  font-size: max(11px, 12 * var(--u));
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #fff;
}

/* Slide 2 & 3 — caption sits on the vertical centre line */
.slide-caption.pos-mid {
  bottom: 50%;
}

/* Slide 4 — caption sits above centre (was `calc(50% - 162px)`) */
.slide-caption.pos-upper {
  top: calc(50% - 162px);
  top: calc(50% - 162 * var(--u));
  bottom: auto;
}

.slide-title-anime {
  position: absolute;
  top: 96px;
  top: calc(96 * var(--u));
  left: 50%;
  transform: translateX(-50%);
  font-family: 'Borel', cursive;
  font-size: 96px;
  font-size: max(64px, 96 * var(--u));
  line-height: 1.2;
  padding-top: 0.15em;
  background: linear-gradient(180deg, #fff 0%, #be78ff 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.slide-title-script {
  position: absolute;
  top: 170px;
  top: calc(170 * var(--u));
  left: 73px;
  left: calc(73 * var(--u));
  font-family: 'Borel', cursive;
  font-size: 56px;
  font-size: max(40px, 56 * var(--u));
  color: #fff;
}

.badge-new {
  position: absolute;
  top: 88px;
  top: calc(88 * var(--u));
  left: 230px;
  left: calc(230 * var(--u));
  transform: rotate(-15deg);
  background: var(--purple-400);
  color: var(--purple-900);
  padding: 2px 8px;
  padding: calc(2 * var(--u)) calc(8 * var(--u));
  border-radius: 6px;
  font-size: 14px;
  font-size: max(12px, 14 * var(--u));
  font-weight: 600;
}

.chat-bubble {
  position: absolute;
  background: rgba(255, 255, 255, 0.16);
  /* px first as a fallback for engines without container query units */
  padding: 6px 8px;
  padding: calc(6 * var(--u)) calc(8 * var(--u));
  border-radius: 12px 12px 12px 4px;
  border-radius: calc(12 * var(--u)) calc(12 * var(--u)) calc(12 * var(--u)) calc(4 * var(--u));
  font-size: 14px;
  font-size: max(13px, 14 * var(--u));
  line-height: 1.43;
  color: #fff;
  max-width: 230px;
  max-width: calc(230 * var(--u));
}

/* Bubble placement, in design px scaled by --u */
.chat-bubble.pos-a {
  top: 70px;
  top: calc(70 * var(--u));
  left: 255px;
  left: calc(255 * var(--u));
}

.chat-bubble.pos-b {
  top: 170px;
  top: calc(170 * var(--u));
  right: 187px;
  right: calc(187 * var(--u));
}

.chat-bubble.pos-c {
  top: 253px;
  top: calc(253 * var(--u));
  right: 496px;
  right: calc(496 * var(--u));
}

.chat-bubble.pos-d {
  top: 502px;
  top: calc(502 * var(--u));
  right: 444px;
  right: calc(444 * var(--u));
  max-width: 210px;
  max-width: calc(210 * var(--u));
}

.dots {
  position: absolute;
  bottom: 8px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 4px;
  align-items: center;
  z-index: 5;
}

.dot {
  width: 12px;
  height: 12px;
  border-radius: 8px;
  background: #fff;
  opacity: 0.3;
  cursor: pointer;
  transition: width 0.3s, opacity 0.3s;
}

.dot.active {
  width: 28px;
  opacity: 1;
}

/* A visitor who asked for less motion gets the stills, never a clip. */
@media (prefers-reduced-motion: reduce) {
  .slide .bg-video { display: none; }
}
