/* =============================================================================
   PAGE /tournoi/{id}/matches — HABILLAGE MOBILE
   =============================================================================

   Tout est scope sous `body.uft-matches-page`, classe posee par
   templates/tournoi/tournoi_details/matches.html.twig. Rien ne peut fuir
   ailleurs, et le desktop n'est jamais touche : chaque bloc est dans un
   `@media (max-width: ...)`.

   ---------------------------------------------------------------------------
   CE QUI EXISTE DEJA AILLEURS — NE PAS DUPLIQUER
   ---------------------------------------------------------------------------
   fix/responsive.css (~ligne 1010) traite deja, sous 991px :
     - l'empilement vertical des deux colonnes (terrains / matchs a plannifier)
     - l'accordeon « Matchs a plannifier » (.plan-section-toggle)
   fix/style.css (~ligne 2319) traite deja :
     - le defilement horizontal des terrains, cartes de 85vw sous 768px
   Ces regles restent la ou elles sont. Ce fichier ne fait que completer.

   ---------------------------------------------------------------------------
   POURQUOI DU CSS UNIQUEMENT
   ---------------------------------------------------------------------------
   `public/js/match.js` CLONE la derniere journee du DOM pour en creer une
   nouvelle (`.journey-container` -> `.clone()`), et reconstruit le bouton
   « Supprimer » depuis un template JS (match.js ~2665) avec les memes classes
   `col-* masquer-btn btn-click1 remove-journey`.

   Consequence : une regle CSS s'applique automatiquement aux journees creees
   apres coup, alors qu'une modification du markup devrait etre repliquee dans
   le template ET dans le JS. D'ou le choix de tout faire en CSS.

   Accroches JS a preserver (aucune n'est modifiee ici) :
     .remplissage-automatique, .add-terrain-btn, .edit-journey-temps-jeux,
     .degenerer-match, .remove-journey, #button-ajouter-journee, #save-matchs,
     .journey-date-str, .terrain-item, .sortable-match-item
   ============================================================================= */


/* -----------------------------------------------------------------------------
   1. CONTENEUR DE LA LISTE DES JOURNEES
   -----------------------------------------------------------------------------
   `.journey-list-container` porte `padding: 0 30px !important` (fix/style.css,
   sans media query, donc actif aussi en mobile) : 60px perdus, soit 17% d'un
   ecran de 360px. Le `!important` d'origine impose le notre.
   -------------------------------------------------------------------------- */
@media (max-width: 991.98px) {

    body.uft-matches-page .journey-list-container {
        padding-left: 10px !important;
        padding-right: 10px !important;
    }
}


/* -----------------------------------------------------------------------------
   2. DATE DE LA JOURNEE
   -----------------------------------------------------------------------------
   Le `<h6 class="journey-date-str">` porte en style INLINE
   `font-size: 2em; white-space: nowrap; width: 100%`. A 2em, « Samedi 15 aout
   2026 » ne tient pas sur 360px, et `nowrap` l'empeche de se replier : la page
   deborde horizontalement.

   Les deux declarations etant inline, `!important` est obligatoire (une
   declaration importante de feuille de style bat une declaration normale de
   l'attribut style).
   -------------------------------------------------------------------------- */
@media (max-width: 991.98px) {

    body.uft-matches-page .journey-date-str {
        font-size: 18px !important;
        white-space: normal !important;
        line-height: 1.25;
        margin-bottom: 6px !important;
    }
}


/* -----------------------------------------------------------------------------
   3. BOUTONS D'UNE JOURNEE -> PAVES CARRES
   -----------------------------------------------------------------------------
   Cinq a six boutons (REMPLISSAGE AUTOMATIQUE, AJOUTER UN TERRAIN, TEMPS DE
   JEU, DEGENERER LES MATCHES, et SUPPRIMER a partir de la 2e journee) declares
   `col-12 col-md-12 col-lg-2 col-xl-2`.

   `col-12` n'est PAS borne a un breakpoint : il s'applique a toutes les
   largeurs. En mobile, chaque bouton occupait donc une ligne pleine largeur —
   environ 350px de hauteur de boutons avant le premier terrain, repete pour
   CHAQUE journee.

   Meme parti pris que /poules et /finales : des paves carres cote a cote qui
   se replient sur deux lignes. Dimensions alignees sur celles de
   tournoi-poules.css (section 8) : 104x60, graisse 900, libelle 10px.
   Toute modification de ces valeurs doit etre reportee aux trois endroits.

   Points a ne pas manquer :
     - `white-space: normal` : les libelles sont longs (« REMPLISSAGE
       AUTOMATIQUE ») et DOIVENT pouvoir passer sur plusieurs lignes.
     - `padding` en `!important` : `.masquer-btn` pose `12px 30px`, ce qui ne
       laisserait aucune place au texte dans un pave de 104px.
     - la decoupe de `.masquer-btn` est en POURCENTAGES
       (`100% 60%` -> `91% 100%`), donc dependante de la hauteur du bouton :
       sur un pave carre le biseau devenait enorme. Remplacee par une valeur en
       pixels, identique quelle que soit la taille.
   -------------------------------------------------------------------------- */
@media (max-width: 991.98px) {

    /* La barre d'en-tete d'une journee. `.journey-container > .row` ne matche
       que celle-ci : le second enfant direct porte la classe `row--`
       (volontairement neutralisee dans le markup), pas `row`. */
    body.uft-matches-page .journey-container > .row {
        --bs-gutter-x: 0;
        --bs-gutter-y: 0;
        gap: 10px !important;
        margin-bottom: 18px !important;
        padding: 0;
    }

    /* DEUX PAR LIGNE. Largeur en pourcentage plutot qu'en pixels : c'est la
       seule facon de garantir le nombre par ligne quelle que soit la largeur
       de l'ecran (a 104px fixes, un telephone large en logeait trois).
       `- 5px` = la moitie du `gap` de 10px, pour que deux paves plus l'espace
       qui les separe fassent exactement 100%. */
    body.uft-matches-page .journey-container > .row > .masquer-btn {
        width: calc(50% - 5px);
        max-width: calc(50% - 5px);
        height: 60px;
        flex: 0 0 calc(50% - 5px);
        margin: 0 !important;
        padding: 8px 6px !important;
        font-size: 10px !important;
        font-weight: 900 !important;
        line-height: 1.2;
        text-align: center;
        white-space: normal;
        -webkit-clip-path: polygon(0 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 0 100%);
        clip-path: polygon(0 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 0 100%);
    }

    /* Le libelle est enveloppe dans un `<span>` qui contient parfois une icone
       (`bi-plus-lg`, `bi-clock-history`) et parfois non. On empile icone puis
       texte pour que les paves avec et sans icone gardent la meme allure. */
    body.uft-matches-page .journey-container > .row > .masquer-btn > span {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 2px;
        width: 100%;
    }

    /* `pe-2` (padding-right) est pense pour une icone EN LIGNE avec le texte :
       une fois l'icone au-dessus, ce padding la decale vers la gauche. */
    body.uft-matches-page .journey-container > .row > .masquer-btn .bi {
        padding-right: 0 !important;
        font-size: 14px;
        line-height: 1;
    }
}


/* -----------------------------------------------------------------------------
   4. BOUTONS DE BAS DE PAGE
   -----------------------------------------------------------------------------
   « AJOUTER UNE JOURNEE » et « METTRE EN LIGNE ».

   Une seule ligne, 50 / 50, et la meme typographie que les boutons de bas de
   page de /equipes, /poules, /finales et /tournoi/new : Futura Std, droit,
   graisse 700, 12px, padding 11/14. Les cinq pages du parcours de
   configuration presentent donc le meme pied de page.

   Le premier bouton porte `margin-right: 20px` et les deux `font-size: 1em` en
   style inline — sans `!important`, une declaration de feuille de style
   importante suffit donc a les surcharger. Les deux `mt-5` (3rem) sont
   neutralises de la meme facon.

   `align-items: flex-start` : chaque bouton garde la hauteur que lui donne son
   padding, on ne les egalise pas.
   -------------------------------------------------------------------------- */
@media (max-width: 991.98px) {

    body.uft-matches-page .button-ajouter-journee-ctnr {
        flex-direction: row;
        align-items: flex-start;
        gap: 10px;
        padding-top: 1.5rem !important;
        padding-bottom: 1.5rem !important;
    }

    body.uft-matches-page .button-ajouter-journee-ctnr > .btn {
        flex: 0 0 calc(50% - 5px);
        max-width: calc(50% - 5px);
        width: calc(50% - 5px);
        margin: 0 !important;
        padding: 11px 14px !important;
        font-family: 'Futura Std', sans-serif !important;
        font-style: normal !important;
        font-weight: 700 !important;
        font-size: 12px !important;
        /* Les boutons sont deja `d-flex align-items-center` : il ne manque que
           le centrage horizontal du couple libelle + chevron. */
        justify-content: center;
        text-align: center;
        line-height: 1.2;
        /* « AJOUTER UNE JOURNEE » ne tient pas sur une ligne dans une demi
           largeur de telephone. */
        white-space: normal;
    }

    /* Le chevron ne doit pas se retrouver sur sa propre ligne quand le libelle
       se replie : `flex-shrink: 0` le garde colle au texte. */
    body.uft-matches-page .button-ajouter-journee-ctnr > .btn .bi {
        flex: 0 0 auto;
        font-size: 12px;
    }
}


/* -----------------------------------------------------------------------------
   5. MODALS
   -----------------------------------------------------------------------------
   Onze modals sur cette page, en deux familles :

     A. formulaire   — #ModalAddTerrain, #ModalMatchEdit, #ModalPause,
                       #Modalevent, #ModalAddJournee, #Modaltemps,
                       #ModalFillTerrainByPoule
     B. confirmation — #ModalDelete, #ModalRemplissage, #ModalRetirerTerrain,
                       #ModalRetirerJourney (un titre + deux boutons NON/OUI)

   Les selecteurs sont prefixes par `body.uft-matches-page` : ces ids
   n'existent que sur cette page, mais le scope garantit qu'un id homonyme
   ajoute ailleurs plus tard ne recevrait pas ces regles par surprise.
   -------------------------------------------------------------------------- */
@media (max-width: 767.98px) {

    /* --- Commun aux deux familles --------------------------------------- */

    /* `.modal-content` (fix/style.css) : `padding: 1em` + decoupes de 35px aux
       quatre coins, calibrees pour un ecran large. Meme valeur que les modals
       de /poules et /finales : 18px. */
    body.uft-matches-page .modal-content {
        padding: 0.6em !important;
        -webkit-clip-path: polygon(18px 0, 100% 0, 100% 18px, 100% 100%, calc(100% - 18px) 100%, 18px 100%, 0 100%, 0 18px);
        clip-path: polygon(18px 0, 100% 0, 100% 18px, 100% 100%, calc(100% - 18px) 100%, 18px 100%, 0 100%, 0 18px);
    }

    body.uft-matches-page .modal-header {
        padding: 4px 6px 8px 6px;
        align-items: flex-start;
    }

    body.uft-matches-page .modal-body {
        padding: 6px 8px 12px 8px;
    }

    /* Les titres de ces modals sont des `<h1>` : ~2.5rem par defaut, soit un
       titre plus haut que le formulaire qu'il annonce. */
    body.uft-matches-page .modal-header h1,
    body.uft-matches-page .modal-body h1 {
        font-size: 15px;
        line-height: 1.3;
    }

    body.uft-matches-page .modal-title {
        font-size: 15px;
        line-height: 1.3;
    }

    /* --- A. Modals de formulaire ----------------------------------------- */

    /* `.row.row-cols-2` impose DEUX colonnes a toutes les largeurs, alors que
       les enfants sont declares `col-12` : selon l'ordre de cascade de
       Bootstrap l'un des deux gagne, et a 50% les champs deviennent
       inutilisables. On tranche explicitement : une colonne. */
    body.uft-matches-page .modal-body .row.row-cols-2 {
        --bs-gutter-x: 0;
        flex-direction: column;
        gap: 10px !important;
    }

    body.uft-matches-page .modal-body .row.row-cols-2 > * {
        width: 100%;
        max-width: 100%;
        flex: 0 0 auto;
        padding-left: 0;
        padding-right: 0;
    }

    body.uft-matches-page .modal-body .form-label {
        font-size: 11px;
        line-height: 15px;
        margin-bottom: 0.35rem;
    }

    /* 16px est un plancher : en dessous, iOS Safari zoome au focus du champ. */
    body.uft-matches-page .modal-body .form-control,
    body.uft-matches-page .modal-body .form-select {
        height: 38px;
        padding: 4px 12px;
        font-size: 16px;
    }

    /* #Modaltemps : les champs de duree portent `width: 20%` en style inline,
       calibre sur un modal large. A 20% de 300px il ne reste pas la place
       d'afficher deux chiffres. */
    body.uft-matches-page #Modaltemps .form-control[style*="width: 20%"] {
        width: 72px !important;
        flex: 0 0 auto;
        text-align: center;
    }

    body.uft-matches-page #Modaltemps .modal-body > .d-flex {
        gap: 0.75rem !important;
    }

    /* Pastilles de duree inter-match : `flex-wrap` est deja pose en inline,
       il ne manque que de quoi les compacter. */
    body.uft-matches-page #Modaltemps .uft-ck-item label {
        padding: 6px 12px;
        font-size: 11px;
    }

    /* --- B. Modals de confirmation --------------------------------------- */

    /* Rangee NON / OUI : `gap-4` (1.5rem) entre deux boutons en `w-100`, et
       `mt-5` (3rem) au-dessus. Trop genereux une fois le modal compacte. */
    body.uft-matches-page .modal-body > .d-flex.flex-row.gap-4,
    body.uft-matches-page .modal-content > .d-flex.flex-row.gap-4 {
        gap: 10px !important;
        margin-top: 1rem !important;
    }

    body.uft-matches-page .modal-body > .d-flex.flex-row.gap-4 > .btn,
    body.uft-matches-page .modal-content > .d-flex.flex-row.gap-4 > .btn {
        font-size: 12px !important;
        padding: 10px 8px;
        white-space: nowrap;
    }

    /* Boutons « Valider » des modals de formulaire : `mt-5` (3rem) et
       `font-size: 1em` en style inline, d'ou le `!important`. */
    body.uft-matches-page .modal-body > .btn {
        margin-top: 1.25rem !important;
        font-size: 12px !important;
        padding: 10px 26px;
        white-space: nowrap;
    }
}

/* -----------------------------------------------------------------------------
   6. COMPACITE DES TERRAINS ET DES CARTES DE MATCH
   -----------------------------------------------------------------------------
   Tout est calibre pour une colonne desktop large : cartes de terrain de
   300px, libelles a 0.9rem / 0.8rem, marges en `rem`. Sur telephone, une carte
   de terrain occupait 85vw et un seul match tenait a l'ecran.

   Les cartes de match ont EXACTEMENT le meme markup dans les deux contextes
   (`.sortable-match-item`, generees par le template pour les terrains et par
   match.js pour la liste a plannifier). Les regles ne sont donc pas prefixees
   par l'un ou l'autre conteneur : elles s'appliquent aux deux, ce qui garantit
   qu'une carte reste identique a elle-meme quand on la deplace de la liste
   vers un terrain — et evite d'avoir a maintenir deux jeux de valeurs.

   NE SONT PAS TOUCHES, volontairement :
     - les boutons crayon / corbeille des terrains (`.pen-edit-terrain-btn`,
       `.pen-remove-terrain-btn`) et le crayon des matchs (`.pen-edit-btn`) :
       leur positionnement absolu est valide, on n'y touche pas.
     - `padding-top: 12px` sur `.terrain-list-ctnr` (fix/style.css) : c'est lui
       qui empeche les boutons en `top: -10px` d'etre rognes par
       l'`overflow-y: hidden` du conteneur a defilement.
     - la hauteur de `.full-match-list-ctnr` (500px) : des cartes plus compactes
       suffisent a en afficher davantage.

   Les tailles de police des titres, des noms d'equipe et du « VS » sont en
   style INLINE dans le markup — d'ou les `!important`.
   -------------------------------------------------------------------------- */
@media (max-width: 991.98px) {

    /* --- La carte de terrain --------------------------------------------- */

    /* 300px en desktop, 85vw sous 768px (fix/style.css). A 85vw on ne devine
       pas qu'il y a un terrain suivant ; a 240px la carte voisine depasse, ce
       qui rend le defilement horizontal evident. Le `max-width` en vw garde
       une marge sur les tres petits ecrans. */
    body.uft-matches-page .journey-container .terrain-list-ctnr > .terrain-item {
        width: 240px;
        max-width: 72vw;
        padding-bottom: 1.25rem !important;
    }

    body.uft-matches-page .journey-container .terrain-list-ctnr {
        gap: 8px !important;
    }

    /* Le fond decoratif de la carte est un `::after` avec une decoupe de 35px,
       proportionnee a une carte de 300px. */
    body.uft-matches-page .terrain-clip-path-fix:after {
        -webkit-clip-path: polygon(0 0, 100% 0, 100% calc(100% - 18px), calc(100% - 18px) 100%, 0 100%);
        clip-path: polygon(0 0, 100% 0, 100% calc(100% - 18px), calc(100% - 18px) 100%, 0 100%);
    }

    /* Le nom du terrain porte `py-3` : 1rem au-dessus et en dessous. */
    body.uft-matches-page .terrain-item .terrain-name {
        font-size: 13px;
        padding-top: 8px !important;
        padding-bottom: 8px !important;
        margin-bottom: 0;
    }

    /* --- La carte de match ------------------------------------------------
       Communes aux terrains ET a la liste « Matchs a plannifier ». */

    /* `mb-3 pb-1 px-3` : 1rem de marge basse et 1rem de padding lateral, sur
       une carte qui n'en fait plus que 240 de large. */
    body.uft-matches-page .sortable-match-item > .clip-leftPoint {
        margin-bottom: 8px !important;
        padding-left: 8px !important;
        padding-right: 8px !important;
        padding-bottom: 3px !important;
    }

    /* Titre « GROUPE A - PHASE.P#1 » : 0.9rem en inline. */
    body.uft-matches-page .sortable-match-item .match-title {
        font-size: 10px !important;
        line-height: 1.25;
        padding-top: 3px !important;
        padding-bottom: 2px !important;
    }

    /* Etiquettes « JOURNEE 2 » (bleue) et « MATCH 1, PLACES 1-8 » (verte) :
       11px et 5px de padding (global.css). */
    body.uft-matches-page .sortable-match-item .etiquette-poule,
    body.uft-matches-page .sortable-match-item .etiquette-ph-f {
        font-size: 9px;
        padding: 2px 5px;
        margin-bottom: 3px;
        line-height: 1.2;
    }

    /* Noms d'equipes : 0.8rem en inline. `word-break` parce qu'un nom long
       (« PSG ACADEMY A ») doit se couper plutot que d'elargir la carte. */
    body.uft-matches-page .sortable-match-item .team_1_name,
    body.uft-matches-page .sortable-match-item .team_2_name {
        font-size: 10px !important;
        line-height: 1.2;
        word-break: break-word;
    }

    /* Le « VS » n'existe que dans la liste a plannifier. 0.75rem en inline. */
    body.uft-matches-page .sortable-match-item .vs-label {
        font-size: 9px !important;
        letter-spacing: .5px !important;
    }

    /* Le bandeau gris de l'heure. */
    body.uft-matches-page .sortable-match-item .match-result-div {
        margin-top: 1px;
        margin-bottom: 1px;
    }

    body.uft-matches-page .sortable-match-item .match_item_start_time,
    body.uft-matches-page .sortable-match-item .pause_duration {
        font-size: 10px;
        padding-left: 6px !important;
        padding-right: 6px !important;
    }

    /* `gap-1` (0.25rem) entre equipe 1 / heure / equipe 2. */
    body.uft-matches-page .sortable-match-item .clip-leftPoint > .d-flex.flex-column {
        gap: 2px !important;
    }

    /* Cartes de pause : meme traitement pour le libelle. */
    body.uft-matches-page .sortable-match-item .pause_name {
        font-size: 10px;
        line-height: 1.25;
    }

    /* --- Boutons internes a un terrain ------------------------------------
       « AJOUTER UNE PAUSE » et « AJOUTER UN EVENEMENT » : `width: 100%` en
       inline (conserve) mais `padding: 12px 30px` de `.masquer-btn`, ce qui ne
       laisse presque plus de place au libelle dans une carte de 240px. */
    body.uft-matches-page .terrain-item .masquer-btn {
        padding: 8px 6px !important;
        font-size: 9px !important;
        line-height: 1.2;
        white-space: normal;
    }

    body.uft-matches-page .terrain-item .masquer-btn .bi {
        font-size: 11px;
        padding-right: 3px !important;
    }
}

/* -----------------------------------------------------------------------------
   7. ONGLET VERTICAL « MATCHS A PLANNIFIER » + PANNEAU LATERAL
   -----------------------------------------------------------------------------
   Il y a UNE liste par journee, pas une pour la page : le bloc vit dans
   `.journey-container`, repete par la boucle du template. L'onglet vertical est
   donc lui aussi place DANS la journee — il devient collant a l'interieur de
   celle-ci et disparait quand on passe a la suivante.

   Ferme  : la colonne sort du flux, l'onglet vertical est le seul point
            d'entree. Plus rien ne traine en bas de la journee.
   Ouvert : la colonne devient un panneau `fixed` colle a droite, sur toute la
            hauteur de l'ecran. On la ferme par la barre verte en tete du
            panneau (l'accordeon d'origine, conserve tel quel).

   Le passage en `position: fixed` evite de deplacer le bloc dans le DOM : les
   selecteurs de match.js (`.full-match-list-parent-ctnr`,
   `.full-match-list-ctnr`, `connectWith` du sortable) continuent de voir la
   meme arborescence.

   DESKTOP INTACT : tout est borne a 991.98px, et l'onglet porte `d-lg-none`
   dans le markup — au-dessus de 992px il n'existe pas et la colonne reste a sa
   place, a droite des terrains.
   -------------------------------------------------------------------------- */
@media (max-width: 991.98px) {

    /* --- L'onglet vertical ------------------------------------------------ */

    /* `height: 0` : le conteneur ne prend aucune place dans le flux, le bouton
       deborde par-dessus le contenu. `pointer-events: none` sur le conteneur
       (et `auto` sur le bouton) pour que la bande invisible n'intercepte pas
       les clics sur les terrains situes derriere. */
    body.uft-matches-page .journey-plan-tab-ctnr {
        position: sticky;
        top: 40vh;
        height: 0;
        display: flex;
        justify-content: flex-end;
        /* INDISPENSABLE avec `height: 0`. Par defaut un conteneur flex etire
           ses enfants (`align-items: stretch`) : le bouton heritait donc d'une
           hauteur de 0 et son fond etait ecrase, seul le padding restait
           visible. `flex-start` lui rend sa hauteur de contenu, qui deborde
           librement du conteneur sans hauteur. */
        align-items: flex-start;
        z-index: 1040;
        pointer-events: none;

        /* Le conteneur est etendu a la largeur REELLE de l'ecran, quel que soit
           le padding de ses ancetres : `justify-content: flex-end` place alors
           le bouton contre le bord du telephone, pas contre le bord du bloc.
           Plus fiable qu'une marge negative calee sur une valeur de padding
           precise — si ce padding change, le bouton reste colle. */
        width: 100vw;
        margin-left: calc(50% - 50vw);
    }

    /* Masque quand le panneau est ouvert : il se retrouverait dessous.
       La classe est posee par le script inline du template. */
    body.uft-matches-page .journey-container.plan-open .journey-plan-tab-ctnr {
        display: none;
    }

    body.uft-matches-page .journey-plan-tab {
        pointer-events: auto;
        border: 0;
        /* Texte vertical, lu de haut en bas : le bouton devient une languette
           etroite le long du bord droit. */
        writing-mode: vertical-rl;
        /* En `vertical-rl` l'axe du texte est vertical : `padding` haut/bas
           encadre le libelle, gauche/droite donne l'epaisseur de la languette. */
        padding: 16px 15px;
        background-color: #006f3a;
        color: #ffffff;
        font-size: 10px;
        font-weight: 500;
        font-style: italic;
        text-transform: uppercase;
        letter-spacing: .5px;
        line-height: 1;
        white-space: nowrap;
        box-shadow: -2px 0 8px rgba(0, 0, 0, .3);
        /* UN SEUL biseau, en haut a gauche — le seul angle libre : la droite
           touche le bord de l'ecran. En pixels, pour que la decoupe ne change
           pas de taille avec la hauteur du bouton. */
        -webkit-clip-path: polygon(12px 0, 100% 0, 100% 100%, 0 100%, 0 12px);
        clip-path: polygon(12px 0, 100% 0, 100% 100%, 0 100%, 0 12px);
    }

    /* --- Le panneau ------------------------------------------------------- */

    /* Ferme : hors du flux. */
    body.uft-matches-page .journey-container .matches-plan-col {
        display: none;
    }

    /* Ouvert : fenetre PLEIN ECRAN, comme un modal.

       Les quatre cotes sont cales sur le viewport plutot que d'imposer une
       hauteur : `height: 100vh` se serait retrouve trop grand sur mobile, ou
       la barre d'adresse du navigateur est comptee dans `vh` mais masque une
       partie de l'ecran.

       `padding-top` genereux : il degage la place de la croix de fermeture,
       posee en absolu par-dessus. */
    body.uft-matches-page .journey-container .matches-plan-col.mobile-expanded {
        display: block;
        position: fixed !important;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        transform: none;
        width: auto !important;
        height: 100%;
        max-width: none !important;
        max-height: none;
        z-index: 1045;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        /* Amortit le defilement : arrive en butee, la page derriere ne prend
           pas le relais. */
        overscroll-behavior: contain;
        background-color: #ffffff;
        /* ZONE SURE iOS. Cette fenetre est calee sur les QUATRE cotes du
           viewport : avec `viewport-fit=cover`, elle passe donc sous l'encoche
           et sous la barre d'accueil. Les 46px du haut degagent la croix de
           fermeture, l'encart s'y ajoute pour qu'elle ne finisse pas sous
           l'ilot dynamique. Vaut 0 hors iOS. */
        padding: calc(46px + var(--uft-safe-top, 0px)) 12px calc(20px + var(--uft-safe-bottom, 0px)) 12px;
    }

    /* --- La croix de fermeture ------------------------------------------- */

    /* Masquee par defaut : la colonne fermee est deja en `display: none`, mais
       la regle protege le cas ou elle redeviendrait visible autrement. */
    body.uft-matches-page .plan-section-close {
        display: none;
    }

    /* Positionnee en absolu par rapport a la fenetre (qui est `fixed`, donc
       bloc contenant). `position: fixed` serait equivalent ici, mais `absolute`
       garde la croix solidaire de la fenetre si elle change un jour de mode. */
    body.uft-matches-page .matches-plan-col.mobile-expanded .plan-section-close {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        position: absolute;
        top: calc(10px + var(--uft-safe-top, 0px));
        right: 10px;
        z-index: 3;
        width: 30px;
        height: 30px;
        padding: 0;
        border: 0;
        border-radius: 3px;
        /* Meme rouge que les boutons de fermeture des pages tournoi. */
        background-color: #C72520;
        color: #ffffff;
        font-size: 14px;
        line-height: 1;
    }

    /* `mt-3 mb-5` sur le conteneur interne : 3rem de vide en bas d'une fenetre
       dont le padding est deja gere ci-dessus. `px-3` en plus du padding de la
       fenetre ferait 26px de perdus de chaque cote. */
    body.uft-matches-page .matches-plan-col.mobile-expanded > .full-match-list-parent-ctnr > .d-flex.flex-column {
        margin-top: 0 !important;
        margin-bottom: 0 !important;
        padding-left: 0 !important;
        padding-right: 0 !important;
    }

    /* Le fond decoratif `::after` de `.poly-match-list-div` est en
       `height: 100%` sur un conteneur qui, lui, ne defile plus : il ne
       couvrirait que la premiere hauteur d'ecran. La fenetre portant deja son
       propre fond blanc, on le retire. */
    body.uft-matches-page .matches-plan-col.mobile-expanded .poly-match-list-div:after {
        display: none;
    }

    /* La barre verte sert de titre a la fenetre. Elle etait collante en haut
       pour rester atteignable comme moyen de fermeture — inutile depuis que la
       croix, elle, est en position absolue et donc toujours visible. Rendue au
       flux : elle defile avec le reste et ne mange plus de hauteur en
       permanence. Elle ferme toujours au clic. */
    body.uft-matches-page .matches-plan-col.mobile-expanded .plan-section-toggle {
        position: static;
        margin-bottom: 10px !important;
    }

    /* Les filtres (groupes / finales / journees / equipes) : deux des quatre
       portent `max-width: 150px !important` en style inline, calibre sur une
       colonne desktop etroite. Dans une fenetre de 92vw, ils se retrouvaient
       plus petits que leurs voisins et la rangee partait de travers. */
    body.uft-matches-page .matches-plan-col.mobile-expanded .match-journey-filter,
    body.uft-matches-page .matches-plan-col.mobile-expanded .match-team-filter {
        max-width: 100% !important;
    }

    body.uft-matches-page .matches-plan-col.mobile-expanded .form-select {
        font-size: 11px !important;
        padding-left: 10px !important;
        padding-right: 26px !important;
    }

    /* La decoupe de `.top-polygon-btn` (fix/style.css) est en POURCENTAGES :

         polygon(50% 0%, 80% 0, 100% 0, 100% 56%, 100% 100%,
                 50% 100%, 20% 100%, 0 100%, 0 40%, 20% 0)

       Le biseau haut-gauche vaut 20% de la LARGEUR et 40% de la HAUTEUR : il
       change donc de taille et d'inclinaison d'un filtre a l'autre selon la
       place que chacun occupe, et les quatre selects n'ont pas le meme angle.

       Repris en pixels : 12px sur les deux axes, identique partout. Les
       sommets colineaires (50% 0%, 80% 0, 100% 56%, 50% 100%) sont supprimes,
       ils ne dessinaient rien. */
    body.uft-matches-page .matches-plan-col.mobile-expanded .top-polygon-btn {
        -webkit-clip-path: polygon(12px 0, 100% 0, 100% 100%, 0 100%, 0 12px);
        clip-path: polygon(12px 0, 100% 0, 100% 100%, 0 100%, 0 12px);
    }

    /* Les deux rangees de filtres portent `px-3` : superflu, la fenetre a deja
       son padding. */
    body.uft-matches-page .matches-plan-col.mobile-expanded .plan-section-content > .d-flex.flex-row {
        padding-left: 0 !important;
        padding-right: 0 !important;
        gap: 8px !important;
    }

    /* `height: 500px` (fix/style.css) est calibre pour une colonne desktop
       etroite. Ici c'est la FENETRE qui defile, sur toute sa hauteur : une
       hauteur fixe a l'interieur creerait un second ascenseur imbrique. */
    body.uft-matches-page .matches-plan-col.mobile-expanded .full-match-list-ctnr {
        height: auto;
        overflow-y: visible;
    }
}

/* -----------------------------------------------------------------------------
   8. RETOUR VISUEL DE L'APPUI LONG (TACTILE)
   -----------------------------------------------------------------------------
   public/js/uft-touch-drag.js pose la classe `uft-drag-armed` sur la carte au
   moment ou l'appui long atteint son seuil, juste avant d'emettre le
   `mousedown` de synthese — donc AVANT que jQuery UI ne clone la carte pour en
   faire son fantome, qui herite ainsi de l'effet.

   Sans ce retour, rien ne distingue « le glissement est arme » de « il ne se
   passe rien » : l'utilisateur releve le doigt avant le seuil et conclut que
   la fonction est cassee. Le shim declenche aussi une vibration courte quand
   l'appareil le permet.

   PAS de media query : la classe n'est posee que par le shim tactile, lui-meme
   charge uniquement sur cette page (`enableTouchDrag`) et ne reagissant qu'aux
   evenements `touch*`. A la souris, elle n'apparait jamais.

   Une section 8 precedente agrandissait le titre des cartes pour en faire une
   poignee. Elle a ete retiree avec la poignee elle-meme : la contrainte venait
   de `touch-punch`, remplace depuis.
   -------------------------------------------------------------------------- */
body.uft-matches-page .sortable-match-item.uft-drag-armed {
    /* Souleve la carte. `transform` plutot que `margin` : aucune influence sur
       la mise en page, donc aucun reflow des cartes voisines au moment ou le
       glissement demarre. */
    transform: scale(1.04);
    box-shadow: 0 8px 20px rgba(0, 0, 0, .4);
    /* Le fantome de jQuery UI est place a la souris des le `mousedown` : une
       transition trop longue le ferait grandir pendant le deplacement. */
    transition: transform .12s ease, box-shadow .12s ease;
    position: relative;
    z-index: 5;
}

/* -----------------------------------------------------------------------------
   9. PLACEHOLDER DE DEPOT
   -----------------------------------------------------------------------------
   Le placeholder est le trou qui s'ouvre a l'endroit ou la carte va atterrir.
   Il doit avoir EXACTEMENT la taille et l'allure de la carte deplacee, sinon le
   contenu se decale pendant le glissement et on ne vise pas ce qu'on croit.

   Deux moities a ce correctif :
     - cote JS (match.js, callback `start`), le placeholder reprend la liste de
       classes de la carte : toutes les regles ecrites pour
       `.sortable-match-item` s'appliquent donc a son contenu ;
     - ici, on neutralise l'habillage propre de `.sortable-match-item-holder`
       (clean.css:460), qui lui donnait une allure de case vide : bordure
       pointillee, fond translucide, decoupe differente de celle des cartes, et
       surtout une hauteur fixe de 50px et une marge basse de 10px qui
       s'ajoutaient a celles de la carte copiee.

   PAS de media query, et volontairement : le decalage existait aussi bien en
   desktop qu'en mobile — le placeholder n'a jamais eu la taille de la carte.
   C'est le seul endroit de ce fichier qui modifie le rendu desktop, et cela ne
   concerne QUE le placeholder, visible uniquement pendant un glissement.
   Le scope `body.uft-matches-page` empeche d'atteindre l'autre sortable du site
   (`.sortable-criteres-egalites`, tournoi.js).

   `.sortable-placeholder-active` (opacite 0.5) est conservee : c'est la seule
   chose qui distingue le trou d'une vraie carte. Sans elle, on ne saurait plus
   dire ou est le placeholder et ou sont les matchs deja poses.
   -------------------------------------------------------------------------- */
body.uft-matches-page .sortable-match-item-holder {
    /* La carte copiee porte deja sa propre decoupe (`.clip-leftPoint`) et sa
       marge basse (`mb-3`). Tout ce que le holder ajoutait faisait doublon. */
    border: 0;
    background-color: transparent;
    -webkit-clip-path: none;
    clip-path: none;
    width: 100%;
    height: auto;
    margin-bottom: 0 !important;
    padding: 0;
}

/* -----------------------------------------------------------------------------
   10. SELECTEUR « PLACER SUR… » DES CARTES A PLANNIFIER
   -----------------------------------------------------------------------------
   Injecte par match.js (`setupMobileTerrainAssign`) sur chaque carte de la
   liste a plannifier, en mobile uniquement. Le choix envoie le match a la fin
   du terrain retenu ; l'ordre precis se regle ensuite entre les terrains, au
   glisser-deposer.

   Le seuil de la media query reprend EXACTEMENT celui du test JavaScript
   (991.98px) : les deux ne peuvent pas diverger, et en desktop le selecteur
   n'est pas seulement masque — il n'est pas dans le DOM.

   Le `<select>` ne peut pas declencher de glissement : jQuery UI Sortable
   l'exclut par defaut via son option `cancel`. Le menu s'ouvre donc au doigt,
   et un balayage au-dessus fait defiler la page normalement.
   -------------------------------------------------------------------------- */
@media (max-width: 991.98px) {

    /* Le selecteur vit DANS la boite blanche de la carte : la bande grise du
       bas est la bordure simulee de la carte, rien ne doit s'y poser. */
    body.uft-matches-page .uft-assign-terrain-ctnr {
        margin: 6px 0 3px 0;
        padding: 0;
        width: 100%;
        /* Centre le selecteur, qui ne fait plus toute la largeur de la carte. */
        display: flex;
        justify-content: center;
    }

    body.uft-matches-page .uft-assign-terrain {
        /* Demi-largeur : le selecteur est une commande secondaire, il ne doit
           pas peser autant que la carte de match qui le porte. */
        width: 50%;
        height: 30px;
        padding: 2px 26px 2px 10px;
        /* 16px minimum sur un champ de saisie evite le zoom automatique d'iOS,
           mais un `<select>` n'y est pas soumis : le menu s'ouvre en surcouche
           native, sans mise au point sur le champ. On peut donc rester compact. */
        font-size: 11px;
        font-weight: 700;
        font-style: italic;
        text-transform: uppercase;
        color: #ffffff;
        background-color: #006f3a;
        border: 0;
        border-radius: 0;
        /* Meme biseau, en pixels, que les autres commandes de la fenetre. */
        -webkit-clip-path: polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px);
        clip-path: polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px);
    }

    /* La fleche par defaut de Bootstrap est sombre, illisible sur le vert. */
    body.uft-matches-page .uft-assign-terrain {
        background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
        background-repeat: no-repeat;
        background-position: right 8px center;
        background-size: 10px 8px;
    }

    /* Les options sont rendues par le systeme : fond clair impose, sinon le
       texte blanc heriterait et deviendrait invisible dans le menu natif. */
    body.uft-matches-page .uft-assign-terrain option {
        color: #373759;
        background-color: #ffffff;
        font-style: normal;
    }
}

/* -----------------------------------------------------------------------------
   11. EN-TETE D'UNE CARTE DE TERRAIN
   -----------------------------------------------------------------------------
   Trois elements se disputent le haut de la carte, tous en position absolue et
   tous poses en style INLINE (d'ou les `!important`) :

     .btn-fill-terrain-poule   « Matchs par Groupe », injecte par match.js:479
                               a `top:-10px; left:-5px`
     .pen-remove-terrain-btn   corbeille, `top:-10px; right:20px`
     .pen-edit-terrain-btn     crayon,    `top:-10px; right:-10px`

   Le nom du terrain, lui, est dans le flux et centre. Sur une carte desktop de
   300px il restait lisible entre les deux groupes de boutons ; ramene a 240px
   en mobile, il passait SOUS « Matchs par Groupe ».

   On ne deplace rien : on degage simplement la bande occupee par les boutons
   (28px de haut, remontes de 10px, soit 18px sous le bord) en repoussant le
   titre en dessous. Le positionnement des boutons est conserve.
   -------------------------------------------------------------------------- */
@media (max-width: 991.98px) {

    /* Le titre passe sous la bande des boutons. La valeur de la section 6
       (8px) ne suffisait pas : elle ne tenait pas compte de ces trois
       elements superposes. */
    body.uft-matches-page .terrain-item .terrain-name {
        padding-top: 24px !important;
    }

    /* « Matchs par Groupe » : `btn-sm` le laisse a 0.875rem, soit pres de la
       moitie de la largeur d'une carte de 240px. */
    body.uft-matches-page .terrain-item .btn-fill-terrain-poule {
        top: -8px !important;
        left: -4px !important;
        padding: 4px 8px !important;
        font-size: 9px !important;
        line-height: 1.15;
        white-space: nowrap;
    }

    /* Crayon et corbeille.

       A l'origine : crayon a `right: -10px` (il depassait donc du bord droit de
       la carte) et corbeille a `right: 20px`. Le crayon occupant 28px de large,
       il s'etendait de -10 a +18px : 2px seulement le separaient de la
       corbeille, les deux se lisaient comme un seul bloc.

       On decale la paire de 10px vers l'interieur — le crayon vient affleurer
       le bord de la carte au lieu d'en sortir — et on porte l'ecart entre les
       deux a 8px.

       Seule la position horizontale change : les positions verticales et la
       taille des boutons restent celles d'origine. */
    body.uft-matches-page .terrain-item .pen-edit-terrain-btn {
        right: 0 !important;
    }

    body.uft-matches-page .terrain-item .pen-remove-terrain-btn {
        right: 36px !important;
    }
}
