:root {
  /* Stage 9 type pass: Manrope for headings/labels/numbers (titles,
     nav, scoreboard, uppercase labels, table headers), Inter for
     body/data text (names, paragraphs, table cells) - picked and
     compared live in the Estuardos Type Lab artifact. Both loaded
     from Google Fonts in index.html's <head>. */
  --font-heading: 'Manrope', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* Team palette: #074f57 main, black secondary, white tertiary,
     #18a8b6 light accent, #062225 dark accent (also used in social
     media graphics). Page background uses the dark accent rather than
     pure black; tables use a separate neutral dark-grey pair so data
     grids read distinctly from the page/card chrome around them. */
  --main: #074f57;
  --black: #000000;
  --white: #ffffff;
  --accent-light: #18a8b6;
  --accent-dark: #062225;
  --grey-header: #181a1c;
  --grey-header-dark: #1a1a1a; /* Perfil GOL/AST/PA/PI grids: a game column beyond that season's own real game count (Stage 9) */
  --grey-cell: #222528;
  --grey-cell-hover: #3d3d3d;

  /* Color-scale endpoints used by app.js for the stat-table gradients
     (rank/total/matchday cells) and the Results table's Cancha/Hora
     gradients — read at runtime via getComputedStyle, so these are the
     single source of truth for both CSS and JS. */
  --scale-best: #0b5394;
  --cancha-light: #4a86c9;
  --cancha-dark: #0d2b4a;
  --hora-light: #8a63b3;
  --hora-dark: #2e1a47;
  /* GC's own scale-high (purple) — also DIF's scale-low, since DIF is
     defined as spanning from "as bad as the worst GC" to "as good as
     the best GF" rather than the usual grey-to-color scale every other
     column uses. */
  --gc-color: #8f2eb3;
  /* Goalkeeper kit color for the current era's uniform theme (Temas
     tab, historical doc — NOT the same as the fixed orange used for
     the POR position pill everywhere else on the site). Update this
     alongside --main/--accent-light/etc. whenever the team's colors
     change (see the Temas tab's "Portero" column for the active row's
     value). */
  --portero: #fe7f2e;

  --bg: var(--accent-dark);
  --card: var(--grey-cell);
  --border: #444444;
  --text: var(--white);
  /* Both muted tones nudged slightly lighter than their original values
     (#9a9a9a / #668a8e) after a contrast audit — the originals sat just
     under 4.5:1 (WCAG AA for normal-size text) against their real
     backgrounds (muted on --card, muted-alt on --bg), close enough to
     read fine but not quite passing. These clear 4.5:1 with real margin
     against every background they're actually used on, at a difference
     small enough not to change the look. */
  --muted: #9e9e9e;
  /* A second, distinct muted tone — Perfil's secondary text (full name,
     Debut/Cumpleaños labels) and the footer's "last updated" line only,
     not a replacement for --muted everywhere else. */
  --muted-alt: #6f9599;
  --accent: var(--accent-light);
  /* Win/draw/loss — used directly as the Results table's R column and
     the leaderboard's result-bar row (.result-chip-g/p/e,
     .result-bar-g/p/e below), AND read into app.js's COLORS object as
     the all-time balance table's PG/PE/PP (and PTS, via --good again)
     column scale-highs — same three colors, one definition. */
  --good: #25b659;
  --bad: #ec071e;
  --draw: #979797;
  /* Penales (Stage 7 extension) - a tie decided in Estuardos' favor
     by a penalty shootout (see the Penales glossary entry in the
     project instructions), same win-color role as --good but visually
     distinct from a regulation win. */
  --draw-pk: #5f9acf;
  /* Unknown-score match (some older seasons have real games Daniel has
     no surviving record of the final score for) — a distinct visual
     status from g/p/e/ex, never counted toward season team stats
     (see computeStandingsFromMatches_ in dashboard_export.gs). */
  --unknown-score: #8e7cc3;
}

* { box-sizing: border-box; }

/* CSS cascade rule: an author-stylesheet "display" declaration always
   beats the browser's built-in "[hidden] { display: none }" rule,
   regardless of selector specificity, since normal author rules
   outrank normal user-agent rules in the origin/importance order —
   the only thing that can override an author "display" rule is a
   HIGHER-precedence declaration, hence !important here. Without this,
   any element toggled via the "hidden" IDL property in app.js (e.g.
   showTeamBalance_/showTeamSeasonDetail_) that also carries a class
   like .table-wrap.compact (display: table) stays visibly on screen
   even while "hidden" is true — confirmed as the cause of the all-time
   balance table showing underneath a selected season's results. */
[hidden] { display: none !important; }

html, body {
  /* Defensive backstop — the page itself should never scroll
     horizontally; only individual .table-wrap elements should (via
     their own overflow-x: auto). Without this, any future wide/nowrap
     content that slips past a .table-wrap's containment would drag the
     whole page (header, nav) sideways instead of just scrolling a
     table, the same failure mode fixed below for .table-wrap.compact. */
  overflow-x: hidden;
}

body {
  margin: 0;
  /* Seamless dark diamond pattern, tiled at the same scale as the banner
     (see .site-header). --bg is the fallback while the image loads. */
  background: var(--bg) url("images/Base-verde-dark-lowRes.jpg") repeat;
  background-size: 2100px auto;
  color: var(--text);
  font-family: var(--font-body);
  line-height: 1.5;
}

/* Stage 9 type pass - headings, nav, scoreboard, uppercase labels
   and table headers get the display face; everything else (names,
   paragraphs, table cells) inherits --font-body from body above. */
h1, h2, h3, h4, h5,
.tab-btn,
.partido-titulo, .partido-meta-item, .partido-banda-nombre, .partido-banda-score,
.partido-vs-equipo, .partido-vs-sep,
.perfil-dorsal, .perfil-detalle,
.insignia-label,
.jugador-card-pos,
.timeline-date,
.records-subheading,
.social-label,
#loading-overlay p,
thead th, table th {
  font-family: var(--font-heading);
}

/* Loading overlay — shown while data.json is still fetching (see app.js:
   hidden right when the fetch resolves, whether that's a successful
   init() or the error path). Covers the whole viewport rather than just
   <main> since the header/nav would otherwise render immediately with
   nothing underneath them to click yet. Removed from view entirely via
   display:none (not just visually faded) so it can't block clicks on
   the real page once hidden. */
.loading-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
}
.loading-overlay p { color: var(--muted); margin: 0; font-size: 0.9rem; text-transform: uppercase; letter-spacing: 0.05em; }
.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid var(--grey-header);
  border-top-color: var(--accent-light);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

.site-header {
  text-align: center;
  padding: 1.5rem 1rem;
  /* --main is the fallback in case the image fails to load; the pattern
     is a genuinely seamless tile (confirmed against its own source),
     so it's repeated at native resolution rather than stretched to
     "cover" — that avoids ever upscaling it, even on a very wide
     screen, and needs no larger source image to look sharp. */
  background: var(--main) url("images/Base-verde-lowRes.jpg") repeat;
  background-size: 2100px auto;
}
/* Wraps the badge image so it's a real, clickable/keyboard-focusable
   control (Inicio's only entry point — see app.js setupInicio_) while
   looking exactly like the plain image it replaced: button chrome
   stripped back to nothing, image itself carries all the visible sizing. */
.site-badge-btn {
  background: none;
  border: none;
  padding: 0;
  margin: 0 auto;
  display: block;
  cursor: pointer;
}
.site-badge {
  height: 7.5rem;
  width: auto;
  display: block;
  margin: 0 auto;
}
.subtitle { margin: 0.25rem 0 0; color: var(--white); opacity: 0.85; }

/* Both nav levels share the same button shape/border/text rules — a
   rounded rectangle, white text, no border while inactive, a white
   border while active — and only differ in background: the top-level
   nav (and its buttons) are black, the sub-nav (and its buttons) match
   the page's own background instead of having a dedicated color of
   their own. Padding on the nav bar itself keeps the buttons' borders
   clear of the bar's edges. */
.tabs {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.75rem;
  padding: 1rem;
}
.main-nav { background: var(--black); }
.sub-nav { background: transparent; }
.tab-btn {
  border: 2px solid transparent;
  border-radius: 8px;
  color: var(--white);
  font-size: 1rem;
  padding: 0.6rem 1.2rem;
  cursor: pointer;
}
.main-nav .tab-btn { background: var(--black); }
.sub-nav .tab-btn { background: transparent; }
.tab-btn.active {
  border-color: var(--white);
  font-weight: 600;
}
/* Main nav's active state drops the border (bold text alone is enough
   of a marker there) — kept for the Equipo/Individuales sub-nav, which
   still uses the shared .tab-btn.active rule above. */
.main-nav .tab-btn.active { border-color: transparent; color: var(--accent-light); }
/* Home icon — first item in the main nav, reuses the site favicon
   instead of a text label. Padding trimmed from the shared .tab-btn
   rule since an icon needs less breathing room than a text label to
   look balanced next to it. */
.nav-home-btn { padding: 0.4rem 0.7rem; }
.nav-home-icon { height: 1.4rem; width: auto; display: block; }
/* Vertical dividers between main-nav items — a thin line centered in
   each gap, not on the last item (nothing follows it). Uses
   --grey-header (the site's main dark grey) rather than --border,
   which is tuned for light content on a dark card, not dark-on-black
   here. Positioned via ::before at half the .tabs gap so it sits
   centered between two buttons regardless of each button's own width. */
.main-nav .main-tab-btn:not(:last-child) {
  position: relative;
}
.main-nav .main-tab-btn:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -0.375rem;
  transform: translateY(-50%);
  width: 1px;
  height: 1.5rem;
  background: var(--grey-header);
}

main { max-width: 900px; margin: 0 auto; padding: 1.5rem 1rem 3rem; }
/* Detailed leaderboard views (per-match or per-era columns) need much
   more horizontal room than the 900px reading-width column — toggled
   via JS alongside the table-wrap's own compact/full-width switch. */
main.wide { max-width: 1400px; }

.tab-panel { display: none; }
.tab-panel.active { display: block; }
.section-panel { display: none; }
.section-panel.active { display: block; }

/* Plantel — roster cards, grouped into Porteros/Defensas/Medios/
   Delanteros sections (app.js's plantelSectionHtml_), 4 per row within
   each section. Each card is just the player photo (dorsal/name are
   already baked into the image itself, same style as the team's social
   media graphics), so there's no separate text overlay to style here —
   just lay the images out in a grid. #plantel-grid itself is now just a
   vertical stack of sections; the 4-column card grid lives one level
   down, in .plantel-cards-grid. */
.plantel-grid { display: flex; flex-direction: column; gap: 2rem; }
.plantel-section h3 { margin-top: 0; }
.plantel-cards-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
}
/* A real <button> now (see app.js) — reset back to the plain, unstyled
   look it had as a <div>, since none of a button's default chrome
   (background, border, padding, centered text) is wanted here. */
.plantel-card {
  display: block;
  cursor: pointer;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  text-align: left;
  width: 100%;
  font: inherit;
}
.plantel-card img { width: 100%; height: auto; display: block; }
/* Shown instead of a broken-image icon when a card's photo file isn't
   uploaded yet (app.js's plantelSectionHtml_ swaps to this on the
   img's onerror) — most relevant to Miembros Previos while Daniel is
   still filling in that photo set, but works the same for either
   grid. Same aspect ratio / look as .jugador-card-placeholder so a
   placeholder tile doesn't stand out oddly next to real photo tiles. */
/* Generic "this links to a player's profile" affordance - applied
   wherever a player's name/photo appears site-wide (Ultimo Partido/
   Alineaciones cards, Lideres Historicos, Records entries, Individuales/
   BALANCE table rows), wired by one shared delegated click listener
   (setupJugadorLinks_, app.js). Distinct from .plantel-card, which
   already had its own dedicated click handling before this and is
   left untouched. tr.jugador-link also gets the existing
   tbody tr:hover background highlight for free - no separate rule
   needed for table rows. */
.jugador-link { cursor: pointer; }
.jugador-link:hover { opacity: 0.85; }
.era-link { cursor: pointer; }
.era-link:hover { opacity: 0.85; }

/* Same "this links somewhere" affordance, for a match sheet (Stage 9) —
   Resultados table rows (tr.match-row-link, gets the existing
   tbody tr:hover background highlight for free, same reasoning as
   .jugador-link above) and inline match mentions inside Records
   entries (.partido-link — a dotted underline since those sit inside
   plain text, unlike a whole row/card). Both wired by one shared
   delegated click listener (setupPartidoLinks_, app.js). */
.match-row-link { cursor: pointer; }
.partido-link {
  cursor: pointer;
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 2px;
}
.partido-link:hover { opacity: 0.85; }

.plantel-card-placeholder {
  width: 100%; aspect-ratio: 5 / 6; border-radius: 8px; background: var(--grey-cell);
  display: flex; align-items: center; justify-content: center;
  color: var(--muted); font-size: 0.8rem; font-weight: 600; padding: 0.5rem; text-align: center;
}
@media (max-width: 640px) {
  /* Inicio cards drop back to a stacked single column on phones -
     the desktop side-by-side split above gets too tight otherwise. */
  .inicio-grid { flex-direction: column; }
  #ultimo-partido-card, .inicio-side { flex-basis: auto; }
  .plantel-cards-grid { grid-template-columns: repeat(3, 1fr); }
  .records-leaders-grid, .records-highlights-grid { grid-template-columns: 1fr; }
  /* 3 fixed columns (see .historia-cards) get too cramped on a narrow
     phone — same 2-column drop as .plantel-cards-grid above. */
  .historia-cards { grid-template-columns: repeat(2, 1fr); }
  /* Main nav (home icon + Jugadores/Estadísticas/Historia) had no
     wrap/overflow handling at all — on a narrow phone it simply ran
     past the viewport edge with "Historia" cut off and unreachable.
     Tighter sizing gets all 4 items to fit on most phones; the scroll
     fallback below guarantees nothing is ever truly unreachable even
     on the narrowest screens or with larger accessibility font sizes. */
  .main-nav {
    justify-content: flex-start;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .main-nav::-webkit-scrollbar { display: none; }
  .main-nav.tabs { gap: 0.35rem; padding: 0.75rem 0.5rem; }
  .main-nav .main-tab-btn { flex-shrink: 0; }
  .main-nav .main-tab-btn:not(.nav-home-btn) { padding: 0.55rem 0.8rem; font-size: 0.9rem; }
  /* Divider ::after is centered at half the .tabs gap (see its own rule
     above) — re-centered here since the mobile gap is narrower. */
  .main-nav .main-tab-btn:not(:last-child)::after { right: -0.175rem; }
}

/* Perfil — one player's profile page, reached only via a Plantel card
   click (or a shared #jugador/<id> link), never the main nav — see
   activateSection_/routeFromHash_ in app.js. */
.perfil-volver {
  background: transparent;
  border: 2px solid var(--white);
  border-radius: 8px;
  color: var(--white);
  font-size: 0.9rem;
  padding: 0.5rem 1rem;
  cursor: pointer;
  margin-bottom: 1.5rem;
}

/* Match-sheet page (Stage 9) - Volver and the Prev/Next arrows share
   one row, Volver on the left, the two small triangle-only buttons on
   the right (Daniel's own simplification - these used to be full
   text buttons on their own row). */
.partido-topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 1.5rem;
}
.partido-topbar .perfil-volver { margin-bottom: 0; }
.partido-nav { display: flex; gap: 0.5rem; }
.partido-nav-btn {
  background: transparent;
  border: 2px solid var(--white);
  border-radius: 8px;
  color: var(--white);
  font-size: 0.85rem;
  width: 2.5rem;
  height: 2.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  cursor: pointer;
}
.partido-nav-btn:disabled {
  opacity: 0.35;
  cursor: default;
}
.perfil-header {
  display: flex;
  gap: 1.5rem;
  align-items: flex-start;
  flex-wrap: wrap;
  margin-bottom: 2rem;
}
.perfil-foto { width: min(250px, 100%); height: auto; display: block; flex-shrink: 0; }
/* Same missing-photo fallback as .plantel-card-placeholder, sized for
   the profile header instead of a grid card — swapped in via the
   img's onerror in renderPerfil. */
.perfil-foto-placeholder {
  width: min(250px, 100%); aspect-ratio: 5 / 6; border-radius: 8px; background: var(--grey-cell);
  display: flex; align-items: center; justify-content: center;
  color: var(--muted); font-size: 1rem; font-weight: 600; padding: 0.75rem; text-align: center;
  flex-shrink: 0;
}
.perfil-dorsal { color: var(--accent-light); font-size: 3rem; font-weight: 700; line-height: 1; margin: 0 0 0.25rem; }
.perfil-info h2 { margin: 0 0 0.5rem; font-size: 2rem; text-transform: uppercase; letter-spacing: 0.02em; }
/* Full name reads as a subtitle under the big nickname — muted and
   italic, clearly secondary, not competing with it. */
.perfil-nombre-completo { color: var(--muted-alt); font-style: italic; font-size: 1.05rem; margin: 0 0 0.4rem; }
/* Debut/Cumpleaños — label (small, muted, uppercase, like a table
   header) + value (bold white, larger) instead of one flat line of
   plain text, so the actual data — 2010, Octubre 2 — is what the eye
   lands on rather than blending into its own label. */
.perfil-detalle {
  color: var(--muted-alt);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin: 0.25rem 0;
}
.perfil-valor {
  color: var(--white);
  font-weight: 700;
  font-size: 1rem;
  text-transform: none;
  letter-spacing: normal;
  margin-left: 0.4rem;
}
/* Social links — left-aligned under the info column (not centered like
   the footer's), same icon assets/sizing as .social-links but a touch
   smaller since this sits inline with a text-heavy column rather than
   as its own footer band. Empty (no accounts entered) collapses to
   nothing via the parent's own margin rules, no placeholder shown. */
.perfil-social { display: flex; gap: 0.5rem; margin-top: 0.35rem; }
.perfil-social img { width: 28px; height: 28px; display: block; border-radius: 6px; }

/* Badges — a plain flex-wrap grid (unlike Plantel's fixed 4-column
   grid) since a player might have anywhere from zero to a dozen. Each
   card is self-contained: icon image (or a plain text placeholder if
   Daniel hasn't filled in that badge's Imagen cell yet — see
   buildLogrosJson_) plus the badge name/season underneath. */
/* Grid (not flex-wrap) so cards distribute evenly across the full
   row width instead of hugging the left edge with a ragged, mostly-
   empty last row (the old flex-wrap layout on a phone-width screen
   left 2 cards floating with a lot of dead space beside them). Same
   auto-fill/minmax pattern as .partido-jugadores-grid below - at
   least 3 per row on a typical phone, more on wider screens, each
   card stretching to fill its column. */
/* Column floor is the larger of 80px (the mobile minimum from the
   earlier grid fix) and 1/7th of the row (minus its share of the 6
   gaps between 7 columns) - so on a wide desktop screen this floor
   wins and caps the row at 7 badges, evenly filling the width
   instead of the ~9-10 tiny badges auto-fill alone produced; on a
   narrow phone the 80px floor wins instead, same as before. */
.insignias-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(max(80px, calc((100% - 6 * 1rem) / 7)), 1fr)); gap: 1rem; }
.insignia-card {
  text-align: center;
  background: var(--grey-header);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 0.6rem;
}
.insignia-card img { width: 100%; height: auto; display: block; }
.insignia-placeholder {
  width: 100%;
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--grey-cell);
  border-radius: 8px;
  color: var(--muted);
  font-size: 0.75rem;
  padding: 0.3rem;
}
.insignia-label { font-weight: 700; color: var(--white); font-size: 0.8rem; margin-top: 0.4rem; }
.insignia-temporada { color: var(--muted); font-size: 0.75rem; }

/* Perfil — Tarjetas (collectible cards, one per year a card was
   designed for that player; see renderPerfil). Same card language as
   .insignia-card (rounded box, image + subtitle, no title needed — the
   year alone is the label, same as .historia-card's crest/jersey
   subtitle-only cards) but a narrower auto-fill floor than
   .insignias-grid's, since a trading-card graphic is portrait-oriented
   rather than square like a badge icon. */
.tarjetas-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-bottom: 0.5rem; }
.tarjeta-card {
  text-align: center;
  background: var(--grey-header);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 0.6rem;
}
.tarjeta-card img { width: 100%; height: auto; display: block; border-radius: 8px; }
.tarjeta-anio { color: var(--muted); font-size: 0.75rem; margin-top: 0.4rem; }

/* Inicio — Último Partido / Próximo Partido cards. Side by side on
   desktop again (Daniel's later call, reversing the note above) —
   Próximo Partido has much less content than Último Partido (no
   lineup grid, no scoreboard bands), so it gets a narrower share of
   the row instead of an even 50/50 split; align-items: flex-start so
   the shorter Próximo card doesn't stretch to match Último's height.
   Drops back to a single stacked column on narrow screens (see the
   640px media query below) so Próximo never has to fight Último for
   width on a phone. Visual language borrowed from the Estuardos
   social-media match graphics: an uppercase letter-spaced title, an
   icon+label meta row (trophy/calendar/clock/pin), and — for Último
   Partido — full-width colored scoreboard bands instead of a plain
   "3 - 2" text pill. */
.inicio-grid { display: flex; align-items: flex-start; gap: 2rem; }
/* <main> goes wide for this section (see activateSection_ in app.js)
   so the two cards get real room on a desktop screen instead of being
   squeezed under the default 900px reading-width <main>. Próximo
   Partido is capped with max-width, since its plain "vs" block never
   needs to grow past a comfortable size - the extra width goes to
   Último Partido instead (flex: 1 1, no basis cap), which actually
   benefits from it (more lineup photos per row). */
#ultimo-partido-card { flex: 1 1 480px; min-width: 0; }
/* Wraps Próximo Partido + the social block below it (Stage 9 -
   see index.html) - carries the flex sizing/width cap that used to
   sit directly on #proximo-partido-card, since that card is no
   longer the only thing in this column. */
.inicio-side { flex: 1 1 320px; max-width: 380px; min-width: 0; display: flex; flex-direction: column; gap: 2rem; }
/* Daniel's call: blend into the page instead of standing out as a grey
   panel, with the brand color doing the framing work instead. Shared by
   Ultimo/Proximo Partido on Inicio and both match-sheet cards (Stage 9). */
.partido-card {
  background: var(--bg);
  border: 1px solid var(--main);
  border-radius: 12px;
  padding: 1.5rem;
}
/* Same size as the plain h3 rule below (Historia's section titles) -
   Daniel's call, these were noticeably smaller before. */
.partido-titulo {
  margin: 0 0 1.25rem;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--accent-light);
  font-size: 1.4rem;
}
.partido-meta-row { display: flex; justify-content: center; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.5rem; }
.partido-meta-item { display: flex; align-items: center; gap: 0.35rem; color: var(--white); font-weight: 700; font-size: 0.78rem; text-transform: uppercase; }
.partido-meta-item svg { width: 16px; height: 16px; color: var(--accent-light); flex-shrink: 0; }

/* Último Partido's scoreboard — two full-width bands, score grouped
   close to the name on the left (not spread to opposite edges).
   Estuardos' own band always uses the team's brand color (var(--main))
   — not a win/draw/loss result color, since the score already makes
   the outcome obvious. The rival's band uses their real kit colors
   read off RES's Rival cell, falling back to the plain grey card
   background if that rival isn't colored yet. */
.partido-marcador { border-radius: 10px; overflow: hidden; margin-bottom: 1.75rem; }
.partido-banda { display: flex; align-items: center; gap: 1.25rem; padding: 0.7rem 1.25rem; color: var(--white); background: var(--grey-cell); }
.partido-banda-local { background: var(--main); }
.partido-banda-nombre { font-weight: 700; text-transform: uppercase; font-size: 1.6rem; }
.partido-banda-score { font-weight: 700; font-size: 2.15rem; min-width: 0.56em; font-variant-numeric: tabular-nums; }
/* Penales (Stage 7 extension) - the small "Penales: 2-3" line under
   Ultimo Partido's two score bands (margin-top pulls it up under the
   marcador's own margin-bottom), and the inline "(P 2-3)" annotation
   next to a marcador elsewhere (Resultados table, Alineaciones). Both
   only ever render for a match m.penales is truthy for. */
.partido-marcador-penales, .partido-marcador-default { text-align: center; color: var(--muted); font-size: 0.8rem; margin-top: -1.25rem; margin-bottom: 1.25rem; }
.marcador-penales { color: var(--muted); font-weight: 400; font-size: 0.8em; }

/* Próximo Partido's plain "ESTUARDOS FC / vs / RIVAL" centered block —
   no score yet, so no colored bands; the rival's kit color (if set)
   shows as a pill behind their name instead. */
.partido-vs { text-align: center; margin-bottom: 0.5rem; }
.partido-vs-equipo { display: block; font-weight: 700; text-transform: uppercase; font-size: 1.5rem; letter-spacing: 0.02em; color: var(--white); }
.partido-vs-sep { display: block; color: var(--muted); font-weight: 700; text-transform: uppercase; letter-spacing: 0.15em; font-size: 0.8rem; margin: 0.5rem 0; }

/* Below the scoreboard: left half the lineup (Titulares/Suplentes card
   grids), right half the scoring info (Goles/Asistencias — plain
   comma-separated text lists, no photos needed there per Daniel). */
.partido-columnas { display: flex; gap: 2rem; flex-wrap: wrap; }
.partido-col { flex: 1.15 1 300px; min-width: 0; }
.partido-col h4 { margin: 0 0 0.75rem; color: var(--accent-light); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.08em; }
.partido-col h4:not(:first-child) { margin-top: 1.25rem; }
.partido-lista { color: var(--white); font-size: 1.15rem; margin: 0; line-height: 1.5; }

/* "Ver todos los resultados" — Último Partido's own link into the
   Equipo tab for this season (see renderUltimoPartido_). Right-aligned
   under the two columns, small and secondary — this card's own content
   is still the main event, this is just a way out of it. */
.partido-ver-todos {
  display: block;
  text-align: right;
  margin-top: 1.25rem;
  color: var(--accent-light);
  font-size: 0.85rem;
  font-weight: 700;
  text-decoration: none;
}
.partido-ver-todos:hover { text-decoration: underline; }

/* Grid (not flex-wrap) - see .insignias-grid above for why: fills the
   row edge-to-edge instead of leaving wasted space when a lineup or
   photo row does not happen to fill an exact number of fixed-width
   cards. */
.partido-jugadores-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 0.75rem; }
/* Replaces the old "Titulares"/"Suplentes" h4 headings (Daniel's
   call) - a plain thin rule between the two grids instead. Only
   rendered between them when both are non-empty (see app.js). */
.jugadores-divider { border: none; border-top: 1px solid var(--border); margin: 1rem 0; }
.jugador-card { text-align: center; }
/* No border/radius here — the images/fotos-perfiles photos already have
   their own border baked into the asset, so adding a second one on
   top looked doubled/odd. No fixed height/object-fit:cover either —
   images/fotos-perfiles isn't square (300x360), so cropping it into a 76x76
   box cut the top/bottom edge of that baked-in border off. Scaled to
   the card's width, full image, natural aspect ratio, nothing cropped. */
.jugador-card img { width: 100%; height: auto; display: block; }
/* Same aspect ratio as the real images/fotos-perfiles photos (300x360) so a
   placeholder tile lines up with real photo tiles in the same grid. */
.jugador-card-placeholder {
  width: 100%; aspect-ratio: 5 / 6; border-radius: 8px; background: var(--grey-cell);
  display: flex; align-items: center; justify-content: center;
  color: var(--muted); font-size: 0.6rem; padding: 0.3rem; text-align: center;
}
.jugador-card-nombre { font-size: 0.72rem; font-weight: 700; color: var(--white); margin-top: 0.35rem; line-height: 1.2; }
/* Position pill — same POSITION_COLORS_ palette (app.js) the PI
   detailed leaderboard view already uses, reused here instead of a
   second color scheme for the same five position codes. Overlaid on
   the photo's bottom-left corner (moved here from top-left, Daniel's
   call) — captain owns top-right, goal/assist badges own bottom-
   right — same cutout-ring border treatment as those two so all
   three corner badges read as one family. Lives inside
   .jugador-card-photo-wrap (position: relative) in the markup, same
   as the other two. */
.jugador-card-pos {
  position: absolute; bottom: -4px; left: -4px;
  display: inline-block; padding: 0.1rem 0.4rem;
  border-radius: 6px; font-size: 0.62rem; font-weight: 700;
  background: var(--grey-cell); color: var(--muted);
  border: 2px solid var(--bg);
}

/* Equipo tab — Alineaciones (TxJ starter lineups, Stage 7). One block
   per match, its own header (jornada/rival/formación) above a
   partido-jugadores-grid of jugador-cards — reuses that same card/grid
   look (and .jugador-card-pos's POSITION_COLORS_ palette) rather than a
   third visual language for "a grid of players" on this site. */
/* Resultados/Alineaciones toggle — the standings table above and the
   Resultados table/Alineaciones list below both come right up to this
   element's own edges (no built-in spacing of their own), so this
   needed its own top/bottom margin — .stat-selector itself has none
   (the Historial tab's stat selector always sits inside a .controls
   wrapper, which supplies that spacing there instead). */
#temporada-view-selector { margin: 1.25rem 0; }
.alineacion-match { padding-bottom: 1.25rem; margin-bottom: 1.25rem; border-bottom: 1px solid var(--border); }
.alineacion-match:last-child { border-bottom: none; margin-bottom: 0; }
.alineacion-match-header {
  display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.6rem;
  font-weight: 700; flex-wrap: wrap;
}
.alineacion-match-header .jornada-cell { color: var(--accent-light); }
.alineacion-formacion { font-size: 0.8rem; font-weight: 400; color: var(--muted); }
.alineacion-marcador {
  font-weight: 700; font-size: 0.85rem; padding: 0.15rem 0.55rem;
  border-radius: 6px; color: #fff;
}
.alineacion-marcador.result-chip-g { background: var(--good); }
.alineacion-marcador.result-chip-p { background: var(--bad); }
.alineacion-marcador.result-chip-e { background: var(--draw); color: var(--black); }
.alineacion-marcador.result-chip-ex { background: var(--draw-pk); color: var(--black); }
.alineacion-marcador.result-chip-unknown { background: var(--unknown-score); color: var(--black); }
/* Wraps the photo/placeholder only (not the name/pos pill below it) so
   the captain badge can be positioned absolutely against just the
   image, not the whole card. */
.jugador-card-photo-wrap { position: relative; }
/* Captain badge — a small "C" pill overlapping the photo's corner, in
   the CAPTAIN_COLOR_ reserved for this since the PI position palette
   was introduced (app.js) and unused until now. A solid --bg border
   acts as a cutout ring so the badge stays legible against any photo,
   not just light or dark ones. */
.jugador-card-capitan {
  position: absolute; top: -4px; right: -4px; width: 20px; height: 20px;
  border-radius: 50%; display: flex; align-items: center; justify-content: center;
  font-size: 0.7rem; font-weight: 800; border: 2px solid var(--bg);
}

/* Último Partido — per-card goal/assist badges (Stage 7 extension),
   replacing the old separate Goles/Asistencias text lists. The ball
   icon badge and the "A" badge get their own tint (goal green-ish,
   assist blue-ish) so the two read apart from each other and from
   the neutral position pill in the opposite corner. */
/* Overlaid on the photo's bottom-right corner (moved here from
   bottom-left so the position pill could take that corner instead,
   Daniel's call), stacked one per row - same corner-badge treatment
   as .jugador-card-capitan (top-right), a border acting as a cutout
   ring so each stays legible against any photo. Goal badge on top,
   assist badge below when both are present. Border is --accent-light
   (Stage 9 color-fix pass) — it used to be --bg, which on Inicio (page
   background is also --bg) meant the ring just blended invisibly into
   the surrounding page instead of reading as a deliberate ring; the
   match-sheet page overrides this to the theme's own Acento already
   (below), so this base rule only ever shows on Inicio/unthemed. */
.jugador-card-badges {
  position: absolute; bottom: -4px; right: -4px;
  display: flex; flex-direction: column; gap: 2px; align-items: flex-end;
}
.jugador-card-badge {
  display: inline-flex; align-items: center; gap: 0.15rem;
  padding: 0.12rem 0.4rem; border-radius: 6px; font-size: 0.68rem; font-weight: 700;
  border: 2px solid var(--accent-light);
}
/* Ball icon is a CSS mask of Daniel's PNG (Stage 9 color-fix pass), not
   a plain <img> — same reasoning as the pitch outline: a mask lets the
   match-sheet page recolor it per era (below); a raw <img>'s own pixels
   can't be recolored by CSS at all. Raster mask-image is alpha-based by
   default in every real browser, so this just reuses the icon's own
   transparent-background shape. Base/unthemed color is plain white,
   matching the original <img> asset's own (already-white) pixels. */
.jugador-card-badge-balon {
  display: block; width: 11px; height: 11px;
  background-color: #ffffff;
  -webkit-mask-image: url(images/partidos/balon-icono.png);
  mask-image: url(images/partidos/balon-icono.png);
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
}
.jugador-card-badge-gol { background: var(--main); color: #ffffff; }
.jugador-card-badge-ast { background: var(--main); color: #ffffff; }
.jugador-card-badge-count { font-size: 0.6rem; }

/* Último Partido — starting-formation pitch (Stage 7 extension), the
   card's right column when there's a real lineup to show. Vertical
   orientation (goalkeeper at the bottom, forwards at the top) — see
   canchaSvgHtml_'s own doc comment (app.js) for how player markers are
   positioned. */
/* Gets more of the row's width than its Titulares/Suplentes sibling —
   the pitch reads poorly cramped down to card-sized, so this column is
   allowed to grow past an even 50/50 split. */
.partido-col-cancha { display: flex; justify-content: center; align-items: flex-start; flex: 0.9 1 260px; }

/* Standalone match-sheet page (Stage 9 revision) - a home-page-style
   two-column row: the compact game-data card on the left (narrower,
   same width cap as .inicio-side), the score/lineup card on the right
   (wider, same proportions as #ultimo-partido-card). */
/* Page-level title (season/tournament code + jornada) sitting above
   the grid, bigger than any of the card-level titles below it. */
.partido-encabezado {
  margin: 0 0 1.5rem;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent-light);
  font-size: 1.6rem;
}
/* Jornada part of the header (e.g. J21 in SOL29 J21) stays plain white, distinct from the torneo code's accent color. */
.partido-encabezado-jornada { color: var(--white); }
.partido-grid { display: flex; align-items: flex-start; gap: 2rem; }
/* Marcador (score+lineup) card on the left, same width as
   #ultimo-partido-card; game-data card on the right, same width cap
   as .inicio-side -- the same left/right split Inicio itself uses,
   so both cards size/stack identically on mobile too. */
.partido-marcador-card { flex: 1 1 480px; min-width: 0; }
.partido-datos-card { flex: 1 1 320px; max-width: 380px; min-width: 0; }
/* Stacked one per row (Daniel's call - plenty of vertical room here),
   left-aligned rather than the centered/side-by-side layout this
   started with. */
.partido-datos-row { display: flex; flex-direction: column; gap: 1.5rem; }
.partido-dato { display: flex; flex-direction: column; gap: 0.35rem; text-align: left; }
/* Goles Adicionales (Stage 9) — a lone .partido-dato block reused
   inside the marcador card itself (partidoColumnasHtml_), below the
   last row of player photos, rather than the datos-card's own stacked
   .partido-datos-row context — needs its own top margin since there's
   no row/divider giving it that spacing here. */
.partido-goles-adicionales { margin-top: 1rem; }
.partido-dato-titulo { color: var(--accent-light); font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; }
.partido-dato-valor { color: var(--white); font-size: 1.1rem; font-weight: 700; }
@media (max-width: 640px) {
  .partido-grid { flex-direction: column; }
  /* At least 3 photos per row here too, same as Plantel's grid --
     placed after .partido-jugadores-grid's own base rule (above, in
     the stylesheet) so this actually wins the cascade; the same
     override used to sit earlier in the file, before that base rule,
     where it was silently losing to it. */
  .partido-jugadores-grid { grid-template-columns: repeat(3, 1fr); }
  /* flex-basis is a WIDTH hint in the normal row layout above, but
     once .partido-grid flips to flex-direction: column here, that
     same basis becomes a HEIGHT floor instead -- .partido-datos-card's
     320px floor left a lot of dead space below its short Fecha/Hora/
     Cancha content (Daniel's report). Reset both cards to size purely
     by their own content on mobile, same as Inicio's cards effectively
     already do (their content is tall enough that the same latent
     issue never shows). */
  .partido-marcador-card, .partido-datos-card { flex-basis: auto; max-width: none; }
}

/* Era-accurate match-sheet theming (Stage 9) — app.js's
   aplicarTemaPartido_ sets --tema-* as custom properties on <body>
   itself for whichever era the page is currently showing; every rule
   below just reads them with the ORIGINAL static value as its
   fallback, so an era with no theme (or a data.json from before this
   feature existed) renders pixel-identical to before. Most rules are
   still scoped under #partido-content so Inicio's Último/Próximo
   Partido cards — which reuse these same .partido-card/
   .partido-banda-local/.cancha-jugador classes — are never touched;
   only the standalone match-sheet page changes by era. */
/* The background specifically is scoped by body[data-section="partido"]
   instead (that attribute is set by activateSection_ on every nav —
   app.js) rather than #partido-content or #section-partido: Daniel's
   explicit ask is that EVERY part of the page below the black nav bar
   changes color on this page, edge to edge — not just the two cards,
   and not just #section-partido's own box, which sits inset inside
   <main>'s centered max-width column and never reaches the viewport
   edges. <body> is the one element that actually spans full-bleed. */
body[data-section="partido"] {
  background: var(--tema-fondo, var(--bg));
}
/* Volver + the prev/next arrows sit directly on that full-bleed
   background now, so their border/text (fixed white before theming
   existed) need the same contrast-aware pick everything else on this
   page uses — a light Fondo would otherwise make them nearly invisible,
   exactly like the border-color problem above. Scoped by the same
   data-section attribute (not just .partido-nav-btn/.partido-topbar
   .perfil-volver's own specificity) so leftover --tema-* values never
   bleed into the Perfil page's OWN (unthemed) Volver button, which
   reuses the plain .perfil-volver class outside this page. */
body[data-section="partido"] .partido-topbar .perfil-volver,
body[data-section="partido"] .partido-nav-btn {
  border-color: var(--tema-acento, var(--white));
  color: var(--tema-texto-fondo, var(--white));
}
/* The site-wide footer sits directly on <body> too (a sibling of
   <main>, below it) — same full-bleed background as everything else
   on this page, so its own fixed-color text needs the same treatment.
   .social-label ("@estuardosfc", normally --white per its own rule
   further down) is the one that actually goes invisible on a light
   Fondo; .updated ("Actualizado: ...", inherited from .site-footer's
   own --muted-alt) is included too since that muted tone was tuned
   for the static dark page, not an arbitrary themed one. The icons
   themselves (.social-links) are untouched — Daniel's explicit call
   from the very first version of this feature. */
body[data-section="partido"] .site-footer {
  color: var(--tema-texto-fondo, var(--muted-alt));
}
body[data-section="partido"] .social-label {
  color: var(--tema-texto-fondo, var(--white));
}
#partido-content .partido-card {
  background: var(--tema-fondo, var(--bg));
  /* A darkened Acento (--tema-acento-oscuro, computed in app.js —
     mixed 35% toward black), not the raw bright one — Daniel's ask,
     matching Inicio's own unthemed card border (--main: muted, "blend
     into the page" rather than a bright outline). Falls back to that
     same --main when unthemed, not --accent-light, for the identical
     reason. (Principal alone, the very first version of this rule, was
     dropped even earlier — a theme with a white/near-white Principal
     made the border nearly invisible against the also-themed Fondo.) */
  border-color: var(--tema-acento-oscuro, var(--main));
}
#partido-content .partido-encabezado { color: var(--tema-acento, var(--accent-light)); }
#partido-content .partido-encabezado-jornada { color: var(--tema-texto-fondo, var(--white)); }
#partido-content .partido-col h4 { color: var(--tema-acento, var(--accent-light)); }
/* Shared theming scope (this pass) — Daniel's ask: the score band,
   player photos, and field section stay VISUALLY IDENTICAL between the
   standalone match-sheet page (#partido-content) and Inicio's Último
   Partido card (#ultimo-partido-card), not just similar — any themed
   rule for those three areas is written once, targeting both ancestors
   together, so a future edit to one can't silently drift from the
   other. Card background/border, the season/jornada title, and the
   Fecha/Hora/Cancha info card (which doesn't exist on Inicio at all)
   stay #partido-content-only — Daniel's explicit prior call (Stage 9)
   that Inicio's card should "blend into the page" rather than stand
   out, unaffected by this pass. .partido-dato-titulo/-valor ARE in
   this shared list even though the Fecha/Hora/Cancha card isn't,
   because Goles Adicionales (a later pass) reuses those same two
   classes for its own title/value line, and that one DOES render on
   Inicio (it's part of the shared partidoColumnasHtml_ output, same as
   the photo grid it sits under). aplicarTemaPartido_ is called on both
   #ultimo-partido-card (renderUltimoPartido_) and document.body
   (renderPartido_, per Stage 9) — see app.js — so the same --tema-*
   values reach whichever ancestor is in play. */
#partido-content .partido-dato-titulo,
#ultimo-partido-card .partido-dato-titulo { color: var(--tema-acento, var(--accent-light)); }
#partido-content .partido-dato-valor,
#ultimo-partido-card .partido-dato-valor { color: var(--tema-texto-fondo, var(--white)); }
#partido-content .partido-banda-local,
#ultimo-partido-card .partido-banda-local {
  background: var(--tema-principal, var(--main));
  /* Daniel's explicit call (same per-column-mapping convention as the
     field markers, see below): this bar always pairs Principal with
     Dorsales specifically — not a WCAG contrast pick against Principal
     (--tema-texto-principal, still used elsewhere on this page, e.g.
     the goal/assist badges) — so it stays fixed regardless of how
     Principal/Dorsales's own contrast happens to work out for a given
     theme. */
  color: var(--tema-dorsales, var(--white));
}
/* Field marker colors (this pass) — each of the three visual parts of
   a marker pill now maps to its own dedicated Temas column, rather
   than the earlier all-white ring/text convention: outfield markers
   use Principal (background) / Secundario (border) / Dorsales (number
   text); the goalkeeper marker uses its own parallel trio, Portero /
   Portero Sec / Portero Dor. This supersedes the previous "marker text
   and ring are always fixed white" rule (see the base rules below,
   which still carry the ORIGINAL static colors as fallbacks for an era
   with no theme) — Daniel's explicit per-column mapping this time, not
   a contrast computation. */
#partido-content .cancha-jugador rect,
#ultimo-partido-card .cancha-jugador rect {
  fill: var(--tema-principal, var(--main));
  stroke: var(--tema-secundario, #ffffff);
}
#partido-content .cancha-jugador text,
#ultimo-partido-card .cancha-jugador text { fill: var(--tema-dorsales, #ffffff); }
#partido-content .cancha-jugador-por rect,
#ultimo-partido-card .cancha-jugador-por rect {
  fill: var(--tema-portero, var(--portero));
  stroke: var(--tema-portero-sec, #ffffff);
}
#partido-content .cancha-jugador-por text,
#ultimo-partido-card .cancha-jugador-por text { fill: var(--tema-portero-dor, #ffffff); }
/* Field outline (see canchaSvgHtml_'s alpha-masked <rect>, right below
   in the CSS source) and the Titulares/Suplentes name labels, which
   sit directly on the now-themed card background above and need the
   same background-aware contrast pick as .partido-dato-valor rather
   than the fixed white they used before theming existed. */
#partido-content .cancha-lineas-fill,
#ultimo-partido-card .cancha-lineas-fill { fill: var(--tema-acento, var(--accent-light)); }
#partido-content .jugador-card-nombre,
#ultimo-partido-card .jugador-card-nombre { color: var(--tema-texto-fondo, var(--white)); }
/* Goles/asistencias count pills (UPDATED: Secundario background, Acento
   border, text/icon = --tema-texto-secundario; older wording below says
   Principal and is superseded). Originally: Principal,
   same as the field diagram's own player markers (Daniel's call: only
   the card BORDER and the Volver/nav-arrow controls needed the Acento
   swap, not these — Principal is the right "brand" color here). The
   ball icon (.jugador-card-badge-balon, a CSS mask of Daniel's PNG
   rather than a plain <img> — see ICON_BALON_/app.js) and the assist
   "A" + the count number (plain text, colored via this rule's own
   `color`) all pick up the same contrast color computed against
   Principal specifically (--tema-texto-principal). */
#partido-content .jugador-card-badge-gol,
#partido-content .jugador-card-badge-ast,
#ultimo-partido-card .jugador-card-badge-gol,
#ultimo-partido-card .jugador-card-badge-ast {
  background: var(--tema-secundario, var(--main));
  color: var(--tema-texto-secundario, #ffffff);
}
/* The pill's own cutout-ring border (.jugador-card-badge's base rule,
   above) was still hardcoded to the site's static --bg (a dark teal) —
   visibly wrong once the page background itself is themed, per
   Daniel's report. Acento, per his call. */
#partido-content .jugador-card-badge,
#ultimo-partido-card .jugador-card-badge {
  border-color: var(--tema-acento, var(--bg));
}
#partido-content .jugador-card-badge-balon,
#ultimo-partido-card .jugador-card-badge-balon {
  background-color: var(--tema-texto-secundario, #ffffff);
}

/* Field art is Daniel's own line drawing (see canchaSvgHtml_'s doc
   comment, app.js) — the SVG here just positions player markers over
   it at the right viewBox coordinates. Sized to fill essentially the
   whole column (not capped down to a small fixed width) so the pitch
   and its dorsal numbers stay legible. */
.cancha-svg { width: 100%; max-width: 480px; height: auto; }
/* The pitch outline itself is drawn from an alpha mask of Daniel's PNG
   (canchaSvgHtml_, app.js) rather than the raw <image>, specifically so
   it can be recolored per era below without needing a separate PNG per
   theme — the fill is just the line art's own shape. Base rule here is
   the original static teal (same hex as --accent-light); the scoped
   #partido-content override above repaints it to each era's Acento. */
.cancha-lineas-fill { fill: var(--accent-light); }
.cancha-jugador rect { fill: var(--main); stroke: #ffffff; stroke-width: 3; }
.cancha-jugador text { fill: #ffffff; font-size: 30px; font-weight: 800; text-anchor: middle; }
/* Goalkeeper marker — the site-wide --portero var (current era's kit
   color), same value the old inline style used to set per-marker in
   app.js before this rule replaced it, now a plain class override so
   the match-sheet page's own era-themed rule below (higher specificity,
   #partido-content ...) can win there without an inline-style fight. */
.cancha-jugador-por rect { fill: var(--portero); }

/* Historia — all four sections render at once now (no tab-switching:
   Daniel wants the whole page scannable on load), so each one is just a
   titled block stacked vertically with breathing room between them. */
.historia-block { margin-bottom: 2.5rem; }
.historia-block:last-child { margin-bottom: 0; }
.historia-block h3 { margin-top: 0; }

/* Historia — ¿Quiénes somos? placeholder copy. */
.placeholder-text { color: var(--muted-alt); font-size: 0.95rem; max-width: 640px; }

/* Historia — Línea de Tiempo. A plain vertical rail (border-left) with
   a dot per event, same accent-light/muted color language as the rest
   of the site rather than a new palette. */
.timeline { list-style: none; margin: 0; padding: 0; border-left: 3px solid var(--border); }
.timeline li { position: relative; padding: 0 0 1.5rem 1.5rem; }
.timeline li:last-child { padding-bottom: 0; }
.timeline li::before {
  content: '';
  position: absolute;
  left: -9px;
  top: 0.2rem;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent-light);
  border: 2px solid var(--bg);
}
.timeline-date { display: block; color: var(--accent-light); font-weight: 700; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.04em; }
.timeline-desc { color: var(--white); margin: 0.2rem 0 0; }
/* Entries linked to a match sheet (linkHistoriaEventos_): whole entry is clickable. */
.timeline li.timeline-link { cursor: pointer; }
.timeline li.timeline-link .timeline-date::after { content: ' \2192'; opacity: 0.6; }
.timeline li.timeline-link:hover .timeline-date,
.timeline li.timeline-link:focus-visible .timeline-date { text-decoration: underline; }
.timeline li.timeline-link:hover .timeline-date::after { opacity: 1; }
.timeline li.timeline-link:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 4px; border-radius: 4px; }

/* Historia — Escudos / Jerseys. Same card language as .insignia-card
   (badge icon + label underneath) but sized for a crest/jersey graphic
   rather than a small achievement icon, and with an optional subtitle
   line (Jerseys' brand name) that Escudos simply never fills in. */
/* 3 columns (not 4) so each crest/jersey graphic renders bigger and
   more legible — card width comes from the grid track (1fr), not a
   fixed px value, so it scales with whatever main's max-width is. */
.historia-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; }
.historia-card {
  text-align: center;
  background: var(--grey-header);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 0.75rem;
}
.historia-card img { width: 100%; height: auto; display: block; border-radius: 8px; }
.historia-card-title { font-weight: 700; color: var(--white); font-size: 0.85rem; margin-top: 0.5rem; }
.historia-card-subtitle { color: var(--muted); font-size: 0.75rem; margin-top: 0.15rem; }
#jerseys-tipo-selector { margin-bottom: 1rem; }

/* Career stats — same table language as the Jugadores BALANCE view
   (#leaderboard-table.balance-mode): normal table font-size (no
   oversized-value treatment — that's only right for a single highlight
   row like #standings-table, and badly bloated a many-row table like
   this one), same padding, plain bold white values, thick black grid.
   No sticky columns needed (unlike the real BALANCE table) since this
   one is never wide enough to need horizontal scrolling in the first
   place — just Temporada + 4 stats. */
#perfil-stats-wrap { border: none; border-radius: 0; background: transparent; }
#perfil-stats-table th, #perfil-stats-table td {
  border: 2px solid var(--black);
  text-align: center;
  padding: 0.6rem 1.25rem;
}
#perfil-stats-table td { font-weight: 700; color: var(--white); }

h2 { margin-top: 0; }
h3 { color: var(--accent-light); font-size: 1.4rem; text-transform: uppercase; letter-spacing: 0.05em; margin: 2rem 0 0.75rem; font-weight: 700; }

/* Team stats — single-season standings snapshot. Same two-row table
   language as every other table on the site (grey header row, thick
   black grid) instead of the old rounded flex "card", which read as
   visually inconsistent and didn't adapt well to a phone screen. No
   color scale on the values — that only makes sense comparing across
   multiple rows (like the all-time balance table below it), and would
   be meaningless against a single season's own numbers. No sticky
   columns needed either: just 8 narrow numeric columns and one row,
   so it fits a phone screen without any scrolling — plain
   border-collapse: collapse (the site's default) is fine here, unlike
   the tables that need border-collapse: separate for their sticky
   columns. */
#standings-wrap { border: none; border-radius: 0; background: transparent; }
#standings-table th, #standings-table td {
  border: 2px solid var(--black);
  text-align: center;
  padding: 0.6rem 1.25rem;
}
/* Grouped like the real RES tab's "Torneo de Liga" box — [PJ PG PE PP]
   [GF GC DIF] [PTS] read as three clusters, not 8 uniform cells. Same
   "no divider within a pair" technique already used for dorsal/Jugador
   on the leaderboard: both cells on an internal boundary suppress
   their shared border (collapse only keeps a line if at least one side
   still specifies one), while the two real group boundaries — PP|GF
   and DIF|PTS — are left alone and keep their default 2px border. */
/* Clusters (RD added between PP and GF): [PJ PG PE PP RD] [GF GC DIF]
   [PTS] — columns 1-5, 6-8, 9. */
#standings-table td:nth-child(1), #standings-table th:nth-child(1),
#standings-table td:nth-child(6), #standings-table th:nth-child(6) {
  border-right: none;
}
#standings-table td:nth-child(2), #standings-table th:nth-child(2),
#standings-table td:nth-child(3), #standings-table th:nth-child(3),
#standings-table td:nth-child(4), #standings-table th:nth-child(4),
#standings-table td:nth-child(7), #standings-table th:nth-child(7) {
  border-left: none;
  border-right: none;
}
#standings-table td:nth-child(5), #standings-table th:nth-child(5),
#standings-table td:nth-child(8), #standings-table th:nth-child(8) {
  border-left: none;
}
#standings-table td { font-weight: 700; color: var(--white); font-size: 1.35rem; }

/* Column-title tooltips (th[data-tip]) — one shared floating element
   (#th-tip, built by setupTablaTooltips_ in app.js), position: fixed on
   <body> so no overflow:auto .table-wrap can clip it. Hover on desktop,
   tap/focus on touch. */
th[data-tip] { cursor: help; }
#th-tip {
  position: fixed;
  z-index: 1000;
  max-width: 14rem;
  padding: 0.4rem 0.65rem;
  border-radius: 6px;
  background: var(--black);
  color: var(--white);
  border: 1px solid var(--border);
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1.25;
  pointer-events: none;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
}
#th-tip[hidden] { display: none; }

.table-wrap {
  overflow-x: auto;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
}
/* Compact mode (the Historial leaderboard's simple view): the wrapper
   hugs the table's own content width instead of stretching to fill
   the page, so a short 4-column table doesn't get spread out with
   large gaps between columns — but stays centered on the page rather
   than sticking to the left edge.
   Uses width: fit-content (a normal block box), NOT display: table —
   display: table was the previous approach and caused two separate
   real bugs: (1) on a phone, a display:table box with width:auto
   sizes itself to fit (nowrap) content even beyond its containing
   block, dragging the WHOLE WRAPPER — and with it the whole page,
   since nothing above it clipped horizontal overflow — wider than the
   viewport, instead of scrolling internally like it should; (2) on a
   wide many-column detail table, that same auto-sizing-beyond-parent
   behavior on a table-DISPLAY box interacted unreliably with its own
   overflow-x: auto, in some cases preventing the internal scrollbar
   from working at all — silently locking out any columns past the
   visible edge, worse on both counts than the box-drag bug. A plain
   block box sized via fit-content (capped by max-width: 100%) doesn't
   have either issue: overflow-x: auto on a normal block container is
   the most well-supported scroll pattern in CSS, no table-layout
   sizing ambiguity involved. */
.table-wrap.compact { display: block; width: fit-content; max-width: 100%; margin: 0 auto; }

/* Goals charts (Equipo tab: GF/GC per season, and per season, per
   jornada) — same card container language as .table-wrap, but with its
   own padding since a canvas has no built-in cell padding. Chart.js is
   configured with maintainAspectRatio: false and fills its container,
   so this fixed height is what actually controls the chart's height —
   position: relative is required for Chart.js's own resize handling. */
.chart-wrap {
  background: var(--grey-header);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1.25rem 1rem 1rem;
  height: 280px;
  position: relative;
}
.table-wrap.compact table { width: auto; }
/* The leaderboard table already carries its own thick black grid —
   the wrap's soft grey card border/radius on top of that just reads as
   a stray outline, so it's dropped for this one table specifically. */
#leaderboard-wrap { border: none; border-radius: 0; background: transparent; }

/* Récords tab — Líderes Históricos: one column per stat (GOL/AST/PA/PI),
   short top-5 lists. A plain 2-column grid (not flex-wrap) so it stays
   visually even regardless of how many cards there are — flex-wrap with
   a min-width let 3 fit on one row and stranded the 4th alone on its
   own, which read as lopsided. Same grid reused for .records-highlights-
   grid below, now that it holds up to 4 cards per group too. */
.records-leaders-grid, .records-highlights-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem;
  margin-bottom: 1.5rem;
}
.records-leaders-grid { margin-bottom: 2.5rem; }
.record-leader-col {
  background: var(--grey-header);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1rem 1.25rem;
}
.record-leader-col h4 { margin: 0 0 0.15rem; color: var(--accent-light); font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.06em; }
/* Era-range info icon (Stage 9) - replaces the old always-visible
   .record-leader-range subtitle line site-wide. One small circled-i
   button sitting right after a stat title's text, everywhere a stat
   title appears (Lideres Historicos, Individuales' own #stat-title,
   the Records tab's per-stat cards, Perfil's own Records section) -
   see statRangeBtnHtml_/hydrateStatRangeIcons_ (app.js). Desktop
   hover shows the popover via plain :hover, no JS needed; .open
   (toggled by setupStatRangeIcons_'s delegated click handler) is the
   tap-to-pin-open equivalent for touch, where :hover doesn't fire. */
.stat-range-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1em;
  height: 1em;
  margin-left: 0.4em;
  padding: 0;
  border: none;
  background: none;
  color: var(--muted);
  cursor: pointer;
  vertical-align: middle;
  flex-shrink: 0;
}
.stat-range-btn svg { width: 100%; height: 100%; display: block; }
.stat-range-btn:hover, .stat-range-btn:focus-visible, .stat-range-btn.open { color: var(--accent-light); }
.stat-range-popover {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-top: 0.4rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.4rem 0.6rem;
  color: var(--white);
  font-size: 0.75rem;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  white-space: normal;
  width: max-content;
  max-width: 200px;
  text-align: center;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.12s ease;
  z-index: 20;
}
.stat-range-btn:hover .stat-range-popover,
.stat-range-btn:focus-visible .stat-range-popover,
.stat-range-btn.open .stat-range-popover {
  opacity: 1;
  visibility: visible;
}
.record-leader-row {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.3rem 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.9rem;
}
.record-leader-row:last-child { border-bottom: none; }
.record-leader-rank { color: var(--muted); font-weight: 700; width: 1.2rem; flex-shrink: 0; }
.record-leader-nombre { flex: 1; color: var(--white); }
.record-leader-total { color: var(--accent-light); font-weight: 700; }

/* Récords tab — "Individuales"/"Equipo" group headers, one step down
   from the tab's own h3 (which already applies to "Récords" itself). */
.records-subheading { margin: 1.5rem 0 0.75rem; color: var(--muted-alt); font-size: 0.95rem; text-transform: uppercase; letter-spacing: 0.05em; }
.records-subheading:first-child { margin-top: 0; }

/* Récords tab — the 8 highlight cards (goals/assists per match/season,
   individual and team, plus the two streaks). Same card language as
   .record-leader-col above, just a bigger headline number since each
   card only has one thing to say. */
.record-card {
  background: var(--grey-header);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1.25rem 1.5rem;
}
.record-card h5 { margin: 0 0 0.75rem; color: var(--accent-light); font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.06em; }
.record-highlight-value { font-size: 2.5rem; font-weight: 700; color: var(--white); line-height: 1; margin-bottom: 0.75rem; }
.record-highlight-entry { font-size: 0.9rem; color: var(--white); padding: 0.35rem 0; border-top: 1px solid var(--border); }
.record-highlight-entry:first-of-type { border-top: none; }
.record-highlight-entry .record-highlight-meta { display: block; color: var(--muted); font-size: 0.8rem; margin-top: 0.1rem; }

table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
/* These three tables use border-collapse: separate instead — required
   for the sticky frozen columns further down to render their borders
   reliably. A collapsed border is really ONE shared line computed
   between two adjacent cells based on the table's static layout, and
   that computation doesn't reliably follow a cell once it's
   repositioned by sticky during horizontal-scroll compositing — that's
   what caused the frozen columns' grid lines to flicker/vanish under
   scroll (a box-shadow reinforcement was tried first and reverted: it
   didn't fix the flicker and made the static/unscrolled borders read
   as uneven/doubled). Separate borders are just normal per-element
   borders with no cross-cell sharing, immune to that. border-spacing:
   0 keeps cells flush (no visible gap between them), and — since
   separate borders don't merge/collapse away doubled thickness the
   way collapsed ones do — each cell below is deliberately given a
   border on only 2 of its 4 sides (right + bottom); the header row
   additionally draws a top border and the first column additionally
   draws a left border, so the full grid reconstructs with exactly one
   border's worth of thickness at every shared edge, never two. */
#matches-table, #leaderboard-table, #team-balance-table, #otras-rivales-table, #otras-horarios-table, #perfil-stat-detail-table {
  border-collapse: separate;
  border-spacing: 0;
}

/* Results table — every column centered except Rival, which stays
   left-aligned since it's the one variable-length text field. Column
   order (Jornada, R, Marc., Rival, Fecha, Hora, Cancha) puts the most
   important data first so it's visible without scrolling; Rival is
   4th, not last, hence the :not(:nth-child(4)) rather than
   :not(:last-child). GF/GC merged into one "Marc." column (3rd,
   "3 - 2" style) picks up centering for free from this same rule. */
#matches-table th:not(:nth-child(4)), #matches-table td:not(:nth-child(4)) {
  text-align: center;
}
/* Cancha column — narrow, just a 1-digit court number. Now the LAST
   column (moved from 2nd) as part of the reorder above. */
#matches-table th:last-child, #matches-table td:last-child {
  width: 1%; padding-left: 0.5rem; padding-right: 0.5rem;
}
/* Full cell grid, not just a bottom border between rows. Black rather
   than the usual --border grey — several cells in this table carry
   their own colored backgrounds (Jornada/Cancha/Hora/Rival), and the
   subtler grey border read as invisible against grey-on-grey cells.
   Right + bottom on every cell, plus top on the header row and left on
   the first column — see the border-collapse: separate comment above
   for why it's split this way instead of a plain 4-side border. */
#matches-table th, #matches-table td {
  border-right: 2px solid var(--black);
  border-bottom: 2px solid var(--black);
}
#matches-table thead th { border-top: 2px solid var(--black); }
#matches-table th:first-child, #matches-table td:first-child { border-left: 2px solid var(--black); }
/* Rival name — bold, matching the kit-color treatment. Now the 4th
   column (moved from last, then from 5th to 4th once GF/GC merged into
   one Marc. column). */
#matches-table td:nth-child(4) { font-weight: 700; }
/* Jornada column — the main dark grey (--grey-header, same as the
   column headers) with light-accent text, rather than a fixed accent
   background. Also the table's one frozen/sticky column on
   narrow screens: it's the only column that identifies which match a
   scrolled-right row belongs to, so it stays pinned to the left edge
   while the rest of the row scrolls under it — it's still the FIRST
   column after the reorder above, so this sticky behavior is
   unchanged. Only one column needs freezing here (unlike the player
   leaderboard's 2-3), so no left-offset math is needed — it's always
   left: 0. */
#matches-table td.jornada-cell { background: var(--grey-header); color: var(--accent-light); font-weight: 700; }
#matches-table th:first-child, #matches-table td:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
}
/* Result column — a thin solid-colored line instead of a G/E/P letter,
   same idea as the leaderboard's result-bar row. Fixed narrow width on
   both header and cell so the "R" heading doesn't force the column
   wider than the line itself needs to be. Now the 2nd column (moved
   from 5th) as part of the reorder above. */
#matches-table th:nth-child(2), #matches-table td:nth-child(2) {
  width: 22px;
  padding-left: 0.3rem;
  padding-right: 0.3rem;
}
#matches-table td.result-chip { padding: 0; }
.result-chip-g { background: var(--good); }
.result-chip-p { background: var(--bad); }
.result-chip-e { background: var(--draw); }
.result-chip-ex { background: var(--draw-pk); }
.result-chip-unknown { background: var(--unknown-score); }

/* Equipo tab — all-time balance table (one row per season). Same
   thick-black-grid convention as the leaderboard/Results tables; the
   soft grey card wrapper is dropped for the same reason it's dropped
   on #leaderboard-wrap — the table already carries its own border. */
#team-balance-wrap { border: none; border-radius: 0; background: transparent; }
/* Results table (Equipo tab) — same reasoning as #leaderboard-wrap:
   #matches-table already carries its own thick black grid, so the
   plain .table-wrap grey card border/radius on top of it just reads
   as a stray outline. */
#matches-wrap { border: none; border-radius: 0; background: transparent; }
/* Right + bottom on every cell, plus top on the header row and left on
   the first column — see the border-collapse: separate comment further
   up for why it's split this way instead of a plain 4-side border. */
#team-balance-table th, #team-balance-table td, #otras-rivales-table th, #otras-rivales-table td, #otras-horarios-table th, #otras-horarios-table td {
  border-right: 2px solid var(--black);
  border-bottom: 2px solid var(--black);
  text-align: center;
  padding: 0.6rem 1.25rem;
}
#team-balance-table thead th, #otras-rivales-table thead th, #otras-horarios-table thead th { border-top: 2px solid var(--black); }
/* Temporada column — the only text (not numeric-scale) column, so it
   stays left-aligned like Rival does on the Results table. Also the
   frozen/sticky column — the one thing that identifies which season a
   scrolled-right row belongs to, same reasoning as #matches-table's
   Jornada column above (only one column to freeze, so left is always
   0, no offset math needed). */
#team-balance-table th:first-child, #team-balance-table td:first-child, #otras-rivales-table th:first-child, #otras-rivales-table td:first-child, #otras-horarios-table th:first-child, #otras-horarios-table td:first-child {
  text-align: left;
  font-weight: 700;
  border-left: 2px solid var(--black);
  position: sticky;
  left: 0;
  z-index: 1;
}

/* Perfil GOL/AST/PA/PI per-game grid (Stage 9) — same table language
   and same one-frozen-column pattern as #team-balance-table just above
   (Temporada is the only column that identifies a scrolled-right row,
   so it stays pinned at left: 0, no offset math needed). Game columns
   get a narrower padding than Temporada/TOTAL — up to ~28 of them can
   be on screen at once, and they only ever hold a short value. */
#perfil-stat-detail-wrap { border: none; border-radius: 0; background: transparent; }
#perfil-stat-detail-table th, #perfil-stat-detail-table td {
  border-right: 2px solid var(--black);
  border-bottom: 2px solid var(--black);
  text-align: center;
}
#perfil-stat-detail-table thead th { border-top: 2px solid var(--black); }
#perfil-stat-detail-table th:first-child, #perfil-stat-detail-table td:first-child {
  text-align: left;
  font-weight: 700;
  padding: 0.6rem 1.25rem;
  border-left: 2px solid var(--black);
  position: sticky;
  left: 0;
  z-index: 1;
}
/* TOTAL — 2nd column (right after the frozen Temporada column), same
   position + same grey-to-accent scale styling (set inline by app.js,
   scaleColor_ against this player's own season totals) as every other
   stat table's own TOT column — not sticky itself, same as those. */
#perfil-stat-detail-table th:nth-child(2), #perfil-stat-detail-table td:nth-child(2) {
  padding: 0.4rem 0.5rem;
  width: 3.4rem;
  min-width: 3.4rem;
  max-width: 3.4rem;
}
/* Game columns (3rd onward) — as narrow as the content allows: a plain
   1-2 digit header, and a cell that's either a short number or (PI)
   just a color with no text at all — "width: 1%" is the standard
   shrink-to-content hint, backed by minimal padding so up to ~28 of
   them stay readable side by side without ballooning the table width. */
#perfil-stat-detail-table th:nth-child(n+3), #perfil-stat-detail-table td:nth-child(n+3) {
  padding: 0.4rem 0.1rem;
  width: 1.4rem;
  min-width: 1.4rem;
  max-width: 1.4rem;
}
/* A column beyond that season's own real game count (e.g. column 26 in
   a 23-game season) — a shade darker than the header grey, so it reads
   as "this game never happened" rather than a real blank/0 value. */
.off-game-cell { background: var(--grey-header-dark); }

th, td { padding: 0.55rem 0.75rem; text-align: left; white-space: nowrap; }
thead th { background: var(--grey-header); color: var(--muted); font-size: 0.75rem; text-transform: uppercase; border-bottom: 1px solid var(--border); }
tbody td { background: var(--grey-cell); }
tbody tr:not(:last-child) td { border-bottom: 1px solid var(--border); }
/* Hover targets the cells directly, not the <tr> — each td now paints
   its own opaque background, so a background set on the row itself
   would be completely covered and invisible.
   Wrapped in :where() so this rule's own specificity is just "td"
   (0,0,0,1) — any class-based color on a cell (.jornada-cell,
   .result-chip-g/p/e, .result-bar-g/p/e, the leaderboard's grey
   result-bar leading cells, etc.) naturally outranks it and stays
   correctly colored on hover instead of flashing to plain grey. Cells
   colored via inline style="" (the rank/total/matchday/PA/PI scales,
   set per-cell by app.js) were already immune to this either way,
   since inline styles beat any stylesheet rule regardless of
   specificity — this fix is for the CLASS-based colored cells, which
   without :where() lost to this rule purely on selector length. */
:where(tbody tr:hover) td { background: var(--grey-cell-hover); }

/* Leaderboard column sizing — rank, dorsal, and TOT columns narrower
   than the name column (which does the heavy lifting for readability)
   but with real breathing room, not crammed; all three centered. */
#leaderboard-table th, #leaderboard-table td { padding: 0.6rem 1.25rem; }
/* Every header centered, regardless of column. */
#leaderboard-table th { text-align: center; }
/* Body-cell centering — deliberately excludes the Jugador (name)
   column, which stays left-aligned like every other table's name
   column. In non-balance mode that's column 3, already left out below;
   in balance mode Jugador shifts to column 2, so that column is
   excluded here with :not(.balance-mode) instead of being listed
   unconditionally — otherwise this would center player names in
   BALANCE while every other view left-aligns them. */
#leaderboard-table:not(.balance-mode) td:first-child,
#leaderboard-table:not(.balance-mode):not(.sin-dorsal) td:nth-child(2),
#leaderboard-table td:nth-child(4),
#leaderboard-table.sin-dorsal td:nth-child(3),
#leaderboard-table td:last-child {
  text-align: center;
}
/* Rank column ("#") — narrow, just a 1-2 digit number. A declared FIXED
   width (not the usual "width: 1%" shrink-to-content hint) so it stays
   consistently narrow — though since these tables use table-layout:
   auto, this is only a strong hint, not a guarantee; the sticky
   columns' "left" offsets are measured from the ACTUAL rendered width
   at runtime (app.js's syncStickyOffsets_()), not assumed from this
   value, precisely because auto layout doesn't always honor it exactly
   (see the "Frozen leading columns" comment further down). */
#leaderboard-table th:first-child, #leaderboard-table td:first-child {
  width: 2.75rem;
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}
/* Detailed mode's match/era columns (5th onward) — much narrower
   padding than the 4 fixed columns, so 20+ numeric columns stay
   compact instead of each eating >2rem of horizontal padding alone. */
#leaderboard-table th:nth-child(n+5), #leaderboard-table td:nth-child(n+5) {
  padding: 0.5rem 0.6rem;
  text-align: center;
}
/* Match header cells wrap onto two lines (jornada code / rival, via
   jornadaHeaderHtml in app.js) instead of forcing the column wide
   enough to fit both on one line — the main lever on total table width. */
#leaderboard-table th:nth-child(n+5) {
  white-space: normal;
  line-height: 1.2;
}
/* Player name column — active/inactive color (set inline per row by
   app.js from the Jugadores tab's Activo flag), not the grey used by
   every other cell. Slightly wider than a plain content-fit column,
   and pulled in tight against the dorsal cell on the left (no divider
   between them) while keeping normal breathing room on the right. */
#leaderboard-table:not(.balance-mode):not(.sin-dorsal) th:nth-child(3), #leaderboard-table:not(.balance-mode):not(.sin-dorsal) td:nth-child(3) {
  min-width: 8rem;
}
#leaderboard-table:not(.balance-mode):not(.sin-dorsal) td:nth-child(3) {
  padding-left: 0.5rem;
  padding-right: 1.5rem;
}
/* No-dorsal layout (.sin-dorsal: all-time stat tables) — columns are
   # | Jugador | TOT | eras..., so Jugador is column 2 and the narrow
   era columns start at 4 instead of 5. */
#leaderboard-table.sin-dorsal th:nth-child(2), #leaderboard-table.sin-dorsal td:nth-child(2) { min-width: 8rem; }
#leaderboard-table.sin-dorsal td:nth-child(2) { padding-left: 0.75rem; padding-right: 1.5rem; }
#leaderboard-table.sin-dorsal th:nth-child(4), #leaderboard-table.sin-dorsal td:nth-child(4) {
  padding: 0.5rem 0.6rem;
  text-align: center;
}
#leaderboard-table.sin-dorsal th:nth-child(4) { white-space: normal; line-height: 1.2; }
/* Dorsal column — narrow (just enough for a 2-digit number); the
   active/inactive background is set inline per row, same as the name
   cell — the header stays the same grey as every other header. Also a
   declared fixed width, same reasoning/caveat as the rank column
   above — the actual sticky offset is measured, not assumed.
   Scoped away from balance-mode: without ":not(.balance-mode)" here,
   this rule's "width: 2.4rem" was the ONLY width declaration touching
   column 2 in balance mode too (dorsal shifts to column 1 there, so
   column 2 is Jugador) — the balance-mode-specific block further down
   only sets min-width for that column, which doesn't cancel out a
   competing width from a lower-specificity rule on a DIFFERENT
   property. That stray width hint was fighting the real content width,
   widening the visual gap between the dorsal and Jugador cells instead
   of the tight pairing every other table gets. */
#leaderboard-table:not(.balance-mode):not(.sin-dorsal) td:nth-child(2) {
  width: 2.4rem;
  padding-left: 0.4rem;
  padding-right: 0.4rem;
}
#leaderboard-table:not(.balance-mode):not(.sin-dorsal) th:nth-child(2) {
  width: 2.4rem;
  padding-left: 0.4rem;
  padding-right: 0.4rem;
}
/* Thick black grid lines, mirroring the real season-doc tables —
   overrides the thin bottom-only border used elsewhere. Rank/Total/
   matchday cell backgrounds are set inline per-cell by app.js's color
   scales, so they layer on top of this border grid untouched.
   Right + bottom on every cell, plus top on the header row and left on
   the first column — see the border-collapse: separate comment further
   up for why it's split this way instead of a plain 4-side border. */
#leaderboard-table th, #leaderboard-table td {
  border-right: 2px solid var(--black);
  border-bottom: 2px solid var(--black);
}
#leaderboard-table thead th { border-top: 2px solid var(--black); }
#leaderboard-table th:first-child, #leaderboard-table td:first-child { border-left: 2px solid var(--black); }
/* Dorsal and Jugador read as one visual unit — no divider between them.
   Scoped away from balance-mode, where column 3 is GOL, not Jugador —
   without this it would silently lose its left border too. Only the
   LEFT-hand cell of a shared edge needs to suppress its border in
   border-collapse: separate mode (there's no "merge and pick a
   winner" step like collapse had, so the right-hand cell simply never
   draws a left border of its own in this grid to begin with — nothing
   to separately suppress there). */
#leaderboard-table:not(.balance-mode):not(.sin-dorsal) th:nth-child(2), #leaderboard-table:not(.balance-mode):not(.sin-dorsal) td:nth-child(2) { border-right: none; }
/* The thin result-bar row needs no border overrides at all now — it's
   a normal body row, so it never gets a top border (only the header
   row does) and its own bottom border (from the base rule above) is
   what draws the line beneath it; vertical dividers come from the
   same column rules as every other row, including the dorsal/Jugador
   no-divider rule just above. (Previously this row explicitly zeroed
   its own top/bottom and borrowed collapsed borders from its
   neighbors — a collapse-specific trick that doesn't apply, or need
   to apply, under border-collapse: separate.) The 4 leading
   (non-match) cells get the header's dark-grey background instead of
   standing out as bare black gaps. */
#leaderboard-table td.result-bar:nth-child(-n+4) { background: var(--grey-header); }

/* BALANCE mode — no rank column, so dorsal/name shift one column left
   (1,2 instead of 2,3); the 4 stat columns start at 3, each centered
   with its own inline blue value-scale (app.js). Higher specificity
   than the plain #leaderboard-table rules above (id+class beats id
   alone), so these safely override the normal-mode column widths/
   borders without touching any other view. */
#leaderboard-table.balance-mode td:nth-child(1) {
  min-width: 8rem;
  width: auto;
  padding-left: 0.75rem;
  padding-right: 1.5rem;
  text-align: left;
}
#leaderboard-table.balance-mode th:nth-child(1) { min-width: 8rem; width: auto; padding-left: 0.75rem; padding-right: 1.5rem; }

/* Frozen leading columns — the identity of a row (dorsal + name, plus
   rank outside BALANCE mode) stays pinned to the left edge while
   stat/era/match columns scroll underneath, so you never lose track
   of which player a row belongs to on a narrow screen.
   Left offsets come from --sticky-left-2/--sticky-left-3, custom
   properties set on the table element by app.js's syncStickyOffsets_()
   after every render — NOT hardcoded rem guesses. These tables use
   table-layout: auto (so Jugador's name column can stay content-
   flexible), and auto layout only treats a cell's declared "width" as
   a hint, not a guarantee — the ACTUAL rendered width of the rank/
   dorsal columns can differ slightly by device/font, which is exactly
   what caused a visible gap between dorsal and Jugador on one phone
   despite looking correct on desktop with a hardcoded value. Measuring
   the real rendered width and writing it as a custom property is
   correct on every device, not just the one it happened to be tuned
   against. The rem fallback (before the var's first value) only
   matters for the instant before JS runs on first paint. z-index keeps
   these cells painted above the columns scrolling in behind them;
   every sticky cell already has an opaque background (the default
   grey tbody background, or an inline/class color set elsewhere), so
   nothing bleeds through. */
#leaderboard-table:not(.balance-mode) th:first-child, #leaderboard-table:not(.balance-mode) td:first-child {
  position: sticky;
  left: 0;
  z-index: 2;
}
#leaderboard-table:not(.balance-mode) th:nth-child(2), #leaderboard-table:not(.balance-mode) td:nth-child(2) {
  position: sticky;
  left: var(--sticky-left-2, 2.75rem);
  z-index: 2;
}
#leaderboard-table:not(.balance-mode):not(.sin-dorsal) th:nth-child(3), #leaderboard-table:not(.balance-mode):not(.sin-dorsal) td:nth-child(3) {
  position: sticky;
  left: var(--sticky-left-3, 5.15rem);
  z-index: 2;
}
#leaderboard-table.balance-mode th:nth-child(1), #leaderboard-table.balance-mode td:nth-child(1) {
  position: sticky;
  left: 0;
  z-index: 2;
}
#leaderboard-table.balance-mode th:nth-child(n+2),
#leaderboard-table.balance-mode td:nth-child(n+2) {
  text-align: center;
  padding: 0.6rem 1.25rem;
}

.detail-toggle {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--muted);
  font-size: 0.85rem;
  cursor: pointer;
  user-select: none;
}
.detail-toggle input { accent-color: var(--accent-light); width: 1.1rem; height: 1.1rem; cursor: pointer; }
.detail-toggle input:disabled { cursor: not-allowed; opacity: 0.4; }
.detail-toggle:has(input:disabled) { cursor: not-allowed; opacity: 0.5; }

.detail-message {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1rem;
  color: var(--muted);
  text-align: center;
}

/* Detailed leaderboard view (per-match or per-era columns) — the wrap
   goes full-width + scrollable instead of the compact/hugging layout
   used for the simple TOT-only table. */
.table-wrap:not(.compact) table { width: max-content; min-width: 100%; }

/* line-height/font-size: 0 — an empty <td> still gets a phantom inline
   content line-box sized by the inherited line-height (~20px here)
   even with padding removed; zeroing both collapses it to the
   explicit 4px height with nothing fighting it. */
.result-bar { height: 4px; padding: 0 !important; line-height: 0; font-size: 0; }
.result-bar span { display: block; height: 100%; }
.result-bar-g { background: var(--good); }
.result-bar-p { background: var(--bad); }
.result-bar-e { background: var(--draw); }
.result-bar-ex { background: var(--draw-pk); }
.result-bar-unknown { background: var(--unknown-score); }

.utility-row td { font-style: italic; color: var(--white); }

.val-strong { font-weight: 700; }
/* TOTAL row (#team-balance-table and #perfil-stats-table) — the main
   dark grey, same as a column header, so it visually stands apart from
   the plain season rows above it instead of blending in as just
   another row. Class-based, so it naturally outranks both the default
   tbody td background and the :where()-downgraded hover rule below,
   regardless of source order. */
.total-row td { background: var(--grey-header); }

.controls {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
  margin-bottom: 1rem;
}
.stat-selector { display: flex; gap: 0.4rem; flex-wrap: wrap; }
/* Perfil page's own stat selector (BALANCE/GOL/AST/PA/PI) sits directly
   under the "Estadísticas" h3 with no .controls wrapper around it (that
   class also carries a search box/era filter/toggle this page doesn't
   have) — just its own bottom margin before the table/chart below. */
#perfil-stat-selector { margin-bottom: 1rem; }
#perfil-grafica-selector { margin-bottom: 1rem; }
.stat-btn {
  background: var(--grey-header);
  border: 1px solid var(--border);
  color: var(--muted);
  padding: 0.45rem 0.9rem;
  border-radius: 8px;
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 700;
}
.stat-btn.active { color: var(--black); background: var(--accent-light); border-color: var(--accent-light); }
/* A stat with no recorded data for the selected era (#stat-selector only —
   Perfil's #perfil-stat-selector never disables buttons). */
.stat-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.stat-btn:disabled.active { background: var(--grey-header); border-color: var(--border); color: var(--muted); }

#player-search, #era-filter, #team-era-filter {
  background: var(--grey-header);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 0.5rem 0.75rem;
  border-radius: 8px;
  font-size: 0.9rem;
}
#player-search { flex: 1; min-width: 140px; }

/* Rank (#) is de-emphasized vs. the Dorsal/Jugador identity columns
   below - lighter weight and a touch smaller so a 1-2 digit rank
   number is never mistaken for the player's actual dorsal. */
.rank-cell { color: var(--white); font-weight: 400; font-size: 0.8em; }
/* Dorsal + Jugador bold - column numbers shift in BALANCE mode
   (no rank column there, see the balance-mode comment above), so
   this targets each mode's real dorsal/name columns separately
   instead of a fixed 2/3 that silently bolded the GOL column
   instead of the dorsal in BALANCE mode. */
#leaderboard-table:not(.balance-mode):not(.sin-dorsal) td:nth-child(2),
#leaderboard-table:not(.balance-mode):not(.sin-dorsal) td:nth-child(3),
#leaderboard-table.sin-dorsal td:nth-child(2),
#leaderboard-table.balance-mode td:nth-child(1) {
  font-weight: 700;
  color: var(--white);
}

.site-footer { text-align: center; color: var(--muted-alt); font-size: 0.8rem; padding: 1rem; }
/* Inicio has its own social block inline in the page (see below) -
   the footer's copy of the same links would just be a duplicate
   directly beneath it, so it's hidden specifically on that section.
   activateSection_ (app.js) sets body[data-section] on every nav. The
   footer's "Actualizado" timestamp line is unaffected - still shows
   on every section, Inicio included. */
body[data-section="inicio"] .site-footer .social-links { display: none; }

/* Inicio-only social block (Stage 9) - plain background (no card),
   sits below the Último/Próximo Partido cards. Title uses the accent
   color + the same size as the scoreboard team names; the handle
   matches that size too but in white and sentence case (not the
   uppercase treatment .social-label uses in the footer). */
/* No longer needs its own top margin - .inicio-side's gap (see above) already spaces it from Próximo Partido. */
.inicio-social { text-align: center; }
/* max-width + centered margin - narrows the wrap so it breaks into
   two balanced lines instead of running the full column width
   (Daniel's call). */
.inicio-social-titulo { color: var(--accent-light); font-weight: 700; font-size: 1.4rem; margin: 0 auto 1.1rem; max-width: 260px; }
.inicio-social-links { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 0.75rem; margin-bottom: 1.1rem; }
.inicio-social-links img { width: 32px; height: 32px; display: block; border-radius: 6px; }
.inicio-social-handle { color: var(--white); font-weight: 700; font-size: 1.4rem; margin: 0; }
/* Social links — same row-of-icons + handle-label layout as the team's
   own social media graphics. Icons are already self-contained square
   assets (solid teal background, no transparency needed), so there's
   nothing to style on them beyond a consistent display size. */
.social-links {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}
.social-links img { width: 32px; height: 32px; display: block; border-radius: 6px; }
.social-label {
  color: var(--white);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-size: 0.9rem;
  margin-left: 0.3rem;
}

@media (max-width: 480px) {
  .site-header h1 { font-size: 1.5rem; }
  th, td { padding: 0.45rem 0.5rem; font-size: 0.8rem; }
  /* The standings snapshot and all-time balance tables set their own
     generous desktop padding (0.6rem 1.25rem, ID-scoped) that doesn't
     shrink under the plain "th, td" rule above — an ID selector beats
     a type selector regardless of which is inside the media query.
     With 7-8 narrow numeric columns, that leftover desktop padding
     alone was enough to force horizontal scrolling on a phone despite
     how much visually empty space sits in each cell. Tightening it
     here lets both fit a phone screen with no scrolling at all. */
  #standings-table th, #standings-table td,
  #team-balance-table th, #team-balance-table td,
  #otras-rivales-table th, #otras-rivales-table td,
  #otras-horarios-table th, #otras-horarios-table td {
    padding: 0.45rem 0.4rem;
  }
  .chart-wrap { height: 220px; padding: 1rem 0.6rem 0.75rem; }
  /* Same issue on the player-side BALANCE view: the base leaderboard
     padding (0.6rem 1.25rem, ID-scoped, line 343) survives the plain
     "th, td" rule above for the same specificity reason, and BALANCE
     mode's four stat columns (GOL/AST/PA/PI) have their own even more
     specific override (id+class+nth-child, line 515) carrying the same
     generous padding — needs an equally-specific mobile match to win. */
  #leaderboard-table th, #leaderboard-table td {
    padding: 0.45rem 0.4rem;
  }
  #leaderboard-table.balance-mode th:nth-child(n+2),
  #leaderboard-table.balance-mode td:nth-child(n+2) {
    padding: 0.45rem 0.4rem;
  }
  /* Same fix again for the Perfil career-stats table — same shape/issue
     as the two above (ID-scoped desktop padding surviving the generic
     mobile rule). */
  #perfil-stats-table th, #perfil-stats-table td {
    padding: 0.45rem 0.4rem;
  }
}

/* Otras (Estadísticas) — Rivales más comunes / Horarios tables reuse the
   #team-balance-table look; the wrappers just drop the outer frame. */
#otras-rivales-wrap, #otras-horarios-wrap { border: none; border-radius: 0; background: transparent; }
.otras-section-title { margin: 1.5rem 0 0.75rem; }
.otras-section-title:first-child { margin-top: 0; }
#otras-horarios-chart-wrap { margin-bottom: 1rem; }

/* Player icons (Individuales leaderboards + Récords) — fixed height, width
   follows the image's own shape (no circle, no background, no cropping). */
.jugador-icono {
  height: 30px;
  width: auto;
  max-width: 40px;
  object-fit: contain;
  vertical-align: middle;
  margin-right: 0.6rem;
}
.record-highlight-entry .jugador-icono { height: 26px; }
@media (max-width: 640px) {
  .jugador-icono { height: 24px; max-width: 32px; margin-right: 0.7rem; }
  .record-highlight-entry .jugador-icono { height: 22px; }
}

/* Récords individual cards: icon spans the full two-line row height, name
   and game/season reference stacked beside it. */
.record-highlight-con-icono { display: flex; align-items: center; gap: 0.6rem; }
.record-highlight-con-icono .jugador-icono { height: 40px; max-width: 48px; margin-right: 0; flex-shrink: 0; }
.record-highlight-text { min-width: 0; }
@media (max-width: 640px) {
  .record-highlight-con-icono .jugador-icono { height: 36px; max-width: 42px; }
}

/* Dorsal cell with the player icon in front of the number (tables that keep
   a dorsal column): icon, dorsal, then name in the next cell. */
.dorsal-icono-wrap { display: inline-flex; align-items: center; gap: 0.5rem; }
.dorsal-icono-wrap .jugador-icono { margin-right: 0; }
.dorsal-num { min-width: 1.6rem; text-align: center; }

/* Home-page PARTIDOS counter: black rounded digit squares, white text,
   no border (unlike the sibling .partido-card boxes). */
.partidos-contador { text-align: center; }
.partidos-contador[hidden] { display: none; }
.partidos-digitos { display: flex; justify-content: center; gap: 0.4rem; }
.partidos-digito { flex: 0 1 4.2rem; aspect-ratio: 3 / 4; display: flex; align-items: center; justify-content: center; background: var(--black, #000); color: var(--white, #fff); font-size: 3.2rem; font-weight: 800; border-radius: 10px; font-variant-numeric: tabular-nums; }
.partidos-etiqueta { color: var(--white, #fff); font-weight: 800; letter-spacing: 0.3em; font-size: 1.3rem; margin-top: 0.7rem; }
.partidos-desde { color: var(--white, #fff); font-weight: 600; letter-spacing: 0.12em; font-size: 0.85rem; margin-top: 0.3rem; }

/* Mobile fixes. Kept at the END of the file on purpose: the earlier
   max-width:640px block sits above these elements' base rules, so its
   .records-*-grid / .historia-cards overrides were silently losing the
   cascade (equal specificity, later rule wins). */
@media (max-width: 640px) {
  /* Records: one card per row (two never fit side by side on a phone). */
  .records-leaders-grid, .records-highlights-grid { grid-template-columns: 1fr; gap: 1rem; }
  .record-card { padding: 1rem; }
  /* Historia crests/jerseys: two per row so the artwork stays legible. */
  .historia-cards { grid-template-columns: repeat(2, 1fr); gap: 0.9rem; }
  /* Stats / Jugadores sub-nav: tighter buttons so all fit on one line,
     with a horizontal-scroll fallback on the narrowest screens. */
  .sub-nav { justify-content: flex-start; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
  .sub-nav::-webkit-scrollbar { display: none; }
  .sub-nav.tabs { gap: 0.25rem; padding: 0.75rem 0.5rem; }
  .sub-nav .tab-btn { flex: 0 0 auto; padding: 0.5rem 0.65rem; font-size: 0.9rem; }
}
@media (max-width: 380px) {
  .sub-nav .tab-btn { padding: 0.45rem 0.5rem; font-size: 0.82rem; }
}
#stat-title:empty, #perfil-stat-title:empty { display: none; }
@media (max-width: 640px) { .tarjetas-grid { grid-template-columns: repeat(2, 1fr); } }

/* Background test (easy to roll back: delete this block plus the pattern
   lines in the body rule and the two .sub-nav rules). Inicio boxes get a
   solid color with square corners and no border; the PARTIDOS counter gets
   the same solid box. Scoped to #section-inicio so the match-sheet page
   (era-themed cards) is untouched. */
#section-inicio .partido-card {
  background: var(--box-solid, #082f32);
  border: none;
  border-radius: 0;
}
.partidos-contador {
  background: var(--box-solid, #082f32);
  padding: 1.5rem;
}

/* Solid-box design, site-wide. --box-solid is the single reference for
   the solid color. Grey boxes (cards, charts, messages) lose their border
   and rounded corners; subsections sit above a solid box of consistent
   width. Table designs are untouched. Roll back by deleting this block. */
:root { --box-solid: #082f32; }

.solid-box,
.plantel-section,
.historia-block,
.perfil-header {
  background: var(--box-solid);
  padding: 1.5rem;
  margin-bottom: 1.5rem;
  border: none;
  border-radius: 0;
}
.historia-block:last-child { margin-bottom: 1.5rem; }
.solid-box > h3:first-child,
.plantel-section > h3:first-child,
.historia-block > h3:first-child { margin-top: 0; }
.solid-box > :last-child { margin-bottom: 0; }

/* Auto-hide boxes whose content is all hidden/empty. */
.solid-box:not(:has(> :not([hidden]))) { display: none; }
#perfil-insignias-box:has(#perfil-insignias:empty),
#perfil-tarjetas-box:has(#perfil-tarjetas:empty) { display: none; }

/* Grey boxes: no border, no rounded corners (images keep theirs). */
.insignia-card, .tarjeta-card, .historia-card, .chart-wrap,
.record-leader-col, .record-card, .detail-message {
  border: none;
  border-radius: 0;
}
.tarjeta-card img { border-radius: 8px; }

@media (max-width: 640px) {
  .solid-box, .plantel-section, .historia-block, .perfil-header { padding: 1rem; margin-bottom: 1rem; }
}

/* Boxes holding a narrow (compact) table: center the headings and
   selectors on the same axis as the table. */
.solid-box:has(.table-wrap.compact) > :is(h3, h4, .detail-message) { text-align: center; }
.solid-box:has(.table-wrap.compact) > .stat-selector { justify-content: center; }

/* ---- Round of tweaks ---- */
/* Divider lines: a touch darker than the solid box beneath. The match
   sheet overrides with a value computed from the era's own Fondo. */
:root { --box-divider: color-mix(in srgb, var(--box-solid) 45%, #000); }
.jugadores-divider { border-top-color: var(--box-divider); }
#partido-content .jugadores-divider { border-top-color: var(--tema-divider, var(--box-divider)); }
.alineacion-match { border-bottom-color: var(--box-divider); }

/* Match sheet: same solid-box look as Inicio's Último Partido. The card
   is a solid box in the era's Fondo; the page behind it shows that
   era's own background image (images/fondos/<themeCode>.jpg), falling
   back to the default pattern when the file is missing. */
body[data-section="partido"] {
  background: var(--tema-fondo-img, none, none), url("images/Base-verde-dark-lowRes.jpg") repeat, var(--bg);
  /* Themed image: native pixel size (any tile size works); default pattern: scaled as on the other pages. */
  background-size: auto, auto, 2100px auto, auto; /* png layer, jpg layer, default pattern, color */
}
#partido-content .partido-card {
  background: var(--tema-fondo, var(--box-solid));
  border: none;
  border-radius: 0;
}

/* Individuales: season chooser on its own row above the other filters. */
.controls-season { margin-bottom: 0.75rem; }

/* Position color legend (player profile, PI table). */
.pos-legend { display: flex; flex-wrap: wrap; gap: 0.5rem 1.25rem; justify-content: center; margin: 1rem 0 1.25rem; font-size: 0.85rem; color: var(--white); }
.pos-legend-item { display: inline-flex; align-items: center; gap: 0.4rem; }
.pos-legend-swatch { width: 14px; height: 14px; display: inline-block; }
.pos-legend-code { font-weight: 700; }

/* Profile: the section title (Estadísticas) stays left-aligned like the
   other profile sections; only the selected stat's own title is centered. */
#section-perfil .solid-box > h3:first-child { text-align: left; }

/* "Activa" tag on a streak that is still running through the latest game. */
.streak-activa {
  display: inline-block;
  margin-left: 0.4rem;
  padding: 0.05rem 0.4rem;
  background: var(--accent-light);
  color: var(--black);
  font-size: 0.65rem;
  line-height: 1.4;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-radius: 3px;
  vertical-align: middle;
}

.record-highlight-more { color: var(--muted-alt); font-size: 0.85rem; }

/* ---- Real links (open-in-new-tab support) ----
   Nav tabs, cards and mentions are <a href> now; reset the link look so
   they read exactly like the buttons/spans they replaced. */
a.tab-btn { text-decoration: none; text-align: center; line-height: normal; }
a.plantel-card, a.jugador-card, a.record-leader-row, a.era-link { color: inherit; text-decoration: none; }
a.jugador-card { display: block; }
a.partido-link { color: inherit; }

/* "Récord del equipo" tag on a profile record that equals the all-time
   best of any player (Récords tab). Sits next to the big total number
   (the Activa tag stays on the streak's start/end games). Gold on
   dark text - team-level meaning, so deliberately not era-themed. */
.record-historico {
  display: inline-block;
  margin-left: 0.75rem;
  padding: 0.05rem 0.4rem;
  background: #e0b341;
  color: #1a1400;
  font-size: 0.65rem;
  line-height: 1.4;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-radius: 3px;
  vertical-align: middle;
}
