/* =========================================================================
   AQUAE Engagements — feuille de style unique
   ========================================================================= */

:root {
    --encre:            #0f172a;
    --encre-douce:      #475569;
    /* Le gris des mentions secondaires : en-tetes de tableau, dates, aides de
       champ, pied de page. Il etait a #94a3b8, soit 2,50 : 1 sur blanc — sous
       le minimum de 4,5 : 1 que demande le WCAG pour du petit texte, et
       illisible pour qui ne voit plus de tres pres. #64748b donne 4,76 : 1 et
       reste aussi discret a l oeil. */
    --encre-tres-douce: #64748b;
    --fond:             #f4f6fb;
    --surface:          #ffffff;
    --bordure:          #e2e8f0;
    --accent:           #4f46e5;
    --accent-fonce:     #4338ca;
    --accent-clair:     #eef2ff;
    /* La colonne des menus : un bleu profond, et les deux encres qui s'y
       lisent. Trois valeurs a changer pour la reteinter en entier. */
    --lateral-fond:     #1e3a8a;
    --lateral-encre:    rgba(255, 255, 255, .76);
    --lateral-survol:   rgba(255, 255, 255, .14);
    --degrade:          linear-gradient(150deg, #4f46e5 0%, #6366f1 45%, #06b6d4 100%);
    --succes:           #047857;
    --succes-fond:      #ecfdf5;
    --erreur:           #b91c1c;
    --erreur-fond:      #fef2f2;
    --info:             #1d4ed8;
    --info-fond:        #eff6ff;
    --rayon:            14px;
    --rayon-petit:      9px;
    --ombre:            0 1px 2px rgba(15, 23, 42, .04), 0 12px 32px -12px rgba(15, 23, 42, .18);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    min-height: 100vh;
    background: var(--fond);
    color: var(--encre);
    font-family: "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    font-size: 16px;
    line-height: 1.55;
}

a { color: var(--accent); }
a:hover { color: var(--accent-fonce); }

h1, h2, h3 { line-height: 1.25; margin: 0; }

/* ---------- Marque ---------------------------------------------------- */

.marque {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-weight: 700;
    letter-spacing: -.01em;
    text-decoration: none;
    color: var(--encre);
}

.marque__pastille {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border-radius: 10px;
    background: var(--degrade);
    color: #fff;
    font-size: 13px;
    letter-spacing: .02em;
}

.marque--clair { color: #fff; }
.marque--clair .marque__pastille { background: rgba(255, 255, 255, .18); }

/* ---------- Pages publiques (connexion / inscription) ----------------- */

.gabarit-auth { display: block; }

.auth {
    display: grid;
    grid-template-columns: 1fr;
    min-height: 100vh;
}

.auth__vitrine {
    display: none;
    background: var(--degrade);
    color: #fff;
    padding: 56px 52px;
}

.auth__titre {
    margin-top: 64px;
    font-size: 2.3rem;
    font-weight: 700;
    letter-spacing: -.02em;
}

.auth__atouts {
    margin: 44px 0 0;
    padding: 0;
    list-style: none;
    max-width: 40ch;
}

.auth__atouts li {
    position: relative;
    padding: 0 0 0 30px;
    margin-bottom: 16px;
    color: rgba(255, 255, 255, .9);
    font-size: .95rem;
}

.auth__atouts li::before {
    content: "";
    position: absolute;
    left: 0;
    top: .45em;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: rgba(255, 255, 255, .22);
    box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, .55);
}

.auth__panneau {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    padding: 40px 20px;
}

/* Le logo coiffe le formulaire des pages publiques. Deux limites le tiennent,
   l'une en largeur, l'autre en hauteur : plus grand, il repousserait les champs
   sous le bord de l'ecran, et c'est la saisie qui compte ici. */
.logo-appli {
    display: block;
    /* Les attributs width et height du <img> reservent la place avant le
       chargement, mais ils valent aussi des dimensions imposees : sans ces
       deux « auto », les limites ci-dessous ecrasaient l'image au lieu de la
       reduire. */
    width: auto;
    height: auto;
    max-width: 220px;
    /* Un portable ouvre souvent une fenetre de 800 pixels de haut : le logo y
       rend la hauteur qu'il prend, plutot que de pousser le bouton « Se
       connecter » sous le bord de l'ecran. Les deux limites s'appliquent
       ensemble sans deformer l'image. */
    max-height: 24vh;
    margin: 0 auto 24px;
}

/* ---------- Resultats ---------------------------------------------------- */

/* La pastille PDF devant le titre d'un document. Le dessin vit ici, en une
   seule copie : trois gabarits l'affichent — l'ecran de depot, la page des
   clubs, la page publique — et trois copies d'un meme SVG auraient fini par ne
   plus se ressembler. Elle est decorative : le lien dit deja ce qu'il ouvre. */
.lien-pdf::before {
    content: "";
    display: inline-block;
    width: 15px;
    height: 18px;
    margin-right: 8px;
    vertical-align: -4px;
    background: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 24'>\
<path d='M3 1.6h8.4L17 7.2V22.4H3z' fill='%23fff' stroke='%23dc2626' stroke-width='1.5' stroke-linejoin='round'/>\
<path d='M11.4 1.6v5.6H17' fill='none' stroke='%23dc2626' stroke-width='1.5' stroke-linejoin='round'/>\
<rect x='1.2' y='11.6' width='17.6' height='7.2' rx='1.6' fill='%23dc2626'/>\
<text x='10' y='17.3' font-family='Helvetica,Arial,sans-serif' font-size='5.4' font-weight='700' fill='%23fff' text-anchor='middle'>PDF</text>\
</svg>") no-repeat center / contain;
}

/* Zone de depot : un libelle ordinaire tant qu'aucun script ne tourne — le
   champ de fichier est dedans, et le clic l'ouvre comme n'importe quel label. */
.zone-depot {
    display: block;
    padding: 18px 16px;
    margin-bottom: 18px;
    border: 2px dashed var(--bord);
    border-radius: 12px;
    text-align: center;
    cursor: pointer;
    transition: border-color .15s, background .15s;
}

.zone-depot:hover { border-color: var(--accent); background: #f7f9ff; }

/* Survol d'un glissement : la cible doit etre franche, on lache a l'aveugle. */
.zone-depot--visee {
    border-color: var(--accent);
    border-style: solid;
    background: #eef2ff;
}

.zone-depot--envoi { opacity: .6; cursor: progress; }

.zone-depot__icone { display: block; color: var(--accent); }
.zone-depot__icone svg { width: 26px; height: 26px; }

.zone-depot__texte {
    display: block;
    margin-top: 6px;
    font-weight: 600;
}

.zone-depot__aide {
    display: block;
    margin-top: 2px;
    font-size: .82rem;
    color: var(--encre-douce);
}

/* Le champ natif reste dans le label, atteignable au clavier, mais invisible :
   son « Aucun fichier choisi » doublonnerait avec la ligne d'etat. */
.zone-depot input[type="file"] {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

/* Cote clubs et public, un sous-dossier se decale — le bloc est le meme a tous
   les niveaux, seul son retrait change. */
.bloc-dossier__enfant { margin: 10px 0 0 18px; }

/* --- L'explorateur de l'administration ---------------------------------- */

/* Le fil d'Ariane : ou l'on est, et autant de cibles ou lacher ce qu'on
   deplace — remonter de trois niveaux d'un seul geste. */
.fil-ariane {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px;
    margin-bottom: 14px;
    font-size: .92rem;
}

.fil-ariane__maillon {
    padding: 4px 9px;
    border-radius: 8px;
    text-decoration: none;
    color: var(--encre-douce);
}

.fil-ariane__maillon:hover { background: var(--fond-doux); color: var(--encre); }
.fil-ariane__maillon--actif { color: var(--encre); font-weight: 600; }
.fil-ariane__separateur { color: var(--encre-douce); }

/* Une ligne de l'explorateur se prend et se pose : le curseur le dit. */
.tableau--explorateur tbody tr[draggable="true"] { cursor: grab; }
.tableau--explorateur tbody tr[draggable="true"]:active { cursor: grabbing; }
.ligne--glissee { opacity: .45; }

/* La cible visee pendant qu'on tient une ligne au-dessus. Le fond porte sur
   toutes les cellules : une ligne de tableau n'a pas de fond a elle. */
.cible-dossier,
.cible-dossier > td { background: #eef2ff; }
.cible-dossier > td:first-child { box-shadow: inset 3px 0 0 var(--accent); }
.fil-ariane__maillon.cible-dossier { box-shadow: inset 0 0 0 2px var(--accent); }

/* Le dossier parent : une ligne de service, plus discrete que le reste. */
.ligne-remonter td { background: var(--fond-doux); }
.ligne-remonter a { color: var(--encre-douce); text-decoration: none; }
.ligne-remonter a:hover { color: var(--encre); }

/* Le pictogramme du dossier, devant son nom — pendant de la pastille PDF. */
.lien-dossier { display: inline-flex; align-items: center; gap: 8px; }
.icone-dossier { display: inline-flex; color: #d97706; }
.icone-dossier svg { width: 19px; height: 19px; }
.icone-dossier--haut { font-size: 1.05rem; color: var(--encre-douce); }

.explorateur__vide {
    padding: 22px 12px;
    text-align: center;
    color: var(--encre-douce);
}

/* La barre du deplacement en deux temps : ce qu'on tient, et ou le poser. */
.barre-deplacement {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px;
}

.barre-deplacement__actions { display: flex; align-items: center; gap: 8px; }

/* Un formulaire qui tient sur une ligne, dans une barre ou une cellule. */
.forme-en-ligne {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
}

.forme-en-ligne input[type="text"] { min-width: 0; }

/* ---------- Carte formulaire ------------------------------------------ */

.carte {
    width: 100%;
    max-width: 460px;
    background: var(--surface);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    box-shadow: var(--ombre);
    padding: 32px;
}

.carte__titre { font-size: 1.4rem; letter-spacing: -.01em; }

/* Une carte qui porte deux reglages a besoin de les separer. Un trait et un
   intitule suffisent : la carte est etroite (460 px), on ne va pas y empiler
   des sous-cartes. */
.carte__sous-titre {
    margin: 30px 0 14px;
    padding-top: 22px;
    border-top: 1px solid var(--bordure);
    font-size: .95rem;
    font-weight: 700;
}

.carte__intro {
    margin: 8px 0 26px;
    color: var(--encre-douce);
    font-size: .92rem;
}

.carte__bas {
    margin: 22px 0 0;
    padding-top: 18px;
    border-top: 1px solid var(--bordure);
    text-align: center;
    font-size: .9rem;
    color: var(--encre-douce);
}

/* ---------- Formulaires ----------------------------------------------- */

.champ { margin-bottom: 18px; }

.champ label {
    display: block;
    margin-bottom: 6px;
    font-size: .87rem;
    font-weight: 600;
    color: var(--encre);
}

.requis { color: var(--erreur); font-weight: 400; }

.champ input {
    width: 100%;
    padding: 11px 13px;
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-petit);
    background: #fff;
    color: var(--encre);
    font: inherit;
    font-size: .95rem;
    transition: border-color .15s, box-shadow .15s;
}

.champ input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(79, 70, 229, .16);
}

/* Valeur imposee, que personne ne modifie : le numero de club. On garde le
   gabarit d'un champ pour ne pas trouer l'alignement du formulaire, mais le
   fond mat et l'absence de bordure claire disent qu'il n'y a rien a saisir. */
.champ__fige {
    margin: 0;
    padding: 11px 13px;
    border: 1px dashed var(--bordure);
    border-radius: var(--rayon-petit);
    background: var(--fond);
    color: var(--encre);
    font-size: .95rem;
    font-weight: 600;
    letter-spacing: .08em;
    font-variant-numeric: tabular-nums;
}

.champ__aide, .champ__erreur {
    margin: 6px 0 0;
    font-size: .8rem;
}

.champ__aide  { color: var(--encre-tres-douce); }
.champ__erreur { color: var(--erreur); font-weight: 500; }

.champ--erreur input { border-color: var(--erreur); }
.champ--erreur input:focus { box-shadow: 0 0 0 3px rgba(185, 28, 28, .14); }

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

/* ---------- Boutons ---------------------------------------------------- */

.bouton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 10px 18px;
    border: 1px solid transparent;
    border-radius: var(--rayon-petit);
    font: inherit;
    font-size: .92rem;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    transition: background-color .15s, border-color .15s, color .15s;
}

.bouton--principal { background: var(--accent); color: #fff; }
.bouton--principal:hover { background: var(--accent-fonce); color: #fff; }

.bouton--fantome {
    background: transparent;
    border-color: var(--bordure);
    color: var(--encre-douce);
}
.bouton--fantome:hover { background: var(--fond); color: var(--encre); }

.bouton--large { width: 100%; padding: 12px 18px; margin-top: 6px; }

/* ---------- Alertes ---------------------------------------------------- */

.alerte {
    width: 100%;
    max-width: 460px;
    margin: 0 auto 18px;
    padding: 12px 15px;
    border: 1px solid transparent;
    border-radius: var(--rayon-petit);
    font-size: .89rem;
}

.alerte--erreur { background: var(--erreur-fond); border-color: #fecaca; color: var(--erreur); }
.alerte--succes { background: var(--succes-fond); border-color: #a7f3d0; color: var(--succes); }
.alerte--info   { background: var(--info-fond);   border-color: #bfdbfe; color: var(--info); }

.gabarit-app .alerte { max-width: none; margin: 0 0 20px; }

/* ---------- Espace connecté ------------------------------------------- */

.gabarit-app {
    display: flex;
    flex-direction: column;
}

.barre {
    background: var(--surface);
    border-bottom: 1px solid var(--bordure);
}

.barre__contenu {
    max-width: 1240px;
    margin: 0 auto;
    padding: 14px 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}

.barre__nav {
    display: flex;
    align-items: center;
    gap: 14px;
}

.barre__club {
    font-size: .88rem;
    font-weight: 600;
    color: var(--encre-douce);
    padding: 5px 11px;
    border-radius: 999px;
    background: var(--accent-clair);
}

/* L'administration n'a plus « Mon club » dans son menu : sa pastille de nom
   devient le lien vers son compte. */
.barre__club--lien { text-decoration: none; }
.barre__club--lien:hover { color: var(--accent-fonce); }

.barre__nav form { margin: 0; }

.coque {
    flex: 1;
    width: 100%;
    max-width: 1240px;
    margin: 0 auto;
    display: flex;
    align-items: flex-start;
}

.page {
    flex: 1;
    min-width: 0;
    padding: 30px 24px 56px;
}

.accueil__sur-titre {
    margin: 0;
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--accent);
}

.accueil__titre {
    margin: 6px 0 0;
    font-size: 2rem;
    letter-spacing: -.02em;
}

.accueil__intro {
    margin: 10px 0 0;
    max-width: 62ch;
    color: var(--encre-douce);
}

.stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 16px;
    margin-top: 28px;
}

.stat {
    background: var(--surface);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    padding: 20px 22px;
}

.stat__valeur {
    margin: 0;
    font-size: 2rem;
    font-weight: 700;
    letter-spacing: -.02em;
}

.stat__libelle {
    margin: 2px 0 0;
    font-size: .85rem;
    color: var(--encre-douce);
}

.colonnes {
    display: grid;
    grid-template-columns: 1fr;
    gap: 20px;
    margin-top: 20px;
}

.bloc {
    background: var(--surface);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    padding: 24px;
}

.bloc__titre {
    font-size: 1.05rem;
    margin-bottom: 18px;
}

.etapes { margin: 0; padding: 0; list-style: none; }

.etapes__item {
    display: flex;
    gap: 14px;
    padding: 12px 0;
    border-top: 1px solid var(--bordure);
}
.etapes__item:first-child { border-top: 0; padding-top: 0; }

.etapes__item strong { font-size: .94rem; }

.etapes__item p {
    margin: 2px 0 0;
    font-size: .85rem;
    color: var(--encre-douce);
}

.etapes__item em { font-style: normal; color: var(--encre-tres-douce); }

.etapes__puce {
    flex: 0 0 26px;
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--fond);
    border: 1px solid var(--bordure);
    font-size: .78rem;
    font-weight: 700;
    color: var(--encre-tres-douce);
}

.etapes__item--fait .etapes__puce {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

.fiche {
    margin: 0;
    display: grid;
    grid-template-columns: minmax(120px, 40%) 1fr;
    gap: 0;
}

.fiche dt, .fiche dd {
    margin: 0;
    padding: 9px 0;
    border-top: 1px solid var(--bordure);
    font-size: .89rem;
}

.fiche dt { color: var(--encre-douce); }
.fiche dd { font-weight: 600; word-break: break-word; }
.fiche dt:first-of-type, .fiche dt:first-of-type + dd { border-top: 0; }

.pied {
    border-top: 1px solid var(--bordure);
    padding: 18px 20px;
    text-align: center;
    font-size: .82rem;
    color: var(--encre-tres-douce);
}

.pied p { margin: 0; }

/* ---------- Ecrans larges --------------------------------------------- */

@media (min-width: 900px) {
    .auth { grid-template-columns: 46% 54%; }
    /* Page d'erreur : pas de vitrine, la carte se centre sur toute la largeur. */
    .auth--seule { grid-template-columns: 1fr; }
    .auth__vitrine { display: block; }
    .auth__panneau { padding: 40px; }
    .colonnes { grid-template-columns: 1.15fr 1fr; }
    /* Une liste flanquee d'un formulaire de saisie garde une seule colonne
       tant que l'ecran ne peut pas nourrir les deux : cote a cote, la liste
       etouffait — ses libelles passaient sous la colonne d'actions epinglee.
       Les deux s'empilent donc, et ne se separent qu'au large. */
    .colonnes--liste { grid-template-columns: minmax(0, 1fr); }
    /* Empiles, c'est la LISTE qui vient en premier : elle est le contenu, le
       formulaire n'est qu'une action. Seul l'ecran large, ou les deux tiennent
       cote a cote, met le formulaire a gauche. */
    .colonnes--liste > :first-child { order: 2; }
    .colonnes--liste > :last-child  { order: 1; }
    /* Sous la liste, le formulaire garde une largeur de saisie : des champs de
       mille pixels pour une heure ou un libelle ne se lisent plus. */
    .colonnes--liste > :first-child .bloc { max-width: 620px; }
}

@media (min-width: 1500px) {
    /* La place existe : le formulaire prend la colonne de GAUCHE, a sa largeur
       utile, et la liste s'etale sur tout le reste. */
    .colonnes--liste { grid-template-columns: 340px minmax(0, 1fr); align-items: start; }
    .colonnes--liste > :first-child,
    .colonnes--liste > :last-child { order: 0; }
}

@media (max-width: 520px) {
    .grille-2 { grid-template-columns: 1fr; }
    .carte { padding: 24px 20px; }
    .accueil__titre { font-size: 1.6rem; }
}

/* ---------- Menu lateral ---------------------------------------------- */

.lateral {
    flex: 0 0 236px;
    align-self: stretch;
    padding: 24px 12px;
    /* Le fond suffit a separer la colonne de la page : le filet d'avant
       ferait une arete grise au bord du bleu. */
    border-right: 0;
    background: var(--lateral-fond);
}

.lateral__nav {
    display: flex;
    flex-direction: column;
    gap: 2px;
    position: sticky;
    top: 24px;
}

.lateral__item {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 9px 12px;
    border-radius: var(--rayon-petit);
    font-size: .91rem;
    font-weight: 500;
    text-decoration: none;
    color: var(--lateral-encre);
    transition: background-color .15s, color .15s;
}

.lateral__item:hover { background: var(--lateral-survol); color: #fff; }

/* L'entree courante en pastille blanche : sur un fond bleu, c'est elle qui se
   voit en premier, et l'on sait ou l'on est sans lire. */
.lateral__item--actif {
    background: #fff;
    color: var(--accent-fonce);
    font-weight: 600;
}
.lateral__item--actif:hover { background: #fff; color: var(--accent-fonce); }

.lateral__item--inactif {
    color: rgba(255, 255, 255, .42);
    cursor: default;
}
.lateral__item--inactif:hover { background: transparent; color: rgba(255, 255, 255, .42); }

.lateral__icone { flex: 0 0 18px; width: 18px; height: 18px; }

.lateral__item--inactif .etiquette { margin-left: auto; }

/* ---------- Entete de page -------------------------------------------- */

.entete-page {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 20px;
    flex-wrap: wrap;
    margin-bottom: 24px;
}

.entete-page__titre { font-size: 1.7rem; letter-spacing: -.02em; }

.entete-page__intro {
    margin: 6px 0 0;
    color: var(--encre-douce);
    font-size: .92rem;
}

.fil {
    margin: 0 0 6px;
    font-size: .82rem;
    color: var(--encre-tres-douce);
}
.fil a { text-decoration: none; }
.fil a:hover { text-decoration: underline; }

/* ---------- Tableaux ---------------------------------------------------- */

.tableau-boite {
    background: var(--surface);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    overflow-x: auto;
}

.tableau {
    width: 100%;
    border-collapse: collapse;
    font-size: .9rem;
}

.tableau th, .tableau td {
    padding: 12px 16px;
    text-align: left;
    border-top: 1px solid var(--bordure);
    white-space: nowrap;
}

.tableau thead th {
    border-top: 0;
    background: #fbfcfe;
    font-size: .76rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--encre-tres-douce);
}

.tableau tbody tr:hover { background: #fbfcfe; }

.colonne-etroite { width: 1%; }

.colonne-actions {
    width: 1%;
    text-align: right;
}

.colonne-actions form { display: inline; margin: 0; }
.colonne-actions .bouton + form { margin-left: 6px; }

.lien-fort {
    font-weight: 600;
    text-decoration: none;
    color: var(--encre);
}
.lien-fort:hover { color: var(--accent); text-decoration: underline; }

.discret { color: var(--encre-tres-douce); }

.note {
    margin: 14px 0 0;
    font-size: .82rem;
    color: var(--encre-tres-douce);
}

/* ---------- Etiquettes -------------------------------------------------- */

.etiquette {
    display: inline-block;
    padding: 3px 9px;
    border-radius: 999px;
    background: var(--fond);
    border: 1px solid var(--bordure);
    font-size: .74rem;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--encre-tres-douce);
    white-space: nowrap;
}

.etiquette--succes {
    background: var(--succes-fond);
    border-color: #a7f3d0;
    color: var(--succes);
}

/* ---------- Etat vide ---------------------------------------------------- */

.vide {
    background: var(--surface);
    border: 1px dashed var(--bordure);
    border-radius: var(--rayon);
    padding: 48px 28px;
    text-align: center;
}

.vide__titre { margin: 0; font-size: 1.05rem; font-weight: 700; }

.vide__texte {
    margin: 8px auto 22px;
    max-width: 46ch;
    color: var(--encre-douce);
    font-size: .9rem;
}

/* ---------- Formulaire en pleine page ------------------------------------ */

.bloc--formulaire { max-width: 640px; }

.champ select {
    width: 100%;
    padding: 11px 13px;
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-petit);
    background: #fff;
    color: var(--encre);
    font: inherit;
    font-size: .95rem;
}

.champ select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(79, 70, 229, .16);
}

.champ--case label {
    display: flex;
    align-items: center;
    gap: 9px;
    font-weight: 500;
}

.champ--case input { width: auto; margin: 0; }

.actions-formulaire {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 26px;
    padding-top: 20px;
    border-top: 1px solid var(--bordure);
}

.bouton--petit { padding: 6px 12px; font-size: .82rem; }

.bouton--danger { color: var(--erreur); }
.bouton--danger:hover { background: var(--erreur-fond); border-color: #fecaca; color: var(--erreur); }

.visuellement-cache {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* ---------- Menu lateral sur petit ecran --------------------------------- */

@media (max-width: 860px) {
    .coque { flex-direction: column; }

    .lateral {
        flex: none;
        width: 100%;
        align-self: auto;
        padding: 10px 12px;
        border-right: 0;
        border-bottom: 0;
        overflow-x: auto;
    }

    .lateral__nav {
        position: static;
        flex-direction: row;
        gap: 4px;
    }

    .lateral__item { white-space: nowrap; }
    .lateral__item--inactif .etiquette { display: none; }

    .page { padding: 24px 16px 48px; }

    .entete-page { flex-direction: column; align-items: stretch; }
}

/* ---------- Back-office : menu, filtres, tableaux ---------------------- */

.lateral__titre {
    margin: 18px 0 4px;
    padding: 0 12px;
    font-size: .7rem;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, .72);
}

.stats--compact {
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    margin-top: 0;
    margin-bottom: 22px;
}

.stats--compact .stat { padding: 14px 16px; }
.stats--compact .stat__valeur { font-size: 1.5rem; }
.stats--compact .stat__libelle { font-size: .78rem; }

.barre-outils {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

.recherche {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1 1 340px;
}

.recherche input {
    flex: 1;
    min-width: 0;
    padding: 9px 13px;
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-petit);
    background: var(--surface);
    color: var(--encre);
    font: inherit;
    font-size: .9rem;
}

.recherche input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(79, 70, 229, .16);
}

.filtres {
    display: inline-flex;
    padding: 3px;
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-petit);
    background: var(--surface);
}

.filtres__item {
    padding: 6px 14px;
    border-radius: 6px;
    font-size: .85rem;
    font-weight: 600;
    text-decoration: none;
    color: var(--encre-douce);
}

.filtres__item:hover { background: var(--fond); color: var(--encre); }

.filtres__item--actif {
    background: var(--accent);
    color: #fff;
}
.filtres__item--actif:hover { background: var(--accent-fonce); color: #fff; }

.ligne--pause { background: #fcfcfd; }
.ligne--pause .lien-fort { color: var(--encre-douce); }

.cellule-principale { display: block; }

.cellule-secondaire {
    display: block;
    margin-top: 2px;
    font-size: .8rem;
    color: var(--encre-tres-douce);
}

/* Sur une ligne peinte par le suivi en direct, meme un gris corrige ne tient
   pas : les fonds sont francs — voulus ainsi pour un ecran de salle — et la
   mention tombe a 1,8 : 1 sur le vert du podium, 1,9 : 1 sur le jaune de
   l echauffement. Elle repasse donc en encre pleine, comme le nom qu elle
   accompagne. L attribut est pose par le serveur et tenu a jour par
   assets/js/suivi.js ; un forfait garde son rouge, qui dit autre chose. */
.tableau tr[data-etat]:not([data-etat=""]):not(.ligne--forfait) .cellule-secondaire,
.tableau tr[data-etat]:not([data-etat=""]):not(.ligne--forfait) .discret {
    color: var(--encre);
}

.etiquette--accent {
    background: var(--accent-clair);
    border-color: #c7d2fe;
    color: var(--accent-fonce);
}

.etiquette--alerte {
    background: #fff7ed;
    border-color: #fed7aa;
    color: #b45309;
}

.entete-page__titre .etiquette {
    vertical-align: middle;
    margin-left: 8px;
    font-size: .7rem;
}

.tableau--nu { font-size: .86rem; }
.tableau--nu th, .tableau--nu td { padding: 9px 0; white-space: normal; }
.tableau--nu thead th { background: transparent; padding-top: 0; }

/* Aucune marge horizontale : c'est ce qui donne a ce tableau son alignement
   franc sur le bord du bloc. Mais rien ne separait deux colonnes voisines, et
   la quatrieme — les actions — a colle « AGE » a « CODE ». La marge se pose
   donc ENTRE les colonnes, jamais sur les bords. */
.tableau--nu th + th,
.tableau--nu td + td { padding-left: 14px; }

/* Une mesure ne se coupe pas en deux : « 17 ans » tient sur une ligne, meme
   dans une colonne reduite a son minimum. */
.tableau--nu .colonne-etroite { white-space: nowrap; }

/* ---------- Blocs empiles et zone dangereuse --------------------------- */

.colonnes > div {
    display: grid;
    gap: 20px;
    align-content: start;
    min-width: 0;
}

.bloc__intro {
    margin: -8px 0 18px;
    font-size: .86rem;
    color: var(--encre-douce);
}

.bloc--danger { border-color: #fecaca; }
.bloc--danger .bloc__titre { color: var(--erreur); }

.bouton--contour {
    background: transparent;
    border-color: #fecaca;
}

.bouton--desactive {
    opacity: .45;
    cursor: not-allowed;
    background: transparent;
    border-color: var(--bordure);
    color: var(--encre-tres-douce);
}

.champ select:disabled,
.champ--case input:disabled {
    opacity: .6;
    cursor: not-allowed;
    background: var(--fond);
}

/* ---------- Sections solos / groupes ----------------------------------- */

.section-liste { margin-bottom: 34px; }

.section-liste__titre {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 14px;
    font-size: 1.05rem;
    letter-spacing: -.01em;
}

.section-liste__compte {
    display: inline-grid;
    place-items: center;
    min-width: 24px;
    height: 24px;
    padding: 0 7px;
    border-radius: 999px;
    background: var(--accent-clair);
    color: var(--accent-fonce);
    font-size: .76rem;
    font-weight: 700;
}

.section-liste .note { margin-top: 0; }

/* ---------- Blocs par categorie ---------------------------------------- */

.categories-engagees {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.bloc-categorie {
    background: var(--surface);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    /* Le bandeau de titre est teinte : il doit epouser les coins arrondis. */
    overflow: hidden;
}

.bloc-categorie__tete {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 12px 20px;
    background: var(--accent-clair);
    border-bottom: 1px solid #dfe4fb;
    cursor: pointer;
    user-select: none;
    /* Le marqueur natif de <summary> laisse la place a notre chevron. */
    list-style: none;
}

.bloc-categorie__tete::-webkit-details-marker { display: none; }
.bloc-categorie__tete::marker { content: ''; }

.bloc-categorie__tete:hover { background: #e6ebff; }

.bloc-categorie__tete:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}

.bloc-categorie__intitule { flex: 1; min-width: 0; }

.bloc-categorie__chevron {
    flex: 0 0 16px;
    display: grid;
    place-items: center;
    width: 16px;
    height: 16px;
    color: var(--accent-fonce);
    transition: transform .15s ease;
}

.bloc-categorie__chevron svg { width: 15px; height: 15px; }

.bloc-categorie[open] > .bloc-categorie__tete > .bloc-categorie__chevron {
    transform: rotate(90deg);
}

/* Replie, le bandeau n'a plus de contenu sous lui : son filet n'a plus lieu d'etre. */
.bloc-categorie:not([open]) .bloc-categorie__tete { border-bottom: 0; }

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

.bloc-categorie__titre {
    display: block;
    font-size: 1.02rem;
    color: var(--accent-fonce);
    letter-spacing: -.01em;
}

.bloc-categorie__meta {
    display: block;
    margin: 3px 0 0;
    font-size: .82rem;
    color: var(--encre-douce);
}

.engagement-ligne {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 18px;
    padding: 12px 20px;
}

/* Seules les lignes suivantes portent un filet : la premiere s'appuie sur la
   bordure basse du bandeau de titre. */
.engagement-ligne + .engagement-ligne {
    border-top: 1px solid var(--bordure);
}

.engagement-ligne__actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
    padding-top: 4px;
}

.engagement-ligne__actions form { margin: 0; }

.composition {
    flex: 1;
    min-width: 0;
    margin: 0;
    padding: 0;
    list-style: none;
}

.composition li {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 10px;
    padding: 5px 0;
    font-size: .9rem;
    font-weight: 600;
}

.composition .discret {
    font-size: .78rem;
    font-weight: 400;
}

@media (max-width: 620px) {
    .engagement-ligne { flex-direction: column; gap: 8px; }
    .engagement-ligne__actions { padding-top: 0; }
}

/* ---------- Choix des athletes ------------------------------------------ */

.champ__intitule {
    display: block;
    margin-bottom: 6px;
    font-size: .87rem;
    font-weight: 600;
    color: var(--encre);
}

.choix-athletes {
    margin: 10px 0 0;
    padding: 0;
    list-style: none;
    max-height: 330px;
    overflow-y: auto;
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-petit);
}

.choix-athletes li + li { border-top: 1px solid var(--bordure); }

.choix-athletes__item {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: 4px 11px;
    margin: 0;
    padding: 10px 13px;
    cursor: pointer;
    font-weight: 400;
}

.choix-athletes__item:hover { background: var(--fond); }

.choix-athletes__item input {
    grid-row: span 2;
    width: auto;
    margin: 0;
}

.choix-athletes__nom { font-size: .9rem; font-weight: 600; }

.choix-athletes__detail {
    grid-column: 2;
    font-size: .78rem;
    color: var(--encre-tres-douce);
}

.champ--erreur .choix-athletes { border-color: var(--erreur); }

/* ---------- Listes deroulantes groupees --------------------------------- */

.champ optgroup {
    font-weight: 700;
    font-style: normal;
    color: var(--encre-tres-douce);
}

.champ optgroup option { font-weight: 400; color: var(--encre); }


/* ---------- Musique de prestation --------------------------------------- */

/* Une prestation = une ligne, un lien, deux pastilles d'etat.
   Avant, chaque prestation offrait trois ou quatre elements cliquables qui
   menaient tous a la meme page : le nom, la musique, la fiche, le volet de
   depot. La ligne entiere est maintenant la cible, et les pastilles ne font
   que dire ou l'on en est. */
.prestation-ligne {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px 12px;
    padding: 7px 10px;
    margin: 0 -10px;
    border-radius: var(--rayon-petit);
    color: var(--encre);
    text-decoration: none;
}

a.prestation-ligne:hover { background: var(--fond); }
a.prestation-ligne:hover .prestation-ligne__nom { color: var(--accent); }

/* La composition d'un groupe se lit, elle ne se clique pas : ses athletes
   n'ont pas de prestation a eux. */
.prestation-ligne--inerte { cursor: default; }

.prestation-ligne__corps { flex: 1; min-width: 0; }

.prestation-ligne__nom {
    display: block;
    font-size: .95rem;
    font-weight: 600;
}

.prestation-ligne__detail {
    display: block;
    margin-top: 1px;
    font-size: .8rem;
    font-weight: 400;
    color: var(--encre-douce);
    word-break: break-word;
}

/* Les etats restent groupes a droite, et passent sous le nom quand la place
   manque. */
.prestation-ligne__etats {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
}

.prestation {
    color: var(--encre);
    text-decoration: none;
    border-bottom: 1px dashed var(--encre-tres-douce);
}

.prestation:hover {
    color: var(--accent);
    border-bottom-color: var(--accent);
}


.lecteur {
    width: 100%;
    margin-top: 14px;
}

.champ input[type="file"] {
    padding: 9px 11px;
    background: var(--fond);
    font-size: .88rem;
}

.champ input[type="file"]::file-selector-button {
    margin-right: 12px;
    padding: 6px 13px;
    border: 1px solid var(--bordure);
    border-radius: 6px;
    background: var(--surface);
    color: var(--encre-douce);
    font: inherit;
    font-size: .85rem;
    font-weight: 600;
    cursor: pointer;
}

.champ input[type="file"]::file-selector-button:hover {
    background: var(--fond);
    color: var(--encre);
}

/* ---------- Formation (engagement de groupe) ---------------------------- */

.formation {
    flex: 1;
    min-width: 0;
}

.formation__club {
    margin: 0;
    font-size: .95rem;
}

.formation__athletes {
    margin: 2px 0 0;
    font-size: .9rem;
    color: var(--encre);
    word-break: break-word;
}

.formation__musique {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin: 9px 0 0;
    padding-top: 9px;
    border-top: 1px dashed var(--bordure);
    font-size: .86rem;
}

/* ---------- Choix de la federation -------------------------------------- */

/* Le filtre vient avant le choix de la vue : il porte donc un intitule, que
   les deux autres n'ont pas. Sans lui, trois boitiers se suivraient sans qu'on
   sache lequel repond a quelle question. */
/* Un conteneur de niveau bloc : sans lui, les boitiers etant en ligne, le
   choix de la vue viendrait se ranger a cote du filtre comme s'ils etaient de
   meme rang. Ils ne le sont pas — le filtre decide de ce que la vue montrera. */
.barre-filtres { margin-bottom: 12px; }

.filtres--federations {
    align-items: center;
    gap: 2px;
}

.filtres__intitule {
    padding: 6px 12px 6px 10px;
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--encre-tres-douce);
}

/* ---------- Glisser-deposer des lignes ---------------------------------- */

/* La main s'affiche sur la cellule du nom, pas sur toute la ligne : les
   commandes de droite restent des commandes, et ne promettent pas un
   deplacement qu'elles refusent. */
[data-glissable] tbody tr[draggable="true"] .cellule-prestation { cursor: grab; }
[data-glissable] tbody tr[draggable="true"]:active .cellule-prestation { cursor: grabbing; }

/* La ligne emportee s'efface : on suit le trait, pas elle. */
.ligne--glissee { opacity: .4; }

/* Ou elle se posera. Un filet, et non un fond : un fond entrerait en conflit
   avec les teintes des lignes libres et avec le suivi en direct, qui peignent
   deja la rangee. */
.ligne--cible-haut td { box-shadow: inset 0 3px 0 var(--accent); }
.ligne--cible-bas  td { box-shadow: inset 0 -3px 0 var(--accent); }

/* ---------- Repos insuffisant entre deux passages ------------------------ */

/* Le nom de l'athlete qui enchaine trop vite, et lui seul : dans un groupe,
   peindre toute la formation obligerait a chercher lequel des cinq. Le rouge
   est celui des alertes du site ; il porte un soulignement ondule pour que le
   signal ne repose pas sur la seule couleur. */
.athlete-presse {
    color: var(--erreur);
    text-decoration: underline wavy var(--erreur) 1px;
    text-underline-offset: 3px;
}

/* La marque sur la ligne : assez visible pour accrocher l'oeil qui parcourt la
   colonne, assez discrete pour ne pas concurrencer le nom. */
.marque-repos {
    margin-left: 6px;
    color: var(--erreur);
    font-size: .95em;
    cursor: help;
}

/* ---------- Onglets d'une journee --------------------------------------- */

/* Meme boitier que les autres filtres : ce sont les memes gestes, et l'ecran
   n'a pas besoin d'un troisieme vocabulaire pour dire « choisissez une vue ». */
.filtres--onglets { margin-bottom: 18px; }

/* Les deux panneaux d'ajout se partagent la largeur a parts egales : ils font
   le meme travail sur deux categories, en donner plus a l'un suggererait une
   hierarchie qui n'existe pas. */
@media (min-width: 900px) {
    .colonnes--paire { grid-template-columns: 1fr 1fr; }
}

/* ---------- Choix de saison --------------------------------------------- */

.filtres--saisons {
    margin-bottom: 18px;
}

/* ---------- Actions groupees en tete de page ---------------------------- */

.entete-page__actions {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

/* Le bouton d'archive vit dans le <summary> : il ne doit pas s'etirer. */
.bloc-categorie__tete .bouton { flex: 0 0 auto; }

/* ---------- Colonne d'actions toujours atteignable ---------------------- */

/* Les boutons d'action s'empilent SI LA BOITE EST ETROITE, au lieu d'elargir
   le tableau. C'est la colonne la plus large de toutes — 334 px a elle seule
   dans la liste des comptes, contre 161 une fois empilee — et la laisser
   pousser, c'etait forcer un debordement, donc laisser la colonne epinglee
   ci-dessous recouvrir la precedente.

   La mesure porte sur la BOITE, pas sur la fenetre : c'est elle qui donne la
   place reelle, une fois la colonne laterale deduite. Une requete de fenetre
   se tromperait des que le menu change de largeur. Le conteneur n'est declare
   que la ou la question se pose — un tableau sans colonne d'actions n'a rien a
   empiler — ce qui laisse hors de cause l'organigramme et son debordement
   visible, regles plus bas.

   Chaque bouton, lui, garde son libelle d'un seul tenant. */
.tableau-boite:has(.colonne-actions) {
    container-type: inline-size;
    container-name: tableau;
}

@container tableau (max-width: 1000px) {
    .tableau td.colonne-actions { white-space: normal; }
    .tableau td.colonne-actions .bouton { white-space: nowrap; }
}

/* Un tableau large finit par deborder : sans cela, les boutons d'action
   partent hors ecran derriere la barre de defilement et passent inapercus. */
.tableau td.colonne-actions,
.tableau thead th:last-child {
    position: sticky;
    right: 0;
    z-index: 1;
    background: var(--surface);
    box-shadow: -10px 0 10px -10px rgba(15, 23, 42, .22);
}

.tableau thead th:last-child { background: #fbfcfe; }
.tableau tbody tr:hover td.colonne-actions { background: #fbfcfe; }
.tableau tbody tr.ligne--pause td.colonne-actions { background: #fcfcfd; }

.colonne-actions .bouton,
.colonne-actions form { vertical-align: middle; }

/* ---------- Inscriptions en attente ------------------------------------- */

.alerte--alerte {
    background: #fff7ed;
    border-color: #fed7aa;
    color: #b45309;
}

.stat--alerte {
    border-color: #fed7aa;
    background: #fffbf5;
}

.stat--alerte .stat__valeur { color: #b45309; }

.ligne--attente { background: #fffbf5; }

.lateral__pastille {
    margin-left: auto;
    display: inline-grid;
    place-items: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 999px;
    background: #b45309;
    color: #fff;
    font-size: .72rem;
    font-weight: 700;
}

/* Numero de club, place devant le nom plutot que dans une colonne : le tableau
   tenait sinon plus large que son cadre, et la colonne d'actions epinglee a
   droite recouvrait la precedente. Chasse fixe pour que les numeros s'alignent
   d'une ligne a l'autre, gris pour rester derriere le nom du club. */
.numero-club {
    margin-right: 8px;
    color: var(--encre-tres-douce);
    font-variant-numeric: tabular-nums;
    letter-spacing: .06em;
    font-size: .85rem;
}

/* Numero de licence pas encore attribue : la valeur est une prevision, pas un
   fait. Le trait plus pale la distingue d'un numero deja porte par l'athlete. */
.champ__fige--attente {
    color: var(--encre-tres-douce);
    font-weight: 500;
}

/* --- Import d'un effectif ------------------------------------------------ */

/* Bilan de l'analyse : quatre nombres, lisibles d'un coup d'oeil. */
.resume-import {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 24px;
    margin: 0 0 18px;
    padding: 14px 16px;
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-petit);
    background: var(--fond);
    list-style: none;
    font-size: .9rem;
}
.resume-import strong {
    font-variant-numeric: tabular-nums;
    font-size: 1.05rem;
}

/* Exemple de fichier : chasse fixe, pour que les colonnes s'alignent. */
.exemple-csv {
    margin: 10px 0;
    padding: 12px 14px;
    overflow-x: auto;
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-petit);
    background: var(--surface);
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: .82rem;
    line-height: 1.5;
    white-space: pre;
}

/* Case a cocher accompagnee de son libelle, dans une cellule de tableau. */
.etiquette-case {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    font-size: .85rem;
    cursor: pointer;
}
.etiquette-case input { margin-top: 2px; }

/* Les lignes en erreur sont ecartees : le fond le dit sans crier. */
.ligne--import-erreur { background: #fdf7f7; }
.ligne--import-erreur td { color: var(--encre-douce); }
.ligne--import-identique { background: #fcfcfd; }

/* --- Organigramme -------------------------------------------------------- */

/* Une ligne libre n'est pas un passage : pas de rang, une typographie a part,
   et un fond choisi ligne par ligne. Le fond est pose en style en ligne depuis
   la palette de app/journees.php — c'est une donnee, pas une classe fixe. */
.ligne--libre strong { letter-spacing: .04em; text-transform: uppercase; font-size: .85rem; }

/* Choix de teinte dans la colonne d'actions : discret, il ne doit pas peser
   autant que les boutons a cote. */
.choix-teinte {
    padding: 4px 6px;
    border: 1px solid var(--bordure);
    border-radius: 6px;
    background: var(--surface);
    color: var(--encre-douce);
    font: inherit;
    font-size: .78rem;
    vertical-align: middle;
    cursor: pointer;
}

/* Les prestations du club qui consulte : c'est ce qu'il vient chercher dans un
   organigramme de cinquante lignes. */
.ligne--sienne { background: #f5f8ff; }

/* Chasse fixe : les heures d'une colonne doivent s'aligner d'une ligne a
   l'autre, sinon la lecture verticale devient penible. */
.heure-organigramme {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    font-size: .85rem;
}

/* Un organigramme doit tenir dans la page : sept colonnes, dont quatre
   d'horaires, debordaient de 59 px et imposaient un ascenseur horizontal.
   Marges resserrees et en-tetes autorises a passer a la ligne. */
/* Largeurs IMPOSEES, et non deduites du contenu.
   Firefox ne reduit pas une colonne de tableau sur les coupures proposees par
   <wbr> : mesure faite, un groupe de cinq athletes lui donnait 633 px et
   poussait le tableau 178 px hors du cadre, la ou Chromium tombait a 0.
   Avec table-layout: fixed, le moteur n'arbitre plus — il applique. Les
   colonnes horaires et la colonne d'actions ont une largeur fixe, la colonne
   des prestations prend ce qui reste et son texte s'y replie. */
.tableau--organigramme { table-layout: fixed; }

/* Sur un telephone, la largeur de l'ecran ne suffit pas aux colonnes
   horaires : sans plancher, la colonne des prestations tombait a zero et les
   noms s'ecrivaient lettre par lettre. Le tableau garde donc une largeur
   minimale — 14 rem pour les prestations, plus le rang, plus ses colonnes
   d'heures — et le cadre defile horizontalement. --colonnes-heure est pose
   par la page.

   LA COLONNE DE QUEUE ENTRE DANS LE COMPTE, et c'est ce qui manquait. Trois
   pages se servent de ce tableau : l'ordre de passage d'un club n'a rien
   apres les heures, la fiche d'une journee y ajoute 12 rem d'actions, la
   console 14 rem de boutons d'etat. Ces deux-la depassaient donc le plancher
   sans l'atteindre : le moteur, qui doit bien loger les colonnes fixes,
   prenait la place sur les prestations. Mesure dans un cadre de 660 px : la
   colonne tombait a 76 px, et « LEFEVRE Marie » s'ecrivait « LEFEVR / E
   Marie ».

   La queue se reconnait a son <col> plutot que de se declarer page par page :
   une page qui reutilise ce tableau demain ne peut pas oublier de le dire. */
.tableau--organigramme { min-width: calc(16.5rem + var(--colonnes-heure, 4) * 5.5rem + var(--colonne-queue, 0rem)); }
.tableau--organigramme:has(.col-actions) { --colonne-queue: 12rem; }
.tableau--organigramme:has(.col-suivi)   { --colonne-queue: 14rem; }

.tableau--organigramme .col-rang    { width: 2.5rem; }
.tableau--organigramme .col-heure   { width: 5.5rem; }
.tableau--organigramme .col-actions { width: 12rem; }
/* .col-prestation ne porte aucune largeur : elle recueille le reste. */

.tableau--organigramme th,
.tableau--organigramme td { padding: 9px 10px; }

.tableau--organigramme thead th {
    white-space: normal;
    line-height: 1.25;
    font-size: .72rem;
}

/* Les cellules d'heures n'ont pas a s'elargir : leur contenu fait huit
   caracteres et ne varie jamais. */
.tableau--organigramme .heure-organigramme { width: 1%; }

/* Colonne d'actions resserree : les trois commandes tiennent sur une ligne. */
.tableau--organigramme .colonne-actions .bouton--petit { padding: 4px 8px; }

/* Filet de securite : un nom qui n'offre aucune coupure — cinq athletes separes
   par des barres, ou un patronyme a rallonge — dilaterait la colonne jusqu'a
   pousser les horaires hors du cadre. Les <wbr> poses apres les barres suffisent
   d'ordinaire ; ceci rattrape le reste. */
/* Colonne des prestations : c'est ICI que se jouait tout le probleme.
   `.tableau th, .tableau td` impose white-space: nowrap a toutes les cellules.
   Aucune coupure n'etait donc possible — ce qui explique que overflow-wrap et
   word-break soient restes sans le moindre effet. Chromium honorait tout de
   meme les <wbr>, Firefox non : d'ou un rendu correct chez l'un et un
   debordement de 178 px chez l'autre, sur la meme page.
   Il faut rendre le retour a la ligne possible, et lui donner de bons points
   de coupure : les <wbr> poses par libelle_secable(). */
/* `.tableau td` seul : la classe nue (0,1,0) perdait contre `.tableau td`
   (0,1,1), et seul le nth-child de l'organigramme faisait replier. Mesure : la
   cellule restait en nowrap partout ailleurs. */
.tableau td.cellule-prestation,
.tableau--organigramme tbody td:nth-child(2) {
    white-space: normal;
    overflow-wrap: anywhere;
}

/* Une cellule de texte libre (un libelle et sa ligne de details) : elle se
   replie aux espaces plutot que de filer sous la colonne d'actions epinglee,
   ou elle devenait illisible. La largeur minimale evite l'exces inverse — sans
   elle, le moteur reduit la colonne mot a mot des que le tableau est a l'etroit. */
.tableau td.cellule-texte {
    white-space: normal;
    overflow-wrap: break-word;
    min-width: 15rem;
}
.tableau td.cellule-texte .cellule-secondaire { white-space: normal; }

/* Derniere colonne horaire : c'est l'heure de passage sur le podium, celle
   qu'on cherche en priorite. Les colonnes d'echauffement la preparent. */
.heure-organigramme--passage {
    font-weight: 700;
    color: var(--encre);
}
thead .heure-organigramme--passage { font-weight: 700; }

/* Forfait : la ligne reste a sa place, barree et en rouge. La retirer ferait
   croire a une erreur d'impression a qui compare avec l'ordre affiche. */
.ligne--forfait td { color: var(--erreur); text-decoration: line-through; }
.ligne--forfait .cellule-secondaire,
.ligne--forfait .discret { color: var(--erreur); opacity: .75; }
/* Les commandes, elles, restent lisibles : il faut pouvoir lever le forfait. */
.ligne--forfait .colonne-actions { text-decoration: none; }
.ligne--forfait .colonne-actions .bouton { text-decoration: none; }

/* --- Suivi en direct ----------------------------------------------------- */

/* Une ligne close s'efface du regard : en fin de journée, ce qui reste coloré
   est ce qui reste à faire. */
.ligne--close td { color: var(--encre-douce); }

.etat-badge:empty { display: none; }

.etat-badge {
    display: inline-block;
    margin-top: .2rem;
    padding: .1rem .45rem;
    border-radius: 999px;
    background: rgba(0, 0, 0, .07);
    font-size: .74rem;
    font-weight: 600;
    letter-spacing: .01em;
}

.legende-suivi {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .4rem;
    margin: .6rem 0 .9rem;
    font-size: .82rem;
}

.legende-suivi__intitule { color: var(--encre-douce); }

.legende-suivi__item {
    padding: .15rem .5rem;
    border-radius: 4px;
    font-weight: 600;
}

/* L'état du lien réseau. Discret tant que tout va bien : il ne devient visible
   que lorsqu'il a quelque chose de désagréable à annoncer. */
.legende-suivi__reseau,
.lien-reseau {
    padding: .15rem .55rem;
    border-radius: 999px;
    font-size: .78rem;
    font-weight: 600;
}

.legende-suivi__reseau[data-etat="ok"],
.lien-reseau[data-etat="ok"] {
    background: #dcfce7;
    color: #166534;
}

.legende-suivi__reseau[data-etat="ko"],
.lien-reseau[data-etat="ko"] {
    background: #fee2e2;
    color: #991b1b;
}

/* --- La console de l'opérateur ------------------------------------------- */

/* La console montre le MEME tableau que l'ordre de passage des clubs, plus une
   colonne de boutons : l'operateur voit ce que voit la salle, et n'a pas a
   traduire d'un ecran a l'autre. Ne reste donc ici que ce qui lui est propre —
   la colonne de suivi, les etats d'envoi, et le filtre des passages termines. */

/* Pas de plancher propre ici : celui de .tableau--organigramme compte deja la
   colonne de queue. Le sien ne reservait que 7,5 rem aux prestations, et les
   noms s'y ecrivaient lettre par lettre comme dans la fiche d'une journee. */
.tableau--organigramme .col-suivi { width: 14rem; }

/* `.tableau td` impose nowrap a toutes les cellules : la classe nue (0,1,0)
   perdait contre lui (0,1,1), et les boutons debordaient de leur colonne au
   lieu de s'y empiler. Meme piege que pour la colonne des prestations, plus
   haut — il valait la peine d'etre ecrit deux fois. */
.tableau td.colonne-suivi {
    white-space: normal;
    text-align: right;
}

.console__bouton {
    margin: 2px 0 2px 4px;
    padding: 7px 12px;
}

/* Masquer les passages termines : le plateau avance, l'ecran se vide par le
   haut. C'est la premiere demande d'un operateur apres une heure de journee. */
.console--sans-termines tbody tr.ligne--close { display: none; }

/* L'envoi en cours, et l'echec. Dans une salle au reseau incertain, un clic
   parti dans le vide sans que personne ne le voie est pire que pas de suivi. */
.ligne--envoi { opacity: .55; }

.ligne--echec > td { background: #fef2f2; }
.ligne--echec > td:first-child { box-shadow: inset 4px 0 0 var(--erreur); }

}

/* --- Couleur libre des lignes libres -------------------------------------- */

/* Sur un fond sombre, la couleur du texte est posée en ligne par le serveur ;
   les textes secondaires, qui ont leur propre gris, doivent suivre. */
.ligne--sombre .cellule-secondaire,
.ligne--sombre .numero-club,
.ligne--sombre .heure-organigramme { color: inherit; opacity: .85; }

input[type="color"].choix-teinte {
    width: 2.6rem;
    height: 1.9rem;
    padding: 2px;
    cursor: pointer;
}

input[type="color"].choix-teinte--large {
    width: 5rem;
    height: 2.4rem;
}

/* --- Logo du club --------------------------------------------------------- */

.logo-club {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 2rem;
    height: 2rem;
    border-radius: 6px;
    object-fit: contain;
    background: var(--surface);
    border: 1px solid var(--bordure);
    vertical-align: middle;
}

/* Sans logo, deux initiales : la place est prise, la liste ne saute pas. */
.logo-club--vide {
    font-size: .7rem;
    font-weight: 700;
    letter-spacing: .02em;
    color: var(--encre-douce);
    background: var(--accent-clair);
    border-color: transparent;
}

.logo-club--petit { width: 1.6rem; height: 1.6rem; margin-right: .35rem; font-size: .6rem; }
.logo-club--barre { width: 1.5rem; height: 1.5rem; margin-right: .4rem; font-size: .58rem; }
.logo-club--titre { width: 2.6rem; height: 2.6rem; margin-right: .6rem; font-size: .9rem; }
.logo-club--grand { width: 7rem; height: 7rem; border-radius: 12px; font-size: 2rem; }

.barre__club { display: inline-flex; align-items: center; min-width: 0; }

.entete-page__titre--logo { display: flex; align-items: center; flex-wrap: wrap; gap: .3rem; }

.logo-bloc {
    display: flex;
    gap: 1.25rem;
    align-items: flex-start;
    flex-wrap: wrap;
}

.logo-bloc__actions { flex: 1 1 14rem; }

/* --- Téléphone avec indicatif --------------------------------------------- */

.telephone {
    display: flex;
    gap: .5rem;
}

.telephone__indicatif { flex: 0 1 13rem; min-width: 0; }
.telephone__numero    { flex: 1 1 8rem; min-width: 0; }

@media (max-width: 640px) {
    .telephone { flex-direction: column; }
    .telephone__indicatif { flex-basis: auto; }
}

/* L'indicatif choisi s'affiche en tete du numero, dans le meme cadre. */
.telephone__saisie {
    flex: 1 1 8rem;
    min-width: 0;
    display: flex;
    align-items: stretch;
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-petit);
    background: var(--surface);
}

.telephone__saisie:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-clair);
}

.telephone__prefixe {
    display: flex;
    align-items: center;
    padding: 0 .55rem 0 .7rem;
    color: var(--encre-douce);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    border-right: 1px solid var(--bordure);
}

.telephone__prefixe[hidden] { display: none; }

.telephone__saisie .telephone__numero {
    flex: 1 1 auto;
    border: 0;
    box-shadow: none;
    background: transparent;
    min-width: 0;
}

/* Le logo en tete du tableau de bord, a droite du nom du club. */
.accueil--avec-logo {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1.5rem;
}

.accueil__logo { flex: none; }

.logo-club--accueil {
    width: 6.5rem;
    height: 6.5rem;
    border-radius: 14px;
    box-shadow: var(--ombre);
}

.accueil__logo--vide {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 6.5rem;
    height: 6.5rem;
    border: 2px dashed var(--bordure);
    border-radius: 14px;
    font-size: .78rem;
    font-weight: 600;
    text-align: center;
    color: var(--encre-douce);
    text-decoration: none;
}

.accueil__logo--vide:hover { border-color: var(--accent); color: var(--accent); }

@media (max-width: 640px) {
    .logo-club--accueil, .accueil__logo--vide { width: 4.5rem; height: 4.5rem; }
}

/* Un groupe du menu : intitule non cliquable, entrees en retrait dessous. */
.lateral__item--groupe {
    cursor: default;
    color: var(--lateral-encre);
}
.lateral__item--groupe:hover { background: transparent; color: var(--lateral-encre); }
.lateral__item--ouvert { color: #fff; font-weight: 600; }

.lateral__item--sous {
    padding-left: 41px;
    padding-top: 7px;
    padding-bottom: 7px;
    font-size: .88rem;
}

/* Athlete non admis dans la categorie choisie : present mais grise, pour que
   le club comprenne pourquoi il ne peut pas le cocher. */
.choix-athletes__item--exclu .choix-athletes__item { opacity: .45; cursor: not-allowed; }


/* --- Organigramme previsionnel ------------------------------------------- */

/* Publier et arreter sont deux decisions, et le club ne pouvait pas faire la
   difference : une grille mise en ligne se lisait comme une grille arretee, on
   reservait le train dessus, puis un horaire bougeait. D'ou un bandeau franc
   plutot qu'une note en bas de page.

   L'ambre deja en service dans l'interface (« etiquette--alerte »,
   « alerte--alerte »), mais avec un sceau plein : c'est lui qu'on voit avant
   d'avoir lu la phrase. */
.bandeau-previsionnel {
    /* Dans la grille imprimee, « .programme » est une colonne flex : le
       bandeau y est un item a taille propre, et le corps recoit le reste. */
    flex: 0 0 auto;
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 12px;
    margin: 0 0 14px;
    padding: 12px 16px;
    background: #fffbeb;
    border: 1px solid #fcd34d;
    border-left: 5px solid #d97706;
    border-radius: var(--rayon);
    color: #7c3c04;
}

.bandeau-previsionnel__sceau {
    flex: 0 0 auto;
    margin: 0;
    padding: 4px 10px;
    border-radius: 4px;
    background: #b45309;
    color: #fff;
    font-size: .72rem;
    font-weight: 800;
    letter-spacing: .09em;
    text-transform: uppercase;
}

/* 18 rem de base : en dessous, la phrase passe sous le sceau plutot que de se
   couper en colonne d'un mot. */
.bandeau-previsionnel__texte {
    flex: 1 1 18rem;
    margin: 0;
    font-size: .92rem;
    line-height: 1.5;
}

.bandeau-previsionnel__texte strong { color: #7c2d12; }

/* « .tableau th, .tableau td » interdit le retour a la ligne, ce qui va bien
   a une cellule d'un mot. La colonne « Visibilite » en porte deux depuis que
   « Previsionnel » existe, et la seconde disparaissait sous la colonne
   d'actions collee au bord droit. Ici, et ici seulement, elles se rangent
   l'une sous l'autre quand la place manque. */
.cellule-visibilite { white-space: normal; }
.cellule-visibilite .etiquette { display: block; width: fit-content; margin: 2px 0; }

.etiquette--previsionnel {
    background: #fffbeb;
    border-color: #fcd34d;
    color: #b45309;
}

/* Meme traitement que sur le titre d'une page : l'etiquette se pose sur la
   ligne du titre sans en changer la hauteur. */
.section-liste__titre .etiquette { vertical-align: middle; margin-left: 8px; font-size: .7rem; }

/* La marque dans l'onglet d'une journee : savoir laquelle bougera encore avant
   de l'ouvrir. Le boitier des onglets ne se replie pas (« inline-flex » sans
   retour a la ligne) : sous 700 px, la marque s'efface plutot que de le pousser
   hors de l'ecran — le bandeau de la journee ouverte dit la meme chose, en
   plus grand. */
.filtres__marque {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    border: 1px solid #fcd34d;
    border-radius: 999px;
    background: #fffbeb;
    color: #b45309;
    font-size: .68rem;
    font-weight: 700;
    vertical-align: 1px;
}

@media (max-width: 700px) {
    .filtres__marque { display: none; }
}

/* --- Organigramme de l'evenement ----------------------------------------- */

.programme__banniere {
    background: var(--accent);
    color: #fff;
    border-radius: var(--rayon);
    padding: 1.25rem 1.5rem;
    margin-bottom: 1rem;
    text-align: center;
}

.programme__titre { margin: 0; font-size: 2rem; font-weight: 800; letter-spacing: -.01em; }
.programme__sous-titre { margin: .2rem 0 0; opacity: .9; font-size: .95rem; }

/* La grille : une regle des heures a gauche (4 rem), puis une colonne par
   jour. En-tetes et corps partagent la meme definition de colonnes pour rester
   alignes. Les positions sont donnees en minutes par le serveur (--debut,
   --duree, --minute) et exprimees en pourcentage de la hauteur du corps :
   seule celle-ci fixe l'echelle. A l'ecran, un pixel et demi par minute (une
   journee de 8:00 a 22:00 fait 1 260 px, ca defile, mais une demi-heure reste
   un vrai rectangle) ; sur papier, ce qui reste de la page. */

.programme__cadre { border: 1px solid var(--bordure); border-radius: var(--rayon); background: var(--surface); overflow: hidden; }

.programme__entetes,
.programme__corps {
    display: grid;
    grid-template-columns: 4rem repeat(var(--programme-colonnes, 1), minmax(0, 1fr));
}

.programme__entetes { border-bottom: 1px solid var(--bordure); background: var(--fond); }
.programme__coin { border-right: 1px solid var(--bordure); }

.programme__entete {
    margin: 0;
    padding: .7rem .5rem;
    font-size: 1.05rem;
    font-weight: 700;
    text-align: center;
    border-right: 1px solid var(--bordure);
}
.programme__entete:last-child { border-right: 0; }
.programme__entete--aujourdhui { background: var(--accent-clair); color: var(--accent-fonce); }
.programme__entete .etiquette { margin-left: .35rem; vertical-align: middle; }

.programme__corps {
    position: relative;
    height: calc(var(--programme-minutes) * 1.5px);
    /* Une ligne fine par heure, a travers toutes les colonnes : c'est elle qui
       permet de suivre 14:00 d'un jour a l'autre. */
    background-image: repeating-linear-gradient(
        to bottom,
        var(--bordure) 0, var(--bordure) 1px,
        transparent 1px, transparent calc(100% * 60 / var(--programme-minutes))
    );
}

.programme__regle { position: relative; border-right: 1px solid var(--bordure); background: var(--fond); }

.programme__graduation {
    position: absolute;
    top: calc(var(--minute) * 100% / var(--programme-minutes));
    right: .4rem;
    transform: translateY(-50%);
    font-size: .78rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--encre-douce);
    background: var(--fond);
    padding: 0 .15rem;
}
.programme__graduation:first-child { transform: none; }

.programme__jour {
    position: relative;
    border-right: 1px solid var(--bordure);
    min-width: 0;
}
.programme__jour:last-child { border-right: 0; }
.programme__jour--aujourdhui { background: rgba(79, 70, 229, .04); }

.programme__vide {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    margin: 0; padding: 1rem; text-align: center;
    color: var(--encre-tres-douce); font-size: .85rem;
}

/* Un bloc : place a la hauteur de son horaire, haut comme sa duree, dans sa
   voie si d'autres le chevauchent. Le contenu est rogne plutot que de deborder
   sur le bloc suivant ; le titre complet est dans l'infobulle. */
.programme__bloc {
    position: absolute;
    top: calc(var(--debut) * 100% / var(--programme-minutes));
    height: calc(var(--duree) * 100% / var(--programme-minutes));
    box-sizing: border-box;
    padding: .3rem .5rem .3rem .6rem;
    border-left: 5px solid transparent;
    border-radius: 6px;
    outline: 2px solid var(--surface);
    overflow: hidden;
    overflow-wrap: anywhere;
    line-height: 1.25;
}

.programme__horaire { margin: 0; font-size: .82rem; font-weight: 700; font-variant-numeric: tabular-nums; opacity: .85; }
.programme__libelle { margin: .1rem 0 0; font-weight: 700; font-size: .98rem; }
.programme__libelle a { color: inherit; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 2px; }

/* Une demi-heure ne laisse la place qu'a une ligne : horaire et libelle cote a cote. */
.programme__bloc--court { padding-top: .15rem; padding-bottom: .15rem; }
.programme__bloc--court .programme__horaire { display: inline; margin-right: .4rem; }
.programme__bloc--court .programme__libelle { display: inline; font-size: .9rem; }

/* Cote administration : tout le bloc est cliquable (le lien du libelle est
   etendu au rectangle), et une croix en haut a droite le retire. */
.programme__bloc--editable { cursor: pointer; }
.programme__bloc--editable:hover { filter: brightness(.94); }
.programme__bloc--editable .programme__modifier { color: inherit; text-decoration: none; }
.programme__bloc--editable .programme__modifier::after { content: ''; position: absolute; inset: 0; }
.programme__bloc--editable:hover .programme__modifier { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 2px; }
.programme__bloc--edite { outline: 3px solid var(--accent); z-index: 2; }

.programme__retirer {
    position: absolute; top: 2px; right: 2px; z-index: 1;
    width: 1.3rem; height: 1.3rem; padding: 0;
    border: 0; border-radius: 4px;
    background: rgba(255, 255, 255, .55);
    color: inherit; font: inherit; font-size: 1rem; line-height: 1;
    cursor: pointer; opacity: 0; transition: opacity .12s;
}
.programme__bloc--sombre .programme__retirer { background: rgba(0, 0, 0, .3); }
.programme__bloc--editable:hover .programme__retirer,
.programme__retirer:focus-visible { opacity: 1; }
.programme__retirer:hover { background: var(--erreur); color: #fff; }
.programme__bloc--court .programme__retirer { top: 50%; transform: translateY(-50%); }
.programme__bloc--editable.programme__bloc--court { padding-right: 1.6rem; }

/* Le bloc en cours ressort d'un lisere ; la ligne rouge marque l'heure. */
.programme__bloc--en-cours { outline: 3px solid var(--erreur); z-index: 2; }

.programme__maintenant {
    position: absolute;
    top: calc(var(--minute) * 100% / var(--programme-minutes));
    left: 0; right: 0;
    height: 0;
    border-top: 2px solid var(--erreur);
    z-index: 3;
    pointer-events: none;
}
.programme__maintenant::before {
    content: '';
    position: absolute; left: -5px; top: -5px;
    width: 8px; height: 8px;
    border-radius: 50%;
    background: var(--erreur);
}

/* Sur un ecran etroit, l'echelle ne tient pas : les jours s'empilent, et les
   blocs redeviennent une liste dans l'ordre des heures. (Ecran seulement : une
   page A4 est plus etroite que 900 px et doit garder la grille.) */
@media screen and (max-width: 900px) {
    .programme__entetes { display: none; }
    .programme__corps { display: block; height: auto; background-image: none; }
    .programme__regle { display: none; }
    .programme__jour { border-right: 0; border-bottom: 1px solid var(--bordure); padding: .6rem; }
    .programme__jour::before {
        content: attr(aria-label);
        display: block; font-weight: 700; font-size: 1.05rem; margin-bottom: .5rem;
    }
    /* « relative » et non « static » : la croix de retrait se place par rapport
       a son bloc. Sortie du flux, elle se serait collee en haut de la journee,
       toutes les croix au meme endroit. */
    .programme__bloc {
        position: relative !important;
        top: auto !important;
        left: auto !important;
        width: auto !important;
        height: auto !important;
        margin-bottom: .5rem;
        outline: 0;
    }
    .programme__vide { position: static; }
    .programme__maintenant { display: none; }
}

/* Pleine largeur pour les pages qui le demandent : l'organigramme et ses
   colonnes par jour. */
.coque--large { max-width: none; }
.coque--large .page { padding-left: 32px; padding-right: 32px; }

/* A l'impression : la grille seule, telle qu'a l'ecran, en paysage sur une
   feuille — quelle que soit l'imprimante, ses marges ou la police.
   L'organigramme est sorti du flux (position fixe) et cale sur la zone
   imprimable : le document lui-meme n'a plus de hauteur, donc plus rien ne
   peut engendrer une deuxieme feuille, et si une imprimante rogne davantage
   que prevu, c'est un bord de la grille qui est coupe, pas une page qui
   s'ajoute. Banniere et en-tetes gardent leur taille, le corps recoit le
   reste ; les blocs, places en pourcentage de ce corps, s'y adaptent seuls.
   (L'orientation paysage est demandee par la grille elle-meme, via une regle
   @page dans la page : elle ne doit pas s'appliquer aux autres impressions.) */
@media print {
    .barre, .lateral, .entete-page, .bloc--formulaire, .pied, .alerte, .section-liste,
    .programme__retirer, .programme__maintenant { display: none !important; }
    /* html et body sont ramenes a une hauteur nulle par la page de
       l'organigramme elle-meme (regle dans programme-grille.php) : cette
       feuille est commune, et les autres impressions ont besoin de leur flux. */
    .coque, .page { display: block; margin: 0; padding: 0; max-width: none; }
    .programme {
        position: fixed; top: 0; left: 0;
        width: calc(100% - 2mm); height: calc(100% - 3mm);
        display: flex; flex-direction: column;
        box-sizing: border-box; overflow: hidden;
    }
    .programme__cadre { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; break-inside: avoid; }
    .programme__entetes { flex: 0 0 auto; }
    .programme__corps { flex: 1 1 auto; min-height: 0; height: auto; }
    .programme__banniere { padding: .6rem 1rem; margin-bottom: .5rem; border-radius: 4px; }
    .programme__titre { font-size: 1.4rem; }
    .programme__sous-titre { font-size: .85rem; }
    .programme__entete { padding: .35rem .3rem; font-size: .9rem; }
    .programme__bloc { padding: .12rem .3rem .12rem .4rem; border-left-width: 4px; border-radius: 3px; outline-width: 1px; }
    .programme__bloc--en-cours, .programme__bloc--edite { outline: 1px solid var(--surface); z-index: auto; }
    .programme__horaire { font-size: .68rem; }
    .programme__libelle { font-size: .8rem; margin-top: 0; }
    /* Une demi-heure sur une longue journee ne fait que 4 ou 5 mm : une seule
       ligne serree, sans marge. */
    .programme__bloc--court { padding-top: 0; padding-bottom: 0; line-height: 1.1; }
    .programme__bloc--court .programme__horaire,
    .programme__bloc--court .programme__libelle { font-size: .7rem; }
    .programme__libelle a { text-decoration: none; }
    .programme__graduation { font-size: .68rem; }
    /* Le bandeau part avec la grille sur la feuille : un organigramme punaise
       au mur du vestiaire doit porter la mention, sinon elle ne sert a rien.
       Resserre, parce que chaque millimetre pris ici est pris au corps. */
    .bandeau-previsionnel { margin-bottom: .4rem; padding: .3rem .6rem; gap: 8px; border-left-width: 4px; }
    .bandeau-previsionnel__sceau { padding: 2px 7px; font-size: .62rem; }
    .bandeau-previsionnel__texte { font-size: .72rem; line-height: 1.3; }
    .programme__bloc, .programme__banniere, .programme__entete--aujourdhui, .programme__jour--aujourdhui,
    .programme__regle, .programme__entetes,
    .bandeau-previsionnel, .bandeau-previsionnel__sceau { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* --- Acces public : la page direct.php et l'affiche ----------------------- */

/* Sans menu lateral, la page publique se lit sur un telephone tenu droit :
   la coque n'a plus de colonne a reserver. */
.coque--publique .page { padding-top: 20px; }
.gabarit-public .barre__nav { display: flex; }

/* Le filtre par club, sous la legende du suivi. */
.filtre-club { display: flex; align-items: center; gap: .5rem; margin: 0 0 .8rem; font-size: .92rem; }
.filtre-club select { max-width: 100%; }

/* L'affiche : un aperçu a l'ecran, l'objet reel a l'impression. */
.lien-public { margin: 0 0 .4rem; font-size: 1.1rem; overflow-wrap: anywhere; }

.affiche {
    margin-top: 1.5rem;
    padding: 2rem 1.5rem;
    border: 1px dashed var(--bordure);
    border-radius: var(--rayon);
    background: var(--surface);
    text-align: center;
}
.affiche__sur-titre { margin: 0; font-size: 1.1rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--accent); }
.affiche__titre { margin: .3rem 0 0; font-size: 2.4rem; font-weight: 800; letter-spacing: -.01em; }
.affiche__sous-titre { margin: .2rem 0 0; color: var(--encre-douce); }
.affiche__qr { width: min(60vw, 320px); margin: 1.5rem auto; }
.affiche__qr svg { display: block; width: 100%; height: auto; }
.affiche__consigne { margin: 0; color: var(--encre-douce); }
.affiche__lien { margin: .4rem 0 0; font-size: 1.5rem; font-weight: 800; overflow-wrap: anywhere; }
.affiche__detail { margin: 1.2rem 0 0; font-size: .9rem; color: var(--encre-douce); }

/* A l'impression, l'affiche seule, pleine page, le QR code assez grand pour
   etre lu de loin. (C'est la page admin-public.php qui masque le reste : ses
   regles ne doivent pas toucher les autres impressions.) */
@media print {
    .affiche { border: 0; padding: 0; margin: 0; }
    .affiche__sur-titre { font-size: 1.6rem; margin-top: 10mm; }
    .affiche__titre { font-size: 3.4rem; }
    .affiche__sous-titre { font-size: 1.2rem; }
    .affiche__qr { width: 120mm; margin: 14mm auto; }
    .affiche__consigne { font-size: 1.15rem; }
    .affiche__lien { font-size: 2.2rem; }
    .affiche__detail { font-size: 1.05rem; margin-top: 10mm; }
}

/* --- Choix de la langue -------------------------------------------------- */

/* Deux codes de langue, cote a cote : celui qui est actif est plein, l'autre
   est un lien. Petit, mais present sur chaque page — y compris publiques. */
.langues {
    display: inline-flex;
    gap: 2px;
    margin: 0;
    padding: 2px;
    border-radius: 999px;
    background: var(--fond);
    border: 1px solid var(--bordure);
}

.langues__choix {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: .76rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-decoration: none;
    color: var(--encre-douce);
}
.langues__choix:hover { color: var(--encre); background: var(--surface); }
.langues__choix--actif { background: var(--accent); color: #fff; }
.langues__choix--actif:hover { background: var(--accent); color: #fff; }

/* Le drapeau est dessine : un emoji de drapeau n'est pas rendu sous Windows.
   Le cadre clair le detache aussi bien du fond blanc que du bouton accentue. */
.langues__drapeau {
    width: 17px;
    height: 12px;
    flex: none;
    border-radius: 2px;
    clip-path: inset(0 round 2px);
    box-shadow: 0 0 0 1px rgba(15, 23, 42, .18);
}
.langues__choix--actif .langues__drapeau { box-shadow: 0 0 0 1px rgba(255, 255, 255, .55); }

/* Panneau de connexion : le choix se pose au-dessus du formulaire, aligne a
   droite, et un peu plus grand qu'ailleurs — c'est la premiere page qu'ouvre
   un club etranger, et rien d'autre ne lui dira que l'anglais existe. */
/* Meme largeur que la carte, pour que le choix s'aligne sur son bord droit
   plutot que de flotter au milieu. */
.auth__langues { width: 100%; max-width: 460px; display: flex; justify-content: flex-end; margin-bottom: 18px; }
.auth__langues .langues { padding: 3px; }
.auth__langues .langues__choix { padding: 5px 12px; font-size: .84rem; }
.auth__langues .langues__drapeau { width: 20px; height: 14px; }

@media print { .langues { display: none !important; } }

/* --- L'ordre de passage sur un telephone --------------------------------- */

/* Six colonnes ne tiennent pas dans 375 px : au-dela, c'est du defilement
   horizontal, et personne ne defile pour lire une liste de passage debout
   dans une salle. Chaque rangee devient donc une carte : le rang en pastille,
   le nom en entier, puis les horaires en petites tuiles « colonne / heure »,
   celle du passage en pleine largeur. Le tableau reste un tableau dans le
   code — seule sa mise en page change, et l'impression le retrouve intact. */
@media screen and (max-width: 700px) {
    .tableau--cartes { min-width: 0; }
    .tableau-boite:has(.tableau--cartes) { border: 0; background: transparent; overflow: visible; }

    .tableau--cartes,
    .tableau--cartes tbody { display: block; width: auto; }

    /* L'en-tete n'a plus de colonnes a nommer : chaque tuile porte le sien. */
    .tableau--cartes thead,
    .tableau--cartes colgroup { display: none; }

    /* La carte : une grille de tuiles, qui s'adapte au nombre de colonnes
       horaires de la journee (il est reglable). */
    .tableau--cartes tr {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
        gap: 8px;
        position: relative;
        margin-bottom: 10px;
        padding: 12px 14px 12px 50px;
        border: 1px solid var(--bordure);
        border-radius: var(--rayon);
        background: var(--surface);
        box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
    }

    .tableau--cartes td { display: block; width: auto; border: 0; padding: 0; white-space: normal; }

    /* Le rang : une pastille a gauche, lisible d'un coup d'oeil. */
    .tableau--cartes td[data-role="rang"] {
        position: absolute;
        top: 12px; left: 10px;
        width: 32px;
        text-align: center;
        font-size: 1.2rem;
        font-weight: 800;
        color: var(--encre-douce);
    }

    /* Le nom prend toute la largeur de la carte. */
    .tableau--cartes .cellule-prestation {
        grid-column: 1 / -1;
        font-size: 1rem;
    }
    .tableau--cartes .cellule-secondaire { margin-top: 2px; }

    /* La colonne de suivi de la console traverse la carte, et ses boutons
       prennent toute la largeur : on vise avec un pouce, au bord d'un bassin,
       et un bouton raté fait perdre un passage. */
    .tableau--cartes td.colonne-suivi {
        grid-column: 1 / -1;
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
        margin-top: 4px;
    }

    .tableau--cartes .console__bouton {
        flex: 1 1 100%;
        margin: 0;
        padding: 11px 12px;
    }
    .tableau--cartes .etat-badge { display: inline-block; margin: 4px 0 0; }

    /* Une tuile d'horaire : le nom de la colonne au-dessus, l'heure dessous. */
    .tableau--cartes td.heure-organigramme {
        width: auto;
        min-width: 0;
        padding: 5px 8px;
        border-radius: 8px;
        background: var(--fond);
        text-align: center;
        font-variant-numeric: tabular-nums;
        line-height: 1.2;
    }
    .tableau--cartes td.heure-organigramme::before {
        content: attr(data-colonne);
        display: block;
        margin-bottom: 2px;
        font-size: .6rem;
        font-weight: 700;
        letter-spacing: .05em;
        text-transform: uppercase;
        color: var(--encre-tres-douce);
    }
    .tableau--cartes td.heure-organigramme:empty { display: none; }

    /* L'heure de passage est celle qu'on vient chercher : pleine largeur,
       le nom a gauche, l'heure a droite, en gros. */
    .tableau--cartes td.heure-organigramme--passage {
        grid-column: 1 / -1;
        display: flex;
        align-items: center;
        justify-content: space-between;
        text-align: left;
        font-size: 1.25rem;
        font-weight: 800;
    }
    .tableau--cartes td.heure-organigramme--passage::before { margin: 0; font-size: .66rem; }

    /* Une ligne libre — pause, remise des prix — n'a ni rang ni horaire :
       elle reste une bande, comme sur grand ecran. */
    /* Une ligne libre garde l'alignement qu'elle a sur grand ecran. */
    .tableau--cartes tr.ligne--libre {
        display: block;
        padding: 10px 14px;
    }
    .tableau--cartes tr.ligne--libre .heure-organigramme,
    .tableau--cartes tr.ligne--libre td[data-role="rang"] { display: none; }

    /* Les reperages de l'ecran large valent aussi sur la carte. */
    .tableau--cartes tr.ligne--sienne { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
    .tableau--cartes tr.ligne--close { opacity: .62; }
    .tableau--cartes tr.ligne--courante {
        border-color: var(--accent);
        box-shadow: inset 4px 0 0 var(--accent);
    }
    /* La rangee suivie n'a pas de premiere cellule a border : c'est la carte
       entiere qui porte le filet. */
    .tableau--cartes tr.ligne--courante td:first-child { box-shadow: none; }

    /* La legende et le filtre tiennent dans la largeur du telephone. */
    .legende-suivi { flex-wrap: wrap; gap: .3rem; }
    .filtre-club select { flex: 1; min-width: 0; }
}

/* --- Les listes du club sur un telephone --------------------------------- */

/* Meme constat que pour l'ordre de passage, et meme remede, mais sur des
   colonnes qui ne sont pas des horaires : l'effectif et les juges. Sept
   colonnes font 797 px, la page en offre 341 — le tableau debordait, et la
   colonne d'actions, collee a droite, venait se poser PAR-DESSUS les dates.
   Une presidente de club qui verifie une date de naissance au bord du bassin
   ne pouvait plus la lire.

   Chaque rangee devient donc une carte : le nom en tete, les autres cellules
   en paires « intitule / valeur » — l'intitule vient de data-intitule, pose
   dans le gabarit — et les boutons en bas, cote a cote. Le tableau reste un
   tableau dans le code : l'impression et les lecteurs d'ecran le retrouvent
   intact. */
@media screen and (max-width: 700px) {
    .tableau--liste { min-width: 0; }
    .tableau-boite:has(.tableau--liste) {
        border: 0;
        background: transparent;
        overflow: visible;
    }

    .tableau--liste,
    .tableau--liste tbody { display: block; width: auto; }

    /* Chaque cellule porte son intitule : l'en-tete n'a plus rien a nommer. */
    .tableau--liste thead { display: none; }

    .tableau--liste tr {
        display: block;
        margin-bottom: 10px;
        padding: 12px 14px;
        border: 1px solid var(--bordure);
        border-radius: var(--rayon);
        background: var(--surface);
        box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
    }

    .tableau--liste td {
        display: flex;
        align-items: baseline;
        gap: .6rem;
        width: auto;
        padding: 3px 0;
        border: 0;
        white-space: normal;
    }

    .tableau--liste td::before {
        content: attr(data-intitule);
        flex: 0 0 7.5rem;
        font-size: .72rem;
        font-weight: 700;
        letter-spacing: .06em;
        text-transform: uppercase;
        color: var(--encre-tres-douce);
    }

    /* Le nom tient la tete de la carte, en grand et sans intitule : c'est lui
       qu'on cherche du regard. */
    .tableau--liste td[data-role="titre"] {
        display: block;
        margin-bottom: 6px;
        font-size: 1.05rem;
    }
    .tableau--liste td[data-role="titre"]::before { content: none; }

    /* Les actions reprennent la largeur de la carte, separees du reste. */
    .tableau--liste td.colonne-actions {
        display: flex;
        position: static;
        gap: 8px;
        margin-top: 8px;
        padding-top: 10px;
        border-top: 1px solid var(--bordure);
        background: transparent;
        box-shadow: none;
    }
    .tableau--liste td.colonne-actions::before { content: none; }
    .tableau--liste td.colonne-actions .bouton { flex: 1; text-align: center; }
    .tableau--liste td.colonne-actions form { flex: 1; display: flex; }
    .tableau--liste td.colonne-actions form .bouton { width: 100%; }

    /* Une cellule vide n'a pas d'intitule a montrer. */
    .tableau--liste td:empty { display: none; }
}

/* --- L'en-tete sur un telephone ------------------------------------------ */

/* La barre du haut ne se repliait pas : la pastille du club, le choix de
   langue et « Se deconnecter » tenaient sur une seule ligne, large de 545 px
   dans un ecran de 375. La page entiere defilait donc de 170 px vers la
   droite, et le bouton de deconnexion sortait de l'ecran — introuvable pour
   qui ne pense pas a faire glisser la page.

   Le nom du club passe donc sur sa propre ligne, tronque s'il est long, et
   les commandes se rangent en dessous. */
@media (max-width: 600px) {
    .barre__contenu {
        flex-wrap: wrap;
        gap: 10px;
        padding: 12px 16px;
    }

    .barre__nav {
        width: 100%;
        flex-wrap: wrap;
        justify-content: flex-end;
        gap: 10px;
    }

    /* Le nom du club prend sa propre ligne. Le serrer a cote du choix de
       langue et de « Se deconnecter » le reduisait a « Ae... », et poussait le
       bouton a couper son libelle en deux : trois lignes courtes se lisent
       mieux que deux lignes encombrees. */
    .barre__club {
        flex: 1 1 100%;
        min-width: 0;
    }

    /* « min-width: 0 » en plus de la coupure : sans lui, un element de flex
       refuse de descendre sous la largeur de son contenu, et la pastille
       pousserait encore les commandes dehors. */
    .barre__club__nom {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .marque__texte { font-size: .95rem; }
}

/* --- Suivre le direct ---------------------------------------------------- */

/* Dans un ordre de passage de cent lignes, on perd les intitules de colonnes
   des le premier defilement : l'en-tete reste donc en haut de l'ecran.

   Une condition : aucun ancetre ne doit etre une zone de defilement. Le cadre
   du tableau en est une (« overflow-x: auto »), et un en-tete colle a un cadre
   qui ne defile pas verticalement ne bouge plus du tout. Au-dessus de 900 px,
   le tableau tient dans la page : on lui rend le defilement de la page, et
   l'en-tete suit. En dessous, le cadre reprend ses droits — et sous 700 px il
   n'y a plus de tableau du tout, mais des cartes. */
@media (min-width: 901px) {
    .tableau-boite:has(.tableau--organigramme) { overflow: visible; }

    .tableau--organigramme thead th {
        position: sticky;
        top: 0;
        z-index: 3;
        background: #fbfcfe;
        box-shadow: 0 1px 0 var(--bordure);
    }
}

/* La rangee suivie : un filet a gauche, et un fond a peine pose. On la
   retrouve d'un coup d'oeil apres avoir fait defiler la liste. */
.ligne--courante td:first-child { box-shadow: inset 4px 0 0 var(--accent); }
.ligne--courante { background: #f7f9ff; }

/* Le bouton de retour : il n'apparait que lorsque la rangee suivie a quitte
   l'ecran, et se pose au-dessus du pouce plutot qu'au milieu du texte. */
.aller-courant {
    position: fixed;
    left: 50%;
    bottom: 18px;
    transform: translateX(-50%);
    z-index: 20;
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: 9px 16px;
    border: 0;
    border-radius: 999px;
    background: var(--accent);
    color: #fff;
    font: inherit;
    font-size: .9rem;
    font-weight: 700;
    box-shadow: 0 6px 18px rgba(15, 23, 42, .22);
    cursor: pointer;
}
.aller-courant::after { content: '↓'; font-weight: 400; }
.aller-courant:hover { background: var(--accent-fonce); }
.aller-courant:focus-visible { outline: 3px solid var(--accent-clair); outline-offset: 2px; }

/* « Le tableau tient dans la page » n'est vrai que de l'ordre de passage nu.
   Les deux variantes a colonne de queue en demandent bien davantage : la fiche
   d'une journee ajoute 12 rem d'actions, la console 14 rem de boutons d'etat.
   Entre 901 et 1150 px, elles debordent — et comme le cadre avait renonce a
   defiler, c'est la PAGE qui partait vers la droite, menu lateral compris.

   Dans cette fourchette, le cadre reprend donc son defilement. L'en-tete cesse
   de coller, puisqu'il ne le pourrait plus : c'est le prix, et il est moindre
   qu'un menu qui s'en va. La colonne d'actions, elle, reste epinglee au bord
   du cadre — c'est exactement ce pour quoi elle est collante. */
@media (min-width: 901px) and (max-width: 1149px) {
    .tableau-boite:has(.col-actions),
    .tableau-boite:has(.col-suivi) { overflow-x: auto; }

    .tableau-boite:has(.col-actions) .tableau--organigramme thead th,
    .tableau-boite:has(.col-suivi)   .tableau--organigramme thead th { position: static; }
}

@media print { .aller-courant { display: none !important; } }

/* --- Ecrans tactiles ----------------------------------------------------- */

/* Sans souris, il n'y a pas de survol : une commande qui n'apparait qu'au
   survol n'apparait jamais. Sur tablette, la croix de retrait d'un bloc de
   l'organigramme reste donc visible, et assez grande pour le doigt. */
@media (hover: none), (pointer: coarse) {
    .programme__retirer {
        opacity: 1;
        width: 1.7rem;
        height: 1.7rem;
        font-size: 1.15rem;
        background: rgba(255, 255, 255, .75);
    }
    .programme__bloc--sombre .programme__retirer { background: rgba(0, 0, 0, .35); }
    .programme__bloc--editable.programme__bloc--court { padding-right: 2rem; }
}

/* --- Depot d'un fichier depuis la liste ---------------------------------- */

/* --- Les longues listes gardent leur en-tete ----------------------------- */

/* Passe douze lignes, un tableau se lit en faisant defiler, et les intitules
   de colonnes disparaissent les premiers. Le cadre devient donc sa propre zone
   de defilement, plafonnee a la hauteur de l'ecran : l'en-tete s'y colle. On
   ne touche pas au defilement de la page — arrive en bout de liste, il reprend
   la main tout seul.

   C'est aussi la seule facon de garder la colonne d'actions epinglee a droite :
   elle a besoin, elle, d'une zone de defilement. Les deux cohabitent ici,
   l'une en haut, l'autre a droite. */
@media screen and (min-width: 901px) {
    .tableau-boite--collant {
        max-height: calc(100vh - 150px);
        overflow: auto;
    }

    .tableau-boite--collant .tableau thead th {
        position: sticky;
        top: 0;
        z-index: 3;
        background: #fbfcfe;
        box-shadow: 0 1px 0 var(--bordure);
    }

    /* Le coin : il colle en haut et a droite, donc au-dessus des deux. */
    .tableau-boite--collant .tableau thead th:last-child {
        z-index: 4;
        box-shadow: -10px 0 10px -10px rgba(15, 23, 42, .22), 0 1px 0 var(--bordure);
    }
}

@media print {
    .tableau-boite--collant { max-height: none; overflow: visible; }
}
