/*
 * Chess Club -- couche graphique MOBILE (espace membre / application).
 *
 * Parti pris (cf. docs/reference/STRATEGIE-ESPACE-MEMBRE.md sec.6) : mobile-first,
 * tuiles larges, typo genereuse, aplats contrastes "a plat".
 *
 * IDENTITE = couleurs OFFICIELLES du club (logo LOE-2021, lion blanc sur damier) :
 *   bleu  #5266A4 (rgb 82,102,164)   -- en-tetes, navigation (comme le site)
 *   rouge #E3352C (rgb 227,53,44)    -- accent, premium/adherents, incitation
 *   blanc #FFFFFF                    -- le lion ; surfaces
 *
 * N1 (LOT-APP-NAV) -- Tokens & themes :
 *   Toute couleur passe par un TOKEN semantique (--app-*). Deux jeux : clair (:root)
 *   et sombre ([data-theme="dark"], indicatif SPEC-REFONTE-NAVIGATION-APP.md sec.9).
 *   Roles de marque SEPARES : --app-blue (accent : liens, actif, icones) est distinct
 *   des fonds structurants --app-bar-bg / --app-primary / --app-hero-bg, ce qui rend
 *   le sombre coherent (un fond ne s'eclaircit pas comme un accent).
 *   Taille de texte reglable : --app-fs (multiplicateur, defaut 1 ; 3 crans en N1c) ;
 *   toute typo est exprimee en calc(px * var(--app-fs)).
 *   Lisibilite (sec.8) : le texte secondaire est ASSOMBRI (AA sur blanc), les meta pales
 *   supprimees/assombries. Le sombre n'est PAS un substitut au contraste : les deux
 *   themes sont haute lisibilite.
 *
 * @since 5.8.x -- Strategie espace membre (couche graphique mobile)
 * @since N1a   -- migration tokens + echafaudage theme sombre + taille de texte
 */

/* =========================================================================
 * EA-3 -- THEMES A DEUX AXES DECOUPLES (remplace l'idee "7 themes").
 *
 * AXE 1, SURFACE : clair (:root) / sombre ([data-theme="dark"]) / auto (systeme).
 *   Structurel -- fond, texte, bordures. C'est ce qui rend une interface lisible.
 * AXE 2, ACCENT : club (defaut) + N palettes, portees par [data-accent="..."].
 *   Une palette ne dit QUE deux teintes de marque ; elle ne touche jamais la surface.
 *
 * Pourquoi deux axes plutot que sept themes : aplatir "clair/sombre x 5 palettes" imposerait
 * de redefinir le jeu complet de tokens sept fois, et de dupliquer chaque palette en variante
 * sombre. Ici, 3 surfaces x (1+N) accents sortent de MOINS de CSS qu'avant.
 *
 * Trois valeurs par palette, parce qu'une meme teinte ne joue pas le meme role selon la
 * surface : --acc-1 (base, fond de bouton en clair), --acc-1-lite (la meme, ECLAIRCIE, pour
 * du TEXTE sur fond sombre) et --acc-1-deep (ASSOMBRIE, pour un fond en surface sombre).
 * Sans ce triplet, une palette vive devient illisible en sombre -- exactement le piege que
 * le decouplage doit eviter.
 * ========================================================================= */
:root,
[data-accent="club"] {
  --acc-1: #5266A4; --acc-1-lite: #8ea3d6; --acc-1-deep: #33406b;
  --acc-2: #E3352C; --acc-2-lite: #f2726a; --acc-2-deep: #cf3b32;
  --acc-soft: #eef1f8; --acc-bord: #d4ddec;
}
/* Palettes ludiques (mode enfant, et disponibles a l'adulte si la politique l'autorise).
   ATTENTION avant de "raviver" une teinte : --acc-1 sert de FOND a du texte blanc. Mesure du
   2026-08-17 (calcul de ratio WCAG sur la feuille reellement servie) : les valeurs d'origine
   d'ocean, jungle et sun tombaient a 3.13, 3.01 et 2.44 -- sous le seuil AA de 4.5. Elles ont
   ete assombries jusqu'a ~4.7 en conservant leur teinte. Le mode enfant est precisement celui
   ou la garantie AA est revendiquee : une palette joyeuse et illisible n'est pas un choix. */
[data-accent="violet"] { --acc-1: #6b4de6; --acc-1-lite: #b3a1f2; --acc-1-deep: #3f2d8a;
                         --acc-2: #ff6f91; --acc-2-lite: #ffa8bc; --acc-2-deep: #c2455f;
                         --acc-soft: #f0ecfd; --acc-bord: #ddd4f8; }
[data-accent="ocean"]  { --acc-1: #197cab; --acc-1-lite: #7fcbee; --acc-1-deep: #145d80;
                         --acc-2: #ff8a3d; --acc-2-lite: #ffb583; --acc-2-deep: #c25f21;
                         --acc-soft: #e9f5fc; --acc-bord: #cfe8f6; }
[data-accent="jungle"] { --acc-1: #188458; --acc-1-lite: #79d6b0; --acc-1-deep: #146544;
                         --acc-2: #ff6f91; --acc-2-lite: #ffa8bc; --acc-2-deep: #c2455f;
                         --acc-soft: #e8f7f0; --acc-bord: #cceade; }
[data-accent="sun"]    { --acc-1: #a26708; --acc-1-lite: #f5c46e; --acc-1-deep: #8a5806;
                         --acc-2: #5266a4; --acc-2-lite: #8ea3d6; --acc-2-deep: #33406b;
                         --acc-soft: #fdf3e2; --acc-bord: #f6e2bd; }
[data-accent="berry"]  { --acc-1: #d6336c; --acc-1-lite: #f08bae; --acc-1-deep: #83203f;
                         --acc-2: #7048e8; --acc-2-lite: #ac95f2; --acc-2-deep: #43298a;
                         --acc-soft: #fceaf1; --acc-bord: #f7d0de; }
/* Accents SOBRES : la meme mecanique, pour qui ne veut ni bleu club ni couleur vive. */
[data-accent="ardoise"] { --acc-1: #47566b; --acc-1-lite: #9aa8bb; --acc-1-deep: #2d3644;
                          --acc-2: #b3603a; --acc-2-lite: #d99a7c; --acc-2-deep: #7d4226;
                          --acc-soft: #eef0f3; --acc-bord: #d7dce3; }
[data-accent="foret"]   { --acc-1: #2f6b4f; --acc-1-lite: #86bda3; --acc-1-deep: #1d4231;
                          --acc-2: #b3603a; --acc-2-lite: #d99a7c; --acc-2-deep: #7d4226;
                          --acc-soft: #eaf2ee; --acc-bord: #cfe0d7; }

:root {
  /* --- Accents de marque (derives de l'axe ACCENT, EA-3) ------------------------------------- */
  --app-blue:      var(--acc-1);       /* accent : liens, nav active, icones, chips actifs */
  --app-blue-dark: var(--acc-1-deep);
  --app-blue-soft: #b9c4da;            /* texte secondaire pose sur la barre : structurel */
  --app-red:       var(--acc-2);       /* remplissage CTA/accent (texte blanc dessus) */
  --app-red-dark:  var(--acc-2-deep);  /* rouge en TEXTE sur surface claire (encre) */
  --app-red-soft:  #fdecea;
  --app-red-bord:  #f5c5c1;

  /* --- Fonds structurants (varient selon le theme) ----------------------- */
  --app-bar-bg:    var(--acc-1);   /* barre du haut + barre du bas */
  --app-portraits-grout: #c9c6bd;   /* joint de la mosaique de portraits : NEUTRE en clair pour que les
                                        carreaux BLEUS ne se fondent pas dans la barre bleue (bug theme clair) */
  --app-on-bar:    #ffffff;   /* texte/icone sur la barre */
  --app-primary:   var(--acc-1);   /* remplissage bouton primaire / chip actif */
  --app-on-primary:#ffffff;
  /* LA POLICE DE L APP EST UN TOKEN, et pas une valeur ecrite dans une seule regle.
     Elle etait posee en dur sur .cclub-app : tout ce que l app ajoute AILLEURS -- le bouton
     flottant d installation, les surcouches posees sur le body -- n avait aucun moyen de la
     retrouver, et tombait sur la police du navigateur.
     *Une valeur ecrite a un seul endroit n est pas partagee : elle est simplement la, et
     inaccessible a tout ce qui n est pas dessous.* */
  /* ============================================================================
     LA POLICE DE L'INTERFACE, EN UN SEUL ENDROIT PAR SURFACE.
     ============================================================================
     Refus de recette EXP-0055 (president) : << les polices ne respectent pas les
     polices standardisees >>. La cause immediate -- les controles de formulaire
     n'heritent pas de la police -- a ete corrigee sur la racine de l'app. RESTAIT
     LA DISPERSION : 14 piles distinctes declarees a la main dans le produit, dont
     deux `sans-serif` nus qui abandonnent le choix au navigateur.

     *Une charte qui n'existe pas comme valeur unique n'est pas une charte : c'est
     une habitude, et une habitude se perd a chaque ecran neuf.*

     /!\ TROIS DEFINITIONS, ET C'EST DELIBERE : une variable CSS n'existe que sous
     la racine qui la declare, et les trois surfaces (back-office, front, app) ne
     chargent pas les memes feuilles. Une definition unique en laisserait deux sans
     valeur. `NR-POLICE` verifie qu'elles disent la meme chose -- il remplace
     l'unicite qu'on ne peut pas obtenir sans etape de construction.

     NE PAS Y RAMENER : la chasse fixe (un numero de cheque, une cle technique --
     l'alignement porte du sens), les documents imprimes (un PDF n'a pas les polices
     du systeme) et les gabarits de courriel (les logiciels de messagerie ne
     connaissent pas -apple-system). Trois raisons differentes, toutes legitimes. */
  --cclub-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  /* `--app-font` reste, et POINTE sur la valeur canonique : une centaine de regles
     l emploient, et deux noms portant deux valeurs finiraient par diverger. */
  --app-font: var(--cclub-font);
  --app-hero-bg:   var(--acc-1);   /* carte "hero" mise en avant */
  --app-on-hero:   #ffffff;
  --app-hero-delta:#aef0cf;   /* delta positif pose sur le hero */

  /* --- Surfaces & texte -------------------------------------------------- */
  --app-bg:        #f4f4f1;   /* fond d'ecran (clair, legerement chaud) */
  --app-tile:      #ffffff;   /* surface de carte / tuile */
  --app-sheet:     #e7e4db;   /* feuille modale (bottom-sheet) : ASSOMBRIE vs page/tuile pour se detacher */
  --app-surface-2: #f1efe9;   /* surface secondaire (bloc doux) */
  --app-border:    #e6e4dd;
  --app-border-soft:#ece7db;
  /* Echiquier du quiz (diagrammes) -- couleurs FIXES, identiques clair/sombre :
     un diagramme d'echecs ne s'adapte pas au theme (une piece blanche reste claire).
     Style "mosaique arrondie" (variante C) : tuiles a joints aux couleurs du club. */
  --app-sq-l:      #f4f2ec;   /* case claire (creme chaud) */
  --app-sq-d:      #aab8dd;   /* case foncee (bleu pale club) */
  --app-sq-grout:  #c9c6bd;   /* joint entre les tuiles (comme le bandeau mosaique) */
  --app-pc-l:      #ffffff;   /* piece blanche */
  --app-pc-d:      #1c2b3a;   /* piece noire / bleu-nuit (et contour) */
  --app-text:      #1c2b3a;   /* texte primaire */
  --app-text-2:    #4a5568;   /* texte secondaire ASSOMBRI (AA sur blanc) */
  --app-text-3:    #64748b;   /* meta (ex-#9aa1a9), assombri */
  --app-ok:        #178a63;   /* progression positive (AA sur blanc) */
  --app-ok-bg:     #e3f2ec;
  --app-warn:      #8a5b00;   /* alerte / a faire (encre ambre, AA sur blanc) */
  --app-warn-bg:   #fdf6e3;
  --app-blue-bg:   var(--acc-soft);   /* surface d'accent douce (etat selectionne) */
  --app-blue-bord: var(--acc-bord);   /* bordure d'accent douce */
  --app-skel:      #ece9e2;   /* squelette de chargement */
  --app-upsell-sub:#b14039;

  /* --- Teintes de domaine (fond du disque d'icone ; *-ic = couleur icone). */
  --app-sport-bg:    #e8edf6; --app-sport-ic:    #5266A4;
  --app-club-bg:     #fde7e5; --app-club-ic:     #E3352C;
  --app-progress-bg: #efe9f8; --app-progress-ic: #6f57b0;
  --app-money-bg:    #e3f2ec; --app-money-ic:    #1f8a6b;
  --app-event-bg:    #fbe9e2; --app-event-ic:    #c4623a;
  --app-dispo-bg:    #eaf3de; --app-dispo-ic:    #5c8a1f;

  /* --- Echelle mobile ---------------------------------------------------- */
  --app-fs:          1;        /* multiplicateur de taille de texte (N1c : 3 crans) */

  /* ECHELLE TYPOGRAPHIQUE NOMMEE (A4 / EchelleApp-1, build 1616).
     L'app employait DIX-HUIT tailles nominales distinctes -- 10 11 12 13 14 15 16
     17 18 19 20 22 23 24 26 30 32 42 -- dont aucune ne portait de nom. Non par
     negligence : *une taille qui n'a pas de nom se choisit a l'oeil, et l'oeil
     tranche a un pixel pres a chaque fois qu'on lui repose la question.* D'ou 15 px
     a cote de 14, 17 a cote de 16, 19 a cote de 20.

     HUIT crans, et le chiffrage se declare : sur 514 occurrences, 458 (89 %) NE
     BOUGENT PAS. Les 56 autres se deplacent d'au plus 3 px -- sauf UNE, de 42 a
     32 px, sur un chiffre vedette unique. C'est la seule que l'oeil peut voir, et
     donc la seule qui se recette a ce titre.

     Chaque cran garde le multiplicateur : le reglage de taille du membre continue
     de s'appliquer partout. *Un cran nomme qui perdrait le multiplicateur casserait
     le reglage d'accessibilite sans qu'aucun compteur ne le signale.*

     Le multiplicateur est ecrit EN PREMIER dans chaque cran -- `calc(var(--app-fs)
     * 11px)` et non l'inverse. Ce n'est pas cosmetique : la conversion des 485
     occurrences existantes se fait en substituant le motif `calc(11px *
     var(--app-fs))`, et une definition ecrite dans cet ordre-la se serait
     substituee ELLE-MEME, en une reference circulaire que le navigateur resout en
     silence par une taille par defaut. *Une substitution globale ne distingue pas
     ce qu'elle definit de ce qu'elle emploie.* */
  --app-fs-xs:       calc(var(--app-fs) * 11px);   /* mention, legende */
  --app-fs-sm:       calc(var(--app-fs) * 12px);   /* texte secondaire */
  --app-fs-md:       calc(var(--app-fs) * 13px);   /* texte courant */
  --app-fs-lg:       calc(var(--app-fs) * 14px);   /* valeur, libelle fort */
  --app-fs-xl:       calc(var(--app-fs) * 16px);   /* titre de carte */
  --app-fs-2xl:      calc(var(--app-fs) * 20px);   /* titre d'ecran */
  --app-fs-3xl:      calc(var(--app-fs) * 26px);   /* chiffre mis en avant */
  --app-fs-hero:     calc(var(--app-fs) * 32px);   /* chiffre vedette unique */
  --app-radius:      16px;
  --app-radius-pill: 999px;
  --app-tap:         48px;     /* cible tactile minimale */
  --app-gap:         11px;
}

/* --- Theme SOMBRE (indicatif SPEC sec.9) ---------------------------------
   Echafaudage : defini ici mais PAS auto-active (ni bascule ni prefers-color-scheme)
   tant que les blocs peints en dur dans le JS ne sont pas migres (N1b). L'activation
   (@media + bascule) arrive en N1c. Confort ET haute lisibilite (contraste AA). */
[data-theme="dark"] {
  /* EA-3 : l'accent choisi joue ICI ses variantes ECLAIRCIE (texte) et ASSOMBRIE (fond) --
     c'est tout l'interet du decouplage : la palette ne change pas, son role change. */
  --app-blue:      var(--acc-1-lite);   /* accent eclairci pour texte/actif sur sombre */
  --app-blue-dark: var(--acc-1-lite);
  --app-blue-soft: #aab8dd;
  --app-red:       var(--acc-2-deep);   /* CTA : reste assez sombre pour du texte blanc (AA) */
  --app-red-dark:  var(--acc-2-lite);   /* rouge en TEXTE : eclairci pour contraste sur sombre */
  --app-red-soft:  #3a2422;
  --app-red-bord:  #5a3330;

  --app-bar-bg:    #1a2130;   /* barre : bleu-gris sombre (pas l'accent clair) */
  --app-portraits-grout: #1a2130;   /* joint mosaique : comme la barre en sombre (le bleu ressort deja) */
  --app-on-bar:    #f1f3f6;
  --app-primary:   var(--acc-1-deep);
  --app-on-primary:#f1f3f6;
  --app-hero-bg:   var(--acc-1-deep);
  --app-on-hero:   #f1f3f6;
  --app-hero-delta:#7ee3b0;

  --app-bg:        #12161d;
  --app-tile:      #1c222c;
  --app-sheet:     #2a3340;   /* feuille modale (bottom-sheet) : ECLAIRCIE vs fond/tuile pour se detacher */
  --app-surface-2: #232a35;
  --app-border:    #2b323d;
  --app-border-soft:#2b323d;
  --app-text:      #f1f3f6;
  --app-text-2:    #aab3c0;
  --app-text-3:    #8994a3;
  --app-ok:        #4ecb93;
  --app-ok-bg:     #17321f;
  --app-warn:      #e3b667;
  --app-warn-bg:   #33291a;
  --app-blue-bg:   #23304a;
  --app-blue-bord: #33415e;
  --app-skel:      #232a35;
  --app-upsell-sub:#f2a29c;

  --app-sport-bg:    #23304a; --app-sport-ic:    #9db4e6;
  --app-club-bg:     #3a2422; --app-club-ic:     #f2726a;
  --app-progress-bg: #2b2740; --app-progress-ic: #b9a6d6;
  --app-money-bg:    #15302a; --app-money-ic:    #58c79a;
  --app-event-bg:    #3a2a22; --app-event-ic:    #e0977a;
  --app-dispo-bg:    #2b3520; --app-dispo-ic:    #a9cc6e;
}

/* --- Taille de texte : 3 crans (N1c) ------------------------------------
   L'attribut est pose sur <html> ; --app-fs multiplie toute la typo (classes + inline). */
[data-textsize="grand"] { --app-fs: 1.14; }
[data-textsize="xl"]    { --app-fs: 1.30; }

/* Conteneur d'ecran ------------------------------------------------------- */
.cclub-app {
  background: var(--app-bg);
  color: var(--app-text);
  font-family: var(--app-font);
  font-size: var(--app-fs-xl);
  -webkit-font-smoothing: antialiased;
  max-width: 480px;
  margin: 0 auto;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
/* EA-32 : barre du haut + barre du bas FIXES, seul le contenu central defile.
   La coquille occupe toute la hauteur visible ; #cclub-screen est la seule zone scrollable. */
.cclub-app--shell { height: 100vh; height: 100dvh; min-height: 0; overflow: hidden; }
.cclub-app--shell .cclub-app-bar,
.cclub-app--shell .cclub-app-checker,
.cclub-app--shell .cclub-fbar,
.cclub-app--shell .cclub-bottomnav { flex: 0 0 auto; }
.cclub-app__scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; }

/* Barre superieure -------------------------------------------------------- */
.cclub-app-bar { background: var(--app-bar-bg); padding: 14px 16px 10px; }
.cclub-app-bar__title { color: var(--app-on-bar); font-size: var(--app-fs-2xl); font-weight: 600; margin: 10px 0 0; }
.cclub-app-bar__sub   { color: var(--app-blue-soft); font-size: var(--app-fs-md); }
/* N6 : marque de marque -- echo du logo SANS damier. Le bleu/rouge a parts egales ne tient que
   grace au lion blanc central (absent des surfaces de l'app) ; hors logo il vibre -> abandonne.
   Bleu = seule couleur structurante ; tuile bleue en degrade. */
.cclub-app-mark {
  width: 36px; height: 36px; border-radius: 9px; flex-shrink: 0;
  background: linear-gradient(135deg, var(--app-blue) 0%, var(--app-blue-dark) 100%);
}

/* N6 : filet bleu de liaison (remplace le bandeau damier abandonne). */
.cclub-app-checker {
  height: 3px;
  background: var(--app-blue);
}

/* N6 : bichromie bleue des photos de membres (EA-39) -- filtre A L'AFFICHAGE, zero stockage,
   reversible. Ressort d'appartenance sans typo fine. Rendu a calibrer sur les photos reelles (SPEC 12.5). */
.cclub-bichromie { filter: grayscale(1) sepia(1) hue-rotate(185deg) saturate(0.55) brightness(1.05) contrast(1.02); }

/* N6 : bandeau MOSAIQUE de portraits (public, ecran de connexion). TRICHROMIE Rouge/Bleu/Blanc =
   rythme identitaire du club, applique en FILTRE a l'affichage (zero stockage, reversible ; source =
   endpoint public regenere 1x/jour). Visages seuls, AUCUN nom (RGPD ; adultes consentants uniquement).
   Rendu des filtres a calibrer sur photos reelles (comme la bichromie). */
.cclub-portraits {
  display: grid;
  /* Les carreaux remplissent EXACTEMENT la largeur : N colonnes en 1fr (N calcule en JS selon la
     largeur reelle), le meme ecart de 2px entre carreaux ET sur les bords (gap + padding). */
  grid-template-columns: repeat(var(--cclub-portraits-cols, 10), 1fr);
  align-content: start;
  gap: 2px; padding: 2px;
  overflow: hidden;
  background: var(--app-portraits-grout);
}
/* Carreaux CARRES (aspect-ratio) : la hauteur d'un rang = la largeur d'un carreau. On genere
   exactement 2 rangs -> la bande fait pile 2 carreaux de haut (+ joint + marges). */
.cclub-portraits__cell { overflow: hidden; border-radius: 4px; background: var(--app-skel); aspect-ratio: 1 / 1; }
.cclub-portraits__cell img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cclub-tri-b img { filter: grayscale(1) sepia(1) hue-rotate(185deg) saturate(1.25) brightness(0.95); }        /* bleu */
.cclub-tri-r img { filter: grayscale(1) sepia(1) saturate(3) hue-rotate(-25deg) brightness(1.02); }           /* rouge */
.cclub-tri-w img { filter: grayscale(1) brightness(1.12) contrast(0.96); }                                    /* blanc/neutre */
/* Fallback identitaire quand aucune photo consentie n'est disponible : carres pleins aux couleurs
   OFFICIELLES du club (fixes, hors thematisation -- c'est une marque, pas une surface d'UI). */
.cclub-portraits__cell.cclub-sq--w { background: #ffffff; }
.cclub-portraits__cell.cclub-sq--b { background: #5266A4; }
.cclub-portraits__cell.cclub-sq--r { background: #E3352C; }
/* Piece d'echecs posee sur un carreau du club (fallback quand < 10 photos consenties, EA-39).
   Glyphe centre, encre FIXE choisie pour le contraste : foncee sur blanc, blanche sur bleu/rouge
   (couleurs de marque, hors thematisation). */
.cclub-portraits__cell.cclub-sq-pc {
  display: flex; align-items: center; justify-content: center;
  font-size: 3vh; line-height: 1; -webkit-user-select: none; user-select: none;
}
.cclub-sq--w.cclub-sq-pc { color: #1c2b3a; }              /* piece foncee sur carreau blanc */
.cclub-sq--b.cclub-sq-pc,
.cclub-sq--r.cclub-sq-pc { color: #ffffff; }              /* piece blanche sur carreau bleu/rouge */

/* Carte "hero" (resume mis en avant) ------------------------------------- */
.cclub-hero {
  background: var(--app-hero-bg); color: var(--app-on-hero);
  border-radius: var(--app-radius);
  padding: 14px 16px; margin: 14px;
  display: flex; align-items: center; justify-content: space-between;
}
.cclub-hero__num { font-size: var(--app-fs-3xl); font-weight: 600; }
.cclub-hero__delta { font-size: var(--app-fs-lg); color: var(--app-hero-delta); font-weight: 400; }

/* Mur de tuiles ----------------------------------------------------------- */
.cclub-tiles {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--app-gap);
  padding: 0 14px;
}
.cclub-tile {
  background: var(--app-tile); border: 1px solid var(--app-border);
  border-radius: var(--app-radius); padding: 14px; min-height: 96px;
  display: block; text-decoration: none; color: inherit;
}
.cclub-tile:active { transform: scale(.98); }
.cclub-tile__icon {
  width: 46px; height: 46px; border-radius: 13px;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--app-fs-3xl); margin-bottom: 10px;
}
.cclub-tile__title { font-size: var(--app-fs-xl); font-weight: 600; color: var(--app-text); }
.cclub-tile__sub   { font-size: var(--app-fs-sm); color: var(--app-text-2); }
.cclub-tile--wide { grid-column: 1 / -1; }

/* Teintes de domaine appliquees au disque d'icone */
.cclub-tile--sport    .cclub-tile__icon { background: var(--app-sport-bg);    color: var(--app-sport-ic); }
.cclub-tile--club     .cclub-tile__icon { background: var(--app-club-bg);     color: var(--app-club-ic); }
.cclub-tile--progress .cclub-tile__icon { background: var(--app-progress-bg); color: var(--app-progress-ic); }
.cclub-tile--money    .cclub-tile__icon { background: var(--app-money-bg);    color: var(--app-money-ic); }
.cclub-tile--event    .cclub-tile__icon { background: var(--app-event-bg);    color: var(--app-event-ic); }
.cclub-tile--dispo    .cclub-tile__icon { background: var(--app-dispo-bg);    color: var(--app-dispo-ic); }

/* Marqueur "reserve adherents" (freemium) -> rouge de marque */
.cclub-lock { font-size: var(--app-fs-sm); color: var(--app-red-dark); font-weight: 600; }

/* Bandeau d'incitation a l'adhesion (premium) ----------------------------- */
.cclub-upsell {
  background: var(--app-red-soft); border: 1px solid var(--app-red-bord);
  border-radius: var(--app-radius); padding: 13px 14px; margin: 12px 14px 0;
  display: flex; align-items: center; gap: 12px;
}
.cclub-upsell__title { font-size: var(--app-fs-lg); font-weight: 600; color: var(--app-red-dark); }
.cclub-upsell__sub   { font-size: var(--app-fs-sm); color: var(--app-upsell-sub); }

/* Barre de navigation basse ---------------------------------------------- */
.cclub-bottomnav {
  display: flex; justify-content: space-around; align-items: center;
  background: var(--app-bar-bg); padding: 9px 6px 11px; margin-top: auto;
}
.cclub-bottomnav a {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  color: var(--app-blue-soft); text-decoration: none; font-size: var(--app-fs-xs); min-width: var(--app-tap);
}
.cclub-bottomnav a.is-active { color: var(--app-on-bar); }
/* AA2-11 -- LE MODE APERCU DOIT SE VOIR. Le meme geste -- toucher une zone -- a DEUX effets selon
   que le tiroir est ouvert ou ferme : tiroir ferme il navigue, tiroir ouvert il previsualise.
   C'est le point dur assume de la spec, et il n'est acceptable qu'a une condition : *un etat qui
   change le sens d'un geste doit se voir.*
   DEUX SIGNES CUMULES, JAMAIS UN SEUL, et sur deux objets differents -- un lisere sur LA BARRE
   (l'etat) et le gras souligne sur LA ZONE previsualisee (l'objet vise). *Un seul signe se confond
   avec un survol ; deux se lisent comme un etat.*
   Et la zone previsualisee ne prend PAS la couleur d'actif ci-dessus : elle n'est pas ou l'on est,
   elle est ce qu'on regarde. Les confondre rendrait le mode apercu invisible tout en le declarant
   present. */
.cclub-bottomnav.is-preview-mode { box-shadow: inset 0 2px 0 0 var(--app-blue-soft); }
.cclub-bottomnav a.is-preview { color: var(--app-on-bar); font-weight: 700; }
.cclub-bottomnav a.is-preview > span { text-decoration: underline; text-underline-offset: 3px; }
/* CINQ zones depuis le build 1632 : sur un telephone etroit chaque zone tombe a ~72px, et un
   libelle un peu long passerait a la ligne ou deborderait sur son voisin. On le borne ici
   plutot que de raccourcir les mots jusqu'a l'obscurite. */
.cclub-bottomnav a > span {
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cclub-bottomnav i { font-size: var(--app-fs-2xl); }

/* Boutons d'action plein contraste --------------------------------------- */
.cclub-app-btn {            /* primaire (bleu de marque) */
  display: block; width: 100%; box-sizing: border-box;
  background: var(--app-primary); color: var(--app-on-primary);
  border: 0; border-radius: var(--app-radius-pill);
  padding: 14px 18px; font-size: var(--app-fs-xl); font-weight: 600;
  text-align: center; text-decoration: none; cursor: pointer;
  min-height: var(--app-tap);
}
.cclub-app-btn--accent { background: var(--app-red); color: var(--app-on-primary); }  /* CTA energique (s'inscrire, adherer) */
/* EA-R1 : fabrique UNIQUE de badge (pastille de statut). Remplace >=6 variantes inline
   (badgesBlock, tourStateBadge, ivBadge, bienfaiteurBadge, chips presence, compteur cloche).
   La couleur (fond/texte) est portee par le JS appBadge() via les tokens --app-* (2 themes). */
.cclub-app-badge { display: inline-flex; align-items: center; gap: 5px; font-size: var(--app-fs-xs); font-weight: 600; border-radius: var(--app-radius-pill); padding: 3px 9px; white-space: nowrap; line-height: 1.4; }
.cclub-app-badge--lg { font-size: var(--app-fs-sm); padding: 5px 12px; gap: 6px; }
.cclub-app-badge--count { display: inline-block; min-width: 16px; height: 16px; padding: 0 3px; box-sizing: border-box; border-radius: 9px; font-size: var(--app-fs-xs); font-weight: 700; line-height: 16px; text-align: center; gap: 0; }
.cclub-app-btn--ghost  { background: transparent; color: var(--app-blue); border: 1.5px solid var(--app-blue); }
/* EA-2 : SEGMENT / CHIP -- fabrique unique des boutons de choix de l'app.
   Absorbe six jeux ad hoc : segBtn (segments), mdBtn (dispo d'un match), detPrimBtn/detSubBtn
   (onglets de detail), rndChip (rondes), dispoBtns (feuille de match), presToggle (presence).
   Un seul patron : un bouton de CHOIX, eteint ou allume (.is-on), decline en tailles et en tons.
   L'etat allume porte aussi aria-pressed : la couleur ne doit jamais etre le seul signal. */
.cclub-app-seg {
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  position: relative; box-sizing: border-box;
  border: 1px solid var(--app-border); background: var(--app-tile); color: var(--app-text-2);
  border-radius: var(--app-radius-pill); padding: 8px 14px;
  font-size: var(--app-fs-sm); font-weight: 600; line-height: 1.2;
  min-height: var(--app-tap); cursor: pointer; white-space: nowrap;
}
.cclub-app-seg.is-on { background: var(--app-primary); color: var(--app-on-primary); border-color: var(--app-primary); }
.cclub-app-seg:focus-visible { outline: 2px solid var(--app-blue); outline-offset: 2px; }
.cclub-app-seg[disabled] { opacity: .5; cursor: default; }

/* Formes : le groupe segmente colle ses boutons dans un cadre commun (bordures portees par le
   groupe), l'onglet de detail s'etire, la puce reste ronde. */
.cclub-app-seg--flat { border: 0; background: transparent; border-radius: 0; }
.cclub-app-seg--flat.is-on { border: 0; }
.cclub-app-seg--grow { flex: 1; }
.cclub-app-seg--sm { padding: 5px 11px; font-size: var(--app-fs-sm); }
.cclub-app-seg--dot { width: 30px; height: 30px; min-height: 30px; padding: 0; border-radius: 8px; font-weight: 700; }

/* Cible tactile des puces de la feuille de match : 30px a l'oeil, 48px au doigt. La zone est
   etendue par un pseudo-element, la densite du tableau reste intacte -- une case de disponibilite
   qui ferait 48px casserait la lecture de la grille. */
.cclub-app-seg--dot::after { content: ""; position: absolute; top: 50%; left: 50%; width: var(--app-tap); height: var(--app-tap); transform: translate(-50%, -50%); }

/* Tons : reprennent les memes couples fond/texte que la fabrique de badge. */
.cclub-app-seg--ok.is-on     { background: var(--app-ok);       border-color: var(--app-ok);       color: var(--app-on-primary); }
.cclub-app-seg--warn.is-on   { background: var(--app-warn);     border-color: var(--app-warn);     color: var(--app-on-primary); }
.cclub-app-seg--danger.is-on { background: var(--app-red-dark); border-color: var(--app-red-dark); color: var(--app-on-primary); }
.cclub-app-seg--info.is-on   { background: var(--app-blue);     border-color: var(--app-blue);     color: var(--app-on-primary); }

/* Rangee alignee a droite (ex-style inline de la ligne "Suivre un tournoi"). */
.cclub-row--end { display: flex; justify-content: flex-end; margin-bottom: 6px; }

/* Cadre d'un groupe segmente (ex-segWrap) : une seule bordure autour de la serie. */
.cclub-app-seggrp { display: inline-flex; border: 1px solid var(--app-border); border-radius: var(--app-radius-pill); overflow: hidden; }
.cclub-app-seggrp--end { margin-left: auto; }
.cclub-app-seggrp--row { display: flex; gap: 6px; border: 0; border-radius: 0; }
.cclub-app-seggrp--tight { display: flex; gap: 3px; border: 0; border-radius: 0; }
.cclub-rnd-chips { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 8px; }

/* ERGO-1 (build 1794) -- ONGLETS DE L'APP (primitive `appTabs()`).
   ⚑ Ces trois classes sont NOMMEES dans le JS : sans règle ici, elles donneraient l'illusion
   d'un composant tout en ne portant rien — c'est le défaut relevé cinq fois au train 8
   (« une classe qui ne porte pas son style donne l'illusion d'un composant », build 1591).
   La barre DÉFILE horizontalement plutôt que de passer à la ligne : sur un téléphone, six
   onglets qui se replient en deux rangées déplacent le contenu à chaque changement d'onglet.
   `scrollbar-width: none` masque la barre sans empêcher le geste. */
/* /!\ `overflow-y: hidden` EST OBLIGATOIRE ET LE FILET `NR-SCROLL-PARASITE` L'A EXIGE.
   Un `overflow-x` seul laisse l'axe vertical à `visible`, que le navigateur promeut alors
   en `auto` : la barre gagne un défilement vertical parasite de quelques pixels, et sur un
   téléphone elle « accroche » le doigt au lieu de laisser la page défiler. ⚑ *Un filet du
   produit m'a repris sur mon propre composant, le jour où je l'écrivais.* */
.cclub-app-tabs__bar {
    margin-bottom: 10px;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}
.cclub-app-tabs__bar::-webkit-scrollbar { display: none; }
/* Le groupe ne doit pas se comprimer : chaque onglet garde sa largeur et l'on fait défiler. */
.cclub-app-tabs__bar .cclub-app-seggrp { flex-wrap: nowrap; }
.cclub-app-tabs__bar .cclub-app-tab { white-space: nowrap; }
.cclub-app-tabs__panel { min-width: 0; }

/* ERGO-7 (build 1803) -- L'AFFORDANCE : CE QUI EST CLIQUABLE DOIT SE VOIR ET SE PRENDRE.
   ⚑ Constat présidentiel : *« on ne sait pas ce qui peut être cliqué, et ce qui ne l'est pas. »*
   Mesure : **77** balises `<a>` sans `href` employées comme boutons — ni focusables, ni
   actionnables au clavier. Le script leur pose `role`/`tabindex` ; la feuille leur donne le
   signal visible du focus, que **rien** ne portait (7 règles `:focus-visible` dans toute l'app).
   ⚑ *Une action qu'on ne voit pas n'est pas une action manquante : c'est une action qu'on croit
   absente, et dont on demande l'ajout.* */
a:not([href])[role="button"]:focus-visible,
.cclub-app-link:focus-visible {
    outline: 2px solid var(--app-blue);
    outline-offset: 2px;
    border-radius: 6px;
}
/* La fabrique d'action visible : un vrai bouton, qui se lit comme un lien d'action. */
.cclub-app-link {
    display: inline-flex; align-items: center; gap: 4px;
    background: transparent; border: 0; padding: 0;
    color: var(--app-blue); font: inherit;
    cursor: pointer; min-height: var(--app-tap);
    text-align: left;
}
.cclub-app-link:hover { text-decoration: underline; }

/* ERGO-4 (build 1801) -- LES 7 `style=` DE LA CARTE D'INTERVENTION, rendus à la feuille (R-33c). */
.cclub-iv-card {
    background: var(--app-tile); border: 1px solid var(--app-border);
    border-radius: 14px; margin: 12px 14px; padding: 12px 14px;
}
.cclub-iv-head    { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
.cclub-iv-date    { font-size: var(--app-fs-lg); color: var(--app-text); font-weight: 600; }
.cclub-iv-hour    { font-size: var(--app-fs-sm); color: var(--app-text-2); font-weight: 400; }
.cclub-iv-badge   { text-align: right; }
.cclub-iv-contact { margin-top: 8px; }
.cclub-iv-intro   { font-size: var(--app-fs-md); color: var(--app-text-2); }
.cclub-iv-none    { padding: 24px; text-align: center; color: var(--app-text-2); font-size: var(--app-fs-lg); }

/* ERGO-5 (build 1798) -- LA RANGÉE QUI OUVRE SA LISTE EN MODALE (`appRowSheet`).
   La valeur devient un BOUTON : il doit donc se voir comme tel — c'est exactement le défaut
   transversal que relève `ERGO-7` (*on ne voit pas ce qui est cliquable*). Le chevron le dit,
   et la cible respecte `--app-tap` : ⚑ *une cible tactile plus petite que le doigt n'est pas
   une petite cible, c'est une cible qu'on rate.* */
.cclub-app-kv--sheet .cclub-app-kv__v {
    display: inline-flex; align-items: center; gap: 6px;
    background: transparent; border: 0; padding: 0;
    color: var(--app-blue); font: inherit; text-align: right;
    cursor: pointer; min-height: var(--app-tap);
}
.cclub-app-kv--sheet .cclub-app-kv__v:focus-visible { outline: 2px solid var(--app-blue); outline-offset: 2px; }
.cclub-app-sheet-chev { font-size: 1.1em; line-height: 1; }
.cclub-sheet-list { max-height: 60vh; overflow-y: auto; overflow-x: hidden; }
.cclub-sheet-item {
    padding: 10px 2px; border-bottom: 1px solid var(--app-border);
    font-size: var(--app-fs-md);
}
.cclub-sheet-item:last-child { border-bottom: 0; }

/* ERGO-2 (build 1797) -- LES 11 `style=` DU BLOC « DÉTAIL DU TOURNOI », rendus à la feuille.
   ⚑ Le motif était le SEUL du produit à porter des onglets ; le généraliser sans payer sa dette
   l'aurait multipliée par le nombre d'appelants (`ERGO-3`, `-4`, `-6` s'y branchent ensuite). */
.cclub-det-title { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.cclub-det-ffe   { color: var(--app-blue); font-weight: 400; white-space: nowrap; }
.cclub-det-sub   { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.cclub-det-body  { margin-top: 8px; }
/* État vide d'un onglet : il DIT qu'il n'y a rien, il ne laisse pas une zone blanche.
   *Un état vide muet ne se distingue pas d'un écran cassé : c'est la même zone blanche.* */
.cclub-det-empty { font-size: var(--app-fs-sm); color: var(--app-text-2); padding: 4px 0; }
.cclub-det-intro { font-size: var(--app-fs-xs); color: var(--app-text-3); line-height: 1.5; margin: 2px 0 6px; }
.cclub-det-forced { color: var(--app-primary); }
.cclub-conc-more {
    width: 100%; margin-top: 6px; padding: 7px;
    border: 1px solid var(--app-border); border-radius: 10px;
    background: transparent; color: var(--app-blue);
    font-size: var(--app-fs-sm); cursor: pointer;
    min-height: var(--app-tap);
}

/* EA-1c : variante COMPACTE, pour un bouton d'action au bout d'une ligne de liste. Elle reste
   sur --app-tap : un bouton plus petit visuellement, jamais une cible tactile plus petite. */
.cclub-app-btn--sm { display: inline-flex; align-items: center; justify-content: center; width: auto; padding: 8px 14px; font-size: var(--app-fs-md); min-height: var(--app-tap); }
.cclub-app-btn--sm.cclub-app-btn--ghost { color: var(--app-red-dark); border-color: var(--app-border); }

/* Sélecteur de profils "famille" (parent + enfants, F2) ------------------- */
.cclub-fbar {
  display: flex; gap: 8px; overflow-x: auto; overflow-y: hidden; padding: 12px 14px 0;
  -webkit-overflow-scrolling: touch;
}
.cclub-fchip {
  flex: 0 0 auto; padding: 7px 14px; border-radius: var(--app-radius-pill);
  background: var(--app-tile); border: 1px solid var(--app-border); color: var(--app-text);
  font-size: var(--app-fs-lg); text-decoration: none; cursor: pointer; white-space: nowrap;
}
.cclub-fchip.is-on { background: var(--app-primary); color: var(--app-on-primary); border-color: var(--app-primary); }

/* Etat de chargement (squelette) ----------------------------------------- */
.cclub-skel { background: var(--app-skel); border-radius: 8px; }

/* EA-3 : rangee de reglage + pastilles d'ACCENT ---------------------------
   Chaque pastille montre les DEUX teintes de sa palette : un accent est un couple, et une
   pastille unicolore laisserait croire le contraire. L'etat retenu porte .is-on ET
   aria-pressed -- jamais la seule couleur, invisible pour qui ne la distingue pas. */
.cclub-set-row { display: flex; align-items: center; gap: 8px; font-size: var(--app-fs-lg); color: var(--app-text); padding: 6px 0; }
.cclub-set-row--top { border-top: 1px solid var(--app-surface-2); }
.cclub-acc-sws { display: flex; flex-wrap: wrap; gap: 8px; margin-left: auto; }
.cclub-acc-sw {
  position: relative; display: inline-flex; overflow: hidden;
  width: 30px; height: 30px; padding: 0; border-radius: 50%;
  border: 2px solid var(--app-border); background: transparent; cursor: pointer;
}
/* Cible tactile portee a --app-tap sans grossir la pastille : meme technique que les puces
   de la feuille de match (EA-2). Une rangee de huit pastilles de 48px ne tiendrait pas. */
.cclub-acc-sw::after { content: ""; position: absolute; top: 50%; left: 50%; width: var(--app-tap); height: var(--app-tap); transform: translate(-50%, -50%); }

/* ============================================================================================
   LE CONFIGURATEUR DE TUILES (recette groupee des portes, item 12).

   MESURE au navigateur en 375 px, AVANT : SEIZE cibles a 18x18 -- huit poignees de traine et
   huit oeils -- sur des lignes de 38 px, la ou le produit tient --app-tap (48). Ce sont les deux
   SEULS gestes de cet ecran : reordonner ses tuiles, et decider si une tuile parait sur l'accueil.

   ON REPREND LE MOTIF DEJA ETABLI PAR `.cclub-acc-sw` -- un `::after` centre, dimensionne au cran
   tactile -- plutot que d'en inventer un second : la cible fait 48, l'icone reste dessinee a 18.
   *On agrandit ce qu'on TOUCHE, pas ce qu'on VOIT.* Et c'est ce meme motif qui avait fait de ma
   premiere mesure un faux positif sur les pastilles d'accent : `getBoundingClientRect()` ne voit
   pas un pseudo-element etendu. *Une mesure qui ignore un motif du produit n'est pas severe :
   elle est fausse, et elle accuse du code juste.*
   ============================================================================================ */
.cclub-tilerow {
  display: flex; align-items: center; gap: 10px;
  min-height: var(--app-tap);
  padding: 2px; border-top: 1px solid var(--app-surface-2);
}
.cclub-tilerow.is-off { opacity: .55; }
.cclub-tilerow__ic  { color: var(--app-blue); display: inline-flex; }
.cclub-tilerow__lbl { flex: 1; min-width: 0; font-size: var(--app-fs-lg); color: var(--app-text); }
.cclub-tilelist__help { font-size: var(--app-fs-sm); color: var(--app-text-2); margin-bottom: 2px; }

.cclub-tilerow__act {
  position: relative;          /* le ::after se centre dessus */
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.cclub-tilerow__act::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: var(--app-tap); height: var(--app-tap);
  transform: translate(-50%, -50%);
}
.cclub-tilerow__act:focus-visible { outline: 2px solid var(--app-primary); outline-offset: 4px; border-radius: 6px; }
/* La poignee : `touch-action:none` est NECESSAIRE -- sans elle, le navigateur interprete la
   traine comme un defilement et le reordonnancement ne demarre jamais. */
.cclub-tgrip { color: var(--app-text-3); cursor: grab; touch-action: none; }
.cclub-tgrip:active { cursor: grabbing; }
/* L'oeil dit son etat par la COULEUR **et** par `aria-pressed` : la couleur seule ne se lit ni
   au lecteur d'ecran, ni pour qui distingue mal le vert du gris. */
.cclub-teye { color: var(--app-ok); }
.cclub-teye.is-off { color: var(--app-text-3); }
.cclub-acc-sw.is-on { border-color: var(--app-text); }
.cclub-acc-sw:focus-visible { outline: 2px solid var(--app-blue); outline-offset: 2px; }
.cclub-acc-sw__a, .cclub-acc-sw__b { width: 50%; height: 100%; }
.cclub-acc-sw__a { background: var(--acc-1); }
.cclub-acc-sw__b { background: var(--acc-2); }

/* Overlay de l'app (EA-1) : voile commun a TOUTES les surfaces modales ----
   .cclub-menu-ov porte le voile ; le panneau qu'il contient decide de la forme --
   .cclub-carte-panel (plein ecran) ou .cclub-ov-sheet (feuille de bas de page). Le nom
   historique est conserve : il est reference par deux surfaces et par la fabrique ovOpen,
   et le renommer sans recette visuelle complete serait du risque sans gain. */
/* LA FAMILLE EST REPOSEE ICI, ET CE N'EST PAS une redondance (build 1360). Les voiles et les
   feuilles sont poses en fin de <body>, donc HORS de `.cclub-app` : ils heritent de la page hote.
   Dans le shell PWA le body porte la bonne pile, mais dans la PAGE D'APERCU DE DIFFUSION il ne
   porte rien -- et toutes les feuilles y sortaient en Times New Roman (mesure : font-family
   calculee = "Times New Roman" sur la feuille, sur son titre et sur ses boutons). L'apercu est
   l'ecran sur lequel l'app se relit avant diffusion : il doit montrer l'app, pas une variante
   involontaire. Defaut PREEXISTANT, il touchait deja la feuille "joueur de tournoi". */
.cclub-menu-ov { position: fixed; inset: 0; z-index: 10000; background: rgba(10,14,20,.45); opacity: 0; pointer-events: none; transition: opacity .2s;
  font-family: var(--cclub-font, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif); }
.cclub-menu-ov.is-open { opacity: 1; pointer-events: auto; }

/* Feuille de bas de page (EA-1) : ex-styles en dur d'appModal(). */
.cclub-ov--sheet { display: flex; align-items: flex-end; justify-content: center; }
.cclub-ov-sheet { background: var(--app-tile); color: var(--app-text); width: 100%; max-width: 480px; border-radius: var(--app-radius) var(--app-radius) 0 0; padding: 18px 16px 20px; box-shadow: 0 -4px 24px rgba(0,0,0,.22); transform: translateY(12px); transition: transform .2s ease; max-height: 88vh; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.cclub-menu-ov.is-open .cclub-ov-sheet { transform: translateY(0); }
.cclub-ov-sheet__t { font-weight: 600; font-size: var(--app-fs-xl); margin-bottom: 8px; }
.cclub-ov-sheet__acts { display: flex; gap: 8px; margin-top: 14px; }
.cclub-ov-sheet__acts > .cclub-app-btn { flex: 1; }
.cclub-ov-sheet__acts .cclub-app-btn--danger { background: var(--app-red); color: var(--app-on-primary); }

/* Feuille "joueur de tournoi" (T5) : voile plus dense, liseret et poignee pour l'identifier
   d'un coup d'oeil au milieu d'un ecran de tournoi. Meme fabrique, autre habillage. */
.cclub-menu-ov--dense { background: rgba(4,7,12,.62); }
.cclub-ov-sheet--tour { background: var(--app-sheet); border: 1px solid var(--app-border); border-bottom: none; padding: 8px 16px 20px; box-shadow: 0 -8px 30px rgba(0,0,0,.55); max-height: 85vh; }
.cclub-ov-grip { width: 40px; height: 4px; background: var(--app-text-3); opacity: .5; border-radius: var(--app-radius-pill); margin: 4px auto 12px; }

/* Boite centree (EA-1b) : accueil du jour, QR de connexion. */
.cclub-ov--center { display: flex; align-items: center; justify-content: center; padding: 18px; }
.cclub-ov-box { background: var(--app-tile); color: var(--app-text); border-radius: var(--app-radius); max-width: 360px; width: 100%; padding: 18px; transform: scale(.96); transition: transform .18s ease; max-height: 88vh; overflow-y: auto; }
.cclub-menu-ov.is-open .cclub-ov-box { transform: scale(1); }
/* Le QR se scanne : fond blanc et texte sombre sont FONCTIONNELS, pas decoratifs -- ils ne
   doivent suivre ni le theme ni le mode sombre, sinon la camera de l'enfant ne lit plus rien.
   Seuls hex volontaires de ce bloc. */
.cclub-ov-box--qr { background: #fff; color: #1c2b3a; max-width: 320px; text-align: center; }
.cclub-ov-box--qr .cclub-ov-qr-note { color: #5a6b82; }
.cclub-ov-qr { width: 220px; height: 220px; margin: 0 auto; }
.cclub-ov-qr-svg { width: 100%; height: auto; }
.cclub-ov-box__acts { margin-top: 12px; display: flex; justify-content: center; }
.cclub-ov-box__acts .cclub-app-btn { max-width: 240px; }

/* Contenu commun aux boites centrees et aux feuilles ---------------------- */
.cclub-ov-sheet__d { font-size: var(--app-fs-md); color: var(--app-text-2); margin-bottom: 8px; }
.cclub-ov-sheet__wait { padding: 16px; text-align: center; color: var(--app-text-3); font-size: var(--app-fs-md); }
.cclub-ov-sheet__t--lg { font-size: var(--app-fs-xl); color: var(--app-text); }

/* Popup d'accueil du jour (EA-43) ---------------------------------------- */
.cclub-ov-box__head { display: flex; align-items: center; gap: 8px; }
.cclub-ov-box__ic { width: 34px; height: 34px; border-radius: 10px; background: var(--app-blue-bg); color: var(--app-blue); display: flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.cclub-ov-box__tag { flex: 1; font-size: var(--app-fs-sm); font-weight: 600; color: var(--app-blue); }
.cclub-ov-box__x { color: var(--app-text-2); cursor: pointer; font-size: var(--app-fs-2xl); line-height: 1; font-weight: 600; min-width: var(--app-tap); min-height: var(--app-tap); display: inline-flex; align-items: center; justify-content: flex-end; }
.cclub-ov-box__t { font-size: var(--app-fs-xl); font-weight: 600; color: var(--app-text); margin-top: 10px; }
.cclub-ov-box__b { font-size: var(--app-fs-lg); color: var(--app-text-2); margin-top: 5px; line-height: 1.45; }
.cclub-ov-box__cta { font-size: var(--app-fs-lg); padding: 12px 16px; text-decoration: none; display: inline-flex; align-items: center; justify-content: center; }
.cclub-ov-box__later { margin-top: 10px; text-align: center; }
.cclub-ov-box__later a { font-size: var(--app-fs-sm); color: var(--app-text-3); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; min-height: var(--app-tap); }
/* AA2-01 : .cclub-menu-panel / -body / -grp / -it / -tx / -t / -d / -ic sont partis avec le menu
   sandwich (13 regles). Ce qui RESTE ci-dessous est partage avec la carte du joueur et la popup
   Cours -- le prefixe `menu-` n'y designe plus un menu, c'est un nom historique de bandeau
   d'overlay. */
.cclub-menu-head { background: var(--app-bar-bg); color: var(--app-on-bar); display: flex; align-items: center; justify-content: space-between; padding: 16px; flex: 0 0 auto; }
.cclub-menu-title { font-size: var(--app-fs-xl); font-weight: 600; }
.cclub-menu-x { color: var(--app-on-bar); cursor: pointer; display: inline-flex; align-items: center; justify-content: flex-end; min-width: var(--app-tap); min-height: var(--app-tap); }

/* Carte de membre plein ecran (N3d) : geste avatar ----------------------- */
.cclub-carte-panel { position: absolute; inset: 0; background: var(--app-bg); display: flex; flex-direction: column; }
.cclub-carte-body { flex: 1 1 auto; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 16px 12px 28px; color: var(--app-text); text-align: center; font-size: var(--app-fs-2xl); }

/* Mode enfant (N5) : bandeau discret + accueil ludique ------------------- */
.cclub-kid-band { position: sticky; top: 0; z-index: 50; background: var(--app-primary); color: var(--app-on-primary); display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 14px; font-size: var(--app-fs-lg); font-weight: 600; }
/* 36 px mesures avant T9-AA2.2 : c'est la SEULE sortie du mode enfant, et elle etait sous le
   cran tactile du produit. Une sortie qu'on rate se retente, et l'enfant croit etre enferme. */
.cclub-kid-hand { background: var(--app-on-primary); color: var(--app-primary); border-radius: var(--app-radius-pill); padding: 7px 14px; font-size: var(--app-fs-md); font-weight: 600; cursor: pointer; white-space: nowrap; min-height: var(--app-tap); display: inline-flex; align-items: center; }
.cclub-kid-hi { font-size: var(--app-fs-3xl); font-weight: 700; color: var(--app-text); padding: 16px 16px 2px; }

/* Mode enfant (N5) -- palette ludique NON genree, CHOISIE par l'enfant (localStorage cote client ;
   zero donnee serveur, zero RGPD : le sexe n'est jamais lu ni expose). data-kid="1" est pose sur
   <html> pendant la "main a l'enfant" ; data-kid-color porte la teinte. On ne surcharge QUE les tokens
   --app-* -> recolore bandeau/boutons/accents et arrondit les coins, sans toucher au reste de l'app.
   Place APRES [data-theme="dark"] (specificite egale) pour l'emporter dans les deux themes. */
/* EA-3 : le mode enfant N'EST PAS un accent parmi d'autres -- c'est une POLITIQUE DE SURFACE.
   Il force une surface claire quel que soit data-theme (garantie de contraste AA pour l'enfant,
   meme si le telephone du parent est en sombre) et arrondit les coins. Sa COULEUR, elle, vient
   desormais de l'axe accent : data-kid-color pose l'accent correspondant, et les tokens de
   marque en derivent comme partout ailleurs. Une seule definition de palette pour les deux axes. */
[data-kid="1"] {
  --app-radius: 22px;                       /* coins plus ronds, plus doux */
  --app-blue:       var(--acc-1);
  --app-bar-bg:     var(--acc-1);
  --app-primary:    var(--acc-1);
  --app-on-primary: #ffffff;
  --app-hero-bg:    var(--acc-1);
  --app-on-hero:    #ffffff;
  --app-red:        var(--acc-2);           /* CTA "jouer" en teinte secondaire vive */
  --app-bg:         var(--acc-kid-bg, #f4f1ff);
  /* Le mode enfant est une surface claire ASSUMEE (texte fonce sur clair), meme si l'appareil du
     parent est en theme sombre -> on re-force les surfaces/texte/teintes clairs pour garantir le
     contraste AA en mode enfant quel que soit data-theme. */
  --app-tile:       #ffffff;
  --app-surface-2:  #f4f2fb;
  --app-border:     #e7e3f5;
  --app-border-soft:#e7e3f5;
  --app-text:       #26324a;
  --app-text-2:     #4a5568;
  --app-text-3:     #64748b;
  --app-ok:         #178a63;  --app-ok-bg:   #e3f2ec;
  --app-warn:       #8a5b00;  --app-warn-bg: #fdf6e3;
  --app-sport-bg:   #e8edf6;  --app-sport-ic:    #5266a4;
  --app-club-bg:    #fde7e5;  --app-club-ic:     #e3352c;
  --app-progress-bg:#efe9f8;  --app-progress-ic: #6f57b0;
  --app-money-bg:   #e3f2ec;  --app-money-ic:    #1f8a6b;
  --app-event-bg:   #fbe9e2;  --app-event-ic:    #c4623a;
  --app-dispo-bg:   #eaf3de;  --app-dispo-ic:    #5c8a1f;
}
/* Fond de page propre a chaque palette en mode enfant (la surface reste claire, la teinte
   change). Les couleurs de marque, elles, viennent de [data-accent] pose par le meme geste. */
[data-kid="1"][data-kid-color="violet"] { --acc-kid-bg: #f4f1ff; }
[data-kid="1"][data-kid-color="ocean"]  { --acc-kid-bg: #ecf7fd; }
[data-kid="1"][data-kid-color="jungle"] { --acc-kid-bg: #edfaf3; }
[data-kid="1"][data-kid-color="sun"]    { --acc-kid-bg: #fff6e6; }
[data-kid="1"][data-kid-color="berry"]  { --acc-kid-bg: #fdeff4; }

/* Selecteur de couleur ludique (apercu de teinte = fond litteral assume, ce n'est pas un badge d'etat) */
.cclub-kid-colors { display: flex; gap: 12px; padding: 8px 16px 2px; }
/* T9-AA2.2 -- LA CIBLE PASSE AU CRAN TACTILE DE L'APP. Mesure au navigateur : 34x34 pour les
   cinq pastilles, 36 px pour << Rendre la main >>, alors que le produit tient --app-tap (44).
   C'est l'ecran d'un ENFANT : la main y est plus petite, la visee moins sure, et une cible plus
   petite que le doigt n'est pas une petite cible -- c'est une cible qu'on rate. La pastille de
   couleur reste dessinee a 34 px (le disque), mais son BOUTON en fait 44 : on agrandit ce qu'on
   touche, pas ce qu'on voit. */
.cclub-kid-sw {
  width: var(--app-tap); height: var(--app-tap);
  border: 0; padding: 0; cursor: pointer;
  background: none;                       /* la couleur vit sur le disque, pas sur le bouton */
  display: inline-flex; align-items: center; justify-content: center;
}
.cclub-kid-sw::before {
  content: ""; width: 34px; height: 34px; border-radius: var(--app-radius-pill);
  border: 3px solid transparent; box-sizing: border-box;
  box-shadow: 0 1px 3px rgba(0,0,0,.18);
}
.cclub-kid-sw.is-on::before { border-color: var(--app-on-primary); outline: 2px solid var(--acc-1); }
/* LE FOCUS SE VOIT, ET IL NE SE CONFOND PAS AVEC L'ETAT ACTIF : l'etat actif se dit par le
   liseré du disque, le focus par un anneau autour du bouton. Deux signaux qui se ressemblent
   sur le meme element ne se distinguent plus. */
.cclub-kid-sw:focus-visible { outline: 3px solid var(--app-primary); outline-offset: -2px; border-radius: var(--app-radius-pill); }
/* LA COULEUR VIT SUR LE DISQUE, PAS SUR LE BOUTON : sans ce deplacement, agrandir la cible
   aurait peint un carre de 44 px a la place de la pastille. */
.cclub-kid-sw--violet::before { background: #6b4de6; }
.cclub-kid-sw--ocean::before  { background: #1f9bd6; }
.cclub-kid-sw--jungle::before { background: #1fa971; }
.cclub-kid-sw--sun::before    { background: #e8930c; }
.cclub-kid-sw--berry::before  { background: #d6336c; }

/* Les trois enveloppes du mode enfant, sorties des `style=` inline (R-34). Elles reprennent la
   gouttiere de 14 px du reste de l'app -- l'enfant ne doit pas voir un autre produit. */
.cclub-kid-act { margin: 14px 14px 0; }
.cclub-kid-act--tight { margin: 6px 14px 0; }
.cclub-kid-quizwrap { padding: 12px 6px 0; }
.cclub-kid-back-link { margin: 0 8px 6px; gap: 5px; }
.cclub-kid-foot { height: 20px; }

/* =========================================================================
 * APP-TUILE-CALENDRIER (build 1360) -- LA GRILLE PLANNING DE LA TUILE Calendrier.
 *
 * DEUX VUES, ET LE MEME ARBITRAGE QU'EN BACK-OFFICE (CAL-7) : on ne dessine pas une duree
 * qu'on ignore. Le modele d'entree normalise ne porte AUCUNE heure de fin -- ni les
 * evenements, ni les tournois, ni les rondes. Une grille horaire a blocs proportionnels
 * serait donc une fiction dessinee : elle affirmerait des durees que personne n'a saisies.
 *
 * VUE SEMAINE = sept bandes-jours empilees, chacune avec sa rangee << toute la journee >>
 * puis ses entrees horodatees dans l'ordre, HEURE EN CLAIR. C'est la forme native du
 * planning sur un telephone : sept colonnes de 53 px sur un ecran de 375 px ne se lisent
 * pas, et se toucher encore moins (cible tactile 48 px).
 * VUE MOIS = grille 7 x N compacte, une pastille de couleur par famille presente et le
 * compte du jour ; le jour touche ouvre son detail SOUS la grille. La vue mois repond a
 * << ou se passe-t-il quelque chose >>, pas a << a quelle heure >>.
 * ========================================================================= */

.cclub-cal-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
/* 36 px a l'oeil, 48 px au doigt : la zone est etendue par un pseudo-element, EXACTEMENT le
   patron que le design-system emploie deja pour les puces de la feuille de match
   (`.cclub-app-seg--dot::after`). Deux fleches de 48 px de large encadrant le libelle de periode
   ecraseraient l'en-tete ; la cible tactile, elle, n'est pas negociable. */
.cclub-cal-nav {
  width: 36px; height: 36px; flex: 0 0 auto; position: relative;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--app-border); border-radius: var(--app-radius-pill);
  background: var(--app-tile); color: var(--app-blue); cursor: pointer; padding: 0;
}
.cclub-cal-nav::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: var(--app-tap); height: var(--app-tap); transform: translate(-50%, -50%);
}
.cclub-cal-nav:active { transform: scale(.94); }
.cclub-cal-nav:focus-visible { outline: 2px solid var(--app-blue); outline-offset: 2px; }
/* PAS de text-transform ici : en francais les noms de mois sont en MINUSCULE.
   << 17 - 23 Aout 2026 >> est une faute, vue a l'ecran au premier rendu. */
.cclub-cal-per {
  flex: 1 1 auto; text-align: center; font-weight: 600; color: var(--app-text);
  font-size: var(--app-fs-lg);
}

/* Legende + filtres par famille : la MEME pastille sert de legende et de bouton de filtre.
   Deux objets distincts pour la meme information auraient double la surface pour rien. */
/* Ces boutons SONT des boutons de choix : ils empruntent la fabrique `.cclub-app-seg`
   (+ `--sm`) plutot que de la recopier -- geometrie, focus visible et surtout `min-height:
   var(--app-tap)` viennent d'elle. Reconstruire un jeu de chips a la main est exactement ce que
   la fabrique EA-2 a ete ecrite pour absorber, et c'est ainsi qu'une cible a 32 px etait passee.
   ON N'EMPLOIE PAS `.is-on` : l'etat allume de la fabrique remplit le bouton de bleu plein, ce
   qui noierait la pastille de couleur -- or c'est ELLE qui porte l'information de famille. Ici
   l'etat par defaut EST l'etat actif, et c'est l'extinction qui se signale. */
.cclub-cal-fam { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.cclub-cal-fam .cclub-app-seg.is-off { opacity: .45; }
.cclub-cal-dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; display: block; }

/* Familles : reemploi STRICT des teintes de domaine deja au socle (--app-*-ic), zero hex neuf.
   cours = dispo, evenement = event, tournoi = sport, interclubs/coupe = club. */
.cclub-cal-f-cours     { background: var(--app-dispo-ic); }
.cclub-cal-f-event     { background: var(--app-event-ic); }
.cclub-cal-f-tournoi   { background: var(--app-sport-ic); }
.cclub-cal-f-interclub { background: var(--app-club-ic); }

/* --- Vue SEMAINE : bandes-jours ---------------------------------------- */
.cclub-cal-day { border-top: 1px solid var(--app-border); padding: 8px 0 4px; }
.cclub-cal-day:first-child { border-top: 0; }
.cclub-cal-day.is-today .cclub-cal-dname { color: var(--app-blue); font-weight: 700; }
/* `capitalize` mettrait une majuscule a CHAQUE mot -- << Samedi 15 Aout 2026 >>, faute de
   francais vue a l'ecran. Seule la premiere lettre se capitalise. */
.cclub-cal-dname {
  font-size: var(--app-fs-sm); color: var(--app-text-3); margin-bottom: 2px;
}
.cclub-cal-dname::first-letter { text-transform: uppercase; }
.cclub-cal-empty { font-size: var(--app-fs-md); color: var(--app-text-3); padding: 2px 0 6px; }

/* Une entree : cible tactile pleine largeur, >= 48 px de haut. */
.cclub-cal-it {
  display: flex; gap: 9px; align-items: flex-start; width: 100%; text-align: left;
  min-height: var(--app-tap); padding: 7px 0; border: 0; background: none; cursor: pointer;
}
.cclub-cal-it:active { opacity: .7; }
.cclub-cal-it:focus-visible { outline: 2px solid var(--app-blue); outline-offset: 2px; }
.cclub-cal-h {
  flex: 0 0 46px; font-size: var(--app-fs-md); font-weight: 600;
  color: var(--app-text-2); font-variant-numeric: tabular-nums; padding-top: 1px;
}
/* Une entree SANS heure ne montre pas une heure inventee : elle montre qu'elle n'en a pas. */
.cclub-cal-h--allday { font-weight: 400; color: var(--app-text-3); }
.cclub-cal-bar { flex: 0 0 3px; align-self: stretch; border-radius: 2px; }
/* `display: block` N'EST PAS DECORATIF ICI. Le titre et le sous-titre sont des <span> (un <div>
   dans un <button> serait du contenu de flux dans un element interactif) : sans cette declaration
   ils restent INLINE et se collent bout a bout -- vu a l'ecran, << Adultes debutants - Mardi
   soirClub LOE >>. Meme famille de defaut que la piste d'occupation du build 1354 : le balisage
   est juste, l'element existe, et il ne se comporte pas comme on le lit. */
.cclub-cal-tx { flex: 1 1 auto; min-width: 0; }
.cclub-cal-h, .cclub-cal-tx, .cclub-cal-t, .cclub-cal-s { display: block; }
.cclub-cal-t { font-size: var(--app-fs-lg); color: var(--app-text); font-weight: 500; line-height: 1.3; }
.cclub-cal-s { font-size: var(--app-fs-sm); color: var(--app-text-2); line-height: 1.35; margin-top: 1px; }
.cclub-cal-go { flex: 0 0 auto; color: var(--app-text-3); align-self: center; }

/* --- Vue MOIS : grille compacte ---------------------------------------- */
.cclub-cal-mhead, .cclub-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; }
.cclub-cal-mhead { margin-bottom: 3px; }
.cclub-cal-mhead span {
  text-align: center; font-size: var(--app-fs-xs); color: var(--app-text-3);
  text-transform: uppercase; letter-spacing: .03em;
}
/* min-height sur le TOKEN, pas sur un 46 px ecrit a la main : la cellule est un <button>, donc
   une cible tactile, et deux pixels sous le seuil restent sous le seuil. */
.cclub-cal-cell {
  min-height: var(--app-tap); border-radius: 9px; background: var(--app-surface-2);
  border: 1px solid transparent; padding: 3px 2px 4px; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
}
.cclub-cal-cell:focus-visible { outline: 2px solid var(--app-blue); outline-offset: 1px; }
.cclub-cal-cell.is-out { opacity: .38; }
.cclub-cal-cell.is-today { border-color: var(--app-blue); }
.cclub-cal-cell.is-sel { background: var(--app-blue-bg); border-color: var(--app-blue); }
.cclub-cal-cell.is-void { cursor: default; }
.cclub-cal-n { font-size: var(--app-fs-sm); color: var(--app-text); font-variant-numeric: tabular-nums; }
.cclub-cal-cell.is-today .cclub-cal-n { color: var(--app-blue); font-weight: 700; }
.cclub-cal-dots { display: flex; gap: 2px; flex-wrap: wrap; justify-content: center; }
.cclub-cal-more { font-size: var(--app-fs-xs); color: var(--app-text-3); line-height: 1; }
.cclub-cal-sel-h {
  margin: 12px 0 2px; font-size: var(--app-fs-md); font-weight: 600;
  color: var(--app-text);
}
.cclub-cal-sel-h::first-letter { text-transform: uppercase; }

/* --- Feuille de detail d'une entree ------------------------------------- */
.cclub-cal-sheet-t { font-size: var(--app-fs-xl); font-weight: 600; color: var(--app-text); }
.cclub-cal-sheet-m { font-size: var(--app-fs-md); color: var(--app-text-2); margin-top: 3px; }
.cclub-cal-sheet-note {
  font-size: var(--app-fs-sm); color: var(--app-text-3);
  margin-top: 10px; line-height: 1.45;
}

/* Quota surface app (build 1412) : le bloc d'abonnement de l'écran Calendrier,
   et l'état de chargement de la grille — tous deux portaient leur style inline. */
.cclub-cal-loading {
  padding: 20px; text-align: center;
  color: var(--app-text-3); font-size: var(--app-fs-md);
}
.cclub-cal-abo-t {
  font-size: var(--app-fs-md); color: var(--app-text-2);
  line-height: 1.45; margin: 0 0 10px;
}
/* Séparateur de la feuille « Ajouter à mon agenda » : il distingue le
   téléchargement (qui fige) de l'abonnement (qui suit). */
.cclub-cal-sheet-sep {
  height: 1px; background: var(--app-line); margin: 16px 0 12px;
}
.cclub-cal-sub-item { margin: 10px 0; }
.cclub-cal-sub-lib  { font-weight: 600; font-size: var(--app-fs-md); margin-bottom: 4px; }
.cclub-cal-sub-url  {
  width: 100%; font-size: var(--app-fs-sm);
  padding: 6px 8px; border: 1px solid var(--app-line); border-radius: 8px;
  background: var(--app-bg-2); color: var(--app-text-1);
}

/* --- ETAT VIDE de l'espace membre (L8 residuel, build 1451) ------------------
   PREMIERE des SIX PRIMITIVES SANS NOM relevees par EA-0 -- liste, etat vide,
   champ, chargement, retour d'action, erreur. La mesure du 2026-08-22 disait
   l'essentiel : l'etage des TOKENS est sain (475 couleurs sur 476 par var(--app-*),
   zero hex, --app-fs sur les 447 tailles), mais l'etage AU-DESSUS manque -- aucun
   nom pour les motifs, donc 4 945 lignes ecrites a la main.

   Cet etat vide etait recopie SEPT FOIS dans le fichier, sous la forme
   `color:var(--app-text-2);font-size:var(--app-fs-lg)`. Il porte enfin un
   nom, et le prochain ecran n'aura plus a le redecouvrir.

   Ce n'est PAS le catalogue Cclub_App_* que EA-0 demande -- c'est une brique, et
   elle est posee ici parce que l'ecran logistique en avait besoin quatre fois.
   *Nommer un motif au moment ou l'on s'en sert coute une ligne ; le nommer apres
   coup suppose de retrouver ses sept copies.* */
/* --- LE PICTOGRAMME, ET POURQUOI IL SORT DE L'ECHELLE (build 1620) -----------
   NE D'UN REFUS DE RECETTE, ET LE DEFAUT ETAIT DANS MA PROPRE ANALYSE. Le build
   1616 annoncait un << chiffre vedette >> passant de 42 a 32 px, en demandant de
   le verifier a l'oeil -- sans dire ni lequel ni ou. Le president n'a rien trouve,
   et pour cause : ce n'etait pas un chiffre. C'est le PICTOGRAMME 🚧 de l'ecran de
   maintenance, sur un ecran qu'on ne voit qu'en panne.

   Il reprend sa taille d'origine et sort de l'echelle TYPOGRAPHIQUE, qui gouverne
   du texte. *Un pictogramme n'est pas un caractere qu'on lit : c'est une image
   faite de police, et la rapetisser au cran du texte lui retire sa fonction --
   etre vu avant d'etre lu.* Il garde le multiplicateur d'accessibilite. */
.cclub-app-picto {
  font-size: calc(var(--app-fs) * 42px);
  line-height: 1;
  margin-bottom: 8px;
}

.cclub-app-empty {
  color: var(--app-text-2);
  font-size: var(--app-fs-lg);
  padding: 10px 0;
}
/* MES ENGAGEMENTS (build 1632) : une facon de s'engager, et l'etat de mon voeu. La ligne porte
   son libelle et son bouton Oui/Non -- meme forme que la fiche du back-office, pour qu'un
   adherent retrouve a l'ecran ce qu'il a rempli sur le papier. */
.cclub-app-eng {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px solid var(--app-surface-2);
}
.cclub-app-eng:last-of-type { border-bottom: 0; }
.cclub-app-eng__t {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--app-fs-lg);
  color: var(--app-text-1);
}
.cclub-app-eng > .cclub-app-btn { flex: 0 0 auto; min-width: 72px; }
/* Le refus est une reponse, pas une case de plus : il se detache du catalogue au-dessus. */
.cclub-app-eng--refus {
  margin-top: 10px;
  padding-top: 14px;
  border-top: 1px solid var(--app-surface-2);
  border-bottom: 0;
}
.cclub-app-eng__intro {
  font-size: var(--app-fs-md);
  color: var(--app-text-2);
  padding-bottom: 10px;
}
.cclub-app-eng__role {
  font-size: var(--app-fs-lg);
  color: var(--app-text-1);
  padding: 6px 0;
}
.cclub-app-eng__role + .cclub-app-eng__role { border-top: 1px solid var(--app-surface-2); }
a.cclub-app-eng__role {
  display: flex; align-items: center; gap: 8px;
  min-height: var(--app-tap);
  color: var(--app-blue); text-decoration: none; cursor: pointer;
}
.cclub-app-eng__autre { padding: 12px 0 14px; }
.cclub-app-eng__autre label {
  display: block;
  font-size: var(--app-fs-md);
  color: var(--app-text-2);
  padding-bottom: 6px;
}

/* PropoArb-1 : une PROPOSITION d'arbitrage en attente de reponse. Elle ne se confond pas
   avec un arbitrage confirme -- elle porte ses deux gestes, et rien tant qu'on n'a pas
   repondu. Les actions passent sous le texte en dessous de 380px : deux boutons et un
   libelle de tournoi ne tiennent pas sur une ligne de telephone etroit. */
.cclub-app-propo {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--app-surface-2);
}
.cclub-app-propo:last-child { border-bottom: 0; }
.cclub-app-propo__txt { flex: 1 1 180px; min-width: 0; }
.cclub-app-propo__t {
  font-size: var(--app-fs-lg);
  font-weight: 600;
  color: var(--app-text-1);
}
.cclub-app-propo__d {
  font-size: var(--app-fs-md);
  color: var(--app-text-2);
}
.cclub-app-propo__acts { display: flex; gap: 8px; flex: 0 0 auto; }
.cclub-app-propo__acts .cclub-app-btn[disabled] { opacity: .55; pointer-events: none; }

/* =========================================================================
 * LA FICHE D'ARBITRAGE -- et les quatre classes qui n'avaient AUCUN STYLE.
 *
 * `cclub-arb-h`, `cclub-arb-pre`, `cclub-arb-code` et `cclub-arb-note` etaient
 * employees par la modale de detail d'arbitrage depuis le T9-C1.1 (2026-08-31) :
 * mesure du 2026-09-15, elles n'existaient dans AUCUNE feuille, ni ici, ni en
 * ligne. Le mot de passe du tournoi se rendait donc en texte courant, au milieu
 * du reste. *Une classe posee sur un element ne promet rien : c'est la feuille
 * qui decide, et une classe sans regle se lit comme un style qui existe.*
 * ========================================================================= */
.cclub-arb-h   { margin-top: 14px; }
.cclub-arb-pre { white-space: pre-line; font-size: var(--app-fs-md); color: var(--app-text-2); }
.cclub-arb-note{ margin-top: 6px; font-size: var(--app-fs-sm); color: var(--app-red-dark); }

/* CodeTournoi-1 -- LE SECRET EST MASQUE PAR DEFAUT (DEC-2026-08-22, point 4).
   La ligne porte le masque et son bouton cote a cote ; le bouton herite de
   `--app-tap` via .cclub-app-btn--sm, donc la cible tactile est tenue. */
.cclub-arb-code {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 6px; padding: 10px 12px;
  background: var(--app-surface-2);
  border: 1px solid var(--app-border);
  border-radius: var(--app-radius);
}
/* /!\ LE TOKEN DU MASQUE A CHANGE AVANT MEME D'ETRE LIVRE, ET C'EST UNE MESURE QUI L'A DIT.
   J'avais pris `--app-text-3` (meta) pour le retrait visuel. Calcul WCAG sur la feuille reellement
   servie : #64748b sur #f1efe9 = **4,14:1**, sous le seuil AA de 4,5 pour du texte de 14px.
   Le commentaire du token dit vrai -- il EST conforme *sur blanc* (4,76:1) -- mais cette carte
   pose un fond `--app-surface-2`, un peu plus sombre que blanc, et le duo repasse dessous.
   *Un token declare conforme l'est sur le fond ou on l'a mesure, pas sur tous les fonds.*
   `--app-text-2` donne **6,55:1** en clair et reste en retrait de `--app-text`. */
.cclub-arb-code__v {
  flex: 1 1 120px; min-width: 0;
  font-size: var(--app-fs-lg); font-weight: 600; letter-spacing: 3px;
  color: var(--app-text-2);          /* masque : present, mais en retrait -- et AA sur CE fond */
  word-break: break-all;
}
/* Le bouton est desactive pendant l'appel reseau (`b.disabled=true`) : sans cette regle, rien ne
   signale que l'appui a ete pris en compte. La fabrique porte bien un etat desactive, mais il est
   aujourd'hui limite aux propositions d'arbitrage -- on le reprend ICI plutot que d'elargir une
   regle globale a tous les boutons de l'app, ce qui serait un changement d'une autre portee. */
.cclub-arb-code .cclub-app-btn[disabled] { opacity: .55; pointer-events: none; }
/* REVELE -- chasse FIXE, et c'est une exception ASSUMEE a `--cclub-font`, celle
   que l'en-tete de cette feuille nomme deja : *<< la chasse fixe (un numero de
   cheque, une CLE TECHNIQUE -- l'alignement porte du sens) >>*. Un mot de passe
   se relit caractere par caractere ; le O et le 0 doivent se distinguer. */
.cclub-arb-code__v.is-clair {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: 1px;
  color: var(--app-text);
  -webkit-user-select: all; user-select: all;   /* un appui long selectionne tout */
}
/* Variante PLEINE PAGE de l'etat vide : quand le vide occupe l'ecran entier et non
   un coin de carte, il se centre et respire. C'est ce que `emptyNote()` ecrivait a
   la main depuis toujours. Deux crans d'un MEME objet, pas deux objets. */
.cclub-app-empty--page {
  padding: 30px 20px;
  text-align: center;
}

/* =========================================================================
 * CATALOGUE DE COMPOSANTS DE L'APP (A2 / CatalogueApp-1, build 1612)
 * Emis par includes/clubs/class-cclub-app-ui.php ; vocabulaire arrete par
 * docs/reference/SPEC-VOCABULAIRE-APP.md.
 *
 * CE QUI EST NOMME ICI ETAIT ECRIT A LA MAIN, ET LA MESURE LE DISAIT :
 *   - la CARTE   : 81 appels, un seul `style=` de 214 caracteres recopie dans la fabrique ;
 *   - la RANGEE  : 21 fabriques concurrentes, une par ecran qui l'a redecouverte.
 *
 * Pourquoi `--kv` est AUTONOME et ne compose pas avec `.cclub-app-row` : cette
 * derniere existe deja et porte une bordure BASSE (ligne de liste), quand la
 * rangee cle/valeur porte une bordure HAUTE. Les composer obligerait la variante
 * a defaire la base. *Deux motifs qui doivent s'annuler l'un l'autre ne sont pas
 * une base et son modificateur.*
 * ========================================================================= */
.cclub-app-card {
  background: var(--app-tile);
  border: 1px solid var(--app-border);
  border-radius: 16px;
  margin: 14px;
  padding: 12px 16px;
}
.cclub-app-card__t {
  font-size: var(--app-fs-md);
  color: var(--app-text-2);
  margin-bottom: 6px;
}
.cclub-app-kv {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  font-size: var(--app-fs-lg);
  padding: 5px 0;
  border-top: 1px solid var(--app-surface-2);
}
.cclub-app-kv__k { color: var(--app-text-2); }
/* `text-align:right` et non `flex-end` : la valeur peut passer a la ligne, et
   c'est son TEXTE qui doit rester aligne a droite, pas seulement sa boite. */
.cclub-app-kv__v { color: var(--app-text); font-weight: 500; text-align: right; }

/* --- LES DEUX ETATS QU'UN ECRAN MONTRE AVANT SON CONTENU (ARB-2, build 1456) --
   2e et 3e des SIX primitives sans nom relevees par EA-0 (liste, etat vide,
   champ, CHARGEMENT, retour d'action, ERREUR).

   Elles sont nommees ICI parce qu'ARB-2 rend la mini-app d'arbitrage
   atteignable pour la premiere fois : un arbitre qui l'ouvre aujourd'hui voit
   EXACTEMENT ces deux etats-la, puis l'etat vide -- jamais une ligne de contenu,
   le club n'ayant encore affecte personne. *Le premier ecran d'une surface neuve
   est celui de son etat vide, pas celui de son etat plein.*

   MESURE, pour que la dette ne soit pas silencieuse : le motif d'erreur de
   chargement est ecrit A LA MAIN 12 FOIS dans l'app membre. Onze restent, et
   c'est declare -- les reprendre releve de `LOT-ERGO-APP`/EA-0, dont le
   perimetre est l'app entiere, pas cet ecran. */
.cclub-app-load {
  padding: 20px 0;
  text-align: center;
  color: var(--app-text-3);
  font-size: var(--app-fs-md);
}
.cclub-app-err {
  padding: 20px 0;
  text-align: center;
  color: var(--app-red-dark);
  font-size: var(--app-fs-md);
}
/* --- LE CHAMP DE SAISIE (A3c, build 1615) ------------------------------------
   4e des SIX PRIMITIVES SANS NOM, et la derniere. Dix-neuf champs, aucune
   fabrique : chacun habille a la main, avec 4 rayons, 8 rembourrages, 5 tailles
   de texte et 2 bordures differentes.

   SON ABSENCE AVAIT PRODUIT TROIS DEFAUTS, tous MESURES sur la page servie et
   qu'aucun compteur du projet ne pouvait voir :

   1. LA POLICE. Les champs natifs n'heritent PAS de la police du document : ils
      s'affichaient en Arial pendant que toute l'app est en Segoe UI / Roboto.
      Personne ne l'avait declare -- il n'y avait pas d'endroit pour le faire.
   2. LA CIBLE TACTILE. Les champs mesuraient 36 px de haut, quand l'app declare
      elle-meme --app-tap: 48px comme minimum. *Un produit qui nomme sa cible
      tactile et ne l'applique pas a ses champs ne s'est pas trompe de valeur :
      il n'a jamais eu d'endroit ou l'appliquer.*
   3. LE THEME SOMBRE. DIX-SEPT champs sur 19 ne declaraient ni fond ni couleur :
      ils restaient BLANCS en surface sombre. Le texte y etait lisible (21:1),
      donc aucun controle de contraste ne pouvait le signaler -- c'est une tache
      claire au milieu d'une interface sombre, et cela ne se voit qu'en regardant.

   `font: inherit` couvre la police ET la graisse ; la taille est redonnee juste
   apres, sinon elle suivrait celle du parent au lieu du cran choisi. */
.cclub-app-field {
  width: 100%; box-sizing: border-box;
  min-height: var(--app-tap);
  padding: 10px 12px;
  border: 1px solid var(--app-border);
  border-radius: 10px;
  background: var(--app-tile);
  color: var(--app-text);
  font: inherit;
  /* 16 px PLANCHER, ET C'EST UNE CONTRAINTE TECHNIQUE, PAS UN GOUT : Safari sur
     iPhone ZOOME la page des qu'un champ recoit le focus avec un texte sous
     16 px. L'app en avait 17 dans ce cas -- a chaque saisie, la page sautait.
     `max()` laisse le reglage de taille du membre AGRANDIR le texte, jamais le
     faire repasser sous le plancher. *Un reglage de confort qui reintroduit un
     saut de page a chaque frappe n'est plus un reglage de confort.* */
  font-size: max(16px, var(--app-fs-xl));
}
/* Le champ n'est pas toujours pleine largeur : un rang dans une composition
   d'equipe tient sur trois caracteres. La CIBLE TACTILE, elle, ne se negocie
   pas -- c'est la largeur qui varie, jamais la hauteur. */
.cclub-app-field--inline { width: auto; }
.cclub-app-field--zone   { min-height: 92px; padding: 10px 12px; }
.cclub-app-field:focus-visible {
  outline: 2px solid var(--app-blue); outline-offset: 1px; border-color: var(--app-blue);
}

/* --- LE RETOUR D'ACTION (A3b, build 1614) ------------------------------------
   5e des SIX PRIMITIVES SANS NOM. Elle n'avait pas seulement perdu son nom : elle
   n'existait pas. L'app rendait ses 22 retours d'action avec la boite NATIVE du
   navigateur (`window.alert`), au milieu d'une interface par ailleurs soignee.

   POURQUOI LE FOND N'EST PAS ROUGE POUR UNE ERREUR, ET C'EST UN PIEGE EVITE :
   `--app-red-dark` vaut `--acc-2-deep` en surface claire (rouge sombre, encre sur
   blanc) mais `--acc-2-lite` en surface SOMBRE -- un rouge ECLAIRCI, fait pour
   etre du TEXTE sur fond sombre. L'employer comme FOND avec du texte clair aurait
   donne, en theme sombre, du quasi-blanc sur du rose. *Un token dit un role, pas
   une couleur : le lire comme une couleur marche jusqu'au jour ou la surface
   change.*
   Le toast prend donc `--app-text` en fond et `--app-tile` en texte : les deux
   s'inversent ENSEMBLE avec la surface, donc le contraste est garanti des deux
   cotes sans qu'aucune valeur ne soit ecrite deux fois. L'erreur se distingue par
   un LISERE de marque, qui n'a pas de contrainte de lisibilite.

   La barre de navigation n'est pas `fixed` (elle est en flux, `margin-top:auto`) :
   le toast se pose donc au-dessus d'elle en dur, sinon il la recouvrirait. */
/* REFONTE AU BUILD 1618, SUR TROIS GRIEFS DE RECETTE -- l'ergonomie etait acceptee, sa mise en
   oeuvre refusee : << la police denote de la charte >>, << l'affichage est trop discret, et il est
   possible de le rater >>, << le noir denote ; j'assombrirais le reste de l'ecran >>.

   1. LA POLICE. Le premier grief a la MEME cause que les champs en Arial du build 1615, et la
      feuille l'avait deja ecrit au build 1360, huit lignes plus bas : ce qui est pose en fin de
      <body> sort de `.cclub-app` et herite de la page hote -- Times New Roman dans l'apercu.
      *Un piege documente a cote de la ligne qu'on ecrit ne protege que celui qui lit le
      voisinage.* La pile est donc REPOSEE ici, comme sur les voiles.
   2. LA VISIBILITE. Le message ne descend plus dans un coin : l'ecran s'assombrit et il parait
      au centre. Le voile ne BLOQUE pas -- c'est tout ce qui le distingue encore de la boite
      native qu'on remplace.
   3. LE NOIR. Le fond reprend la surface de carte : c'est le voile qui porte le contraste, pas
      une couleur etrangere a la charte. */
.cclub-app-toasts {
  position: fixed; inset: 0;
  z-index: 100002;              /* au-dessus de la surcouche de menu (10000) */
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  font-family: var(--cclub-font, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif);
  background: rgba(10, 14, 20, .42);
  opacity: 0; transition: opacity .18s ease;
  pointer-events: none;         /* le voile assombrit, il n'emprisonne pas */
}
.cclub-app-toasts.is-on { opacity: 1; }
.cclub-app-toast {
  pointer-events: auto;
  background: var(--app-tile); color: var(--app-text);
  border: 1px solid var(--app-border);
  border-radius: 14px; padding: 16px 18px;
  max-width: min(88vw, 380px);
  font-size: var(--app-fs-xl); line-height: 1.4; font-weight: 500; text-align: center;
  box-shadow: 0 10px 34px rgba(10, 14, 20, .34);
  opacity: 0; transform: scale(.94);
  transition: opacity .18s ease, transform .18s ease;
  cursor: pointer;              /* on peut le chasser sans attendre */
}
.cclub-app-toast.is-in { opacity: 1; transform: scale(1); }
/* L'erreur garde son liseré de marque, elargi : il porte seul la distinction, et n'a aucune
   contrainte de lisibilite puisqu'il ne porte pas de texte. */
.cclub-app-toast--err { border-left: 5px solid var(--acc-2); }
/* Le mouvement est un confort, jamais le porteur de l'information. */
@media (prefers-reduced-motion: reduce) {
  .cclub-app-toast { transition: none; transform: none; }
  .cclub-app-toast.is-in { transform: none; }
}

/* Cran DENSE des deux etats (A3, build 1613) : dans une carte deja serree -- une
   ligne de tableau, un panneau d'echeances -- le cran pleine page ouvre un trou au
   milieu du contenu. Les treize ecritures a la main du chargement se repartissaient
   d'elles-memes en ces deux crans : six centrees a 20-24 px, trois collees a 6-8 px.
   *Un motif recopie six fois a l'identique n'est pas une variation, c'est un cran
   qui n'a pas ete nomme.* */
.cclub-app-load--dense,
.cclub-app-err--dense {
  padding: 6px 0;
  text-align: left;
  font-size: var(--app-fs-sm);
}

/* --- LES MOTIFS DE L'ECRAN LOGISTIQUE, NOMMES (L8 residuel, build 1452) -------
   MA DETTE, ET LE CLIQUET L'A DITE SANS AMBIGUITE : le premier jet de cet ecran
   a fait monter `style_app` de 505 a 514. R-33c ne laisse pas le choix -- on
   corrige, on ne releve pas le plafond.

   Et c'est la DEMONSTRATION de ce que EA-0 a mesure : j'ai ecrit ces neuf motifs
   a la main parce qu'AUCUN n'a de nom. L'etage des tokens est sain (tout passe
   par var(--app-*)), l'etage au-dessus manque. Chacun en recoit un ici -- ce
   n'est pas le catalogue Cclub_App_* que EA-0 demande, ce sont ses premieres
   briques, posees la ou le besoin s'est presente. */
.cclub-app-t     { font-weight: 600; font-size: var(--app-fs-lg); }
.cclub-app-sub   { font-size: var(--app-fs-sm); color: var(--app-text-2); }
.cclub-app-in    { padding-left: 10px; }
.cclub-app-sect  { font-weight: 600; font-size: var(--app-fs-md); margin: 12px 0 4px; }
.cclub-app-num   { font-size: var(--app-fs-xl); font-weight: 700; }
.cclub-app-lbl   { font-size: var(--app-fs-xs); color: var(--app-text-2); }
.cclub-app-stats { display: flex; gap: 14px; margin: 10px 0; flex-wrap: wrap; }
.cclub-app-box   { border: 1px solid var(--app-border-soft); border-radius: 12px;
                   padding: 8px 10px; margin-bottom: 6px; }
.cclub-app-boxt  { font-weight: 600; font-size: var(--app-fs-md); }
.cclub-app-boxn  { color: var(--app-text-2); font-weight: 400; }
.cclub-app-row   { border-bottom: 1px solid var(--app-border-soft); padding: 2px 0; }
.cclub-app-name  { font-size: var(--app-fs-md); }
/* CIBLE DE 48 px : on compose un numero au doigt, dans un gymnase, parfois en
   courant. Ce n'est pas une marge de confort, c'est la condition pour que le
   lien soit atteignable. */
.cclub-app-tel   { display: inline-flex; align-items: center; min-height: 48px;
                   color: var(--app-accent); }
.cclub-app-tel-s { color: var(--app-accent); }

/* ── T9-AA2.3 : l'écran des mercredis, groupé par créneau ──────────────────
   Ces classes remplacent des `style=` inline que ma première version avait
   posés : le filet NR-ERGO-STD est un CLIQUET, ses compteurs ne peuvent que
   descendre. 🔑 *Écrire un écran neuf en style inline ne crée pas une dette
   plus tard : elle est déjà là au moment du build.* */
.cclub-merc-pills { display: flex; flex-wrap: wrap; gap: 8px;
                    padding: 0 14px 14px; margin-top: -8px; }
/* Cible de 48 px : on la touche au doigt, souvent debout dans le hall du club. */
.cclub-merc-who   { display: inline-flex; align-items: center; gap: 6px;
                    padding: 7px 12px; min-height: 48px;
                    border: 1px solid var(--app-surface-2); border-radius: 999px;
                    background: var(--app-tile); color: var(--app-text);
                    font-size: var(--app-fs-md); cursor: pointer; text-decoration: none; }
/* La pastille dit qu'une absence est déjà annoncée : sans elle il faudrait
   ouvrir la feuille pour le savoir. */
.cclub-merc-dot   { width: 8px; height: 8px; border-radius: 50%;
                    background: var(--app-warn); }
.cclub-merc-hint  { font-size: var(--app-fs-sm); color: var(--app-text-2);
                    padding-bottom: 4px; }
.cclub-merc-sheet { padding: 0 2px; }
.cclub-merc-line  { display: flex; justify-content: space-between; align-items: center;
                    gap: 10px; padding: 8px 0; border-top: 1px solid var(--app-surface-2); }
.cclub-merc-when  { font-size: var(--app-fs-md); color: var(--app-text); }
.cclub-merc-when--off { color: var(--app-text-2); }
.cclub-merc-act   { cursor: pointer; font-size: var(--app-fs-sm); white-space: nowrap;
                    color: var(--app-text-2); }
.cclub-merc-act--back { color: var(--app-blue); }

/* ============================================================================================
   LES ACTIONS DE LIGNE DE L'APP (build 1808, recette groupee des portes).

   MESURE au navigateur en 375 px, AVANT : dix-sept cibles d'action a 16-17 px de haut sur
   trois portes -- << Demander a m'inscrire >> (8, Les cours du club), << Faire l'appel >> et
   << Je ne pourrai pas >> (8, Mes interventions), et l'appel a benevolat (1). Le produit tient
   pourtant --app-tap (48 px).

   CE NE SONT PAS DES LIENS DANS UNE PHRASE : mesures `display:block`, sur leur propre ligne, et
   ce sont les gestes LES PLUS UTILES de ces portes -- s'inscrire a un cours, faire l'appel d'une
   seance, se declarer indisponible, repondre a un appel du club.

   *Une cible plus petite que le doigt n'est pas une petite cible : c'est une cible qu'on rate.
   Et sur une action d'inscription, la rater ne se solde pas par un geste a refaire -- elle se
   solde par une inscription qui n'a pas lieu, et que personne ne compte.*

   La hauteur vient d'un `min-height` + un centrage, JAMAIS d'un `padding` vertical seul : le
   padding grossirait aussi la zone coloree au survol et decollerait la ligne du tableau qui la
   porte. On agrandit ce qu'on TOUCHE, pas ce qu'on VOIT (meme regle qu'au mode enfant).
   ============================================================================================ */
.cclub-app-rowact {
  display: inline-flex;
  align-items: center;
  min-height: var(--app-tap);
  cursor: pointer;
  white-space: nowrap;
  font-size: var(--app-fs-md);
  color: var(--app-blue);
}
/* Se retirer, annuler : le rouge d'action du produit, jamais une autre nuance. */
.cclub-app-rowact--off {
  color: var(--app-red-dark);
  font-size: var(--app-fs-sm);
}
.cclub-app-rowact:focus-visible {
  outline: 2px solid var(--app-primary);
  outline-offset: 2px;
  border-radius: 6px;
}
/* Les deux actions d'encadrant heritaient de `.cclub-merc-act` (13 px, gris) : elles gardent
   leur couleur et leur taille, et ne prennent d'ici que la CIBLE. */
.cclub-merc-act.cclub-app-rowact { font-size: var(--app-fs-sm); color: var(--app-text-2); }
/* Champ de motif de la feuille d'absence — 44 px : saisie au pouce. */
.cclub-abs-lbl    { display: block; font-size: var(--app-fs-sm); color: var(--app-text-2);
                    padding-bottom: 4px; }
.cclub-abs-input  { width: 100%; min-height: 44px; box-sizing: border-box; padding: 0 12px;
                    border: 1px solid var(--app-surface-2); border-radius: 8px;
                    background: var(--app-tile); color: var(--app-text);
                    font-size: var(--app-fs-md); }
.cclub-abs-note   { font-size: var(--app-fs-sm); color: var(--app-text-2); padding-top: 6px; }

/* ── T9-AA2.3-B : la feuille d'appel de l'encadrant ────────────────────────
   Écrites en classes dès le premier jet : le cliquet NR-ERGO-STD ne peut que
   descendre, et la dette d'un écran neuf est là au moment du build. */
.cclub-anim-row   { display: flex; justify-content: space-between; align-items: center;
                    gap: 10px; padding: 7px 0; border-top: 1px solid var(--app-surface-2); }
.cclub-anim-main  { flex: 1; min-width: 0; }
.cclub-anim-t     { font-size: var(--app-fs-lg); color: var(--app-text); font-weight: 500; }
.cclub-anim-s     { font-size: var(--app-fs-sm); color: var(--app-text-2); }
.cclub-anim-when  { font-size: var(--app-fs-sm); color: var(--app-text-2);
                    white-space: nowrap; text-align: right; }
.cclub-anim-acts  { display: flex; flex-wrap: wrap; gap: 14px; padding: 2px 0 8px; }
/* Ligne de la feuille : le nom à gauche, les deux touches à droite. */
.cclub-enc-line   { display: flex; justify-content: space-between; align-items: center;
                    gap: 10px; padding: 7px 0; border-top: 1px solid var(--app-surface-2); }
.cclub-enc-nom    { flex: 1; min-width: 0; font-size: var(--app-fs-md); color: var(--app-text); }
/* L'absence annoncée par la famille reste visible pendant le pointage : elle dit
   qui ne pas attendre, et n'empêche pas de pointer présent celui qui vient. */
.cclub-enc-flag   { display: block; font-size: var(--app-fs-sm); color: var(--app-warn); }
.cclub-enc-acts   { display: flex; gap: 8px; }
/* 44 px : on pointe debout, au pouce, parfois d'une seule main. */
.cclub-enc-b      { display: inline-flex; align-items: center; justify-content: center;
                    width: 44px; height: 44px; border-radius: 50%;
                    border: 1px solid var(--app-surface-2); background: var(--app-tile);
                    color: var(--app-text-2); font-size: var(--app-fs-md); font-weight: 600;
                    cursor: pointer; text-decoration: none; }
.cclub-enc-b--on          { color: var(--app-on-primary); border-color: transparent; }
.cclub-enc-b--on.cclub-enc-b--present { background: var(--app-ok); }
.cclub-enc-b--on.cclub-enc-b--absent  { background: var(--app-red); }
.cclub-anim-q     { font-size: var(--app-fs-lg); color: var(--app-text); }
.cclub-anim-h     { font-size: var(--app-fs-md); color: var(--app-text-2); margin-top: 6px; }
.cclub-anim-cta   { margin-top: 10px; }
.cclub-anim-cta .cclub-app-btn { max-width: 200px; font-size: var(--app-fs-lg); padding: 10px 14px; }

/* ============================================ LES CONTROLES HERITENT DE LA POLICE DE L APP
   Refus de recette EXP-0055 : << les polices ne respectent pas les polices standardisees sur
   l application Smartphone >>. Mesure a l ecran : le corps de l app est en -apple-system, les
   boutons du quiz en ARIAL.

   LA CAUSE N EST PAS UNE FEUILLE OUBLIEE, C EST UNE REGLE DU NAVIGATEUR : un <button>, un
   <input>, un <select> et un <textarea> n heritent PAS de la police de leur parent -- ils
   prennent celle du systeme. Tant qu un bouton porte une classe qui fixe sa police, rien ne
   se voit ; le jour ou l on en ecrit un sans, il change de fonte tout seul.
   *Une propriete qui ne s herite pas ne se rappelle a personne : elle se contente d etre
   fausse la ou on a oublie de l ecrire.*

   La regle est posee sur la RACINE de l app plutot que sur chaque composant : elle couvre
   ainsi les boutons ecrits en HTML inline par le JS, qui n ont aucune feuille a eux. */
.cclub-app button,
.cclub-app input,
.cclub-app select,
.cclub-app textarea { font-family: inherit; }

/* ============================================================================================
   LE `select` PRENAIT LA POLICE DE L'APP, ET RIEN D'AUTRE (T9-A3.3, recette de PORTE-TRANSV).

   MESURE au navigateur, sur un champ temoin pose dans l'app : la POLICE est bien heritee, et la
   TAILLE suit le reglage (13 px -> 16,9 px en cran XL, verifie en poussant le reglage puis en le
   restaurant). Mais le `select`, lui, sortait en **noir sur blanc, 21 px de haut** : le style
   natif du navigateur. En theme sombre il serait donc reste blanc, et sous le cran tactile dans
   tous les cas.

   *Un controle qui herite la police d'un theme sans en heriter les couleurs ne parait pas
   depourvu de style : il parait appartenir a un autre produit -- et en theme sombre, il eblouit.*

   On ne lui retire PAS son chevron natif (`appearance`) : le remplacer obligerait a redessiner
   l'ouverture, le clavier et l'etat desactive, pour un gain d'apparence. On lui donne ce qui
   manque -- la couleur, le fond, la bordure du socle et la cible.
   ============================================================================================ */
.cclub-app select {
  min-height: var(--app-tap);
  padding: 0 10px;
  border: 1px solid var(--app-surface-2);
  border-radius: 8px;
  background: var(--app-tile);
  color: var(--app-text);
  font-size: var(--app-fs-md);
}
.cclub-app select:focus-visible { outline: 2px solid var(--app-primary); outline-offset: 2px; }

/* CE QUE L APP POSE HORS D ELLE-MEME : le bouton flottant d installation et les surcouches
   sont ajoutes au <body>, donc en dehors de .cclub-app -- ils n heritaient de rien. Mesure a
   l ecran apres le premier correctif : le bouton << Installer l app >> restait en Arial.
   *Un reset borne a un conteneur ne protege pas ce que le meme code ajoute a cote.* */
[id^="cclub-"], [id^="cclub-"] button, [id^="cclub-"] input { font-family: var(--app-font); }

/* ============================================================================================
   BALAYAGE ENTRE LES ZONES DE LA BARRE (demande presidentielle du 2026-09-04).

   LE SENS DU MOUVEMENT DOIT SE VOIR. Sans glissement, le contenu est simplement remplace et
   rien ne dit qu'on s'est deplace LATERALEMENT : le raccourci se lit alors comme un
   rechargement fortuit, et l'on ne sait plus si l'on a avance ou recule.

   L'ecran ENTRE depuis le cote d'ou il vient : un balayage vers la gauche fait entrer le
   suivant par la droite. C'est le seul sens qui ne contredise pas le doigt.

   ON N'ANIME QUE `transform`, JAMAIS `left` NI `margin` : le conteneur porte le defilement
   vertical de toute l'app, et animer une propriete de mise en page le recalculerait a chaque
   image. `will-change` n'est PAS pose -- la classe ne vit que 220 ms, et le laisser en
   permanence reserverait une couche graphique pour un effet qui ne joue presque jamais.
   ============================================================================================ */
@keyframes cclub-slide-de-la-droite { from { transform: translateX(7%); opacity: .55; } to { transform: none; opacity: 1; } }
@keyframes cclub-slide-de-la-gauche { from { transform: translateX(-7%); opacity: .55; } to { transform: none; opacity: 1; } }
.cclub-app--slide-gauche { animation: cclub-slide-de-la-droite 220ms ease-out; }
.cclub-app--slide-droite { animation: cclub-slide-de-la-gauche 220ms ease-out; }

/* Le mouvement est un confort, jamais le porteur de l'information : la navigation reste
   entiere sans lui. */
@media (prefers-reduced-motion: reduce) {
  .cclub-app--slide-gauche, .cclub-app--slide-droite { animation: none; }
}
