/*
 * The scrolling tab row — the fixture page's, now shared with the club page.
 * See TabBar.js for why the filter sheet's and the search overlay's rows are
 * not this component.
 *
 * The filter sheet's and the search overlay's tab row, with one difference that
 * changes its mechanics: this one can be wider than the shell and scrolls. So
 * the tabs are content-sized rather than sharing the row evenly, the hairlines
 * are drawn on the *scroller* so they span the viewport rather than the track,
 * and the indicator lives inside the track so it travels with the content it
 * belongs to.
 *
 * A rule top and bottom, not just under: the row is a band between the header
 * above and the panels to come below, and closing only one side leaves it
 * reading as the bottom edge of the block above rather than as its own strip.
 * Both are the same hairline, so the band is symmetrical and the underline —
 * the one accent-coloured mark here — stays the only thing that moves.
 */
/*
 * Sticky within whichever scrolling body it sits in (the club and fixture
 * pages' own `__body`, both `overflow-y: auto`) — the bar above it (back
 * button, follow/share) scrolls away, but the tabs themselves stay pinned so
 * a switch between sections never needs a scroll back up first. `top: 0`
 * pins to that scrolling ancestor's own edge, not the viewport's, since
 * sticky positioning resolves against the nearest scrolling ancestor rather
 * than the page. The background keeps panel content from showing through
 * once something scrolls in behind it, and the low z-index only needs to clear
 * that same panel content, not any of the app's real overlays.
 *
 * "Clear the panel content" is not free, though, and the rule under this one is
 * what actually buys it — see it for why a z-index of 1 is not on its own
 * enough.
 */
/*
 * Every panel column a tab row scrolls under, held to one layer.
 *
 * Without this the bar's `z-index: 1` is not the promise it looks like. A crest
 * on a commentary row, a player node on the lineup pitch, the squad's own team
 * switcher — several things inside a panel are positioned at `z-index: 1` for
 * their own local reasons, and against a bar that is also 1 the tie is broken
 * by tree order. The panels come after the bar, so they win, and a club badge
 * scrolls up over the tabs.
 *
 * It went unnoticed because the fixture page's panels carry `zoom: 0.9` below
 * 500px, and a zoom other than 1 happens to create a stacking context — so on
 * a phone the content was already contained and the bug only appeared on a
 * wider screen, where that zoom returns to 1. The club and league pages, whose
 * panels have no zoom at all, had it at every width.
 *
 * `isolation: isolate` is the whole fix: it creates that stacking context on
 * purpose rather than as a side effect of something else, so a panel is one
 * layer and nothing inside it can out-rank the bar. Raising the bar's own
 * z-index instead would work until the next component picks 2.
 */
.fixture-details__panels,
.club-details__panels,
.league-details__panels {
  isolation: isolate;
}

.tab-bar {
  position: sticky;
  top: 0;
  z-index: 1;
  flex: none;
  background: var(--bg);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  /* The row keeps its own momentum; the page behind it must not inherit a
     flick that runs off either end. */
  overscroll-behavior-x: contain;
}

.tab-bar__track {
  position: relative;
  display: flex;
  /* Content-sized, so the row is as wide as its tabs and genuinely overflows
     rather than squeezing every label into the viewport. */
  width: max-content;
  min-width: 100%;
  padding-inline: var(--space-3);
}

.tab-bar__tab {
  flex: none;
  padding: var(--space-2) var(--space-3) var(--space-3);
  color: var(--text-muted);
  font-size: var(--text-sm);
  transition: color var(--duration) var(--easing);
}

.tab-bar__tab[aria-selected="true"] {
  color: var(--accent);
}

/*
 * The label goes bold when active. The row's widths must not move with it — the
 * underline is placed from measured boxes, and a weight swap that resized its
 * tab would drag the indicator off the label it is under and re-cut the
 * scroller's extent at the same time. The ghost twin below reserves the bold
 * width up front, which is the bottom nav's own answer to this.
 */
.tab-bar__label {
  position: relative;
  display: block;
  font-weight: var(--weight-medium);
  white-space: nowrap;
}

/* Invisible bold twin, zero height, holding the wider width at every weight. */
.tab-bar__label::before {
  content: attr(data-label);
  display: block;
  height: 0;
  overflow: hidden;
  visibility: hidden;
  font-weight: var(--weight-bold);
}

.tab-bar__tab[aria-selected="true"] .tab-bar__label {
  font-weight: var(--weight-bold);
}

/*
 * Sits on the row's own hairline. Width is set once from the widest tab and
 * every switch is translateX + scaleX off a left origin, so the slide never
 * touches layout. --spring rather than a plain ease: INTERACTIONS.md files a
 * tab indicator as a physical object moving, and those overshoot.
 */
.tab-bar__indicator {
  position: absolute;
  bottom: 0;
  left: 0;
  height: 2px;
  border-radius: var(--radius-full);
  background: var(--accent);
  opacity: 0;
  transform-origin: left center;
  pointer-events: none;
}

/* Added one frame after the first placement so it does not fly in from 0. */
.tab-bar--ready .tab-bar__indicator {
  opacity: 1;
  transition:
    transform var(--spring-duration) var(--spring),
    opacity var(--duration) var(--easing);
}
