/* ════════════════════════════════════════════════════════════════════
 * PLB — Blocs visuels partagés des pages Ligue
 *
 * POURQUOI CE FICHIER
 *   ligue.html et equipe.html affichent les mêmes objets : une carte
 *   d'équipe, une ligne de match. Tant que chaque page portait sa copie,
 *   une ligue rendait mieux que l'autre — la 2FOPEN n'avait pas la même
 *   brillance au survol que la FSGT, et personne ne savait pourquoi.
 *   Ici, une seule définition. Ajouter une ligue ou une page ne demande
 *   plus que de charger ce fichier : le résultat est identique d'office.
 *
 *   Le code qui produit le HTML correspondant vit dans ligue-ui.js. Les
 *   deux vont ensemble : ne pas charger l'un sans l'autre.
 *
 * VARIABLES ATTENDUES (toutes avec un repli, comme menu.css)
 *   --surface --surface2 --border --text --muted --dim --teal --accent
 *   --r-sm --win --loss
 * ════════════════════════════════════════════════════════════════════ */

/* ── FIL D'ARIANE DANS LE VOLET ───────────────────────────────────────
   Le chemin parcouru — Ligues / FSGT Foot 7 / POULE 1 — vit sur la ligne du
   logo, à la suite de « PasseLaBalle », et pas sur une ligne à part sous le
   titre : c'est là qu'on cherche par où revenir, et ça évite d'écrire
   « Ligues » deux fois sur le même écran.

   Chaque étape est un lien, et elle doit le dire SANS qu'on ait à survoler :
   un fond qui n'apparaît qu'au survol n'apprend rien à qui ne survole pas.
   D'où le soulignement permanent, discret, qui s'allume en teal au survol.
   S'ajoute à .nav-cat (menu.css), qui donne la forme et l'espacement. */
.nav-cat.crumb-link{
  text-decoration:underline;
  text-decoration-color:rgba(var(--ink,255,255,255),.32);
  text-underline-offset:4px;
  text-decoration-thickness:1px;
}
.nav-cat.crumb-link:hover{color:var(--header-fg,#fff);text-decoration-color:var(--teal,#3DD6C4)}

/* ── BANDEAU D'IDENTITÉ D'UNE ÉQUIPE ──────────────────────────────────
   Repris tel quel de l'onglet « Mes équipes » d'activity.html — mêmes noms
   de classes, même allure. Une équipe doit se présenter pareil partout.

   La teinte vient du LOGO (voir hueFromImage dans ligue-ui.js) et n'est
   jamais écrite en dur : la page pose --tb-a / --tb-a2 / --tb-d en style
   inline, calculés depuis la couleur dominante de l'écusson. Une équipe
   sans logo retombe sur un hash de son nom et garde son blason monogramme.

   Tout le reste est fourni par la page : sous-titre, forme, pastilles.
   Le bloc ne sait rien de la 2FOPEN ni de la FSGT — c'est ce qui permet
   d'ajouter une ligue sans y revenir. */
.team-banner{
  display:flex;align-items:center;gap:1rem;
  /* Couleur 1 → couleur 2 de l'écusson → fond, calculées à l'affichage
     depuis le logo (bannerHtml) : s'adapte seul à tout nouveau logo. */
  background:linear-gradient(90deg,var(--tb-d) 0%,var(--tb-d2,var(--tb-d)) 26%,var(--surface,#141926) 58%);
  border:1px solid var(--border,#242c42);
  border-left:3px solid var(--tb-a);
  border-radius:12px;padding:.7rem 1rem;
}
.tb-crest{width:54px;height:54px;flex-shrink:0;filter:drop-shadow(0 2px 5px rgba(0,0,0,.4))}
.tb-crest--logo{border-radius:50%;padding:3px;display:flex;position:relative}
.tb-crest--logo img{width:100%;height:100%;border-radius:50%;object-fit:cover;background:#fff}
.tb-crest-fb{
  position:absolute;inset:3px;border-radius:50%;align-items:center;justify-content:center;
  color:#fff;font-family:'Outfit',sans-serif;font-weight:900;font-size:1.05rem;background:inherit;
}
.tb-crest--shield{
  height:60px;clip-path:polygon(0 0,100% 0,100% 62%,50% 100%,0 62%);
  display:flex;align-items:center;justify-content:center;padding:2px;
}
.tb-mono{
  width:100%;height:100%;clip-path:polygon(0 0,100% 0,100% 62%,50% 100%,0 62%);
  display:flex;align-items:center;justify-content:center;
  color:#fff;font-family:'Outfit',sans-serif;font-weight:900;font-size:1.15rem;
}
.tb-id{min-width:0}
.tb-nm{
  font-family:'Outfit',sans-serif;font-weight:800;font-size:1.15rem;line-height:1.05;
  color:var(--text,#E6EDF3);display:flex;align-items:center;gap:.55rem;flex-wrap:wrap;
}
.tb-sub{color:var(--muted,#8B949E);font-size:.74rem;margin-top:3px}
.tb-sub a{color:var(--tb-a)}
.tb-form{display:inline-flex;gap:4px}
.tb-p{
  width:20px;height:20px;border-radius:5px;display:flex;align-items:center;justify-content:center;
  font-size:.66rem;font-weight:800;color:#fff;font-family:'Outfit',sans-serif;
}
.tb-p.v{background:var(--win,#3fb950)}
.tb-p.n{background:var(--draw,#e3b341);color:#000}
.tb-p.d{background:var(--loss,#f85149)}
.tb-chips{display:flex;gap:.4rem;margin-left:auto;flex-wrap:wrap;justify-content:flex-end}
.tb-chip{
  background:rgba(13,17,23,.6);border:1px solid var(--border,#242c42);border-radius:20px;
  padding:.25rem .7rem;font-size:.74rem;color:var(--muted,#8B949E);white-space:nowrap;
}
.tb-chip b{font-family:'Outfit',sans-serif;color:var(--text,#E6EDF3)}
@media(max-width:600px){
  .team-banner{flex-wrap:wrap}
  .tb-chips{margin-left:0;width:100%;justify-content:flex-start}
}

/* ── CARTE D'ÉQUIPE ───────────────────────────────────────────────────
   Écusson teinté par le nom, puis le nom. Pas de sous-titre : le nombre
   de membres appartient au groupe, il n'a rien à faire sur une page
   publique. Pas de hauteur maximale non plus — on montre toutes les
   équipes, sans rien à dérouler. */
.tgroup{margin-bottom:.75rem}
.tgroup:last-child{margin-bottom:0}
.tgroup-h{
  font-size:.62rem;font-weight:700;color:var(--dim,#5B6478);letter-spacing:.06em;
  text-transform:uppercase;padding:.15rem 0 .4rem;
  display:flex;justify-content:space-between;gap:.4rem;
}
.tgroup.is-cur .tgroup-h{color:var(--accent,#3DD6C4)}
.tcards{display:flex;flex-direction:column;gap:.35rem}
/* Liste d'équipes en pastilles (PLBUI.paintTeams) : en flux, plusieurs par
   ligne, avec la place pour le halo et le relief des équipes actives. */
.ttags{display:flex;flex-wrap:wrap;gap:7px 6px;padding:2px 0}
.ttags .team-tag{max-width:100%}
/* Variante en grille : la MÊME carte, mais en colonnes quand il faut montrer
   toute une poule d'un coup (21 équipes engagées). En colonne unique elles
   feraient défiler l'écran ; en pastilles de texte, on perdait le logo et la
   couleur de chaque club — ce qu'on venait justement de leur donner. */
.tcards--grid{
  display:grid;grid-template-columns:repeat(auto-fill,minmax(186px,1fr));
  gap:.35rem;
}

.tcard{
  /* --hl = la couleur de surbrillance de CETTE carte. Par défaut la teinte
     tirée du nom ; le teal de la marque pour une équipe sur PasseLaBalle.
     Tout passe par cette variable : une seule règle de survol, donc aucune
     bataille de spécificité entre « carte PLB » et « carte survolée » —
     c'est ce qui privait les cartes PLB de leur surbrillance. */
  --hl:var(--c-a);
  display:flex;align-items:center;gap:.55rem;padding:.4rem .6rem .4rem .45rem;border-radius:16px;
  border:1px solid var(--border,#242c42);width:100%;text-align:left;
  color:var(--text,#E6EDF3);text-decoration:none;
  /* Couleur 1 → couleur 2 de l'écusson → fond (voir teamCard). */
  background:linear-gradient(90deg,var(--c-d) 0%,var(--c-d2,var(--c-d)) 42%,var(--surface,#141926) 88%);
  transition:transform .12s,border-color .12s,background .12s,box-shadow .12s;
}

/* Une équipe déjà sur PasseLaBalle se repère à son ENCADREMENT, pas à sa
   couleur : le liseré teal de la marque, l'écusson sur blanc et l'éclair.
   Sa teinte reste la sienne — celle de son logo — sinon toutes les équipes
   inscrites se ressemblent et on perd l'identité visuelle qu'on venait
   justement de leur donner. Le cadre suffit à les distinguer. */
.tcard.plb{
  border-color:color-mix(in srgb,var(--teal,#3DD6C4) 55%,var(--border,#242c42));
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--teal,#3DD6C4) 16%,transparent);
}
/* Au survol, le cadre reste teal — c'est le repère « elle est chez nous » —
   pendant que le fond s'allume dans la couleur de l'équipe. */
a.tcard.plb:hover{border-color:var(--teal,#3DD6C4)}

/* La règle de survol, unique, valable pour toutes les cartes cliquables :
   la ligne s'allume dans SA couleur, on voit ce qu'on s'apprête à ouvrir.
   Intensité choisie pour que l'écart au repos se VOIE : une carte PLB est
   déjà teintée de teal à 17 %, un survol à 30-38 % passait inaperçu. */
a.tcard:hover,
button.tcard:hover{
  transform:translateX(2px);
  border-color:var(--hl);
  background:linear-gradient(90deg,
              color-mix(in srgb,var(--hl) 50%,var(--surface,#141926)) 0%,
              color-mix(in srgb,var(--hl) 16%,var(--surface,#141926)) 100%);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--hl) 34%,transparent);
}
a.tcard:hover .tn,
button.tcard:hover .tn{color:var(--tint-fg,#fff)}
.tcard.off{opacity:.68}

/* Carte SÉLECTIONNÉE (liste qui sert de sélecteur, cf. l'onglet Équipes).
   Même grammaire que le survol, en permanent et un cran au-dessus : c'est
   un état, pas une invitation. Le liseré reprend la couleur de l'équipe,
   donc on sait laquelle est active sans lire son nom. */
.tcard.sel{
  border-color:var(--hl);
  background:linear-gradient(90deg,
              color-mix(in srgb,var(--hl) 62%,var(--surface,#141926)) 0%,
              color-mix(in srgb,var(--hl) 22%,var(--surface,#141926)) 100%);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--hl) 48%,transparent);
}
.tcard.sel .tn{color:var(--tint-fg,#fff)}
.tcard.sel{cursor:default}
/* « On ne voit pas trop l'équipe sélectionnée » (Daniel, 01/10) : le fond
   seul ne suffisait pas, les cartes au repos sont déjà en dégradé. D'où un
   vrai CADRE, détaché de la carte (outline + halo, à la couleur de l'équipe,
   comme la pastille « de luxe » des équipes PLB), et une coche à droite.
   Pleine opacité même si l'équipe est en sommeil (.off). */
.tcard.sel{
  outline:2px solid var(--hl);outline-offset:2px;opacity:1;
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--hl) 48%,transparent),
             0 0 14px 2px color-mix(in srgb,var(--hl) 45%,transparent);
}
.tcard.sel::after{
  content:'✓';margin-left:auto;flex-shrink:0;
  width:18px;height:18px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  font-size:.7rem;font-weight:800;color:#fff;background:var(--hl);
}
a.tcard.sel:hover,button.tcard.sel:hover{transform:none}

.tcrest{
  width:26px;height:26px;border-radius:50%;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;color:#fff;
  font-family:'Outfit',sans-serif;font-weight:800;font-size:.68rem;
  object-fit:cover;
}
.tcard.plb .tcrest{background:#fff;object-fit:contain}
/* La carte sert aussi de bouton (sélection d'une équipe dans la page, cf.
   activity.html) : sans ces trois déclarations, un <button> hérite de la
   police et des marges du navigateur et ne ressemble plus au <a>. */
button.tcard{cursor:pointer;font-family:inherit;font-size:inherit}

.tid{flex:1;min-width:0;display:block;text-align:left}
.tcard .tn{display:block;font-size:.78rem;font-weight:600;
           overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Seconde ligne facultative : nombre de membres, d'événements… Les pages de
   ligue ne s'en servent pas — ces chiffres appartiennent au groupe, pas au
   championnat, et n'ont rien à faire sur une page publique. */
.tcard .tsub{display:block;font-size:.65rem;color:var(--muted,#8B949E);
             overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tcard .bolt{font-size:.62rem;flex-shrink:0}

/* ── TABLEAU DE CLASSEMENT ─────────────────────────────────────────────
   Un classement n'est pas un tableur : on doit y retrouver SON équipe d'un
   coup d'œil parmi vingt-six, et lire qui monte et qui coule sans compter.
   D'où l'écusson devant chaque nom, les cinq derniers résultats en
   pastilles, et la colonne Pts détachée du gris ambiant. */
.st-crest{
  position:relative;overflow:hidden;
  width:20px;height:20px;border-radius:50%;flex:none;
  display:inline-grid;place-items:center;vertical-align:-5px;margin-right:7px;
  color:#fff;font-family:'Outfit',sans-serif;font-weight:800;font-size:.55rem;
}
/* Le logo recouvre les initiales ; s'il échoue, il se retire et les découvre. */
.st-crest img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}

/* La colonne qui décide du classement mérite de se voir. Fond teinté à
   l'accent de la ligue plutôt qu'un simple gras : à taille égale, c'est le
   contraste qui attire l'œil, pas l'épaisseur du trait. */
/* Depuis le 26/09 la colonne est en 3e position, juste après le nom, et non
   plus au bout du tableau : le `padding-right:16px` qui la décollait du bord
   droit n'a plus lieu d'être, elle a maintenant des voisines des deux côtés. */
td.pt, th.pt-h{
  font-family:'Outfit',sans-serif;font-weight:800;font-size:15px;
  color:var(--text,#E6EDF3);padding:0 10px 0 4px;
  font-variant-numeric:tabular-nums;
}
th.pt-h{font-size:inherit;font-weight:inherit;color:inherit}
td.pt b{
  display:inline-block;min-width:2.1rem;padding:2px 7px;border-radius:7px;
  background:color-mix(in srgb,var(--accent,#3DD6C4) 16%,transparent);
  color:var(--accent,#3DD6C4);
}
/* Allègement : vingt cases pleines l'une sous l'autre faisaient une colonne
   de pavés. La couleur de l'accent suffit à attirer l'œil ; le fond ne
   garde qu'un voile. */
td.pt b{background:color-mix(in srgb,var(--accent,#3DD6C4) 6%,transparent)}

/* Forme : V vert, N jaune, D rouge. Assez petites pour tenir dans une
   cellule, assez lisibles pour se compter sans effort. */
.forme{display:inline-flex;gap:2px}
.fm{
  width:14px;height:14px;border-radius:3px;font-style:normal;
  font-size:8.5px;font-weight:700;line-height:14px;text-align:center;
  display:inline-block;color:#0A0F1E;
}
.fm.fV{background:var(--win,#3fb950)}
.fm.fN{background:var(--draw,#e3b341)}
.fm.fD{background:var(--loss,#f85149);color:#fff}

/* Ligne de classement (PLBUI.stAttrs) : l'équipe y est la même pastille
   que dans le calendrier (.team-tag, plus bas). Toute la ligne est
   cliquable ; la survoler allume sa pastille comme si on la survolait. */
/* Dans le tableau, la pastille prend la carrure d'une carte de la colonne
   de gauche : largeur commune (les dégradés s'alignent d'une ligne à
   l'autre), écusson et texte un cran plus grands. */
.standings .team-tag{min-width:min(220px,100%);padding:1px 14px 1px 1px;font-size:13.5px}
.standings .team-tag .st-crest{width:24px;height:24px;font-size:.58rem;margin-right:8px}
/* Ici la cellule ne coupe rien : le survol peut sortir du cadre — halo à la
   couleur du club et léger glissement, comme les cartes de gauche. */
.standings .team-tag{transition:border-color .15s,background .15s,box-shadow .15s,color .15s,transform .15s}
.standings a.team-tag:hover,
.standings tr.clic:hover a.team-tag{
  transform:translateX(3px);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--tg-a) 45%,transparent),
             0 6px 22px color-mix(in srgb,var(--tg-a) 45%,transparent),
             inset 0 1px 0 rgba(255,255,255,.14);
}
.standings tr.clic{cursor:pointer}
.standings tr.clic td{transition:background .15s}
.standings tr.clic:hover td{background:hsl(var(--th,190) 60% 50% / .08)}

/* Les lignes des équipes du visiteur CONNECTÉ, en relief à la couleur de
   leur club : fond teinté, liseré épais, pastille « allumée » en permanent
   et étiquette « Mon équipe ». Rien pour un visiteur anonyme — on ne devine
   pas son équipe à partir de ce qu'il a consulté. Le liseré passe devant
   celui des zones de montée/descente : sa propre équipe prime. */
.standings tr.moi td{background:hsl(var(--th,190) 60% 45% / .15)}
.standings tr.moi td.rk{box-shadow:inset 4px 0 0 hsl(var(--th,190) 70% 60%);font-weight:800;color:var(--text,#E6EDF3)}
/* Plus d'étiquette « Mon équipe » (26/09) : la ligne surlignée suffit. Une
   équipe PasseLaBalle garde sa pastille de luxe (.plb), déjà « allumée ».
   Une équipe EN COURS (.plb-part) garde sa jauge : ce contour plein, plus
   spécifique, l'écrasait — la pastille de La Smala paraissait finie (28/09). */
.standings tr.moi .team-tag:not(.plb):not(.plb-part){
  border-color:var(--tg-a);color:var(--tint-fg,#fff);font-weight:800;
  background:linear-gradient(90deg,
    color-mix(in srgb,var(--tg-a) 62%,var(--surface,#141926)) 0%,
    color-mix(in srgb,var(--tg-a) 22%,var(--surface,#141926)) 100%);
}

/* Zones de montée et de descente. Un liseré à gauche, pas un fond : le fond
   entrerait en concurrence avec la surbrillance des équipes PasseLaBalle.
   Rien ne s'affiche tant que la ligue n'a pas renseigné ses compteurs. */
tr.zone-up   td:first-child{box-shadow:inset 3px 0 0 var(--win,#3fb950)}
tr.zone-down td:first-child{box-shadow:inset 3px 0 0 var(--loss,#f85149)}
.zone-legend{
  display:flex;gap:14px;flex-wrap:wrap;font-size:11.5px;color:var(--muted,#8B949E);
  margin-top:8px;
}
.zone-legend i{font-style:normal;display:inline-block;width:9px;height:9px;
               border-radius:2px;margin-right:5px;vertical-align:0}

/* Sous 720px, le tableau ne tient pas en largeur. On masquait V/N/D/F/BP/BC
   et la forme — mais c'est justement ce qu'on vient chercher (Daniel,
   26/09 : « je ne vois pas les buts pris »). Désormais tout reste, le
   tableau DÉFILE au doigt, et le rang + la pastille d'équipe restent
   fixés à gauche : on sait toujours de quelle ligne on lit les chiffres.
   Les cellules fixées ont un fond plein (sinon les chiffres glisseraient
   dessous en transparence), teinté pour « mon équipe ». */
@media(max-width:720px){
  /* Largeur au plus juste : sans min-width imposé, chaque colonne prend ce
     que son contenu demande. Avant, un tableau forcé à 640px distribuait la
     place en trop à TOUTES les colonnes — la colonne Équipe devenait plus
     large que les noms, au détriment des chiffres. */
  table.standings{width:max-content;min-width:100%;font-size:12.5px}
  table.standings th, table.standings td{padding:8px 5px}
  table.standings th{font-size:9.5px;letter-spacing:.06em}
  table.standings td.pt{font-size:13.5px;padding-right:8px}
  table.standings td.pt b{min-width:1.7rem;padding:1px 5px}
  .st-crest{margin-right:5px}
  .fm{width:12px;height:12px;line-height:12px;font-size:7.5px}
  table.standings th.rk, table.standings td.rk{
    position:sticky;left:0;z-index:2;width:28px;min-width:28px;
    background:var(--surface,#141926);
  }
  /* width:1% : la colonne Équipe se réduit à son contenu, les chiffres se
     partagent le reste. */
  table.standings th:nth-child(2), table.standings td.tn{
    position:sticky;left:28px;z-index:2;background:var(--surface,#141926);
    box-shadow:6px 0 8px -6px rgba(0,0,0,.6);width:1%;
  }
  /* Les POINTS restent visibles, fixés au bord droit : c'est la colonne
     qu'on vient lire. Seule la forme demande encore de faire glisser. */
  table.standings th:last-child, table.standings td.pt{
    position:sticky;right:0;z-index:2;background:var(--surface,#141926);
    box-shadow:-6px 0 8px -6px rgba(0,0,0,.6);
  }
  .standings tr.moi td.pt{
    background:linear-gradient(hsl(var(--th,190) 60% 45% / .15), hsl(var(--th,190) 60% 45% / .15)),
               var(--surface,#141926);
  }
  .standings .team-tag{min-width:0;max-width:124px;font-size:12px;padding:1px 9px 1px 1px}
  .standings .team-tag .st-crest{width:20px;height:20px;margin-right:6px}
  .standings tr.moi td.rk, .standings tr.moi td.tn{
    background:linear-gradient(hsl(var(--th,190) 60% 45% / .15), hsl(var(--th,190) 60% 45% / .15)),
               var(--surface,#141926);
  }
  /* Au doigt, pas de survol : pas de glissement de la pastille. */
  .standings a.team-tag:hover, .standings tr.clic:hover a.team-tag,
  .standings a.team-tag.plb:hover, .standings tr.clic:hover a.team-tag.plb{transform:none}
}

/* ── LIGNE DE MATCH ─────────────────────────────────────────────────────
   UNE ligne par rencontre, pas deux. La date et le terrain occupaient une
   deuxième ligne pleine largeur : une journée de 13 rencontres faisait 26
   lignes et poussait le classement hors de l'écran. Ils passent en colonnes,
   de part et d'autre de l'affiche — et le terrain s'autorise deux lignes
   dans SA colonne sans faire grandir la rangée, puisqu'il est le plus haut
   des éléments alignés au centre.

       quand        domicile    score    visiteur     terrain      état
      (96px)         (1fr)      (auto)    (1fr)       (150px)     (auto)
   ─────────────────────────────────────────────────────────────────────── */
.mrow{
  display:grid;
  grid-template-columns:92px minmax(0,1fr) auto minmax(0,1fr) auto;
  gap:0 12px;align-items:center;
  padding:5px 22px;border-bottom:1px solid rgba(var(--ink,255,255,255),.045);
}
.mrow:last-of-type{border-bottom:none}
.mt{font-weight:600;font-size:13.5px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mt.r{text-align:right}
.mt.win{color:var(--text,#E6EDF3)} .mt.lose{color:var(--muted,#8B949E)}
.sc{
  font-family:'Outfit',sans-serif;font-weight:800;font-size:14.5px;
  font-variant-numeric:tabular-nums;letter-spacing:.02em;
  padding:2px 9px;border-radius:var(--r-sm,9px);background:var(--surface2,#1a2035);
  white-space:nowrap;min-width:62px;text-align:center;
}
/* Flèche › permanente sur la pastille de MON équipe (visiteur connecté) :
   « entre ici », même sans survol. */
.team-tag.go .tg-n::after{content:"\00a0›";font-weight:900;opacity:.9}

/* Raccourci « Mes équipes ». Il vit dans la COLONNE DE GAUCHE depuis le
   26/09 (il barrait le haut de la page centrale, devant le classement) :
   c'est donc une petite carte empilée comme les autres, une équipe par
   ligne. Toute la ligne est le lien vers la page de l'équipe : la pastille,
   le rang en petit (et la poule si c'est une autre), puis une flèche › en
   bout de ligne. Plus de date du prochain match (27/09 : trop large).
   En colonne, `flex-wrap` ne sert plus : chaque équipe a sa ligne, et les
   noms longs tronquent au lieu de pousser la carte. */
.me-strip{
  display:flex;flex-direction:column;align-items:stretch;gap:2px;
  padding:.6rem .5rem .5rem;border-radius:12px;
  background:var(--surface,#141926);border:1px solid var(--border,#242c42);
}
.me-lbl{
  font:700 10.5px 'Outfit',sans-serif;letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted,#8B949E);padding:0 .35rem;margin-bottom:.3rem;
}
.me-row{display:flex;align-items:center;gap:8px;min-width:0;max-width:100%;font-size:12.5px;color:var(--muted,#8B949E);
  text-decoration:none;padding:3px 4px 3px 2px;border-radius:8px;transition:background .15s}
.me-row:hover{background:color-mix(in srgb,var(--text,#E6EDF3) 6%,transparent)}
/* La pastille peut rétrécir (elle tronque le nom à l'ellipse) ; c'est le rang
   et la date qui gardent leur taille et se collent à droite, pour s'aligner
   d'une ligne à l'autre. */
.me-row .team-tag{flex:1 1 auto;min-width:0}
.me-row .me-i{flex:none;margin-left:auto;padding-left:6px;white-space:nowrap}
.me-row b{color:var(--text,#E6EDF3);font-weight:600}
/* La flèche « entrer » : toujours visible (téléphone = pas de survol).
   Double chevron » DESSINÉ en SVG (PLBUI.flecheGo) — centré par construction,
   à la couleur du club (--th, posé sur la ligne et repeint avec le logo),
   un léger relief. Ni cercle ni contour : la pastille turquoise du 29/09
   était trop voyante et son chevron décentré (Daniel). Discrète au repos,
   elle s'avive et avance d'un cran au survol. */
.me-row .me-go{
  flex:none;width:16px;height:16px;margin-left:2px;
  color:hsl(var(--th,175) 60% 62%);opacity:.75;
  filter:drop-shadow(0 1px 1px rgba(0,0,0,.55));
  transition:transform .15s,opacity .15s}
:root[data-theme="light"] .me-row .me-go{
  color:hsl(var(--th,175) 55% 38%);filter:drop-shadow(0 1px 0 rgba(0,0,0,.18))}
.me-row .me-i + .me-go{margin-left:4px}
.me-row .team-tag + .me-go{margin-left:auto}
.me-row:hover .me-go,.me-row:focus-visible .me-go{opacity:1;transform:translateX(2px)}
/* Une seule flèche par ligne : celle de la pastille (.go, posée aussi par
   surlignerMesEquipes) s'efface ici au profit de .me-go. */
.me-row .team-tag.go .tg-n::after{content:none}

/* Journée en cours (page ligue) : matchs à venir = liseré aux couleurs de
   la ligue et date allumée ; matchs joués = date estompée. Un détail, pas un
   fond pleine ligne. « Mon match » (.moi, plus bas) garde la priorité. */
.mrow.avenir{box-shadow:inset 2px 0 0 color-mix(in srgb,var(--accent,#3DD6C4) 45%,transparent)}
.mrow.avenir .mwhen b{color:var(--accent,#3DD6C4)}
.mrow.joue .mwhen{opacity:.5}

/* Mon match dans le calendrier (visiteur connecté) : même relief que ma
   ligne de classement — fond teinté et liseré à la couleur de mon club. */
.mrow.moi{
  background:hsl(var(--th,190) 60% 45% / .15);
  box-shadow:inset 4px 0 0 hsl(var(--th,190) 70% 60%);
}

/* Coup d'envoi d'un match à venir, à la place du « VS » (même case que le
   score) : lisible comme un score, un ton plus discret. */
.sc.ko{color:var(--muted,#8B949E);font-weight:800;letter-spacing:.01em}
/* Allègement : l'horaire d'un match à venir se lit sans case autour. La
   case reste pour le SCORE — c'est elle qui dit « ce match est joué ». */
.sc.ko{background:transparent}

/* Forfait : un F rouge à la place du chiffre (PLBUI.scoreMatch). */
.sc-f{color:var(--loss,#f85149);font-weight:900}
/* Score saisi dans l'appli, pas encore validé par la ligue (* ou ! si désaccord) */
.sc-nv{font-size:.62em;vertical-align:super;margin-left:1px;font-weight:800;opacity:.75;cursor:help}
.sc-nv.conflit{color:var(--loss,#f85149);opacity:1}
.sc.none{color:var(--dim,#5B6478);font-weight:700;font-size:12px;letter-spacing:.08em}

/* Quand : jour au-dessus, heure en dessous. Deux lignes très serrées, pour
   que la colonne reste étroite sans tronquer « jeu. 23 nov. ». */
.mwhen{font-size:10.5px;color:var(--dim,#5B6478);line-height:1.25;white-space:nowrap}
.mwhen b{display:block;color:var(--muted,#8B949E);font-weight:600}

/* Terrain : le nom sur la 1re ligne, l'adresse sur la 2e, tronquée — elle
   n'est là que pour lever un doute entre deux gymnases du même nom. Le clic
   sur le terrain ouvre sa fiche (adresse complète, consignes) ; la flèche
   bleue, à côté, part directement vers l'itinéraire. */
.mplace{font-size:10.5px;line-height:1.25;min-width:0;text-align:right;
        display:flex;align-items:center;justify-content:flex-end;gap:5px}
.mplace > b,.lieu-btn{min-width:0}
.mplace b{display:block;color:var(--muted,#8B949E);font-weight:600;
          overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mplace .maps{display:block;color:var(--dim,#5B6478);text-decoration:none;
              overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Le terrain d'une rencontre est un bouton : relief au survol, comme les
   pastilles d'équipe. */
.lieu-btn{
  flex:0 1 auto;font:inherit;color:inherit;text-align:inherit;cursor:pointer;
  background:none;border:1px solid transparent;border-radius:7px;padding:2px 6px;
  transition:background .15s,border-color .15s,box-shadow .15s,transform .15s;
}
.lieu-btn:hover,.lieu-btn:focus-visible{
  background:rgba(61,214,196,.08);border-color:rgba(61,214,196,.38);
  box-shadow:0 3px 10px rgba(0,0,0,.35);transform:translateY(-1px);outline:none;
}
.lieu-btn:hover b{color:var(--teal,#3DD6C4)}
/* Icône de navigation en tête du terrain (PLBUI.iconeLieu), bleu Google
   Maps : on comprend sans lire qu'on va vers le lieu et son itinéraire. */
.lieu-btn{display:inline-flex;align-items:center;gap:6px}
.lieu-btn > span:last-child,.lieu-btn > b{min-width:0}
.lieu-ico{
  flex:none;width:20px;height:20px;border-radius:50%;display:grid;place-items:center;
  color:#4C8DF6;background:rgba(66,133,244,.12);border:1px solid rgba(66,133,244,.35);
}
.lieu-ico svg{width:11px;height:11px}
.lieu-btn:hover .lieu-ico{background:rgba(66,133,244,.26)}
/* Icône seule (PLBUI.boutonLieu) : pas de cadre autour, l'icône EST le bouton. */
.lieu-btn.solo{padding:0;border:0;background:none;box-shadow:none;transform:none}
.lieu-btn.solo .lieu-ico{width:26px;height:26px;transition:background .15s,transform .15s}
.lieu-btn.solo .lieu-ico svg{width:13px;height:13px}
.lieu-btn.solo:hover .lieu-ico,.lieu-btn.solo:focus-visible .lieu-ico{background:rgba(66,133,244,.3);transform:scale(1.08)}
/* Une colonne de dix cercles cerclés de bleu faisait une seconde grille :
   au repos, l'icône n'a plus de contour et son fond est à peine teinté ;
   le bleu plein revient au survol. */
.lieu-btn.solo .lieu-ico{border-color:transparent;background:rgba(66,133,244,.08)}
.lieu-sans{display:inline-flex;opacity:.45}
.lieu-sans .lieu-ico{width:26px;height:26px;border-color:transparent}
.lieu-btn:hover .maps{color:var(--muted,#8B949E)}

/* La flèche bleue « y aller » (PLBUI.flecheItineraire) : la couleur de
   Google Maps, pour qu'on comprenne sans lire qu'on part vers le lieu. */
.go-maps{
  flex:none;display:inline-flex;align-items:center;justify-content:center;gap:6px;
  min-width:26px;height:26px;padding:0 6px;border-radius:100px;
  color:#4C8DF6;background:rgba(66,133,244,.12);border:1px solid rgba(66,133,244,.35);
  text-decoration:none;font-size:.78rem;font-weight:700;
  transition:background .15s,transform .15s,box-shadow .15s;
}
.go-maps:hover{background:rgba(66,133,244,.24);transform:translateY(-1px);
               box-shadow:0 3px 10px rgba(0,0,0,.35)}
.go-maps span{color:#8AB4F8}
.lx-x .go-maps{height:28px;padding:0 12px 0 10px}

/* Ancienne disposition, sur deux lignes — réservée aux saisons archivées,
   dont les données figées ne se découpent pas en colonnes. */
.mrow.legacy{grid-template-columns:1fr auto 1fr;gap:4px 14px;padding:7px 22px}
.mrow.legacy .mmeta{
  grid-column:1/-1;font-size:11px;color:var(--dim,#5B6478);line-height:1.3;
  display:flex;flex-wrap:wrap;gap:3px 12px;justify-content:center;align-items:center;
}

.mrow.exempt{grid-template-columns:1fr;text-align:center;color:var(--muted,#8B949E);
             font-size:12px;padding:4px 22px;background:rgba(var(--ink,255,255,255),.02)}

/* ── CALENDRIER D'UN JOUEUR (/activity, onglet Moi — 27/09) ─────────────
   La MÊME ligne que le calendrier d'une poule (PLBUI.ligneMatch), avec deux
   colonnes de plus, parce qu'un joueur mélange futsal, foot à 7, five… :

     quand | activité + titre (lieu) | mon équipe | score | adversaire | ➤ | •

   L'activité a une largeur FIXE : chaque ligne est sa propre grille, une
   colonne « auto » décalerait les équipes d'une ligne à l'autre. */
.mrow.large{grid-template-columns:92px minmax(0,1.25fr) minmax(0,1fr) auto minmax(0,1fr) 26px 10px}
.m-ev{display:flex;align-items:center;gap:8px;min-width:0}
.m-ev .m-act{flex:none;width:78px;display:flex}
.m-ev .m-act > *{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.m-titre{min-width:0;line-height:1.25}
.m-titre b{display:block;font-size:13px;font-weight:600;color:var(--text,#E6EDF3);
           overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.m-titre span{display:block;font-size:10.5px;color:var(--dim,#5B6478);
              overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Ma réponse, seulement quand elle n'est PAS « présent » (vue « Tous ») :
   un point, le mot dans l'infobulle. */
.m-pres{width:8px;height:8px;border-radius:50%;justify-self:center}
.m-pres.absent{background:var(--absent,var(--loss,#f85149))}
.m-pres.invited{background:var(--draw,#e3b341)}
.mrow.large.m-absent > :not(.m-pres){opacity:.55}
/* Séparateur de mois : la date courte (« jeu. 21 sept. ») n'a pas d'année. */
.mrow.msep{grid-template-columns:1fr;padding:9px 22px 3px;font:700 10.5px 'Outfit',sans-serif;
           letter-spacing:.07em;text-transform:uppercase;color:var(--muted,#8B949E);
           background:rgba(var(--ink,255,255,255),.02)}

/* Variante `compact` (ligneMatch(m, {cls:'compact'})) : pour une colonne
   étroite — la carte championnat de /activity, onglet Équipes (01/10).
   La disposition téléphone (date à gauche sur deux lignes, pastilles à leur
   largeur naturelle) faisait des pastilles en escalier et laissait un trou
   entre elles et l'heure (Daniel : « mise en forme pas terrible »). Ici :
       mar. 6 oct.  20h30                    ➤
       [ Tiki-Taka ]
       [ Muret ]
   Les deux pastilles partent du même bord gauche. */
.mrow.compact{grid-template-columns:auto auto minmax(0,1fr) auto;row-gap:5px;column-gap:8px;padding:4px 0 2px;border-bottom:none;box-shadow:none}
.mrow.compact .mwhen{grid-column:1;grid-row:1;align-self:center;white-space:nowrap;font-size:12px;line-height:1.2}
.mrow.compact .mwhen b{display:inline;color:var(--text,#E6EDF3)}
.mrow.compact .sc{grid-column:2;grid-row:1;justify-self:start;align-self:center;font-size:12px;min-width:0;padding:0;color:var(--text,#E6EDF3)}
.mrow.compact .mplace{grid-column:4;grid-row:1;align-self:center}
.mrow.compact .mplace .lieu-ico{width:24px;height:24px}
/* `.mt:not(.r)` explicite : la règle téléphone `.mrow .mt:not(.r)` a le même
   poids et vient plus bas — sans ça, sous 720 px, la 2e pastille repassait
   en colonne 2 et ne s'étirait plus. */
.mrow.compact .mt.r,.mrow.compact .mt:not(.r){grid-column:1/-1;text-align:left}
.mrow.compact .mt.r{grid-row:2}
.mrow.compact .mt:not(.r){grid-row:3}
/* Taille des pastilles = celle de l'extrait de classement juste au-dessus
   (.mini-st : 12 px, écusson 18 px). Pleine largeur, elles paraissaient
   énormes à côté de lui (Daniel, 01/10) : largeur naturelle, alignées à
   gauche — c'est le bord commun qui fait l'alignement. */
.mrow.compact .team-tag{font-size:12px;padding:1px 9px 1px 1px}
.mrow.compact .team-tag .st-crest{width:18px;height:18px;margin-right:5px}

/* ── TAG D'ÉQUIPE ──────────────────────────────────────────────────────
   Le nom de l'adversaire est la porte la plus utile d'un calendrier : on va
   y lire ses derniers résultats avant de le jouer. En texte souligné on ne
   la voyait pas. En pastille avec écusson, bord et relief au survol, elle se
   donne pour ce qu'elle est — et l'écusson identifie l'équipe même quand le
   nom est tronqué. */
/* Même grammaire que la carte d'équipe (.tcard) : dégradé partant de la
   couleur du club (`--th`, posée par tagEquipe) au repos ; au survol, le
   fond s'allume dans cette couleur, le bord aussi, le nom passe en blanc.
   Pas de translateY : la cellule du calendrier (.mt) est en overflow:hidden
   pour tronquer les noms longs, et une pastille soulevée y perdait son bord
   haut. Tout le relief est donc dessiné DEDANS. */
/* Couleurs un peu ADOUCIES pour les équipes « normales » (26/09) : à côté
   des pastilles vives des équipes actives, elles criaient trop. */
.team-tag{
  --tg-a:hsl(var(--th,200) 48% 52%);
  --tg-d:hsl(var(--th,200) 34% 25%);
  display:inline-flex;align-items:center;gap:0;min-width:0;max-width:100%;
  padding:1px 10px 1px 1px;border-radius:100px;
  background:linear-gradient(90deg,var(--tg-d) 0%,var(--surface2,#1a2035) 100%);
  border:1px solid color-mix(in srgb,var(--tg-a) 32%,var(--border,#242c42));
  color:var(--text,#E6EDF3);text-decoration:none;font-size:13px;font-weight:600;
  transition:border-color .15s,background .15s,box-shadow .15s,color .15s,transform .18s;
}
/* ALLÈGEMENT (26/09, soir) : « des petits carrés partout ». Rien n'est
   retiré, on baisse seulement le volume : au repos, une équipe ordinaire
   perd son contour et ne garde qu'un voile de la couleur de son club, qui
   s'efface vers la droite. Des dizaines de contours fins, c'est ce qui
   faisait « quadrillage ». La pastille complète revient au survol, et les
   équipes PasseLaBalle (.plb) et la mienne gardent leur relief — elles
   ressortent d'autant mieux. */
.team-tag:not(.plb):not(.mine){
  border-color:transparent;
  background:linear-gradient(90deg,color-mix(in srgb,var(--tg-d) 70%,transparent) 0%,transparent 85%)
             border-box;
}
/* Écusson EMBOÎTÉ : toute la hauteur intérieure de la pastille (1 px de
   marge), au lieu de flotter dans un contour plus large que lui. */
.team-tag .st-crest{width:20px;height:20px;margin-right:6px;font-size:.52rem;vertical-align:0}
.team-tag .tg-n{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
a.team-tag:hover,
.standings tr.clic:hover a.team-tag{
  border-color:var(--tg-a);color:var(--tint-fg,#fff);
  background:linear-gradient(90deg,
    color-mix(in srgb,var(--tg-a) 72%,var(--surface,#141926)) 0%,
    color-mix(in srgb,var(--tg-a) 26%,var(--surface,#141926)) 100%);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--tg-a) 55%,transparent),
             inset 0 1px 0 rgba(255,255,255,.14);
}
/* Équipe consultée : c'est déjà elle le sujet de la page, pas un lien à
   suivre. On la marque sans lui donner l'air d'une porte. */
.team-tag.mine{border-color:color-mix(in srgb,var(--accent,#3DD6C4) 50%,var(--border,#242c42));
               background:color-mix(in srgb,var(--accent,#3DD6C4) 10%,transparent)}
.team-tag.lose{opacity:.62}
.team-tag.off{opacity:.55;cursor:default}
/* ── ÉQUIPE ÉLIMINÉE D'UNE COUPE (29/09) ───────────────────────────────
   Pastille ÉTEINTE et FISSURÉE : couleurs du club passées au gris, plus de
   relief ni de reflet, et une fissure en zigzag qui la traverse. Elle reste
   cliquable (sa page existe toujours) ; l'infobulle dit à quel tour. La
   fissure prend la place du reflet (::after), sélecteurs doublés pour passer
   devant .plb et .plb-part. */
.team-tag.out,.team-tag.out.plb,.team-tag.out.plb-part:not(.plb){
  position:relative;overflow:hidden;filter:grayscale(1);opacity:.5;
  box-shadow:none;font-weight:600;
}
.team-tag.out::before{display:none}
.team-tag.out::after,.team-tag.out.plb::after,.team-tag.out.plb-part::after{
  content:"";position:absolute;inset:0;pointer-events:none;border-radius:inherit;transition:none;
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 20' preserveAspectRatio='none'%3E%3Cpath d='M-2 15 L14 9 L22 13 L35 4 L44 11 L57 6 L63 12 L78 3 L86 9 L102 5' fill='none' stroke='%23000' stroke-opacity='.75' stroke-width='2.4' vector-effect='non-scaling-stroke'/%3E%3Cpath d='M-2 16 L14 10 L22 14 L35 5 L44 12 L57 7 L63 13 L78 4 L86 10 L102 6' fill='none' stroke='%23fff' stroke-opacity='.55' stroke-width='1' vector-effect='non-scaling-stroke'/%3E%3Cpath d='M35 4 L38 -1 M57 6 L55 14 L58 21' fill='none' stroke='%23000' stroke-opacity='.6' stroke-width='1.4' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E")
    center/100% 100% no-repeat;
}
a.team-tag.out:hover,a.team-tag.out.plb:hover,a.team-tag.out.plb-part:hover{
  transform:none;opacity:.8;box-shadow:none;
}

/* ── PASTILLE D'UNE ÉQUIPE PASSELABALLE (variante « D », 26/09) ─────────
   Ce qui donne envie d'avoir la sienne : les DEUX couleurs de son écusson
   (--th → --th2, extraites par hueFromImage en ignorant blanc, noir et
   gris) en dégradé et en contour, un halo diffus de ces couleurs, et au
   survol un reflet qui traverse la pastille pendant qu'elle s'avance. Les
   autres équipes gardent la pastille normale ci-dessus. */
.team-tag.plb{
  position:relative;overflow:hidden;color:#fff;font-weight:800;
  border:1.5px solid transparent;
  background:
    linear-gradient(100deg,hsl(var(--th,200) 72% 44%) 0%,hsl(var(--th2,var(--th,200)) 62% 30%) 70%,
                           hsl(var(--th2,var(--th,200)) 45% 19%) 100%) padding-box,
    linear-gradient(100deg,hsl(var(--th,200) 85% 64%),hsl(var(--th2,var(--th,200)) 85% 60%)) border-box;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.28),
    inset 0 -1px 0 rgba(0,0,0,.25),
    -4px 0 12px hsl(var(--th,200) 80% 55% / .4),
    6px 0 14px hsl(var(--th2,var(--th,200)) 80% 55% / .35),
    0 4px 10px rgba(0,0,0,.45);
}
.team-tag.plb .st-crest{box-shadow:0 0 0 1.5px hsl(var(--th,200) 80% 70%)}
/* Le reflet : une bande de lumière qui traverse au survol. */
.team-tag.plb::after{
  content:"";position:absolute;inset:0;pointer-events:none;border-radius:inherit;
  background:linear-gradient(115deg,transparent 30%,rgba(255,255,255,.32) 45%,transparent 60%);
  background-size:250% 100%;background-position:100% 0;transition:background-position .6s ease;
}
/* Au survol : le reflet passe ET la pastille s'avance, ombre plus portée. */
a.team-tag.plb:hover,
.standings tr.clic:hover a.team-tag.plb{
  color:#fff;border-color:transparent;
  background:
    linear-gradient(100deg,hsl(var(--th,200) 76% 50%) 0%,hsl(var(--th2,var(--th,200)) 66% 34%) 70%,
                           hsl(var(--th2,var(--th,200)) 48% 22%) 100%) padding-box,
    linear-gradient(100deg,hsl(var(--th,200) 90% 70%),hsl(var(--th2,var(--th,200)) 90% 66%)) border-box;
  transform:translateY(-2px) scale(1.04);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.34),
    -5px 0 18px hsl(var(--th,200) 85% 58% / .6),
    8px 0 18px hsl(var(--th2,var(--th,200)) 85% 58% / .5),
    0 9px 18px rgba(0,0,0,.55);
}
a.team-tag.plb:hover::after,
.standings tr.clic:hover a.team-tag.plb::after{background-position:0 0}
/* ── ÉQUIPE QUI DÉMARRE SUR PASSELABALLE (28/09) ────────────────────────
   Réclamée, mais pas encore assez de membres pour être « active ». Une
   JAUGE : jusqu'à --prog (0..1, donné par la vue standings) la pastille est
   exactement celle d'une équipe active — ses deux couleurs, son contour
   allumé ; au-delà, une piste vide et sombre. La limite est NETTE, marquée
   d'un trait de lumière : c'est elle qui dit « c'est commencé, pas fini ».
   Rien ne doit briller au-delà (première version : anneau de l'écusson et
   halo tout autour — la pastille paraissait entourée de bout en bout).
   Sélecteurs en :not(.plb) pour passer devant l'allègement des équipes
   ordinaires (plus haut). */
.team-tag.plb-part:not(.plb){
  --fin:calc(var(--prog,.25) * 100%);
  position:relative;overflow:hidden;color:#fff;font-weight:700;
  border:1.5px solid transparent;
  background:
    linear-gradient(100deg,hsl(var(--th,200) 72% 44%) 0%,hsl(var(--th2,var(--th,200)) 62% 32%) var(--fin),
                           var(--tag-track,var(--surface,#141926)) var(--fin),var(--tag-track,var(--surface,#141926)) 100%) padding-box,
    linear-gradient(90deg,hsl(var(--th,200) 85% 64%) 0%,hsl(var(--th2,var(--th,200)) 85% 60%) var(--fin),
                          rgba(var(--ink,255,255,255),.07) var(--fin)) border-box;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.12),0 3px 8px rgba(0,0,0,.35);
}
.team-tag.plb-part:not(.plb) .st-crest{box-shadow:none}
/* Le nom passe devant le trait du front : il ne doit pas le barrer. */
.team-tag.plb-part:not(.plb) .tg-n,
.team-tag.plb-part:not(.plb) .st-crest{position:relative;z-index:1}
/* Le front de remplissage : un trait vertical lumineux, net. */
.team-tag.plb-part:not(.plb)::before{
  content:"";position:absolute;pointer-events:none;top:0;bottom:0;width:2px;
  left:calc(var(--fin) - 1px);
  background:linear-gradient(180deg,transparent,rgba(255,255,255,.95) 30%,rgba(255,255,255,.95) 70%,transparent);
  box-shadow:0 0 6px 1px hsl(var(--th2,var(--th,200)) 90% 70% / .9);
}
/* Survol : la partie remplie s'allume comme une pastille active, la piste
   reste vide — la jauge se lit encore mieux. */
a.team-tag.plb-part:not(.plb):hover,
.standings tr.clic:hover a.team-tag.plb-part:not(.plb){
  color:#fff;border-color:transparent;
  background:
    linear-gradient(100deg,hsl(var(--th,200) 76% 50%) 0%,hsl(var(--th2,var(--th,200)) 66% 36%) var(--fin),
                           color-mix(in srgb,#fff 4%,var(--tag-track,var(--surface,#141926))) var(--fin),
                           color-mix(in srgb,#fff 4%,var(--tag-track,var(--surface,#141926))) 100%) padding-box,
    linear-gradient(90deg,hsl(var(--th,200) 90% 70%) 0%,hsl(var(--th2,var(--th,200)) 90% 66%) var(--fin),
                          rgba(var(--ink,255,255,255),.16) var(--fin)) border-box;
  transform:translateY(-2px) scale(1.04);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22),0 8px 16px rgba(0,0,0,.5);
}
/* Le reflet qui traverse au survol : le même que la pastille active. */
.team-tag.plb-part::after{
  content:"";position:absolute;inset:0;pointer-events:none;border-radius:inherit;
  background:linear-gradient(115deg,transparent 30%,rgba(255,255,255,.28) 45%,transparent 60%);
  background-size:250% 100%;background-position:100% 0;transition:background-position .6s ease;
}
a.team-tag.plb-part:hover::after,
.standings tr.clic:hover a.team-tag.plb-part::after{background-position:0 0}
@media(prefers-reduced-motion:reduce){
  a.team-tag.plb-part:hover,.standings tr.clic:hover a.team-tag.plb-part{transform:none}
  .team-tag.plb-part::after{transition:none}
}

/* La cellule du calendrier ne coupe plus une pastille qui s'avance : c'est
   la pastille elle-même qui tronque un nom trop long (.tg-n). */
.mt:has(.team-tag){overflow:visible}
@media(prefers-reduced-motion:reduce){
  a.team-tag.plb:hover,.standings tr.clic:hover a.team-tag.plb{transform:none}
  .team-tag.plb::after{transition:none}
}

/* Le nom d'équipe mène à sa page : calendrier, résultats, place au classement. */
.tlink{color:inherit;text-decoration:none;border-bottom:1px solid transparent;
       transition:border-color .15s,color .15s}
.tlink:hover{color:var(--accent,#3DD6C4);
             border-bottom-color:color-mix(in srgb,var(--accent,#3DD6C4) 55%,transparent)}

/* ── ÉTAT D'UN MATCH ──────────────────────────────────────────────────
   Trois états, trois couleurs, les mêmes partout — calendrier d'une ligue
   comme calendrier d'une équipe :

   · ✓ dans l'appli  (vert)  la rencontre existe comme événement PLB : les
                             joueurs sont convoqués et répondent.
   · ❌ hors appli   (rouge) elle est au calendrier de la ligue mais dans
                             aucun agenda — c'est le match qu'on oublie.
   · ⚠️ non programmé (jaune) la ligue n'a pas fixé de date. Il passe avant
                             les deux autres : sans date, un match ne PEUT
                             pas entrer dans l'appli.

   La couleur suffit à lire une journée entière sans lire un seul mot. */
.mstat{
  display:inline-flex;align-items:center;gap:5px;white-space:nowrap;
  font-size:11px;font-weight:700;padding:2px 9px;border-radius:100px;
  border:1px solid transparent;letter-spacing:.01em;
}
.mstat.ok   {background:rgba(63,185,80,.14); color:var(--win,#3fb950);
             border-color:rgba(63,185,80,.32)}
.mstat.ko   {background:rgba(248,81,73,.13); color:var(--loss,#f85149);
             border-color:rgba(248,81,73,.34)}
.mstat.wait {background:rgba(227,179,65,.14);color:var(--draw,#e3b341);
             border-color:rgba(227,179,65,.34)}
.mstat.err  {background:rgba(248,81,73,.13); color:var(--loss,#f85149);
             border-color:rgba(248,81,73,.34);white-space:normal}

/* « + » : ajouter le match à l'agenda de l'équipe. Une ACTION réservée au
   capitaine (seul reste de l'ancienne colonne d'état), en rond compact. */
.add-btn{
  width:26px;height:26px;padding:0;border-radius:50%;cursor:pointer;flex:none;
  font:700 16px/1 'Outfit',sans-serif;display:inline-grid;place-items:center;
  background:color-mix(in srgb,var(--teal,#3DD6C4) 16%,transparent);
  color:var(--teal,#3DD6C4);border:1px solid color-mix(in srgb,var(--teal,#3DD6C4) 45%,transparent);
  transition:background .15s,transform .15s;
}
.add-btn:hover{background:color-mix(in srgb,var(--teal,#3DD6C4) 28%,transparent);transform:scale(1.08)}
.add-btn:disabled{opacity:.5;cursor:default;transform:none}

@media(max-width:720px){
  /* Téléphone : DEUX lignes par match (il en fallait 5, puis 4) —
       lun. 28 sept.  [domicile ]  ┐
       20h10          [extérieur]  ┘ score   ➤
     La date à gauche en deux lignes, les équipes empilées, le score et
     l'icône du terrain à droite sur toute la hauteur. */
  .mrow{grid-template-columns:74px minmax(0,1fr) auto auto;row-gap:3px;column-gap:8px;padding:7px 12px}
  .mrow .team-tag{font-size:12px;padding:1px 9px 1px 1px}
  .mrow .team-tag .st-crest{width:18px;height:18px;margin-right:5px}
  .mrow .sc{font-size:13px;min-width:48px;padding:2px 6px}
  .mwhen{grid-column:1;grid-row:1/3;align-self:center;white-space:normal;font-size:10.5px}
  .mwhen b{display:block;white-space:nowrap}
  .mrow .mt.r{grid-column:2;grid-row:1;text-align:left}
  .mrow .mt:not(.r){grid-column:2;grid-row:2}
  .mrow .sc{grid-column:3;grid-row:1/3;align-self:center}
  .mplace{grid-column:4;grid-row:1/3;align-self:center}
  .mplace .lieu-ico{width:28px;height:28px}
  /* Calendrier d'un joueur : une ligne de plus en tête (activité + titre),
     le reste descend d'un cran. */
  .mrow.large{grid-template-columns:74px minmax(0,1fr) auto auto}
  .mrow.large .mwhen{grid-row:1/4}
  .mrow.large .m-ev{grid-column:2/4;grid-row:1}
  .mrow.large .m-pres{grid-column:4;grid-row:1}
  .mrow.large .mt.r{grid-row:2}
  .mrow.large .mt:not(.r){grid-row:3}
  .mrow.large .sc,.mrow.large .mplace{grid-row:2/4}
  .mrow.msep{padding:9px 12px 3px}
}

/* ══════════════════════════════════════════════════════════════════════
   GABARIT DE PAGE — trois colonnes, partagé par ligue.html et equipe.html

   POURQUOI ICI ET PLUS DANS LES PAGES (Daniel, 26/09)
     Les deux pages en avaient chacune une copie. Elles étaient à deux
     détails près identiques — et ces deux détails étaient justement des
     divergences silencieuses (`margin-bottom` de l'intertitre, et `1fr` au
     lieu de `minmax(0,1fr)` au dernier palier, ce qui laissait une adresse
     de gymnase insécable élargir toute la page sur téléphone).
     Une seule définition : les deux pages ne PEUVENT plus diverger.

   LES PALIERS — on resserre avant de sacrifier
     Le premier jet repliait la colonne de droite dès 1160 px. C'était trop
     tôt : à cette largeur les trois colonnes tiennent largement, et sur un
     écran de portable (ou un navigateur qui partage l'écran avec l'éditeur)
     on perdait la colonne pour rien — le sondage et la liste se retrouvaient
     tout en bas de page. Donc :
       ≥ 1161      trois colonnes au large
       1160 → 1001 trois colonnes RESSERRÉES (les latérales maigrissent)
       1000 → 901  deux colonnes, la droite passe sous le centre
       ≤ 900       tout empilé, dans l'ordre de l'importance
     Le tableau du classement vit dans `.tscroll` (overflow-x) : une colonne
     centrale plus étroite le fait défiler, elle ne le casse pas.
   ══════════════════════════════════════════════════════════════════════ */
/* LARGEURS — les deux latérales ont grossi aux dépens du centre (Daniel,
   26/09 : « tu peux réduire la colonne centrale légèrement, ça ne gêne pas »).
   Ce sont elles qui portent des NOMS : l'effectif et les 26 équipes à droite,
   « Mes équipes » à gauche depuis qu'il a quitté le haut de page. Les noms
   longs y tronquaient trop tôt. Le centre, lui, a de la marge depuis que le
   calendrier et le classement ont été resserrés.
   Droite 232 → 268, gauche 226 → 244 : 54 px pris au centre en tout. */
.layout{display:grid;grid-template-columns:244px minmax(0,1fr) 268px;gap:1.1rem;align-items:start}
/* Pas de position:sticky : avec une colonne plus haute que l'écran, la
   latérale se fige pendant que le centre continue de défiler, et on ne sait
   plus laquelle on fait bouger. Les trois défilent ensemble. */
.side{display:flex;flex-direction:column;gap:.75rem}
.col{min-width:0}
.aside-card{background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:.75rem .85rem}
.aside-ttl{
  font-size:.62rem;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);
  font-weight:600;margin-bottom:.55rem;display:flex;justify-content:space-between;
  gap:.4rem;align-items:baseline;
}
.aside-ttl span{text-transform:none;letter-spacing:0;font-weight:500}

@media(max-width:1160px){
  /* On resserre surtout la GAUCHE : elle ne porte que quatre intitulés
     courts, là où la droite porte des noms d'équipe. */
  .layout{grid-template-columns:182px minmax(0,1fr) 232px;gap:.9rem}
}
@media(max-width:1000px){
  .layout{grid-template-columns:200px minmax(0,1fr);gap:1rem}
  .side-right{grid-column:2;order:3}
}
@media(max-width:900px){
  /* minmax(0,1fr) et pas 1fr : une adresse de gymnase insécable suffisait à
     élargir la colonne, donc toute la page, au-delà de l'écran du téléphone. */
  .layout{grid-template-columns:minmax(0,1fr)}
  .col{order:1}
  .side{position:static;order:2}
  .side-right{grid-column:1;order:3}
}

/* ══════════════════════════════════════════════════════════════════════
   LIENS UTILES — le bloc des rubriques de ligue (PLBUI.lienWidget)

   UNE SEULE DÉFINITION POUR TOUT LE SITE (Daniel, 26/09)
     Le markup venait déjà de lienWidget(), mais le STYLE était recopié dans
     ligue.html et dans equipe.html — et les deux copies avaient divergé : la
     page équipe montrait quatre boutons encadrés, la page championnat quatre
     lignes sobres. Deux pages, deux apparences, pour exactement le même bloc.
     Daniel a tranché pour la version sobre ; elle vit ici, et nulle part
     ailleurs.

   POURQUOI SANS CADRE
     La carte « Liens utiles » encadre déjà les rubriques une fois. Les
     encadrer encore chacune faisait des boîtes dans une boîte, et quatre
     liserés de couleur pour quatre lignes qu'on lit en deux secondes.
     Au repos : rien. Au survol : un fond, qui suffit à dire « cliquable ».

   QUATRE ÉTATS, tous rendus par lienWidget() :
     (défaut)  lien vers un document de la ligue
     .act      bouton : ouvre une fiche construite depuis NOTRE base
     .lock     le document existe mais n'est pas public
     .off      la ligue ne publie rien pour cette rubrique
   ══════════════════════════════════════════════════════════════════════ */
.srcbox{
  display:flex;align-items:center;gap:.7rem;text-decoration:none;
  margin:0;padding:.5rem .55rem;border:0;border-radius:9px;
  background:transparent;transition:background .15s;
}
.srcbox:hover{background:color-mix(in srgb,var(--accent,#3DD6C4) 10%,transparent)}
.srcbox:hover .src-txt b{color:var(--tint-fg,#fff)}
.src-ico{font-size:1rem;opacity:.9;flex-shrink:0}
.src-txt{display:flex;flex-direction:column;min-width:0;flex:1}
.src-txt b{color:var(--text,#E6EDF3);font-size:.8rem;font-weight:600;transition:color .15s}
.src-txt i{font-style:normal;color:var(--muted,#8B949E);font-size:.71rem;margin-top:.1rem}
.src-go{color:var(--accent,#3DD6C4);font-size:.75rem;font-weight:700;
        white-space:nowrap;flex-shrink:0}

/* Rubrique sans document : présente, mais visiblement inerte. */
.srcbox.off{opacity:.45;cursor:default}
.srcbox.off:hover{background:transparent}
.srcbox.off:hover .src-txt b{color:var(--text,#E6EDF3)}
.srcbox.off .src-go{color:var(--muted,#8B949E)}

/* ── RUBRIQUE VERROUILLÉE ─────────────────────────────────────────────
   Un document qui existe mais qu'on ne diffuse pas à tout internet : il se
   voit, il s'explique, il ne s'ouvre pas. Différent du grisé « la ligue ne
   publie rien » — ici c'est NOUS qui fermons, et il faut que ça se comprenne
   sans lire l'infobulle. Sans cadre, c'est l'ambre du sous-titre et du
   cadenas qui porte l'état. */
.srcbox.lock{cursor:default;opacity:.85}
.srcbox.lock:hover{background:transparent}
.srcbox.lock:hover .src-txt b{color:var(--text,#E6EDF3)}
.srcbox.lock .src-txt i{color:var(--draw,#e3b341)}
.srcbox.lock .src-go{color:var(--draw,#e3b341)}

/* ── LE SEUL ENDROIT QUI GARDE UN CADRE ───────────────────────────────
   Le bandeau de provenance du classement (« Classement officiel 2FOPEN »)
   n'est pas dans une liste : il est seul, en pleine largeur, sous le
   tableau. Sans cadre il flotterait. D'où ce modificateur — à n'utiliser
   QUE pour un widget isolé, jamais dans la colonne des liens utiles. */
.srcbox-cadre{
  background:var(--surface2,#1a2035);border:1px solid var(--border,#242c42);
  border-left:3px solid var(--accent,#3DD6C4);border-radius:10px;
  padding:.6rem .8rem;transition:border-color .15s,transform .15s;
}
.srcbox-cadre:hover{
  background:var(--surface2,#1a2035);border-color:var(--accent,#3DD6C4);
  transform:translateY(-1px);
}
.srcbox-cadre:hover .src-txt b{color:var(--text,#E6EDF3)}

/* ══════════════════════════════════════════════════════════════════════
   LES LIEUX D'UNE POULE — fenêtre modale
   Ouverte depuis la rubrique « Terrains » de la colonne Liens utiles. Elle
   remplace la carte « Où ça se joue », qui occupait un tiers de la page de
   championnat pour une information qu'on consulte une fois par saison.
   ══════════════════════════════════════════════════════════════════════ */
/* C'est un <button>, pas un <a> : il faut lui rendre l'apparence d'une
   ligne de la liste (les boutons n'héritent ni la police ni l'alignement). */
.srcbox.act{width:100%;font-family:inherit;font-size:inherit;text-align:left;cursor:pointer}
.srcbox.act .src-go{color:var(--accent,#3DD6C4);font-weight:700}

.lx-mask{
  position:fixed;inset:0;z-index:200;display:grid;place-items:center;padding:20px;
  background:rgba(6,9,18,.72);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
}
.lx-win{
  width:min(860px,100%);max-height:86vh;display:flex;flex-direction:column;
  background:var(--surface,#141926);border:1px solid var(--border,#242c42);
  border-radius:16px;overflow:hidden;box-shadow:0 24px 60px rgba(0,0,0,.55);
}
.lx-top{
  display:flex;align-items:baseline;gap:10px;padding:14px 18px;
  border-bottom:1px solid var(--border,#242c42);
}
.lx-top b{font-family:'Outfit',sans-serif;font-size:1rem}
.lx-top span{color:var(--muted,#8B949E);font-size:.8rem}
.lx-close{
  margin-left:auto;background:none;border:0;color:var(--muted,#8B949E);
  font-size:1rem;cursor:pointer;padding:2px 6px;border-radius:6px;
}
.lx-close:hover{color:var(--text,#E6EDF3);background:rgba(var(--ink,255,255,255),.07)}

.lx-list{
  overflow:auto;padding:16px 18px;display:grid;gap:14px;
  grid-template-columns:repeat(auto-fill,minmax(250px,1fr));
  /* Les cartes étaient COUPÉES (description et « Itinéraire » tronqués) :
     la liste a une hauteur limitée par la fenêtre, et une carte en
     overflow:hidden n'a pas de hauteur minimale — la grille écrasait donc
     les rangées pour tout faire tenir, au lieu de laisser défiler. Des
     rangées à la hauteur du contenu rendent le défilement à la liste. */
  grid-auto-rows:max-content;align-content:start;
}
.lx-wait{grid-column:1/-1;color:var(--muted,#8B949E);font-size:.85rem;padding:18px 2px}

.lx{
  border:1px solid var(--border,#242c42);border-radius:12px;overflow:hidden;
  background:rgba(var(--ink,255,255,255),.02);display:flex;flex-direction:column;
}
/* L'en-tête porte la photo du lieu quand il y en a une, un aplat teinté par
   son nom sinon : deux gymnases ne se ressemblent jamais, même sans image. */
.lx-h{
  min-height:92px;padding:10px 12px;display:flex;flex-direction:column;
  justify-content:flex-end;gap:4px;position:relative;
}
.lx-n{font-family:'Outfit',sans-serif;font-weight:700;font-size:.92rem;color:#fff;
      text-shadow:0 1px 3px rgba(0,0,0,.6);line-height:1.2}
/* En-tête avec image : cliquable, l'image s'ouvre en entier (plan d'accès). */
.lx-h[data-zoom]{cursor:zoom-in}
.lx-h[data-zoom]:focus-visible{outline:2px solid var(--accent,#3DD6C4);outline-offset:-2px}
.lx-z{
  position:absolute;top:8px;right:8px;font-size:.66rem;font-weight:700;
  padding:3px 9px;border-radius:100px;background:rgba(10,15,30,.72);color:#fff;
}
.lx-h[data-zoom]:hover .lx-z{background:var(--accent,#3DD6C4);color:#0B1020}
/* Visionneuse : l'image entière, au-dessus de toutes les fenêtres. */
.lx-zm{
  position:fixed;inset:0;z-index:1100;display:grid;place-items:center;padding:16px;
  background:rgba(4,6,12,.9);cursor:zoom-out;
}
.lx-zm img{max-width:100%;max-height:100%;object-fit:contain;border-radius:10px;
           box-shadow:0 20px 50px rgba(0,0,0,.6)}
.lx-zm .lx-close{position:absolute;top:12px;right:12px;margin:0;font-size:1.3rem;color:#fff;
                 background:rgba(255,255,255,.12)}
/* Pastilles de l'en-tête : nombre de rencontres, puis le type de surface
   (`Place.info` — « Gymnase », « terrain synthétique »). Deux étiquettes
   courtes, pas des phrases. */
.lx-tags{display:flex;gap:5px;flex-wrap:wrap}
.lx-c{
  font-size:.64rem;font-weight:700;padding:2px 8px;
  border-radius:100px;background:rgba(10,15,30,.66);color:#fff;
}
.lx-s{background:rgba(61,214,196,.28)}
.lx-b{padding:11px 12px;display:flex;flex-direction:column;gap:7px;flex:1}
/* L'adresse en entier, sur autant de lignes qu'il faut : c'est elle qu'on
   recopie dans le GPS. */
.lx-a{font-size:.76rem;color:var(--muted,#8B949E);line-height:1.45;
      white-space:normal;overflow-wrap:anywhere}
.lx-d{white-space:pre-line;overflow-wrap:anywhere}
/* La description porte l'accès détaillé et les mises en garde (« à ne pas
   confondre avec l'UrbanSoccer voisin »). C'est le contenu qui justifie la
   fenêtre : on ne la tronque pas, la carte grandit. */
.lx-d{font-size:.76rem;color:var(--text,#E6EDF3);line-height:1.55}
.lx-x{display:flex;gap:6px;flex-wrap:wrap;margin-top:auto;padding-top:3px}
.lx-foot{
  padding:11px 18px;border-top:1px solid var(--border,#242c42);
  background:rgba(var(--ink,255,255,255),.02);font-size:.72rem;color:var(--muted,#8B949E);line-height:1.5;
}

/* Petite fenêtre d'actions (PLBUI.fenetre) : partager, nous écrire. */
.lx-win.sm{width:min(440px,100%)}
.fx-body{overflow:auto;padding:14px 18px;display:flex;flex-direction:column;gap:8px}
.fx-body p{font-size:.82rem;color:var(--muted,#8B949E);line-height:1.5;margin:0 0 4px}
.fx-pre{
  margin:0 0 6px;padding:10px 12px;max-height:180px;overflow:auto;
  font:.72rem/1.45 ui-monospace,Consolas,monospace;color:var(--text,#E6EDF3);
  background:rgba(var(--ink,255,255,255),.03);border:1px solid var(--border,#242c42);border-radius:10px;
  white-space:pre;
}
.fx-a{
  display:flex;align-items:center;gap:11px;width:100%;padding:10px 12px;
  background:rgba(var(--ink,255,255,255),.03);border:1px solid var(--border,#242c42);border-radius:10px;
  color:var(--text,#E6EDF3);font:inherit;font-size:.86rem;font-weight:600;
  text-decoration:none;text-align:left;cursor:pointer;transition:border-color .15s;
}
.fx-a:hover{border-color:var(--accent,#3DD6C4)}
.fx-i{font-size:1.05rem;width:1.4em;text-align:center;flex-shrink:0}

/* Fiche d'un seul lieu (PLBUI.ouvrirLieu) : la carte occupe la fenêtre. */
.lx-win.lieu .fx-body{padding:14px}
.lx-win.lieu .lx-h{min-height:120px}
.lx-win.lieu .lx-n{font-size:1.05rem}
.lx-win.lieu .lx-a,.lx-win.lieu .lx-d{font-size:.84rem}
.fx-body p.lx-none{font-size:.76rem;font-style:italic;margin:2px 0 0}

@media(max-width:560px){
  .lx-win.sm{height:auto;max-height:100vh;position:absolute;bottom:0;border-radius:16px 16px 0 0}
  .lx-mask{padding:0}
  .lx-win{max-height:100vh;height:100vh;border-radius:0;border:0}
  .lx-list{grid-template-columns:1fr}
}

/* ── CLASSEMENT PROCHE (PLBUI.extraitClassement) ───────────────────────
   Un tableau de 26 lignes, personne ne le lit. Ce qu'un capitaine veut
   savoir tient en trois choses : où je suis, qui je rattrape, qui me
   rattrape. Deux équipes au-dessus, deux en dessous, le leader s'il sort de
   la fenêtre. Page équipe (colonne latérale) et onglet Équipes d'Activité. */
.mini-st-w{min-width:0}
.mini-st{width:100%;border-collapse:collapse;font-size:.74rem}
.mini-st td{padding:.2rem .15rem;border-bottom:1px solid rgba(var(--ink,255,255,255),.04);vertical-align:middle}
.mini-st tr:last-child td{border-bottom:none}
/* Le rang est la DERNIÈRE colonne et la seule en chiffres : les matchs joués
   et les points ont quitté l'extrait, illisibles sans en-tête (Daniel, 26/09).
   `.n` prend tout le reste, donc les noms ne sont plus tronqués. */
.mini-st .r{width:1.6rem;text-align:right;color:var(--dim,#6e7681);
            font-variant-numeric:tabular-nums;font-weight:700}
/* La pastille se tronque d'elle-même (max-width:100% + ellipse du nom) :
   la cellule reste visible pour que le relief au survol ne soit pas rogné. */
.mini-st .n{max-width:0;width:100%;overflow:visible}
.mini-st .n .team-tag{font-size:12px}
.mini-st .n .team-tag .st-crest{width:18px;height:18px}
.mini-st tr.moi td{background:rgba(61,214,196,.10)}
.mini-st tr.moi .r{color:var(--teal,#3DD6C4)}
/* ⋮ : « il y a des équipes entre les deux ». */
.mini-st tr.gap td{padding:0;text-align:center;color:var(--dim,#6e7681);font-size:.6rem;line-height:.9}
.mini-gaps{
  margin-top:.45rem;padding-top:.4rem;border-top:1px solid var(--border);
  font-size:.68rem;color:var(--muted);line-height:1.45;
}
.mini-gaps b{color:var(--text);font-weight:600}

/* ══════════════════════════════════════════════════════════════════════
   ENCART DISCRET — « annonce » fondue, pas bannière
   Pas de cadre, pas de fond plein, pas de bouton : une capture de l'app
   estompée par le haut, une phrase, un lien. Il doit se lire comme une
   respiration de la page, pas comme une publicité. Règle de vie : UN SEUL
   visible à la fois par zone de défilement, et il ne s'affiche que quand
   le message a du sens pour qui regarde.
   ══════════════════════════════════════════════════════════════════════ */
.nudge{
  display:flex;flex-direction:column;align-items:flex-start;gap:.45rem;
  padding:.2rem .3rem .1rem;margin-top:.15rem;
}
/* La capture se fond dans le fond par le haut et les côtés : c'est ce qui
   évite l'effet vignette collée. `mask-image` est bien supporté ; si un
   navigateur l'ignore, il reste une image à faible opacité, pas un trou. */
.nudge img{
  width:100%;max-width:150px;height:auto;align-self:center;
  opacity:.62;border-radius:10px;
  -webkit-mask-image:linear-gradient(180deg,transparent 0%,#000 26%,#000 74%,transparent 100%);
          mask-image:linear-gradient(180deg,transparent 0%,#000 26%,#000 74%,transparent 100%);
}
.nudge p{
  font-size:.76rem;line-height:1.45;color:var(--text,#E6EDF3);margin:0;
}
.nudge a{
  font-size:.74rem;font-weight:600;color:var(--teal,#3DD6C4);text-decoration:none;
}
.nudge a:hover{text-decoration:underline}

/* Variante en ligne, pour un encart glissé entre deux cartes plutôt que
   dans une colonne : image à gauche, texte à droite. */
.nudge.inline{
  flex-direction:row;align-items:center;gap:.9rem;
  padding:.3rem .2rem;
}
.nudge.inline img{max-width:64px;align-self:center;opacity:.55;
  -webkit-mask-image:linear-gradient(90deg,transparent 0%,#000 30%,#000 100%);
          mask-image:linear-gradient(90deg,transparent 0%,#000 30%,#000 100%)}
.nudge.inline p{flex:1;min-width:0}

@media(max-width:700px){
  /* Sur téléphone la colonne passe sous le contenu : l'encart y serait tout
     en bas, sans valeur. On le réduit au texte, sans l'image. */
  .nudge img{display:none}
}

/* ══════════════════════════════════════════════════════════════════════
   SONDAGE (aperçu) — voir sondageDemo() dans ligue-ui.js
   Compact : il se glisse au-dessus de l'effectif, qui est long. Sur
   téléphone il doit tenir en quelques lignes, d'où des barres fines et
   pas de marges généreuses.
   ══════════════════════════════════════════════════════════════════════ */
.sd{display:flex;flex-direction:column;gap:.45rem}
.sd-h{display:flex;align-items:baseline;gap:.4rem}
.sd-t{
  font-size:.62rem;text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted,#8B949E);font-weight:600;
}
/* La pastille « aperçu » n'est pas décorative : c'est elle qui empêche de
   croire que le sondage est actif. Ne pas la retirer tant que la fonction
   n'est pas branchée. */
.sd-tag{
  font-size:.56rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  padding:1px 6px;border-radius:100px;
  background:rgba(227,179,65,.16);color:var(--draw,#e3b341);
}
.sd-q{font-size:.78rem;line-height:1.4;color:var(--text,#E6EDF3);font-weight:600}
.sd-l{list-style:none;display:flex;flex-direction:column;gap:.3rem;margin:.1rem 0 0}
/* Bouton radio, libellé, jauge, nombre. La jauge est ce qui fait comprendre
   la fonction : une liste de choix ne montre pas un dépouillement. Les
   nombres sont fictifs, la pastille « aperçu » et la note le disent.
   L'option est un <button> pleine largeur : on peut la cocher, et c'est ce
   qui fait comprendre la fonction sans une ligne d'explication. */
.sd-l li{list-style:none}
.sd-o{
  display:grid;grid-template-columns:auto 1fr 46px 1.4rem;align-items:center;gap:.45rem;
  width:100%;padding:.2rem .3rem;margin:0;border:0;border-radius:7px;
  background:transparent;font-family:inherit;text-align:left;cursor:pointer;
  transition:background .15s;
}
.sd-o:hover{background:color-mix(in srgb,var(--accent,#3DD6C4) 8%,transparent)}
/* Le rond : vide au repos, plein de l'accent une fois choisi. */
.sd-ra{
  width:13px;height:13px;border-radius:50%;flex:none;
  border:1.5px solid var(--border,#242c42);background:transparent;
  transition:border-color .15s,box-shadow .15s;
}
.sd-o:hover .sd-ra{border-color:var(--accent,#3DD6C4)}
.sd-o.on .sd-ra{
  border-color:var(--accent,#3DD6C4);
  box-shadow:inset 0 0 0 3px var(--accent,#3DD6C4);
}
.sd-o.on .sd-lab{color:var(--text,#E6EDF3);font-weight:600}
/* LA RÉPONSE RETENUE — dite par la seule mise en forme, jamais par une phrase
   (Daniel, 26/09). Jauge pleine à l'accent, libellé et nombre en avant : à une
   voix d'écart, c'est ce contraste qui fait comprendre qui l'a emporté.
   Pas de coche ni de couronne : le rond reste libre pour le choix du visiteur,
   sinon on confondrait « ce qui a gagné » et « ce que j'ai voté ». */
.sd-o.win .sd-lab{color:var(--text,#E6EDF3);font-weight:700}
.sd-o.win .sd-bar i{background:var(--accent,#3DD6C4)}
.sd-o.win .sd-n{color:var(--accent,#3DD6C4);font-weight:700}
.sd-lab{font-size:.72rem;color:var(--muted,#8B949E);overflow:hidden;
        text-overflow:ellipsis;white-space:nowrap;transition:color .15s}
.sd-bar{height:5px;border-radius:3px;background:rgba(var(--ink,255,255,255),.07);overflow:hidden}
.sd-bar i{display:block;height:100%;border-radius:3px;
          background:color-mix(in srgb,var(--accent,#3DD6C4) 70%,transparent)}
.sd-n{font-size:.68rem;color:var(--dim,#5B6478);text-align:right;
      font-variant-numeric:tabular-nums}
/* Le total : c'est lui qui donne son sens aux barres (« 22 réponses » sur 24
   équipes se comprend, « 13 » tout seul ne dit rien). */
.sd-c{font-size:.63rem;color:var(--dim,#5B6478);font-variant-numeric:tabular-nums}
.sd-f{font-size:.65rem;color:var(--dim,#5B6478);line-height:1.4}
/* Le bouton DOIT avoir l'air cliquable : bordure pleine à l'accent, texte à
   l'accent, curseur main, et un état de survol. Il était en pointillés gris et
   `disabled` — ça se lisait comme un bouton cassé (Daniel, 26/09).
   Il répond : au clic il passe en `.done` et dit que la fonction arrive.
   Voir l'écouteur délégué en bas de ligue-ui.js. */
.sd-btn{
  align-self:flex-start;font-family:inherit;font-size:.72rem;font-weight:700;
  padding:.36rem .8rem;border-radius:100px;cursor:pointer;
  color:var(--accent,#3DD6C4);
  background:color-mix(in srgb,var(--accent,#3DD6C4) 12%,transparent);
  border:1px solid color-mix(in srgb,var(--accent,#3DD6C4) 45%,transparent);
  transition:background .15s,border-color .15s,transform .15s;
}
.sd-btn:hover{
  background:color-mix(in srgb,var(--accent,#3DD6C4) 22%,transparent);
  border-color:var(--accent,#3DD6C4);
}
.sd-btn:active{transform:translateY(1px)}
/* Après le clic : le message remplace le libellé, et le bouton s'éteint —
   il n'y a rien de plus à en tirer pour l'instant. */
.sd-btn.done{
  cursor:default;font-weight:600;color:var(--muted,#8B949E);
  background:rgba(var(--ink,255,255,255),.04);border-color:var(--border,#242c42);
  border-style:dashed;
}
.sd-btn.done:hover{background:rgba(var(--ink,255,255,255),.04);border-color:var(--border,#242c42)}

/* ══════════════════════════════════════════════════════════════════════
   COUPE — le modèle « tableau », en face du modèle « classement »
   Rendu par PLBCOUPE.carte() (coupes.js). Ici et pas dans la page : la
   page équipe affichera le même tableau le jour où une équipe a un
   parcours en coupe.
   ══════════════════════════════════════════════════════════════════════ */
.cp{padding:18px 20px 22px;display:flex;flex-direction:column;gap:20px}

/* Les tableaux côte à côte quand la place le permet : c'est la comparaison
   qui fait comprendre la cascade — on voit que le second commence après. */
.cp-blocs{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}
.cp-bloc{
  padding:14px 16px;border-radius:12px;
  border:1px solid var(--border,#242c42);background:rgba(var(--ink,255,255,255),.02);
}
/* La consolante se distingue sans crier : un liseré, pas une autre couleur
   de fond. Ce n'est pas un trophée de second rang, c'est un autre chemin. */
.cp-conso{box-shadow:inset 3px 0 0 color-mix(in srgb,var(--accent,#3DD6C4) 40%,transparent)}
.cp-t{
  font-family:'Outfit',sans-serif;font-size:1rem;font-weight:800;
  color:var(--text);display:flex;align-items:center;gap:8px;
}
.cp-badge{
  font-size:.56rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  padding:2px 7px;border-radius:100px;
  background:rgba(227,179,65,.16);color:var(--draw,#e3b341);
}
.cp-from{margin-top:5px;font-size:.72rem;color:var(--accent,#3DD6C4)}
.cp-from b{font-weight:700}
.cp-r{margin-top:7px;font-size:.78rem;color:var(--muted);line-height:1.5}

/* L'échelle des tours. `su` = on connaît la date ; sans elle, le tour existe
   mais ne peut pas encore être daté — et le dire vaut mieux que l'omettre. */
.cp-steps{list-style:none;margin-top:12px;display:flex;flex-direction:column;gap:6px}
.cp-step{
  display:flex;justify-content:space-between;align-items:baseline;gap:10px;
  padding:6px 9px;border-radius:8px;background:rgba(var(--ink,255,255,255),.03);
  font-size:.74rem;color:var(--dim,#5B6478);
}
.cp-step b{font-weight:600;color:var(--muted)}
.cp-step i{font-style:normal;text-align:right}
.cp-step.su{background:color-mix(in srgb,var(--accent,#3DD6C4) 9%,transparent)}
.cp-step.su b{color:var(--text)}
.cp-step.su i{color:var(--accent,#3DD6C4);font-weight:600}
/* Une rencontre déjà connue du tour : sa propre ligne, sous le nom du tour. */
.cp-step{flex-wrap:wrap}
.cp-mt{flex-basis:100%;font-size:.72rem;color:var(--text);line-height:1.45}
.cp-mt a{color:inherit;font-weight:600;text-decoration:none}
.cp-mt a:hover{text-decoration:underline}
/* Intertitre du calendrier de la coupe : le tour, au-dessus de ses rencontres. */
.cp-tour-lbl{padding:.6rem 1rem .2rem;font-size:.7rem;font-weight:600;color:var(--muted);
  letter-spacing:.02em}
.cp-aff{cursor:pointer;border-bottom:1px dotted currentColor}
.cp-aff:hover{color:var(--accent,#3DD6C4)}

/* L'arbre d'illustration. Trois colonnes qui convergent ; les cases sont
   vides parce que le tirage n'a pas eu lieu, et la légende le dit. */
/* Le schéma et sa légende forment un tout : ce conteneur les garde collés,
   au lieu de laisser le `gap` de `.cp` (20 px) les séparer comme deux blocs
   indépendants. La légende doit se lire comme la note du schéma. */
.cp-apercu{display:flex;flex-direction:column}
.cp-fmt h4{
  font-family:'Outfit',sans-serif;font-size:.78rem;font-weight:700;
  text-transform:uppercase;letter-spacing:.05em;color:var(--muted);
  display:flex;align-items:center;gap:8px;margin-bottom:10px;
}
/* ── L'ARBRE, EN GRILLE À POSITIONS EXPLICITES ─────────────────────────
   Trois colonnes de rencontres, deux colonnes de LIAISONS entre elles. Sans
   les traits, trois colonnes de cases ne sont qu'un tableau : ce qui fait
   comprendre une coupe, c'est de voir deux rencontres se rejoindre.

   POURQUOI DES POSITIONS EXPLICITES, ET PAS DES COLONNES EN FLEX
   Pour qu'un trait tombe pile sur le milieu d'une case, il faut que la grille
   connaisse ce milieu. D'où 8 rangées d'unité sous la rangée des titres : une
   rencontre de quart occupe 2 rangées, donc son centre tombe sur une LIGNE de
   la grille, et la liaison n'a plus qu'à s'accrocher à ces lignes-là.
     quarts   : 2-4, 4-6, 6-8, 8-10   → centres sur les lignes 3, 5, 7, 9
     liaisons : 3-5 et 7-9            → milieux sur 4 et 8
     demies   : 3-5 et 7-9            → centres sur 4 et 8, donc alignées
     liaison  : 4-8                   → milieu sur 6
     finale   : 5-7                   → centre sur 6
   Aucun calcul en JavaScript, aucune mesure : la grille aligne toute seule,
   et ça reste vrai quelle que soit la hauteur des cases.
   `column-gap` est à zéro à dessein : le trait doit TOUCHER la case, un
   espace entre les deux casserait la lecture du schéma. */
/* La hauteur de la rangée d'unité fixe TOUT l'espacement du schéma : une case
   de quart en occupe deux, donc l'air entre deux quarts vaut deux rangées moins
   la hauteur d'une case. À 23 px les quarts se touchaient (Daniel, 26/09) ; à
   36 px ils respirent, et le schéma fait ~300 px de haut — c'est la partie la
   plus regardée de la carte, elle mérite la place. */
.cp-tab{
  display:grid;
  grid-template-columns:minmax(0,1fr) 26px minmax(0,1fr) 26px minmax(0,1fr);
  grid-template-rows:auto repeat(8,minmax(36px,1fr));
  column-gap:0;row-gap:0;
}
.cp-rd{
  font-size:.62rem;text-transform:uppercase;letter-spacing:.05em;
  color:var(--dim,#5B6478);font-weight:700;text-align:center;
  align-self:end;padding-bottom:8px;
}
.cp-rd1{grid-column:1;grid-row:1}
.cp-rd2{grid-column:3;grid-row:1}
.cp-rd3{grid-column:5;grid-row:1}

.cp-m{
  display:flex;flex-direction:column;gap:3px;padding:7px 10px;border-radius:9px;
  border:1px dashed var(--border,#242c42);background:var(--surface,#0f1424);
  align-self:center;
}
.cp-s{font-size:.66rem;color:var(--dim,#5B6478);font-style:italic;
      overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cp-q1{grid-column:1;grid-row:2/4}
.cp-q2{grid-column:1;grid-row:4/6}
.cp-q3{grid-column:1;grid-row:6/8}
.cp-q4{grid-column:1;grid-row:8/10}
.cp-d1{grid-column:3;grid-row:3/5}
.cp-d2{grid-column:3;grid-row:7/9}
/* La finale est la seule case pleine : c'est là qu'on veut arriver. */
.cp-fi{
  grid-column:5;grid-row:5/7;border-style:solid;
  border-color:color-mix(in srgb,var(--accent,#3DD6C4) 45%,transparent);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--accent,#3DD6C4) 8%,transparent);
}

/* La liaison : un « ⊐ » qui part du milieu des deux cases de gauche, se
   referme, et repart d'un trait vers la case suivante, pointe en avant. */
.cp-y{
  position:relative;margin-right:9px;box-sizing:border-box;
  border:2px solid color-mix(in srgb,var(--accent,#3DD6C4) 32%,transparent);
  border-left:none;border-radius:0 9px 9px 0;
}
.cp-y::after{
  content:'';position:absolute;top:50%;left:100%;width:9px;height:0;
  border-top:2px solid color-mix(in srgb,var(--accent,#3DD6C4) 32%,transparent);
  transform:translateY(-1px);
}
.cp-y::before{
  content:'';position:absolute;top:50%;left:100%;
  transform:translate(4px,-50%);
  border:4px solid transparent;
  border-left-color:color-mix(in srgb,var(--accent,#3DD6C4) 55%,transparent);
}
.cp-yA{grid-column:2;grid-row:3/5}
.cp-yB{grid-column:2;grid-row:7/9}
.cp-yC{grid-column:4;grid-row:4/8}

/* Le VRAI tableau (coupes.js → arbreReel) : 32 cases au premier tour, donc
   des cases serrées. Positions et rangées posées par le script (calculées) ;
   ici, seulement l'allure. */
.cp-tab-reel .cp-m{padding:3px 7px;gap:1px;border-radius:7px;margin:1px 0}
.cp-tab-reel .cp-y{margin-right:6px}
.cp-rd-d{display:block;margin-top:2px;font-size:.6rem;font-weight:600;text-transform:none;
         letter-spacing:0;color:var(--accent,#3DD6C4)}
.cp-reel{border-style:solid;cursor:pointer}
.cp-reel:hover{border-color:color-mix(in srgb,var(--accent,#3DD6C4) 55%,transparent)}
.cp-reel .cp-e{font-style:normal;color:var(--text);font-size:.64rem}
.cp-reel .cp-g{font-weight:700}
/* Les pastilles d'équipe (tagEquipe) en format tableau : 32 cases serrées. */
.cp-reel .team-tag{font-size:11px;padding:1px 8px 1px 1px;align-self:flex-start}
.cp-reel .team-tag .st-crest{width:15px;height:15px;margin-right:5px;font-size:.42rem}

.cp-legend{margin-top:9px;font-size:.66rem;color:var(--dim,#5B6478);line-height:1.5}

.cp-fmt ul{list-style:none;display:flex;flex-direction:column;gap:7px}
.cp-fmt li{font-size:.76rem;color:var(--muted);line-height:1.5;padding-left:14px;position:relative}
.cp-fmt li::before{content:'·';position:absolute;left:4px;color:var(--dim,#5B6478)}
.cp-fmt li b{color:var(--text);font-weight:600}

@media(max-width:560px){
  /* Un arbre à trois colonnes ne tient pas sur un téléphone : cinq colonnes
     donneraient des cases de 40 px. On repasse en simple colonne, tour par
     tour — et les liaisons disparaissent, parce qu'un trait qui ne relie plus
     rien de visible n'explique plus rien. C'est ici que l'ordre du DOM
     reprend la main : titre, ses rencontres, titre suivant… */
  .cp-tab{display:flex;flex-direction:column;gap:6px}
  .cp-y{display:none}
  .cp-rd{text-align:left;align-self:auto;padding:8px 0 2px}
  .cp-m{align-self:auto}
  /* En colonne, 24 cases « À tirer » ne seraient que du bruit : le titre du
     tour suffit à dire qu'il vient après. */
  .cp-tab-reel .cp-vide{display:none}
  .cp{padding:14px 14px 18px}
}

/* ══════════════════════════════════════════════════════════════════════
   MARCHE À SUIVRE — récupérer une équipe pas encore sur PasseLaBalle
   Rendu par PLBUI.troisEtapes(). Ici et pas dans une page : la page équipe
   l'affiche en clair, la page championnat l'ouvre en fenêtre.
   Remplace l'ancien champ de code, qui exigeait d'être connecté — un
   cul-de-sac pour exactement le public visé par le mailing.
   ══════════════════════════════════════════════════════════════════════ */
.howto{padding:.9rem 1.1rem}
.howto ol{margin:.5rem 0 0;padding-left:1.15rem;display:flex;flex-direction:column;gap:.42rem}
.howto li{font-size:.84rem;line-height:1.45}
.howto .code-here{
  display:inline-block;font-family:'Outfit',sans-serif;font-weight:700;
  letter-spacing:.1em;padding:.1rem .45rem;border-radius:6px;
  background:color-mix(in srgb,var(--accent,#3DD6C4) 16%,transparent);
  color:var(--accent,#3DD6C4);
}
.howto .ht-note{font-size:.72rem;color:var(--dim,#5B6478);margin-top:.7rem;line-height:1.45}
/* Les trois badges, DANS l'étape 1. Sur leur propre ligne : à la suite du
   texte ils auraient coupé la phrase en deux. */
.howto .ht-stores{display:block;margin-top:.45rem}
/* En fenêtre, `.fx-body` porte déjà le rembourrage : le doubler décalerait
   tout le texte vers l'intérieur. */
.howto.pop{padding:0}

/* ══════════════════════════════════════════════════════════════════════
   L'AFFICHE DU MATCH (PLBUI.afficheMatch) — façon soir de combat.
   Deux moitiés aux couleurs de chaque club, coupées en biais, un éclair
   au milieu. Toutes les teintes viennent des écussons (--ha/--hb, posées
   par le JS depuis hueFor/hue2For) : rien n'est écrit en dur pour un club.
   z-index 1050 : au-dessus des fenêtres de page (détail « Joués »
   d'Activité, 1000). La fiche d'un lieu, ouverte DEPUIS l'affiche, passe
   devant (règle `.vsx-mask ~ .lx-mask`).
   ══════════════════════════════════════════════════════════════════════ */
.vsx-mask{
  position:fixed;inset:0;z-index:1050;display:flex;padding:22px 16px;overflow-y:auto;
  overscroll-behavior:contain;
  background:rgba(4,6,14,.8);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);
}
.vsx{
  position:relative;margin:auto;width:min(520px,100%);flex-shrink:0;
  border-radius:18px;overflow:hidden;background:var(--surface,#141926);
  border:1px solid rgba(var(--ink,255,255,255),.1);box-shadow:0 30px 80px rgba(0,0,0,.6);
  animation:vsx-in .45s cubic-bezier(.2,.9,.3,1.15);
}
@keyframes vsx-in{from{opacity:0;transform:scale(.9) translateY(14px)}to{opacity:1;transform:none}}
.vsx-close{
  position:absolute;top:10px;right:10px;z-index:5;width:32px;height:32px;border-radius:50%;
  border:1px solid rgba(255,255,255,.25);background:rgba(10,15,30,.55);color:#fff;cursor:pointer;font-size:.9rem;
}
.vsx-close:hover{background:rgba(10,15,30,.85)}

/* La scène : deux moitiés en biais, chacune dans ses deux couleurs. */
.vsx-stage{position:relative;padding:16px 14px 14px;isolation:isolate;color:#fff}
.vsx-stage::before,.vsx-stage::after{content:"";position:absolute;inset:0;z-index:-2}
.vsx-stage::before{
  background:linear-gradient(180deg,transparent 45%,rgba(0,0,0,.38)),
             linear-gradient(135deg,hsl(var(--ha) 70% 46%),hsl(var(--ha2) 60% 22%));
  clip-path:polygon(0 0,58% 0,42% 100%,0 100%);
}
.vsx-stage::after{
  background:linear-gradient(180deg,transparent 45%,rgba(0,0,0,.38)),
             linear-gradient(225deg,hsl(var(--hb) 70% 46%),hsl(var(--hb2) 60% 22%));
  clip-path:polygon(58% 0,100% 0,100% 100%,42% 100%);
}
/* L'éclair : le trait lumineux sur la coupure, et un voile sombre en bas
   pour que les noms se lisent sur n'importe quelles couleurs. */
.vsx-duel::before{
  content:"";position:absolute;left:50%;top:-40%;bottom:-40%;width:3px;z-index:-1;
  transform:translateX(-50%) rotate(9deg);
  background:linear-gradient(transparent,#fff6c8 30%,#fff 50%,#fff6c8 70%,transparent);
  box-shadow:0 0 14px 3px rgba(255,236,160,.75);opacity:.9;
}
.vsx-stage > *{position:relative}

.vsx-top{display:flex;flex-direction:column;align-items:center;gap:1px;margin:0 36px 14px;text-align:center}
.vsx-top b{font:800 .72rem/1.2 'Outfit',sans-serif;letter-spacing:.2em;text-transform:uppercase;
           padding:.2rem .7rem;border-radius:100px;background:rgba(0,0,0,.35);border:1px solid rgba(255,255,255,.2)}
.vsx-top span{font-size:.7rem;opacity:.85;margin-top:4px;text-shadow:0 1px 2px rgba(0,0,0,.5)}

.vsx-duel{position:relative;display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);
          align-items:center;gap:8px}
.vsx-side{display:flex;flex-direction:column;align-items:center;gap:8px;min-width:0;text-align:center}
.vsx-crest{
  position:relative;width:92px;height:92px;border-radius:50%;overflow:hidden;flex-shrink:0;
  display:grid;place-items:center;
  background:linear-gradient(135deg,hsl(var(--h) 65% 55%),hsl(var(--h2) 58% 30%));
  border:3px solid rgba(255,255,255,.9);
  box-shadow:0 0 0 3px rgba(0,0,0,.25),0 10px 26px rgba(0,0,0,.45);
  animation:vsx-g .5s .1s both cubic-bezier(.2,.9,.3,1.3);
}
.vsx-side:last-child .vsx-crest{animation-name:vsx-d}
@keyframes vsx-g{from{transform:translateX(-40px) scale(.7);opacity:0}}
@keyframes vsx-d{from{transform:translateX(40px) scale(.7);opacity:0}}
.vsx-crest img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;background:#fff}
.vsx-ini{font:900 1.9rem/1 'Outfit',sans-serif;color:#fff;text-shadow:0 2px 4px rgba(0,0,0,.35)}
.vsx-nm{
  display:block;max-width:100%;font:900 1rem/1.1 'Outfit',sans-serif;text-transform:uppercase;
  letter-spacing:.02em;color:#fff;text-shadow:0 2px 6px rgba(0,0,0,.6);
  overflow-wrap:anywhere;
}
.vsx-link{color:inherit;text-decoration:none;max-width:100%}
.vsx-link:hover .vsx-nm{text-decoration:underline}
.vsx-side.lose{opacity:.62}
.vsx-side.win .vsx-crest{box-shadow:0 0 0 3px #ffd86b,0 0 24px 4px rgba(255,216,107,.55),0 10px 26px rgba(0,0,0,.45)}

.vsx-vs{
  font:900 italic 2.6rem/1 'Outfit',sans-serif;letter-spacing:-.02em;color:#fff;
  text-shadow:0 0 18px rgba(255,236,160,.8),0 3px 0 rgba(0,0,0,.35);
  animation:vsx-pulse 2.2s ease-in-out infinite;
}
@keyframes vsx-pulse{50%{transform:scale(1.08);text-shadow:0 0 28px rgba(255,236,160,1),0 3px 0 rgba(0,0,0,.35)}}
.vsx-score{
  font:900 2.3rem/1 'Outfit',sans-serif;font-variant-numeric:tabular-nums;white-space:nowrap;
  padding:.35rem .7rem;border-radius:14px;background:rgba(0,0,0,.5);
  border:1px solid rgba(255,255,255,.25);box-shadow:0 8px 20px rgba(0,0,0,.4);
}
.vsx-score i{font-style:normal;opacity:.6;margin:0 .1em}
.vsx-bas{display:flex;justify-content:center;margin-top:10px}
.vsx-verdict,.vsx-compte{
  font:800 .74rem/1 'Outfit',sans-serif;letter-spacing:.16em;text-transform:uppercase;
  padding:.4rem .9rem;border-radius:100px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.25);
}
.vsx-verdict.v{background:var(--win,#2ea043);border-color:transparent}
.vsx-verdict.d{background:var(--loss,#f85149);border-color:transparent}
.vsx-verdict.n{background:var(--draw,#d29922);color:#000;border-color:transparent}
/* La signature, en bas de la scène : discrète, mais lisible sur une capture. */
.vsx-sign{
  display:block;width:max-content;margin:12px auto 0;
  font:700 .66rem/1 'Outfit',sans-serif;letter-spacing:.18em;text-transform:uppercase;
  color:rgba(255,255,255,.72);text-decoration:none;text-shadow:0 1px 3px rgba(0,0,0,.6);
}
.vsx-sign:hover{color:#fff}

/* Le pratique, sous l'affiche. */
.vsx-info{padding:8px 10px 10px;display:flex;flex-direction:column;gap:5px}
.vsx-l{display:flex;align-items:center;gap:9px;padding:5px 9px;border-radius:10px;
       background:var(--surface2,#1a2035);border:1px solid var(--border,#242c42);font-size:.84rem}
.vsx-l > span{flex:none;display:grid;place-items:center;min-width:28px}
.vsx-l b{display:block;font-weight:600;color:var(--text,#E6EDF3)}
.vsx-l b::first-letter{text-transform:uppercase}
.vsx-l small{display:block;color:var(--muted,#8B949E);font-size:.74rem;line-height:1.35}
.vsx-i{font-size:1.05rem}
/* Le terrain : TOUT le bloc est le bouton (ouvre la fiche du lieu). */
button.vsx-lieu{width:100%;font:inherit;text-align:left;cursor:pointer;color:inherit;
                transition:border-color .15s,background .15s}
button.vsx-lieu > div{flex:1;min-width:0}
button.vsx-lieu .lieu-ico{width:28px;height:28px}
button.vsx-lieu .lieu-ico svg{width:13px;height:13px}
.vsx-go{flex:none;font-size:1.4rem;line-height:1;color:var(--muted,#8B949E);padding-left:4px}
button.vsx-lieu:hover,button.vsx-lieu:focus-visible{border-color:#4C8DF6;background:rgba(66,133,244,.08);outline:none}
button.vsx-lieu:hover .vsx-go,button.vsx-lieu:focus-visible .vsx-go{color:#4C8DF6}
@media (max-width:420px){
  .vsx-crest{width:72px;height:72px}
  .vsx-ini{font-size:1.5rem}
  .vsx-nm{font-size:.86rem}
  .vsx-vs{font-size:2rem}
  .vsx-score{font-size:1.8rem;padding:.3rem .5rem}
}
@media (prefers-reduced-motion:reduce){
  .vsx,.vsx-crest,.vsx-vs{animation:none}
}

.vsx-mask ~ .lx-mask{z-index:1060}

/* Une ligne de calendrier ouvre l'affiche (feuille-match.js). */
.mrow[data-fx],.mrow[data-ev],.mrow[data-cp],.mrow[data-st]{cursor:pointer}
.mrow[data-fx]:hover,.mrow[data-ev]:hover,.mrow[data-cp]:hover,.mrow[data-st]:hover{background:color-mix(in srgb,var(--teal,#3DD6C4) 6%,transparent)}
/* Le signe qu'elle s'ouvre, sans bouton en plus (Daniel, 05/10 : « sur
   mobile je n'ai pas de place ») : un › à la couleur du site collé au
   score / à l'heure / au VS — la case existe déjà, aucune colonne ajoutée.
   Il s'avive et avance d'un cran au survol. */
.mrow[data-fx] .sc::after,.mrow[data-ev] .sc::after,.mrow[data-cp] .sc::after,.mrow[data-st] .sc::after{
  content:"›";display:inline-block;margin-left:5px;font-weight:900;font-size:1.05em;line-height:1;
  color:var(--teal,#3DD6C4);opacity:.6;transition:transform .15s,opacity .15s}
.mrow[data-fx]:hover .sc::after,.mrow[data-ev]:hover .sc::after,
.mrow[data-cp]:hover .sc::after,.mrow[data-st]:hover .sc::after{opacity:1;transform:translateX(2px)}
:root[data-theme="light"] .mrow .sc::after{color:#0f8f82}

/* Partager l'affiche : un vrai bouton, plein, sous le pratique. */
.vsx-share{
  display:flex;align-items:center;justify-content:center;gap:8px;width:100%;margin-top:2px;
  padding:9px 12px;border-radius:10px;border:none;cursor:pointer;
  font:800 .86rem/1 'Outfit',sans-serif;letter-spacing:.02em;
  color:#0b1220;background:linear-gradient(135deg,#3DD6C4,#4C8DF6);
  box-shadow:0 4px 14px rgba(61,214,196,.25);transition:filter .15s,transform .15s}
.vsx-share:hover{filter:brightness(1.08)}
.vsx-share:active{transform:scale(.98)}
.vsx-share:disabled{opacity:.7;cursor:progress}
/* L'aperçu de l'image dans la fenêtre de partage (PC). */
.fx-affiche{display:block;width:100%;max-width:280px;margin:0 auto 10px;border-radius:12px;
  box-shadow:0 8px 24px rgba(0,0,0,.4)}

/* Le temps du chargement : le décor, écussons vides qui respirent. */
.vsx-wait .vsx-stage::before,.vsx-wait .vsx-stage::after{background:linear-gradient(135deg,#2a3350,#161c2e)}
.vsx-wait .vsx-crest{background:rgba(255,255,255,.08);animation:vsx-attente 1s ease-in-out infinite alternate}
@keyframes vsx-attente{from{opacity:.45}to{opacity:1}}

/* Sous chaque nom : la place au classement actuel, et la forme. */
.vsx-st{display:flex;flex-direction:column;align-items:center;gap:5px}
.vsx-rang{
  font:700 .7rem/1 'Outfit',sans-serif;letter-spacing:.02em;white-space:nowrap;
  padding:.28rem .55rem;border-radius:100px;background:rgba(0,0,0,.4);border:1px solid rgba(255,255,255,.2);
}
.vsx-rang sup{font-size:.62em;margin-left:1px}
.vsx-rang small{font-size:.9em;opacity:.65;margin-left:1px}
.vsx-forme{display:inline-flex;gap:3px}
.vsx-forme i{
  width:17px;height:17px;border-radius:4px;display:grid;place-items:center;font:800 .6rem/1 'Outfit',sans-serif;
  font-style:normal;box-shadow:0 1px 3px rgba(0,0,0,.35);
}
.vsx-forme i.V{background:var(--win,#2ea043);color:#fff}
.vsx-forme i.N{background:var(--draw,#d29922);color:#000}
.vsx-forme i.D{background:var(--loss,#f85149);color:#fff}

/* Rendez-vous et coup d'envoi : deux pastilles sous le jour, sur la même
   ligne — le RDV en avant, aux couleurs des deux clubs (c'est l'heure à
   laquelle il faut être là). Compact : l'affiche du haut passe avant. */
.vsx-heures{display:flex;flex-wrap:wrap;gap:5px;margin-top:4px}
.vsx-h{
  display:inline-flex;align-items:baseline;gap:5px;padding:2px 8px;border-radius:100px;
  font:800 .86rem/1.3 'Outfit',sans-serif;font-variant-numeric:tabular-nums;color:var(--text,#E6EDF3);
  background:rgba(var(--ink,255,255,255),.06);border:1px solid var(--border,#242c42);
}
.vsx-h small{font:700 .58rem/1 'Outfit',sans-serif;letter-spacing:.1em;text-transform:uppercase;color:var(--muted,#8B949E)}
.vsx-h.rdv{
  color:#fff;border-color:transparent;
  background:linear-gradient(135deg,hsl(var(--ha) 60% 40% / .7),hsl(var(--hb) 60% 40% / .7));
}
.vsx-h.rdv small{color:rgba(255,255,255,.85)}

/* Le mot laissé sur le match. */
.vsx-note{
  display:flex;gap:9px;align-items:flex-start;padding:6px 9px;border-radius:10px;font-size:.82rem;
  background:color-mix(in srgb,var(--draw,#d29922) 12%,transparent);
  border:1px solid color-mix(in srgb,var(--draw,#d29922) 40%,transparent);
}
.vsx-note p{margin:0;line-height:1.45;color:var(--text,#E6EDF3)}
.vsx-note p + p{margin-top:4px}

/* Une section sous l'affiche (la feuille de match). */
.vsx-sec{padding:0 10px 10px;border-top:1px solid var(--border,#242c42)}
.vsx-sec-t{
  display:flex;align-items:center;gap:10px;margin:8px 0 6px;
  font:800 .64rem/1 'Outfit',sans-serif;letter-spacing:.2em;text-transform:uppercase;color:var(--muted,#8B949E);
}
.vsx-sec-t::before,.vsx-sec-t::after{content:"";flex:1;height:1px;background:var(--border,#242c42)}

/* ══════════════════════════════════════════════════════════════════════
   MODE CLAIR — <html data-theme="light"> (theme-mode.js)
   Le sombre ne passe par aucune de ces règles : il reste tel quel. Ici,
   seulement ce qui ne se règle pas par une variable de palette.
   ══════════════════════════════════════════════════════════════════════ */
:root[data-theme="light"]{
  /* Texte posé sur un fond TEINTÉ (survol, sélection) : blanc en sombre,
     où la teinte est mêlée au fond sombre ; encre en clair, où elle est
     mêlée au blanc et devient pâle. */
  --tint-fg:var(--text,#0F1420);
}
/* Les teintes du club (--ch/--ch2, posées par teamCard/bannerHtml) en tons
   PÂLES : un dégradé sombre sous un nom en encre foncée serait illisible.
   `!important` car les tons sombres sont en style inline ; filtré sur
   [style*="--ch:"] pour ne rien casser là où une page pose ses propres
   --c-d / --tb-d sans les teintes. */
:root[data-theme="light"] .tcard[style*="--ch:"]{
  --c-d:hsl(var(--ch) 62% 86%) !important;
  --c-d2:hsl(var(--ch2) 52% 91%) !important;
}
:root[data-theme="light"] .team-banner[style*="--ch:"]{
  --tb-d:hsl(var(--ch) 60% 84%) !important;
  --tb-d2:hsl(var(--ch2) 50% 91%) !important;
}
:root[data-theme="light"] .tb-chip{background:rgba(255,255,255,.72)}
:root[data-theme="light"] .team-tag{
  --tg-a:hsl(var(--th,200) 50% 46%);
  --tg-d:hsl(var(--th,200) 55% 84%);
}
/* Jauge d'une équipe qui démarre : le nom est blanc et court sur la piste
   vide — en clair la piste reste donc sombre (ardoise), sinon le nom
   disparaîtrait sur du blanc. */
:root[data-theme="light"] .team-tag.plb-part{--tag-track:#3B4457}
/* Pastilles de forme / verdict : en clair, vert, jaune et rouge sont
   assombris (theme.css) — le texte foncé n'y tient plus, il passe en blanc. */
:root[data-theme="light"] .fm,
:root[data-theme="light"] .tb-p.n,
:root[data-theme="light"] .vsx-forme i.N,
:root[data-theme="light"] .vsx-verdict.n{color:#fff}
:root[data-theme="light"] .go-maps span{color:#1A73E8}
:root[data-theme="light"] .lieu-ico,
:root[data-theme="light"] .go-maps{color:#1A73E8}
/* Voiles des fenêtres : plus légers sur une page claire. Les ombres portées
   aussi. */
:root[data-theme="light"] .lx-mask{background:rgba(15,20,32,.42)}
:root[data-theme="light"] .vsx-mask{background:rgba(15,20,32,.55)}
:root[data-theme="light"] .lx-win{box-shadow:0 24px 60px rgba(15,20,32,.22)}
:root[data-theme="light"] .lieu-btn:hover,
:root[data-theme="light"] .lieu-btn:focus-visible,
:root[data-theme="light"] .go-maps:hover{box-shadow:0 3px 10px rgba(15,20,32,.14)}
@media(max-width:720px){
  :root[data-theme="light"] table.standings th:nth-child(2),
  :root[data-theme="light"] table.standings td.tn{box-shadow:6px 0 8px -6px rgba(15,20,32,.22)}
  :root[data-theme="light"] table.standings th:last-child,
  :root[data-theme="light"] table.standings td.pt{box-shadow:-6px 0 8px -6px rgba(15,20,32,.22)}
}
