/*
 * Football Statistics - Shared Styles
 * Common CSS used across all pages
 */

/* ============================================
   Custom Fonts
   ============================================ */
@font-face {
    font-family: 'Univers Condensed';
    src: url('fonts/Univers57-Condensed-Italic.woff2') format('woff2');
    font-weight: 400;
    font-style: italic;
    font-display: swap;
}

@font-face {
    font-family: 'Univers Condensed';
    src: url('fonts/Univers67-Condensed BoldItalic.woff2') format('woff2');
    font-weight: 700;
    font-style: italic;
    font-display: swap;
}

@font-face {
    font-family: 'Sequel Sans Black';
    src: url('fonts/sequel-sans-black-display.woff2') format('woff2');
    font-weight: 900;
    font-style: normal;
    font-display: swap;
}

/* ============================================
   CSS Variables (Design Tokens)
   ============================================ */
:root {
    --primary: #0073A8;
    --secondary: #A8A200;
    --secondary-text: #737000; /* AA-compliant gold for TEXT (4.5:1+); --secondary stays for bars/dots */
    --loss: #9B59B6;
    --bg-page: #f8f9fa;
    --bg-white: #ffffff;
    --text-dark: #222;
    --text-mid: #444;
    --text-light: #5a5a5a;
    --border: #e0e0e0;
    --hover-bg: #e8e8e8;
    --text-strong: #1a1a1a;
    --notice-bg: #fff3cd;
    --notice-border: #ffc107;
    --notice-text: #856404;
    --shadow: 0 2px 8px rgba(0,0,0,0.1);
    --highest: #007a7a;
    --lowest: #b35900;
    --active-bg: #e8f5e9;
    --active-text: #2e7d32;
    /* Condensed display font (Univers Condensed — italic faces only) + system fallback.
       Used for section titles, the entity header, and Matches-view team names. */
    --font-condensed: 'Univers Condensed', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    /* ---- Tokens below: #105 phase 1 (2026-09-28). Same values as the literals they replaced;
       edit a value here to change it everywhere it is used. ---- */

    /* Brand, extra */
    --primary-hover: #005f8a;         /* primary buttons on hover (entity pages override at runtime) */
    --hero-from: rgba(0, 115, 168, 0.95);
    --hero-to: rgba(168, 162, 0, 0.95);
    --progress-end: #00a0e0;          /* loading bar gradient end */
    --progress-glow: rgba(0, 115, 168, 0.3);
    --list-current-bg: rgba(0, 115, 168, 0.1); /* current item in entity pickers */

    /* Text and surfaces, extra */
    --text-on-colour: #fff;           /* text on any coloured fill: buttons, pills, badges */
    --text-faint: #999;               /* "#id" after an official's name */
    --modal-nav-arrow: #d0d0d0;       /* match modal previous/next arrows */
    --control-border: #ccc;           /* player-pick buttons */
    --nav-focus-bg: #faf5d8;          /* mobile menu: current section */
    --nav-focus-hover-bg: #f3ebc4;
    --spinner-track: #f3f3f3;
    --detail-row-bg: #f8f9fa;         /* expanded match row */

    /* Results: match rows and cards */
    --result-win-bg: #e6f3fa;
    --result-draw-bg: #faf9e6;
    --result-loss-bg: #f5eef8;
    --result-none-bg: #ffffff;        /* unplayed */
    --result-win-detail-bg: #f5fafe;  /* the expanded row under a result */
    --result-draw-detail-bg: #fdfcf5;
    --result-loss-detail-bg: #fbf8fc;
    --result-none-detail-bg: #fafafa;
    --result-draw-pill: #8a6e00;      /* score pill on a draw */

    /* Competition badges */
    --tier-1: #ffd700;
    --tier-2: #c0c0c0;
    --tier-3: #cd7f32;
    --tier-4: #8b4513;
    --tier-badge-ink: #333;           /* text on tier 1-2 badges */
    --badge-ink: #1a1a1a;             /* dark text on light round badges */
    --badge-fallback: #777;           /* border base when a badge sets no colour */
    --badge-league-from: #005a87;
    --badge-league-to: #0073A8;
    --badge-cup-from: #5e5e5e;
    --badge-cup-to: #737373;
    --badge-cup-round-from: #757575;
    --badge-cup-round-to: #9e9e9e;
    --badge-euro-from: #b8860b;
    --badge-euro-to: #daa520;
    --badge-euro-round-from: #9b7509;
    --badge-euro-round-to: #b8860b;

    /* Cup rounds */
    --round-r1: #ca8a04;
    --round-r2: #0891b2;
    --round-r3: #be185d;
    --round-r32: #7e22ce;             /* R32 / 4th Round */
    --round-r16: #4169e1;             /* R16 / 5th Round */
    --round-qf: #15803d;
    --round-sf: #c2410c;
    --round-third: #57534e;           /* 3rd-place play-off */
    --round-other: #6b7280;           /* preliminary / qualifying / other */
    --round-final-gold: #d5ad1f;
    --round-final-gold-light: #ebeb84;
    --round-final-silver: #9aa0a6;
    --round-final-silver-light: #eef1f4;
    --round-group-plain: #dde8e6;
    --round-group-ink: #3a3a3a;

    /* World Cup podium */
    --podium-champion: #e3b23c;
    --podium-runner-up: #9aa0ad;
    --podium-third: #cd7f32;
    --podium-host: #2e9e5b;
    --podium-hover-bg: #eef1f4;

    /* Player positions (squad and line-up badges) */
    --pos-gk: #e8f5e9;
    --pos-def: #fff9c4;
    --pos-mid: #e3f2fd;
    --pos-fwd: #ffebee;
    --sub-off: #c0392b;
    --sub-on: #2e7d32;

    /* Broadcasters (their brand colours) */
    --bc-bbc: #FFD42F;
    --bc-itv: #146A4D;
    --bc-bbc1: #CC4642;
    --bc-bbc2: #2A8270;
    --bc-itv1: #38D2DA;
    --bc-itv4: #5BE81F;
    --bc-ink-dark: #000;

    /* Errors */
    --error-bg: #fff5f5;
    --error-border: #ffcccc;
    --error-text: #cc0000;

    /* Corner radii */
    --radius-card: 8px;               /* panels, cards, modals, menus */
    --radius-control: 6px;            /* buttons, inputs, selects */
    --radius-small: 4px;              /* small buttons, list items, focus rings */
    --radius-badge: 3px;              /* badges and pills */
    --radius-focus: 2px;              /* focus outline on links and sort buttons */
    --radius-soft: 5px;
    --radius-bar: 12px;               /* progress bar */
    --radius-float: 2rem;             /* floating scroll button */
    --radius-pill: 999px;
    --radius-round: 50%;
}

/* ============================================
   Reset & Base Styles
   ============================================ */
* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    scrollbar-gutter: stable;
}

body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
    line-height: 1.6;
    color: var(--text-dark);
    background: var(--bg-page);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    padding-top: 200px; /* Space for fixed nav - adjust based on content */
}

/* ============================================
   Skip Link (Accessibility)
   Hidden by default, appears on focus for keyboard users
   ============================================ */
.skip-link {
    position: absolute;
    top: -100px;
    left: 50%;
    transform: translateX(-50%);
    background: var(--primary);
    color: white;
    padding: 0.75rem 1.5rem;
    border-radius: 0 0 var(--radius-card) var(--radius-card);
    text-decoration: none;
    font-weight: 600;
    z-index: 10000;
    transition: top 0.2s ease;
}

.skip-link:focus {
    top: 0;
    outline: 2px solid white;
    outline-offset: 2px;
}

/* Screen reader only - visually hidden but announced */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ============================================
   Focus Visible (Accessibility)
   Clear focus indicators for keyboard navigation
   ============================================ */

/* Links - nav, footer, general */
a:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
    border-radius: var(--radius-focus);
}

/* Buttons - primary and secondary */
.btn-primary:focus-visible,
.btn-secondary:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* Modal close button */
.close-btn:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
    border-radius: var(--radius-small);
}

/* Menu toggle button */
.menu-toggle:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* More filters toggle */
.more-filters-toggle:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* Table header sort buttons */
.league-table th:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: -2px;
}

/* ============================================
   Navigation
   ============================================ */
nav {
    background: var(--bg-page);
    padding: 0.25rem 0;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    /* box-shadow: 0 2px 4px rgba(0,0,0,0.1); */
    z-index: 1000;
}

nav .container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 2rem;
}

/* Nav top row: brand and menu toggle (inverted: club colour bg, white text) */
.nav-top-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin: -0.25rem -2rem 0.25rem;
    padding: 0.5rem 2rem 0.25rem;
    position: relative;
    background: var(--primary);
}

/* Entity header container */
.entity-header-container {
    text-align: left;
    padding: 0.5rem 0;
    border-top: 1px solid var(--border);
    position: relative;
}

/* Hide border when container is empty (no entity selected) */
.entity-header-container:empty {
    border-top: none;
    padding: 0;
}

.nav-brand {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    text-decoration: none;
}

.nav-brand img {
    height: 2rem;
    width: 2rem;
    object-fit: cover;
    border-radius: var(--radius-round);
}

.nav-brand span {
    font-family: var(--font-condensed);
    font-size: 1.3rem;
    font-weight: 700;
    font-style: italic;
    color: white;
}

nav ul {
    list-style: none;
    display: none; /* Hidden - use dropdown menu instead */
    gap: 2rem;
}

nav a {
    text-decoration: none;
    color: var(--text-mid);
    font-weight: 500;
    transition: color 0.3s;
}

nav a:hover {
    color: var(--primary);
}

/* Menu button - always visible (white on coloured nav bar) */
.menu-toggle {
    display: block;
    background: none;
    border: 1px solid rgba(255, 255, 255, 0.4);
    border-radius: var(--radius-small);
    padding: 0.5rem 0.75rem;
    min-height: 44px;
    cursor: pointer;
    font-family: var(--font-condensed);
    font-size: 0.85rem;
    font-weight: 700;
    font-style: italic;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: white;
    flex: none;
    width: auto;
}
.menu-toggle .toggle {
    color: inherit;
    display: inline-block;
    width: 0.8em;
    text-align: center;
}

.menu-toggle:hover {
    background: rgba(255, 255, 255, 0.15);
}

/* ---- First-visit navigation hint (coachmark anchored under the Menu button) ---- */
.nav-hint {
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    z-index: 1200;
    max-width: min(300px, calc(100vw - 2rem));
    background: var(--bg-white);
    color: var(--text-dark);
    border: 1px solid var(--border);
    border-radius: var(--radius-card);
    padding: 0.85rem 1rem;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
    text-align: left;
    animation: navHintIn 0.25s ease-out;
}
/* Caret pointing up toward the Menu button (top-right of the nav row) */
.nav-hint::before {
    content: '';
    position: absolute;
    top: -7px;
    right: var(--nav-hint-caret-right, 26px); /* set in JS to aim at the button centre */
    width: 13px;
    height: 13px;
    background: inherit;
    border-left: 1px solid var(--border);
    border-top: 1px solid var(--border);
    transform: rotate(45deg);
}
.nav-hint-title {
    margin: 0 0 0.25rem;
    font-family: var(--font-condensed);
    font-style: italic;
    font-weight: 700;
    font-size: 0.98rem;
    color: var(--primary);
}
.nav-hint-sub {
    margin: 0 0 0.7rem;
    font-size: 0.82rem;
    color: var(--text-mid);
    line-height: 1.35;
}
.nav-hint-dismiss {
    display: inline-block;
    min-height: 36px;
    padding: 0.4rem 0.9rem;
    background: var(--primary);
    color: var(--text-on-colour);
    border: none;
    border-radius: var(--radius-soft);
    font-weight: 700;
    font-size: 0.82rem;
    cursor: pointer;
}
.nav-hint-dismiss:hover { filter: brightness(1.08); }
.nav-hint-dismiss:focus-visible {
    outline: 2px solid var(--secondary);
    outline-offset: 2px;
}
@keyframes navHintIn {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: none; }
}
/* One-time attention pulse on the Menu button (white ring on the coloured bar) */
.menu-toggle.nav-hint-pulse { animation: navHintPulse 1.4s ease-out 3; }
@keyframes navHintPulse {
    0%   { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.55); }
    70%  { box-shadow: 0 0 0 9px rgba(255, 255, 255, 0); }
    100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
}
@media (prefers-reduced-motion: reduce) {
    .nav-hint { animation: none; }
    .menu-toggle.nav-hint-pulse { animation: none; }
}

/* Dropdown navigation menu (used on all screen sizes) */
.mobile-menu {
    display: none;
    position: absolute;
    top: 100%;
    right: 2rem;
    background: var(--bg-white);
    border: 1px solid var(--border);
    border-radius: var(--radius-card);
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    min-width: 180px;
    max-height: calc(100vh - 70px);
    overflow-y: auto;
    z-index: 1001;
}

.mobile-menu.active {
    display: block;
}

.mobile-menu a {
    display: block;
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--border);
}

.mobile-menu a:last-child {
    border-bottom: none;
}

.mobile-menu a:hover {
    background: var(--bg-page);
}

/* WC-2026 launch focus: a subtle gold tint on the promoted World Cup / Nations /
   WC Player Rankings rows, hinting they're the current spotlight. Temporary —
   paired with the reordering + focus:true flags in nav.js; remove together. */
.mobile-menu a.nav-focus {
    background: var(--nav-focus-bg);
}
.mobile-menu a.nav-focus:hover {
    background: var(--nav-focus-hover-bg);
}

/* Nav group subheadings */
.mobile-group-label {
    display: block;
    padding: 0.6rem 1rem 0.4rem;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: white;
    background: var(--primary);
    border-bottom: none;
}

.mobile-group-label:first-child {
    border-radius: var(--radius-card) var(--radius-card) 0 0;
}

.mobile-group-label + a {
    border-top: none;
}

/* ============================================
   Hero Section (legacy — used by unrebuilt pages)
   ============================================ */
.hero {
    background: linear-gradient(135deg, var(--hero-from) 0%, var(--hero-to) 100%);
    background-size: 200% 200%;
    animation: gradientShift 15s ease infinite;
    color: white;
    text-align: center;
    padding: 2rem 1rem;
    position: relative;
    overflow: hidden;
}

/* Hero background image layer */
.hero::after {
    content: '';
    position: absolute;
    inset: 0;
    background: url('images/hero-yearbooks.jpg') center center / cover no-repeat;
    z-index: -1;
}

@keyframes gradientShift {
    0% { background-position: 0% 50%; }
    50% { background-position: 100% 50%; }
    100% { background-position: 0% 50%; }
}

.hero::before {
    content: '';
    position: absolute;
    top: -50%;
    left: -50%;
    width: 200%;
    height: 200%;
    background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
    animation: pulse 10s ease-in-out infinite;
}

@keyframes pulse {
    0%, 100% { transform: scale(1); opacity: 0.5; }
    50% { transform: scale(1.1); opacity: 0.3; }
}

.hero h1 {
    font-size: 2rem;
    margin-bottom: 0.5rem;
    position: relative;
    z-index: 1;
    text-shadow: 0 2px 8px rgba(0,0,0,0.4);
}

.hero p {
    font-size: 1rem;
    opacity: 0.95;
    position: relative;
    z-index: 1;
    text-shadow: 0 2px 8px rgba(0,0,0,0.4);
}

/* ============================================
   Main Container
   ============================================ */
.main-container {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 0rem 2rem;
    flex: 1 0 auto;
}

/* ============================================
   Loading State
   ============================================ */
#loading {
    text-align: center;
    padding: 4rem 1rem;
    background: var(--bg-white);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow);
}

.spinner {
    width: 40px;
    height: 40px;
    border: 3px solid var(--border);
    border-top-color: var(--primary);
    border-radius: var(--radius-round);
    animation: spin 1s linear infinite;
    margin: 0 auto 1rem;
}

#loading p {
    color: var(--text-mid);
}

.loading-content {
    max-width: 500px;
    margin: 0 auto;
}

#loadingStage {
    font-size: 1.1rem;
    font-weight: 500;
    margin-bottom: 1.5rem;
}

.progress-bar-container {
    width: 100%;
    height: 24px;
    background: var(--border);
    border-radius: var(--radius-bar);
    overflow: hidden;
    margin-bottom: 0.75rem;
    box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
}

.progress-bar {
    height: 100%;
    background: linear-gradient(90deg, var(--primary) 0%, var(--progress-end) 100%);
    border-radius: var(--radius-bar);
    transition: width 0.3s ease;
    width: 0%;
    box-shadow: 0 0 10px var(--progress-glow);
}

.progress-info {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.875rem;
    color: var(--text-mid);
}

#progressPercent {
    font-weight: 600;
    color: var(--primary);
}

#progressDetails {
    font-family: 'SF Mono', 'Consolas', 'Monaco', monospace;
}

/* ============================================
   Lazy-Load Overlay (Split Database Mode)
   ============================================ */
.loading-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.7);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10000;
}

.loading-overlay .loading-content {
    background: white;
    padding: 30px;
    border-radius: var(--radius-card);
    text-align: center;
    max-width: 400px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}

.loading-overlay .spinner {
    width: 50px;
    height: 50px;
    border: 4px solid var(--spinner-track);
    border-top: 4px solid var(--primary);
    border-radius: var(--radius-round);
    animation: spin 1s linear infinite;
    margin: 0 auto 20px;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

.loading-overlay p {
    margin: 0;
    font-size: 1rem;
    color: var(--text-mid);
}

/* ============================================
   Sections (Cards)
   ============================================ */
.section {
    background: var(--bg-white);
    border-radius: var(--radius-card);
    padding: 1.25rem;
    margin-bottom: 1rem;
    box-shadow: var(--shadow);
}

/* Accessibility wrapper added by nav.js (initAccessibilityHeadings): wraps the
   .section-header toggle button in an <h2> for a real document outline. Must be
   visually inert — the styled title lives in .section-title inside the button. */
.section-heading {
    margin: 0;
    padding: 0;
    font: inherit;
    color: inherit;
}

.section-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    cursor: pointer;
    user-select: none;
    border: none;
    background: none;
    width: 100%;
    padding: 0;
    text-align: left;
    font: inherit;
    color: inherit;
}

.section-header:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
    border-radius: var(--radius-small);
}

.section-header .toggle {
    font-size: 1rem;
    color: var(--text-light);
    transition: transform 0.2s ease;
}

.section.collapsed .toggle {
    transform: rotate(-90deg);
}

.section.collapsed .section-content {
    display: none;
}

.section-title {
    font-size: 1.1rem;
    font-weight: 700;
    text-transform: capitalize;
    letter-spacing: 0.02em;
    color: var(--entity-btn-color, var(--secondary-text));
    margin-bottom: 0.75rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--border);
    font-family: var(--font-condensed);
    font-style: italic;
}

/* ============================================
   Honours Section
   ============================================ */
.honours-section {
    margin-bottom: 1rem;
}

.honours-content {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.honour-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.4rem 0;
    border-bottom: 1px solid var(--bg-page);
}

.honour-row:last-child {
    border-bottom: none;
}

.honour-label {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-dark);
    min-width: 160px;
}

.honour-seasons {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    flex: 1;
}

.honour-badge {
    display: inline-block;
    padding: 0.2rem 0.5rem;
    font-size: 0.75rem;
    font-family: 'SF Mono', 'Consolas', 'Monaco', 'Courier New', monospace;
    color: var(--text-mid);
    background: var(--bg-page);
    border-radius: var(--radius-small);
    white-space: nowrap;
}

.honour-badge.shared {
    font-style: italic;
}

.honour-divider {
    height: 1px;
    background: var(--text-light);
    margin: 0.5rem 0;
    opacity: 0.3;
}

/* ============================================
   Buttons
   ============================================ */
button {
    padding: 0.75rem 1.25rem;
    border: none;
    border-radius: var(--radius-control);
    font-family: inherit;
    font-size: 0.9rem;
    font-weight: 400;
    cursor: pointer;
    transition: all 0.2s ease;
}

.btn-primary {
    background: var(--entity-btn-color, var(--primary));
    color: white;
    font-family: var(--font-condensed);
    font-style: italic;
}

.btn-primary:hover {
    background: var(--entity-btn-hover, var(--primary-hover));
    transform: translateY(-1px);
}

.btn-primary:disabled {
    background: var(--border);
    color: var(--text-light);
    cursor: not-allowed;
    transform: none;
}

.btn-secondary {
    background: var(--bg-white);
    color: var(--text-mid);
    border: 1px solid var(--border);
    font-family: var(--font-condensed);
    font-weight: 400;
    font-style: italic;
}

.btn-secondary:hover {
    background: var(--border);
    color: var(--text-dark);
}

/* Toggle buttons (for view switching) */
.btn-primary.active {
    background: var(--entity-btn-color, var(--primary));
}

.btn-primary.inactive {
    background: var(--bg-white);
    color: var(--text-mid);
    border: 1px solid var(--border);
}

.btn-primary.inactive:hover {
    background: var(--border);
    color: var(--text-dark);
}

.button-row {
    display: flex;
    gap: 0.75rem;
    margin-top: 0;
}

.button-row + .button-row {
    margin-top: 0.5rem;
}

.button-row button {
    flex: 1;
}

/* ============================================
   Form Elements (Filters)
   ============================================ */
.filters {
    background: var(--bg-white);
    border-radius: var(--radius-card);
    padding: 1.5rem;
    margin-bottom: 1.5rem;
    box-shadow: var(--shadow);
}

.filter-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1rem;
}

@media (min-width: 600px) {
    .filter-grid {
        grid-template-columns: repeat(4, 1fr);
    }
}

.filter-group {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0; /* Allow shrinking in grid */
}

.filter-group label {
    font-size: 0.875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-light);
}

.filter-group select {
    width: 100%;
    min-width: 0; /* Allow shrinking below content width */
    box-sizing: border-box;
    background: var(--bg-page);
    border: 1px solid var(--border);
    border-radius: var(--radius-control);
    padding: 0.6rem 0.75rem;
    color: var(--text-dark);
    font-family: inherit;
    font-size: 0.9rem;
    cursor: pointer;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23777' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.75rem center;
    padding-right: 2.5rem;
    transition: border-color 0.2s;
}

.filter-group select:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: -1px;
    border-color: var(--primary);
}

.filter-group input {
    width: 100%;
    min-width: 0;
    background: var(--bg-page);
    border: 1px solid var(--border);
    border-radius: var(--radius-control);
    padding: 0.6rem 0.75rem;
    font-family: inherit;
    font-size: 0.9rem;
    box-sizing: border-box;
}

.filter-group input:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: -1px;
    border-color: var(--primary);
}

/* Combined filter groups (side-by-side selects) */
.filter-group-combined .combined-selects {
    display: flex;
    gap: 0.25rem;
}

.filter-group-combined .select-two-thirds {
    flex: 2;
    min-width: 0;
}

.filter-group-combined .select-one-third {
    flex: 1;
    min-width: 0;
}

/* Stacked filter groups (vertically stacked selects) */
.filter-group-stacked .stacked-selects {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.filter-group-stacked .stacked-selects select {
    width: 100%;
}

/* Secondary selects are disabled (greyed) when primary is at its default */
.filter-group-stacked .stacked-selects select:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

/* Sub-labels within a stacked group (e.g. First card / Second card / Position) */
.filter-group-stacked .filter-sublabel {
    display: block;
    margin-top: 0.5rem;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--text-light);
}

/* Full-width filter groups span all grid columns */
.filter-group.filter-group-full-width {
    grid-column: 1 / -1;
}

/* Combined filter cells (mode + value side by side) */
.combined-filter {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.combined-filter label {
    font-size: 0.875rem;
    color: var(--text-mid);
    margin-bottom: 0;
}

.combined-filter .filter-row {
    display: flex;
    gap: 0.25rem;
}

.combined-filter .filter-row select:first-child {
    flex: 2;
}

.combined-filter .filter-row select:last-child {
    flex: 1;
    min-width: 55px;
}

/* Kickoff time filter with modifier dropdown */
.kickoff-controls {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.kickoff-controls select {
    width: 100%;
}

/* ============================================
   Statistics Display
   ============================================ */
.stat-row {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    padding: 0.4rem 0;
    border-bottom: 1px solid var(--bg-page);
    gap: 1rem;
}

.stat-row:last-child {
    border-bottom: none;
}

.stat-label {
    font-size: 0.9rem;
    color: var(--text-mid);
    flex-shrink: 0;
}

.stat-value {
    font-family: 'SF Mono', 'Consolas', 'Monaco', 'Courier New', monospace;
    font-size: 0.85rem;
    color: var(--text-dark);
    text-align: right;
    word-break: break-word;
}

.stat-value.highlight {
    color: var(--primary);
    font-weight: 600;
}

/* ============================================
   Stat Grid — per-entity Record summary panels
   (project_records_board_redesign Thread 2). A
   responsive grid of value-forward metric tiles
   replacing the cramped .stat-row key/value list.
   ============================================ */
.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
    gap: 0.5rem;
    margin-top: 0.75rem;
}
.stat-tile {
    background: var(--bg-page);
    border: 1px solid var(--border);
    border-radius: var(--radius-card);
    padding: 0.6rem 0.75rem;
}
.stat-tile-value {
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--text-dark);
    line-height: 1.15;
}
.stat-tile-sub {
    font-size: 0.8rem;
    font-weight: 400;
    color: var(--text-light);
    white-space: nowrap;
}
.stat-tile-label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-light);
    margin-top: 0.15rem;
}
.stat-tile-badge {
    margin-top: 0.35rem;
}

/* Identity caption above a stat-grid (e.g. World Cup Tournament Summary:
   host · dates · champion — facts, not metrics, so not big-number tiles). */
.tournament-identity {
    font-size: 0.9rem;
    color: var(--text-light);
    margin-bottom: 0.75rem;
}
.tournament-identity .dot-sep {
    color: var(--border);
    margin: 0 0.2rem;
}

/* ============================================
   International tournament medal strip (internationals.html Overview, data from
   wc-tournament-map.js): champion gold · runner-up silver · third bronze · host green.
   ============================================ */
.wc-podium { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.wc-podium-item {
    display: inline-flex; flex-direction: column; gap: 0.1rem;
    padding: 0.4rem 0.7rem; border-radius: var(--radius-card); text-decoration: none;
    background: var(--bg-page); border-left: 4px solid var(--border);
}
.wc-podium-item:hover { background: var(--podium-hover-bg); }
.wc-podium-label {
    font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-light);
}
.wc-podium-nation { font-size: 0.95rem; font-weight: 600; color: var(--text-dark); }
.wc-podium-item.wc-p-champion { border-left-color: var(--podium-champion); }
.wc-podium-item.wc-p-runner   { border-left-color: var(--podium-runner-up); }
.wc-podium-item.wc-p-third    { border-left-color: var(--podium-third); }
.wc-podium-item.wc-p-host     { border-left-color: var(--podium-host); }

/* ============================================
   Record Bars (W/D/L visualization)
   ============================================ */
.record-bar {
    display: flex;
    height: 10px;
    border-radius: var(--radius-soft);
    overflow: hidden;
    margin: 0.75rem 0;
}

.record-bar .win,
.record-bar .home {
    background: var(--primary);
}

.record-bar .draw {
    background: var(--secondary);
}

.record-bar .loss,
.record-bar .away {
    background: var(--loss);
}

.record-legend {
    display: flex;
    justify-content: space-between;
    font-size: 0.8rem;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.legend-item {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    font-family: 'SF Mono', 'Consolas', 'Monaco', 'Courier New', monospace;
}

.legend-dot {
    width: 10px;
    height: 10px;
    border-radius: var(--radius-round);
}

.legend-dot.win,
.legend-dot.home { background: var(--primary); }
.legend-dot.draw { background: var(--secondary); }
.legend-dot.loss,
.legend-dot.away { background: var(--loss); }

/* ============================================
   More Filters Toggle
   ============================================ */
.more-filters-toggle {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background: none;
    border: none;
    color: var(--primary);
    font-size: 0.85rem;
    font-weight: 500;
    cursor: pointer;
    padding: 0.75rem 0;
    min-height: 44px;
    margin-top: 0.25rem;
}

.more-filters-toggle:hover {
    text-decoration: underline;
}

.more-filters-toggle .arrow {
    transition: transform 0.2s;
    font-size: 0.7rem;
}

.more-filters-toggle.expanded .arrow {
    transform: rotate(90deg);
}

.filter-grid-secondary {
    display: none;
    grid-template-columns: repeat(2, 1fr);
    gap: 1rem;
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border);
}

.filter-grid-secondary.visible {
    display: grid;
}

@media (min-width: 600px) {
    .filter-grid-secondary {
        grid-template-columns: repeat(3, 1fr);
    }
}

/* ============================================
   Date Filter Mode Selector (Two-mode filtering)
   ============================================ */
.date-filter-modes {
    grid-column: 1 / -1;
    margin-bottom: 0.5rem;
}

.date-mode-selector {
    display: flex;
    gap: 1.5rem;
    margin-bottom: 0.75rem;
}

.date-mode-option {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    cursor: pointer;
}

.date-mode-option input[type="radio"] {
    margin: 0;
    cursor: pointer;
}

.date-mode-option label {
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
}

.date-mode-section {
    display: none;
    padding: 0.75rem;
    background: var(--bg-page);
    border-radius: var(--radius-control);
    border: none;
    margin: 0;
}

.date-mode-section.active {
    display: block;
}

.date-mode-section legend {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.date-mode-description {
    font-size: 0.75rem;
    color: var(--text-light);
    margin-bottom: 0.75rem;
    font-style: italic;
}

.date-mode-fields {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 0.75rem;
}

.date-field-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    grid-column: 1 / -1;
}

.date-field-row .filter-group {
    flex: 1;
    min-width: 0;
}

.date-field-label {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-mid);
    min-width: 35px;
}

@media (max-width: 600px) {
    .date-mode-selector {
        flex-direction: column;
        gap: 0.75rem;
    }
}

/* ============================================
   Games Display (Inline)
   ============================================ */
.games-info {
    padding: 0.75rem 1.25rem;
    background: var(--bg-page);
    font-size: 0.85rem;
    color: var(--text-mid);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

/* Inline games container (for pages using inline display instead of modal) */
#games {
    display: flex;
    flex-direction: column;
    min-height: 400px;
}

.games-list {
    flex: 1;
    /* No overflow scroll-container here: the page scrolls, and overflow-y:auto would
       trap position:sticky on the table header (it'd resolve to this box, not the
       viewport, and scroll away). See .games-table th. */
    padding: 0;
}

/* Desktop: Table view */
.games-table {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
}

/* Column widths defined in HTML via <colgroup><col> elements */

/* Column alignment */
.games-table .align-right {
    text-align: right;
}

.games-table .align-center {
    text-align: center;
}

.games-table th {
    background: var(--bg-page);
    padding: 0.6rem 0.75rem;
    text-align: left;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-mid);
    /* Sticky below the fixed nav so the (sortable) Date header stays visible while
       scrolling. Matches .players-table thead; --nav-height is kept current by the
       page's ResizeObserver. */
    position: sticky;
    top: var(--nav-height, 194px);
    z-index: 100;
}

/* Sortable Date header: a real <button> styled to read as the column header */
.games-table th .games-sort-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
    text-transform: inherit;
    letter-spacing: inherit;
    cursor: pointer;
}

.games-table th .games-sort-btn:hover {
    color: var(--text-strong);
}

.games-table th .games-sort-btn:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
    border-radius: var(--radius-focus);
}

.games-table th .games-sort-ind {
    font-size: 0.6rem;
    color: var(--primary);
}

.games-table td {
    padding: 0.6rem 0.75rem;
    border-bottom: 1px solid var(--border);
    font-size: 0.85rem;
}

/* Matches-view team names in the condensed display face (matchday-graphics feel).
   Desktop: both team cells carry the .team-cell class (set in games-display.js).
   Mobile: the .team spans in each card. Slight bump as the condensed face runs narrow. */
.games-table tbody td.team-cell,
.game-card .result .team {
    font-family: var(--font-condensed);
    font-style: italic;
    font-size: 0.95rem;
    letter-spacing: 0.01em;
}

/* The team-cell face is italic; keep the emoji flag upright (the browser would
   otherwise apply a synthetic slant to it). */
.team-flag {
    font-style: normal;
    display: inline-block;
}

/* "As it stands" provisional occupant shown beneath a knockout placeholder
   (e.g. the team currently topping a group, under "Winner Group C"). Rendered
   by games-display.js when a game carries home_team_subtitle/away_team_subtitle.
   Deliberately the plain system face so it reads as live metadata, not a name.
   Inherits the cell's text-align (right for home, left for away). */
.team-subtitle {
    display: block;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    font-style: normal;
    font-weight: 400;
    font-size: 0.7rem;
    letter-spacing: 0;
    line-height: 1.15;
    margin-top: 1px;
    color: var(--text-light);
}

.games-table tr:hover {
    filter: brightness(0.95);
}

.games-table .score {
    font-family: 'SF Mono', 'Consolas', 'Monaco', 'Courier New', monospace;
    font-weight: 600;
    text-align: center;
    white-space: nowrap;
}

/* ============================================================================
   Card-style desktop table (cfg.cardRows — World Cup). Each match is a group of
   rows mimicking the mobile card: header (date + comp/tier badges), fixture
   (home/score/away on the 6-col grid), optional PSO, and meta (venue +
   broadcaster). The cardBg gradient is a background-image on each <tr> (over the
   white base), so it fills the full row width; cells stay transparent.
   ============================================================================ */

/* Minimal sort-only header (the column labels no longer apply). */
.games-table-cards thead .games-sort-th { text-align: left; }

/* Header / meta rows: full-width flex line — info left, badges right (like the card
   header). The colspan-6 cell holds the flex; no column alignment needed here. */
.games-table .match-row-line {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}
.match-header-row .match-date {
    font-size: 0.8rem;
    color: var(--text-light);
}
/* Venue in the card-style meta row (e.g. domestic pages without broadcaster
   badges) — subdued, matching the header date. */
.games-table-cards .match-meta-row .card-meta-venue {
    font-size: 0.8rem;
    color: var(--text-light);
}
/* Tight vertical rhythm: the rows group as one block (small inner gaps), with breathing
   room above the header and below the meta row to separate matches — mirroring the mobile
   card rather than the table's default per-row padding. The PSO row's bottom is tightened
   too (its top is already 0 from the matchday PSO rule). */
.match-header-row > td { padding-top: 0.55rem; padding-bottom: 0.1rem; }
.match-fixture-row > td { padding-top: 0.1rem; padding-bottom: 0.1rem; }
.match-meta-row > td { padding-top: 0.1rem; padding-bottom: 0.55rem; }
.games-table-cards .pso-result-row > td { padding-bottom: 0.1rem; }

/* The match block reads as one unit: drop internal row borders; the divider goes
   under the meta row (always present on WC — every match has a venue). */
.games-table-cards tbody td { border-bottom: none; }
.games-table-cards .match-meta-row > td { border-bottom: 1px solid var(--border); }

/* The whole match block is clickable; the fixture row is the keyboard button. */
.games-table-cards .match-header-row,
.games-table-cards .match-meta-row,
.games-table-cards .match-fixture-row,
.games-table-cards .pso-result-row { cursor: pointer; }

/* Hover dims the hovered row only by default; across a multi-row card that reads as
   broken (one row at a time), so suppress the per-row hover dim in card mode. Needs the
   .expandable class to out-specify `.games-table tr.expandable:hover` below. Hover is a
   mouse-only affordance, not a11y — cursor:pointer + the keyboard focus state remain. */
.games-table-cards tbody tr.expandable:hover { filter: none; }

/* Row background colors (pastel) */
.games-table tr.win-row { background: var(--result-win-bg); }
.games-table tr.draw-row { background: var(--result-draw-bg); }
.games-table tr.loss-row { background: var(--result-loss-bg); }
/* Unplayed: neutral white — no result yet, no team-perspective tint */
.games-table tr.unplayed-row { background: var(--result-none-bg); }

/* Detail rows: much paler to give contrast with squad number badges */
.games-table tr.detail-row.win-row { background: var(--result-win-detail-bg); }
.games-table tr.detail-row.draw-row { background: var(--result-draw-detail-bg); }
.games-table tr.detail-row.loss-row { background: var(--result-loss-detail-bg); }
.games-table tr.detail-row.unplayed-row { background: var(--result-none-detail-bg); }

/* Unplayed score cell — 'v' between teams instead of a numeric score */
/* Unplayed fixtures get a pill too, matching .score-pill's geometry — but black-on-white
   with a hairline border (so the white pill still reads as a pill on the white row),
   setting them apart from the result-coloured pills of played matches. */
.unplayed-score {
    display: inline-block;
    padding: 0.05rem 0.55rem 0.05rem 0.5rem;
    background: var(--bg-white);
    color: var(--text-dark);
    border: 1px solid var(--border);
    font-weight: normal;
    font-style: italic;
}

.games-table .score.win { color: var(--primary); }
.games-table .score.draw { color: var(--secondary-text); }
.games-table .score.loss { color: var(--loss); }

/* Mobile: Card view */
.games-cards {
    display: none;
}

/* Mobile sort bar (the cards layout has no table header). Lives inside .games-cards,
   so it shows only when the card layout is. The bar itself is inert — only its buttons
   are interactive: a compact Date toggle (left, mirroring the desktop header button)
   and, for in-progress lists, the "Latest result" jump (right). */
.games-sort-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    width: 100%;
    min-height: 44px;
    padding: 0 1rem;
    background: var(--bg-page);
    border-bottom: 1px solid var(--border);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-mid);
    /* Stick below the fixed nav (same offset + stacking as the desktop .games-table th
       header) so the sort bar stays visible while scrolling the card list, rather than
       sliding up behind the nav. --nav-height is kept current by entity-header.js. */
    position: sticky;
    top: var(--nav-height, 194px);
    z-index: 100;
}

/* Buttons fill the bar height so each is a ≥44px touch target while the labels
   stay visually compact. */
.games-sort-bar .games-sort-btn,
.games-sort-bar .games-jump-latest {
    min-height: 44px;
}

.games-sort-bar .games-sort-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
    text-transform: inherit;
    letter-spacing: inherit;
    cursor: pointer;
}

.games-sort-bar .games-sort-btn:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
    border-radius: var(--radius-focus);
}

.games-sort-bar .games-sort-ind {
    color: var(--primary);
}

/* Sort <select> — replaces the old Date toggle in the mobile bar and the desktop
   card-style header. Native control (one tap on mobile, self-describing to AT) with
   a themed chevron. Shares the bar's compact uppercase type. */
.games-sort-select {
    min-height: 44px;
    background-color: var(--bg-white);
    border: 1px solid var(--border);
    border-radius: var(--radius-control);
    padding: 0.3rem 1.7rem 0.3rem 0.6rem;
    font: inherit;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-mid);
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%230073A8' stroke-width='1.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.6rem center;
    background-size: 0.7rem;
}

.games-sort-select:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* Desktop card-style header: lay the Date toggle (left) and the jump (right) on one row. */
.games-sort-th-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

/* "Latest result" jump — a quiet text action in the primary colour, on both the mobile
   bar and the desktop card-style header. */
.games-jump-latest {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font: inherit;
    font-weight: 600;
    text-transform: none;
    letter-spacing: 0;
    color: var(--primary);
    white-space: nowrap;
    cursor: pointer;
}

.games-jump-latest:hover { text-decoration: underline; }

.games-jump-latest:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
    border-radius: var(--radius-focus);
}

/* Brief highlight on the match the jump lands on, so it's easy to spot. */
@keyframes games-jump-flash {
    0%, 30% { box-shadow: inset 0 0 0 2px var(--primary); }
    100% { box-shadow: inset 0 0 0 2px transparent; }
}
.games-jump-flash { animation: games-jump-flash 1.3s ease-out; }

.game-card {
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--border);
}

.game-card:last-child {
    border-bottom: none;
}

.game-card .date {
    font-size: 0.75rem;
    color: var(--text-light);
    margin-bottom: 0.25rem;
}

.game-card .result {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.95rem;
}

.game-card .team {
    flex: 1;
}

.game-card .team.home {
    text-align: right;
}

.game-card .team.away {
    text-align: left;
}

/* Kit-card layout (PROTOTYPE — WC Matches view). Mobile-first: the card layout is used
   at ALL widths and the desktop table is suppressed. The collapsed block (.kit-card-core)
   hosts a full-height kit art layer behind date · teams · stadium; the expandable detail
   sits AFTER the core, so the kit spans only the collapsed block and never covers the
   expanded detail, and the stadium row stays put on expand. */
.kit-card-layout .games-table { display: none; }
.kit-card-layout .games-cards { display: block; }

/* The card layout is tuned for a phone-width column. Left to run full-bleed on desktop
   it strands the kit+score cluster in the middle of an over-wide row, with dead bands of
   whitespace either side. Cap the column and centre it so desktop sees the same well-
   proportioned card the mobile design was tuned for. The sort bar lives inside .games-cards
   too, so it tracks the same width. (No media query needed — below this width the viewport
   itself is the limit, so phones keep the full-bleed layout.) */
.kit-card-layout { max-width: 680px; margin-left: auto; margin-right: auto; }

/* Small top gap (header sits near the top edge); the reclaimed space goes into a bigger
   header↔result gap so the date/badge row clears the kit. Card height ≈ unchanged. */
/* Edge-align the corner content instead of centring it: the date+badges hug the TOP of
   the header and the stadium+broadcaster hug the BOTTOM of the meta. This removes the
   centring offset (which differed between the two rows and rendered unevenly across
   devices), so the top/bottom gaps are driven purely by padding. The 1px extra top
   padding compensates for the card's 1px BOTTOM border, equalising the visible gaps. */
.game-card.kit-card { padding: 3px 10px 2px 10px; }
.game-card.kit-card .card-header { margin-bottom: 0.5rem; align-items: flex-start; }
.game-card.kit-card .card-meta { margin-top: 0.5rem; align-items: flex-end; }
/* Pin the badges to the line-box edge (removes the line-height leading that otherwise
   floats them inward) without changing the row height, so card height/kit stay put. */
.game-card.kit-card .card-header .tier-badge { vertical-align: top; }
.game-card.kit-card .card-meta .broadcaster-badge { vertical-align: bottom; }

/* Badge sizing in kit cards. Two fixes:
   1. Trim vertical padding so badges aren't over-tall in their rows.
   2. Equal height + a visible edge on every badge. The header tier/competition
      badges used a box-shadow ring (sits outside the box → 0 layout height) while
      the meta broadcaster badges use a real 1px border (+2px) — so the rows differed
      by ~2px. Unify the header badges onto a real 1px border too (box-shadow off) so
      both rows match. The border colour is a darkened tone of the badge's own fill
      (color-mix on --badge-bg) where it's set — pastels, finals, groups — and falls
      back to a dark translucent edge for the white-text fills that don't set it
      (WC 2026, knockout rounds), which previously had no edge at all. */
.game-card.kit-card .tier-badge,
.game-card.kit-card .broadcaster-badge {
    padding-top: 0.04rem;
    padding-bottom: 0.04rem;
}
.game-card.kit-card .tier-badge {
    border: 1px solid rgba(0, 0, 0, 0.45); /* fallback if color-mix unsupported */
    /* --badge-bg fallback (#777) keeps the color-mix valid for the white-text fills
       that don't set it (WC 2026, knockout rounds) — without it the declaration would
       reset border-color to currentColor (white) on those badges. */
    border: 1px solid color-mix(in srgb, var(--badge-bg, var(--badge-fallback)), black 42%);
    box-shadow: none;
}

.kit-card-core { position: relative; }
/* Header, stadium and PSO sit ABOVE the kit's overflow (z-index 2 beats the result row's
   z-index 1), so the kit can overflow behind them without ever touching their text. */
.kit-card-core > .card-header,
.kit-card-core > .card-meta,
.kit-card-core > .pso-result { position: relative; z-index: 2; }

/* Kit anchored to the RESULT row (not the whole core): centred on the teams/score and
   overflowing symmetrically into the gaps above/below. So nudging the header up directly
   increases its clearance from the kit, while the kit keeps its size and stays centred
   on the fixture. */
.kit-result-bg { position: relative; z-index: 1; display: flex; align-items: center; gap: 10px; }
.kit-result-bg > * { position: relative; z-index: 1; }
.kit-bg-abs {
    position: absolute;
    inset: 0;
    z-index: 0;
    display: flex;
    pointer-events: none;
}
/* Each kit owns half the width and sits toward the centre, so a lone kit (a match
   where only one team has kit data) keeps its correct home/away position instead of
   being pulled toward the score. The central clear-zone for the score pill is the
   42px inner padding on each half (was a single 84px flex gap, which mis-centred a
   solo kit). */
.kit-art { flex: 1 1 0; min-width: 0; display: flex; align-items: center; }
.kit-art:first-child { justify-content: flex-end; padding-right: 42px; }
.kit-art:last-child  { justify-content: flex-start; padding-left: 42px; }
.kit-art .kit-svg { display: block; height: 72px; width: auto; }

/* Names anchored to the INTERIOR (toward the kits) with a gap so they clear them; the
   empty space falls on the outer edges. Bold Univers condensed display face. */
.kit-result-bg .team {
    flex: 1;
    min-width: 0;
    font-family: var(--font-condensed);
    font-weight: 700;
    font-style: italic;
    font-size: 1.05rem;
}
.kit-result-bg .team.home { text-align: right; padding-right: 64px; }
.kit-result-bg .team.away { text-align: left; padding-left: 64px; }

/* Stadium row lives inside the collapsed core (above the detail), so the old "divider
   above the meta row when expanded" is wrong and changed the height — keep it static. */
.game-card.kit-card.expanded .kit-card-core .card-meta {
    margin-top: 0.5rem;
    padding-top: 0;
    border-top: none;
}

@media (max-width: 600px) {
    .kit-art .kit-svg { height: 58px; }
    .kit-art:first-child { padding-right: 28px; }
    .kit-art:last-child { padding-left: 28px; }
    .kit-result-bg .team.home { padding-right: 44px; }
    .kit-result-bg .team.away { padding-left: 44px; }
}

.game-card .score {
    font-family: 'SF Mono', 'Consolas', 'Monaco', 'Courier New', monospace;
    font-weight: 600;
    min-width: 3rem;
    text-align: center;
}

/* Scorelines in the condensed bold-italic face, scaled up so the score is the
   row's focal point (above the 0.95rem team names). Declared after both the
   .games-table .score and .game-card .score rules so it wins on desktop AND mobile.
   (Keeps a monospace fallback for digit alignment if the web font fails to load.) */
.games-table .score,
.game-card .score {
    font-family: 'Univers Condensed', 'SF Mono', 'Consolas', monospace;
    font-style: italic;
    font-weight: 700;
    font-size: 1.05rem;
    /* The larger score's cap-height reaches ~1px above the smaller team text even
       when their line-boxes are centred — nudge down to optically align. */
    position: relative;
    top: 1px;
}

/* Scoreboard chip — wraps the played score (formatMatchScore) so it lifts off the
   pastel result row like a broadcast scoreline graphic. Inverted: white score on a
   result-coloured surface (set per win/draw/loss below). Extra right padding clears
   the italic lean of the trailing digit. */
.score-pill {
    display: inline-block;
    padding: 0.05rem 0.55rem 0.05rem 0.5rem;
    border-radius: 0;
    color: var(--text-on-colour);
    background: var(--text-light); /* neutral fallback if the row has no result class */
    font-variant-numeric: tabular-nums;  /* equal-width digits (a "1" matches a "2") */
}
/* Result-coloured pill backgrounds. Draw is a dedicated warm gold (#8a6e00,
   4.87:1 white-text contrast — AA, in line with win 5.23 and loss 4.67); the
   identity gold --secondary is too light for white text. Covers both the
   desktop table (.score on a <td>) and the mobile card (.score on a <span>). */
.score.win  .score-pill { background: var(--primary); }
.score.draw .score-pill { background: var(--result-draw-pill); }
.score.loss .score-pill { background: var(--loss); }

/* Penalty shoot-out result line (formatPenaltyResult) — a readable sentence under
   the score: spans Home–Score–Away on desktop, full-width on the mobile card.
   The score row above it drops its divider so the two read as one match. */
/* Tuck the PSO line tight under its score row: kill the divider and the score
   row's bottom padding, and the sub-row's top padding, so the gap is a line break
   (not a paragraph break). The sub-row keeps its bottom padding + border as the
   match separator. */
.games-table tbody tr:has(+ .pso-result-row) > td { border-bottom: none; padding-bottom: 0; }
.pso-result-row > td { padding-top: 0; }
.games-table td.pso-result,
.game-card .pso-result {
    text-align: center;
    font-family: var(--font-condensed);
    font-style: italic;
    font-size: 0.88rem;
    color: var(--text-light);
}
.game-card .pso-result { margin-top: 0.1rem; }
/* Bold just the score within the sentence (the rest stays regular weight). */
.pso-result .pso-score-num { font-weight: 700; }
/* The compact "P" penalties tag, bold + upright so it reads as a label. The result
   stays centred under the score pill (default) — compact enough to fit the central
   clear-zone between the kits; the P's side within the string ("P 4–2" vs "2–4 P")
   still encodes the winner. */
.pso-result .pso-tag { font-weight: 700; font-style: normal; }

/* PSO result pill — a slightly-smaller sibling of the score pill, coloured by the
   shootout winner (home → --primary, away → --loss). Square like the card's
   .score-pill; the modal rounds it to match its own dm-pill (see detail modal). */
.pso-pill {
    /* inline-flex + align/justify centre the glyphs vertically — plain inline-block
       with the italic face made the text ride high in the pill. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.2rem;
    padding: 0.2rem 0.45rem;         /* a little vertical breathing room */
    background: var(--text-light);   /* neutral fallback */
    color: var(--text-on-colour);
    font-family: var(--font-condensed);
    font-style: italic;
    font-weight: 700;
    font-size: 0.8rem;
    line-height: 1;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;  /* equal-width digits */
}
.pso-pill .pso-tag { font-style: normal; }
/* Rare double-digit shootout (e.g. 10–9): trim padding so the pill doesn't grow. */
.pso-pill--tight { padding-left: 0.25rem; padding-right: 0.25rem; }
/* The condensed face's glyphs sit high in the line box (empty descent below digits),
   so flex-centring alone leaves the ink looking high. Nudge the ink down a touch
   (em-based, so it scales with the card vs modal pill sizes). */
.pso-pill .pso-tag,
.pso-pill .pso-score-num { transform: translateY(0.08em); }
.pso-pill.pso-home-win { background: var(--primary); }
.pso-pill.pso-away-win { background: var(--loss); }

/* Card background colors (pastel) */
.game-card.win-row { background: var(--result-win-bg); }
.game-card.draw-row { background: var(--result-draw-bg); }
.game-card.loss-row { background: var(--result-loss-bg); }
.game-card.unplayed-row { background: var(--result-none-bg); }

.game-card .score.win { color: var(--primary); }
.game-card .score.draw { color: var(--secondary-text); }
.game-card .score.loss { color: var(--loss); }

/* Neutral pages (world_cups, competitions, scorelines) pass tintRows:false — the
   win/draw/loss row tint encodes an entity perspective that doesn't exist there, so
   it reads as noise. Rows render uniform white and the result colour survives only on
   the .score pill. Detail (expanded) rows keep a faint neutral grey for the affordance.
   Higher specificity + later position so these win over the tint rules above. */
.no-result-tint .games-table tr.win-row,
.no-result-tint .games-table tr.draw-row,
.no-result-tint .games-table tr.loss-row,
.no-result-tint .games-table tr.unplayed-row,
.no-result-tint .game-card.win-row,
.no-result-tint .game-card.draw-row,
.no-result-tint .game-card.loss-row,
.no-result-tint .game-card.unplayed-row {
    background: var(--bg-white);
}
.no-result-tint .games-table tr.detail-row.win-row,
.no-result-tint .games-table tr.detail-row.draw-row,
.no-result-tint .games-table tr.detail-row.loss-row,
.no-result-tint .games-table tr.detail-row.unplayed-row {
    /* White base to match the fixture row; the per-match gradient is copied onto
       these rows inline (see renderDetailAt) so the expanded content shares the
       header background. */
    background-color: var(--bg-white);
}

/* Tier badges in games table/cards */
.tier-badge {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: 600;
    padding: 0.15rem 0.4rem;
    border-radius: var(--radius-badge);
    background: var(--bg-page);
    color: var(--text-mid);
}

.tier-badge.tier-1 { --badge-bg: var(--tier-1); background: var(--badge-bg); color: var(--tier-badge-ink); }
.tier-badge.tier-2 { --badge-bg: var(--tier-2); background: var(--badge-bg); color: var(--tier-badge-ink); }
.tier-badge.tier-3 { background: var(--tier-3); color: var(--text-on-colour); }
.tier-badge.tier-4 { background: var(--tier-4); color: var(--text-on-colour); }

/* League competition badge styling (blue theme) */
.tier-badge.league-comp {
    background: linear-gradient(135deg, var(--badge-league-from) 0%, var(--badge-league-to) 100%);
    color: var(--text-on-colour);
    font-size: 0.7rem;
    white-space: nowrap;
}

/* Domestic cup competition badge styling (grey/silver theme). Darkened so the
   white text clears WCAG AA — the old #9e9e9e–#bdbdbd silver was only ~1.9:1. */
.tier-badge.cup-comp {
    background: linear-gradient(135deg, var(--badge-cup-from) 0%, var(--badge-cup-to) 100%);
    color: var(--text-on-colour);
    font-size: 0.7rem;
    white-space: nowrap;
    text-shadow: 0 1px 2px rgba(0,0,0,0.3);
}

.tier-badge.cup-round {
    background: linear-gradient(135deg, var(--badge-cup-round-from) 0%, var(--badge-cup-round-to) 100%);
    color: var(--text-on-colour);
    font-size: 0.7rem;
    white-space: nowrap;
    padding: 0.15rem 0.4rem;
    text-shadow: 0 1px 2px rgba(0,0,0,0.3);
}

/* European competition badge styling (gold theme) */
.tier-badge.european-comp {
    background: linear-gradient(135deg, var(--badge-euro-from) 0%, var(--badge-euro-to) 100%);
    color: var(--text-on-colour);
    font-size: 0.7rem;
    white-space: nowrap;
    text-shadow: 0 1px 2px rgba(0,0,0,0.3);
}

.tier-badge.euro-round {
    background: linear-gradient(135deg, var(--badge-euro-round-from) 0%, var(--badge-euro-round-to) 100%);
    color: var(--text-on-colour);
    font-size: 0.7rem;
    white-space: nowrap;
    padding: 0.15rem 0.4rem;
    text-shadow: 0 1px 2px rgba(0,0,0,0.3);
}

/* Round/group badge colour coding (games-display.js roundBadgeAttrs) — applied
   site-wide to World Cup, domestic cup and European matches. Knockout rounds use
   vivid colours building toward the trophy; deep rounds are reused by depth
   (5th Round ≡ R16, 4th ≡ R32). Group/pre-knockout stages use pastels / muted
   grey. All knockout colours hold AA white-text contrast on their backgrounds. */
.tier-badge.round-r2,
.tier-badge.round-r3,
.tier-badge.round-r32,
.tier-badge.round-r16,
.tier-badge.round-qf,
.tier-badge.round-sf,
.tier-badge.round-third,
.tier-badge.round-pre {
    color: var(--text-on-colour);
    white-space: nowrap;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}
.tier-badge.round-r1     { --badge-bg: var(--round-r1); background: var(--badge-bg); color: var(--badge-ink); white-space: nowrap; } /* yellow  — 1st Round */
.tier-badge.round-r2     { background: var(--round-r2); }  /* cyan    — 2nd Round */
.tier-badge.round-r3     { background: var(--round-r3); }  /* magenta — 3rd Round */
.tier-badge.round-r32    { background: var(--round-r32); }  /* violet  — R32 / 4th Round */
.tier-badge.round-r16    { background: var(--round-r16); }  /* royal blue — R16 / 5th Round */
.tier-badge.round-qf     { background: var(--round-qf); }  /* green   — Quarter-Final */
.tier-badge.round-sf     { background: var(--round-sf); }  /* orange  — Semi-Final */
.tier-badge.round-third  { background: var(--round-third); }  /* muted stone — 3rd-place play-off */
.tier-badge.round-pre    { background: var(--round-other); }  /* muted grey — prelim / qualifying / other */
/* Finals — two-tone metallic trophy gradients, black text. Gold for World Cup &
   European club competitions; silver for domestic cups (FA/EFL). */
.tier-badge.round-final-gold {
    --badge-bg: var(--round-final-gold); /* representative gold for the ring (bg is a gradient) */
    background: linear-gradient(135deg, var(--round-final-gold) 0%, var(--round-final-gold-light) 50%, var(--round-final-gold) 100%);
    color: var(--badge-ink);
    white-space: nowrap;
}
.tier-badge.round-final-silver {
    --badge-bg: var(--round-final-silver); /* representative silver for the ring (bg is a gradient) */
    background: linear-gradient(135deg, var(--round-final-silver) 0%, var(--round-final-silver-light) 50%, var(--round-final-silver) 100%);
    color: var(--badge-ink);
    white-space: nowrap;
}
.tier-badge.round-group       { background: var(--badge-bg); color: var(--round-group-ink); font-weight: 600; } /* per-letter pastel → --badge-bg inline */
.tier-badge.round-group-plain { --badge-bg: var(--round-group-plain); background: var(--badge-bg); color: var(--round-group-ink); } /* single pastel (no group letter) */

/* Dark-text (light-fill) badges bleed into the pale kit-/result-tinted match
   rows. A 1px ring restores a crisp edge — a darker shade of each badge's own
   fill (color-mix on its --badge-bg) so it reads as a tonal outline (dark blue
   on pastel blue, etc.) rather than a uniform black. box-shadow (not border)
   adds no width, so bordered + white-text badges stay aligned. The rgba()
   fallback gives a plain dark ring on browsers without color-mix support. */
.tier-badge.tier-1,
.tier-badge.tier-2,
.tier-badge.round-r1,
.tier-badge.round-final-gold,
.tier-badge.round-final-silver,
.tier-badge.round-group,
.tier-badge.round-group-plain {
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.55);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--badge-bg), black 45%);
}

/* Expandable rows */
.games-table tr.expandable {
    cursor: pointer;
}

.games-table tr.expandable:hover {
    filter: brightness(0.92);
}

.game-details-row {
    display: none;
}

.game-details-row.expanded {
    display: table-row;
}

.game-details-row td {
    background: var(--detail-row-bg);
    border-bottom: 2px solid var(--border);
    padding: 0.5rem 0.75rem;
}

.game-details {
    font-size: 0.85rem;
    color: var(--text-mid);
    line-height: 1.6;
}

.game-details strong {
    color: var(--text-dark);
}

/* Details table (2-column layout) */
.game-details .details-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.8rem;
    line-height: 1.4;
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

.game-details .details-table td {
    padding: 0.2rem 0;
    vertical-align: top !important;
    border: none;
}

.game-details .details-table .details-label {
    font-weight: 700 !important;
    font-size: 0.8rem;
    color: var(--text-dark);
    white-space: nowrap;
    width: 1%;
    padding-right: 0.75rem;
}

.game-details .details-table .details-value {
    font-size: 0.8rem;
    color: var(--text-mid);
}

/* Mobile: more spacing between columns */
@media (max-width: 600px) {
    .game-details .details-table .details-label {
        padding-right: 1rem;
    }
}

/* Card expandable details */
.game-card .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.25rem;
}

.game-card .card-header .date {
    margin-bottom: 0;
}

.game-card.expandable {
    cursor: pointer;
}

/* Subtle slide-down/up on expand: grid-template-rows 0fr→1fr animates the inner
   content's auto-height with no JS measuring. The card-details is always laid out
   (so it can transition — display:none can't); its single child is the clipper.
   Visual separators (border/padding) live on the child so they collapse with it
   and don't peek when closed.
   Shared by mobile cards (open trigger = .game-card.expanded) AND the desktop
   detail row (open trigger = .card-details.is-open, toggled by renderDetailAt) —
   both reuse buildMobileDetailsHtml content, so this one mechanism drives both. */
.card-details {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.28s ease;
    font-size: 0.8rem;
    color: var(--text-mid);
    line-height: 1.6;
}

.game-card.expanded .card-details,
.card-details.is-open {
    grid-template-rows: 1fr;
}

/* Clipper: an overflow:hidden BFC so the collapsing content (incl. its top
   margin/border) is fully hidden at 0fr — nothing peeks when closed. */
.card-details-inner {
    overflow: hidden;
    min-height: 0;
}

/* Visual separator lives inside the clipper so it collapses with the content. */
.card-details-inner > * {
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--border);
}

@media (prefers-reduced-motion: reduce) {
    .card-details { transition: none; }
}

/* Desktop detail row: the single full-width cell hosts the .card-details grid.
   Horizontal inset matches the mobile card's 1rem side padding so the lineup
   badges (which hug the outer edges of their columns) get breathing room; the
   per-match gradient wash still spans full width because it lives on the <tr>
   (this <td> is transparent). Vertical spacing is owned by the inner clipper's
   top separator, with a little bottom room. */
.games-table tr.detail-row > td {
    padding: 0 1rem 0.6rem;
}

/* When the whole card carries a gradient (cardBg sets an inline style on the card),
   the expanded details stay transparent so the card's gradient shows through the
   expanded region too — matching the header rather than sitting on an opaque white
   block. (If text legibility ever needs it, a translucent white overlay can be added
   here — but not a fully opaque one.) */

.card-details strong {
    color: var(--text-dark);
}

/* Card details table (mobile 2-column layout) */
.card-details .details-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.8rem;
    line-height: 1.4;
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

.card-details .details-table td {
    padding: 0.2rem 0;
    vertical-align: top !important;
    border: none;
}

.card-details .details-table .details-label {
    font-weight: 700 !important;
    color: var(--text-dark);
    white-space: nowrap;
    width: 1%;
    padding-right: 1rem;
}

.card-details .details-table .details-value {
    color: var(--text-mid);
}

/* Position colour coded squad number badges */
.squad-badge {
    display: inline-block;
    width: 1.8em;
    padding: 0.1em 0;
    border-radius: var(--radius-badge);
    text-align: center;
    font-size: inherit;
    font-weight: inherit;
    font-family: inherit;
    line-height: 1.2;
    color: var(--text-dark);
}

/* Manager badge: a neutral 👔 standing in for a squad number on the outer rail. */
.squad-badge.mgr-badge { background: var(--bg-page); color: var(--text-mid); }

.squad-badge.pos-gk  { background: var(--pos-gk); }
.squad-badge.pos-def { background: var(--pos-def); }
.squad-badge.pos-mid { background: var(--pos-mid); }
.squad-badge.pos-fwd { background: var(--pos-fwd); }

/* Inline 2-letter position badge for player lists. Reuses the .pos-* colour
   classes above via shared selectors. */
.pos-badge {
    display: inline-block;
    min-width: 1.8em;
    padding: 0.1em 0.35em;
    margin-right: 0.4em;
    border-radius: var(--radius-badge);
    text-align: center;
    font-size: 0.75em;
    font-weight: 600;
    color: var(--text-dark);
    vertical-align: 1px;
    letter-spacing: 0.02em;
    /* Read as a UI chip: use the default system font, not the condensed/italic
       player-name font the badge would otherwise inherit (e.g. in the modal). */
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-style: normal;
}
.pos-badge.pos-gk  { background: var(--pos-gk); }
.pos-badge.pos-def { background: var(--pos-def); }
.pos-badge.pos-mid { background: var(--pos-mid); }
.pos-badge.pos-fwd { background: var(--pos-fwd); }
/* A badge alone in a Pos column: drop the gap it keeps from a following name. */
.pos-cell .pos-badge { margin-right: 0; }

/* Backend player IDs (#12345) are a pre-launch debugging aid. Hidden by
   default; revealed only when Debug mode is on (nav.js toggles body.debug-mode).
   Lives here (shared) so any page rendering .player-id inherits the behaviour. */
.player-id { display: none; }
body.debug-mode .player-id { display: inline; }

.detail-toggle-btn {
    background: none;
    border: none;
    cursor: pointer;
    font: inherit;
    font-size: 0.65rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--primary);
    padding: 0.3rem 0.5rem;
    border-radius: var(--radius-small);
}
.detail-toggle-btn:hover {
    text-decoration: underline;
}
.detail-toggle-btn:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* Mobile-card variant of the peek/expand control. */
.mobile-toggle-row {
    text-align: center;
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--border);
}
.mobile-toggle-row .detail-toggle-btn {
    min-height: 44px;
    padding: 0.4rem 0.75rem;
}

/* Modal-opening variant: a bordered pill that reads as a tap action. The inline
   ▾/▴ disclosure arrow is dropped (it no longer expands in place — it opens a modal). */
.detail-toggle-btn--modal {
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    background: var(--bg-white);
    padding: 0.5rem 1.1rem;
}
.detail-toggle-btn--modal:hover {
    text-decoration: none;
    background: var(--bg-page);
    border-color: var(--primary);
}

/* Manager names - slightly bolder */
.games-table .manager-name {
    font-weight: 600;
}

/* Manager records */
.games-table .manager-record {
    color: var(--text-mid);
    line-height: 1.4;
}

/* Mobile card details */
.mobile-details {
    font-size: 0.75rem;
}

.mobile-incident {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: 0.4rem;
    padding: 0.15rem 0;
    font-size: 0.75rem;
    align-items: center;
}

/* Each side splits the scorer (squad badge + name, on the OUTER edge) from the detail
   (goal-type marker + minute + emoji, on the INNER edge nearest the score). */
.incident-home, .incident-away {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.4rem;
    color: var(--text-mid);
    min-width: 0;
}
.incident-player {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    min-width: 0;
    font-size: 0.7rem;          /* match the lineup name size */
    overflow-wrap: anywhere;
}
.incident-player .squad-badge { flex: none; }
/* Away mirrored: badge on the outer (right) edge, like the away lineup rail, and a
   wrapped name right-aligns toward that edge (default left-align would break inward). */
.incident-away .incident-player { flex-direction: row-reverse; }
.incident-away .incident-player .pname { text-align: right; }
.incident-detail { white-space: nowrap; flex: none; }

.incident-score {
    text-align: center;
    white-space: nowrap;
    font-weight: 600;
}

/* Subs tab: each substitution is a two-line cell inside one side's incident column.
   .sub-evt stacks the leaving (line 1) and entering (line 2) players; each line reuses
   the incident player/detail rails (player outer, minute + arrow inner). */
.sub-evt { display: flex; flex-direction: column; gap: 0.1rem; flex: 1; min-width: 0; }
.sub-evt-line {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.4rem;
    min-width: 0;
}
.sub-evt-line .lineup-name { font-size: 0.7rem; overflow-wrap: anywhere; }
.sub-evt-off .lineup-name { color: var(--text-light); }   /* leaving player, slightly muted */
.sub-arrow { font-weight: 700; }
.sub-arrow--off { color: var(--sub-off); }   /* red — player coming off */
.sub-arrow--on  { color: var(--sub-on); }   /* green — player coming on */

/* Merged Timeline tab: goals/cards/subs event rows are hidden until their toggle is
   active; any combination of toggles shows as one chronological list (CSS show/hide,
   no re-render). */
.timeline-scope .mobile-incident.evt-goals,
.timeline-scope .mobile-incident.evt-cards,
.timeline-scope .mobile-incident.evt-subs { display: none; }
.timeline-scope.show-goals .mobile-incident.evt-goals { display: grid; }
.timeline-scope.show-cards .mobile-incident.evt-cards { display: grid; }
.timeline-scope.show-subs  .mobile-incident.evt-subs  { display: grid; }
/* PSO heading is a .mobile-info block — toggled with Goals like its kick rows. */
.timeline-scope .mobile-info.evt-goals { display: none; }
.timeline-scope.show-goals .mobile-info.evt-goals { display: block; }
.timeline-toggles { margin-top: 0.2rem; }

/* Tabbed match detail (modal): a row of section tabs; only the active panel shows.
   Referee/commentators sit in .detail-officials below, always visible. */
.detail-tabs {
    display: flex;
    gap: 0.4rem;
    justify-content: center;
    flex-wrap: wrap;
    /* Pinned to the top of the scrolling body so the section nav stays reachable while
       reading a long section. Full-bleed (negative side margins) over a white bg so
       scrolled content doesn't show beside/behind it. */
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--bg-white);
    margin: 0 -1.25rem 0.85rem;
    padding: 0.75rem 1.25rem 0.6rem;
    border-bottom: 1px solid var(--border);
}
.detail-tab {
    background: none;
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    padding: 0.4rem 0.9rem;
    min-height: 36px;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--text-mid);
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.detail-tab:hover { background: var(--bg-page); }
.detail-tab.active { background: var(--primary); border-color: var(--primary); color: var(--text-on-colour); }
.detail-tab-panel { display: none; }
.detail-tab-panel.active { display: block; }
/* Tabs already separate the sections, so the first block in a panel doesn't need
   its own top divider (the rule that draws it for in-flow stacking). */
.detail-tab-panel > .mobile-section:first-child,
.detail-tab-panel > .lineup-meta-scope:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
}
.detail-officials {
    margin-top: 0.85rem;
    padding-top: 0.65rem;
    border-top: 1px solid var(--border);
}

/* Own-goal ball: emoji are colour glyphs that ignore `color`, so tint the ⚽ red
   via a filter to doubly signal "not a regular goal" alongside the (OG) prefix.
   Experimental — exact hue varies a little by platform emoji font. */
.og-ball {
    display: inline-block;
    filter: grayscale(1) sepia(1) saturate(9) hue-rotate(-50deg) brightness(0.92);
}

.mobile-section {
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--border);
}

.mobile-lineup {
    font-size: 0.7rem;
    line-height: 1.4;
    margin-bottom: 0.25rem;
}

/* Unused subs are appended (greyed) to the end of each team's subs line. */
.mobile-unused {
    color: var(--text-light);
}

/* Starting XI: two columns (home left / away right) at every width — same as
   the desktop aesthetic, which saves vertical space vs stacking. Each player is
   a [badge] Name chip; the position-coloured squad badge replaces the desktop
   table's central badge column. Long names wrap within the column. */
.lineup-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.4rem 1.25rem;
    font-size: 0.7rem;
    line-height: 1.6;
}
.lineup-grid .lineup-col > strong {
    display: block;
    margin-bottom: 0.2rem;
}
/* Manager row sits a little apart from the XI/subs, with a hairline separator. */
.manager-grid {
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px dashed var(--border);
}
/* Each player is a block (badge+name row, then optional metadata rows). */
.lineup-grid .lineup-player { display: block; }
.lineup-grid .lineup-row {
    display: flex;
    align-items: baseline;
    gap: 0.4em;
}
.lineup-grid .lineup-row .squad-badge { flex: none; }
/* Let a long name wrap inside its column instead of overflowing: min-width:0
   lets the flex item shrink below its content width, and overflow-wrap breaks
   an over-long single word (e.g. on a narrow phone column). */
.lineup-grid .lineup-name { min-width: 0; overflow-wrap: anywhere; }
.lineup-home .lineup-row { justify-content: flex-start; }
/* Away mirrored: row-reverse puts the badge on the outer (right) edge as a clean
   aligned rail, with names reading toward the centre. The team label right-aligns
   to sit above its right-edge column. (lineup-away is ON the .lineup-col, so the
   label is a direct child — `.lineup-away > strong`, not a descendant selector.) */
.lineup-away .lineup-row { flex-direction: row-reverse; justify-content: flex-start; }
.lineup-away > strong { text-align: right; }

/* Lineup metadata: indented rows under each player (Club / Age / Stats), toggled
   by buttons at the top of the lineup section. Hidden by default; a class on
   .lineup-meta-scope reveals the matching rows — pure CSS show/hide, no re-render.
   Reuses the sub line-2 indent + condensed/muted styling. */
/* The scope carries the section divider (border-top), so the toggle row sits
   BELOW the line, grouped with the lineups it controls; the first section right
   after the toggles drops its own divider to avoid a double line. */
.lineup-meta-scope { margin-top: 0.5rem; padding-top: 0.5rem; border-top: 1px solid var(--border); }
.lineup-meta-toggles + .mobile-section { margin-top: 0; padding-top: 0; border-top: 0; }
.lineup-meta-toggles { display: flex; justify-content: center; gap: 1.5rem; margin-bottom: 0.6rem; flex-wrap: wrap; }
.lineup-meta-btn {
    /* Plain system font (matches the "Attendance" label), UPPERCASE — reads as UI
       chrome, not match content. 30px height is below the 44px touch ideal, but
       accepted here as this only toggles informational metadata. */
    font-family: inherit; font-style: normal; font-weight: 600;
    font-size: 0.72rem; letter-spacing: 0.03em; text-transform: uppercase;
    min-height: 30px; min-width: 4rem; padding: 0 1.1rem;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid rgba(0, 0, 0, 0.18); background: var(--bg-white); color: var(--text-mid);
    border-radius: var(--radius-control); cursor: pointer;
}
.lineup-meta-btn:hover { background: var(--bg-page); }
.lineup-meta-btn.active { background: var(--primary); color: var(--text-on-colour); border-color: var(--primary); }
.player-meta, .lineup-summary { display: none; }
.lineup-meta-scope.meta-club .pm-club,
.lineup-meta-scope.meta-age .pm-age,
.lineup-meta-scope.meta-stats .pm-stats { display: block; }
.lineup-meta-scope .player-meta {
    /* System font (inherits the body stack) — trialling legibility over the
       condensed face at this small metadata size. */
    font-family: inherit; color: var(--text-light);
    font-size: 0.95em; margin-left: 1.3em;
}
.lineup-meta-scope .lineup-summary {
    font-family: inherit; font-weight: bold; color: var(--text-mid);
    margin-top: 0.3rem;
}
.lineup-away .player-meta,
.subs-away .player-meta { margin-left: 0; margin-right: 1.3em; text-align: right; }
.lineup-away .lineup-summary, .subs-away .lineup-summary { text-align: right; }
/* .lineup-desktop / .lineup-mobile (2026-09-05): the side-by-side grid above is
   ONE of two lineup layouts always built into the DOM — CSS shows exactly one per
   viewport width, same build-both approach as games-display.js's table/card split.
   Desktop keeps the two-column side-by-side grid + Nationality/Age/Stats toggles
   unchanged (rules above); mobile switches to one-team-at-a-time tabs below. */
.lineup-mobile { display: none; }
@media (max-width: 600px) {
    .lineup-desktop { display: none; }
    .lineup-mobile { display: block; }
}

/* Mobile one-team-at-a-time lineup: a tab per team (switchLineupTeam), then that
   team's XI/Bench with EVERY field always visible (no toggle needed — only one
   team's worth of players is on screen), each player a 2x2 grid:
     [badge + name]      [age, born ...]
     [nationality/club]  [Nth app (N goals)]
   Both teams' sections are always in the DOM; team-home/team-away on the scope
   (set by switchLineupTeam) shows only the matching .mp-team via CSS. */
.team-tabs { display: flex; gap: 0.5rem; margin-bottom: 0.6rem; }
.team-tab-btn {
    /* Matches .lineup-meta-btn's size — a new control, but the same UI language. */
    flex: 1; font-family: inherit; font-weight: 600; font-size: 0.72rem;
    min-height: 36px; padding: 0 0.5rem;
    border: 1px solid rgba(0, 0, 0, 0.18); background: var(--bg-white); color: var(--text-mid);
    border-radius: var(--radius-control); cursor: pointer;
}
.team-tab-btn.active { background: var(--primary); color: var(--text-on-colour); border-color: var(--primary); }
.mp-team { display: none; }
.lineup-mobile-scope.team-home .mp-team-home,
.lineup-mobile-scope.team-away .mp-team-away { display: block; }
/* Matches .lineup-grid .lineup-col > strong's size (the old desktop-shared
   heading) — same reasoning as .mp-player below. */
.mp-heading { font-weight: bold; font-size: 0.7rem; margin: 0.5rem 0 0.3rem; }
.mp-heading:first-child { margin-top: 0; }
.mp-player {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 1rem;
    row-gap: 0.15rem;
    padding: 0.35rem 0;
    border-bottom: 1px solid var(--border);
    /* Matches .lineup-grid's desktop size (the old mobile layout inherited it
       unchanged — only the column gap shrank at ≤600px, not the font). */
    font-size: 0.7rem;
}
.mp-name { display: flex; align-items: baseline; gap: 0.4em; font-weight: 600; }
.mp-name .lineup-name { min-width: 0; overflow-wrap: anywhere; }
.mp-age, .mp-apps { text-align: right; color: var(--text-light); }
.mp-nat { color: var(--text-light); }
/* mobileSection() reuses metaSummary()'s .lineup-summary divs (the per-team
   totals line) for the same content the desktop Stats toggle reveals — but
   .lineup-summary is `display:none` by default, only shown via a meta-* class
   on an ANCESTOR .lineup-meta-scope (the desktop toggle mechanism). The mobile
   scope has no such toggle — everything always shows — so it needs its own
   override here, or these totals silently stay hidden. */
.lineup-mobile-scope .lineup-summary {
    display: block; font-family: inherit; font-weight: bold;
    color: var(--text-mid); margin-top: 0.3rem;
}

@media (max-width: 600px) {
    /* Desktop-hidden at this width, but kept here (rather than moved) so the
       gap rule stays next to the layout it belongs to. Away stays mirrored
       (badge on the right rail), names wrap as needed. */
    .lineup-grid { gap: 0.3rem 0.6rem; }
}

/* The bench reuses the .lineup-grid / .lineup-col styles (it's rendered with the
   same col/chip helpers as the starting XI); the swap detail moved to the Timeline. */

.mobile-info {
    font-size: 0.7rem;
    color: var(--text-mid);
    padding: 0.1rem 0;
}

/* Neutral section heading (e.g. "Penalty shoot-out") — centred because it spans
   both teams, unlike the team-specific left/right lineup labels. */
.mobile-info.pso-heading {
    text-align: center;
}

/* === Expanded-detail context blocks (WC group/knockout matches) === */

/* Group-table snapshot (pos/P/W/D/L/GD/Pts; the two teams highlighted). */
.group-table-snapshot { margin: 0.5rem 0; }
.group-table-snapshot .gt-title,
.match-context .mc-title {
    font-size: 0.7rem;
    font-weight: 700;
    color: var(--text-mid);
    margin-bottom: 0.25rem;
}
.group-table-snapshot .gt-title { text-align: center; }
.gt-table { width: 100%; border-collapse: collapse; font-size: 0.7rem; color: var(--text-mid); }
.gt-table th { font-weight: 600; color: var(--text-light); text-align: right; padding: 0.1rem 0.25rem; border-bottom: 1px solid var(--border); }
.gt-table td { text-align: right; padding: 0.1rem 0.25rem; white-space: nowrap; }
.gt-table .gt-pos { color: var(--text-light); }
.gt-table .gt-team { text-align: left; width: 99%; color: var(--text-dark); }
.gt-table .gt-pts { font-weight: 700; color: var(--text-dark); }
.gt-table tbody tr.gt-hi { background: color-mix(in srgb, var(--primary) 12%, transparent); }
.gt-table tbody tr.gt-hi .gt-team { font-weight: 700; }

/* Generic context wrapper + compact, header-less tables. */
.match-context { margin: 0.5rem 0; font-size: 0.7rem; color: var(--text-mid); }
/* In the Context tab (and the unplayed peek), the optional leading blocks — group
   table, then prior results — carry a BOTTOM divider so they're separated from the
   always-present WC head-to-head below. Putting the divider at the bottom (and only
   when a block follows) means a skipped block never leaves a stray or doubled line. */
.group-table-snapshot:not(:last-child),
.match-context.results-so-far:not(:last-child) {
    padding-bottom: 0.75rem;
    border-bottom: 1px solid var(--border);
}
/* "Results so far" section: centred section heading, then the two team columns,
   then a centred per-stadium history table. */
.rsf-heading, .venue-history .vh-title { text-align: center; }
.venue-history { margin-top: 0.6rem; }
.match-context table { border-collapse: collapse; font-size: 0.7rem; color: var(--text-mid); }
.match-context td { padding: 0.05rem 0.3rem; white-space: nowrap; }

/* Prior group games — two columns under the teams (home left, away right). */
.prior-games { display: flex; gap: 1rem; align-items: flex-start; }
.prior-games .pg-side { flex: 1; min-width: 0; }
.prior-games .pg-home { text-align: left; }
.prior-games .pg-away { text-align: right; }
.pg-table { width: 100%; }
.prior-games .pg-away .pg-table { margin-left: auto; }
.pg-table .pg-score { font-weight: 700; color: var(--text-dark); }
.pg-table .pg-city { color: var(--text-light); }
.pg-table .pg-none { color: var(--text-light); }

/* Head-to-head — centred, oriented to the home team. */
.match-context.h2h .h2h-heading { text-align: center; }
.match-context.h2h .h2h-none { text-align: center; color: var(--text-light); }
.h2h-table { margin: 0 auto; }
.h2h-table .h2h-score { font-weight: 700; color: var(--text-dark); text-align: center; }
.h2h-table .h2h-round { color: var(--text-light); }
.h2h-table .h2h-city { color: var(--text-light); }

/* City columns drop on narrow screens to save width. */
@media (max-width: 600px) {
    .pg-table .pg-city, .h2h-table .h2h-city { display: none; }
}

/* Third card row (mobile): same left/right layout as the header — venue left, broadcaster
   badge right. Rendered after .card-details, so it sits directly under the fixture when
   collapsed and drops to the bottom of the expansion when open. When expanded it gains a
   top divider to separate it from the detail content above. */
.game-card .card-meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.25rem;
}
.game-card .card-meta .card-meta-venue {
    font-size: 0.75rem;
    color: var(--text-light);
}
.game-card .card-meta .card-meta-badges {
    flex-shrink: 0;
}
.game-card.expanded .card-meta {
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--border);
}

.broadcaster-badge {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: 600;
    padding: 0.15rem 0.4rem;
    border-radius: var(--radius-badge);
    background: var(--bg-page);
    color: var(--text-mid);
    border: 1px solid var(--border);
}
/* Channel colours. A family default (gold BBC / dark-green ITV) covers un-themed
   variants (BBC Scotland, ITV2, …); the specific channels below override it with
   their corporate brand colours. The border matches the fill (darkened for the
   light/bright chips) so badges read as solid chips, not bordered ones. */
.broadcaster-badge.bbc { background: var(--bc-bbc); color: var(--bc-ink-dark); border-color: rgba(0,0,0,0.6); border-color: color-mix(in srgb, var(--bc-bbc), black 45%); }
.broadcaster-badge.itv { background: var(--bc-itv); color: var(--text-on-colour); border-color: color-mix(in srgb, var(--bc-itv), black 30%); }

/* Per-channel overrides (must follow the family rules — equal specificity, later wins).
   All keep WCAG AA (≥4.5:1). Split by family: BBC channels run white text on a deeper
   fill; ITV channels run black text on a bright fill (brightened slightly above the
   corporate colour so black reads well at a distance, and so the bright ITV cyan stays
   clearly distinct from BBC2's deep teal):
     BBC1 — red darkened from #E8504B → white (4.6:1)
     BBC2 — brightened ~halfway back toward the brand #10A88D, capped → white (4.6:1)
     ITV1 — corporate cyan #1CCBD4 brightened slightly → black (~12:1)
     ITV4 — vivid lime → black (~13:1) */
.broadcaster-badge.bbc1 { background: var(--bc-bbc1); color: var(--text-on-colour); border-color: color-mix(in srgb, var(--bc-bbc1), black 30%); }
.broadcaster-badge.bbc2 { background: var(--bc-bbc2); color: var(--text-on-colour); border-color: color-mix(in srgb, var(--bc-bbc2), black 30%); }
.broadcaster-badge.itv1 { background: var(--bc-itv1); color: var(--bc-ink-dark); border-color: color-mix(in srgb, var(--bc-itv1), black 35%); }
.broadcaster-badge.itv4 { background: var(--bc-itv4); color: var(--bc-ink-dark); border-color: color-mix(in srgb, var(--bc-itv4), black 35%); }

.no-details {
    font-size: 0.7rem;
    color: var(--text-light);
    font-style: italic;
    text-align: center;
    padding: 0.5rem;
}

.games-pagination {
    padding: 0.75rem 1.25rem;
    border-top: 1px solid var(--border);
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: var(--bg-page);
    flex-shrink: 0;
}

/* `hidden` must actually hide. The display:flex above beats the UA stylesheet's
   [hidden] { display: none }, so players-view.js's pager — hidden whenever a table fits on one
   page — still drew a 25px empty bar with a top border under every short player table on six
   pages (2026-09-16). An author display rule always wins over the attribute; say so explicitly. */
.games-pagination[hidden] { display: none; }

.games-pagination button {
    padding: 0.5rem 1rem;
    min-height: 44px;
    flex: none;
}

.games-pagination .page-info {
    font-size: 0.85rem;
    color: var(--text-mid);
}
/* "(n / N)" position suffix beside a stage page label ("Group A (3 / 9)") */
.page-info .page-pos { color: var(--text-light); font-weight: 400; }

@media (max-width: 600px) {
    .games-table {
        display: none;
    }
    .games-cards {
        display: block;
    }
}

/* Floating scroll-to-pagination button */
/* Always in DOM but hidden; visible class + mobile media query reveal it */
.scroll-to-pagination-btn {
    display: none;
    position: fixed;
    bottom: 1.25rem;
    right: 1rem;
    z-index: 100;
    background: var(--primary);
    color: var(--text-on-colour);
    border: none;
    border-radius: var(--radius-float);
    padding: 0.625rem 1rem;
    font-size: 0.875rem;
    font-weight: 600;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
    min-height: 44px;
    align-items: center;
    gap: 0.375rem;
    white-space: nowrap;
}

@media (max-width: 600px) {
    .scroll-to-pagination-btn.visible {
        display: flex;
    }
}

/* The detail modal owns the screen — hide the floating page-nav button beneath it. */
body.detail-modal-open .scroll-to-pagination-btn { display: none !important; }

/* ============================================
   Ranking Tables (shared utilities)
   Used by: player_rankings.html, player_streaks.html
   ============================================ */

/* Player name with optional stacked club context */
/* Player name and club context in data tables */
.player-name {
    font-weight: 500;
    max-width: 280px;
}

/* Player-name display treatment — see db-utils getFullNameHtml(). Self-contained:
   .pname carries the condensed font AND light letter tracking, so a styled name gets
   the full treatment in ANY context (listing tables, match detail, …) with no
   container font rule to remember. The surname is uppercased in CSS only, so the
   stored "Surname, Firstname" text is never mutated (search/copy/keys stay intact).
   (Container rules like `.players-table .player-name` are retained — they also
   condense PLAIN, non-.pname names such as managers.) */
.pname { font-family: var(--font-condensed); letter-spacing: 0.0225em; }
/* Caps read tighter than lowercase, so the uppercased surname gets a touch more tracking. */
.player-surname { text-transform: uppercase; letter-spacing: 0.03em; }
/* Run-on Mc/Mac prefix keeps its stored casing (McGRATH, MacALLISTER) — see getFullNameHtml. */
.name-prefix { text-transform: none; }

/* Match-detail player names get the condensed/uppercase treatment from the global
   .pname rule above (self-contained). overflow-wrap lets an over-long uppercased
   surname break inside a narrow phone lineup column (the text is nested in
   .pname/.player-surname, and overflow-wrap doesn't inherit). */
.card-details .lineup-name .pname,
.card-details .lineup-name .player-surname { overflow-wrap: anywhere; }

/* "#id" after a manager/referee name - two records can share a name (formatOfficialNameHtml) */
.manager-id {
    font-size: 0.75rem;
    color: var(--text-faint);
    font-weight: 400;
    margin-left: 0.5rem;
}

/* Club context displayed below player name in same cell */
.club-context {
    font-size: 0.75rem;
    color: var(--text-light);
    display: block;
    word-wrap: break-word;
}

/* Two-row match cell: the fixture + score in the Univers display font on top, with a
   .club-context sub-line beneath for the competition/round. Mirrors player-name +
   club-context so a match reads the same way a player does. */
.match-line {
    display: block;
    font-family: var(--font-condensed);
    font-weight: 700;
    font-style: italic;
    font-size: 0.95rem;
    color: var(--text-dark);
}

/* Wider player column on larger screens */
@media (min-width: 768px) {
    .player-name {
        max-width: 360px;
    }
}

/* ============================================
   Rank pills (HIGHEST / LOWEST) - markup from db-utils.js rankBadge(), on every page
   ============================================ */
.rank-badge {
    display: inline-block;
    padding: 0.15rem 0.55rem;
    border-radius: var(--radius-pill);
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    line-height: 1.3;
    white-space: nowrap;
    vertical-align: middle;
    color: var(--text-on-colour);
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.rank-badge.highest { background: var(--highest); }
.rank-badge.lowest  { background: var(--lowest); }
/* Inline after a value in a stat row; a stat tile gives it its own line (.stat-tile-badge). */
.stat-value .rank-badge { margin-left: 0.35rem; }

/* ============================================
   Tier Grid
   ============================================ */
.tier-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.75rem;
}

@media (min-width: 500px) {
    .tier-grid {
        grid-template-columns: repeat(4, 1fr);
    }
}

.tier-item {
    text-align: center;
    padding: 0.75rem;
    background: var(--bg-page);
    border-radius: var(--radius-control);
}

.tier-item.inactive {
    opacity: 0.4;
}

.tier-value {
    font-family: 'SF Mono', 'Consolas', 'Monaco', 'Courier New', monospace;
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--primary);
}

.tier-label {
    font-size: 0.8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-light);
    margin-top: 0.15rem;
}

.tier-years {
    font-size: 0.7rem;
    color: var(--text-light);
    font-family: 'SF Mono', 'Consolas', 'Monaco', 'Courier New', monospace;
}

/* ============================================
   Matchup Row
   ============================================ */
.matchup-row {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    padding: 0.4rem 0;
    border-bottom: 1px solid var(--bg-page);
    gap: 1rem;
}

.matchup-row:last-child {
    border-bottom: none;
}

.matchup-label {
    font-size: 0.85rem;
    color: var(--text-mid);
    flex-shrink: 0;
}

.matchup-value {
    text-align: right;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
}

.matchup-count {
    font-family: 'SF Mono', 'Consolas', 'Monaco', 'Courier New', monospace;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--primary);
}

.matchup-name {
    font-size: 0.75rem;
    color: var(--text-light);
    max-width: 250px;
    word-break: break-word;
}

/* ============================================
   Entity Header (Club/Manager/Scoreline/Streak/Table)
   Fixed height with flexbox centering for consistent sticky alignment
   ============================================ */
.entity-header {
    background: var(--bg-white);
    border-radius: var(--radius-card);
    padding: 0.5rem 1rem;
    margin-bottom: 1rem;
    box-shadow: var(--shadow);
    text-align: center;
    position: sticky;
    top: 76px;
    z-index: 100;
    height: 90px;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    justify-content: center;
    overflow: hidden;
}

.entity-name {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--primary);
    margin-bottom: 0.15rem;
    line-height: 1.2;
}

.entity-results {
    font-size: 0.8rem;
    color: var(--text-mid);
}

.entity-metadata {
    font-size: 0.8rem;
    color: var(--text-light);
}

/* ============================================
   Results Container
   ============================================ */
#results {
    display: none;
    margin-top: 0.75rem;
}

/* ============================================
   Percentage Display
   ============================================ */
.stat-value .pct {
    color: var(--text-light);
    font-size: 0.8rem;
}

/* ============================================
   N/A Text (for unavailable stats)
   ============================================ */
.na-text {
    color: var(--text-light);
    font-style: italic;
}

/* ============================================
   Data Tables (.players-table)
   Used by entity pages (sortable) and analytics pages (static section-table)
   ============================================ */
.players-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--bg-white);
    box-shadow: var(--shadow);
}

/* Scorelines view stacks two .players-table blocks (Margins, then Scores);
   space them so the second table reads as a distinct group. */
.scorelines-block + .scorelines-block {
    margin-top: 1.5rem;
}

.players-table thead {
    position: sticky;
    top: var(--nav-height, 194px);
    z-index: 100;
}

/* players-view.js optional count column (Seasons / WCs). The <th>/<td> always
   render with `.period-col`; the module toggles `.hide-period` on the table to
   drop the whole column for data sets where the count is meaningless (e.g.
   world_cups per-tournament mode, where every player has exactly one WC). */
.players-table.hide-period .period-col {
    display: none;
}

/* players-view.js optional identity column (Nationality domestic / Club on
   world_cups). Same hide mechanism as the count column — world_cups drops it in
   all-time mode (no single club applies); domestic pages always show it.
   (Left-alignment is set after the numeric-column centering rule below.) */
.players-table.hide-identity .identity-col {
    display: none;
}

/* Nationality cell: emoji flag + name on desktop; the name collapses to flag-only
   on mobile (see the media query below), but the column itself stays visible.
   Emoji scale crisply at any size (unlike the old raster flag images). */
.players-table .nat-flag {
    margin-right: 0.35rem;
}

.players-table th {
    text-align: left;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--text-light);
    padding: 0.6rem 0.35rem;
    border-bottom: 2px solid var(--border);
    background: var(--bg-page);
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

.players-table th:hover {
    background: var(--hover-bg);
}

.players-table th.sorted {
    color: var(--primary);
}

.players-table th .sort-indicator {
    display: inline-block;
    width: 0.6rem;
    text-align: center;
    margin-left: 0.1rem;
    font-size: 0.6rem;
}

.players-table td {
    padding: 0.5rem 0.35rem;
    border-bottom: 1px solid var(--border);
    text-align: left;
    font-size: 0.85rem;
    /* Top-align so stat values sit beside the first line of a multi-line entity
       name (e.g. a player/manager with a long wrapped club history) rather than
       floating to the vertical centre of a tall row. */
    vertical-align: top;
}

.players-table td:first-child {
    font-weight: 500;
}

/* Numeric columns center-aligned */
.players-table td:not(:first-child),
.players-table th:not(:first-child) {
    text-align: center;
}

/* …but the identity column (Nationality / Club) is a label, not a stat — keep it
   left-aligned. The :not(:first-child) (always true — identity is never the first
   column) bumps specificity above the numeric-centering rule so it wins. */
.players-table td.identity-col:not(:first-child),
.players-table th.identity-col:not(:first-child) {
    text-align: left;
}

/* WC event tables (hat-tricks, red cards, own goals, penalties): Player is
   column 2 (Date is column 1), so left-align its header to match the
   left-aligned name cells (other tables put Player first). */
#hatTricksTable th:nth-child(2),
#redCardsTable th:nth-child(2),
#ownGoalsTable th:nth-child(2),
#penaltiesTable th:nth-child(2),
/* td too: on player pages column 2 is a plain Club link (no flex cell) and would
   otherwise be centred by .players-table td:not(:first-child). Harmless for the
   club/WC pages where column 2 is a left-aligned .player-name-cell. */
#hatTricksTable td:nth-child(2),
#redCardsTable td:nth-child(2),
#ownGoalsTable td:nth-child(2),
#penaltiesTable td:nth-child(2) {
    text-align: left;
}

/* H/A/N indicator in the domestic event-view "vs" cell (club-events.js) */
.venue-tag {
    color: var(--text-light);
    font-size: 0.85em;
    margin-left: 0.15rem;
}

/* Section tables: sticky headers like all other players-table instances */
/* (--nav-height is set dynamically by each page's ResizeObserver) */
.players-table.section-table th {
    cursor: default;
}
.players-table.section-table th:hover {
    background: var(--bg-page);
}
/* Shrink non-name columns to content width */
.players-table.section-table th,
.players-table.section-table td {
    white-space: nowrap;
    width: 1%;
    padding-left: 0.6rem;
    padding-right: 0.6rem;
}
/* Name column (2nd) takes remaining space */
.players-table.section-table th:nth-child(2),
.players-table.section-table td:nth-child(2) {
    width: auto;
    white-space: normal;
    text-align: left;
    padding-left: 0.4rem;
    padding-right: 0.4rem;
}
/* Name-FIRST section tables (records boards): no leading rank column, so the
   name/match column is column 1 and takes the width; value columns shrink to the
   right. Higher specificity (:not) beats the nth-child(2) rule above regardless of
   order. Used by the records-board redesign (project_records_board_redesign). */
.players-table.section-table.name-first td:first-child,
.players-table.section-table.name-first th:first-child {
    width: auto;
    white-space: normal;
    text-align: left;
}
.players-table.section-table.name-first td:not(:first-child),
.players-table.section-table.name-first th:not(:first-child) {
    width: 1%;
    white-space: nowrap;
    text-align: right;
}
/* Live total row: lighter styling */
.players-table.section-table tr.milestone-live {
    color: var(--text-light);
    font-style: italic;
}
/* Performance-per-Season (mobile): the separate Lg column is hidden and the
   tier is folded into the Pos cell as a muted prefix (e.g. "T1 2nd") to save
   horizontal space without losing the sticky header to a scroll wrapper.
   Hidden on desktop (Lg column shows there); revealed inline on mobile below. */
.season-perf .tier-prefix {
    display: none;
    color: var(--text-light);
    font-weight: 400;
}
/* Stacked match-detail sub-line under the player name in event tables — shown
   only on mobile (see the @media block), where the per-field columns collapse. */
.event-mobile-line {
    display: none;
}

/* ============================================
   Stacked-text cells (Player/Stadium name + sub-line)
   Used by every entity page (clubs, managers, players, referees,
   stadiums, competitions, scorelines, nations) for tabular rows
   that show a primary label on top with year-range / city /
   match-detail underneath in lighter sub-text.
   Promoted from page-local duplicates 2026-05-02.
   ============================================ */
.player-name-cell {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    text-align: left; /* keep left-aligned even when the cell isn't column 1 (e.g. WC hat-tricks) */
}

.player-years {
    font-size: 0.75rem;
    color: var(--text-light);
    font-weight: 400;
}

.player-name-cell a,
.player-card-name a {
    color: var(--text-dark);
    text-decoration: none;
    border-bottom: 1px dotted var(--primary);
    transition: color 0.2s, border-color 0.2s;
}

.player-name-cell a:hover,
.player-card-name a:hover {
    color: var(--primary);
    border-bottom-style: solid;
}

.player-name-cell a:visited,
.player-card-name a:visited {
    color: var(--text-mid);
}

.match-detail-cell {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    align-items: center;
}

.match-date {
    font-size: 0.8rem;
    font-weight: 500;
}

.match-opponent {
    font-size: 0.7rem;
    color: var(--text-light);
    font-weight: 400;
    text-align: center;
}

/* Goal-aggregation views (Goal Minute / Squad Number): the First/Last subtitle is
   "Scorer / TEAM gf-ga OPP" on two centred lines — the scorer name always on its
   own line, the scoreline (kept unbreakable) beneath it. */
.match-opponent .gm-scorer { display: block; }
.match-opponent .gm-fixture { white-space: nowrap; }

/* Mobile: tighter spacing for data tables */
@media (max-width: 600px) {
    .players-table th,
    .players-table td {
        padding: 0.5rem 0.3rem;
        font-size: 0.8rem;
    }

    .players-table td:first-child {
        max-width: 140px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* Stacked name cells (name + subtitle — e.g. stadium / player views) should
       WRAP within the narrow first column rather than truncate. The clip rule
       above is for single-line cells; here the subtitle (city + active years)
       commonly runs off on the constrained mobile viewport, so let it wrap. */
    .players-table td:first-child:has(.player-name-cell) {
        overflow: visible;
        white-space: normal;
    }
    .players-table td:first-child .player-name-cell,
    .players-table td:first-child .player-name-cell span,
    .players-table td:first-child .player-name-cell a {
        white-space: normal;
        overflow: visible;
        text-overflow: clip;
    }

    .players-table th.hide-mobile,
    .players-table td.hide-mobile {
        display: none;
    }

    /* Identity column on mobile: keep the column (the flag is a useful at-a-glance
       cue) but drop the nationality NAME and the column's header text, leaving a
       compact flag-only column. */
    .players-table .nat-name,
    .players-table .identity-col .col-label {
        display: none;
    }

    /* Streak tables (player_streaks / manager_streaks): the date range stacked
       under the streak count is monospace and, with human-readable dates, too
       wide for one line on mobile — let it wrap so the column doesn't force
       horizontal overflow. */
    .streak-dates {
        white-space: normal;
    }

    /* Player-event tables (Hat-tricks / Red Cards / Own Goals / Penalties) are
       too wide for mobile with one column per field. Instead of dropping data,
       collapse to Date · Player(+stacked match detail) [· ⚽ for penalties]:
       the vs / minute / goals / season columns hide (hide-mobile) and their
       values stack under the player name via .event-mobile-line. Mirrors the
       Stadiums view (name + city stacked in column 1). */
    .event-mobile-line {
        display: block;
        margin-top: 0.15rem;
        font-size: 0.72rem;
        font-weight: 400;
        color: var(--text-light);
        white-space: normal;
    }

    /* Performance-per-Season is the widest section table (every cup column is
       meaningful, so none can be dropped). After folding Lg into Pos it's still
       a hair wide for the card on the narrowest phones — tighten its cell
       padding just on mobile so it fits without a scroll wrapper. */
    .players-table.section-table.season-perf th,
    .players-table.section-table.season-perf td {
        padding-left: 0.3rem;
        padding-right: 0.3rem;
    }

    /* Reveal the tier prefix inline within the Pos cell on mobile. */
    .season-perf .tier-prefix {
        display: inline;
    }

    /* Stacked-text cells on mobile: ellipsis-truncate the parent and hide
       the sub-line, except on stadium-city sub-lines which stay visible. */
    .players-table .player-name-cell {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    /* Show the name-cell subtitle (active years / city) on mobile across ALL
       name-cell views — it carries important context and now wraps cleanly
       within the column (see the td:first-child wrap override above). Was
       previously hidden on mobile except for the stadiums view. */
    .players-table .player-years { display: block; }
}

/* ============================================
   Footer
   ============================================ */
footer {
    background: var(--text-dark);
    color: white;
    text-align: center;
    padding: 1.5rem;
    margin-top: 2rem;
    font-size: 0.85rem;
    flex-shrink: 0;
}

footer a {
    color: white;
    text-decoration: none;
}

footer a:hover {
    text-decoration: underline;
}

.footer-disclaimer {
    display: block;
    max-width: 720px;
    margin: 0 auto 0.75rem;
    font-size: 0.8rem;
    color: rgba(255, 255, 255, 0.7);
    line-height: 1.4;
}

/* ============================================
   Error State
   ============================================ */
.error {
    background: var(--error-bg);
    border: 1px solid var(--error-border);
    border-radius: var(--radius-card);
    padding: 1.5rem;
    color: var(--error-text);
    text-align: center;
}

/* ============================================
   No Results
   ============================================ */
.no-results {
    text-align: center;
    padding: 2rem;
    color: var(--text-light);
}

/* ============================================
   Mobile Responsive (900px - Navigation)
   ============================================ */
@media (max-width: 900px) {
    nav .container {
        padding: 0 1rem;
    }

    /* Keep the full-bleed bar's negative margin locked to the reduced
       container padding (1rem) — else it over-corrects by 16px each side
       and spills past the viewport at narrow widths (WCAG 1.4.10 reflow). */
    .nav-top-row {
        margin: -0.25rem -1rem 0.25rem;
        padding: 0.5rem 1rem 0.25rem;
    }

    .main-container {
        padding: 0 1rem;
    }

    .mobile-menu {
        right: 1rem;
    }

    .nav-brand span {
        font-size: clamp(0.9rem, 4.6vw, 1.2rem);
    }

    .entity-header {
        top: 71px;
    }

    .entity-name {
        font-size: 1.1rem;
    }
}

/* ============================================
   Mobile Responsive (600px - Content)
   ============================================ */
@media (max-width: 600px) {
    .hero h1 {
        font-size: 1.5rem;
    }

    .stat-label, .stat-value {
        font-size: 1rem;
    }

    .legend-item {
        font-size: 0.9rem;
    }

    .section-title {
        font-size: 0.85rem;
    }
}

/* ============================================
   Reduced Motion (Accessibility - WCAG 2.3.3)
   Respects user's OS preference for reduced motion
   ============================================ */
@media (prefers-reduced-motion: reduce) {
    /* Disable hero gradient animation */
    .hero {
        animation: none;
        background-position: 50% 50%;
    }

    /* Disable hero pulse overlay */
    .hero::before {
        animation: none;
        opacity: 0.3;
    }

    /* Keep spinner but make it gentler (still functional feedback) */
    .spinner {
        animation-duration: 2s;
    }

    /* Remove transitions for hover effects */
    button,
    .section-header .toggle,
    .filter-group select,
    .filter-group input,
    .league-table tbody tr {
        transition: none;
    }

    /* Skip link can slide without transition */
    .skip-link {
        transition: none;
    }

    /* Disable any transform-based hover effects */
    .btn-primary:hover,
    .btn-secondary:hover {
        transform: none;
    }
}

/* ========================================
   CONSOLIDATED CLASSES (Moved from individual pages)
   ======================================== */

/* Entity Page Classes
   Used by: clubs, managers, players, referees, stadiums, competitions, scorelines */

.matchup-value {
    font-size: 0.95rem;
}

.pct {
    font-size: 0.9rem;
}

.year-range-inputs {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.year-range-field {
    flex: 1;
    min-width: 0;
}

.year-range-field select {
    width: 100%;
}

.year-range-group {
    border: none;
    padding: 0;
    margin: 0;
}

.year-range-group legend {
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-light);
    padding: 0;
    margin-bottom: 0.25rem;
}

.year-range-separator {
    color: var(--text-light);
    font-weight: 500;
    flex-shrink: 0;
}

@media (max-width: 600px) {
    .year-range-group {
        grid-column: 1 / -1;
    }
}

/* Analytics Page Classes
   Used by: rankings, streaks, table, player_rankings, player_streaks, manager_streaks */

.entity-name {
    font-size: 1.2rem;
}

.full-width {
    grid-column: 1 / -1;
}

.toggle {
    font-size: 0.8rem;
    color: var(--text-light);
    transition: transform 0.2s;
}

.ranking-table {
    width: 100%;
    border-collapse: collapse;
}

.team-name {
    font-weight: 500;
}

/* EXPERIMENT (2026-06-08): trial the Univers condensed display font on entity
   names across a few table contexts — the domestic league Table, analytics
   team rankings, and player rankings — to compare readability before settling
   any design rules. (Group-table team names are trialled inline in
   world_cups.html, league-table teams inline in table.html.) Easy to revert as
   a set: delete this block + those two. */
.players-table .team-name,
.players-table .player-name,
.players-table .player-name-cell {
    font-family: var(--font-condensed);
    /* Readability tracking for the close-kerned condensed face (e.g. "Sheffield
       Wednesday"'s double-l). Same 0.0225em as player/manager/referee .pname
       names, so every table entity NAME — club, stadium, competition, nation —
       reads consistently. Non-condensed page titles are larger and need none. */
    letter-spacing: 0.0225em;
}
/* …NAME only — keep the stacked subtitles (player id, club/years/city context) in
   the regular body font AND without the name tracking; condensed + tracking read
   poorly on the longer, lower-contrast line. */
.players-table .player-name .player-id,
.players-table .player-name .manager-id,
.players-table .player-name .club-context,
.players-table .player-name-cell .player-years,
.players-table .player-name-cell .club-context,
.players-table .player-name-cell .manager-id {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    letter-spacing: normal;
}

/* Streak Page Classes
   Used by: streaks, player_streaks, manager_streaks */

.streak-filters {
    font-size: 0.8rem;
    color: var(--text-light);
}

.streak-results {
    font-size: 0.8rem;
    color: var(--text-mid);
}

.streak-value {
    font-family: 'SF Mono', 'Consolas', 'Monaco', 'Courier New', monospace;
    font-weight: 600;
    color: var(--primary);
    display: block;
    text-align: right;
}

.streak-dates {
    font-size: 0.75rem;
    color: var(--text-light);
    font-family: 'SF Mono', 'Consolas', 'Monaco', 'Courier New', monospace;
    display: block;
    text-align: right;
    margin-top: 0.2rem;
}
/* Each date (with its trailing "to") is an unbreakable unit, so when the date
   range wraps on mobile (see .streak-dates white-space:normal in the @media
   block) it breaks cleanly between the two dates, not mid-date. */
.streak-dates .sd-d {
    white-space: nowrap;
}

.ongoing {
    display: inline-block;
    background: var(--active-bg);
    color: var(--active-text);
    font-size: 0.65rem;
    font-weight: 600;
    padding: 0.15rem 0.4rem;
    border-radius: var(--radius-badge);
    margin-left: 0.5rem;
    text-transform: uppercase;
}

/* ============================================
   Entity Selector in Nav (Prototype)
   ============================================ */

/* Entity nav header row (contains selector + filters button) */
/* Two-column layout: left (name + metadata) / right (filters + results) */
.entity-nav-columns {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
}

.entity-nav-left {
    display: flex;
    flex-direction: column;
    min-width: 0; /* Allow text truncation */
    flex-shrink: 0;
    max-width: 60%; /* Leave room for pills/filters on the right */
}

.entity-nav-right {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    text-align: right;
    flex: 1 1 auto; /* Grow to fill space, shrink to allow title room */
    min-width: 0; /* Allow pills to wrap rather than overflow */
    cursor: pointer;
}

.entity-nav-right:hover .entity-nav-filters {
    color: var(--primary);
}

/* Legacy class kept for other pages that still use it */
.entity-nav-header-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    position: relative;
}

/* Spacer hidden by default, available for centered layouts if needed */
.entity-nav-header-row::before {
    display: none;
}

/* Entity selector button */
.entity-selector-btn {
    background: transparent;
    border: none;
    font-family: 'Sequel Sans Black', 'Arial Black', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 1.5rem;
    font-weight: 900;
    font-style: normal;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-strong);
    cursor: pointer;
    padding: 0.25rem 1rem 0.25rem 0;
    border-radius: var(--radius-small);
    transition: background 0.2s;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    text-align: left;
}

.entity-selector-btn:hover {
    background: var(--bg-page);
}

.entity-selector-btn .selector-icon {
    font-size: 0.8rem;
    color: var(--text-light);
}

/* View selector (the "Matches / Group Tables / …" dropdown next to the entity
   name). A native <select> sits invisibly over a styled uppercase label so we
   get the native dropdown UX with custom typography. One step below the entity
   selector in the size hierarchy (1.35 vs 1.5rem) — see the mobile reduction in
   the max-width:600px block. Shared by every entity + analytics page. */
.nav-view-selector-wrap {
    position: relative;
    align-self: flex-start;
    cursor: pointer;
}
.nav-view-label {
    font-family: 'Sequel Sans Black', 'Arial Black', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 1.35rem;
    font-weight: 900;
    font-style: normal;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-light);
    pointer-events: none;   /* clicks fall through to the native select below */
    white-space: nowrap;
    padding-right: 1rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%235a5a5a' d='M2 4l4 4 4-4'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0 center;
}
.nav-view-selector-wrap:hover .nav-view-label { color: var(--text-strong); }
.nav-view-selector {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
    font-size: 1rem;   /* ≥16px keeps iOS from zooming the page on focus */
}
.nav-view-selector:focus + .nav-view-label,
.nav-view-selector:focus-visible + .nav-view-label {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
    border-radius: var(--radius-small);
}

/* Entity filters button (opens filters modal) */
.entity-filters-btn {
    background: rgba(0, 0, 0, 0.07);
    color: var(--text-mid);
    border: 1px solid rgba(0, 0, 0, 0.12);
    font-family: var(--font-condensed);
    font-size: 0.85rem;
    font-weight: 700;
    font-style: italic;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    cursor: pointer;
    padding: 0.2rem 0.75rem;
    min-height: 28px;
    display: flex;
    align-items: center;
    border-radius: var(--radius-small);
    transition: background 0.2s, transform 0.1s;
    margin-left: auto;
}

.entity-filters-btn:hover {
    background: rgba(0, 0, 0, 0.13);
    transform: translateY(-1px);
}

.entity-filters-btn:active {
    transform: translateY(0);
}

/* Entity metadata in nav */
.entity-nav-metadata {
    font-size: 0.8rem;
    color: var(--text-light);
    margin-top: 0;
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

.entity-nav-metadata div,
.entity-nav-filters div {
    line-height: 1.4;
    padding: 1px 0;
}

/* Entity filters in nav */
.entity-nav-filters {
    font-size: 0.75rem;
    color: var(--text-mid);
    margin-top: 0;
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

/* Filter pills (inside entity-nav-filters) */
.filter-pills {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.2em 0.35rem;
    max-height: 3.9em;
    overflow: hidden;
    font-size: 0.78rem;
}

/* When filters button is hidden (e.g. index.html), show all pills — no overflow */
.entity-filters-btn[style*="display:none"] ~ .entity-nav-filters .filter-pills {
    max-height: none;
    overflow: visible;
}

.filter-pill {
    display: inline-block;
    background: rgba(0, 0, 0, 0.07);
    border-radius: var(--radius-badge);
    padding: 0.15em 0.45em;
    white-space: nowrap;
    line-height: 1.5;
    color: var(--text-mid);
}

/* Entity results in nav — spans full width, centered */
.entity-nav-results {
    font-size: 0.75rem;
    color: var(--text-mid);
    margin-top: 0.25rem;
    text-align: center;
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

/* ============================================
   Entity Selector Modal
   ============================================ */

.entity-modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: flex-start;
    justify-content: center;
    z-index: 10000;
    padding: 1rem;
    padding-top: 60px;
}

.entity-modal {
    position: relative;          /* anchor for the perched circular close button */
    background: var(--bg-white);
    border-radius: var(--radius-card);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
    width: 100%;
    max-width: 600px;
    /* dvh tracks the *visible* viewport as mobile browser toolbars show/hide;
       plain vh overshoots on iOS Safari and pushes the pinned footer off-screen.
       The vh line is the fallback for browsers without dvh support. */
    max-height: calc(100vh - 60px - 1rem);
    max-height: calc(100dvh - 60px - 1rem);
    display: flex;
    flex-direction: column;
}

/* Stacked picker: when the entity-selector opens on top of ANOTHER modal (e.g. the
   Player picker launched from inside the Filters modal), drop it so the underlying
   modal's header stays visible — a modal directly on a modal reads as a glitch.
   --stack-top is set inline to the underlying header's bottom; the height is capped
   to fit below it so a long (nation-scoped) list can't overflow the viewport. */
.entity-modal-overlay.stacked-below { padding-top: var(--stack-top, 60px); }
.entity-modal-overlay.stacked-below .entity-modal {
    max-height: calc(100vh - var(--stack-top, 60px) - 1rem);
    max-height: calc(100dvh - var(--stack-top, 60px) - 1rem);
}

.entity-modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 1rem 1.5rem;
    border-bottom: 1px solid var(--border);
}

.entity-modal-header h2 {
    margin: 0;
    font-size: 1.5rem;
    color: var(--text-dark);
    font-family: 'Sequel Sans Black', 'Arial Black', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-weight: 900;
    font-style: normal;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.entity-modal-close {
    /* Perched circular close: a thin grey circle at the top-right corner — its top
       half hangs above the modal's top edge and its rightmost point brushes the right
       edge, so it reads as a distinct affordance instead of getting lost in the header. */
    position: absolute;
    top: -16px;          /* half the 32px diameter → top half overhangs the top edge */
    right: 0;            /* rightmost point flush with the modal's right edge */
    z-index: 2;
    background: var(--bg-white);
    border: 1px solid var(--border);
    font-size: 1.5rem;
    line-height: 1;
    color: var(--text-light);
    cursor: pointer;
    padding: 0;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-round);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
    transition: background 0.2s, color 0.2s, border-color 0.2s;
}

.entity-modal-close:hover {
    background: var(--bg-page);
    color: var(--text-dark);
}

/* ── Match detail modal ──────────────────────────────────────────────────────
   A centred floating card for ONE match's full detail — same overlay convention as
   the filters modal (backdrop greys the page incl. the nav, card pinned below the nav
   row via the base 60px padding-top). The body is the only scroll region. The card is
   wider than the default modal (820 vs 600) and, on mobile, near-full-width with only
   a few px of greyed gutter each side. Inherits the base .entity-modal-overlay
   (padding 1rem / padding-top 60px / align flex-start / justify center). */
.detail-modal {
    max-width: 820px;       /* centred floating card; greyed page around it */
    /* No overflow:hidden — header/body have no opaque bg of their own (they show the
       card's rounded white bg), and clipping would cut off the perched close button. */
    /* Always take the full available height (not just max-height) so the modal never
       jumps size between tabs or between matches — the body flex-fills and scrolls.
       dvh tracks the visible viewport (mobile toolbars); the vh line is the fallback. */
    height: calc(100vh - 60px - 1rem);
    height: calc(100dvh - 60px - 1rem);
}
/* Modal header mirrors the collapsed card: a top row (date+kickoff · comp/round
   badges), the fixture cluster (name+subtitle · kit · score pill · kit · name+subtitle
   — kits flank the pill, names hug inward as one tight central unit), and a meta row
   (venue · broadcaster). The whole thing is vertically stacked, the ✕ sits top-right. */
.detail-modal .detail-modal-title {
    display: block;
    padding: 0.55rem 1rem 0.6rem;
    /* Clip content at the card edge so an over-long name (e.g. a user-enlarged font)
       is cut off rather than escaping the modal. Normal names overflow only into the
       side gutter (well within this box), so they're unaffected. The ✕ and nav arrows
       are siblings (in the header), so they're not clipped. */
    overflow: hidden;
}
.detail-modal-title .dmh-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding-right: 2rem;        /* clear the ✕ */
    min-height: 1.1rem;
}
.detail-modal-title .dm-date {
    font-size: 0.72rem;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    text-transform: none;
    letter-spacing: 0;
    color: var(--text-light);
    white-space: nowrap;
}
.detail-modal-title .dmh-badges { display: flex; align-items: center; gap: 0.3rem; flex-wrap: wrap; justify-content: flex-end; }

/* Fixture cluster — the pill is the fixed centre anchor (like the card's score pill).
   Each side is an equal minmax(0,1fr) column that hugs the pill, so uneven name
   lengths (e.g. "Switzerland" vs "Bosnia") never push the pill off-centre. */
.detail-modal-title .dmh-fixture {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    /* Top-align the columns so the score pill's top sits level with the kit top —
       not floating above it. With the PSO row always reserved the centre stack is the
       tallest cell on mobile; centring would push the (shorter) kits down below the
       pill. The kit is still vertically centred WITH its team name inside .dmh-side. */
    align-items: start;
    column-gap: 0.6rem;
    padding: 0.35rem 0 0.2rem;
}
.detail-modal-title .dmh-side { display: flex; align-items: center; gap: 0.6rem; min-width: 0; }
.detail-modal-title .dmh-home { justify-content: flex-end; }   /* hug the pill from the left */
.detail-modal-title .dmh-away { justify-content: flex-start; }  /* hug the pill from the right */
.detail-modal-title .dm-team { display: flex; flex-direction: column; min-width: 0; }
.detail-modal-title .dm-home { align-items: flex-end; text-align: right; }
.detail-modal-title .dm-away { align-items: flex-start; text-align: left; }
.detail-modal-title .dm-name {
    /* Univers 67 Condensed Bold Italic — same display face as the card team names
       (var(--font-condensed) @ 700/italic). More condensed than Sequel Sans Black, so
       longer names fit without wrapping. Size kept at the current 1.1rem. */
    font-family: var(--font-condensed);
    font-weight: 700;
    font-style: italic;
    letter-spacing: 0.01em;
    font-size: 1.1rem;
    line-height: 1.1;
    color: var(--text-dark);
}
.detail-modal-title .dm-sub { font-size: 0.72rem; font-style: italic; color: var(--text-light); white-space: nowrap; margin-top: 1px; }
/* Reserve the kit's box (kit viewBox is 64×94) even when the slot is empty — an
   upcoming knockout has no kit yet, but the header should keep its height and the
   team names shouldn't shuffle into the gap. Height is the responsive driver
   (72px desktop, 48px mobile below); width follows from the aspect ratio. */
.detail-modal-title .dm-kit { flex: none; height: 72px; aspect-ratio: 64 / 94; }
.detail-modal-title .dm-kit .kit-svg { height: 72px; width: auto; display: block; }
.detail-modal-title .dm-pill {
    flex: none;
    background: var(--text-light);   /* neutral fallback (no result), like .score-pill */
    color: var(--text-on-colour);
    font-weight: 900;
    border-radius: var(--radius-badge);              /* small rounding — softens the corner without a sharp point */
    padding: 0.2rem 0.6rem;
    font-size: 1.2rem;
    white-space: nowrap;
    /* Snug to a single-digit score; tabular digits keep every single-digit score the
       same width (no jiggle when cycling). A 2-digit score trims its padding (below)
       rather than ballooning the common case. */
    font-variant-numeric: tabular-nums;
    /* Floor the width to a single-digit score ("0–0") so an upcoming match's narrow
       "v" pads out to the same width — consistent as you cycle past↔future. ~3em is
       the border-box total of a single-digit score, so those aren't widened/lost. */
    min-width: 3em;
    text-align: center;
}
/* Rare double-digit score (e.g. 10–1): trim the horizontal padding so the pill stays
   about the single-digit width instead of growing. Applied via JS (.dm-pill--tight). */
.detail-modal-title .dm-pill--tight { padding-left: 0.25rem; padding-right: 0.25rem; }
/* Result-coloured pill — same palette as the card's .score-pill. */
.detail-modal-title .dm-pill.win  { background: var(--primary); }
.detail-modal-title .dm-pill.draw { background: var(--result-draw-pill); }
.detail-modal-title .dm-pill.loss { background: var(--loss); }

/* Score pill + (optional) PSO pill stacked, centred under the fixture's centre axis. */
.detail-modal-title .dm-score-stack { display: flex; flex-direction: column; align-items: center; gap: 3px; }
/* PSO pill in the modal: small rounding (matches dm-pill) + sized to read as a smaller
   sibling of the dm-pill, with a little vertical breathing room. */
.detail-modal-title .pso-pill { border-radius: var(--radius-badge); font-size: 0.95rem; padding: 0.2rem 0.5rem; }
/* Invisible PSO pill that still occupies its row — keeps the header height constant
   whether or not a match went to penalties (see buildMatchModalHeader). */
.detail-modal-title .pso-pill--placeholder { visibility: hidden; }

/* Meta row — venue (left) · broadcaster badge(s) (right). The .broadcaster-badge
   styling is global; the card's flex layout is scoped to .game-card, so restate it. */
.detail-modal-title .dmh-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-top: 0.25rem;
}
.detail-modal-title .dmh-meta .card-meta-venue { font-size: 0.75rem; color: var(--text-light); }
.detail-modal-title .dmh-meta .card-meta-badges { flex-shrink: 0; }
.detail-modal-body {
    flex: 1;
    overflow-y: auto;
    /* Always reserve the scrollbar gutter so switching between a tab that scrolls
       (Lineups) and one that doesn't (Cards) never shifts the centred tab bar. */
    scrollbar-gutter: stable;
    -webkit-overflow-scrolling: touch;
    /* Readable centred column within the full-width panel (full width on mobile). */
    width: 100%;
    max-width: 820px;
    margin: 0 auto;
    padding: 0 1.25rem 1.25rem;   /* no top padding — the sticky tab bar pins flush at top */
}
/* Header fills the card width; the perched circular ✕ (base .entity-modal-close)
   sits at the card's top-right corner. */
.detail-modal .entity-modal-header {
    display: block;
    position: relative;
    padding: 0;
    width: 100%;
    max-width: 820px;
    margin: 0 auto;
}
/* Cycle-to-adjacent-match arrows on the header's outer edges — a very subtle light
   grey chevron, vertically centred (clear of the date/venue rows and the centre-hugging
   names). Disabled (faded) at the ends of the list. */
.detail-modal-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 3;
    width: 44px;          /* generous tap target; the visible chevron hugs the outer
                             edge (below), so the hit area can extend in over the text */
    height: 56px;
    display: flex;
    align-items: center;
    padding: 0;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--modal-nav-arrow);
    font-size: 2rem;
    line-height: 1;
    transition: color 0.15s;
}
/* Chevrons hug the OUTER edge of their hit area so they clear edge-reaching team
   names (which can overflow their column on a narrow screen). */
.detail-modal-nav-prev { left: 0; justify-content: flex-start; padding-left: 2px; }
.detail-modal-nav-next { right: 0; justify-content: flex-end; padding-right: 2px; }
.detail-modal-nav:hover:not(:disabled) { color: var(--text-light); }
.detail-modal-nav:disabled { opacity: 0.3; cursor: default; }
@media (max-width: 600px) {
    /* Near-full-width: only a few px of greyed gutter each side (nav row still greyed
       above via the 60px padding-top). */
    .detail-modal-overlay { padding: 6px; padding-top: 60px; }
    .detail-modal { max-width: none; max-height: calc(100dvh - 60px - 6px); }
    /* Reserve room for the edge nav arrows so they don't overlap the names (on the
       wide desktop the names hug the centre, so this is only needed on mobile). The kit
       is trimmed a touch from the card's 58px to keep even the longest names (e.g.
       "Netherlands") on one line alongside the arrows. */
    .detail-modal-title .dm-kit { height: 48px; }
    .detail-modal-title .dm-kit .kit-svg { height: 48px; }
    .detail-modal-title .dmh-fixture { padding-left: 26px; padding-right: 26px; }
}

/* Modal tabs */
.entity-modal-tabs {
    display: flex;
    border-bottom: 1px solid var(--border);
    background: var(--bg-page);
}

.entity-tab-button {
    flex: 1;
    background: none;
    border: none;
    padding: 0.75rem 1rem;
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--text-light);
    cursor: pointer;
    border-bottom: 2px solid transparent;
    transition: all 0.2s;
}

.entity-tab-button:hover {
    color: var(--text-dark);
    background: rgba(0, 0, 0, 0.02);
}

.entity-tab-button.active {
    color: var(--primary);
    border-bottom-color: var(--primary);
    background: var(--bg-white);
}

.entity-modal-content {
    flex: 1;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.entity-tab-panel {
    display: none;
    flex: 1;
    flex-direction: column;
    overflow: hidden;
}

.entity-tab-panel.active {
    display: flex;
}

/* Filters in modal - make scrollable */
#filtersTabPanel {
    overflow-y: auto;
    padding: 1rem 1.5rem;
}

#filtersTabPanel .filter-grid {
    margin-bottom: 1rem;
}

#filtersTabPanel .button-row {
    padding: 0;
    margin-top: 0;
}

/* ============================================
   Filters Modal (Separate Modal)
   ============================================ */
.filters-modal-custom {
    max-height: calc(100vh - 60px - 1rem);
    max-height: calc(100dvh - 60px - 1rem);
    display: flex;
    flex-direction: column;
}

.filters-modal-content {
    flex: 1;
    overflow-y: auto;
    /* Always reserve the scrollbar gutter so expanding/collapsing a section
       (which changes content height past the viewport) doesn't add/remove the
       scrollbar and reflow the whole modal width. */
    scrollbar-gutter: stable;
    padding: 1rem 1.5rem;
}

/* Use 3 columns for filters modal grid (desktop) */
.filters-modal-custom .filter-grid {
    display: grid;
    grid-template-columns: 1fr;   /* single column on mobile — no value clipping */
    gap: 1rem;
    margin-bottom: 1rem;
}

@media (min-width: 600px) {
    .filters-modal-custom .filter-grid {
        grid-template-columns: repeat(2, 1fr);   /* two columns on desktop */
    }
}

/* Filters modal actions (pinned at bottom, outside scrollable content) */
.filters-modal-actions {
    display: flex;
    gap: 0.75rem;
    justify-content: flex-end;
    padding: 1rem 1.5rem;
    border-top: 1px solid var(--border);
    background: var(--bg-white);
    flex-shrink: 0;
}

.filters-modal-actions .btn-primary,
.filters-modal-actions .btn-secondary {
    padding: 0.6rem 1.25rem;
    font-size: 0.9rem;
}

/* Ensure More Date Filters section uses proper styling in modal */
.filters-modal-custom .more-filters-toggle {
    margin-bottom: 1rem;
}

.filters-modal-custom .filter-grid-secondary {
    margin-bottom: 1rem;
}

/* Collapsible labelled filter sections (Goals / People / Where).
   Keep the always-visible primary filters uncluttered; fold the rest away. */
.filter-section {
    border-top: 1px solid var(--border);
}

.filter-section-header {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    background: none;
    border: none;
    padding: 0.85rem 0;
    cursor: pointer;
    font-family: var(--font-condensed);
    font-size: 0.95rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-mid);
}

.filter-section-header:hover {
    color: var(--text-dark);
}

.filter-section-chevron {
    font-size: 0.7rem;
    color: var(--text-light);
    transition: transform 0.15s ease;
}

.filter-section:not(.collapsed) .filter-section-chevron {
    transform: rotate(90deg);
}

.filter-section-body {
    padding-bottom: 1rem;
}

/* Short explanatory line for a section's less-obvious controls. */
.filter-section-hint {
    font-size: 0.75rem;
    color: var(--text-light);
    font-style: italic;
    margin: 0 0 0.75rem;
}

/* Search-picker button inside the filters panel (internationals player, competitions
   managers) — styled like a filter select; opens the entity search modal. */
.player-pick-btn {
    width: 100%;
    text-align: left;
    padding: 0.45rem 0.6rem;
    border: 1px solid var(--control-border);
    border-radius: var(--radius-control);
    background: var(--bg-white);
    color: var(--text-mid);
    cursor: pointer;
    font: inherit;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.player-pick-btn:hover { border-color: var(--primary); }
.player-pick-btn.has-value { color: var(--text-dark); font-weight: 600; border-color: var(--primary); }

.filter-section.collapsed .filter-section-body {
    display: none;
}

.entity-modal-search {
    padding: 1rem 1.5rem;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 1rem;
}

.entity-search-wrapper {
    flex: 1;
    position: relative;
    display: flex;
    align-items: center;
}

.entity-search-input {
    flex: 1;
    padding: 0.5rem 2rem 0.5rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-small);
    font-size: 0.95rem;
}

/* Hide native search clear button (WebKit/Blink) — we have our own */
.entity-search-input::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
}

.entity-search-input:focus {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
    border-color: var(--primary);
}

.entity-search-clear {
    position: absolute;
    right: 0.35rem;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.4rem;
    height: 1.4rem;
    border: none;
    background: var(--text-light);
    color: var(--text-on-colour);
    border-radius: var(--radius-round);
    font-size: 0.85rem;
    line-height: 1;
    cursor: pointer;
    padding: 0;
}

.entity-search-clear:hover {
    background: var(--text-dark);
}

.entity-search-clear:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

.entity-search-count {
    font-size: 0.75rem;
    color: var(--text-light);
    white-space: nowrap;
}

.entity-modal-list {
    flex: 1;
    overflow-y: auto;
    padding: 0.5rem;
}

.entity-list-item {
    padding: 0.75rem 1rem;
    cursor: pointer;
    border-radius: var(--radius-small);
    margin-bottom: 0.25rem;
    transition: background 0.2s;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.entity-list-item:hover {
    background: var(--bg-page);
}

.entity-list-item.focused {
    background: var(--bg-page);
    outline: 2px solid var(--primary);
    outline-offset: -2px;
}

.entity-list-item.current {
    background: var(--list-current-bg);
    font-weight: 600;
}

.entity-name-with-badge {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.entity-name-text {
    font-family: var(--font-condensed);
    font-weight: 400;
    font-style: italic;
}

.entity-subtitle {
    display: block;
    width: 100%;
    font-size: 0.75rem;
    font-style: normal;
    color: var(--text-light);
    line-height: 1.3;
    margin-top: -0.1rem;
    overflow: hidden;
    text-overflow: ellipsis;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

.entity-current-badge {
    font-size: 0.7rem;
    color: var(--primary);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.entity-list-empty {
    padding: 2rem;
    text-align: center;
    color: var(--text-light);
}

/* Mobile adjustments */
@media (max-width: 600px) {
    .entity-modal {
        max-height: calc(100vh - 60px - 1rem);
        max-height: calc(100dvh - 60px - 1rem);
    }

    .entity-modal-header h2 {
        font-size: 1.1rem;
    }

    .entity-selector-btn {
        font-size: 1.25rem;
        letter-spacing: 0.02em;
        padding: 0.25rem 0.25rem 0.25rem 0;
    }

    /* Preserve the entity-over-view size hierarchy on mobile: the entity selector
       drops 1.5→1.25rem above, so step the view label down by the same ratio
       (1.35→1.125rem) — otherwise it stays 1.35rem and reads larger than the
       entity name. */
    .nav-view-label {
        font-size: 1.125rem;
        letter-spacing: 0.02em;
    }

    .entity-nav-header-row {
        gap: 0.5rem;
    }

    /* Mobile: horizontal space is the tight constraint. The desktop layout keeps
       the entity name and the filter controls on one row, but on a portrait
       device that clips longer names (e.g. "GREAVES, JIMMY",
       "Hesselink, Jan Vennegoor Of") and pushes the row past the viewport.
       Give the filters their own full-width row beneath the name instead —
       a deliberate, consistent two-row header for every entity. The few extra
       vertical pixels are an acceptable trade when width is the real limit. */
    .entity-nav-columns {
        flex-direction: column;
        gap: 0.4rem;
    }

    .entity-nav-left {
        max-width: 100%;
    }

    .entity-nav-right {
        align-items: flex-start;
        text-align: left;
        width: 100%;
    }

    /* Drop the desktop right-push so the filters button lines up with the
       pills and the entity name on its own row. */
    .entity-filters-btn {
        margin-left: 0;
    }
}

/* competitions.html Players filter: the matching players, on their own line above venue/badges. */
.game-card .card-meta:has(.card-meta-players) { flex-wrap: wrap; }
.game-card .card-meta .card-meta-players {
    flex-basis: 100%;
    font-size: 0.75rem;
    color: var(--text-light);
}
