/* tokens */
:root {
  --page-bg: #f5f2ec;
  --fixed-element-bg: #faf9f6;
  --vert-gutter: 0.75rem;
  --color-default: #171715;
  /* structural grays */
  --bg-hover:      #f0ede8;
  --bg-button:      #c2c0bc;
  --border:        #e4e0d8;
  --border-strong: #c8c4be;
  --text-muted:    #999;
}

/* navbar icon normalisation — 1.5 px visual stroke regardless of SVG viewBox size */
/* .warn-icon class on the SVG excludes it from colour/weight normalisation */
mundial-auth-bar nav [stroke]:not(.chain-icon *):not(.warn-icon *) { stroke: #1C274C; stroke-width: 1.5px; vector-effect: non-scaling-stroke; }

/* guide-btn is a Bootstrap data-bs-toggle="button" — the .btn border it used to have gave a
   free "pressed" indicator when guide mode is open; now that it's a plain borderless icon link
   like its siblings, keep that signal by staying fully opaque instead of dimming while active */
mundial-auth-bar [data-ref="guide-btn"].active { opacity: 1 !important; }

/* base */
body { background: var(--page-bg); color: var(--color-default); }
.sub { font-size: 12px; color: var(--text-muted); }
.sub em { color: #555; font-style: normal; }
.flex-col { flex: 1; min-width: 0; }

/* inline button that looks like a link */
.link-btn { background: none; border: none; padding: 0; cursor: pointer; text-decoration: underline; text-underline-offset: 2px; color: inherit; }
.link-btn:hover { color: #555; }

/* Elo ranking flow (elo-) — used by <elo-ranking> web component on multiple pages */
.elo-header { display: flex; flex-direction: column; gap: 2px; margin-bottom: 10px; }
.elo-title { font-size: 14px; font-weight: 500; }
.elo-meta { font-size: 10px; color: var(--text-muted); overflow-x: hidden; white-space: nowrap;}

/* Stage carousel (Qualified → Round of 32 → … → Winner) — wraps the whole .elo-list below,
   the same pattern insights/status.html uses for its own carousel: a real Bootstrap carousel
   (bootstrap.Carousel instance + data-bs-* controls/indicators — native swipe/keyboard/a11y)
   whose carousel-items only carry a lightweight per-stage caption; prev/next sit absolutely
   over the list's left/right edges (full height of .elo-viz, i.e. caption + list combined),
   indicators sit below the caption in normal flow, above the list. See js/elo_ranking.js's
   EloRanking.connectedCallback(). Overrides below undo Bootstrap's full-bleed-image-carousel
   defaults (wide dark gradient buttons, large rectangular indicators) for this compact look. */
.elo-viz { position: relative; padding-top: 8px; padding-bottom: 8px; }
/* .elo-viz--match (js/elo_ranking.js's `set displayMode`, driven by control_sidebar.js's
   _displayMode) marks match-display mode itself, independent of the currently rendered stage's
   actual content — a `:has(.elo-list > li.elo-pair)` selector would react to *that* instead,
   and a stage with no decided/paired fixtures yet (e.g. the Final before it's played) has zero
   .elo-pair rows even while match-display is on, so anything keyed off :has() would flicker on
   and off as the carousel moves between stages that do/don't currently have fixtures. This rule
   no longer constrains width (it used to cap .elo-viz at 520px to remove the dead gutters full
   page width leaves around a fixture row's actual content — dropped per request); margin-inline
   is a no-op without a width/max-width alongside it, kept only so a future width rule (or any
   other match-display-only styling) has this selector ready without re-deriving the above. */
.elo-viz.elo-viz--match { margin-inline: auto; }
.elo-stage-carousel .carousel-inner { min-height: 20px; }
.elo-stage-carousel .carousel-item { text-align: center; }
.elo-stage-carousel .stage-caption { padding: 2px 40px 8px; }
.elo-viz .carousel-control-prev,
.elo-viz .carousel-control-next {
  position: absolute; top: 0; bottom: 0;
  display: flex; align-items: center;
  width: 32px; border: 0; background: transparent; opacity: 0.35;
  z-index: 2; cursor: pointer;
}
.elo-viz .carousel-control-prev { left: 0; justify-content: flex-start; }
.elo-viz .carousel-control-next { right: 0; justify-content: flex-end; }
.elo-viz .carousel-control-prev:hover,
.elo-viz .carousel-control-next:hover { opacity: 0.9; }
/* Swapped Bootstrap's default white chevron data-URIs for the same navy alt-arrow SVGs used
   elsewhere (e.g. #control-sidebar's csb-collapse button, navbar icons — all #1C274C stroke) —
   no filter needed since, unlike Bootstrap's white-on-transparent original, this SVG is already
   that color natively. The round rgba(245,242,236,.85) + border pairing is this app's own
   standard floating-icon-button look (see map-container.css's #zoom-reset/#zoom-span) rather
   than the plain opacity-only treatment #control-sidebar's .csb-icon-btn uses — needed here
   since these buttons float directly over the pill list rather than a plain page background,
   and were hard to notice without one. background-size is pinned in px (Bootstrap's own default
   is 100% 100%, i.e. relative to the padding box) so the icon itself doesn't stretch to fill
   the extra circle made room for it via padding. */
.elo-viz .carousel-control-prev-icon,
.elo-viz .carousel-control-next-icon {
  width: 16px; height: 16px; background-size: 16px 16px;
  box-sizing: content-box; padding: 7px;
  background-color: var(--bg-button);
  border: 1px solid var(--border); border-radius: 50%;
}
.elo-viz .carousel-control-prev-icon { background-image: url("/images/solar_linear/alt-arrow-left-svgrepo-com.svg"); }
.elo-viz .carousel-control-next-icon { background-image: url("/images/solar_linear/alt-arrow-right-svgrepo-com.svg"); }
.elo-stage-carousel .carousel-indicators {
  position: static; display: flex; justify-content: center; margin: 0 0 8px; gap: 4px;
}
.elo-stage-carousel .carousel-indicators button {
  width: 6px; height: 6px; border-radius: 50%;
  background-color: #ccc; opacity: 1; border: none;
  margin: 0 2px; padding: 0; cursor: pointer;
}
.elo-stage-carousel .carousel-indicators button.active { background-color: #666; }
/* Stages the tournament hasn't reached yet (nobody's there to show) — locked, not just empty */
.elo-viz .carousel-control-next.csb-stage-disabled { opacity: 0.1; pointer-events: none; }
.elo-stage-carousel .carousel-indicators button.csb-stage-locked { opacity: 0.3; pointer-events: none; }

.elo-list { list-style: none; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
/* 3rd Place Final's own heading (js/elo_ranking.js's #thirdPlaceHeading, above its own #ulThirdPlace
   .elo-list) — echoes the carousel's own stage-title ("Final") styling but deliberately weaker
   (smaller, muted, uppercase+tracking instead of a plain word) since it's a subordinate section
   within the same slide, not a second stage title of its own. Hidden whenever no item carries
   _pairThirdPlace — see show(). */
.elo-list-heading { text-align: center; font-size: 11px; font-weight: 500; letter-spacing: 0.04em; text-transform: uppercase; color: var(--border-strong); margin: 10px 0 4px; }
/* Row wrapper — the <ul>'s actual flex-wrap children (see js/elo_ranking.js's EloRanking.show()).
   Two zones, structurally: .elo-pairs (below), a single block-level wrapper holding every
   fixture couple, is the <ul>'s first child whenever match-display mode has at least one
   decided/undecided pairing — sortAndFilter always sorts pairs ahead of lone teams, so
   building it first and appending it before any .elo-solo <li> keeps that order automatic. A
   dedicated wrapper (rather than each .elo-pair row individually claiming flex-basis:100% in
   the same flow as .elo-solo rows, the earlier approach) is what let mobile-width fixture rows
   get their own column-track sizing without a bare 1fr track growing to fit whichever row's
   pill content happens to be longest — see .elo-pairs > li.elo-pair below for why that
   mattered. Lone (unpaired) teams render as plain <li class="elo-solo"> — one pill each — as
   direct children of .elo-list, after .elo-pairs. */
.elo-list > li { display: inline-flex; align-items: center; white-space: nowrap; }
/* .elo-pairs is one flex-wrap item, exactly the way each .elo-pair row used to claim its own
   line individually — pushing whatever solos come after it onto a fresh line below the whole
   fixture block, never interleaved with it. flex:0 0 100% (its role as a flex *item* within
   .elo-list) and display:grid (its role as a grid *container* for its own .elo-pair rows) are
   independent — an element can be both at once. The grid's 3 columns are what every row below
   subgrids into (see .elo-pairs > li.elo-pair) so the separator column sizes to the widest
   .elo-pair-sep across *all* rows, not just its own — gap: 6px 4px carries over the original
   6px between fixture rows (row-gap) and 4px between each row's own 3 columns (column-gap,
   inherited by every subgridded row from here). */
.elo-pairs { flex: 0 0 100%; display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: 6px 4px; }
/* Only meaningfully different once match-display mode actually has fixtures: .elo-pairs is
   always flex-basis:100%, so .elo-list's own justify-content never affects it either way — but
   it does affect .elo-solo rows (lone, unpaired teams), which always render after .elo-pairs.
   Team-display mode has only .elo-solo rows and wants them centered (see the "horiz centered"
   ask this rule was added for); match-display mode's trailing solos should instead read as a
   plain left-aligned overflow list underneath the fixture grid, not re-centered on their own. */
.elo-viz--match .elo-list { justify-content: flex-start; }
/* subgrid (not each row re-declaring its own minmax(0,1fr) auto minmax(0,1fr)) is what makes
   the separator column genuinely align row to row: every row shares .elo-pairs' own 3 column
   tracks instead of computing its own independent auto width, so the middle column sizes to
   fit the widest .elo-pair-sep across *all* rows, and every row's separator gets that same
   shared width — not just whatever its own content happened to need. minmax(0,1fr) on the
   outer two (still set on .elo-pairs itself) caps each pill's column at its fair half-share of
   whatever's left after the separator column, same as before; overflowing pill content is
   clipped (below) instead of stretching the column. grid-column:1/-1 makes each row span all 3
   inherited tracks rather than collapsing into just the first one. */
.elo-pairs > li.elo-pair {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: 1 / -1;
}
/* Left team's pill content (flag, name, pts — see pillContent in elo_ranking.js) renders
   flag-first, which would put it at the outer/left edge of the row once the pill itself is
   pushed flush right via justify-self:end. Reversing just this pill's internal order puts
   its flag last instead, i.e. innermost — right next to the separator, mirroring the right
   team's pill (unreversed, so its flag — already first — sits adjacent on its own side).
   .elo-item-wrap (js/elo_ranking.js) sits between li.elo-pair and .elo-item now — solely so a
   decoration anchored to it can escape .elo-item's own overflow:hidden below (a sibling of a
   clipped element isn't clipped by it; a pseudo-element on the clipped element itself always
   would be). justify-self is a grid property and must stay on the actual grid item (the
   wrapper, still li.elo-pair's direct child); flex-direction reorders .elo-item's own
   children, so it has to reach one level deeper. :first-child/:last-child are left anonymous
   (not .elo-item-wrap:first-child) since exactly one wrapper sits between li.elo-pair and
   .elo-item — whichever element is first/last among the row's children *is* that side's
   wrapper, so naming it isn't necessary to disambiguate left from right. */
.elo-pairs > li.elo-pair > :first-child { justify-self: end; }
.elo-pairs > li.elo-pair > :last-child { justify-self: start; }
.elo-pairs > li.elo-pair :first-child .elo-item { flex-direction: row-reverse; }
.elo-pairs > li.elo-pair > .elo-pair-sep { justify-self: center; }
/* Clip instead of stretch: max-width:100% caps each pill at its minmax(0,1fr) column's actual
   width (grid items otherwise size to content regardless of the column, per justify-self's own
   spec) — min-width:0 lets it actually shrink there instead of stopping at content size. On
   the left pill this crops from its own left edge (already right-aligned via justify-self:end
   above, so it reads as "outer edge clipped, inner/flag edge intact"); the right pill crops
   symmetrically from its right edge. */
.elo-pairs > li.elo-pair :first-child .elo-item,
.elo-pairs > li.elo-pair :last-child .elo-item {
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
}
/* The pill's own fixed-size children (flag, ▶/◀ dot, pts) keep their natural size; only the
   name — the one arbitrarily-long piece — actually shrinks and ellipsizes when a pill gets
   clipped by the rule above. min-width:0 overrides flex's own default content-based minimum
   (the standard "flex child won't shrink below its content" gotcha), which is what lets
   text-overflow:ellipsis engage at all instead of the browser just refusing to shrink the box. */
.elo-pairs > li.elo-pair .elo-item .elo-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Undecided fixture: a single line (kickoff "day month|hour", or a plain dash with no date at
   all). Decided fixture (.elo-pair-sep--score): kickoff day|hour above the score, plus a third
   row for the penalty shootout tally when the fixture went to penalties — see
   js/elo_ranking.js's EloRanking.show(). */
.elo-pair-sep { font-size: 10px; color: var(--border-strong); display: inline-flex; flex-direction: column; align-items: center; line-height: 1.15; }
/* No fixed width here anymore — the shared subgrid column (.elo-pairs above) already sizes
   itself to the widest .elo-pair-sep across every row, decided or not, so this only needs to
   stop its own multi-line content (date/score/pens) from wrapping mid-word. */
.elo-pair-sep.elo-pair-sep--score { white-space: nowrap; }
/* --color-default (body's own default text color) — both the kickoff date and the score are
   real match information, not a muted secondary cue. */
.elo-pair-sep-date { font-size: 9px; color: var(--color-default); }
/* Decided fixture — the actual score instead of a plain dash, so it reads as real information
   (final result) rather than just the same pairing cue as an undecided one. */
.elo-pair-sep-score { font-weight: 600; color: var(--color-default); font-variant-numeric: tabular-nums; }
/* Penalty shootout tally — its own row below the (drawn) regulation/extra-time score, same
   treatment as the kickoff date above it: small and muted, since the score line stays the
   primary, larger-emphasis result. */
.elo-pair-sep-pens { font-size: 9px; color: var(--color-default); font-variant-numeric: tabular-nums; }
/* Fixture selection (activateFixture in index.js, click on the separator) — whole-row
   highlight, the .elo-pair equivalent of .elo-item--active below. Background rather than a
   border/outline so it doesn't nudge the subgrid's column widths; row-gap around it already
   gives the highlight visual breathing room without extra padding. */
.elo-pairs > li.elo-pair.elo-pair--active { background: var(--bg-hover); border-radius: 10px; }
.elo-pair-sep--clickable { cursor: pointer; }
.elo-pair-sep--clickable:hover .elo-pair-sep-date,
.elo-pair-sep--clickable:hover .elo-pair-sep-score,
.elo-pair-sep--clickable:hover .elo-pair-sep-pens { color: #7b2d8b; }
.elo-item { display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px 3px 5px; border-radius: 20px; background: #fff; }
.elo-item--clickable { cursor: pointer; }
.elo-item--clickable:hover { background: var(--bg-hover); border-color: var(--border-strong); }
.elo-item--active { 
background: linear-gradient(to right,
    var(--imp-color, #ddd) 0%,
    #ddd var(--imp-pivot, 0%),
    #ddd var(--native-pivot, 0%),
    var(--exp-color, #ddd) 100%) !important;
}
.elo-item--zoomable { cursor: pointer; }
.elo-item--zoomable:hover { background: var(--bg-hover); border-color: var(--border-strong); }
/* Pill-list counterpart to the map's own flag dimming during dim mode (js/index.js's
   applyDim/animateFlagOpacity, DURATION_MS=180 in js/flag_visibility.js) — set by
   EloRanking.update()'s linkedIds param. Dims the whole pill, not just the flag: dim state is
   inherently transient (cleared on the next click/Escape), so legibility of the dimmed pills
   loses to making "linked to this selection or not" unmistakable at a glance. Same 0.35 opacity
   floor as the map's own. */
.elo-item--dim { opacity: 0.35; transition: opacity 0.18s ease; }
.elo-rank { font-size: 10px; color: var(--text-muted); font-variant-numeric: tabular-nums; min-width: 14px; text-align: right; flex-shrink: 0; }
.elo-dot { font-size: 7px; line-height: 1; }
.elo-name .elo-dot:first-child { margin-left: 3px; }
/* Thin white ring — circle-flags' own artwork already fills a circle, so border-radius:50%
   just clips the img's own square bounding box to match (harmless/no-op on the visible
   circle); the border is what actually adds definition against the pill's gradient bg. */
.elo-flag { width: 20px; height: 20px; border-radius: 50%; border: 0.5px solid #fff; }
/* Wraps .elo-flag — an <img> can't reliably render its own ::before/::after (generated
   content doesn't apply to replaced elements), so a badge anchored to the flag (see
   taxonomy.css's winner check mark) is positioned relative to this wrapper instead. */
.elo-flag-wrap { position: relative; display: inline-flex; flex-shrink: 0; }
.elo-layout { display: block; }
.elo-main { display: block; }
.elo-name { font-size: 12px; white-space: nowrap; }
.elo-pts { font-size: 9px; color: var(--text-muted); font-variant-numeric: tabular-nums; flex-shrink: 0; }
.elo-pts-primary { font-size: 10px; color: var(--text-muted); }

/* Wikipedia player links — used on map page (player table) and live game page */
.pt-wiki { color: inherit; border-bottom: 1px dotted var(--text-muted); }
.pt-wiki:hover { border-bottom-color: #7b2d8b; color: #7b2d8b; }
