/* Coquille, thèmes et écrans communs (classement, stats, profil, ligues,
   authentification). Les règles propres à un jeu vivent dans css/<clé>.css
   (voir css/mot.css). */
:root{
  --safe-top:env(safe-area-inset-top,0px); --safe-bottom:env(safe-area-inset-bottom,0px);
  /* Marges effectivement appliquées : recalculées en JS (`setSafePadding`),
     car iOS annonce parfois une zone de sécurité DÉJÀ exclue du web view. */
  --pad-top:env(safe-area-inset-top,0px); --pad-bottom:env(safe-area-inset-bottom,0px);
  --bg:#eef0f7; --surface:#ffffff; --surface-2:#f6f7fb;
  --text:#15161d; --text-2:#575c6b; --muted:#8b90a0;
  --border:rgba(16,20,40,.10); --border-strong:rgba(16,20,40,.18);
  --brand:#332a52; --brand-2:#4a3d74;
  --accent:#6b5ce7; --accent-ink:#ffffff; --accent-soft:#e6e2fc;
  --ok:#4ea24e; --ok-soft:#e4f2e4;
  --maybe:#c9a227; --maybe-soft:#f8efd2;
  --no:#d03b3b; --no-soft:#f7dede;
  /* Encre des cases et des touches MARQUÉES. En clair comme en sombre c'est
     du blanc ; le thème rouge, lui, n'a pas droit au blanc (il rallumerait le
     bleu) et redéfinit ces variables. Ne pas remettre `color:#fff` en dur. */
  --ok-ink:#ffffff; --maybe-ink:#ffffff; --maybe-ring:transparent;
  /* Logo (barre latérale + écran de connexion) et encre de la barre latérale,
     en variables pour la même raison. */
  --logo-from:#6b5ce7; --logo-to:#a78bfa; --logo-ink:#ffffff;
  --side-ink:#ffffff; --side-ink-2:rgba(255,255,255,.72); --side-ink-3:rgba(255,255,255,.6);
  --side-hover:rgba(255,255,255,.08); --side-active:rgba(255,255,255,.14);
  --photo-filter:none;
  /* Cases « lettre absente » et touches du clavier. En clair, une case
     absente est nettement plus foncée que le fond ; une touche non jouée est
     claire et une touche éliminée devient foncée. */
  --tile-absent:#7e8492; --tile-absent-ink:#ffffff;
  --key:#d7dbe6; --key-ink:#15161d;
  --key-absent:#9aa0ad; --key-absent-ink:#ffffff;
  --shadow:0 1px 2px rgba(16,24,40,.06),0 8px 24px rgba(16,24,40,.06);
  --shadow-lg:0 12px 40px rgba(16,24,40,.16);
  --radius:16px; --radius-sm:12px;
  /* Chaud ou Froid : rampe de chaleur des paliers, glacial (0) → trouvé (7),
     bleu → rouge. Déclarée dans les quatre thèmes. */
  --heat-0:#5b7fd9; --heat-1:#5aa6df; --heat-2:#5fc2c3; --heat-3:#86c46c;
  --heat-4:#dcc23a; --heat-5:#f0952e; --heat-6:#e8602c; --heat-7:#d63a2f;
}
:root[data-theme="dark"]{
  --bg:#0d0e14; --surface:#171922; --surface-2:#1e212c;
  --text:#f4f5fa; --text-2:#b3b9c8; --muted:#858b9b;
  --border:rgba(255,255,255,.12); --border-strong:rgba(255,255,255,.22);
  --brand:#1a1630; --brand-2:#2c2450;
  --accent:#8878ff; --accent-ink:#ffffff; --accent-soft:rgba(136,120,255,.20);
  --ok:#57ab57; --ok-soft:rgba(87,171,87,.18);
  --maybe:#cda52c; --maybe-soft:rgba(205,165,44,.18);
  --no:#e05656; --no-soft:rgba(224,86,86,.15);
  /* Sombre : la case « absente » doit rester bien lisible (gris moyen, texte
     blanc) et se distinguer d'une case vide ; côté clavier, une touche
     éliminée devient au contraire PLUS foncée que les touches libres. */
  --tile-absent:#5c6373; --tile-absent-ink:#ffffff;
  --key:#4b5263; --key-ink:#ffffff;
  --key-absent:#24272f; --key-absent-ink:#8b91a1;
  --shadow:0 1px 2px rgba(0,0,0,.4),0 8px 24px rgba(0,0,0,.4);
  --shadow-lg:0 12px 40px rgba(0,0,0,.5);
  --heat-0:#6d8fe6; --heat-1:#67b4ea; --heat-2:#67cccd; --heat-3:#8fd077;
  --heat-4:#e5cc47; --heat-5:#f6a23c; --heat-6:#f06d3a; --heat-7:#e6483c;
}
@media (prefers-color-scheme:dark){
  :root[data-theme="auto"]{
    --bg:#0d0e14; --surface:#171922; --surface-2:#1e212c;
    --text:#f4f5fa; --text-2:#b3b9c8; --muted:#858b9b;
    --border:rgba(255,255,255,.12); --border-strong:rgba(255,255,255,.22);
    --brand:#1a1630; --brand-2:#2c2450;
    --accent:#8878ff; --accent-ink:#ffffff; --accent-soft:rgba(136,120,255,.20);
    --ok:#57ab57; --ok-soft:rgba(87,171,87,.18);
    --maybe:#cda52c; --maybe-soft:rgba(205,165,44,.18);
    --no:#e05656; --no-soft:rgba(224,86,86,.15);
    --tile-absent:#5c6373; --tile-absent-ink:#ffffff;
    --key:#4b5263; --key-ink:#ffffff;
    --key-absent:#24272f; --key-absent-ink:#8b91a1;
    --shadow:0 1px 2px rgba(0,0,0,.4),0 8px 24px rgba(0,0,0,.4);
    --shadow-lg:0 12px 40px rgba(0,0,0,.5);
    --heat-0:#6d8fe6; --heat-1:#67b4ea; --heat-2:#67cccd; --heat-3:#8fd077;
    --heat-4:#e5cc47; --heat-5:#f6a23c; --heat-6:#f06d3a; --heat-7:#e6483c;
  }
}
/* ---------- Thème ROUGE (filtre nuit) ----------
   But : jouer au lit sans lumière bleue, qui est celle qui retarde
   l'endormissement. Règle de fabrication de la palette : le canal BLEU reste
   sous 40/255 sur TOUTES les couleurs (la plupart sont à 0). C'est pour ça
   qu'il n'y a ni blanc, ni gris, ni vert nulle part — un simple
   `filter:sepia()` global aurait aussi délavé les trois états du jeu.
   Les trois états sont séparés sur l'échelle de CLARTÉ PERÇUE (L* CIELAB),
   pas sur la teinte, puisqu'il n'y a plus qu'une teinte :
     fond 1 · case vide 3 · absente 20 · mal placée 37 · bien placée 57
   soit des écarts de 15 à 20 points, là où deux teintes proches en clarté
   seraient indiscernables une fois l'écran baissé au minimum. En renfort,
   « mal placée » porte un ANNEAU intérieur ambre (`--maybe-ring`) : même à
   très faible luminosité, l'anneau la distingue au premier coup d'œil des
   deux autres. Ne pas « harmoniser » ces valeurs sans refaire le calcul. */
:root[data-theme="red"]{
  --bg:#0c0200; --surface:#1a0400; --surface-2:#280800;
  --text:#ff9628; --text-2:#e06a1a; --muted:#b3521a;
  --border:rgba(255,90,26,.16); --border-strong:rgba(255,90,26,.36);
  --brand:#200500; --brand-2:#300a00;
  --accent:#ff5a1a; --accent-ink:#180300; --accent-soft:rgba(255,90,26,.18);
  --ok:#ff3b1a; --ok-soft:rgba(255,59,26,.16);
  --maybe:#a82200; --maybe-soft:rgba(255,196,0,.13);
  --no:#cf4a12; --no-soft:rgba(207,74,18,.16);
  --ok-ink:#180300; --maybe-ink:#ffc400; --maybe-ring:#ff7a26;
  --logo-from:#ff3b1a; --logo-to:#ffa424; --logo-ink:#1a0300;
  --side-ink:#ff9628; --side-ink-2:rgba(255,150,40,.78); --side-ink-3:rgba(255,150,40,.6);
  --side-hover:rgba(255,90,26,.12); --side-active:rgba(255,90,26,.20);
  /* Les photos de profil sont la seule source d'images : on les repasse en
     niveaux de gris puis on les reteinte en rouge, sinon un avatar bleu vif
     ruinerait tout le principe. */
  --photo-filter:grayscale(1) sepia(1) hue-rotate(-25deg) saturate(2.6) brightness(.85);
  --tile-absent:#5e1400; --tile-absent-ink:#ff8c1e;
  --key:#7d1b02; --key-ink:#ffab26;
  --key-absent:#2a0800; --key-absent-ink:#b3541a;
  --shadow:0 1px 2px rgba(0,0,0,.6),0 8px 24px rgba(0,0,0,.6);
  --shadow-lg:0 12px 40px rgba(0,0,0,.7);
  /* Rampe de chaleur en CLARTÉ seulement (canal bleu ≤ 38, comme le reste). */
  --heat-0:#2a0800; --heat-1:#3f0d00; --heat-2:#571400; --heat-3:#731c00;
  --heat-4:#932700; --heat-5:#b83600; --heat-6:#e04a0e; --heat-7:#ff7a26;
}
*{box-sizing:border-box;margin:0;padding:0}
/* Hauteur de la coquille.
   - Navigateur : `dvh` = la partie réellement visible (barre d'adresse comprise).
   - App INSTALLÉE : `vh` = le cadre entier. Sur iPhone, `innerHeight` peut
     annoncer 812 alors que le cadre en fait 874 (il retranche la barre d'état
     sans que le cadre, lui, soit réduit) : se fier à `innerHeight` laissait
     une bande vide de 62 px en bas.
   PAS de `position:fixed` sur html/body : avec une racine fixée, iOS cale la
   fenêtre sur la zone SÛRE et laisse une bande noire en bas. `overflow:hidden`
   suffit à empêcher la page de défiler, sans toucher au cadre. */
html,body{height:100dvh;width:100%;overflow:hidden;overscroll-behavior:none}
html.standalone,html.standalone body{height:100vh}
/* Le fond de la page prend la couleur de la barre d'onglets : si iOS garde
   quelques pixels sous la coquille (zone de l'indicateur d'accueil), la
   jonction est invisible au lieu de faire une bande d'une autre teinte. */
html{background:var(--surface)}
body{font-family:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;background:var(--bg);color:var(--text);
  -webkit-font-smoothing:antialiased;line-height:1.4;overscroll-behavior:none;
  /* Deux appuis rapprochés sur une touche étaient pris pour un double-tap :
     Safari zoomait et décalait la page. `manipulation` désactive ce geste
     (le zoom à deux doigts, lui, reste possible). */
  touch-action:manipulation;-webkit-text-size-adjust:100%}
button{font-family:inherit;cursor:pointer;border:none;background:none;color:inherit}
[hidden]{display:none !important}
.app{display:flex;height:100%;overflow:hidden}

.sidebar{width:238px;flex-shrink:0;background:var(--brand);color:var(--side-ink);display:flex;flex-direction:column;
  padding:20px 14px;gap:5px}
.brand{display:flex;align-items:center;gap:12px;padding:6px 10px 18px}
.brand .logo{width:38px;height:38px;border-radius:12px;background:linear-gradient(140deg,var(--logo-from),var(--logo-to));
  display:grid;place-items:center;font-size:20px;font-weight:800;color:var(--logo-ink)}
.brand h1{font-size:16px;font-weight:700}
.brand p{font-size:12px;color:var(--side-ink-3);font-weight:500}
.sidenav{display:flex;flex-direction:column;gap:5px}
.nav-item{display:flex;align-items:center;gap:13px;padding:11px 12px;border-radius:12px;color:var(--side-ink-2);
  font-size:14.5px;font-weight:600;transition:background .15s,color .15s;text-align:left;width:100%;position:relative}
.nav-item svg{width:20px;height:20px;flex-shrink:0}
.nav-item:hover{background:var(--side-hover);color:var(--side-ink)}
.nav-item.active{background:var(--side-active);color:var(--side-ink)}
.sidebar .spacer{flex:1}
/* Pastille de non-lus sur un onglet (messages, notifications). */
.nav-badge{position:absolute;top:6px;right:10px;min-width:17px;height:17px;padding:0 5px;border-radius:9px;
  background:var(--accent);color:var(--accent-ink);font-size:10.5px;font-weight:800;font-style:normal;
  display:grid;place-items:center;line-height:1}

.main{flex:1;display:flex;flex-direction:column;min-width:0;min-height:0}
.topbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex:0 0 auto;
  padding:10px 16px;padding-top:calc(10px + var(--pad-top));
  padding-left:calc(16px + env(safe-area-inset-left));padding-right:calc(16px + env(safe-area-inset-right));
  background:var(--bg);border-bottom:1px solid var(--border)}
.topbar .tleft,.topbar .tright{display:flex;align-items:center;gap:8px;min-width:0}
.topbar h2{font-size:16.5px;font-weight:700;line-height:1.2}
.topbar .sub{font-size:12px;color:var(--text-2);font-weight:500}
.icon-btn{width:36px;height:36px;border-radius:10px;display:grid;place-items:center;color:var(--text-2);border:1px solid var(--border);flex-shrink:0}
.icon-btn:hover{background:var(--surface);color:var(--text)}
.icon-btn svg{width:18px;height:18px}
.content{flex:1;min-height:0;overflow-y:auto;padding:12px 14px}
body.view-play .content{overflow:hidden;padding-bottom:6px}
.wrap{max-width:720px;margin:0 auto}
.wrap-narrow{max-width:460px;margin:0 auto}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:11px 18px;border-radius:12px;
  font-size:14.5px;font-weight:700;background:var(--accent);color:var(--accent-ink);box-shadow:var(--shadow)}
.btn:hover{filter:brightness(1.06)} .btn:active{transform:translateY(1px)}
.btn[disabled]{opacity:.5;pointer-events:none}
.btn.block{width:100%}
.btn.sm{padding:8px 13px;font-size:13px;border-radius:10px}
.btn.ghost{background:var(--surface);color:var(--text);border:1px solid var(--border-strong);box-shadow:none}
.btn.danger{background:var(--no-soft);color:var(--no);box-shadow:none}
.toggle-group{display:inline-flex;background:var(--surface-2);border:1px solid var(--border);border-radius:11px;padding:3px;gap:3px}
.toggle-group button{padding:7px 13px;border-radius:8px;font-size:13px;font-weight:600;color:var(--text-2)}
.toggle-group button.on{background:var(--surface);color:var(--text);box-shadow:var(--shadow)}
/* En rouge, l'ombre portée ne se voit pas et `--surface` est presque noir :
   le bouton sélectionné se distinguerait à peine. On le marque à l'encre. */
:root[data-theme="red"] .toggle-group button.on{background:var(--accent-soft);
  color:var(--accent);box-shadow:inset 0 0 0 1px var(--border-strong)}

/* ---------- Cartes, listes, stats ---------- */
.panel{padding:14px;border-radius:16px;background:var(--surface);border:1px solid var(--border);
  box-shadow:var(--shadow);margin-bottom:10px}
.panel h3{font-size:14.5px;font-weight:700}
.panel .cap{font-size:12px;color:var(--text-2);margin-bottom:10px}
/* Titre de panneau avec son action à droite (« Messages privés · Nouveau message »). */
.panel-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:2px}
/* Filtre en temps réel d'une liste (fils privés, choix d'un destinataire) :
   16 px, car en dessous iOS zoome sur le champ au focus. */
.filtre{display:flex;gap:6px;align-items:center;margin-bottom:6px}
.filtre input{flex:1;min-width:0;padding:9px 12px;border-radius:11px;border:1px solid var(--border-strong);
  background:var(--surface);color:var(--text);font-size:16px;font-family:inherit;-webkit-appearance:none;appearance:none}
.filtre input:focus{outline:2px solid var(--accent);outline-offset:-1px;border-color:transparent}
.tri{display:flex;gap:4px;flex:0 0 auto}
.tri button{padding:8px 10px;border-radius:20px;font-size:12.5px;font-weight:700;color:var(--text-2);
  background:var(--surface);border:1px solid var(--border)}
.tri button.on{background:var(--accent);color:var(--accent-ink);border-color:transparent}
.kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-bottom:10px}
.kpi{padding:10px 8px;border-radius:13px;background:var(--surface);border:1px solid var(--border);text-align:center}
.kpi .v{font-size:21px;font-weight:800;line-height:1.1}
.kpi .l{font-size:10.5px;color:var(--text-2);font-weight:600;margin-top:2px;line-height:1.2}

.dist .drow{display:flex;align-items:center;gap:8px;margin-bottom:5px}
.dist .dl{width:12px;font-size:12.5px;font-weight:700;color:var(--text-2);flex-shrink:0}
.dist .dtrack{flex:1;height:20px;background:var(--surface-2);border-radius:5px;overflow:hidden;border:1px solid var(--border)}
.dist .dfill{height:100%;background:var(--tile-absent);border-radius:5px;min-width:24px;
  display:flex;align-items:center;justify-content:flex-end;padding-right:6px;color:var(--tile-absent-ink);font-size:11.5px;font-weight:700}
.dist .dfill.best{background:var(--ok);color:var(--ok-ink)}

.av{width:34px;height:34px;border-radius:50%;flex-shrink:0;object-fit:cover;background:var(--accent-soft);
  color:var(--accent);display:grid;place-items:center;font-weight:800;font-size:14px;border:1px solid var(--border)}
.av.big{width:76px;height:76px;font-size:30px}
.av.xl{width:128px;height:128px;font-size:50px}      /* profil des autres joueurs */
/* Photos : reteintées en rouge par le thème nuit (voir `--photo-filter`).
   Seules les <img> sont concernées ; une pastille à initiale suit déjà les
   couleurs du thème. */
img.av{filter:var(--photo-filter)}
.lrow{display:flex;align-items:center;gap:10px;padding:8px 4px;border-top:1px solid var(--border)}
.lrow:first-of-type{border-top:none}
.lrow .rank{width:20px;font-size:13px;font-weight:800;color:var(--muted);text-align:center;flex-shrink:0}
.lrow .who{flex:1;min-width:0}
.lrow .who b{font-size:14px;font-weight:700;display:block;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lrow .who .d{font-size:11.5px;color:var(--text-2);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lrow.me{background:var(--accent-soft);border-radius:11px;padding-left:7px;padding-right:7px}
.lrow .res{font-size:13.5px;font-weight:700;flex-shrink:0}
.lrow .res.won{color:var(--ok)} .lrow .res.lost{color:var(--no)}
.lrow .res.playing{color:var(--maybe)} .lrow .res.none{color:var(--muted);font-weight:600}
/* Vignette de la grille d'une partie : 5 colonnes, largeur fixe (~30 px) →
   elle ne peut pas déborder de la ligne, même sur un petit écran. */
.mgrid{display:grid;grid-template-columns:repeat(5,5px);gap:2px;flex-shrink:0;align-content:center}
.mgrid i{width:5px;height:5px;border-radius:1px;background:var(--tile-absent);display:block}
.mgrid i.c{background:var(--ok)} .mgrid i.p{background:var(--maybe)}
.tscroll{overflow-x:auto;-webkit-overflow-scrolling:touch}
.sparks{display:flex;gap:3px;margin-top:4px}
.spark{flex:1;height:5px;border-radius:3px;background:var(--surface-2);position:relative;overflow:hidden}
.spark i{position:absolute;inset:0;background:var(--accent);transform-origin:left;display:block}
table.hist{width:100%;border-collapse:collapse;font-size:12.5px;white-space:nowrap}
table.hist th{text-align:left;font-size:10px;text-transform:uppercase;letter-spacing:.4px;color:var(--muted);padding:4px 6px}
table.hist td{padding:5px 6px;border-top:1px solid var(--border)}
table.hist td.w{font-weight:700;letter-spacing:1.2px}
table.hist td.n{text-align:center;font-variant-numeric:tabular-nums;font-weight:700}
/* Historique : ⟲ cliquable sur MES journées manquées, ⟲ discret sur celles
   que quelqu'un a déjà rattrapées. */
table.hist td.n .rat{color:var(--accent);font-size:14px;font-weight:800;padding:0 4px;
  border-radius:6px;line-height:1.4}
table.hist td.n .rat:hover{background:var(--accent-soft)}
table.hist td.n .rat-fait{color:var(--muted);font-size:10.5px;margin-left:2px}

/* ---------- Profil ---------- */
.profhead{display:flex;flex-direction:column;align-items:center;gap:8px;margin-bottom:12px}
.profhead .namerow{display:flex;gap:8px;align-items:center;width:min(300px,100%)}
.profhead .namerow input{flex:1;min-width:0;padding:9px 12px;border-radius:11px;border:1px solid var(--border-strong);
  background:var(--surface);color:var(--text);font-size:16px;font-weight:700;text-align:center;font-family:inherit}
.profhead .namerow input:focus{outline:2px solid var(--accent);outline-offset:-1px;border-color:transparent}
.profhead .em{font-size:12px;color:var(--text-2);text-align:center}
.profhead .em a{color:var(--accent);font-weight:700;cursor:pointer}
.profhead .pname{font-size:18px;font-weight:800}
.profhead .biorow{display:flex;flex-direction:column;gap:6px;align-items:stretch;width:min(300px,100%);margin-top:4px}
.profhead .biorow .row-end{align-items:center}
.profhead .biorow small{color:var(--muted);font-size:11.5px;margin-right:auto}
.profhead textarea{width:100%;padding:9px 12px;border-radius:11px;border:1px solid var(--border-strong);
  background:var(--surface);color:var(--text);font-size:14px;font-family:inherit;resize:vertical;line-height:1.4}
.profhead textarea:focus{outline:2px solid var(--accent);outline-offset:-1px;border-color:transparent}
.bio{font-size:13.5px;color:var(--text-2);text-align:center;max-width:320px;line-height:1.45;white-space:pre-wrap}
.bio.muted{color:var(--muted);font-style:italic}
/* Un nom ou une photo mène au profil du joueur. */
[data-player]{cursor:pointer}
.panel.pack{padding:4px 14px}
.panel.pack details.rules:first-child{border-top:none}
details.rules summary{padding:10px 0}
.avedit{position:relative}
.avedit .pen{position:absolute;right:-2px;bottom:-2px;width:26px;height:26px;border-radius:50%;background:var(--accent);
  color:var(--accent-ink);display:grid;place-items:center;font-size:13px;border:2px solid var(--bg)}
.field{margin-bottom:10px}
.field label{display:block;font-size:12.5px;font-weight:700;color:var(--text-2);margin-bottom:5px}
.field input{width:100%;padding:10px 12px;border-radius:11px;border:1px solid var(--border-strong);
  background:var(--surface);color:var(--text);font-size:15px;font-family:inherit}
.field input:focus{outline:2px solid var(--accent);outline-offset:-1px;border-color:transparent}
.row-end{display:flex;justify-content:flex-end;gap:8px}
details.rules{border-top:1px solid var(--border);padding-top:10px;margin-top:4px}
details.rules summary{font-size:14px;font-weight:700;cursor:pointer;list-style:none;display:flex;
  align-items:center;justify-content:space-between}
details.rules summary::-webkit-details-marker{display:none}
details.rules summary::after{content:"▾";color:var(--muted)}
details.rules[open] summary::after{content:"▴"}
.rules-body{font-size:13px;color:var(--text-2);line-height:1.55;margin-top:8px}
.rules-body p{margin-bottom:7px}
/* ---------- Ligues ---------- */
/* Sélecteur en haut du Classement. Il DÉFILE horizontalement plutôt que de
   passer à la ligne : au-delà de trois ligues, un retour à la ligne poussait
   la grille du jour sous la ligne de flottaison. */
.ligues{display:flex;gap:6px;overflow-x:auto;padding-bottom:8px;margin-bottom:2px;
  -webkit-overflow-scrolling:touch;scrollbar-width:none}
.ligues::-webkit-scrollbar{display:none}
.ligues button{flex:0 0 auto;padding:7px 14px;border-radius:20px;font-size:13px;font-weight:700;
  color:var(--text-2);background:var(--surface);border:1px solid var(--border)}
.ligues button.on{background:var(--accent);color:var(--accent-ink);border-color:transparent}
.ligue-carte{border-top:1px solid var(--border);padding:12px 0}
.ligue-carte:first-of-type{border-top:none}
.ligue-tete b{font-size:14.5px}
.ligue-tete .d{display:block;font-size:12px;color:var(--text-2);margin-top:1px}
.ligue-membres{display:flex;flex-wrap:wrap;gap:6px;margin:8px 0}
.puce{display:inline-flex;align-items:center;gap:4px;background:var(--surface-2);
  border:1px solid var(--border);border-radius:14px;padding:3px 9px;font-size:12.5px;font-weight:600}
.puce .x{color:var(--muted);font-size:15px;line-height:1;padding:0 1px}
.puce .x:hover{color:var(--no)}
/* Membre endormi (rien joué depuis 7 jours) : vu du seul propriétaire, grisé. */
.puce.inactif{opacity:.6}
.puce.inactif i{font-style:normal;font-size:11px;color:var(--muted)}
.ligue-actions{display:flex;gap:6px;flex-wrap:wrap}
.row-inline{display:flex;gap:6px}
.row-inline input{flex:1;min-width:0;padding:10px 12px;border-radius:11px;
  border:1px solid var(--border-strong);background:var(--surface);color:var(--text);
  font-size:15px;font-family:inherit}
.row-inline input:focus{outline:2px solid var(--accent);outline-offset:-1px;border-color:transparent}
.row-inline .btn{flex:0 0 auto}

.code-box{background:var(--accent-soft);border-radius:11px;padding:10px 12px;margin-top:10px;text-align:center}
.code-box b{font-size:17px;letter-spacing:1px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}

.empty{text-align:center;color:var(--text-2);padding:30px 20px}
.spinner{width:32px;height:32px;border-radius:50%;border:3px solid var(--border-strong);border-top-color:var(--accent);
  animation:spin .8s linear infinite;margin:50px auto}
@keyframes spin{to{transform:rotate(360deg)}}
.offline{display:none;align-items:center;gap:8px;justify-content:center;background:var(--maybe-soft);color:var(--maybe);
  font-size:12px;font-weight:700;padding:5px;border-bottom:1px solid var(--border);flex:0 0 auto}
body.is-offline .offline{display:flex}
/* En rouge, `--maybe` est le fond SOMBRE d'une case mal placée : illisible
   comme couleur de texte. Le bandeau prend donc l'encre ambre. */
:root[data-theme="red"] .offline{color:var(--maybe-ink)}
:root[data-theme="red"] .toast{background:var(--surface-2);color:var(--text);
  border:1px solid var(--border-strong)}
.toasts{position:fixed;left:0;right:0;top:calc(58px + env(safe-area-inset-top));display:flex;flex-direction:column;
  align-items:center;gap:8px;z-index:60;pointer-events:none}
.toast{background:var(--text);color:var(--bg);font-size:13px;font-weight:700;padding:9px 15px;border-radius:22px;
  box-shadow:var(--shadow-lg)}
.toast.clic{pointer-events:auto;cursor:pointer;text-decoration:underline}

/* ---------- Hub des jeux ---------- */
.gcard{display:flex;gap:12px;align-items:center;flex-wrap:wrap;padding:14px;border-radius:16px;
  background:var(--surface);border:1px solid var(--border);box-shadow:var(--shadow);margin-bottom:10px}
.gicon{width:44px;height:44px;border-radius:13px;background:var(--accent-soft);color:var(--accent);
  display:grid;place-items:center;flex-shrink:0}
.gicon svg{width:24px;height:24px}
.gbody{flex:1;min-width:150px}
.gbody b{font-size:15px;font-weight:800}
.gbody .d{font-size:12px;color:var(--text-2)}
.gstate{display:block;font-size:12.5px;font-weight:700;margin-top:4px}
.gstate.won{color:var(--ok)} .gstate.lost{color:var(--no)}
.gstate.playing{color:var(--maybe)} .gstate.none{color:var(--muted)}
:root[data-theme="red"] .gstate.playing{color:var(--maybe-ink)}
.gactions{display:flex;gap:6px;flex-wrap:wrap}
.gmissed{width:100%;font-size:12px;color:var(--text-2)}
.gmissed a{color:var(--accent);font-weight:700;cursor:pointer}

/* ---------- Classement par points ---------- */
.lrow .pts{font-size:15px;font-weight:800;flex-shrink:0;white-space:nowrap;text-align:right;line-height:1.15}
.lrow .pts small{font-size:11px;font-weight:700;color:var(--text-2)}
.period{display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap;margin-bottom:8px}
.period .mois{display:flex;align-items:center;gap:4px;font-size:13px;font-weight:700}
.period .mois button{width:28px;height:28px;border-radius:8px;border:1px solid var(--border);color:var(--text-2);
  font-size:16px;line-height:1}
.period .mois button[disabled]{opacity:.35;pointer-events:none}
.ptsrow{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:6px}
.ligues.jeux button.on{background:var(--brand);color:var(--side-ink)}

/* ---------- Réactions ---------- */
.reacts{display:flex;gap:4px;flex-wrap:wrap;padding:0 4px 8px 62px;margin-top:-4px}
.lrow.me + .reacts{padding-left:65px}
.react{display:inline-flex;align-items:center;gap:3px;padding:2px 8px;border-radius:14px;
  border:1px solid var(--border);background:var(--surface-2);font-size:14px;line-height:1.3;cursor:pointer}
.react b{font-size:11px;font-weight:800;color:var(--text-2)}
.react.on{background:var(--accent-soft);border-color:var(--accent)}
.reacts.lecture .react{cursor:default}
.react.flag{margin-left:auto;color:var(--no);font-size:13px}
.react.flag:hover{border-color:var(--no);background:var(--no-soft)}
/* « + » : déplie les cinq choix ; les choix dépliés sont un peu plus grands
   pour le pouce. */
.react.plus{border-style:dashed;color:var(--muted);font-weight:800;min-width:30px;justify-content:center}
.react.plus:hover{color:var(--accent);border-color:var(--accent)}
/* Déplié : la rangée prend toute la largeur du panneau (sous l'avatar, 259 px
   ne suffisent pas à 7 boutons sur un iPhone) et le drapeau ⚑ s'efface le
   temps du choix — il ne peut plus se retrouver collé à la croix. Si ça passe
   quand même à la ligne (320 px), tout reste aligné à gauche : la croix suit
   le dernier émoji, jamais de `margin-left:auto`. */
.reacts.ouvert{padding-left:4px}
.reacts.ouvert .react.pick{font-size:16px;padding:3px 8px}
.reacts.ouvert .react.flag{display:none}
.react.fermer{color:var(--muted);font-weight:700}
/* Sous un message d'un fil : même puces, sans le retrait du Classement. */
.bubble .reacts.msg{padding:5px 0 0;margin:0;gap:3px}
.bubble.mine .reacts.msg{justify-content:flex-end}
.bubble.mine .reacts.msg.ouvert{justify-content:flex-start}
.bubble .reacts.msg .react{font-size:13px;padding:1px 7px}
table.hist td.n .rx{font-size:10px;line-height:1;margin-top:2px;white-space:nowrap}
table.hist td.n .ct{font-size:10.5px;margin-left:2px}
/* Les émojis ignorent les couleurs du thème : en rouge, on les reteinte comme
   les photos. */
:root[data-theme="red"] .react,:root[data-theme="red"] .rx{filter:var(--photo-filter)}

/* ---------- Messages ---------- */
.conv{display:flex;align-items:center;gap:10px;padding:9px 4px;border-top:1px solid var(--border);cursor:pointer}
.conv:first-of-type{border-top:none}
.conv .who{flex:1;min-width:0}
.conv .who b{font-size:14px;font-weight:700;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.conv .who .d{font-size:12px;color:var(--text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.conv.nl .who b{color:var(--accent)}
.nlb{min-width:20px;height:20px;padding:0 6px;border-radius:10px;background:var(--accent);color:var(--accent-ink);
  font-size:11px;font-weight:800;display:grid;place-items:center;flex-shrink:0}
.quand{font-size:11px;color:var(--muted);flex-shrink:0}
.av.grp{background:var(--surface-2);color:var(--text-2)}
.av.grp svg{width:18px;height:18px}
.choix .lrow{width:100%;text-align:left;cursor:pointer}
.choix .lrow:hover{background:var(--surface-2);border-radius:11px}
/* Le fil occupe toute la hauteur : les messages défilent, la zone de saisie
   reste en bas (comme l'écran de jeu, la page elle-même ne défile pas). */
body.view-thread .content,body.view-comments .content{overflow:hidden;padding:0}
.thread{height:100%;display:flex;flex-direction:column}
.thead{flex:0 0 auto;font-size:12px;color:var(--text-2);text-align:center;padding:8px 12px 0}
.msgs{flex:1;min-height:0;overflow-y:auto;padding:12px 14px;display:flex;flex-direction:column;gap:6px}
.msgs .older{align-self:center;margin-bottom:6px}
.msgs .empty{margin:auto}
.bubble{max-width:82%;padding:8px 11px;border-radius:14px;background:var(--surface);border:1px solid var(--border);
  font-size:14px;line-height:1.4;word-break:break-word}
/* `pre-wrap` sur le CORPS seulement : posé sur la bulle, chaque retour à la
   ligne du gabarit HTML devenait une ligne vide (bulles deux fois trop hautes). */
.bubble .body{white-space:pre-wrap}
.bubble[data-mid] .body{cursor:pointer}
.bubble.mine{align-self:flex-end;background:var(--accent-soft);border-color:transparent;border-bottom-right-radius:4px}
.bubble.other{align-self:flex-start;border-bottom-left-radius:4px}
.bubble.sys{align-self:center;max-width:92%;background:var(--surface-2);font-size:12.5px;color:var(--text-2);text-align:center}
.bubble.sys.acc{text-align:left;border-color:var(--border-strong)}
.bubble .acc-etat{font-size:12px;font-weight:700;color:var(--text);margin-top:6px}
.bubble .acc-votes{display:flex;gap:6px;justify-content:center;margin-top:8px}
.bubble .who{font-size:11.5px;font-weight:700;color:var(--accent);margin-bottom:2px;cursor:pointer}
.bubble .quand{font-size:10.5px;color:var(--muted);margin-top:3px;text-align:right}
.bubble .quand a{cursor:pointer;color:var(--muted);text-decoration:underline}
.composer{flex:0 0 auto;display:flex;gap:8px;align-items:flex-end;padding:8px 10px;
  border-top:1px solid var(--border);background:var(--surface)}
.composer textarea{flex:1;min-width:0;padding:9px 12px;border-radius:14px;border:1px solid var(--border-strong);
  background:var(--bg);color:var(--text);font-size:15px;font-family:inherit;resize:none;line-height:1.35;max-height:120px}
.composer textarea:focus{outline:2px solid var(--accent);outline-offset:-1px;border-color:transparent}
.composer .btn{width:40px;height:40px;padding:0;border-radius:50%;flex-shrink:0}
.composer .btn svg{width:20px;height:20px}

/* ---------- Cloche et notifications ---------- */
#bell .icon-btn{position:relative}
.badge{position:absolute;top:-5px;right:-5px;min-width:17px;height:17px;padding:0 5px;border-radius:9px;
  background:var(--accent);color:var(--accent-ink);font-size:10.5px;font-weight:800;font-style:normal;
  display:grid;place-items:center;line-height:1}
.notif{display:flex;gap:10px;padding:9px 4px;border-top:1px solid var(--border);cursor:pointer}
.notif:first-of-type{border-top:none}
.notif.nl{background:var(--accent-soft);border-radius:11px;padding-left:8px;padding-right:8px;border-top:none}
.notif .t{font-size:13.5px;font-weight:600}
.newsitem{margin:6px 0 10px}
.newsitem b{font-size:14px}
.newsitem ul{padding-left:18px;font-size:13.5px;color:var(--text-2);line-height:1.45;margin-top:4px}
.newsitem li{margin-bottom:5px}

/* ---------- Feuille (dialogue) ----------
   Remplace prompt()/confirm() : feuille du bas sur téléphone, dialogue centré
   sur bureau. Fermée par le voile, Échap ou un bouton d'action.
   La feuille est bornée à la hauteur du voile et seul son CORPS défile (même
   recette que `.msgs`) : la page ne défile jamais (`html,body{overflow:hidden}`),
   et une feuille plus haute que l'écran débordait par le haut, titre et
   premiers choix hors de portée — c'était le bug de la liste « Écrire à… ». */
.veil{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:80;display:flex;align-items:flex-end;justify-content:center}
.sheet{background:var(--surface);color:var(--text);width:100%;max-width:460px;border-radius:18px 18px 0 0;
  padding:18px 18px calc(18px + var(--pad-bottom));box-shadow:var(--shadow-lg);animation:sheet-in .18s ease-out;
  display:flex;flex-direction:column;max-height:calc(100% - var(--pad-top) - 12px)}
.sheet h3{font-size:16px;font-weight:800;margin-bottom:10px;flex:0 0 auto}
.sheet-body{flex:1 1 auto;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
.sheet-body p{margin:0 0 12px;color:var(--text-2);font-size:14px;line-height:1.45}
/* Le filtre reste visible pendant que la liste défile sous lui. */
.sheet-body .filtre{position:sticky;top:0;z-index:1;background:var(--surface);padding-bottom:6px;margin-bottom:0}
.sheet-actions{display:flex;gap:8px;justify-content:flex-end;margin-top:6px;flex:0 0 auto}
@keyframes sheet-in{from{transform:translateY(24px);opacity:0}to{transform:none;opacity:1}}
@media (min-width:861px){.veil{align-items:center;padding:20px}.sheet{border-radius:18px;padding-bottom:18px}}

/* ---------- Authentification ---------- */
body.auth-mode .sidebar, body.auth-mode .topbar, body.auth-mode .bottomnav{display:none !important}
body.auth-mode .content{overflow-y:auto}
.auth-wrap{max-width:380px;margin:0 auto;padding:6vh 16px 30px}
.auth-card{background:var(--surface);border:1px solid var(--border);border-radius:18px;box-shadow:var(--shadow-lg);padding:26px 22px}
.auth-logo{width:52px;height:52px;border-radius:15px;background:linear-gradient(140deg,var(--logo-from),var(--logo-to));display:grid;
  place-items:center;font-size:24px;font-weight:800;color:var(--logo-ink);margin:0 auto 14px}
.auth-card h2{text-align:center;font-size:20px;font-weight:800;margin-bottom:3px}
.auth-card .asub{text-align:center;color:var(--text-2);font-size:13px;margin-bottom:18px}
.auth-switch{text-align:center;font-size:13px;color:var(--text-2);margin-top:14px}
.auth-switch a{color:var(--accent);font-weight:700;cursor:pointer}
.auth-err{background:var(--no-soft);color:var(--no);font-size:12.5px;font-weight:600;padding:9px 11px;
  border-radius:10px;margin-bottom:12px;text-align:center}
.auth-err a{color:inherit;text-decoration:underline;cursor:pointer;display:block;margin-top:4px}
.auth-info{background:var(--ok-soft);color:var(--ok);font-size:12.5px;font-weight:600;padding:9px 11px;
  border-radius:10px;margin-bottom:12px;text-align:center}
.auth-text{font-size:13.5px;color:var(--text-2);line-height:1.45;margin:0 0 12px;text-align:center}
.auth-text small{font-size:12px}

/* ---------- Verrou d'orientation ---------- */
/* iOS ignore `orientation` du manifeste : on refuse simplement le paysage sur
   les écrans bas (téléphones couchés). `max-height` plutôt que `max-width` :
   un ordinateur ou une tablette en paysage n'est pas concerné. */
.rotate{display:none;position:fixed;inset:0;z-index:100;background:var(--bg);color:var(--text);
  flex-direction:column;align-items:center;justify-content:center;gap:14px;text-align:center;padding:24px}
.rotate svg{width:54px;height:54px;color:var(--accent);animation:tourne 2.2s ease-in-out infinite}
.rotate b{font-size:17px;font-weight:800}
.rotate p{font-size:13.5px;color:var(--text-2);max-width:280px}
@keyframes tourne{0%,55%{transform:rotate(0)}70%,100%{transform:rotate(-90deg)}}
@media (orientation:landscape) and (max-height:520px){
  .app{display:none}
  .rotate{display:flex}
}

.bottomnav{display:none}
@media (max-width:860px){
  .sidebar{display:none}
  .content{padding:10px 10px 6px}
  .topbar .sub{display:none}
  .bottomnav{display:flex;flex:0 0 auto;
    background:var(--surface);border-top:1px solid var(--border);
    padding:5px 4px calc(5px + var(--pad-bottom));justify-content:space-around}
  .bottomnav button{display:flex;flex-direction:column;align-items:center;gap:2px;padding:4px 10px;border-radius:11px;
    color:var(--muted);font-size:10.5px;font-weight:700;flex:1;position:relative}
  .bottomnav button svg{width:21px;height:21px}
  .bottomnav button.active{color:var(--accent)}
  .bottomnav .nav-badge{top:0;right:calc(50% - 22px)}
  .kpis{grid-template-columns:repeat(4,1fr);gap:6px}
  .kpi .v{font-size:19px}
}
/* Répartition avec des libellés de tranches (« 41–80 ») plutôt qu'un chiffre. */
.dist .dl.wide{width:44px;text-align:right;white-space:nowrap}
