:root {
    --primary: #06439b;      /* bleu vif du logo Tactiklub */
    --primary-dark: #001b4d; /* bleu nuit du logo Tactiklub */
    --accent: #5a9700;       /* vert tactique du logo Tactiklub */
    --accent-dark: #3c6f00;
    --bg: #f4f7fb;
    --card: #ffffff;
    --border: #dde3ee;
    --text: #1c2433;
    --muted: #6b7280;
    --danger: #c8202f;
    --danger-dark: #9c1522;
}

/* Les graphiques et leurs légendes partagent les mêmes couleurs de série.
   Ces variables évitent qu'un thème recolore le SVG sans recolorer sa légende. */
.player-physical-chart {
    --chart-training: #35c8ee;
    --chart-match: #b8ff3f;
}
.chart-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 16px;
    margin-top: 8px;
    color: var(--muted);
}
.chart-legend-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.85rem;
}
.chart-legend-swatch {
    display: inline-block;
    width: 10px;
    height: 10px;
    flex: 0 0 10px;
    border-radius: 50%;
    background: currentColor;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16);
}
.chart-legend-swatch--training { color: var(--chart-training); }
.chart-legend-swatch--match { color: var(--chart-match); }

* { box-sizing: border-box; }

body {
    margin: 0;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    background:
        radial-gradient(circle at 5% 0%, rgba(6, 67, 155, 0.13), transparent 36rem),
        radial-gradient(circle at 95% 18%, rgba(90, 151, 0, 0.10), transparent 32rem),
        linear-gradient(180deg, #fbfdff 0%, #f2f7fb 100%);
    color: var(--text);
}

.topbar {
    position: relative;
    z-index: 1000;
    background: rgba(255, 255, 255, 0.88);
    -webkit-backdrop-filter: saturate(160%) blur(18px);
    backdrop-filter: saturate(160%) blur(18px);
    color: var(--primary-dark);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 2px 28px;
    /* Sur iPhone, l'app tourne en "black-translucent" (le contenu web
       s'affiche sous l'horloge/batterie plutôt qu'en dessous) : sans cette
       marge, tout élément proche du bord haut — dont la pastille "non lu",
       décalée au-dessus du bouton de menu — se retrouve coincé sous la
       barre de statut système. Neutre partout ailleurs (0px par défaut). */
    padding-top: calc(2px + env(safe-area-inset-top, 0px));
    flex-wrap: wrap;
    gap: 10px;
    border-bottom: 1px solid rgba(0, 27, 77, 0.10);
    box-shadow: 0 8px 30px rgba(0, 27, 77, 0.08);
}

.brand {
    font-weight: 700;
    font-size: 1.1rem;
    color: var(--primary-dark);
    text-decoration: none;
    display: flex;
    align-items: center;
    gap: 10px;
}
.brand:hover { opacity: 0.9; }

.brand-logo {
    height: 68px;
    width: 72px;
    object-fit: contain;
    border-radius: 0;
    filter: drop-shadow(0 2px 4px rgba(0, 27, 77, 0.18));
    image-rendering: auto;
}

.menu-wrapper {
    position: relative;
    display: flex;
    align-items: center;
    gap: 12px;
}

.menu-toggle-btn {
    background: #e4edf9;
    border: 1px solid #cddbee;
    border: none;
    border-radius: 8px;
    width: 42px;
    height: 42px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex-shrink: 0;
    position: relative;
}
.menu-toggle-btn-lines {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}
.menu-toggle-btn span {
    display: block;
    width: 22px;
    height: 2px;
    background: var(--primary-dark);
    border-radius: 2px;
    transform-origin: center;
    transition: transform 0.2s, opacity 0.2s;
}
/* L'espacement entre les 3 lignes utilise une marge sur les enfants plutôt
   que "gap" sur le conteneur flex : plus robuste (aucune dépendance à un
   support de "gap" en flexbox toujours inégal selon navigateurs/versions),
   et ça évite que les 3 lignes ne s'affichent collées en un seul bloc. */
.menu-toggle-btn-lines span:not(:last-child) {
    margin-bottom: 5px;
}
.menu-toggle-btn.open .menu-toggle-btn-lines span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu-toggle-btn.open .menu-toggle-btn-lines span:nth-child(2) { opacity: 0; }
.menu-toggle-btn.open .menu-toggle-btn-lines span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
/* Le clic donne le focus au bouton, ce qui déclenche l'anneau de
   focus générique (voir ui-v2/ui.css, "body.mv2 button:focus-visible") :
   son rayon par défaut ne suit pas la forme arrondie de ce bouton et
   son décalage ("outline-offset") le fait paraître flottant/décentré,
   surtout visible une fois la croix affichée. On le fait épouser
   précisément la forme du bouton plutôt que de le supprimer (on garde
   l'indication visuelle au clavier). */
.menu-toggle-btn:focus-visible {
    outline-offset: 1px;
    border-radius: 8px;
}

.menu-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: transparent;
    z-index: 900;
}
.menu-overlay.open { display: block; }

/* Barre de navigation basse : cachée par défaut (desktop/tablette), ne
   s'affiche qu'en mobile via la media query dédiée plus bas. */
.bottom-nav {
    display: none;
}

/* Petit message de confirmation discret après une action (ex: "Joueur
   ajouté ✓"), affiché puis masqué automatiquement via JS. */
.toast {
    position: fixed;
    left: 50%;
    bottom: 24px;
    transform: translateX(-50%) translateY(20px);
    background: var(--primary-dark);
    color: white;
    padding: 12px 22px;
    border-radius: 30px;
    font-size: 0.9rem;
    font-weight: 600;
    box-shadow: 0 6px 20px rgba(0,0,0,0.25);
    opacity: 0;
    pointer-events: none;
    z-index: 3000;
    transition: opacity 0.25s ease, transform 0.25s ease;
    max-width: 90vw;
    text-align: center;
}
.toast.show {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* Menu déroulant classique, ancré juste sous le bouton qui l'ouvre (pas un
   tiroir plein écran) : plus simple, et sans les soucis de position:fixed
   plein écran sur Safari iOS (notamment en orientation paysage). */
.dropdown-menu {
    display: none;
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    min-width: 220px;
    max-width: 80vw;
    max-height: 75vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    background: var(--primary-dark);
    border-radius: 12px;
    z-index: 950;
    flex-direction: column;
    padding: 8px;
    gap: 2px;
    box-shadow: 0 10px 28px rgba(0,0,0,0.3);
}
.dropdown-menu.open { display: flex; }

.dropdown-menu a {
    color: white;
    text-decoration: none;
    padding: 12px 14px;
    border-radius: 8px;
    font-size: 0.95rem;
    opacity: 0.95;
    display: flex;
    align-items: center;
    gap: 10px;
}
.dropdown-menu a:hover { background: rgba(255,255,255,0.12); opacity: 1; }
.menu-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.2em;
    height: 1.2em;
    font-size: 1.05rem;
    line-height: 1;
    flex-shrink: 0;
}
.dropdown-menu-divider {
    height: 1px;
    background: rgba(255,255,255,0.18);
    margin: 6px 8px;
}

.collapsible-title {
    cursor: pointer;
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--primary-dark);
}

.duty-current-name {
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--primary-dark);
    margin: 6px 0;
}

.container {
    max-width: 1240px;
    margin: 30px auto;
    padding: 0 24px;
}

h1 { font-size: 1.5rem; margin-bottom: 4px; color: var(--primary-dark); }
h2 { font-size: 1.2rem; color: var(--primary-dark); }

.page-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 16px;
    flex-wrap: wrap;
    gap: 10px;
}

.card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 18px 20px;
    margin-bottom: 16px;
}

.dashboard-card {
    transition: transform 0.15s, box-shadow 0.15s;
}
.dashboard-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(25, 85, 168, 0.12);
}

.dashboard-icon {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.7rem;
    margin-bottom: 12px;
}
.dashboard-icon-blue { background: #dbe6f7; }
.dashboard-icon-red { background: #eec4c4; }

table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    background: var(--card);
    border-radius: 10px;
}

/* Enrobe chaque <table> (voir table-sort.js). Hauteur bornée + défilement
   vertical INTERNE : c'est la seule méthode vraiment fiable, tous
   navigateurs confondus, pour garder l'en-tête visible sur un long
   tableau — plus fiable que de compter sur le défilement de la page
   entière (qui dépend de tout ce qui l'entoure). */
.table-scroll-wrapper {
    overflow-x: auto;
    overflow-y: auto;
    max-height: 70vh;
    -webkit-overflow-scrolling: touch;
}
/* Coins arrondis recréés sans overflow:hidden sur <table> (qui empêcherait
   position:sticky de fonctionner sur les en-têtes). */
thead tr:first-child th:first-child { border-top-left-radius: 10px; }
thead tr:first-child th:last-child { border-top-right-radius: 10px; }
tbody tr:last-child td:first-child { border-bottom-left-radius: 10px; }
tbody tr:last-child td:last-child { border-bottom-right-radius: 10px; }

th, td {
    text-align: left;
    padding: 10px 12px;
    border-bottom: 1px solid var(--border);
    font-size: 0.92rem;
}

th {
    background: #eaf0fa;
    color: var(--primary-dark);
    font-weight: 600;
    position: relative;
    z-index: 5;
}
/* Tableau d'évaluations d'entraînement : beaucoup de colonnes (11), un
   padding réduit ici l'aide à tenir sans défilement horizontal sur
   iPad/PC. Uniquement en vue tableau classique — le mode carte mobile
   (voir plus bas dans ce fichier) n'est pas concerné. */
.eval-table th, .eval-table td {
    padding: 6px 5px;
    font-size: 0.85rem;
}

.sortable-th {
    cursor: pointer;
    user-select: none;
    position: relative;
    padding-right: 22px;
}
.sortable-th:hover { background: #dfe8f7; }
.sortable-th::after {
    content: "↕";
    position: absolute;
    right: 6px;
    opacity: 0.35;
    font-size: 0.8rem;
}
.sortable-th.sort-asc::after { content: "▲"; opacity: 0.9; }
.sortable-th.sort-desc::after { content: "▼"; opacity: 0.9; }

tr:last-child td { border-bottom: none; }

.btn {
    display: inline-block;
    background: linear-gradient(135deg, var(--primary), #075ccf);
    color: white;
    padding: 9px 16px;
    border-radius: 8px;
    text-decoration: none;
    font-size: 0.9rem;
    border: none;
    cursor: pointer;
}
.btn:hover { background: linear-gradient(135deg, var(--primary-dark), var(--primary)); }

.btn-secondary {
    background: #e7ebf3;
    color: var(--text);
}
.btn-secondary:hover { background: #d7dded; }

.btn-danger { background: var(--danger); }
.btn-danger:hover { background: var(--danger-dark); }

.btn-small { padding: 5px 10px; font-size: 0.8rem; }

form.inline { display: inline; }

label {
    display: block;
    font-size: 0.85rem;
    font-weight: 600;
    margin-bottom: 4px;
    color: var(--muted);
}

input, select, textarea {
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 16px; /* évite le zoom automatique au focus sur iPhone/iPad */
    margin-bottom: 14px;
    font-family: inherit;
}

input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 2px rgba(6, 67, 155, 0.16);
}

textarea { resize: vertical; min-height: 60px; }

.form-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 16px;
}

.badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 12px;
    font-size: 0.78rem;
    font-weight: 600;
}
/* Les badges vert/rouge/gris restent des indicateurs fonctionnels
   (présent/absent, actif/inactif...) distincts de l'identité du club,
   pour rester lisibles d'un coup d'œil. */
.badge-green { background: #dcf0e0; color: #1e7d32; }
.badge-red { background: #fbe1de; color: var(--danger-dark); }
.badge-grey { background: #e7ebf3; color: var(--muted); }
.badge-blue { background: #e5f2d6; color: var(--accent-dark); }
.badge-gold { background: #fdf0d5; color: #8a5a00; }

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

.result-box {
    font-size: 1.6rem;
    font-weight: 700;
    text-align: center;
    padding: 10px;
    color: var(--primary-dark);
}

.actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* Fragment de pagination réutilisable (app/templates/partials/pagination.html)
   — même famille visuelle que .actions/.btn-secondary/.muted ci-dessus,
   juste de quoi aligner proprement le résumé ("X-Y sur Z"), le sélecteur
   du nombre par page et les numéros de page sur une même barre. */
.pagination-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 16px;
}
.pagination-summary { margin: 0; }
.pagination-per-page {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0;
}
.pagination-per-page label { margin: 0; font-weight: 400; }
.pagination-per-page select {
    width: auto;
    margin: 0;
    padding: 4px 8px;
}
.pagination-pages {
    align-items: center;
}
.pagination-current {
    background: var(--primary);
    color: white;
    font-weight: 600;
}
.pagination-ellipsis {
    color: var(--muted);
    padding: 0 2px;
}
@media (max-width: 600px) {
    .pagination-bar { justify-content: center; text-align: center; }
}

/* Page de réponse parent (clic sur la notification) : les boutons
   Présent/Absent sont de vraies cases à cocher radio, seulement
   habillées en gros boutons — accessible au clavier, comportement natif,
   sans dépendre du JS pour la sélection elle-même (juste pour
   afficher/masquer le motif d'absence). */
.parent-status-choice {
    cursor: pointer;
}
.parent-status-choice input[type="radio"] {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
}
.parent-status-btn {
    display: inline-block;
    font-size: 1rem;
    padding: 14px 22px;
    border: 2px solid transparent;
}
.parent-status-choice-active .parent-status-present {
    background: #1e7d32;
    border-color: #1e7d32;
}
.parent-status-choice-active .parent-status-absent {
    background: var(--danger);
    color: white;
    border-color: var(--danger-dark);
}

.muted { color: var(--muted); font-size: 0.85rem; }

.lineup-table input[type="number"] { width: 70px; margin-bottom: 0; }
.lineup-table select { margin-bottom: 0; }
.lineup-table input[type="checkbox"] { width: auto; }

/* Fix64 : périodes de jeu multiples (entrée/sortie) par joueur, dans le
   formulaire "Composition, temps de jeu et buts" — un joueur qui sort
   puis revient a plusieurs lignes plutôt qu'une seule paire écrasée. */
.stints-cell { min-width: 210px; }
.stint-rows { display: flex; flex-direction: column; gap: 4px; margin-bottom: 4px; }
.stint-row { display: flex; align-items: center; gap: 4px; }
.stint-row input[type="number"] { width: 56px; }
.stint-row span { color: var(--muted); font-size: 0.8rem; }
.remove-stint-btn { padding: 2px 7px !important; line-height: 1; }
.add-stint-btn { font-size: 0.78rem; padding: 3px 8px !important; }

.player-photo {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    object-fit: cover;
    vertical-align: middle;
    margin-right: 8px;
    border: 1px solid var(--border);
}

.player-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--primary);
    color: white;
    font-size: 0.8rem;
    font-weight: 700;
    vertical-align: middle;
    margin-right: 8px;
}

.player-photo-large {
    width: 110px;
    height: 110px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid var(--border);
}

.player-avatar-large {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 110px;
    height: 110px;
    border-radius: 50%;
    background: var(--primary);
    color: white;
    font-size: 2rem;
    font-weight: 700;
}

.tactic-pitch {
    position: relative;
    width: 100%;
    max-width: 460px;
    margin: 0 auto;
    padding-bottom: 75%;
    background: linear-gradient(180deg, #2d8a3e 0%, #2d8a3e 100%);
    border: 3px solid #ffffff;
    border-radius: 10px;
    overflow: hidden;
}

/* Terrain de l'éditeur de positions de formation — même style visuel que
   .tactic-pitch, mais jamais soumis à la bascule 3D/paysage (utilisée
   pour visualiser un match) : ici on veut un repère précis et stable
   pour glisser chaque poste, quel que soit l'appareil. */
.formation-editor-pitch {
    position: relative;
    width: 100%;
    max-width: 460px;
    margin: 0 auto;
    padding-bottom: 95%;
    background: linear-gradient(180deg, #2d8a3e 0%, #2d8a3e 100%);
    border: 3px solid #ffffff;
    border-radius: 10px;
    overflow: hidden;
    touch-action: none;
}
.formation-editor-slot {
    position: absolute;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    cursor: grab;
    touch-action: none;
    user-select: none;
}
.formation-editor-slot-dot {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--primary-dark);
    border: 2px solid white;
    box-shadow: 0 2px 6px rgba(0,0,0,0.35);
}
.formation-editor-slot-label {
    margin-top: 4px;
    font-size: 0.68rem;
    font-weight: 700;
    color: white;
    text-shadow: 0 1px 3px rgba(0,0,0,0.7);
    text-align: center;
    max-width: 80px;
    line-height: 1.1;
    white-space: nowrap;
}

.tactic-pitch-lines {
    position: absolute;
    inset: 0;
}
.tactic-pitch-lines::before {
    /* rectangle des buts (en bas, notre propre camp — le gardien y est) */
    content: "";
    position: absolute;
    bottom: 0;
    left: 30%;
    right: 30%;
    height: 9%;
    border: 2px solid rgba(255,255,255,0.6);
    border-bottom: none;
}
.tactic-pitch-lines::after {
    /* petit arc symbolisant la surface de réparation */
    content: "";
    position: absolute;
    bottom: 9%;
    left: 50%;
    width: 70px;
    height: 35px;
    margin-left: -35px;
    border: 2px solid rgba(255,255,255,0.6);
    border-bottom: none;
    border-radius: 60px 60px 0 0;
}

.tactic-halfway-line {
    position: absolute;
    top: 4%;
    left: 0;
    right: 0;
    height: 2px;
    background: rgba(255,255,255,0.6);
}
.tactic-center-dot {
    position: absolute;
    top: 4%;
    left: 50%;
    width: 6px;
    height: 6px;
    background: rgba(255,255,255,0.8);
    border-radius: 50%;
    transform: translate(-50%, -50%);
}
.tactic-center-arc {
    /* demi-cercle central (on ne voit que la moitié du terrain) */
    position: absolute;
    top: 4%;
    left: 50%;
    width: 90px;
    height: 45px;
    margin-left: -45px;
    border: 2px solid rgba(255,255,255,0.6);
    border-top: none;
    border-radius: 0 0 45px 45px;
}

.tactic-slot {
    position: absolute;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
}

.tactic-player {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
}

.tactic-player-extra { margin-top: 4px; opacity: 0.85; }

.tactic-photo {
    width: 52px;
    height: 52px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid white;
    box-shadow: 0 1px 4px rgba(0,0,0,0.35);
}

.tactic-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: var(--primary-dark);
    color: white;
    font-size: 1rem;
    font-weight: 700;
    border: 2px solid white;
    box-shadow: 0 1px 4px rgba(0,0,0,0.35);
}

.tactic-avatar-empty {
    background: rgba(255,255,255,0.25);
    border-style: dashed;
}

.tactic-chip-media {
    position: relative;
    display: inline-block;
}
.tactic-badges {
    position: absolute;
    top: -4px;
    right: -8px;
    display: flex;
    gap: 2px;
}
.tactic-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.6rem;
    font-weight: 700;
    color: white;
    line-height: 1;
    box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}
.tactic-badge-injured {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--danger);
}
.tactic-badge-red {
    width: 10px;
    height: 14px;
    border-radius: 2px;
    background: var(--danger);
}
.tactic-badge-yellow {
    width: 10px;
    height: 14px;
    border-radius: 2px;
    background: #e8b800;
}

.tactic-empty { opacity: 0.85; }

.tactic-name {
    font-size: 0.72rem;
    font-weight: 700;
    color: white;
    text-shadow: 0 1px 2px rgba(0,0,0,0.6);
    white-space: nowrap;
    max-width: 90px;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tactic-pos-label {
    font-size: 0.62rem;
    color: rgba(255,255,255,0.75);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

/* Glisser-déposer sur le schéma tactique */
.tactic-slot {
    padding: 6px;
    border-radius: 10px;
    transition: background 0.15s;
    touch-action: none;
}

.tactic-zone-hover {
    background: rgba(255,255,255,0.22);
    outline: 2px dashed rgba(255,255,255,0.7);
}

.tactic-chip, .tactic-bench-chip {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    cursor: grab;
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
}

.tactic-dragging-source { opacity: 0.35; }

.tactic-ghost {
    opacity: 0.9;
    transform: scale(1.08);
    filter: drop-shadow(0 4px 10px rgba(0,0,0,0.4));
}

.tactic-bench {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    padding: 16px;
    background: var(--card);
    border: 1px dashed var(--border);
    border-radius: 10px;
    min-height: 90px;
    touch-action: none;
}

.tactic-bench-chip .tactic-photo,
.tactic-bench-chip .tactic-avatar {
    width: 46px;
    height: 46px;
    border-color: var(--border);
}

.tactic-bench-chip .tactic-name {
    color: var(--text);
    text-shadow: none;
    font-size: 0.75rem;
}

/* Terrain en perspective 3D façon "vue de coach professionnel" — réservé
   aux écrans larges en mode paysage (ordinateur, iPad), jamais sur
   iPhone (768px de large max même en paysage sur les modèles actuels,
   contre 960px ici). Le glisser-déposer du terrain de match repose sur
   elementFromPoint() (l'élément réellement affiché sous le pointeur),
   qui reste fiable même à travers une transformation 3D — contrairement
   à un calcul de pourcentage sur un rectangle non transformé.
   Placé après les règles de base ci-dessus (et non avant), pour être
   certain que ce bloc l'emporte à spécificité égale. */
@media (min-width: 960px) and (orientation: landscape) {
    .tactic-pitch-3d-wrapper {
        perspective: 1400px;
        display: flex;
        justify-content: center;
        padding: 16px 20px 40px;
    }
    .tactic-pitch {
        max-width: 520px;
        padding-bottom: 100%; /* terrain allongé (au lieu de 75%), pour plus d'espace réel entre chaque ligne de joueurs */
        transform: rotateX(38deg) scale(1.05);
        transform-style: preserve-3d;
        box-shadow: 0 55px 70px -25px rgba(0, 0, 0, 0.45);
        transition: transform 0.3s ease;
    }
    /* Les jetons de joueurs (positionnés en absolute, comme le fond)
       héritent naturellement de cette même transformation grâce à
       transform-style: preserve-3d sur leur parent — ils basculent avec
       le terrain en un seul bloc cohérent. */

    /* Banc à côté du terrain plutôt qu'en dessous, sur 2 colonnes plutôt
       qu'une seule (pour ne pas avoir à trop défiler vers le bas quand il
       y a beaucoup de joueurs) — plus étroit et avec un écart plus net
       vis-à-vis du terrain, pour que les deux zones ne se touchent pas. */
    .tactic-board-layout {
        display: flex;
        align-items: flex-start;
        gap: 44px;
    }
    .tactic-board-layout > .tactic-pitch-3d-wrapper {
        flex: 1 1 auto;
    }
    .tactic-board-layout > .tactic-bench-col {
        flex: 0 0 250px;
        max-width: 250px;
    }
    .tactic-board-layout .tactic-bench {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 8px;
    }
    .formation-card {
        margin-bottom: 4px;
        padding: 10px 16px;
    }
}

.tactic-unavailable-chip {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    opacity: 0.55;
    cursor: default;
}
.tactic-unavailable-chip .tactic-photo,
.tactic-unavailable-chip .tactic-avatar {
    width: 46px;
    height: 46px;
    border-color: var(--border);
    filter: grayscale(1);
}
.tactic-unavailable-chip .tactic-name {
    color: var(--text);
    text-shadow: none;
    font-size: 0.75rem;
}

.tboard-player {
    position: absolute;
    transform: translate(-50%, -50%);
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--primary-dark);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.72rem;
    font-weight: 700;
    text-align: center;
    line-height: 1.1;
    cursor: grab;
    touch-action: none;
    box-shadow: 0 2px 6px rgba(0,0,0,0.35);
    user-select: none;
    border: 2px solid white;
}
/* Pastille libre (adversaire ou repère générique) : rouge plutôt que
   bleu, pour la distinguer d'un coup d'œil des vrais joueurs de
   l'effectif glissés sur le terrain. */
.tboard-player-free {
    background: var(--danger);
}
/* Ballon : plus petit qu'un jeton de joueur, fond blanc, juste l'émoji —
   pour bien le distinguer des joueurs (bleus) et pastilles libres
   (rouges) sur le terrain. */
.tboard-ball {
    width: 28px;
    height: 28px;
    background: white;
    border: 2px solid var(--border);
}
.tboard-ball-icon {
    font-size: 1.1rem;
    line-height: 1;
}

/* Fiche d'un joueur blessé pour une longue durée : fond rouge, visible
   d'un coup d'œil, cohérent avec le rouge du club utilisé partout
   ailleurs pour signaler une exclusion/alerte. */
.card-injured {
    background: #fbe1de;
    border-color: var(--danger);
}

/* Croix rouge (blessure) sur fond de cercle blanc, façon badge médical —
   utilisée à chaque endroit du site signalant un joueur blessé. */
.red-cross-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.3em;
    height: 1.3em;
    border-radius: 50%;
    background: white;
    color: var(--danger);
    font-weight: 900;
    box-shadow: 0 1px 3px rgba(0,0,0,0.3);
    vertical-align: middle;
    margin-bottom: 0.2em;
    flex-shrink: 0;
}

/* Évaluation détaillée par joueur — chaque joueur est un accordéon
   cliquable (clique sur son nom pour déplier/replier le détail de ses
   38 critères), pareil sur mobile et desktop : pas de défilement
   horizontal, pas de double vue à synchroniser. */
.eval-player-block {
    border-bottom: 1px solid var(--border);
    padding: 10px 0;
}
.eval-player-block:last-child {
    border-bottom: none;
}
.eval-player-summary {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 1.05rem;
    font-weight: 700;
    cursor: pointer;
    color: var(--primary-dark);
    list-style: none;
    padding: 4px 0;
}
.eval-player-summary::-webkit-details-marker { display: none; }
.eval-player-detail {
    margin-top: 8px;
}
.eval-summary-pct {
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--primary-dark);
    flex-shrink: 0;
}
.eval-mobile-category {
    margin: 16px 0 8px 0;
    padding-bottom: 4px;
    border-bottom: 2px solid var(--primary-dark);
    color: var(--primary-dark);
    font-size: 0.92rem;
}
.eval-mobile-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    padding: 8px 0;
    border-bottom: 1px solid var(--border);
}
.eval-grid-select {
    width: 64px;
    padding: 3px 2px;
    text-align: center;
    font-size: 0.82rem;
    flex-shrink: 0;
}
.eval-mobile-label {
    flex: 1;
    font-size: 0.87rem;
}
.tboard-player-remove {
    position: absolute;
    top: -10px;
    right: -10px;
    width: 26px;
    height: 26px;
    background: var(--danger);
    border-radius: 50%;
    font-size: 0.95rem;
    line-height: 26px;
    text-align: center;
    color: white;
    border: 2px solid white;
    box-shadow: 0 1px 4px rgba(0,0,0,0.35);
    z-index: 2;
}
/* Masque les croix de suppression sur les joueurs, quand ce mode est actif
   (pratique pour une capture d'écran propre, sans repasser en mode
   "toujours pouvoir supprimer"). */
#tboard-pitch.hide-remove-crosses .tboard-player-remove {
    display: none;
}

/* Terrain complet (deux buts) pour le tableau tactique libre — distinct du
   demi-terrain (.tactic-pitch) utilisé pour la composition d'un match. */
.tboard-pitch {
    position: relative;
    width: 100%;
    max-width: 560px;
    margin: 0 auto;
    padding-bottom: 145%;
    background: #2d8a3e;
    border: 3px solid #ffffff;
    border-radius: 10px;
    touch-action: none;
}
.tboard-halfway-line {
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    height: 2px;
    background: rgba(255,255,255,0.9);
}
.tboard-center-circle {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 32%;
    padding-bottom: 32%;
    border: 2px solid rgba(255,255,255,0.9);
    border-radius: 50%;
    transform: translate(-50%, -50%);
}
.tboard-center-dot {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 7px;
    height: 7px;
    background: rgba(255,255,255,0.9);
    border-radius: 50%;
    transform: translate(-50%, -50%);
}
.tboard-penalty-box {
    position: absolute;
    left: 14%;
    right: 14%;
    height: 15%;
    border: 2px solid rgba(255,255,255,0.9);
}
.tboard-penalty-top { top: 0; border-top: none; }
.tboard-penalty-bottom { bottom: 0; border-bottom: none; }
.tboard-goal-box {
    position: absolute;
    left: 34%;
    right: 34%;
    height: 6%;
    border: 2px solid rgba(255,255,255,0.9);
}
.tboard-goal-top { top: 0; border-top: none; }
.tboard-goal-bottom { bottom: 0; border-bottom: none; }
.tboard-arc {
    position: absolute;
    left: 50%;
    width: 22%;
    height: 8%;
    border: 2px solid rgba(255,255,255,0.9);
    transform: translateX(-50%);
}
.tboard-arc-top { top: 15%; border-top: none; border-radius: 0 0 50% 50%; }
.tboard-arc-bottom { bottom: 15%; border-bottom: none; border-radius: 50% 50% 0 0; }

/* Version paysage (ordinateur, iPad — jamais iPhone, même seuil de 960px
   que le terrain de match) : le terrain s'affiche à l'horizontale (buts à
   gauche/droite plutôt qu'en haut/bas), incliné en perspective 3D. Le
   glisser-déposer reste fiable car le JS se base sur la position réelle
   des repères de coin (voir tactical-board-editor.js), pas sur une
   formule de transformation recalculée à la main. */
@media (min-width: 960px) and (orientation: landscape) {
    .tboard-pitch-3d-wrapper {
        perspective: 1400px;
        display: flex;
        justify-content: center;
        padding: 50px 20px 90px;
    }
    .tboard-pitch {
        max-width: 900px;
        padding-bottom: 69%; /* ratio inversé (1/1.45) : large plutôt que haut */
        transform: rotateX(38deg) scale(1.05);
        transform-style: preserve-3d;
        box-shadow: 0 55px 70px -25px rgba(0, 0, 0, 0.45);
    }
    .tboard-halfway-line {
        top: 0;
        bottom: 0;
        left: 50%;
        right: auto;
        width: 2px;
        height: auto;
    }
    .tboard-penalty-box {
        left: auto;
        right: auto;
        top: 14%;
        bottom: 14%;
        height: auto;
        width: 15%;
    }
    .tboard-penalty-top { left: 0; top: 14%; bottom: 14%; border-top: 2px solid rgba(255,255,255,0.9); border-left: none; }
    .tboard-penalty-bottom { right: 0; left: auto; top: 14%; bottom: 14%; border-bottom: 2px solid rgba(255,255,255,0.9); border-right: none; }
    .tboard-goal-box {
        top: 34%;
        bottom: 34%;
        height: auto;
        width: 6%;
    }
    .tboard-goal-top { left: 0; top: 34%; bottom: 34%; border-top: 2px solid rgba(255,255,255,0.9); border-left: none; }
    .tboard-goal-bottom { right: 0; left: auto; top: 34%; bottom: 34%; border-bottom: 2px solid rgba(255,255,255,0.9); border-right: none; }
    .tboard-arc {
        left: auto;
        top: 50%;
        width: 8%;
        height: 22%;
        transform: translateY(-50%);
    }
    .tboard-arc-top { left: 15%; top: 50%; border-top: 2px solid rgba(255,255,255,0.9); border-left: none; border-radius: 0 50% 50% 0; }
    .tboard-arc-bottom { right: 15%; left: auto; bottom: auto; top: 50%; border-bottom: 2px solid rgba(255,255,255,0.9); border-right: none; border-radius: 50% 0 0 50%; }
}

/* Liste des joueurs de l'effectif, à côté du terrain, glissables dessus */
.tboard-roster {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.tboard-roster-chip {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 8px;
    cursor: grab;
    touch-action: none;
    user-select: none;
    font-size: 0.85rem;
}
.tboard-roster-chip img,
.tboard-roster-chip .tboard-roster-avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}
.tboard-roster-avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--primary-dark);
    color: white;
    font-size: 0.7rem;
    font-weight: 700;
}
.tboard-layout {
    display: flex;
    gap: 20px;
    align-items: flex-start;
    flex-wrap: wrap;
}
.tboard-layout > .tboard-pitch-col {
    flex: 1 1 460px;
}
.tboard-layout > .tboard-roster-col {
    flex: 0 0 200px;
    max-width: 100%;
}

/* Placé après les règles de base ci-dessus (et non avant), pour être
   certain que ce bloc l'emporte à spécificité égale — sinon une règle de
   base déclarée plus bas dans le fichier gagnerait malgré la media
   query. */
@media (min-width: 960px) and (orientation: landscape) {
    /* L'effectif passe sous le terrain plutôt qu'à côté : ça libère de la
       largeur, utilisée pour agrandir le terrain (même proportions,
       juste plus grand) plutôt que de le partager avec la colonne
       effectif — affiché à l'horizontale plutôt qu'en liste verticale. */
    .tboard-layout {
        flex-direction: column;
    }
    .tboard-layout > .tboard-pitch-col {
        flex: 1 1 auto;
        width: 100%;
    }
    .tboard-layout > .tboard-roster-col {
        flex: 1 1 auto;
        max-width: 100%;
        width: 100%;
    }
    .tboard-roster {
        flex-direction: row;
        flex-wrap: wrap;
    }
    .tboard-roster-chip {
        flex: 0 1 220px;
    }
}

.tactic-modal {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.5);
    z-index: 2000;
    align-items: center;
    justify-content: center;
    padding: 16px;
}

.tactic-modal-box {
    background: var(--card);
    border-radius: 12px;
    padding: 20px;
    max-width: 380px;
    width: 100%;
}

/* ============================================================
   RESPONSIVE — tablette (iPad) et mobile (iPhone)
   Objectif : un rendu cohérent, sans texte coupé ni éléments qui
   débordent, quel que soit l'appareil.
   ============================================================ */

/* Tablette et en dessous (iPad portrait ~768-834px, iPad landscape ~1024px
   passe par la règle desktop normale ; celle-ci cible surtout le portrait) */
@media (max-width: 900px) {
    .container {
        padding: 0 12px;
        margin: 16px auto;
    }

    /* Sur mobile, la barre de navigation basse (bouton ☰ "Plus") ouvre
       exactement le même menu : le bouton hamburger de l'en-tête devient
       redondant, on le masque entièrement plutôt que d'avoir deux boutons
       identiques à l'écran. */
    .menu-toggle-btn {
        display: none;
    }

    /* Les tableaux ont souvent plus de colonnes que ne le permet la largeur
       de l'écran (rapports, composition de match...). Le défilement
       horizontal est géré par .table-scroll-wrapper (voir plus bas), PAS
       directement sur <table> : mettre overflow sur le tableau lui-même
       empêche position:sticky de fonctionner sur ses en-têtes. */
    table {
        white-space: nowrap;
    }
    th, td {
        white-space: nowrap;
    }

    .form-grid {
        grid-template-columns: 1fr;
    }

    .topbar {
        /* Ne pas utiliser la propriété raccourcie "padding" ici : elle
           écraserait le padding-top: calc(14px + env(safe-area-inset-top))
           défini dans la règle de base, qui protège le contenu de l'en-tête
           contre le chevauchement avec la barre de statut iOS (horloge,
           batterie) quand l'app est ouverte en plein écran depuis l'écran
           d'accueil. */
        padding-right: 16px;
        padding-bottom: 12px;
        padding-left: 16px;
    }
}

/* Téléphone (iPhone, ~390-430px de large en portrait) */
@media (max-width: 480px) {
    /* Palette resserrée pour un meilleur contraste sur iPhone : fond un
       peu plus soutenu (mieux distinguer les cartes blanches), bordures
       plus visibles, texte secondaire plus lisible. Tablette et PC
       gardent la palette d'origine, inchangée. */
    :root {
        --bg: #e7ecf5;
        --border: #c3d0e6;
        --muted: #4b5566;
    }

    .dashboard-icon-blue { background: #c2daf7; }
    .dashboard-icon-red { background: #f4c6c6; }

    /* Banc du match : 3 joueurs par ligne plutôt que 2, pour profiter au
       mieux de la largeur d'écran disponible sur iPhone. */
    .tactic-bench {
        gap: 8px;
        padding: 10px;
    }
    .tactic-bench-chip {
        flex: 0 1 calc(33.333% - 6px);
    }

    /* Titres des volets repliables (calendrier, Facebook...) : nettement
       trop imposants sur iPhone avec leur taille normale, réduits ici. */
    .collapsible-title {
        font-size: 0.92rem;
        font-weight: 600;
    }

    /* Nom du/des responsable(s) de la semaine (vareuses, matériel) : trop
       imposant sur iPhone avec sa taille normale. */
    .duty-current-name {
        font-size: 1.1rem;
    }
    /* Listes "Ordre de passage à venir" (vareuses, matériel) et leur
       texte explicatif : légèrement réduits, cohérent avec le reste. */
    .duty-explanation,
    .duty-queue-list {
        font-size: 0.85rem;
    }

    /* Le bouton secondaire se distingue plus nettement du nouveau fond,
       qui autrement se confondrait presque avec lui. */
    .btn-secondary {
        background: #d3ddf0;
        border: 1px solid #b9c8e3;
    }
    .btn-secondary:hover { background: #c3d0e8; }

    /* Barre de navigation basse, façon appli native (inspirée d'apps de
       gestion de club "pro") : les 4 sections les plus utilisées toujours
       accessibles d'un tap, sans passer par le menu ☰. */
    .bottom-nav {
        display: flex;
        align-items: center;
        position: fixed;
        bottom: 0; left: 0; right: 0;
        background: var(--card);
        border-top: 1px solid var(--border);
        /* padding-bottom absorbe la zone du home indicator (safe-area-inset-bottom
           ≈ 34px sur iPhone Face ID) pour que les icônes ne se retrouvent pas
           collées sur le trait d'accueil. Le fond de la barre s'étend visuellement
           sous le home indicator mais les icônes restent au-dessus. */
        padding: 6px 4px calc(6px + env(safe-area-inset-bottom, 0px));
        z-index: 500;
        box-shadow: 0 -4px 14px rgba(20, 40, 80, 0.12);
    }
    .bottom-nav-item {
        flex: 1;
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 2px;
        color: var(--muted);
        text-decoration: none;
        font-size: 0.68rem;
        font-weight: 600;
        background: none;
        border: none;
        padding: 4px 0;
        cursor: pointer;
        border-radius: 10px;
        transition: background 0.15s, color 0.15s;
    }
    .bottom-nav-icon {
        font-size: 1.35rem;
        line-height: 1;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 1.35rem;
        height: 1.35rem;
    }
    .bottom-nav-item.active {
        color: var(--primary);
        background: #e3ecfa;
    }
    /* Espace réservé en bas de page pour que le contenu ne se retrouve
       jamais caché derrière la barre fixe. Prend en compte la zone du
       home indicator (safe-area-inset-bottom) qui gonfle la barre du bas
       sur iPhone X et suivants — sans ça, les 34px supplémentaires font
       que le contenu est compressé vers le haut. */
    body { padding-bottom: calc(68px + env(safe-area-inset-bottom, 0px)); }

    /* Garantit que même une page très courte (ex: le hub "Messagerie", 3
       liens seulement) occupe au moins tout l'écran visible. Sans ça, sur
       certains navigateurs mobiles, une page qui ne nécessite aucun
       défilement ne déclenche jamais la réduction de la barre d'adresse :
       la barre de navigation fixe (bottom:0) se retrouve alors positionnée
       par rapport à un viewport plus petit que celui réellement visible une
       fois une page plus longue défilée, et semble "flotter" plus haut que
       sur les autres pages. 100dvh (viewport dynamique, tient compte de
       l'état réel de la barre du navigateur) avec repli 100vh pour les
       navigateurs qui ne le supportent pas encore. */
    body { min-height: 100vh; min-height: 100dvh; }

    /* Cartes un peu plus arrondies et une ombre plus marquée, pour un
       rendu plus "app native" que web plate. */
    .card {
        border-radius: 14px;
        box-shadow: 0 2px 10px rgba(20, 40, 80, 0.06);
    }
    .dashboard-icon {
        box-shadow: 0 2px 6px rgba(20, 40, 80, 0.15);
    }
    /* Bandeau d'en-tête légèrement dégradé plutôt que plat, pour un rendu
       un peu plus riche/premium. */
    .topbar { background: rgba(255, 255, 255, 0.92); }

    /* Quand le menu est ouvert depuis le bouton "Plus" de la barre basse,
       il doit sembler en sortir plutôt que d'apparaître en haut de la
       page — ancré juste au-dessus de la barre, avec une petite montée. */
    .dropdown-menu.bottom-anchored {
        position: fixed;
        top: auto;
        bottom: calc(68px + env(safe-area-inset-bottom, 0px));
        left: 10px;
        right: 10px;
        max-width: none;
        max-height: 65vh;
        animation: dropdown-slide-up 0.18s ease-out;
    }
    /* Le menu ouvert depuis "Plus" (bas) masque les liens déjà présents
       dans la barre de navigation — inutile de les répéter, ça allège
       nettement le menu sur mobile. Le bouton ☰ du haut (desktop/tablette,
       où il n'y a pas de barre basse) continue lui d'afficher la liste
       complète. */
    .dropdown-menu.bottom-anchored a.in-bottom-nav {
        display: none;
    }

    /* Le toast doit s'afficher au-dessus de la barre de navigation basse,
       pas derrière ni collé dessus. */
    .toast {
        bottom: calc(80px + env(safe-area-inset-bottom, 0px));
    }
    @keyframes dropdown-slide-up {
        from { transform: translateY(16px); opacity: 0; }
        to { transform: translateY(0); opacity: 1; }
    }

    .container {
        padding: 0 10px;
    }

    /* Inverse l'ordre bouton/badge : le bouton ☰ passe à gauche, le badge
       équipe à droite. Évite que le badge (texte parfois long, ex:
       "U13b — 2026/2027") ne perturbe l'ouverture du menu sur petit écran. */
    .menu-wrapper {
        flex-direction: row-reverse;
    }
    .dropdown-menu {
        right: auto;
        left: 0;
    }

    /* Texte globalement plus petit et moins agressif sur téléphone */
    body {
        font-size: 0.9rem;
    }

    h1 {
        font-size: 1.1rem;
        padding-bottom: 5px;
        border-bottom: 2px solid var(--primary);
    }
    h2 {
        font-size: 0.95rem;
        padding-bottom: 3px;
        border-bottom: 1px solid var(--border);
    }
    .btn, .btn-secondary, .btn-danger {
        font-size: 0.85rem;
        padding: 7px 14px;
    }
    .btn-small {
        font-size: 0.78rem;
    }

    /* Uniquement sur téléphone : le terrain a besoin de bien plus de
       hauteur (même largeur) pour que les postes ne se chevauchent pas —
       sur tablette/PC, le ratio d'origine (75%) reste inchangé. */
    .tactic-pitch {
        padding-bottom: 145%;
    }

    .card {
        padding: 14px 16px;
    }

    .page-header {
        flex-direction: column;
        align-items: stretch;
    }
    .page-header .btn,
    .page-header .actions {
        width: 100%;
    }

    .btn {
        width: 100%;
        text-align: center;
        padding: 11px 16px; /* cible tactile plus confortable */
    }
    /* Les boutons qui doivent rester côte à côte (actions de tableau,
       double bouton entrée/sortie...) ne passent pas en pleine largeur */
    .actions .btn,
    td .btn,
    .lineup-table .btn {
        width: auto;
    }

    .form-grid {
        gap: 0;
    }

    .result-box {
        font-size: 1.35rem;
    }

    /* Le chrono et ses boutons s'empilent proprement */
    .card > div[style*="justify-content:space-between"] {
        flex-direction: column;
        align-items: stretch !important;
        text-align: center;
    }

    /* Contraste renforcé pour toutes les cartes sur iPhone (pas seulement
       celles issues des tableaux) : le blanc de la carte se distingue mal
       du fond de page très clair sans un peu d'ombre. */
    .card {
        box-shadow: 0 2px 8px rgba(20, 40, 80, 0.10);
    }

    /* Filet de sécurité général : toute mise en page en ligne (souvent en
       style inline dans les templates : nom + bouton, champ + bouton...)
       peut désormais passer à la ligne plutôt que de déborder ou
       d'écraser son contenu sur un écran étroit. Ne change rien pour les
       lignes qui tiennent déjà (elles ne "wrappent" que si besoin). */
    [style*="display:flex"] {
        flex-wrap: wrap;
    }
    [style*="display:flex"] > input,
    [style*="display:flex"] > select,
    [style*="display:flex"] > textarea {
        min-width: 0;
        flex: 1 1 auto;
    }

    /* --------------------------------------------------------------
       Tableaux -> cartes verticales sur iPhone. Un tableau qui défile
       horizontalement (déjà en place pour tablette/desktop) devient
       illisible sur un écran de ~390px : chaque ligne devient une petite
       carte, avec chaque colonne affichée en dessous avec son étiquette
       (via data-label, injecté automatiquement par table-sort.js).
       -------------------------------------------------------------- */
    .table-scroll-wrapper table.sortable-table,
    .table-scroll-wrapper table.lineup-table {
        border: none;
        background: transparent;
    }
    .table-scroll-wrapper table.sortable-table thead,
    .table-scroll-wrapper table.lineup-table thead {
        display: none;
    }
    .table-scroll-wrapper table.sortable-table tbody,
    .table-scroll-wrapper table.lineup-table tbody,
    .table-scroll-wrapper table.sortable-table tr,
    .table-scroll-wrapper table.lineup-table tr {
        display: block;
        width: 100%;
    }
    .table-scroll-wrapper table.sortable-table tr,
    .table-scroll-wrapper table.lineup-table tr {
        background: var(--card);
        border: 1px solid var(--border);
        border-radius: 10px;
        margin-bottom: 14px;
        padding: 6px 14px;
        box-shadow: 0 2px 8px rgba(20, 40, 80, 0.12);
        overflow: hidden;
    }
    /* Joueur blessé pour une longue durée : fond rouge visible directement
       dans la liste, sans avoir à ouvrir sa fiche. */
    .table-scroll-wrapper table.sortable-table tr.player-row-injured {
        background: #fbe1de;
        border-color: var(--danger);
    }
    .table-scroll-wrapper table.sortable-table td,
    .table-scroll-wrapper table.lineup-table td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        flex-wrap: wrap;
        gap: 6px 10px;
        border-bottom: 1px solid var(--border);
        border-top: none !important;
        padding: 9px 0;
        white-space: normal;
        width: 100%;
        font-size: 0.82rem;
    }
    .table-scroll-wrapper table.sortable-table td:last-child,
    .table-scroll-wrapper table.lineup-table td:last-child {
        border-bottom: none;
    }
    .table-scroll-wrapper table.sortable-table td::before,
    .table-scroll-wrapper table.lineup-table td::before {
        content: attr(data-label);
        font-weight: 600;
        font-size: 0.8rem;
        color: var(--primary-dark);
        flex-shrink: 0;
        margin-right: 10px;
    }
    /* Première colonne (nom du joueur) : sert de titre à la carte, pas
       besoin d'étiquette répétée devant. */
    .table-scroll-wrapper table.sortable-table td:first-child,
    .table-scroll-wrapper table.lineup-table td:first-child {
        justify-content: flex-start;
        font-size: 0.9rem;
        font-weight: 600;
        color: var(--primary-dark);
    }
    .table-scroll-wrapper table.sortable-table td:first-child::before,
    .table-scroll-wrapper table.lineup-table td:first-child::before {
        content: none;
    }
    .table-scroll-wrapper table.sortable-table td > select,
    .table-scroll-wrapper table.sortable-table td > input,
    .table-scroll-wrapper table.lineup-table td > select,
    .table-scroll-wrapper table.lineup-table td > input {
        flex: 1 1 0 !important;
        min-width: 0 !important;
        max-width: 100%;
        margin-bottom: 0;
    }
    .table-scroll-wrapper table.sortable-table td.actions,
    .table-scroll-wrapper table.lineup-table td.actions {
        flex-wrap: wrap;
        justify-content: flex-end;
    }
}

/* Page "Fonctionnalités" : une ligne par fonctionnalité activable, avec
   son libellé, sa description et son état courant bien lisible. */
.feature-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 0;
    border-bottom: 1px solid var(--border);
}
.feature-row:last-child { border-bottom: none; }
.feature-toggle-label {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    cursor: pointer;
    flex: 1;
    margin-bottom: 0;
    width: auto;
}
.feature-toggle-label input[type="checkbox"] {
    width: auto;
    margin: 3px 0 0 0;
    flex-shrink: 0;
    transform: scale(1.3);
}
.feature-name {
    display: block;
    font-weight: 600;
    color: var(--text);
}
.feature-desc {
    display: block;
    margin-top: 2px;
    line-height: 1.35;
}
.feature-badge { flex-shrink: 0; }

/* Messagerie : annonces du club et fils de discussion parent/staff. */
.announcement-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
.announcement-dot {
    display: inline-block; width: 9px; height: 9px; border-radius: 50%;
    background: var(--primary); margin-right: 4px; vertical-align: middle;
}
.thread-row {
    display: flex; align-items: center; gap: 12px;
    text-decoration: none; color: var(--text);
}
.thread-preview {
    margin: 4px 0 0 0; overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; font-size: 0.85rem;
}
.chat-thread { display: flex; flex-direction: column; gap: 10px; max-height: 55vh; overflow-y: auto; }
.chat-bubble-row { display: flex; }
.chat-bubble-row.chat-mine { justify-content: flex-end; }
.chat-bubble {
    max-width: 78%; padding: 9px 13px; border-radius: 12px;
    background: #eef2f8; border: 1px solid var(--border);
}
.chat-bubble-mine { background: #dbe6f7; border-color: #c3d4ee; }
.chat-meta { font-size: 0.72rem; color: var(--muted); margin-bottom: 3px; }

/* Pièces jointes de la messagerie : vignettes pour les images,
   lien compact pour les autres documents. */
.attachment-list { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.attachment-thumb {
    display: block; width: 110px; height: 110px; border-radius: 8px;
    overflow: hidden; border: 1px solid var(--border);
}
.attachment-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.attachment-file {
    display: inline-block; padding: 6px 11px; background: #eef2f8;
    border: 1px solid var(--border); border-radius: 8px;
    font-size: 0.85rem; text-decoration: none; color: var(--primary-dark);
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-delete-btn {
    background: none; border: none; cursor: pointer; padding: 0 0 0 6px;
    font-size: 0.8rem; opacity: 0.55;
}
.chat-delete-btn:hover { opacity: 1; }

/* Pastille rouge de messages non lus, sur les boutons de menu (haut et
   barre de navigation basse mobile) et dans le menu déroulant. */
.unread-badge {
    position: absolute;
    z-index: 5;
    top: -4px;
    right: -6px;
    box-sizing: border-box;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: #ff3b30;
    color: #ffffff;
    font-size: 11px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}
.unread-badge-inline {
    display: inline-block;
    margin-left: 6px;
    vertical-align: middle;
    font-size: 0.7rem;
    padding: 1px 7px;
}

/* Bouton icône neutre (sans fond coloré) pour une action secondaire
   comme la suppression, quand on veut juste l'icône, pas un bouton
   plein. */
.icon-btn-plain {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 1.05rem;
    padding: 2px 4px;
    opacity: 0.6;
    line-height: 1;
}
.icon-btn-plain:hover { opacity: 1; }

/* Barre de recherche de la boîte de réception. */
.search-bar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.search-bar input[type="search"] { flex: 1; min-width: 160px; margin-bottom: 0; }

/* Formulaire de modification d'une annonce : replié par défaut, ouvert
   au clic sur le crayon. */
.announcement-edit-form {
    display: none;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--border);
}
.announcement-edit-form.open-edit { display: block; }

/* Enveloppe juste l'icône ☰ (sans toucher au dimensionnement de
   .bottom-nav-icon lui-même, fixé par ailleurs) pour ancrer la pastille
   "non lu" dessus sans perturber la hauteur de la barre de navigation. */
.bottom-nav-icon-badge-wrap {
    position: relative;
    display: inline-block;
    line-height: 1;
}

/* ==========================================================================
   Bibliothèque d'exercices (voir routers/exercise_library.py)
   ========================================================================== */
.exercise-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: flex-end;
    margin-bottom: 18px;
}
.exercise-filters > div { min-width: 150px; flex: 1; }
.exercise-filters label { font-size: 0.78rem; }
.exercise-filters select,
.exercise-filters input { margin-bottom: 0; }

.exercise-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 14px;
}
.exercise-card {
    display: flex;
    flex-direction: column;
    gap: 8px;
    text-decoration: none;
    color: inherit;
}
.exercise-card:hover { border-color: var(--primary); }
.exercise-card-badges { display: flex; flex-wrap: wrap; gap: 6px; }
.exercise-card-title { font-weight: 700; color: var(--primary-dark); font-size: 1rem; }
.exercise-card-objective { color: var(--muted); font-size: 0.85rem; }
.exercise-card-meta {
    display: flex; gap: 12px; font-size: 0.78rem; color: var(--muted);
    margin-top: auto; padding-top: 6px; border-top: 1px solid var(--border);
}

.exercise-sheet-meta {
    display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px;
}
.exercise-sheet-section { margin-top: 18px; }
.exercise-sheet-section h2 { margin-bottom: 6px; }
.exercise-sheet-text { white-space: pre-line; line-height: 1.5; }

/* Schéma animé étape par étape (static/exercise-diagram.js) */
.ex-diagram { margin-top: 10px; }
.ex-diagram-pitch-wrap {
    width: 100%;
    aspect-ratio: 100 / 62;
    border-radius: var(--radius, 10px);
    overflow: hidden;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
}
.ex-diagram-svg { width: 100%; height: 100%; display: block; }
.ex-diagram-step-layer { transition: opacity 0.25s ease; }
.ex-diagram-player circle { filter: drop-shadow(0 0.4px 0.6px rgba(0, 0, 0, 0.35)); }
.ex-diagram-controls {
    margin-top: 12px;
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    align-items: flex-start;
    justify-content: space-between;
}
.ex-diagram-stepinfo { flex: 1; min-width: 200px; }
.ex-diagram-stepcount {
    display: inline-block; font-size: 0.72rem; font-weight: 700;
    color: var(--primary); text-transform: uppercase; letter-spacing: 0.04em;
}
.ex-diagram-steptitle { font-weight: 700; margin-top: 2px; }
.ex-diagram-steptext { color: var(--muted); font-size: 0.85rem; margin-top: 2px; }
.ex-diagram-buttons { display: flex; gap: 8px; flex-wrap: wrap; }

/* Sélecteur d'exercices depuis le formulaire d'entraînement (voir
   training_form.html, section "Exercices de la séance") — même schéma
   visuel que .sub-themes-group (case à cocher + libellé), filtré par
   thème sélectionné comme les sous-thèmes juste au-dessus. */
.exercise-picker-group { margin-top: 10px; }
.exercise-picker-item {
    display: flex; align-items: flex-start; gap: 8px;
    padding: 6px 0; border-bottom: 1px solid var(--border);
}
.exercise-picker-item:last-child { border-bottom: none; }
.exercise-picker-item input { width: auto; margin: 3px 0 0; }
.exercise-picker-item-title { font-weight: 600; font-size: 0.88rem; }
.exercise-picker-item-meta { color: var(--muted); font-size: 0.76rem; margin-top: 1px; }
