/*
 * watch-chat-carousel.css -- the cycling strip at the top of the watch page's chat column.
 *
 * -- WHY THIS IS A STATIC STYLESHEET --------------------------------------------------------
 *
 * Not part of the Tailwind build, for the reason public/css/watch-sub-modals.css and
 * public/css/clips.css both give in their own headers: public/build/app.css is compiled by a
 * separate manual step, so a strip built out of brand-new utility classes renders as nothing
 * until somebody runs it. Hand-written, served as-is.
 *
 * -- ASCII ONLY -------------------------------------------------------------------------------
 *
 * nginx serves text/css with no charset here, so a non-ASCII byte in a `content:` string comes
 * out as mojibake. The arrows are SVGs in the markup, not glyphs in this file.
 */

.xv-carousel {
  position: relative;
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 8px 4px 5px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  background:
    radial-gradient(120% 140% at 50% 0%, rgba(168, 85, 247, 0.09) 0%, rgba(168, 85, 247, 0) 70%),
    rgba(255, 255, 255, 0.02);
}

/*
 * The arrows are OUTSIDE the clipped viewport, as a flex row, rather than absolutely positioned
 * over it. Over it they would sit on top of whatever the active slide drew in its corners -- and
 * the Gifters slide draws a name there, which is exactly the thing somebody is trying to read.
 */
.xv-carousel__arrow {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 22px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: 7px;
  cursor: pointer;
  color: #8b8b94;
  background: none;
  transition: color 120ms ease, background 120ms ease;
}

.xv-carousel__arrow:hover {
  color: #fff;
  background: rgba(255, 255, 255, 0.07);
}

.xv-carousel__arrow svg { width: 15px; height: 15px; }

/*
 * One slide at a time, and the others are not merely invisible -- see the `hidden` note in the
 * JS. This only has to clip the active one.
 *
 * ── 🔴 THE `min-height` IS WRITTEN BY THE JS, AND IT IS WHAT KEEPS CHAT STILL ──────────────
 *
 * The slides are different heights -- a podium is taller than a goal bar, the supporter card
 * taller than both -- and this strip sits directly ABOVE the chat scrollport in the same column.
 * Every rotation therefore resized the scrollport underneath it, and a scrollport that changes
 * height keeps its `scrollTop`: the conversation visibly slid up and down on a 7-second timer
 * while nobody had touched it.
 *
 * watch-chat-carousel.js measures every slide and writes the tallest one here, so the strip is
 * one fixed height for the whole broadcast and the rotation moves nothing below it. It is a
 * FLOOR, not a height: a slide that grows past it (a long goal label wrapping) still grows, and
 * the JS re-measures when it does rather than clipping it.
 */
.xv-carousel__viewport {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  /* Flex, so the active slide is centred in the floor above rather than hanging off its top. */
  display: flex;
  align-items: center;
}

.xv-carousel__slide {
  /* `1 1 auto` in the row above; the column is the slide's OWN direction. */
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: 0;
  padding: 2px 4px;
  text-align: center;
  animation: xv-carousel-in 200ms ease-out;
}

/*
 * 🔴 THIS RULE IS LOAD-BEARING, NOT TIDYING. `hidden` is a UA style (`display: none`) and the
 * rule above is an author style, so `display: flex` WINS and every slide renders at once --
 * which is exactly what happened the first time this was drawn. Any class that sets `display`
 * on an element the JS hides with `hidden` needs this, and it must stay below that rule.
 */
.xv-carousel__slide[hidden] { display: none; }

/*
 * A slide whose whole body is an existing CARD -- the Supporter Level ring, the gifted-sub
 * podium. Those partials were drawn for the rail: they are full-width and bring their own
 * padding, border and background, so the slide must not centre them or add its own box.
 */
.xv-carousel__slide--card {
  align-items: stretch;
  text-align: left;
  padding: 0 2px;
}

/*
 * ⚠️ `:not(.xv-carousel__cta)` IS THE WHOLE POINT OF THIS SELECTOR. The included card wants the
 * full width; the button under it does not, and a bare `> *` gave it `width: 100%` — which no
 * amount of `align-self` can undo, because an explicit width beats cross-axis alignment. The
 * Send a Gift button spanned the strip edge to edge until this was narrowed.
 */
.xv-carousel__slide--card > *:not(.xv-carousel__cta) { width: 100%; }

.xv-carousel__slide--card > .xv-carousel__cta { align-self: center; }

/*
 * 🔴 THE NESTED CARDS LOSE THEIR OWN BOX. `.xv2-watch-supporter` and `.xive-gift-ticker` were
 * drawn to sit as standalone cards IN THE RAIL -- each brings a border, a fill, a radius and (the
 * supporter card) a 16px margin. Dropped inside a strip that already has its own surface, that
 * reads as a box in a box with a hairline between them, which is what it looked like the first
 * time it shipped.
 *
 * ⚠️ `html.xive-shell-v2` IS REQUIRED ON THE SUPPORTER RULE, not decoration: the rule being
 * overridden is `html.xive-shell-v2 .xv2-watch-supporter` (0,2,1) in the compiled sheet, and a
 * bare `.xv-carousel__slide--card .xv2-watch-supporter` (0,2,0) loses to it on specificity no
 * matter which file loads last.
 */
html.xive-shell-v2 .xv-carousel__slide--card .xv2-watch-supporter {
  margin: 0;
  padding: 2px 4px;
  background: none;
  border: 0;
  border-radius: 0;
}

.xv-carousel__slide--card .xive-gift-ticker,
.dark .xv-carousel__slide--card .xive-gift-ticker {
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
}

/*
 * ⚠️ THE PODIUM AND ITS BUTTON DO NOT SHARE A ROW, and it was tried. A chat column is 340px; take
 * two 22px arrows, their gaps and a ~130px button out of that and the podium is left with ~140px,
 * which truncated it to "GIFTERS 560 | tro..." before the first name finished. Stacked, the
 * podium gets the full width and the button sits under it — two short lines instead of one
 * unreadable one.
 */
/*
 * The supporter card at strip width. It was drawn for the rail, which gives it ~308px; here the
 * two arrows and the strip's padding take ~55px of that, and at ~285px its 44px ring pushed the
 * head row until "Supporter Level" wrapped onto two lines and the tier truncated to "Bro...".
 * Shrinking the ring and tightening the gaps buys the text back the width it needs.
 */
html.xive-shell-v2 .xv-carousel__slide--card .xv2-watch-supporter { gap: 9px; }

html.xive-shell-v2 .xv-carousel__slide--card .xv2-watch-supporter__ring {
  width: 34px;
  height: 34px;
}

html.xive-shell-v2 .xv-carousel__slide--card .xv2-watch-supporter__crest {
  width: 27px;
  height: 27px;
}

html.xive-shell-v2 .xv-carousel__slide--card .xv2-watch-supporter__label {
  font-size: 12px;
  white-space: nowrap;
}

html.xive-shell-v2 .xv-carousel__slide--card .xv2-watch-supporter__head { gap: 6px; }

/*
 * The TIER keeps its whole name; the fixed label is what gives way. "Supporter Level" is the same
 * five syllables on every channel and is guessable from half of it, while the tier ("Bronze",
 * "Obsidian") is the one word on this card the viewer actually earned — truncating that to
 * "Bro..." throws away the only variable on the row.
 */
html.xive-shell-v2 .xv-carousel__slide--card .xv2-watch-supporter__tier {
  flex: 0 0 auto;
  white-space: nowrap;
}

html.xive-shell-v2 .xv-carousel__slide--card .xv2-watch-supporter__label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

html.xive-shell-v2 .xv-carousel__slide--card .xv2-watch-supporter__caption { font-size: 11px; }

@keyframes xv-carousel-in {
  from { opacity: 0; transform: translateX(8px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .xv-carousel__slide { animation: none; }
}

/* ── the line above each slide's body: an icon, a label, and the channel's number ─────────── */

.xv-carousel__head {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: 0;
  max-width: 100%;
}

.xv-carousel__icon { width: 13px; height: 13px; flex: 0 0 auto; }

.xv-carousel__label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #a1a1aa;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.xv-carousel__total {
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: #c084fc;
}

/* Pushed hard right so the head reads as "label ... value" however long the label is. */
.xv-carousel__spacer { display: none; }

/*
 * The goal slide's heading. 🔴 NOT the uppercase tracked label the other slides use: those are
 * CATEGORY names this file chose ("Gifters", "Clip it"), and a goal's title is a sentence the
 * creator wrote. "Help me build our community!" set in 10px uppercase at 0.14em tracking ran out
 * of a 340px chat column a third of the way in and clipped.
 */
.xv-carousel__label--plain {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: #e4e4e7;
  min-width: 0;
}

.xv-carousel__hint {
  font-size: 11px;
  color: #8b8b94;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── the podium chips (Gifters, Sparks) ───────────────────────────────────────────────────── */

.xv-carousel__podium {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
}

.xv-carousel__chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
  padding: 2px 6px 2px 3px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.055);
  border: 1px solid rgba(255, 255, 255, 0.06);
}

.xv-carousel__rank {
  display: grid;
  place-items: center;
  width: 15px;
  height: 15px;
  flex: 0 0 auto;
  border-radius: 999px;
  font-size: 9px;
  font-weight: 800;
  color: #1c1917;
  background: #a1a1aa;
}

/* Gold, silver, bronze -- the podium reads at a glance without anybody counting positions. */
.xv-carousel__chip:nth-child(1) .xv-carousel__rank { background: linear-gradient(160deg, #fcd34d, #f59e0b); }
.xv-carousel__chip:nth-child(2) .xv-carousel__rank { background: linear-gradient(160deg, #e5e7eb, #9ca3af); }
.xv-carousel__chip:nth-child(3) .xv-carousel__rank { background: linear-gradient(160deg, #f0b48a, #c2703f); }

.xv-carousel__who {
  font-size: 11px;
  font-weight: 600;
  color: #e4e4e7;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.xv-carousel__score {
  font-size: 10px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: #a78bfa;
  flex: 0 0 auto;
}

/* ── the call to action ───────────────────────────────────────────────────────────────────── */

.xv-carousel__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 6px 15px;
  border: 0;
  border-radius: 999px;
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  color: #fff;
  cursor: pointer;
  background: linear-gradient(97deg, #9333ea 0%, #d946ef 55%, #ec4899 100%);
  box-shadow: 0 5px 14px -6px rgba(217, 70, 239, 0.95);
  transition: filter 120ms ease, transform 110ms ease;
}

.xv-carousel__cta:hover { filter: brightness(1.09); transform: translateY(-1px); }
.xv-carousel__cta:active { transform: none; }
.xv-carousel__cta:disabled { opacity: 0.5; cursor: default; filter: none; transform: none; }
.xv-carousel__cta svg { width: 14px; height: 14px; flex: 0 0 auto; }

/* The Clip slide's button is an action on the stream rather than a spend, so it is not dressed
   as one. Same size, no gradient, no glow. */
.xv-carousel__cta--plain {
  background: rgba(255, 255, 255, 0.09);
  box-shadow: none;
  color: #e4e4e7;
}

.xv-carousel__cta--plain:hover { background: rgba(255, 255, 255, 0.15); filter: none; }

/* ── the goal bar ─────────────────────────────────────────────────────────────────────────── */

.xv-carousel__goal {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-width: 0;
}

.xv-carousel__track {
  flex: 1 1 auto;
  height: 5px;
  border-radius: 999px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.1);
}

.xv-carousel__fill {
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, #a855f7, #ec4899);
  transition: width 320ms cubic-bezier(0.2, 0.9, 0.3, 1);
}

.xv-carousel__goal-num {
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: #d4d4d8;
}

/* ── the dots ─────────────────────────────────────────────────────────────────────────────── */

.xv-carousel__dots {
  display: flex;
  justify-content: center;
  gap: 5px;
  padding-top: 5px;
}

.xv-carousel__dot {
  width: 5px;
  height: 5px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  background: rgba(255, 255, 255, 0.22);
  transition: background 140ms ease, width 140ms ease;
}

.xv-carousel__dot.is-on {
  width: 14px;
  background: linear-gradient(90deg, #a855f7, #ec4899);
}

/* ── a single slide needs no chrome ───────────────────────────────────────────────────────── */

.xv-carousel[data-count="1"] .xv-carousel__arrow,
.xv-carousel[data-count="1"] .xv-carousel__dots { display: none; }

/* ── STREAM TOGETHER ──────────────────────────────────────────────────────────────────────────
   The chat header when this broadcast is running with co-hosts, whose chats watch-chat.js merges
   into this one. The stacked crests say whose messages are about to appear here BEFORE the first
   one does -- which is the whole confusion the treatment exists to prevent.
   ============================================================================================ */

.xv-together {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

/* 🔴 SAME TRAP AS `.xv-carousel__slide[hidden]` ABOVE: `hidden` is a UA style and the rule
   above is an author style, so `display: inline-flex` wins and the title renders on a channel
   that is not streaming together at all. Both titles are toggled with `hidden`. */
.xv-together[hidden] { display: none; }

.xv-together__crests {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
}

.xv-together__crest {
  width: 19px;
  height: 19px;
  border-radius: 999px;
  object-fit: cover;
  background: #2a0f45;
  box-shadow: 0 0 0 2px #18181b;
}

/* Overlapped, so two or three channels read as one room rather than a list. */
.xv-together__crest + .xv-together__crest { margin-left: -7px; }

.xv-together__more {
  display: grid;
  place-items: center;
  font-size: 9px;
  font-weight: 800;
  color: #d4d4d8;
}

.xv-together__label {
  font-weight: 700;
  white-space: nowrap;
}
