/* dashboard/public/css/style.css
 *
 * LA CHARTE. Reprise de la maquette de référence — barre latérale fixe, barre
 * de recherche en haut, colonnes qui racontent une progression — mais posée
 * sur les couleurs de Discord en sombre plutôt que sur du blanc.
 *
 * DEUX RÈGLES QUI EXPLIQUENT TOUT LE RESTE :
 *
 *   1. UNE VALEUR S'ÉDITE LÀ OÙ ELLE S'AFFICHE. Pas de formulaire à part : une
 *      date est un bouton qui porte la date, des œuvres sont des affiches
 *      empilées avec un « + » au bout. C'est ce qui donne l'impression de
 *      manipuler la chose et non de remplir un questionnaire.
 *
 *   2. UN SEUL GESTE PRIMAIRE À L'ÉCRAN. Un bouton bleu, jamais deux. Tout ce
 *      qui l'entoure est secondaire, et se voit comme tel.
 */

:root {
  /* Les gris de Discord, du plus profond au plus clair. */
  --fond: #1e1f22;
  --flanc: #2b2d31;
  --aire: #313338;
  --carte: #383a40;
  --carte-survol: #404249;
  --ligne: #3f4147;

  --texte: #f2f3f5;
  --doux: #b5bac1;
  --faible: #949ba4;

  /* ── LES SEPT TEINTES DE RUBRIQUE ────────────────────────────────────
     Chaque couple : un fond sourd, qui porte du texte blanc, et une couleur
     vive pour la pastille et les accents.

     ELLES VIVENT ICI parce que deux endroits les emploient — l'en-tete
     d'une colonne de debat et le pave d'un debat pose. Ecrites deux fois,
     elles ont diverge : le pave d'Otaku ne ressemblait pas a sa colonne. */
  --fond-gris: #40434a;   --vif-gris: #5c5e66;
  --fond-bleu: #33407a;   --vif-bleu: #8b96ff;
  --fond-vert: #1f5237;   --vif-vert: #45d17f;
  /* L ambre etait #6b4a15 : la meme teinte, mais a 67 % de saturation. Sur une
     pastille de dix-neuf pixels ca passait ; etale sur la bande d un topic, un
     orange sombre et pale lit brun, et c est la seule des sept a le faire. On
     garde le ton, on monte le chroma a 89 % — le blanc dessus reste a 7,1:1,
     dans la meme fourchette que les six autres. */
  --fond-ambre: #8a4508;  --vif-ambre: #f0b232;
  --fond-violet: #4a3172; --vif-violet: #b08bff;
  --fond-rose: #6d2d52;   --vif-rose: #ff8ac4;
  --fond-cyan: #175c63;   --vif-cyan: #4dd0d8;

  --bleu: #5865f2;
  --bleu-clair: #7983f5;
  --vert: #23a55a;
  --jaune: #f0b232;
  --rouge: #da373c;

  --rond: 8px;
  --rond-large: 12px;

  --flanc-large: 260px;
  --haut-haut: 64px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--aire);
  color: var(--texte);
  font: 15px/1.5 "gg sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

/* ── La coque ─────────────────────────────────────────────────────────── */

body.app {
  display: grid;
  grid-template-columns: var(--flanc-large) 1fr;
  grid-template-rows: var(--haut-haut) 1fr;
  grid-template-areas: "flanc haut" "flanc aire";
  /* LA HAUTEUR EXACTE DE LA FENETRE, PAS UN MINIMUM.

     Avec `min-height`, la coque grandissait avec son contenu et c est la PAGE
     ENTIERE qui defilait : la barre laterale et celle du haut remontaient hors
     de l ecran des qu on descendait dans une longue liste. Le menu doit rester
     sous la main, on y va precisement quand on est loin dans une page.

     Ici la coque tient la fenetre, et seule `.aire` defile — ce qu elle sait
     deja faire (overflow-y: scroll, un peu plus bas). */
  height: 100vh;
  height: 100dvh; /* la barre d adresse mobile ne compte pas dans dvh */
  overflow: hidden;
}

.flanc {
  grid-area: flanc;
  /* Le menu peut lui-meme depasser — le forum lui ajoute ses topics. Il
     defile alors pour son compte, sans entrainer le reste. */
  overflow-y: auto;
  background: var(--flanc);
  border-right: 1px solid var(--fond);
  padding: 16px 12px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.marque {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px;
  color: var(--texte);
  text-decoration: none;
  font-size: 16px;
}
.sceau {
  display: grid;
  place-items: center;
  width: 36px; height: 36px;
  border-radius: 10px;
  background: var(--bleu);
  color: #fff;
  font-weight: 700;
}

.menu { display: flex; flex-direction: column; gap: 2px; }

.entree {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border-radius: var(--rond);
  color: var(--doux);
  text-decoration: none;
}
.entree:hover { background: var(--carte); color: var(--texte); }
.entree.actif { background: var(--carte); color: #fff; }
.entree svg {
  width: 20px; height: 20px;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}

/* Le sous-arbre d'un projet : une ligne verticale, et des rameaux. */
.point {
  flex: none;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--faible);
}
.point.brouillon { background: var(--faible); }
.point.vote { background: var(--bleu); }
.point.programmee { background: var(--vert); }
.point.passee { background: #5c5e66; }

/* ── La barre du haut ─────────────────────────────────────────────────── */

.haut {
  grid-area: haut;
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 0 28px;
  background: var(--aire);
  border-bottom: 1px solid var(--ligne);
}

.moi {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--doux);
  text-decoration: none;
}
.moi:hover { color: var(--texte); }
.pastille-avatar {
  display: grid; place-items: center;
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--bleu);
  color: #fff; font-weight: 600; font-size: 14px;
}

/* ── L'aire de contenu ────────────────────────────────────────────────── */

/* LA PLACE DE LA BARRE EST TOUJOURS RÉSERVÉE. Elle apparaissait sur les pages
   longues et disparaissait sur les courtes : dix pixels de largeur en moins,
   donc tout le contenu qui saute d'un écran à l'autre — on le voyait en
   passant de Cinéma à Débats. On garde le couloir, la barre s'y montre ou
   non, et la mise en page ne bouge plus. */
.aire {
  grid-area: aire; padding: 28px 32px 48px;
  overflow-x: auto;
  /* `overflow-y: scroll` PLUTÔT QUE LA SEULE GOUTTIÈRE. `scrollbar-gutter`
     n'était pas honoré ici — la largeur utile restait à 1197 px sur les pages
     courtes et 1187 sur les longues, donc dix pixels de décalage en passant de
     l'une à l'autre. En demandant la barre en permanence, la place est prise
     dans tous les cas. */
  overflow-y: scroll;
  scrollbar-gutter: stable;
}

.fil { color: var(--faible); margin-bottom: 10px; }

.entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 28px;
}
.entete h1 { font-size: 34px; font-weight: 700; margin: 0; letter-spacing: -.02em; }
.gestes { display: flex; gap: 14px; align-items: center; }

/* UN BOUTON DÉSACTIVÉ DOIT EN AVOIR L'AIR. .bouton n'avait aucun état
   désactivé : « Envoyer » restait bleu et plein alors qu'il ne répondait pas.
   Un bouton qui semble cliquable et ne fait rien apprend à ne plus faire
   confiance aux boutons, et on va chercher l'erreur ailleurs. */
.bouton:disabled,
.bouton[aria-disabled="true"] {
  opacity: .45;
  cursor: default;
  filter: saturate(.6);
}
.bouton:disabled:hover { filter: saturate(.6); }

.bouton {
  /* Un libellé de bouton ne se coupe pas : « En écrire un autre » tombait sur
     quatre lignes et le bouton devenait un carré illisible. */
  white-space: nowrap;
  padding: 11px 18px;
  border: 0;
  border-radius: var(--rond);
  font: inherit;
  font-weight: 500;
  cursor: pointer;
}
.bouton.primaire { background: var(--bleu); color: #fff; }
.bouton.primaire:hover { background: var(--bleu-clair); }
.bouton.fantome { background: var(--carte); color: var(--doux); }
.bouton.fantome:hover { background: var(--carte-survol); color: var(--texte); }

/* ── Le tableau à colonnes ────────────────────────────────────────────── */

.tableau {
  display: grid;
  grid-template-columns: repeat(4, minmax(260px, 1fr));
  gap: 18px;
  align-items: start;
}

.chapeau {
  display: flex;
  align-items: center;
  gap: 10px;
  /* Une hauteur commune d'une page à l'autre : les deux icônes des colonnes de
     débat rendaient leur en-tête trois pixels plus haut que celui des soirées,
     ce qui se voit dès qu'on passe de l'une à l'autre. */
  min-height: 47px;
  padding: 12px 16px;
  border-radius: var(--rond-large);
  font-weight: 600;
  margin-bottom: 14px;
}
/* Les en-têtes pastel de la maquette, transposés : une teinte à peine posée
 * sur le fond sombre, et la pastille qui porte la couleur franche. */
/* Les en-têtes pastel de la maquette, transposés : la teinte est franche mais
 * sourde, et la pastille porte la couleur vive. Trop discrets, ils ne
 * séparaient plus rien et les quatre colonnes se confondaient. */
.chapeau.gris   { background: var(--fond-gris); }
.chapeau.bleu   { background: var(--fond-bleu); }
.chapeau.bleu   .point { background: var(--vif-bleu); }
.chapeau.vert   { background: var(--fond-vert); }
.chapeau.vert   .point { background: var(--vif-vert); }
.chapeau.sombre { background: #2c2d31; color: var(--faible); }
.chapeau.sombre .point { background: #5c5e66; }

.compte { margin-left: auto; opacity: .65; font-weight: 500; }

.pile { display: flex; flex-direction: column; gap: 12px; }

/* La carte n'est plus un lien : elle porte un menu, et un bouton dans un lien
 * n'est pas cliquable. Le lien couvre donc la carte par en dessous. */
.fiche {
  position: relative;
  background: var(--carte);
  border: 1px solid transparent;
  border-radius: var(--rond-large);
  padding: 14px;
}
.fiche:hover { background: var(--carte-survol); border-color: var(--ligne); }
.couvre { position: absolute; inset: 0; border-radius: inherit; z-index: 0; }
.fiche > *:not(.couvre) { position: relative; z-index: 1; pointer-events: none; }
/* CE QUI SE CLIQUE RESTE CLIQUABLE. Le lien qui couvre la carte rend le reste
   transparent au clic, sinon on ne pourrait pas cliquer la carte elle-même.
   Mais l'exception ne nommait qu'une classe — `.menu-carte` — et le bouton
   supprimer, refait plus tard en icône sous le nom `.oter-carte`, tombait donc
   dans le trou : deux clics, aucun effet, et rien à l'écran pour le dire.
   On nomme désormais ce qui se clique, pas une classe en particulier. */
.fiche :is(button, a, input, textarea, select, label):not(.couvre) { pointer-events: auto; }
/* L'EXCEPTION DOIT NOMMER LES CHAMPS. Elle ne couvrait que button et a : dans
   le compositeur d'un module — un formulaire posé dans une .fiche — cliquer le
   textarea ne donnait pas le focus, et on ne pouvait rien y taper à la souris.
   Introuvable par un test au script : poser la valeur n'est pas cliquer. */

.fiche h3 {
  font-size: 15px; font-weight: 600;
  margin: 12px 0 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

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

.etiquette {
  padding: 3px 10px;
  border-radius: 20px;
  font-size: 13px;
  font-weight: 500;
}
.etiquette.vote { background: #33407a; color: #b3bbff; }
.etiquette.direct { background: #1f5237; color: #7ae0a3; }

.menu-carte {
  margin-left: auto;
  border: 0; background: none;
  color: var(--faible);
  font-size: 15px; line-height: 1;
  padding: 3px 8px; border-radius: 6px;
  cursor: pointer;
  opacity: 0;
}
.fiche:hover .menu-carte { opacity: 1; }
.menu-carte:hover { background: var(--rouge); color: #fff; }

/* LES AFFICHES DE FRONT. Une soirée à trois œuvres les montre toutes les
 * trois, à leur format vertical : c'est le contenu de la soirée, pas une
 * illustration. */
/* UNE SEULE FORME POUR TOUTES LES CARTES. Chaque cas se dessinait sur ses
   propres proportions : une affiche seule en 16/9 sur toute la largeur, trois
   affiches en 2/3 sur un tiers chacune, un cadre vide figé à 96 px. Résultat,
   trois hauteurs différentes côte à côte dans la même colonne, et des cartes
   qui ne s'alignent sur rien.

   La première réponse fut de figer la HAUTEUR de la zone. Elle alignait, mais
   elle donnait un rapport qui dépendait de la largeur de la fenêtre : mesurée
   le 26 août, la planche faisait 230 × 118, soit 1,95 — jamais 16/9. Une
   bannière s'y faisait recadrer de travers.

   ON FIXE DONC LE RAPPORT, PAS LA HAUTEUR. Toutes les planches d'une colonne
   ont la même largeur, donc la même hauteur : l'alignement tient exactement
   comme avant. Et la forme, elle, ne bouge plus. C'est le même raisonnement —
   fixer la zone et laisser le contenu s'y adapter — appliqué une case plus
   haut. */
:root { --h-planche: 118px; }   /* ne sert plus qu'au cadre vide, ci-dessous */

.planche {
  display: grid; gap: 6px; margin-top: 12px;
  aspect-ratio: 16 / 9;
}
.planche.n1 { grid-template-columns: 1fr; }
.planche.n2 { grid-template-columns: repeat(2, 1fr); }
.planche.n3 { grid-template-columns: repeat(3, 1fr); }

.jaquette {
  height: 100%; min-width: 0;
  border-radius: 8px;
  overflow: hidden;
  background: var(--fond);
  display: grid; place-items: center;
  color: var(--faible);
  font-weight: 600;
}
/* `cover` recadre au lieu de déformer : une affiche verticale et une bannière
   horizontale tiennent dans la même case sans que l'une soit écrasée. */
.jaquette img { width: 100%; height: 100%; object-fit: cover; display: block; }

.vide-planche {
  /* Le cadre vide prend la même forme que les pleines, sinon une soirée sans
     œuvre casse l'alignement qu'on vient d'obtenir. */
  aspect-ratio: 16 / 9;
  border: 1px dashed var(--ligne);
  border-radius: 8px;
  margin-top: 12px;
}

.pied {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 10px;
  min-height: 22px;
}
.menu-mot { color: var(--faible); }
.menu-val { color: var(--doux); text-transform: capitalize; }

/* CE QUI MANQUE SE DIT SUR LA CARTE. Un brouillon incomplet le montre depuis
 * le tableau, sans qu'on ait à l'ouvrir pour le découvrir. */
.alerte {
  padding: 3px 10px;
  border-radius: 20px;
  background: #4a3a1e;
  color: #f5c46a;
  font-size: 13px;
}

/* Une colonne vide dit ce qui lui manque plutôt que d'afficher un cadre nu. */
.creux {
  margin: 0;
  padding: 22px 16px;
  border: 1px dashed var(--ligne);
  border-radius: var(--rond-large);
  color: var(--faible);
  text-align: center;
}

/* Le sous-arbre de la barre latérale. */
.rameau-nom {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  text-transform: capitalize;
}
/* ── Les pages nues (connexion, erreur) ───────────────────────────────── */

body:not(.app) { display: grid; place-items: center; min-height: 100vh; }
/* LA PAGE VIDE, ET RIEN D'AUTRE. La classe s'appelait `.vide` tout court et
   posait 40 px de marge ; or `.liste.vide` et `.datier.vide` marquent aussi
   un contrôle SANS VALEUR — ils héritaient donc de la marge d'une page
   d'erreur, et une liste « Salon… » mesurait 108 px de haut au lieu de 28.
   Un nom de classe, une seule chose. */
.page-vide { text-align: center; padding: 40px; }
.page-vide h1 { font-size: 28px; font-weight: 600; margin: 0 0 16px; }
.page-vide p { color: var(--faible); margin: 0; }
.lien {
  display: inline-block;
  padding: 10px 20px;
  border-radius: var(--rond);
  background: var(--bleu);
  color: #fff;
  text-decoration: none;
}

.menu-carte.arme { background: var(--rouge); color: #fff; opacity: 1; font-size: 13px; }

/* ── Avancer d'une colonne ────────────────────────────────────────────── */
.avancer {
  margin-left: auto;
  border: 0;
  background: var(--ligne);
  color: var(--doux);
  font: inherit;
  font-size: 13px;
  padding: 3px 10px;
  border-radius: 20px;
  cursor: pointer;
  opacity: 0;
}
.fiche:hover .avancer { opacity: 1; }
.avancer:hover { background: var(--bleu); color: #fff; }
.avancer.refuse { background: #4a3a1e; color: #f5c46a; opacity: 1; }
.avancer + .menu-carte { margin-left: 0; }

/* ── Ce qui se replie ─────────────────────────────────────────────────── */
.titre-section {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  user-select: none;
  padding: 10px 0;
}
.titre-section h2 { font-size: 17px; font-weight: 600; margin: 0; }

.chevron {
  width: 22px; height: 22px;
  border: 0; background: none;
  cursor: pointer;
  position: relative;
}
.chevron::before {
  content: '';
  position: absolute; inset: 0;
  margin: auto;
  width: 8px; height: 8px;
  border-right: 2px solid var(--faible);
  border-bottom: 2px solid var(--faible);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .15s;
}
.replie .chevron::before { transform: rotate(-45deg) translate(-2px, 2px); }
.replie .corps { display: none; }

.repliable { margin-bottom: 20px; }
.corps { display: flex; flex-direction: column; gap: 2px; }

.ligne {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: var(--rond);
  background: var(--carte);
  color: inherit;
  text-decoration: none;
}
.ligne:hover { background: var(--carte-survol); }
.ligne b { font-weight: 500; }
.ligne .alerte { margin-left: auto; }
.ligne .menu-val { margin-left: auto; }

/* Une colonne repliée devient une bande verticale qui garde son nom. */
.colonne.repliee { }
.colonne.repliee .pile { display: none; }
.colonne.repliee .chapeau { opacity: .6; }

/* Le plieur de la barre latérale. */
/* ── L'accueil ────────────────────────────────────────────────────────── */
.affiche-large {
  display: block;
  position: relative;
  height: 260px;
  border-radius: 16px;
  overflow: hidden;
  background: var(--carte);
  color: inherit;
  text-decoration: none;
  margin-bottom: 20px;
}
.affiche-large .derriere {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: .55;
}
.affiche-large .dessus {
  position: absolute; inset: auto 0 0 0;
  padding: 28px;
  background: linear-gradient(transparent, rgba(0,0,0,.85));
}
.affiche-large h2 { font-size: 30px; font-weight: 700; margin: 10px 0 4px; }
.affiche-large p { margin: 0; color: var(--doux); text-transform: capitalize; }

.creux.grand {
  display: grid;
  place-items: center;
  height: 180px;
  margin-bottom: 20px;
  text-decoration: none;
}

.compteurs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-bottom: 32px; }
.compteur {
  background: var(--carte);
  border-radius: var(--rond-large);
  padding: 20px 22px;
  color: inherit;
  text-decoration: none;
}
.compteur:hover { background: var(--carte-survol); }
.compteur b { display: block; font-size: 30px; font-weight: 700; line-height: 1.1; }
.compteur span { color: var(--faible); }

.rayons { display: flex; flex-direction: column; }

/* LA MAJUSCULE NE VAUT QUE POUR LA PREMIÈRE LETTRE. `capitalize` mettait une
 * capitale à chaque mot : « Vendredi 14 Août À 21:04 », « Dans 1 Jours ». Le
 * français ne s'écrit pas comme ça. */
.affiche-large p,
.menu-val,
.rameau-nom,
.fiche .date { text-transform: none; }
.affiche-large p::first-letter,
.menu-val::first-letter,
.rameau-nom::first-letter { text-transform: uppercase; }

/* ── La page d'une soirée : les propriétés en lignes ──────────────────── */

.proprietes { max-width: 900px; }

.propriete {
  display: flex;
  align-items: flex-start;
  gap: 24px;
  padding: 14px 0;
  border-bottom: 1px solid var(--ligne);
}
.propriete:last-child { border-bottom: 0; }

/* ── UNE RANGÉE, UN SEUL NIVEAU ───────────────────────────────────────────
   Sur ces pages, quatre rangées se suivent et chacune porte un contrôle. Ils
   étaient sur trois plans différents : le champ de texte creusé dans la page
   (30,31,34), la page elle-même (49,51,56), les listes et les dates posées
   par-dessus (56,58,64). La question paraissait donc noire — un trou entre
   deux pastilles claires — alors que c'est la ligne la plus importante.

   Le fond sombre est le bon réglage QUAND le champ est posé sur une carte :
   il s'y creuse et se distingue. Ici il n'y a pas de carte, juste la page, et
   le même réglage produit l'effet inverse. Les contrôles d'une rangée se
   tiennent donc tous au même niveau, celui de la surface posée. */
.proprietes .champ,
.proprietes input[type="text"],
.proprietes input[type="search"],
.proprietes textarea {
  background: var(--carte);
  border-color: transparent;
}
.proprietes .champ:hover:not(:focus),
.proprietes textarea:hover:not(:focus) { background: var(--carte-survol); }
/* Le bleu au focus reste : c'est lui qui dit où l'on écrit. */
.proprietes .champ:focus,
.proprietes input[type="text"]:focus,
.proprietes input[type="search"]:focus,
.proprietes textarea:focus { border-color: var(--bleu); }

.quoi {
  flex: none;
  width: 130px;
  padding-top: 7px;
  color: var(--faible);
}
.valeur { flex: 1; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.valeur.en-ligne { gap: 10px; }
.fleche { color: var(--faible); }

.etiquette.neutre { background: var(--ligne); color: var(--doux); }

/* Les champs : ils ne ressemblent pas à des champs tant qu'on ne les touche
 * pas. Une page couverte de rectangles bordés fait formulaire ; ici la valeur
 * s'affiche, et se révèle éditable au survol. */
.date, .choix {
  border: 1px solid transparent;
  background: var(--carte);
  color: var(--texte);
  font: inherit;
  padding: 8px 12px;
  border-radius: var(--rond);
  cursor: pointer;
}
.date:hover, .choix:hover { border-color: var(--ligne); background: var(--carte-survol); }
.date:focus, .choix:focus { outline: 0; border-color: var(--bleu); }
.date:disabled, .choix:disabled { opacity: .5; cursor: default; }
.date::-webkit-calendar-picker-indicator { filter: invert(.7); cursor: pointer; }

/* L'accusé de prise en compte : un liseré une seconde, puis plus rien. */
.pris { border-color: var(--vert) !important; }
.rate { border-color: var(--rouge) !important; }

/* Les œuvres, en pastilles, avec un « + » au bout — comme les avatars
 * empilés de la maquette. */
.pastilles { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }

.pastille-oeuvre {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 12px 5px 5px;
  border-radius: 24px;
  background: var(--carte);
}
.pastille-oeuvre img {
  width: 30px; height: 30px;
  border-radius: 50%;
  object-fit: cover;
}
.pastille-oeuvre b { font-weight: 500; }
.oter {
  border: 0; background: none;
  color: var(--faible);
  font-size: 17px; line-height: 1;
  cursor: pointer;
  padding: 0 2px;
  border-radius: 50%;
}
.oter:hover { color: var(--rouge); }

.ajout {
  width: 40px; height: 40px;
  border: 1px dashed var(--ligne);
  border-radius: 50%;
  background: none;
  color: var(--faible);
  font-size: 20px;
  cursor: pointer;
}
.ajout:hover { border-color: var(--bleu); color: var(--bleu); border-style: solid; }

/* ── Le panneau de recherche ──────────────────────────────────────────── */

.voile {
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, .6);
  display: grid;
  place-items: start center;
  padding-top: 12vh;
  z-index: 50;
}
.panneau {
  width: min(720px, 92vw);
  background: var(--flanc);
  border: 1px solid var(--ligne);
  border-radius: 16px;
  padding: 18px;
  max-height: 70vh;
  overflow: auto;
}

.grille-oeuvres {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 14px;
  margin-top: 16px;
}
.carte-oeuvre {
  display: block;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  padding: 0;
}
/* LA HAUTEUR SE DEDUIT DE LA LARGEUR, ET NON L'INVERSE.
 *
 * `.jaquette` porte `height: 100%` — juste la ou elle remplit un cadre pose
 * d'avance. Ici son parent est une cellule de grille, donc etiree a la hauteur
 * de la ligne : l'affiche prenait TOUTE la carte, et `aspect-ratio` en
 * deduisait une largeur plus grande que la cellule. Resultat, des affiches qui
 * debordent a droite et un titre recouvert par la ligne suivante.
 *
 * Ca ne se voyait pas tant que les titres tenaient sur une ligne : c'est une
 * recherche aux titres longs qui l'a fait sortir. */
.carte-oeuvre .jaquette {
  display: block; width: 100%; height: auto;
  aspect-ratio: 2/3; margin-bottom: 8px;
}
/* Et les cartes ne s'etirent pas a la ligne : chacune fait sa hauteur. */
.grille-oeuvres { align-items: start; }
.carte-oeuvre b {
  display: block;
  font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.carte-oeuvre .sous { color: var(--faible); font-size: 13px; }
.carte-oeuvre:hover .jaquette { outline: 2px solid var(--bleu); outline-offset: 2px; }
.carte-oeuvre.refuse .sous { color: #f5c46a; }

.bouton.primaire.refuse { background: #4a3a1e; color: #f5c46a; }

/* ──  GAGNE TOUJOURS ───────────────────────────────────────────────
 *
 * L'attribut vaut  par défaut, mais N'IMPORTE QUELLE règle de
 *  le bat, parce qu'une classe l'emporte sur le style par défaut du
 * navigateur. Deux fois le même bug :
 *
 *      le panneau de recherche s'affichait d'emblée
 *     la liste des soirées refusait de se replier
 *
 * La première fois je n'avais corrigé que le cas sous les yeux. Une règle
 * générale ferme la famille entière.
 */
[hidden] { display: none !important; }

/* ── L'aperçu de ce qui sera publié ───────────────────────────────────── */
.apercu { margin-top: 36px; max-width: 900px; }
.planche-apercu {
  width: 100%;
  border-radius: var(--rond-large);
  border: 1px solid var(--ligne);
  display: block;
  background: var(--carte);
}

/* ── La recherche du haut ─────────────────────────────────────────────── */
/* LE GESTE PRINCIPAL NE SE CACHE PAS. « Lancer le vote » n'apparaissait qu'au
 * survol : introuvable au doigt, et invisible pour qui ne promène pas sa
 * souris sur les cartes. C'est l'action centrale de l'écran. */
.avancer { opacity: 1; }
.fiche .menu-carte { opacity: 0; }
.fiche:hover .menu-carte { opacity: 1; }

/* L'heure en clair à côté du champ : « 17/08/2026 21:04 » se lit mal quand on
 * cherche juste à savoir si c'est un vendredi. */
.dit {
  color: var(--faible);
  align-self: center;
  text-transform: none;
}
.dit::first-letter { text-transform: uppercase; }

/* ── La bascule ───────────────────────────────────────────────────────── */
.bascule {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
  padding: 6px 12px 6px 6px;
  border-radius: 24px;
  border: 1px solid transparent;
}
.bascule:hover { background: var(--carte); }
.bascule input { display: none; }
.bascule span {
  width: 42px; height: 24px;
  border-radius: 12px;
  background: var(--ligne);
  position: relative;
  transition: background .15s;
}
.bascule span::after {
  content: '';
  position: absolute;
  top: 3px; left: 3px;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--doux);
  transition: transform .15s, background .15s;
}
.bascule input:checked + span { background: var(--vert); }
.bascule input:checked + span::after { transform: translateX(18px); background: #fff; }
.bascule input:disabled + span { opacity: .4; }
.bascule b { font-weight: 500; }

/* ── Ce que le bot fera tout seul ─────────────────────────────────────── */
.pilote { margin-top: 36px; max-width: 900px; }
.pilote .ligne.fait { opacity: .5; }
.pilote .ligne.fait b { text-decoration: line-through; }

/* ── Les sondages ─────────────────────────────────────────────────────── */
.sondage {
  background: var(--carte);
  border-radius: var(--rond-large);
  padding: 18px 20px;
  margin-bottom: 12px;
}
.sondage.fini { opacity: .72; }
.sondage h3 { font-size: 18px; font-weight: 600; margin: 12px 0 14px; }
.sondage .rang { align-items: center; }
.sondage .menu-carte { opacity: .5; margin-left: 0; }
.sondage:hover .menu-carte { opacity: 1; }
.sondage .avancer { opacity: 1; margin-left: auto; }

/* Les barres de résultat. On les montre ICI parce qu'ouvrir le salon pour
 * savoir où en est un sondage lancé depuis cette page est un aller-retour de
 * trop. */
.barres { display: flex; flex-direction: column; gap: 8px; }
.barre-ligne { display: flex; align-items: center; gap: 14px; }
.barre-nom {
  flex: none; width: 190px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.barre-piste {
  flex: 1;
  height: 8px;
  border-radius: 4px;
  background: var(--fond);
  overflow: hidden;
}
.barre-plein {
  display: block;
  height: 100%;
  border-radius: 4px;
  background: var(--bleu);
  transition: width .2s;
}
.barre-chiffre { flex: none; width: 30px; text-align: right; color: var(--faible); }

.reponses { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.reponses .champ { margin-bottom: 0; }
.reglages { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.fin-panneau { margin-top: 18px; justify-content: flex-end; display: flex; }

/* ══ NOS CONTRÔLES, AUCUN CONTRÔLE DU SYSTÈME ═══════════════════════════
 *
 * Un `<select>` et un `<input type="datetime-local">` s'affichent avec le
 * style du système d'exploitation : gris clair, bordure carrée, calendrier
 * d'un autre siècle. Au milieu d'une interface sombre travaillée, ça saute
 * aux yeux. Tout est redessiné ici.
 */

/* ── La liste déroulante ──────────────────────────────────────────────── */
.liste { position: relative; display: inline-block; }

.liste-tete {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 170px;
  padding: 9px 14px;
  border: 1px solid transparent;
  border-radius: var(--rond);
  background: var(--carte);
  color: var(--texte);
  font: inherit;
  cursor: pointer;
  text-align: left;
}
.liste-tete:hover { background: var(--carte-survol); border-color: var(--ligne); }
.liste.ouverte .liste-tete { border-color: var(--bleu); }
.liste.vide .liste-tete span { color: var(--faible); }
.liste-tete span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Le chevron, dessiné plutôt qu'emprunté au système. */
.liste-tete i {
  flex: none;
  width: 8px; height: 8px;
  border-right: 2px solid var(--faible);
  border-bottom: 2px solid var(--faible);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .15s;
}
.liste.ouverte .liste-tete i { transform: rotate(-135deg) translate(-3px, -3px); }

.liste-choix {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 100%;
  max-height: 280px;
  overflow: auto;
  background: var(--flanc);
  border: 1px solid var(--ligne);
  border-radius: var(--rond-large);
  padding: 6px;
  z-index: 70;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .45);
}
.liste.ouverte .liste-choix { display: block; }

.liste-choix button {
  display: block;
  width: 100%;
  padding: 9px 12px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--doux);
  font: inherit;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
}
.liste-choix button:hover { background: var(--carte); color: var(--texte); }
.liste-choix button.choisi { background: var(--bleu); color: #fff; }

/* ── Le sélecteur de date ─────────────────────────────────────────────── */
.datier { position: relative; display: inline-block; }

.date-tete {
  padding: 9px 14px;
  border: 1px solid transparent;
  border-radius: var(--rond);
  background: var(--carte);
  color: var(--texte);
  font: inherit;
  cursor: pointer;
  white-space: nowrap;
}
.date-tete::first-letter { text-transform: uppercase; }
.date-tete:hover { background: var(--carte-survol); border-color: var(--ligne); }
.datier.ouverte .date-tete { border-color: var(--bleu); }
.datier.vide .date-tete { color: var(--faible); }

.date-menu {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  width: 268px;
  background: var(--flanc);
  border: 1px solid var(--ligne);
  border-radius: var(--rond-large);
  padding: 14px;
  z-index: 70;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .45);
}
.datier.ouverte .date-menu { display: block; }

.date-mois {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}
.date-mois b { font-weight: 600; text-transform: capitalize; }

.fleche-mois {
  width: 28px; height: 28px;
  border: 0; border-radius: 6px;
  background: none;
  cursor: pointer;
  position: relative;
}
.fleche-mois:hover { background: var(--carte); }
.fleche-mois::before {
  content: '';
  position: absolute; inset: 0; margin: auto;
  width: 8px; height: 8px;
  border-left: 2px solid var(--doux);
  border-bottom: 2px solid var(--doux);
  transform: rotate(45deg) translate(1px, -1px);
}
.fleche-mois.apres::before { transform: rotate(-135deg) translate(1px, -1px); }

.date-entetes, .date-grille {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.date-entetes span {
  text-align: center;
  color: var(--faible);
  font-size: 13px;
  padding-bottom: 6px;
}
.date-grille button {
  aspect-ratio: 1;
  border: 0; border-radius: 6px;
  background: none;
  color: var(--doux);
  font: inherit;
  cursor: pointer;
}
.date-grille button:hover { background: var(--carte); color: var(--texte); }
.date-grille button.choisi { background: var(--bleu); color: #fff; font-weight: 600; }

.date-heure {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--ligne);
}
.date-heure b { min-width: 26px; text-align: center; font-weight: 600; }
.date-heure i { color: var(--faible); font-style: normal; margin: 0 4px; }
.pas {
  width: 26px; height: 26px;
  border: 0; border-radius: 6px;
  background: var(--carte);
  color: var(--doux);
  font: inherit;
  cursor: pointer;
}
.pas:hover { background: var(--bleu); color: #fff; }

.desactive { opacity: .45; pointer-events: none; }

/* ── Nos infobulles ───────────────────────────────────────────────────── */
.a-bulle { position: relative; }
.a-bulle::after {
  content: attr(data-bulle);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  padding: 6px 10px;
  border-radius: 6px;
  background: var(--fond);
  color: var(--texte);
  font-size: 13px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity .12s;
  z-index: 80;
}
.a-bulle:hover::after { opacity: 1; }

/* ── DANS LA BARRE DU HAUT, L'INFOBULLE DESCEND ───────────────────────────
   Elle sort par le dessus — `bottom: calc(100% + 8px)`. Au milieu d'une page
   c'est ce qu'on veut ; dans la barre du haut il n'y a rien au-dessus, et la
   bulle partait hors de l'ecran. On la retourne pour ces boutons-la. */
.haut-actions .a-bulle::after,
.gestes .a-bulle::after {
  bottom: auto;
  top: calc(100% + 8px);
}

/* ── ET AUCUNE INFOBULLE NE FAIT DEFILER LES TOPICS ───────────────────────
   Elle est absolue, donc hors du flux — mais elle compte quand meme dans la
   zone defilable de son conteneur. Cinq tuiles de palette avec leur bulle en
   `nowrap`, et `.aire` gagnait cinquante pixels de large : une barre de
   defilement horizontale en bas de la page, pour du texte que personne ne voit
   tant qu'il ne survole pas.

   SUR LES TOPICS SEULEMENT. `.aire` defile en largeur exprès ailleurs : le
   tableau des Debats et celui des Soirees font quatre colonnes de 260 px
   minimum, et sur un ecran etroit la quatrieme ne s'atteint que comme ca. Une
   regle globale leur aurait coupe une colonne pour regler une bulle.

   `clip` et non `hidden` : `hidden` ferait de `.aire` un conteneur de
   defilement sur les deux axes et casserait le `scrollbar-gutter` pose plus
   haut. `clip` coupe sans rien rendre defilable. */
.aire[data-rubrique="forum"] { overflow-x: clip; }

/* ── Les barres de défilement ─────────────────────────────────────────── */
* { scrollbar-width: thin; scrollbar-color: var(--ligne) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--ligne); border-radius: 5px; }
*::-webkit-scrollbar-thumb:hover { background: var(--faible); }

/* La croix d'effacement d'un champ `type=search` vient du navigateur : on la
 * retire, nos champs se vident à la main. */
input[type=search]::-webkit-search-cancel-button,
input[type=search]::-webkit-search-decoration { -webkit-appearance: none; display: none; }

/* La sélection de texte aux couleurs de la maison. */
::selection { background: var(--bleu); color: #fff; }

/* ── LES CHAMPS DE SAISIE ─────────────────────────────────────────────────
 *
 * Un champ de texte doit rester un vrai `<input>` — on ne réécrit pas la
 * saisie au clavier. Mais RIEN DE CE QUI SE VOIT n'est laissé au navigateur :
 * le fond, la bordure, l'anneau de focus, le texte d'invite, le curseur, la
 * sélection et le remplissage automatique sont tous repris ici.
 *
 * La règle avait disparu en réécrivant la charte, et les champs du panneau de
 * sondage s'affichaient entièrement nus : fond blanc, bordure système.
 */
.champ,
input[type="text"],
input[type="search"],
textarea {
  width: 100%;
  padding: 13px 16px;
  border: 1px solid var(--ligne);
  border-radius: var(--rond);
  background: var(--fond);
  color: var(--texte);
  font: inherit;
  /* L'anneau de focus du système est bleu vif et carré sur Windows. */
  outline: 0;
  /* Le curseur de saisie aux couleurs de la maison. */
  caret-color: var(--bleu);
  transition: border-color .12s;
  -webkit-appearance: none;
  appearance: none;
}
.champ:focus,
input[type="text"]:focus,
input[type="search"]:focus,
textarea:focus { border-color: var(--bleu); }

.champ::placeholder,
input::placeholder,
textarea::placeholder { color: var(--faible); opacity: 1; }

/* Le remplissage automatique repeint le fond en jaune pâle. On le renvoie à
 * nos couleurs — l'ombre intérieure est le seul moyen d'y arriver. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--texte);
  -webkit-box-shadow: 0 0 0 40px var(--fond) inset;
  caret-color: var(--texte);
}

/* La barre de recherche du haut garde son fond, elle vit dans un cadre rond. */
/* Les boutons, partout : jamais le rendu du système. */
button { font: inherit; -webkit-appearance: none; appearance: none; }
/* L'anneau ne vaut plus que pour les liens : tout le reste montre son focus
 * autrement, et les deux ensemble faisaient un double liseré. */
a:focus-visible { outline: 2px solid var(--bleu); outline-offset: 2px; }


/* ── UNE SEULE MARQUE DE SÉLECTION ────────────────────────────────────────
 *
 * J'en avais posé deux, et elles se déclenchaient ensemble : la bordure du
 * contrôle passait au bleu ET un anneau bleu s'ajoutait autour. Ça faisait un
 * double liseré autour de chaque champ.
 *
 * La règle, désormais : un contrôle qui sait montrer son propre focus — champ,
 * liste, sélecteur de date, bouton dessiné — n'a PAS d'anneau. L'anneau reste
 * pour tout le reste, parce qu'un élément sans aucune marque de focus est
 * inutilisable au clavier.
 */
.champ:focus-visible,
input:focus-visible,
textarea:focus-visible,
.liste-tete:focus-visible,
.date-tete:focus-visible,
.bouton:focus-visible,
.menu-carte:focus-visible,
.avancer:focus-visible,
.oter:focus-visible,
.ajout:focus-visible,
.chevron:focus-visible,
/* Ceux qui n'ont pas de marque à eux la reçoivent au clavier seulement. */
.liste-tete:focus-visible,
.date-tete:focus-visible { border-color: var(--bleu); }
.bouton:focus-visible { box-shadow: 0 0 0 2px var(--fond), 0 0 0 4px var(--bleu); }
.liste-choix button:focus-visible,
.date-grille button:focus-visible,
.pas:focus-visible,
.fleche-mois:focus-visible { background: var(--carte-survol); color: var(--texte); }
.chevron:focus-visible::before,
/* ══ LA REPRISE À LA RACINE ═════════════════════════════════════════════
 *
 * Les règles ci-dessus habillent chaque composant, mais elles laissaient
 * passer ce qu'aucune ne visait. Trois oublis relevés en auditant les pages
 * une par une :
 *
 *   « Voir les soirées » était SOULIGNÉ — c'est un lien déguisé en bouton, et
 *   `.bouton` ne disait rien du soulignement.
 *
 *   Le lien invisible qui couvre une carte l'était aussi.
 *
 *   La case à cocher du panneau de sondage rendait en ARIAL, parce que la
 *   règle de police ne visait que les champs de texte.
 *
 * D'où cette section : ce qui s'applique à TOUT, une fois, plutôt qu'une
 * exception par composant.
 */

/* Aucun lien n'est souligné. Ceux qui doivent l'être le demandent. */
a { text-decoration: none; color: inherit; }
a.souligne { text-decoration: underline; }

/* Tout contrôle hérite de la police de la page, sans exception. */
button, input, select, textarea, optgroup { font: inherit; color: inherit; }

/* Une seule graduation d'arrondis, une seule durée de transition : deux
 * valeurs voisines mais différentes se remarquent sans qu'on sache pourquoi. */
.bouton, .champ, .date-tete, .liste-tete, .etiquette, .fiche, .ligne,
.sondage, .compteur, .rythme li, .creux { transition: background .12s, border-color .12s, color .12s; }

/* Le glisser d'une image ou d'un titre ouvre une fenêtre du navigateur au
 * milieu d'un clic mal assuré. */
img, .etiquette, .point, .sceau, .pastille-avatar { -webkit-user-drag: none; user-select: none; }

/* Sur mobile, le navigateur pose un voile gris au toucher. */
* { -webkit-tap-highlight-color: transparent; }

/* Une image qui n'a pas chargé affiche l'icône brisée du système et son texte
 * de remplacement : on garde le fond du cadre à la place. */
img { color: transparent; }

/* Ces liens-là gardent leur teinte propre. */
.sortie { color: var(--faible); }
.sortie:hover { color: var(--texte); }
.moi { color: var(--doux); }
.moi:hover { color: var(--texte); }
.entree { color: var(--doux); }
.lien { background: var(--bleu); color: #fff; }

/* ── LE GLISSER-DÉPOSER ENTRE COLONNES ───────────────────────────────────
 *
 * Le bouton « Lancer le vote → » sur une carte ne disait rien : son libellé
 * changeait selon la colonne, et il fallait le lire pour comprendre. Les
 * colonnes SONT les étapes — on pousse la carte vers la suivante.
 */
.fiche[draggable] { cursor: grab; }
.fiche.saisie { opacity: .4; cursor: grabbing; }

/* La colonne d'accueil s'annonce dès la prise, pas au survol : on doit savoir
 * où l'on peut aller avant de promener la carte. */
.colonne.accueille .pile {
  outline: 2px dashed var(--ligne);
  outline-offset: 6px;
  border-radius: var(--rond-large);
  min-height: 90px;
}
.colonne.visee .pile { outline-color: var(--bleu); background: rgba(88, 101, 242, .06); }

/* Le mot qu'on pose sur une carte quand le dépôt est refusé. */
.dit-carte {
  margin: 10px 0 0;
  padding: 7px 10px;
  border-radius: 6px;
  background: #4a3a1e;
  color: #f5c46a;
  font-size: 13px;
}

/* ── Le bouton de suppression ────────────────────────────────────────────
 *
 * TAILLE FIXE. Il changeait de texte, donc de largeur, et la rangée se
 * décalait sous le curseur entre le premier et le second clic.
 */
.oter-carte {
  margin-left: auto;
  flex: none;
  width: 28px; height: 28px;
  display: grid; place-items: center;
  border: 0;
  border-radius: 6px;
  background: none;
  cursor: pointer;
  opacity: 0;
  transition: opacity .12s, background .12s;
}
.fiche:hover .oter-carte { opacity: .6; }
.oter-carte:hover { opacity: 1; background: var(--ligne); }
.oter-carte svg {
  width: 16px; height: 16px;
  fill: none; stroke: var(--faible); stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.oter-carte:hover svg { stroke: var(--texte); }

/* Armé : la même taille, une autre couleur, et un battement pour qu'on voie
 * que le prochain clic n'est pas anodin. */
.oter-carte.arme { opacity: 1; background: var(--rouge); animation: bat 1.1s infinite; }
.oter-carte.arme svg { stroke: #fff; }
@keyframes bat { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.12); } }

/* ── `hidden` GAGNE TOUJOURS ─────────────────────────────────────────────
 *
 * L' attribut vaut display:none par défaut, mais NIMPORTE QUELLE règle de
 * display le bat : une classe l'emporte sur le style par défaut du navigateur.
 * Deux fois le même bug, à deux endroits :
 *
 *   .voile { display: grid }    le panneau de recherche s'affichait d'emblée
 *   .branche { display: flex }   la liste des soirées refusait de se replier
 *
 * La première fois je n'ai corrigé que le cas sous les yeux. Cette règle-ci
 * ferme la famille entière.
 */
[hidden] { display: none !important; }

/* ── Les débats ───────────────────────────────────────────────────────── */
.mur { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 14px; }
.debat { background: var(--carte); border-radius: var(--rond-large); padding: 18px 20px; }
.debat .rang { align-items: center; }
.debat h3 { font-size: 17px; font-weight: 600; margin: 12px 0 10px; }
.debat .oter-carte { opacity: .4; }
.debat:hover .oter-carte { opacity: 1; }

/* Le panneau de composition : plus large, parce quil porte une affiche. */
.panneau.large { width: min(860px, 94vw); }
.apercu-debat { margin-top: 16px; position: relative; }
.apercu-debat img { width: 100%; border-radius: var(--rond-large); display: block; }
.apercu-debat img:not([src]) { display: none; }
.apercu-debat .creux { padding: 48px 16px; }



/* ═══ DÉBATS ══════════════════════════════════════════════════════════════
   Un débat n'a pas d'étapes : il a un rythme. D'où un calendrier, et non un
   tableau à colonnes — ce qu'on veut lire, c'est la densité. */

/* ── Le calendrier ─────────────────────────────────────────────────────────
   PAS DE BOÎTE DANS UNE BOÎTE. Une case est déjà un contenant : border un
   rectangle à l'intérieur d'un rectangle borde deux fois la même chose. Les
   cases n'ont donc ni fond ni cadre — juste une ligne de séparation — et les
   rendez-vous sont des lignes de texte, distinguées par une pastille de
   couleur et rien d'autre. */
/* ══ L'AGENDA ══════════════════════════════════════════════════════════════
   Il y avait ici une grille de calendrier à sept colonnes. Sur une semaine
   ordinaire elle montrait TROIS rendez-vous dans quarante-deux cases : quatre
   colonnes vides portant chacune un tiret, et le contenu tassé dans des
   vignettes de trente pixels.

   Une grille a un sens quand les cases sont pleines. Un serveur Discord a deux
   ou trois rendez-vous par SEMAINE, pas par jour : elle dépensait donc tout
   l'écran à montrer du vide. On liste, et les jours sans rien disparaissent.

   ── LA COULEUR N'EST PAS UN ORNEMENT ─────────────────────────────────────
   La première version listait juste : des lignes grises, un point de couleur
   de huit pixels. C'était lisible et parfaitement mort — rien ne distinguait
   une soirée ciné d'un créneau vide avant d'avoir LU les deux.

   Chaque type porte donc sa teinte sur toute la carte. On reconnaît un ciné
   d'un débat sans lire, et la page cesse de ressembler à un relevé bancaire.

   Sur fond sombre, une teinte pastel se fabrique en posant la couleur à faible
   opacité : elle s'assombrit avec le fond au lieu de le trouer. */

/* ── LE PROCHAIN, DÉTACHÉ ─────────────────────────────────────────────────
   C'est ce qu'on vient chercher : en haut, plus grand, et il annonce le temps
   qui reste plutôt qu'une date à calculer. */
.prochain {
  /* DEUX CELLULES, pour qu'il pèse plus que les autres sans quitter la grille.
     Sur une fenêtre étroite où il n'y a qu'une colonne, `span 2` se réduit
     tout seul à la seule qui existe. */
  grid-column: span 2; max-width: none;
  display: flex; align-items: center; gap: 20px;
  padding: 22px 24px;
  border-radius: 16px; color: inherit; text-decoration: none;
  background: var(--aire);
  border: 1px solid var(--ligne);
  transition: transform .14s, box-shadow .14s;
}
a.prochain:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0,0,0,.28); }

.prochain.cine  { background: rgba(35,165,90,.16);  border-color: rgba(35,165,90,.40); }
.prochain.debat { background: rgba(121,131,245,.18); border-color: rgba(121,131,245,.42); }
.prochain.vote  { background: rgba(240,178,50,.15);  border-color: rgba(240,178,50,.38); }

.prochain-affiche {
  width: 68px; height: 102px; object-fit: cover; flex: none;
  border-radius: 10px; background: var(--carte);
  box-shadow: 0 3px 10px rgba(0,0,0,.3);
}
.prochain-pastille {
  width: 12px; height: 12px; flex: none; border-radius: 50%;
  background: var(--faible);
}
.prochain.cine  .prochain-pastille { background: var(--vert); }
.prochain.debat .prochain-pastille { background: var(--bleu-clair); }
.prochain.vote  .prochain-pastille { background: var(--jaune); }

.prochain-texte { display: flex; flex-direction: column; gap: 5px; min-width: 0; flex: 1; }
/* LE TEMPS QUI RESTE PASSE AVANT LE TITRE, et c'est délibéré : « dans 2 jours »
   ne demande aucun calcul là où « samedi 22 août » en demande un. */
.prochain-texte em {
  font-style: normal; font-size: 11.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .09em;
}
.prochain.cine  .prochain-texte em { color: #4ade80; }
.prochain.debat .prochain-texte em { color: #a5adf8; }
.prochain.vote  .prochain-texte em { color: #f6c860; }
.prochain-texte > b { font-size: 22px; font-weight: 650; letter-spacing: -.015em; }
.prochain-texte > span { font-size: 13.5px; color: var(--doux); }

.prochain-geste, .rdv-geste {
  flex: none; padding: 8px 15px; border-radius: 9px;
  border: 1px solid rgba(255,255,255,.16); background: rgba(255,255,255,.07);
  color: var(--texte); font-size: 13px; cursor: pointer; font-family: inherit;
  white-space: nowrap;
}
.prochain-geste:hover, .rdv-geste:hover { background: rgba(255,255,255,.14); }

/* ── LA GRILLE DE CARTES ──────────────────────────────────────────────────
   UNE GRILLE DE CARTES, PAS UNE GRILLE DE JOURS. C'est toute la différence
   avec le calendrier qu'il y avait ici : les colonnes ne sont plus des jours
   qu'il faut remplir, ce sont des places que les rendez-vous occupent dans
   l'ordre. Aucune case ne peut donc rester vide.

   `auto-fill` avec un minimum de 290 px : deux colonnes sur un écran ordinaire,
   trois sur un grand, une seule sur une fenêtre étroite. La largeur sert enfin
   à montrer plus, au lieu d'étaler du vide. */
.grille-rdv {
  display: grid; gap: 14px;
  /* ── auto-fit, ET SURTOUT PAS auto-fill ─────────────────────────────────
     `auto-fill` réserve autant de colonnes que la largeur peut en contenir,
     même vides. Sur une semaine à deux rendez-vous, on retrouvait le défaut
     du calendrier : une carte en haut à gauche et trois colonnes de vide.
     `auto-fit` fait disparaître les colonnes que personne n'occupe, et les
     cartes présentes s'étalent pour prendre la place. */
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
}

.carte {
  /* MAIS PAS JUSQU'À L'ABSURDE. Avec `auto-fit` et un seul rendez-vous, la
     carte occuperait seize cents pixels de large pour trois lignes de texte.
     Le plafond la garde à une taille où elle reste une carte. */
  max-width: 480px;
  display: flex; flex-direction: column; gap: 11px;
  padding: 16px 17px; border-radius: 14px;
  color: inherit; text-decoration: none;
  background: var(--aire); border: 1px solid var(--ligne);
  transition: transform .14s, box-shadow .14s, background .14s;
}
a.carte:hover { transform: translateY(-3px); box-shadow: 0 10px 26px rgba(0,0,0,.3); }

.carte.cine       { background: rgba(35,165,90,.13);  border-color: rgba(35,165,90,.26); }
a.carte.cine:hover  { background: rgba(35,165,90,.20); }
.carte.debat      { background: rgba(121,131,245,.15); border-color: rgba(121,131,245,.28); }
a.carte.debat:hover { background: rgba(121,131,245,.22); }
.carte.vote       { background: rgba(240,178,50,.12);  border-color: rgba(240,178,50,.26); }
a.carte.vote:hover  { background: rgba(240,178,50,.19); }

.carte-haut { display: flex; align-items: center; gap: 12px; min-width: 0; }

.carte-affiche {
  width: 40px; height: 60px; object-fit: cover; flex: none;
  border-radius: 7px; background: var(--carte);
  box-shadow: 0 2px 7px rgba(0,0,0,.28);
}
/* LA PASTILLE TIENT LA LARGEUR D'UNE AFFICHE, pas la sienne : sans ça, les
   cartes avec vignette et celles sans ne s'alignent pas, et la grille se met
   à onduler d'une carte à l'autre. */
.carte .tache { width: 40px; flex: none; height: 12px; position: relative; }
.carte .tache::after {
  content: ""; position: absolute; left: 50%; top: 0; transform: translateX(-50%);
  width: 12px; height: 12px; border-radius: 50%; background: var(--faible);
}
.carte.cine  .tache::after { background: var(--vert); }
.carte.debat .tache::after { background: var(--bleu-clair); }
.carte.vote  .tache::after { background: var(--jaune); }

/* ── CHAQUE CARTE PORTE SA DATE ───────────────────────────────────────────
   Sans en-tête de jour pour les regrouper, une carte doit se suffire : sinon
   on remonte chercher à quel jour elle appartient, ce qui est exactement le
   travail qu'on veut éviter.

   LE TEMPS QUI RESTE PASSE AVANT LA DATE : « dans 2 jours » ne demande aucun
   calcul là où « samedi 22 août » en demande un. */
.carte-quand { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.carte-quand em {
  font-style: normal; font-size: 10.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .09em; color: var(--faible);
}
.carte.cine  .carte-quand em { color: #4ade80; }
.carte.debat .carte-quand em { color: #a5adf8; }
.carte.vote  .carte-quand em { color: #f6c860; }
.carte-quand b {
  font-size: 13px; font-weight: 600; color: var(--doux);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Deux lignes au plus, puis les points de suspension. Une question de débat
   fait parfois quatre-vingts caractères : sans borne, une carte deviendrait
   deux fois plus haute que ses voisines et casserait l'alignement de la
   rangée. */
.carte-titre {
  font-size: 15.5px; font-weight: 550; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

.carte-bas { display: flex; align-items: center; gap: 9px; min-width: 0; margin-top: auto; }

.rdv-type {
  flex: none; padding: 2px 9px; border-radius: 999px;
  font-size: 11px; font-weight: 600;
  background: rgba(255,255,255,.09); color: var(--doux);
}
.carte.cine  .rdv-type { background: rgba(35,165,90,.28);  color: #7ee2a8; }
.carte.debat .rdv-type { background: rgba(121,131,245,.30); color: #bcc2fa; }
.carte.vote  .rdv-type { background: rgba(240,178,50,.26);  color: #f8d68a; }
.rdv-salon {
  font-size: 12.5px; color: var(--faible); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rdv-geste { margin-left: auto; }

/* UN CRÉNEAU LIBRE N'EST PAS UN RENDEZ-VOUS. C'est une place où l'on POURRAIT
   mettre quelque chose : le trait discontinu le dit sans un mot, et le fond
   reste vide pour qu'un planning creux ne paraisse pas plein. */
.carte.libre { background: none; border: 1px dashed var(--ligne); }
.carte.libre:hover { background: rgba(255,255,255,.03); }
.carte.libre .carte-titre { font-weight: 400; color: var(--doux); }
.carte.libre .tache::after { background: none; box-shadow: inset 0 0 0 1.5px var(--faible); }
.carte.libre .rdv-type { background: rgba(255,255,255,.06); color: var(--faible); }

/* CE QUI SE MARCHE DESSUS SE SIGNALE LÀ OÙ ÇA SE PASSE. Une pile de bandeaux
   jaunes en haut de page annonce un problème puis oblige à le chercher plus
   bas ; ici la carte concernée porte le mot. */
.carte.heurte { box-shadow: inset 0 0 0 1px rgba(240,178,50,.55); }
.carte-note {
  flex: none; font-size: 10.5px; color: #f6c860;
  background: rgba(240,178,50,.16); padding: 3px 9px; border-radius: 999px;
}

/* UN CRÉNEAU LIBRE N'EST PAS UN RENDEZ-VOUS. C'est une place où l'on POURRAIT
   mettre quelque chose : le trait discontinu le dit sans un mot, et le fond
   reste vide pour qu'un planning creux ne paraisse pas plein. */
.prochain.libre {
  background: none; border: 1px dashed var(--ligne);
}
.prochain.libre .prochain-texte > b { font-weight: 550; color: var(--doux); }
.prochain.libre .prochain-texte em { color: var(--faible); }

.agenda-vide {
  display: flex; flex-direction: column; gap: 7px;
  padding: 44px 0; text-align: center;
}
.agenda-vide b { font-size: 16px; font-weight: 500; }
.agenda-vide span { font-size: 13.5px; color: var(--faible); }
.agenda-vide a { color: var(--bleu-clair); }

/* DEUX MENTIONS, PAS DEUX BOÎTES. Encadrées, elles prenaient l'allure de
   boutons dans une barre de boutons — donc de choses à cliquer. Ce sont des
   constats : ils se lisent, ils ne se cliquent pas. */
.note-heurts { font-size: 13px; color: var(--jaune); white-space: nowrap; }
.note-heurts::before {
  content: ""; display: inline-block; vertical-align: middle;
  width: 6px; height: 6px; margin-right: 7px;
  border-radius: 50%; background: var(--jaune);
}


/* ── Une colonne = une rubrique = une file ────────────────────────────────
   Sur les soirées, les colonnes sont des étapes ; ici ce sont des
   rendez-vous. */
/* LA GRILLE S'ADAPTE AU NOMBRE DE RUBRIQUES. Elle héritait des quatre
   colonnes des soirées — qui, elles, ont quatre étapes fixes — et gardait donc
   une place vide en réserve : trois colonnes serrées pour rien, alors que la
   largeur était disponible. Ici le nombre varie, la grille doit varier avec. */
/* MÊME LARGEUR DE COLONNE QUE LE CINÉMA. Le tableau des soirées pose quatre
   colonnes fixes ; celui des rubriques en a autant qu'il y a de rubriques.
   Sans réglage, il héritait des quatre — d'où une piste vide en réserve et des
   colonnes serrées. Avec `auto-fit` et `1fr`, l'inverse : trois colonnes
   étirées à 366 px, deux pages qui ne se ressemblaient plus.
   On garde donc la MESURE du cinéma — des colonnes de 260 à 280 px — et on
   laisse la ligne se terminer là où elle veut. */
.tableau.rubriques {
  align-items: start;
  /* `auto-fill` AVEC `1fr` : même calcul que le cinéma, donc même largeur de
     colonne d'une page à l'autre. La piste vide qu'il laisse en bout de ligne
     n'est pas un défaut — c'est elle qui donne le ratio. En l'effaçant avec
     `auto-fit`, les trois colonnes s'étiraient à 366 px et les deux pages ne
     se ressemblaient plus. */
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
.colonne.rubrique.dormante { opacity: .5; }

.chapeau .oter-carte { margin-left: 4px; }

/* Deux teintes de plus, pour que chaque rubrique ait la sienne. */
.chapeau.ambre  { background: var(--fond-ambre); }
.chapeau.ambre  .point { background: var(--vif-ambre); }
.chapeau.violet { background: var(--fond-violet); }
.chapeau.violet .point { background: var(--vif-violet); }

/* LE RÉGLAGE SE RANGE DERRIÈRE LA ROUE. Quatre menus étalés en permanence
   au-dessus d'une pile de cartes encombrent l'écran pour dire une chose qu'on
   règle une fois par an. */
.roue {
  display: flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; flex: none; margin-left: 2px;
  border: 0; border-radius: 6px; background: none; cursor: pointer;
  opacity: .6; transition: opacity .15s, background .15s, transform .25s;
}
.roue svg {
  width: 15px; height: 15px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.roue:hover { opacity: 1; background: rgba(255,255,255,.13); }
.colonne.ouverte .roue { opacity: 1; transform: rotate(60deg); background: rgba(255,255,255,.13); }

/* Le rendez-vous en clair : c'est ce qu'on veut savoir en arrivant, et ça se
   lit sans rien ouvrir. */
.resume {
  margin: 8px 2px 12px; font-size: 12.5px; color: var(--faible);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.colonne.dormante .resume { font-style: italic; }

.cadence {
  display: flex; flex-direction: column; gap: 2px;
  padding: 8px; margin-bottom: 12px;
  /* Le panneau doit se détacher du fond : `--aire` EST la couleur de la page,
     il n'avait donc aucun contraste et flottait dans le vide. */
  background: var(--carte); border-radius: var(--rond);
}
.rangee {
  display: flex; align-items: center; gap: 8px;
  padding: 3px 4px; border-radius: 6px; min-width: 0;
}
.rangee > span:first-child {
  flex: 1; min-width: 0; font-size: 13px; color: var(--doux);
}
.rangee .bascule.seule b { display: none; }

.liste.nue { display: inline-block; min-width: 0; flex: none; }
.liste.nue .liste-tete {
  min-width: 0; width: auto; padding: 4px 8px;
  background: none; border: 0; border-radius: 5px;
  font-size: 13px; font-weight: 500; gap: 5px; color: var(--texte);
}
.liste.nue .liste-tete:hover { background: var(--carte); }
.liste.nue .liste-tete span {
  min-width: 0; max-width: 130px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.liste.nue.ouverte .liste-tete { background: var(--carte); }
.liste.nue.vide .liste-tete span { color: var(--faible); font-style: italic; }
/* Le menu flotte au-dessus : il garde une largeur lisible, et s'aligne à
   droite pour ne pas sortir de la colonne. */
.liste.nue .liste-choix { min-width: 168px; left: auto; right: 0; }

.oter-rubrique {
  width: 100%; margin-top: 6px; padding: 7px;
  border: 0; border-radius: 6px; background: none;
  font: inherit; font-size: 12.5px; color: var(--faible); cursor: pointer;
  transition: background .15s, color .15s;
}
.oter-rubrique:hover { background: var(--rouge); color: #fff; }
.oter-rubrique.arme { background: var(--rouge); color: #fff; }

/* ── Les cartes de la file ───────────────────────────────────────────────*/
.fiche.debat h3 {
  margin: 6px 0 0; font-size: 14px; font-weight: 500;
  line-height: 1.4; white-space: normal;
}
.fiche.debat.muette h3 { color: var(--faible); font-style: italic; }

/* LE RANG SE VOIT : c'est lui qui décide de tout, la date d'une carte n'est
   que sa place dans la file. */
.tour {
  display: inline-flex; align-items: center; justify-content: center;
  width: 19px; height: 19px; flex: none;
  border-radius: 50%; font-size: 11px; font-weight: 700;
  background: var(--ligne); color: var(--doux);
}
.tour.suivant { background: var(--bleu); color: #fff; }
.quand-debat {
  flex: 1; min-width: 0; font-size: 12px; color: var(--faible);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.fiche.saisie { opacity: .4; }
.fiche.occupe { opacity: .5; pointer-events: none; }
.pile.visee { background: rgba(88,101,242,.06); border-radius: var(--rond); }

/* Le trait dit où la carte tombera. Sans lui on lâche à l'aveugle, et il faut
   recommencer une fois pour comprendre la règle. */
.trait {
  height: 2px; margin: 3px 0; border-radius: 2px;
  background: var(--bleu); pointer-events: none;
}

/* En tete de pile : la marge passe donc EN DESSOUS, pas au-dessus. */
.ajout-ligne {
  width: 100%; padding: 9px; margin-bottom: 4px;
  background: transparent; color: var(--faible);
  border: 1px dashed var(--ligne); border-radius: var(--rond);
  font: inherit; font-size: 13px; cursor: pointer;
  transition: border-color .15s, color .15s;
}
.ajout-ligne:hover { border-color: var(--bleu); color: var(--texte); }

/* ── Les débats déjà posés ────────────────────────────────────────────────*/
.rendezvous {
  position: relative; display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; margin-bottom: 6px;
  background: var(--aire); border-radius: var(--rond);
  transition: background .15s;
}
.rendezvous:hover { background: var(--carte); }
.corpsrdv { min-width: 0; flex: 1; }
.corpsrdv h3 {
  margin: 0; font-size: 15px; font-weight: 600; line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.corpsrdv .sous { margin: 2px 0 0; font-size: 13px; color: var(--faible); }
.rendezvous .etiquette, .rendezvous .oter-carte { position: relative; z-index: 1; flex: none; }

/* L'aperçu ne clignote plus : la nouvelle image remplace l'ancienne une fois
   chargée, au lieu de vider la balise à chaque lettre. */
.planche-apercu { transition: opacity .18s; }
.planche-apercu:not(.vu) { opacity: 0; }

/* ═══ RIEN NE DÉBORDE, NULLE PART ═════════════════════════════════════════
   Une barre de défilement horizontale veut dire qu'un bloc a imposé sa
   largeur au lieu de s'adapter. Le coupable est presque toujours le même :
   en flex comme en grille, un enfant vaut `min-width: auto`, c'est-à-dire la
   largeur de son contenu — il refuse donc de se réduire, et pousse tout le
   monde. On l'autorise à se réduire, une fois pour toutes. */
.coque > main, .grille > *, .semaine > *, .tableau > * { min-width: 0; }
.corpsrdv, .propriete .valeur { min-width: 0; }

/* Le dernier rempart : si un bloc échappe encore à la règle, la page se
   coupe au lieu de se laisser tirer. Ce n'est pas la correction — c'est le
   filet, pour qu'un oubli ne se voie jamais comme un défaut de conception. */
html, body { max-width: 100%; overflow-x: clip; }


/* Deux teintes de plus, pour les rubriques qu'on invente. */
.chapeau.rose  { background: var(--fond-rose); }
.chapeau.rose  .point { background: var(--vif-rose); }
.chapeau.cyan  { background: var(--fond-cyan); }
.chapeau.cyan  .point { background: var(--vif-cyan); }

/* ── Choisir la couleur d'une rubrique ────────────────────────────────────
   À l'œil, sur la pastille. Nommer « ambre » dans une liste déroulante
   ferait lire un mot pour choisir une couleur. */
.rangee.couleurs { align-items: center; }
.nuancier { display: flex; gap: 5px; flex: none; }
.pastille-teinte {
  width: 17px; height: 17px; padding: 0; flex: none;
  border: 0; border-radius: 50%; cursor: pointer;
  box-shadow: 0 0 0 0 var(--texte);
  transition: transform .12s, box-shadow .12s;
}
.pastille-teinte:hover { transform: scale(1.18); }
.pastille-teinte.choisi { box-shadow: 0 0 0 2px var(--aire), 0 0 0 3.5px var(--texte); }
.pastille-teinte.bleu   { background: #5865f2; }
.pastille-teinte.vert   { background: #23a55a; }
.pastille-teinte.ambre  { background: #d89428; }
.pastille-teinte.violet { background: #8b5cf6; }
.pastille-teinte.rose   { background: #e0559b; }
.pastille-teinte.cyan   { background: #22a8b4; }
.pastille-teinte.gris   { background: #6a6d75; }

/* L'aperçu, collé à la question qu'il rend. */
.apercu-vif .valeur { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.apercu-vif .planche-apercu { max-width: 460px; width: 100%; border-radius: var(--rond); display: block; }
.apercu-vif .planche-apercu:not([src]) { display: none; }
.bouton.petit { padding: 5px 11px; font-size: 12.5px; }
.bouton.mince { padding: 6px 13px; font-size: 12.5px; }

/* Le titre de colonne se lit, il ne s'édite pas : le nom se change derrière
   la roue, avec le reste du réglage. */
.nom-colonne { flex: 1; min-width: 0; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.champ.mince { width: auto; flex: none; max-width: 150px; padding: 5px 9px; font-size: 13px; }


/* Un compteur, pas une jauge : le site compte, c'est toi qui juges. */
/* Une mention en en-tête : du texte, pas une carte. */
.mention { font-size: 13px; color: var(--faible); white-space: nowrap; }

/* ── Semaine ou mois ──────────────────────────────────────────────────────
   Deux vues, pas un menu : il n'y en a que deux, et on veut voir laquelle
   est active sans l'ouvrir. */
.bascule-vue {
  display: inline-flex; padding: 2px; gap: 2px;
  background: var(--aire); border-radius: 999px;
}
.bascule-vue a {
  padding: 5px 14px; border-radius: 999px;
  font-size: 13px; font-weight: 500; color: var(--faible);
  transition: background .15s, color .15s;
}
.bascule-vue a:hover { color: var(--texte); }
.bascule-vue a.actif { background: var(--carte); color: var(--texte); }

/* `.semaine` NOMME DÉJÀ LA LIGNE DE SEPT JOURS : la réutiliser pour la vue
   transformait le calendrier lui-même en grille de sept colonnes, et tout se
   tassait dans un filet vertical. Une classe, une chose — la vue s'appelle
   `.vue-semaine`.

   LA SEMAINE A LA PLACE D'EN DIRE PLUS. Une seule ligne de sept jours : la
   case respire, et chaque rendez-vous peut porter son salon sous son titre
   au lieu de se faire couper. */







/* Un jour vide se signale d'un tiret : sans lui, on ne sait pas si la case
   est vide ou si l'affichage a échoué. */


/* ── Les affiches dans le planning ────────────────────────────────────────
   UNE AFFICHE SE RECONNAÎT AVANT D'ÊTRE LUE. Le calendrier était un mur de
   texte où chaque ligne ressemblait à la précédente ; la vignette dit « c'est
   Interstellar » sans qu'on ait à lire. Elle remplace la pastille de couleur :
   deux repères pour la même chose feraient double emploi. */


/* UN VOTE MONTRE SES TROIS AFFICHES, en éventail : c'est exactement ce qui se
   joue ce soir-là, et trois vignettes le disent mieux qu'un intitulé. Elles se
   chevauchent pour tenir dans la largeur d'une case. */




/* En vue semaine la case respire : l'affiche peut être lue, pas seulement
   reconnue. */






/* ═══ LES MINI-JEUX ═══════════════════════════════════════════════════════
   UN CATALOGUE QU'ON VOIT. L'affiche de chaque jeu est dessinée par le même
   code que la publication : ce qu'on regarde ici est exactement ce qui
   partira dans le salon. */
.jeux {
  display: grid; gap: 16px; margin-bottom: 28px;
  grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
}
.jeu {
  background: var(--aire); border-radius: var(--rond-large);
  overflow: hidden; display: flex; flex-direction: column;
  transition: background .15s;
}
.jeu:hover { background: var(--carte); }
/* Un jeu jamais lancé s'efface un peu : il est là, mais il n'a rien à dire.
   SEULEMENT SI D'AUTRES ONT TOURNÉ : sans point de comparaison, le voile ne
   distingue rien et ternit les quinze tuiles d'un coup. */
.jeux.avec-passe .jeu.jamais { opacity: .55; }
.jeux.avec-passe .jeu.jamais:hover { opacity: 1; }

.planche-jeu { width: 100%; display: block; background: var(--fond); }
.dessous { padding: 13px 15px 15px; }
.dessous h3 { margin: 0; font-size: 15px; font-weight: 600; }
.dessous .quoi {
  margin: 4px 0 0; font-size: 13px; color: var(--doux); line-height: 1.4;
}

/* LA COMMANDE EST LE NOM DU JEU, et l'écrire ici évite d'avoir à le retenir. */
.commandes { margin: 9px 0 0; display: flex; flex-wrap: wrap; gap: 5px; }
.commandes code {
  padding: 2px 7px; border-radius: 5px;
  background: var(--fond); color: var(--bleu-clair);
  font-size: 12.5px; font-family: ui-monospace, Menlo, Consolas, monospace;
}

.chiffres {
  display: flex; flex-wrap: wrap; gap: 4px 12px; margin-top: 11px;
  font-size: 12.5px; color: var(--faible);
}
.chiffres b { color: var(--texte); font-weight: 600; }
.chiffres .en-cours { color: var(--vert); }
.dessous .sous { margin: 8px 0 0; font-size: 12px; color: var(--faible); }

/* ── Ce qui s'est joué ────────────────────────────────────────────────────*/
.partie {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 14px; margin-bottom: 5px;
  background: var(--aire); border-radius: var(--rond);
}
.partie .emoji { font-size: 19px; flex: none; }
.partie h3 { margin: 0; font-size: 14px; font-weight: 600; }

/* ASSEZ DE MONDE, OU PAS. Un « 3 joueurs » sur un jeu qui en demande six dit
   que la partie n'a pas pris — c'est l'information utile, pas le nombre. */
.joueurs { flex: none; font-size: 12.5px; color: var(--faible); }
.joueurs b { font-weight: 600; }
.joueurs.assez b { color: var(--vert); }
.joueurs.court b { color: var(--jaune); }
.duree { flex: none; font-size: 12.5px; color: var(--faible); min-width: 52px; text-align: right; }

/* ── La loupe sur une affiche ─────────────────────────────────────────────
   RIEN DE NATIF : ni `dialog`, ni la visionneuse du navigateur. C'est notre
   fenêtre, avec notre fond, notre typo et nos gestes de fermeture. */
.jeu { cursor: pointer; }
.jeu:focus-visible { outline: 2px solid var(--bleu); outline-offset: 2px; }

/* Le fond de la page ne défile plus derrière la loupe : sinon la molette
   déplace ce qu'on ne regarde pas, et on perd sa place en fermant. */
body.fige { overflow: hidden; }

.visionneuse { position: fixed; inset: 0; z-index: 60; display: flex;
  align-items: center; justify-content: center; padding: 28px; }
.visionneuse-fond { position: absolute; inset: 0; background: rgba(0, 0, 0, .74); }

.visionneuse-corps {
  position: relative; margin: 0; z-index: 1;
  width: min(760px, 100%); max-height: 100%;
  display: flex; flex-direction: column;
  background: var(--aire); border-radius: var(--rond-large);
  overflow: auto;
  animation: monte .16s ease-out;
}
@keyframes monte { from { opacity: 0; transform: translateY(10px); } }

.visionneuse-corps img { width: 100%; display: block; background: var(--fond); }
.visionneuse-corps figcaption { padding: 16px 20px 20px; }
.visionneuse-corps h3 { margin: 0; font-size: 19px; font-weight: 600; }
.visionneuse-corps .quoi { margin: 5px 0 0; color: var(--doux); font-size: 14px; }
.visionneuse-corps .commandes { margin: 12px 0 0; }
.visionneuse-corps .sous { margin: 10px 0 0; font-size: 12.5px; color: var(--faible); }

.visionneuse-fermer {
  position: absolute; top: 10px; right: 10px;
  width: 32px; height: 32px; display: flex;
  align-items: center; justify-content: center;
  border: 0; border-radius: 50%; cursor: pointer;
  background: rgba(0, 0, 0, .55); backdrop-filter: blur(3px);
  transition: background .15s;
}
.visionneuse-fermer:hover { background: rgba(0, 0, 0, .8); }
.visionneuse-fermer svg {
  width: 15px; height: 15px; fill: none; stroke: #fff;
  stroke-width: 2.2; stroke-linecap: round;
}

/* ── Les débats déjà posés, en damier ─────────────────────────────────────
   LA QUESTION EST LE CONTENU. Le pavé portait le fond de la carte partie dans
   le salon — une image le plus souvent générique, qu'il fallait ensuite voiler
   d'un dégradé pour que le texte reste lisible. On peignait un décor, puis on
   le masquait pour lire.

   LA COULEUR REMPLACE L'IMAGE comme repère. Elle vient de la teinte de la
   rubrique, donc une rubrique créée demain a la sienne sans qu'on touche ici.
   On reconnaît la famille d'un coup d'œil, et la question se lit sans rien
   traverser. */
.damier {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
}

.pave {
  position: relative;
  display: flex; flex-direction: column; justify-content: space-between; gap: 10px;
  min-height: 116px; padding: 13px 14px 14px;
  border-radius: var(--rond);
  color: var(--texte);

  /* Un aplat, pas un dégradé : il n'y a plus d'image sous lequel se glisser.
     La teinte est mêlée au fond des cartes plutôt qu'appliquée pure — à pleine
     saturation, sept couleurs côte à côte font une grille qui crie, et le texte
     blanc n'y tient plus. La première ligne sert de repli si color-mix manque. */
  background: var(--fond-teinte, var(--fond-gris));
  border: 1px solid transparent;

  /* IL FAUT QUE ÇA TIENNE À CINQ CENTS : le navigateur n'a pas à calculer la
     mise en page d'une tuile hors écran. */
  content-visibility: auto;
  contain-intrinsic-size: 210px 116px;
  transition: transform .16s, border-color .16s;
}

.pave:hover {
  transform: translateY(-2px);
  border-color: var(--vif-teinte, transparent);
}
.pave:focus-visible { outline: 2px solid var(--vif-teinte, var(--bleu)); outline-offset: 2px; }

/* LA RUBRIQUE EN PETIT, EN COULEUR. Elle était une pastille sur verre dépoli,
   posée par-dessus l'image ; sans image, la couleur du texte suffit à la
   détacher, et une pastille ferait un objet de plus à regarder. */
.pave .numero {
  font-size: 11px; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
  color: var(--vif-teinte, var(--faible));
}

.pave h3 {
  margin: 0;
  font-size: 14.5px; font-weight: 600; line-height: 1.35;
  /* Quatre lignes : une de plus qu'avant, puisque le texte ne dispute plus la
     place à une image. Au-delà, la tuile devient un paragraphe. */
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}

/* Un point dit qu'un fil est ouvert — l'index de la conversation existe. */
.pave .fil-ouvert {
  position: absolute; top: 14px; right: 12px;
  width: 7px; height: 7px; border-radius: 50%; background: var(--vert);
}

.pages {
  display: flex; align-items: center; justify-content: center; gap: 16px;
  margin-top: 14px; font-size: 13px; color: var(--faible);
}
.pages a { color: var(--bleu-clair); font-weight: 500; }
.pages a:hover { text-decoration: underline; }

/* ── Changer l'image d'une carte de débat ─────────────────────────────────
   LE BOUTON VIT SUR L'IMAGE. Sous elle, en petit et en gris, il ne se
   trouvait pas : on cherche à changer une image en regardant l'image. */
.cadre-apercu { position: relative; display: inline-block; max-width: 460px; width: 100%; }
.cadre-apercu:has(img:not([src])) { display: none; }

/* L'ICÔNE SEULE. Le bouton se dépliait au survol pour se nommer, mais replié
   la première lettre du mot dépassait — on lisait « ⟳u », ce qui ne veut rien
   dire et attire l'œil bien plus qu'un libellé absent. Une flèche circulaire
   sur une image se comprend sans mot ; le nom reste dans l'infobulle. */
/* Les deux boutons vivent sur l'image, en haut à droite : c'est en regardant
   l'image qu'on décide d'en changer, pas en lisant sous elle. */
.gestes-fond {
  position: absolute; top: 10px; right: 10px;
  display: flex; gap: 6px;
}
.changer-fond {
  display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0;
  border: 0; border-radius: 50%; cursor: pointer;
  background: rgba(0, 0, 0, .6); backdrop-filter: blur(4px);
  color: #fff;
  transition: background .15s, transform .15s;
}
.changer-fond svg {
  width: 16px; height: 16px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
  transition: transform .4s;
}
/* Au survol il se déplie et se nomme : fermé il ne prend pas la place de
   l'image, ouvert il dit ce qu'il fait sans qu'on ait à deviner l'icône. */
.changer-fond:hover, .changer-fond:focus-visible { background: rgba(0, 0, 0, .85); }
/* Seule la flèche circulaire tourne : c'est ce qu'elle fait. Faire pivoter la
   flèche d'envoi la ferait pointer vers le bas, soit l'inverse du geste. */
#autre-fond:hover svg { transform: rotate(-180deg); }
#fond-a-moi:hover svg { transform: translateY(-2px); }
.changer-fond:active { transform: scale(.96); }
/* Pendant l'envoi : le bouton ne se represse pas, et il le montre. */
.changer-fond[disabled] { opacity: .5; cursor: default; }

/* ── Revenir ──────────────────────────────────────────────────────────────
   UN BOUTON, PAS UN FIL D'ARIANE. Réduit à un mot, le fil n'était plus un
   chemin : juste un lien discret qu'il fallait viser. La flèche dit ce
   qu'elle fait et se clique sans réfléchir. */
.entete { display: flex; align-items: center; gap: 14px; }
.entete h1 { flex: 1; min-width: 0; }

.retour {
  display: flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; flex: none;
  border-radius: 50%; background: var(--aire); color: var(--doux);
  transition: background .15s, color .15s, transform .15s;
}
.retour:hover { background: var(--carte); color: var(--texte); transform: translateX(-2px); }
.retour svg {
  width: 17px; height: 17px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}

/* Le trait qui isole les écrans qu'on ne consulte pas chaque jour. Discret :
   il sépare, il ne découpe pas. */
.coupure {
  height: 1px; border: 0; margin: 10px 12px;
  background: var(--ligne);
}

/* ── LES DOSSIERS DU MENU ────────────────────────────────────────────────
 *
 * Une entrée qui porte des pages : elle garde son lien — cliquer « Arcades »
 * ouvre la page Arcades — et gagne un chevron qui plie ce qu'elle contient.
 *
 * LE BOUTON SE POSE PAR-DESSUS LE LIEN, il ne se range pas à côté. Un
 * <button> dans un <a> n'est pas du HTML valide, et les mettre côte à côte
 * dans une rangée flex couperait la zone cliquable du lien en deux : le
 * survol s'arrêterait avant la flèche. Le lien garde donc toute la largeur,
 * et le bouton flotte sur ses derniers pixels. */
.dossier-tete { position: relative; }
.dossier-tete .entree { padding-right: 32px; }

/* LE CHEVRON N'EST PLUS UN BOUTON, C'EST UN SIGNE. Il etait seul a ecouter
   le clic — on visait une cible de trente pixels pour ouvrir ce que le mot
   d'a cote nommait deja. Desormais toute la ligne bascule, et `pointer-events`
   le rend transparent : le clic le traverse et atteint le bouton qui le
   porte. Sans ca, la fleche aurait ete le seul endroit de la ligne a ne rien
   faire. Il garde la place et le dessin de l'ancien bouton. */
.chevron-place {
  position: absolute; right: 6px; top: 2px; bottom: 2px;
  display: grid; place-items: center;
  width: 30px;
  color: var(--faible);
  pointer-events: none;
}

/* ── UNE PORTE QUI N'EST PAS UNE PAGE ──────────────────────────────────────
   « Arcades » ne mene nulle part : ses ecrans sont ses rameaux, et son
   en-tete ne fait que les decouvrir. C'est donc un bouton, et un bouton
   n'herite ni de la police, ni de la largeur, ni de l'alignement d'un lien —
   sans ces quatre lignes il se serait affiche en petit, centre, et large de
   son seul texte, au milieu d'une colonne d'entrees qui font toute la barre. */
button.entree {
  width: 100%;
  font: inherit;
  text-align: left;
  background: none;
  border: 0;
  cursor: pointer;
}
button.entree:focus-visible { outline: 2px solid var(--bleu); outline-offset: -2px; }

/* `.dossier-bascule`, PAS `.bascule` : ce nom est deja celui de la pastille a
   interrupteur, en forme de gelule — rayon de 24 px et padding de 6. L'en-tete
   du dossier le prenait au passage et s'affichait tout rond, plus court que
   les entrees voisines, alors que rien dans son propre style ne le disait.
   La classe ne sert ici qu'a designer le bouton au script ; elle ne porte
   aucun style, et c'est `.entree` qui l'habille comme les autres lignes. */

.chevron {
  width: 12px; height: 12px;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
  transition: transform .16s;
}
.dossier.replie .chevron { transform: rotate(-90deg); }
.dossier.replie .rameaux { display: none; }

/* Une page-enfant porte une icône là où un topic porte son émoji : même
   gouttière, même alignement, pour que les deux dossiers se lisent pareil. */
.rameau-emoji svg {
  width: 14px; height: 14px; display: block; margin: 0 auto;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}

/* Écrire une question : une commande de la colonne, à côté du réglage. */
.plume {
  display: flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; flex: none;
  border: 0; border-radius: 6px; background: none; cursor: pointer;
  opacity: .6; transition: opacity .15s, background .15s;
}
.plume svg {
  width: 15px; height: 15px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.plume:hover { opacity: 1; background: rgba(255,255,255,.15); }
.plume:disabled { opacity: .3; cursor: default; }

/* La pile reprend sa marge du haut, le bouton n'y est plus. */
.colonne.rubrique .pile { min-height: 8px; }

/* ── L'aperçu d'un mini-jeu ───────────────────────────────────────────────
   ON MONTRE LES PALIERS, PAS UNE IMAGE. Ce qui se règle ici c'est la
   difficulté : voir le premier indice à côté du dernier est la seule façon de
   juger si le jeu est jouable. */
.apercu-jeu { margin-bottom: 12px; }
.apercu-jeu img {
  width: 100%; aspect-ratio: 16 / 9; object-fit: cover;
  border-radius: var(--rond); display: block; background: var(--fond);
}
.apercu-jeu.occupe { opacity: .5; }

.paliers { display: flex; gap: 4px; margin: 8px 0; }
.palier {
  flex: 1; padding: 5px 0; border: 0; border-radius: 5px;
  background: var(--aire); color: var(--faible);
  font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
  transition: background .13s, color .13s;
}
.palier:hover { background: var(--carte); color: var(--texte); }
.palier.choisi { background: var(--bleu); color: #fff; }

/* Ce que les tours passés ont appris — la seule chose qui dise si le jeu prend. */
.bilan-jeu {
  margin: 0 0 10px; font-size: 12.5px; color: var(--faible);
  padding: 8px 10px; background: var(--aire); border-radius: var(--rond);
}
.bilan-jeu b { color: var(--texte); }
.fiche.tour h3 { margin: 4px 0 0; font-size: 13.5px; font-weight: 500; white-space: normal; }


/* ── La recherche d'œuvre, dans la page ───────────────────────────────────
   ELLE NE SE POSE PLUS PAR-DESSUS. Un panneau flottant cache la soirée qu'on
   est en train de composer, et demande un geste de plus pour le refermer. Le
   champ se déplie sous la ligne des œuvres, là où l'on vient de cliquer. */
.cherche-oeuvre {
  margin-top: 10px;
  animation: deplie .16s ease-out;
}
@keyframes deplie { from { opacity: 0; transform: translateY(-4px); } }

.cherche-oeuvre .champ { max-width: 420px; }
.cherche-oeuvre .grille-oeuvres { margin-top: 10px; }

/* ── Les étapes du pilote, dépliables ─────────────────────────────────────
   CHAQUE ÉTAPE MONTRE CE QU'ELLE PUBLIERA. Une ligne de texte — « la séance
   est annoncée » — ne dit pas si l'affiche est réussie, alors que c'est une
   affiche qui part. */
.etape { margin-bottom: 2px; }
.etape .ligne {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 10px 12px; border: 0; border-radius: var(--rond);
  background: var(--aire); color: var(--texte);
  font: inherit; font-size: 14px; text-align: left; cursor: pointer;
  transition: background .13s;
}
.etape .ligne:hover:not(:disabled) { background: var(--carte); }
.etape .ligne:disabled { cursor: default; }
.etape .ligne b { flex: 1; min-width: 0; font-weight: 500; }
.etape.fait .ligne b { color: var(--faible); }

/* Le chevron ne tourne que sur les étapes qui ont quelque chose à montrer. */
.chevron-etape {
  width: 7px; height: 7px; flex: none;
  border-right: 2px solid var(--faible); border-bottom: 2px solid var(--faible);
  transform: rotate(45deg); transition: transform .18s;
}
.ligne.ouverte .chevron-etape { transform: rotate(225deg); }

.etape-apercu { padding: 10px 0 4px; animation: deplie .16s ease-out; }
.etape-apercu img {
  max-width: 420px; width: 100%; display: block;
  border-radius: var(--rond); background: var(--fond);
}

/* ── Étaler une série sur plusieurs soirs ─────────────────────────────────*/
.reglage-serie {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 14px;
}
.mini-champ { display: flex; flex-direction: column; gap: 4px; }
.mini-champ > span { font-size: 12px; color: var(--faible); }
.mini-champ .liste.nue .liste-tete {
  background: var(--aire); padding: 7px 11px;
}
.mini-champ .liste.nue .liste-tete:hover { background: var(--carte); }

/* CHAQUE DATE SE DÉPLACE SEULE. C'est tout l'intérêt d'avoir généré de vraies
   dates plutôt qu'une récurrence : un anniversaire tombe un vendredi, on
   décale ce vendredi-là et rien d'autre. */
.seances { list-style: none; margin: 16px 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 4px; }
.seance-ligne {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 12px; border-radius: var(--rond); background: var(--aire);
  transition: box-shadow .2s;
}
.seance-ligne.pris { box-shadow: inset 0 0 0 1px var(--vert); }
.seance-ligne.faite { opacity: .55; }

.rang-seance {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; flex: none; border-radius: 50%;
  background: var(--ligne); color: var(--doux);
  font-size: 11px; font-weight: 700;
}
.seance-ligne .episodes { flex: 1; min-width: 0; font-size: 13.5px; }
.bouton.petit { padding: 8px 14px; font-size: 13px; }

/* ── Ce que le bot enverra, en entier ─────────────────────────────────────
   UNE AFFICHE SEULE NE DIT PAS CE QUE LE SALON VERRA. Discord montre un texte
   au-dessus — le titre, les épisodes du soir, l'heure, le salon. Sans lui les
   trois étapes se ressemblaient toutes, alors que leurs messages diffèrent. */
/* PAS DE BARRE DE COULEUR À GAUCHE. C'est la marque d'un embed Discord ; nos
   annonces partent en cadre Components V2, qui n'en a pas. L'aperçu doit
   ressembler à ce qui part, pas à ce que Discord ferait d'autre chose. */
.faux-discord {
  max-width: 460px; padding: 12px 14px;
  background: var(--fond); border-radius: var(--rond);
}
.entete-msg { display: flex; align-items: center; gap: 7px; margin-bottom: 8px; }
.pastille-bot {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--vert); color: #fff; font-size: 12px; font-weight: 700;
}
.entete-msg b { font-size: 13.5px; }
.tag-app {
  padding: 1px 5px; border-radius: 4px; background: var(--bleu);
  color: #fff; font-size: 10px; font-weight: 600; letter-spacing: .02em;
}
.entete-msg .ou { font-size: 12px; color: var(--faible); }

.corps-msg h4 { margin: 0 0 2px; font-size: 17px; font-weight: 700; }
.corps-msg p { margin: 0 0 2px; font-size: 14px; }
.corps-msg .petit { font-size: 12.5px; color: var(--faible); }
/* Le cadre : image en haut, texte dessous, dans un seul bloc — la forme des
   annonces de partie, qu'on reprend ici. */
.cadre-msg {
  border-radius: 8px; overflow: hidden;
  background: var(--aire);
}
.cadre-msg img { width: 100%; display: block; }
.cadre-msg .corps-msg { padding: 10px 12px 12px; }

/* Les boutons du message. Ils sont DANS le cadre parce qu'ils y sont sur
   Discord : une rangée posée dessous se lirait comme une barre d'outils de la
   page, pas comme une partie de l'annonce.
   Ils ne sont pas cliquables ici — c'est un aperçu, pas le message. */
.boutons-msg {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 0 12px 12px;
}
.faux-bouton {
  padding: 6px 12px; border-radius: 8px;
  background: var(--carte); border: 1px solid var(--ligne);
  color: var(--texte); font-size: 13px; font-weight: 500;
  white-space: nowrap;
}
/* Le premier est le geste principal — c'est celui que Discord met en vert. */
.faux-bouton:first-child { background: var(--vert); border-color: transparent; color: #fff; }

/* ── LE DÉCOR DES AFFICHES ────────────────────────────────────────────────
   On choisit un CADRAGE, pas un nom de fichier : les vignettes sont les vrais
   fonds, en petit. Elles défilent horizontalement plutôt que de s'empiler —
   huit décors sur trois rangées repousseraient tout le reste de la page. */
.rangee-fonds {
  display: flex; gap: 8px;
  overflow-x: auto; padding-bottom: 6px;
  scrollbar-width: thin;
}
.vignette-fond {
  position: relative; flex: none;
  width: 132px; height: 74px;                 /* le 16/9 des affiches */
  padding: 0; border-radius: 6px; overflow: hidden;
  border: 2px solid transparent; background: var(--carte);
  cursor: pointer;
}
.vignette-fond img { width: 100%; height: 100%; object-fit: cover; display: block; }
.vignette-fond:hover { border-color: var(--ligne); }
.vignette-fond.choisi { border-color: var(--bleu); }

/* « Celui d'origine » n'a pas d'image : c'est un retour en arrière, pas un
   décor de plus. Il se distingue donc au lieu de se déguiser en vignette. */
.vignette-fond.origine {
  display: flex; align-items: center; justify-content: center;
  padding: 0 10px; color: var(--doux); font-size: 12px; line-height: 1.2;
  border-style: dashed; border-color: var(--ligne);
}
.vignette-fond.origine.choisi { border-style: solid; border-color: var(--bleu); color: var(--texte); }

/* DU TEXTE INCRUSTÉ SE VOIT MAL EN VIGNETTE, et se voit très bien en grand —
   sous notre propre titre. On le signale plutôt que de le laisser découvrir. */
.marque-texte {
  position: absolute; right: 4px; bottom: 4px;
  padding: 1px 5px; border-radius: 4px;
  background: rgba(0, 0, 0, .72); color: var(--doux);
  font-size: 10px; letter-spacing: .02em;
}

/* ── Tout aligné ──────────────────────────────────────────────────────────
   Les dates se dimensionnaient sur leur texte : « Vendredi 4 septembre » est
   plus long que « Vendredi 21 août », donc le bord droit partait en escalier.
   Une largeur commune les remet en colonne. */
.seance-ligne .datier { width: 230px; flex: none; }
.seance-ligne .date-tete { width: 100%; text-align: left; }


/* ── CE QUI EXISTE LÀ-BAS ET PAS ICI ──────────────────────────────────────
   Un forum se remplit de tout : des sections durables, et des questions de
   passage. On montre ce qui traîne, on ne décide pas à sa place. */
.fils-libres { display: flex; flex-wrap: wrap; gap: 9px; }
.fil-libre {
  display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
  padding: 10px 14px; border-radius: 10px; cursor: pointer;
  background: none; border: 1px dashed var(--ligne);
  color: inherit; font-family: inherit; text-align: left;
}
.fil-libre:hover { background: rgba(255,255,255,.04); border-color: var(--faible); }
.fil-libre b { font-size: 13.5px; font-weight: 500; }
.fil-libre span { font-size: 11.5px; color: var(--faible); }

/* Un constat qui appelle une correction, pas une alarme : il se lit en passant
   et n'empêche rien. */
.avertissement {
  padding: 12px 16px; margin-bottom: 22px; border-radius: 10px;
  background: rgba(240,178,50,.12); border: 1px solid rgba(240,178,50,.30);
  font-size: 13.5px; color: #f8d68a;
}
.avertissement b { color: #f6c860; }

.lien-nu {
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--bleu-clair); font: inherit; text-decoration: underline;
}


/* ══ LA PAGE D'UN TOPIC ════════════════════════════════════════════════════
   C'était un formulaire : des `<label>` empilés dans de grandes aires grises,
   avec trois paragraphes d'explication autour. À côté de Cinéma et de Débats —
   colonnes à en-tête coloré, cartes, presque pas de texte — ça n'avait pas
   l'air du même site.

   On reprend donc leurs classes telles quelles : `.tableau`, `.colonne`,
   `.chapeau`, `.pile`, `.fiche`. Ce qui se ressemble doit se dessiner pareil,
   sinon chaque écran devient un dialecte. */

/* ── LA FILE ─────────────────────────────────────────────────────────────
   Numérotée : « la 3ᵉ » se désigne, « celle du milieu » non. */
/* ── UNE LIGNE DE FILE EST UNE VALEUR, PAS UNE CARTE ────────────────────
   Elle portait `.fiche` : coin large, bordure au survol, l'objet posé sur la
   page qu'on trouve dans Cinéma et Débats. Dans le panneau d'un module, la
   colonne de droite contient déjà des champs — même fond, coin de 8, pas de
   bordure. Une carte au milieu d'eux se lisait comme un morceau d'un autre
   écran collé là.
   Elle prend donc exactement la surface d'un champ. Ce qui la distingue est
   ce qu'elle contient : un rang, un texte, trois gestes. */
.file-ligne {
  display: flex; align-items: center; gap: 13px;
  padding: 12px 14px; border-radius: 8px;
  background: var(--carte);
}
.file-ligne:hover { background: var(--carte-survol); }
/* Ce qui est parti ne se reprend pas : on le montre en retrait. */
.file-ligne.fanee { background: none; padding: 7px 14px; }
.file-ligne.fanee:hover { background: var(--carte); }

/* LA COLONNE DE DROITE S'EMPILE. `.valeur` range en ligne, ce qui va pour des
   boutons et des listes ; une file y aurait mis ses entrées côte à côte. */
.valeur.en-pile { flex-direction: column; align-items: stretch; gap: 8px; }
.relance-rang {
  flex: none; min-width: 22px; text-align: center;
  font-size: 12px; font-weight: 700; color: var(--faible);
  font-variant-numeric: tabular-nums;
}
.relance-affiche {
  width: 34px; height: 51px; object-fit: cover; flex: none;
  border-radius: 6px; background: var(--aire);
}
.relance-corps { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
.relance-haut { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.relance-haut b {
  font-size: 12.5px; font-weight: 600; color: var(--doux);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.relance-texte {
  font-size: 13.5px; line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* Le compte d'images de l'article. Il dit ce que le texte ne dit plus depuis
   qu'on a retiré les adresses de la fiche : qu'il y en a, et combien. */
.relance-medias { font-size: 11.5px; color: var(--faible); }

/* L'étiquette de genre porte sa couleur : on distingue un film d'un défi avant
   d'avoir lu le mot. */
.etiquette {
  /* `nowrap` : sans lui, « Œuvre de la semaine » se cassait en trois lignes
     dans la rangée et recouvrait l'affiche. */
  flex: none; white-space: nowrap;
  padding: 2px 9px; border-radius: 999px;
  font-size: 11px; font-weight: 600;
  background: rgba(255,255,255,.09); color: var(--doux);
}
.etiquette.oeuvre { background: rgba(35,165,90,.26); color: #7ee2a8; }
.etiquette.defi { background: rgba(240,178,50,.24); color: #f8d68a; }
.etiquette.question { background: rgba(121,131,245,.26); color: #bcc2fa; }

.file-gestes { display: flex; gap: 2px; flex: none; }
.file-gestes button {
  width: 27px; height: 27px; padding: 0; border-radius: 6px;
  border: 0; background: none; color: var(--faible);
  cursor: pointer; font-size: 13px; line-height: 1;
}
.file-gestes button:hover { background: rgba(255,255,255,.10); color: var(--texte); }
.file-gestes [data-maintenant]:hover { color: #45d17f; }
.file-gestes [data-oter]:hover { color: var(--rouge); }

.pile-vide {
  margin: 0; padding: 26px 0; text-align: center;
  color: var(--faible); font-size: 13.5px;
}

.fiche-passee { display: flex; gap: 10px; padding: 10px 12px; opacity: .55; }
.passee-date { flex: none; font-size: 11.5px; color: var(--faible); }
.passee-texte {
  font-size: 12.5px; min-width: 0;
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden;
}

/* ── LE COMPOSITEUR, EN BOUT DE FILE ─────────────────────────────────────
   À sa place : on ajoute au bout de ce qu'on vient de lire. */
/* ── LE COMPOSITEUR N'EST PLUS UN CADRE POINTILLÉ ───────────────────────
   Le pointillé disait « ici, on ajoute » quand la file était une colonne de
   cartes : il fallait distinguer le vide à remplir des entrées déjà posées.
   Dans le panneau, le champ de texte le dit tout seul — il est vide et il
   attend. Un cadre autour aurait ajouté une troisième boîte à une rangée qui
   en compte déjà deux. */
.composer {
  display: flex; flex-direction: column; gap: 10px;
  padding: 0; border: 0; background: none;
}
.composer-haut { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.composer-haut .champ { flex: 0 0 180px; }
.composer-aide { font-size: 12.5px; color: var(--faible); }
.composer-extra { display: flex; flex-direction: column; gap: 9px; }
/* LES CHAMPS PRENNENT LA COLONNE. `.mince` les dimensionne sur leur contenu,
   ce qui allait tant qu'ils étaient côte à côte ; seuls dans le compositeur,
   ils s'arrêtaient au milieu et le texte de l'emplacement se coupait. */
.composer .champ.mince, .composer-extra .champ {
  /* C'EST `max-width` QUI SERRAIT, PAS `width`. Poser une largeur de 100 %
     laissait le champ à 150 px sans rien changer à l'écran — on croit la règle
     fausse alors qu'elle est simplement plafonnée dix lignes plus haut. */
  width: 100%; max-width: none; box-sizing: border-box;
}
.composer-pied { display: flex; align-items: center; gap: 12px; }
/* C'EST « AJOUTER » QUI VA À DROITE, PAS TOUT BOUTON. La règle visait `.bouton`
   tant qu'il n'y en avait qu'un ; « Déposer une image » l'a rejoint dans le
   pied, et deux marges automatiques se partageaient l'espace — les deux boutons
   flottaient au milieu, à distance égale, sans que rien ne dise lequel conclut.
   L'action qui valide reste collée au bord ; le dépôt reste près du compteur,
   du côté de ce qu'on écrit. */
/* Le compteur reste à gauche ; la bascule pousse le reste à droite, et
   « Mettre en file » la suit. C'est `.outils-bascule` qui porte la marge
   maintenant — deux marges automatiques se seraient partagé l'espace. */
.composer-pied .outils-bascule { margin-left: auto; }
.composer-pied .bouton.primaire:first-of-type { margin-left: auto; }
.composer-pied .outils-bascule ~ .bouton.primaire { margin-left: 0; }
.composer textarea.champ { resize: vertical; font-family: inherit; line-height: 1.45; }

/* ══ LE MIROIR ════════════════════════════════════════════════════════════
   Le champ garde tout ce qu'un champ sait faire — curseur, sélection, Ctrl+Z,
   clavier du téléphone — et perd seulement sa couleur. Dessous, à la même
   place, un calque porte le même texte avec les couleurs du markdown.

   TOUT SE JOUE SUR L'ALIGNEMENT. Les deux doivent casser leurs lignes au même
   endroit, au pixel : mêmes police, taille, interligne, rembourrage, bordure
   et règle de césure. Une seule de ces valeurs qui diffère, et le curseur se
   décale un peu plus à chaque ligne.

   D'où l'interdit qui suit : le miroir ne change JAMAIS une largeur. Pas de
   graisse — un `bold` élargit les lettres — pas de taille, pas d'espacement.
   Il ne joue que sur la couleur, le fond, le soulignement et l'épaisseur du
   trait, qui épaissit la lettre sans la pousser. */
.composer-champ { position: relative; }

.composer-champ.peint textarea.champ,
.composer-miroir {
  /* Les mesures partagées. Elles sont ici pour être écrites UNE fois : deux
     listes à tenir d'accord auraient fini par diverger sur une valeur. */
  padding: 13px 16px;
  border: 1px solid transparent;
  border-radius: 8px;
  font: inherit;
  font-size: 15px;
  line-height: 1.45;
  letter-spacing: normal;
  box-sizing: border-box;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  word-break: normal;
  tab-size: 4;
}

.composer-champ.peint textarea.champ {
  position: relative; z-index: 1;
  width: 100%;
  background: transparent;
  /* Le texte devient invisible, mais PAS le curseur : sans cette ligne il
     hériterait de la transparence et l'on écrirait à l'aveugle. */
  color: transparent;
  caret-color: var(--texte);
  resize: vertical;
}
/* Le fond du champ vit sur le miroir maintenant. Le survol le suit, sinon la
   case cesserait de réagir sous la souris. */
.composer-champ.peint:hover .composer-miroir { background: var(--carte-survol); }

/* LA SÉLECTION LAISSE VOIR À TRAVERS. Le champ est au-dessus : une sélection
   opaque recouvrirait le miroir, et l'on sélectionnerait un bloc vide. */
.composer-champ.peint textarea.champ::selection { background: rgba(88, 101, 242, .35); }

.composer-miroir {
  position: absolute; inset: 0; z-index: 0;
  overflow: hidden;
  pointer-events: none;
  background: var(--carte);
  color: var(--texte);
  /* ── DU MOU SOUS LA DERNIÈRE LIGNE ──────────────────────────────────────
     Le champ se laisse défiler quelques pixels de plus que le calque : arrivé
     tout en bas, le calque butait sur sa fin et le texte peint remontait de
     cinq pixels au-dessus du texte réel. Une ligne de rembourrage en plus lui
     donne toujours de quoi suivre. Elle est SOUS le texte : le haut ne bouge
     pas, donc l'alignement non plus. */
  padding-bottom: calc(13px + 1.6em);
}

/* ── LES COULEURS DU MARKDOWN ────────────────────────────────────────────
   LES MARQUES RESTENT VISIBLES, en retrait. C'est le parti de Discord, et il
   est juste : les cacher ferait un éditeur où l'on ne sait plus quoi effacer
   pour retirer un gras, et où le texte à l'écran ne serait plus celui qui
   part. */
.p-marque { color: var(--faible); opacity: .75; }
/* Le gras à l'épaisseur du trait : la lettre grossit, son avance ne bouge pas.
   `font-weight` l'aurait élargie et décalé toute la fin de la ligne. */
.p-gras { -webkit-text-stroke: .32px currentColor; color: var(--texte); }
.p-italique { font-style: italic; }
.p-souligne { text-decoration: underline; }
.p-barre { text-decoration: line-through; color: var(--faible); }
.p-spoiler { background: var(--ligne); border-radius: 3px; }
.p-code { background: var(--fond); border-radius: 3px; }
.p-lien { color: var(--bleu-clair); }
/* Un titre ne peut pas grandir sans tout décaler : il s'épaissit et s'éclaircit.
   C'est la seule concession du miroir, et elle se voit assez. */
.p-titre { -webkit-text-stroke: .42px currentColor; color: #fff; }
.p-petit { color: var(--faible); }
.p-citation { color: var(--doux); }
.p-liste { color: var(--texte); }
/* UNE LIGNE D'ADRESSE SEULE N'EST PAS DU TEXTE : c'est une image, et elle se
   voit comme un objet posé dans l'article plutôt que comme une phrase. */
.p-media {
  color: var(--bleu-clair);
  background: rgba(88, 101, 242, .13);
  border-radius: 4px;
}

/* ── LA BARRE D'ÉCRITURE ─────────────────────────────────────────────────
   DES MOTS, PAS DES ICÔNES. « Citation », « Petit », « Spoiler » n'ont pas de
   dessin que tout le monde reconnaisse, et un jeu de pictogrammes maison se
   devine au survol, un par un. Seules B, I et S gardent leur lettre : celles-là
   se lisent sans légende, et elles portent leur propre style — un B gras, un I
   penché, un S barré disent ce qu'ils font en le faisant.

   ELLE NE S'ENCADRE PAS. Elle borde le champ, et une boîte autour aurait ajouté
   un troisième rectangle à une rangée qui en compte déjà deux. */
.composer-outils { display: flex; align-items: center; flex-wrap: wrap; gap: 2px; }
.composer-outils button {
  background: none; border: 0; cursor: pointer;
  padding: 5px 9px; border-radius: 6px;
  color: var(--faible); font: inherit; font-size: 12.5px; line-height: 1;
}
/* LE SURVOL SE VOIT. Il posait `--carte` sur le fond de la page : quatre
   points de luminosité d'écart, invisibles en passant la main — on ne savait
   pas quel bouton on allait cliquer. */
.composer-outils button:hover { background: var(--carte-survol); color: var(--texte); }
.composer-outils button:disabled { opacity: .55; cursor: default; }
.composer-outils b, .composer-outils i, .composer-outils s { font-size: 13.5px; }
/* Le même filet que dans la barre du haut, et pour la même raison : il sépare
   ce qui met en forme un MOT de ce qui met en forme une LIGNE, et le média des
   deux. Trois familles de gestes, deux traits. */
.outils-filet { width: 1px; height: 15px; background: var(--ligne); margin: 0 7px; flex: none; }

/* ── ÉCRIRE / APERÇU ─────────────────────────────────────────────────────
   À droite, loin des outils d'écriture : ce n'est pas un geste d'écriture,
   c'est un changement de vue. La vue courante s'allume ; deux boutons éteints
   ne diraient pas laquelle on regarde. */
/* ── ÉCRIRE / APERÇU, DANS LE PIED ───────────────────────────────────────
   Contre « Mettre en file » : on relit, puis on range. La vue courante
   s'allume — deux boutons éteints ne diraient pas laquelle on regarde. */
.outils-bascule { display: flex; gap: 2px; margin-left: auto; flex: none; }
.outils-bascule button {
  background: none; border: 0; cursor: pointer;
  padding: 5px 9px; border-radius: 6px;
  color: var(--faible); font: inherit; font-size: 12.5px; line-height: 1;
}
.outils-bascule button:hover { background: var(--carte-survol); color: var(--texte); }
.outils-bascule button.on { background: var(--carte); color: var(--texte); }

/* En aperçu, la barre d'écriture s'efface en entier : chacun de ses boutons
   agirait sur un champ qu'on ne voit plus. */
.composer-outils.lecture { display: none; }

/* Le champ et son calque s'effacent ENSEMBLE, et l'aperçu prend leur place
   dans le même cadre : la rangée ne saute pas d'une vue à l'autre. */
.composer-champ.en-apercu > textarea.champ,
.composer-champ.en-apercu > .composer-miroir { display: none; }

/* ── L'APERÇU ────────────────────────────────────────────────────────────
   La boîte de Discord : un conteneur sans couleur, qui dit « ceci est une
   publication et non un message de la conversation ». Pas d'`accent_color` —
   son liseré aurait donné une barre par section. C'est le choix retenu pour
   la publication ; l'aperçu ne peut pas en faire un autre, sinon il montrerait
   autre chose que ce qui part. */
.composer-apercu {
  border: 1px solid var(--ligne);
  border-radius: 8px;
  padding: 14px 16px;
  background: var(--aire);
  display: flex; flex-direction: column; gap: 9px;
  min-height: 120px;
}
.ap-texte { line-height: 1.45; white-space: pre-wrap; overflow-wrap: break-word; }
/* ICI LES TAILLES SONT LIBRES : on n'écrit pas dans l'aperçu, donc aucun
   caractère n'a besoin de tomber sur un autre. C'est tout l'intérêt d'une
   deuxième vue plutôt que d'un miroir plus ambitieux. */
.ap-h1 { font-size: 21px; font-weight: 700; }
.ap-h2 { font-size: 18px; font-weight: 700; }
.ap-h3 { font-size: 16px; font-weight: 700; }
.ap-petit { font-size: 12.5px; color: var(--faible); }
.ap-citation { border-left: 4px solid var(--ligne); padding-left: 10px; }
.ap-liste { padding-left: 4px; }
.ap-texte a { color: var(--bleu-clair); text-decoration: none; }
.ap-texte a:hover { text-decoration: underline; }
.ap-texte code {
  background: var(--fond); border-radius: 4px; padding: 1px 4px;
  font-family: Consolas, Menlo, monospace; font-size: 13px;
}
/* Un spoiler se cache, et s'ouvre au clic — comme sur Discord, sinon l'aperçu
   montrerait ce que le lecteur ne verra pas tout de suite. */
.ap-spoiler {
  background: var(--fond); border-radius: 4px; color: transparent;
  cursor: pointer;
}
.ap-spoiler.vu { color: inherit; background: var(--ligne); }
/* PLAFONNÉE EN HAUTEUR. Une photo de 4000 pixels remplissait l'aperçu à elle
   seule : on voyait l'image et plus l'article, alors que ce qu'on vient
   vérifier est justement l'enchaînement des deux. */
.ap-media {
  max-width: 100%; max-height: 320px; width: auto;
  border-radius: 8px; display: block;
}
/* L'image n'est pas encore en ligne quand on écrit vite : on le dit, au lieu
   de laisser un cadre cassé. */
.ap-manque {
  color: var(--faible); font-size: 12.5px;
  border: 1px dashed var(--ligne); border-radius: 8px; padding: 10px 12px;
}
.ap-vide { color: var(--faible); }

/* Un fichier tenu au-dessus du champ : il dit qu'il le prendra. Sans ce
   signal, on lâche au jugé et l'on ne sait qu'après si c'était la bonne zone. */
.proprietes .composer textarea.champ.recoit { border-color: var(--bleu); }
.composer-reste { font-size: 11.5px; color: var(--faible); font-variant-numeric: tabular-nums; }
.composer-reste.court { color: var(--jaune); }

/* ══ L'AFFRONTEMENT ════════════════════════════════════════════════════════
   LES DEUX CAMPS SONT L'UN EN FACE DE L'AUTRE, comme ils le seront sur la
   carte. Empilés en deux rangées « Camp A » / « Camp B », il aurait fallu lire
   deux étiquettes pour comprendre ce que la disposition dit toute seule. */
.duel {
  --duel-gouttiere: 14px;
  --duel-vs: 30px;
  display: flex; align-items: flex-start; gap: var(--duel-gouttiere);
  width: 100%; max-width: 520px;
}
.camp { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; position: relative; }

/* ── TROIS PROPOSITIONS, À ÉGALITÉ ────────────────────────────────────────
   La même rangée que le duel, sans le « VS » et un cran plus large : trois
   colonnes dans les 520 pixels du duel auraient donné des jaquettes de la
   taille d'un timbre. */
.trio-rangee {
  display: flex; align-items: flex-start; gap: 14px;
  width: 100%; max-width: 700px;
}
/* LE NUMÉRO EST SUR L'AFFICHE, comme sur la carte qui partira : c'est le seul
   lien entre la case d'ici, le panneau de l'image et le bouton du salon. Sur
   une pastille sombre, parce qu'une affiche sur trois est claire. */
.camp-rang {
  position: absolute; top: 8px; left: 8px;
  width: 24px; height: 24px; border-radius: 50%;
  background: rgba(0, 0, 0, .72); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 12.5px; font-weight: 700;
  pointer-events: none;
}

/* Le VS est aligné sur les affiches, pas sur le bloc entier : sous elles vit le
   champ de saisie, et se centrer dessus le ferait flotter trop bas. */
.duel-vs {
  /* ── CENTRÉ, ET NON CALÉ À 62 PIXELS ──────────────────────────────────
   * Il portait `margin-top: 62px`, une valeur juste pour une largeur et une
   * seule. L'affiche a un `aspect-ratio: 2/3` : sa hauteur suit la largeur de
   * la colonne, donc le décalage fixe se décrochait dès que la fenêtre
   * changeait de taille.
   *
   * `align-self: center` le centre sur la hauteur réelle du camp. Il vise le
   * milieu de l'ensemble affiche + nom plutôt que celui de la seule affiche,
   * soit une quinzaine de pixels plus bas — invisible, et surtout ça tient à
   * toutes les largeurs. */
  flex: none; align-self: flex-start;
  width: var(--duel-vs); text-align: center;
  /* LE MILIEU DE L'AFFICHE, PAS CELUI DE LA COLONNE. Centré sur le camp
   * entier, il tombait 29 px trop bas : la colonne contient aussi le champ du
   * nom. On vise donc la moitié de la hauteur de l'affiche.
   *
   * Cette hauteur vaut 1,5 fois la largeur du camp (`aspect-ratio: 2/3`), et
   * cette largeur est ce qui reste une fois le VS et les deux gouttières
   * retirés, divisé par deux. D'où le facteur 0,375.
   *
   * L'expression tient parce qu'un pourcentage en `margin-top` se calcule sur
   * la LARGEUR du parent, jamais sur sa hauteur. C'est ce qui permet de suivre
   * une hauteur qu'aucune règle ne connaît. */
  margin-top: calc(
    0.375 * (100% - var(--duel-vs) - 2 * var(--duel-gouttiere)) - 0.6em);
  font-family: "Lilita One", var(--police-titre, inherit), sans-serif;
  font-size: 20px; letter-spacing: .04em; color: var(--faible);
}

.camp-affiche {
  position: relative;
  aspect-ratio: 2 / 3;
  border-radius: var(--rond);
  background: var(--fond);
  /* LE TIRET DIT « IL MANQUE QUELQUE CHOSE ». Un aplat plein se lirait comme
     une affiche noire qu'on aurait choisie, et l'on chercherait pourquoi elle
     est vide. Il devient plein dès qu'une image arrive. */
  border: 1px dashed var(--ligne);
  overflow: hidden;
}
.camp.pris .camp-affiche { border-style: solid; border-color: transparent; }
.camp-affiche img { width: 100%; height: 100%; object-fit: cover; display: block; }
.camp-affiche img:not([src]) { display: none; }

/* Le bouton d'image vit sur l'affiche, comme celui d'un fond de débat. */
.camp-image { position: absolute; top: 8px; right: 8px; width: 30px; height: 30px; }
.camp-image svg { width: 14px; height: 14px; }
.camp-image:hover svg { transform: translateY(-2px); }

/* ── LES IMAGES AU CHOIX ──────────────────────────────────────────────────
 * Une bande qui defile sous l'affiche, et non une grille : le nombre varie de
 * trois a douze selon le catalogue, et une grille sauterait d'une ligne a deux
 * pendant qu'on regarde. La bande garde la meme hauteur quoi qu'il arrive. */
.camp-fonds {
  display: flex; gap: 6px;
  overflow-x: auto; overscroll-behavior-x: contain;
  padding-bottom: 2px;
  scrollbar-width: thin;
}
.camp-fonds button {
  flex: none; width: 56px; height: 32px; padding: 0;
  border: 2px solid transparent; border-radius: 5px;
  background: var(--fond) center/cover no-repeat;
  cursor: pointer;
  transition: border-color .12s, opacity .12s;
  opacity: .7;
}
.camp-fonds button:hover { opacity: 1; }
/* Le contour dit laquelle part, et il doit se voir sur une vignette sombre
   comme sur une claire : d'ou la couleur d'accent plutot qu'un blanc. */
.camp-fonds button.choisi { border-color: var(--bleu); opacity: 1; }

.camp-nom { text-align: center; }
.camp-nom-fige { text-align: center; color: var(--doux); font-size: 13px; }

/* La liste des résultats FLOTTE au lieu de pousser : elle recouvre le camp
   d'en face le temps qu'on choisisse, et la page ne saute pas sous le curseur
   à chaque frappe. */
.camp-choix {
  position: absolute; top: 100%; left: 0; z-index: 30;
  display: flex; gap: 8px; flex-wrap: wrap;
  width: max(100%, 240px);
  margin-top: 6px; padding: 10px;
  border-radius: var(--rond);
  background: var(--carte); border: 1px solid var(--ligne);
  box-shadow: 0 12px 28px rgba(0, 0, 0, .38);
  max-height: 300px; overflow-y: auto;
}

/* ── LA SÉRIE D'UN TOURNOI ─────────────────────────────────────────────────
   Une ligne par duel, dans l'ordre où ils partiront. Le rang à gauche, les deux
   noms au milieu, la date à droite : on lit la série de haut en bas comme un
   programme, et le duel qu'on est en train d'écrire se repère sans le chercher. */
.serie { display: flex; flex-direction: column; gap: 4px; width: 100%; max-width: 560px; }

.duel-ligne {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 12px;
  border-radius: var(--rond);
  border: 1px solid transparent;
  background: var(--carte);
  color: var(--doux); text-decoration: none;
  font-size: 13px;
  transition: background .12s, border-color .12s;
}
.duel-ligne:hover { background: var(--carte-survol); }
/* Celui qu'on édite. Un liseré, pas un aplat : il est déjà tout entier au-dessus
   de la liste, la ligne n'a qu'à dire « c'est celui-là ». */
.duel-ligne.sien { border-color: var(--bleu); color: var(--texte); }
/* Un duel joué reste, mais il ne s'offre plus : il raconte, il n'appelle pas. */
.duel-ligne.parti { opacity: .55; }

.duel-rang {
  flex: none; width: 20px; height: 20px;
  display: grid; place-items: center;
  border-radius: 50%; background: var(--fond);
  font-size: 11px; font-variant-numeric: tabular-nums; color: var(--faible);
}
.duel-ligne.sien .duel-rang { background: var(--bleu); color: #fff; }

.duel-noms {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.duel-noms i { font-style: normal; color: var(--faible); margin: 0 4px; font-size: 11px; }

.duel-quand { flex: none; font-size: 12px; font-variant-numeric: tabular-nums; }
.duel-quand.sans { color: var(--faible); }

/* La croix est là en permanence : elle avait été mise au survol ailleurs dans
   ce tableau de bord, et on la cherchait en croyant qu'elle n'existait pas. */
.duel-oter {
  flex: none; width: 24px; height: 24px; padding: 0;
  display: grid; place-items: center;
  border: 0; border-radius: 6px; cursor: pointer;
  background: none; color: var(--faible);
}
.duel-oter:hover { background: var(--fond); color: var(--rouge, #e05561); }
.duel-oter svg {
  width: 13px; height: 13px;
  fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round;
}

/* La carte d'un clash est large, pas verticale : elle mérite plus que les 460
   pixels d'une affiche de débat. */
.cadre-apercu.large, .apercu-vif .cadre-apercu.large .planche-apercu { max-width: 620px; }

.oeuvre-choix { display: flex; gap: 9px; flex-wrap: wrap; }
.oeuvre {
  display: flex; flex-direction: column; gap: 5px; width: 84px;
  padding: 6px; border-radius: 8px; cursor: pointer;
  background: none; border: 1px solid var(--ligne); color: inherit;
  font: inherit; text-align: left;
}
.oeuvre:hover { border-color: var(--faible); }
.oeuvre.on { border-color: var(--bleu); background: rgba(88,101,242,.14); }
.oeuvre img { width: 100%; aspect-ratio: 2/3; object-fit: cover; border-radius: 4px; }
.oeuvre span {
  font-size: 10.5px; line-height: 1.3; color: var(--doux);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}


/* ══ LA BARRE DU HAUT PORTE LES ACTIONS ════════════════════════════════════
   Elles vivaient dans un bandeau propre à chaque page, sous le titre. Deux
   barres empilées pour deux boutons : la seconde ne servait qu'à les tenir. */
.haut-actions {
  display: flex; align-items: center; gap: 12px;
  flex-wrap: wrap;
  /* À GAUCHE, PAS AU MILIEU. `margin-left: auto` poussait les boutons contre
     l'avatar : selon la page ils flottaient au centre ou à droite, jamais au
     même endroit. L'œil doit les trouver sans les chercher — c'est l'avatar
     qui se pousse à droite, pas eux. */
}
/* `.gestes` déménage ici : il ne doit plus pousser vers la droite, la case le
   fait déjà. */
.haut-actions .gestes { margin-left: 0; }

/* ── OÙ L'ON EST SE VOIT ─────────────────────────────────────────────────
   L'entrée active se distinguait par un fond à peine plus clair que le
   survol : à côté d'une page dont on a retiré le titre, ce n'était plus
   assez. Un fond franc et un trait vertical — le repère est le même que
   celui de Discord, et il se lit du coin de l'œil. */
.entree.actif {
  background: rgba(88,101,242,.20);
  color: #fff;
}
.entree.actif svg { color: var(--bleu-clair); }

/* ── LES TOPICS, SOUS « FORUM » ──────────────────────────────────────────
   DU TEXTE, PAS DES CARTES. La première version encadrait chaque ligne, la
   doublait d'un trait vertical et lui collait une pastille rouge : cinq
   entrées de navigation avaient l'air de cinq alertes.

   Ici l'émoji porte l'identité et la COULEUR dit où l'on est. Pas de fond
   plein sur l'entrée active — un menu de navigation se parcourt du regard, et
   trois rectangles empilés arrêtent l'œil à chaque ligne. */
.rameaux { display: flex; flex-direction: column; gap: 1px; margin: 4px 0 8px; }

/* Elle hérite de `.entree` : même taille, même icône, même surbrillance que
   les autres destinations. Il ne reste ici que ce qui la distingue — elle se
   clique pour se replier, pas pour aller ailleurs. */
.rameaux-tete { cursor: pointer; }
/* Sur la page des réglages du forum, aucun topic n'est actif : c'est l'en-tête
   qui porte alors la surbrillance, sinon la colonne n'indique plus rien. */

.rameau-reglages { color: var(--faible); font-size: 13px; }
/* UN TRACÉ, PAS DEUX BORDURES PIVOTÉES. La version d'avant fabriquait la
   flèche avec `border-right` + `border-bottom` et un `translate` de rattrapage :
   elle se décalait d'un pixel selon la taille du texte et ne pointait pas
   droit. Un chemin tourne autour de son centre, sans rattrapage. */
.rameaux-tete .chevron {
  margin-left: auto; flex: none; width: 12px; height: 12px;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
  transition: transform .16s;
}
.rameaux.replie .chevron { transform: rotate(-90deg); }
.rameaux.replie .rameau { display: none; }

.rameau {
  display: flex; align-items: center; gap: 9px;
  padding: 6px 12px 6px 24px; border-radius: 6px;
  color: var(--doux); text-decoration: none; font-size: 13.5px;
}
/* Le survol éclaircit le texte ; il ne pose pas de boîte. */
.rameau:hover { color: var(--texte); }
/* ET L'ACTIF EST UNE COULEUR, pas un rectangle. C'est le repère le plus léger
   qui se lise du coin de l'œil, et le seul qui n'alourdisse pas la colonne. */
.rameau.actif { color: var(--bleu-clair); font-weight: 600; }
/* Une section en sommeil : rien n'en partira, et l'oublier ferait chercher
   pourquoi le topic est silencieux. */
.rameau.dormant { opacity: .4; }

.rameau-emoji { flex: none; width: 17px; text-align: center; font-size: 13.5px; }
.rameau-nom {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* UN POINT, PAS UNE PASTILLE CHIFFRÉE. Il ne dit qu'une chose — « celui-ci se
   taira » — et une chose se dit avec un point. */
.rameau-alerte {
  flex: none; width: 6px; height: 6px; border-radius: 50%;
  background: var(--jaune);
}


/* ── LES VRAIES IMAGES, AU FORMAT DES PASTILLES ───────────────────────────
   `.sceau` et `.pastille-avatar` dessinaient un carré coloré avec une lettre.
   Devenues des images, elles gardent exactement la même place — sans quoi la
   barre du haut et la marque sauteraient de quelques pixels. */
img.sceau, img.pastille-avatar { object-fit: cover; padding: 0; }

/* ── RÉCURRENT OU UNE SEULE FOIS ────────────────────────────────────────────
   Deux boutons plutôt qu'une liste déroulante à deux entrées : c'est un choix
   binaire, et le déplier pour en montrer deux coûte un clic de plus que de les
   montrer tout le temps. */
.bascule-mode {
  display: flex; gap: 4px; padding: 3px;
  background: rgba(0, 0, 0, .24); border-radius: 9px;
}
.bascule-mode button {
  flex: 1; padding: 6px 10px; border: 0; border-radius: 7px;
  background: none; color: var(--doux);
  font-family: inherit; font-size: 13px; cursor: pointer;
}
.bascule-mode button:hover { color: var(--texte); }
.bascule-mode button.actif { background: rgba(255, 255, 255, .11); color: var(--texte); }

.mention.alerte { color: #f0a0a0; }

/* La page d'un topic a TROIS familles de modules, pas quatre étapes : sans
   cette règle, le .tableau réservait une quatrième piste vide de 260 px. */
.tableau.trio { grid-template-columns: repeat(3, minmax(260px, 1fr)); max-width: 1120px; }

/* Un intertitre de section : le nom en gras, le compte en sourdine. La classe
   était utilisée sans avoir jamais été écrite — le bloc s'affichait en HTML
   nu, et personne ne l'avait vu parce qu'il ne sort que s'il existe des fils
   non déclarés. */
.jour-titre {
  display: flex; align-items: baseline; gap: 10px;
  margin-bottom: 10px; font-size: 13.5px;
}
.jour-titre b { font-weight: 600; }
.jour-titre span { color: var(--faible); font-size: 12px; }

/* Un module en sommeil garde sa place, en sourdine. Seul `.fiche.debat.muette`
   existait : la classe posée sur les cartes de module ne dessinait rien. */
.fiche.module.muette { opacity: .55; }
.fiche.module.muette:hover { opacity: .85; }

/* ── LES MODULES, DANS LES COLONNES DES TOPICS ─────────────────────────────
   Les cartes reprennent .fiche.debat : même dessin que les questions d'une
   rubrique, puisque c'est la même idée — une chose qui partira. Il ne s'ajoute
   que le compteur d'avance. */
.fiche.module .tour { font-size: 14px; }
.fiche.module .avance {
  margin-left: auto; min-width: 20px; text-align: center;
  padding: 1px 7px; border-radius: 999px;
  background: rgba(0, 0, 0, .3); color: var(--doux);
  font-size: 11px; font-variant-numeric: tabular-nums;
}
/* ZÉRO D'AVANCE EST UNE ALERTE, pas une valeur : le module est allumé, il a
   une heure, et rien à dire. Le seul chiffre qui prévient avant le silence. */
.fiche.module .avance.vide { background: rgba(200, 60, 60, .2); color: #f0a0a0; }

/* « + », en bout de pile : une carte en pointillé, comme une place libre. Le
   sélecteur répète `.liste.nue` exprès — `nue` retire la bordure, et à
   spécificité moindre le pointillé n'existait tout simplement pas : le « + »
   était deux pixels de texte flottant qu'on ne trouvait qu'en le sachant là. */
.liste.nue.ajouter-module { display: block; }
.liste.nue.ajouter-module .liste-tete {
  width: 100%; padding: 10px; justify-content: center;
  border: 1px dashed var(--ligne); border-radius: 10px;
  color: var(--faible); font-size: 15px;
}
.liste.nue.ajouter-module .liste-tete i { display: none; }
.liste.nue.ajouter-module .liste-tete:hover { color: var(--texte); border-color: rgba(255,255,255,.3); }

/* ══ LE CALENDRIER DES TOPICS ══════════════════════════════════════════════
   Lundi → dimanche, une carte par publication. Les colonnes sont STABLES :
   chaque carte est un rituel qui revient — celle de lundi y sera encore lundi
   prochain. C'est ce qui distingue ce calendrier de celui qu'on a retiré du
   planning, où les cases étaient des jours à remplir, vides quatre fois sur
   sept. */
.tableau.semaine { grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 10px; }
.tableau.semaine .chapeau { padding: 7px 10px; font-size: 12.5px; }
.tableau.semaine .fiche { padding: 9px 10px; }
/* `.fiche h3` est en nowrap pour les colonnes larges ; à un septième d'écran,
   « Classement des membres » se tronquerait à quatre lettres. On laisse plier,
   deux lignes au plus. */
.tableau.semaine h3 {
  font-size: 12.5px; line-height: 1.3; white-space: normal;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.tableau.semaine .chapeau { min-height: 0; }
/* En dessous de mille pixels, sept colonnes lisibles ne tiennent plus : le
   calendrier glisse latéralement plutôt que de devenir illisible. */
@media (max-width: 1000px) {
  .tableau.semaine {
    grid-template-columns: repeat(7, 160px);
    overflow-x: auto; padding-bottom: 8px;
  }
}

/* Un jour vide se voit, sans un mot : c'est une place, pas un manque.
   `.jour-libre`, PAS `.creux` : cinq autres pages utilisent .creux pour un
   texte d'attente, et le redéfinir ici les aurait toutes encadrées de
   pointillés. */
.jour-libre {
  display: block; min-height: 46px; border-radius: 10px;
  border: 1px dashed var(--ligne); opacity: .5;
}

/* ── LE TOUR PORTE LA COULEUR DU MODULE ────────────────────────────────────
   Sur le calendrier comme sur la page d'un topic, la pastille colorée dit ce
   que c'est — film, question, défi — avant qu'on lise quoi que ce soit. Les
   mêmes teintes que partout. */
.fiche.module .tour { font-size: 13px; color: #fff; }
.fiche.module .tour.bleu   { background: #33407a; }
.fiche.module .tour.vert   { background: #1f5237; }
.fiche.module .tour.ambre  { background: #8a4508; }
.fiche.module .tour.violet { background: #4a3172; }
.fiche.module .tour.rose   { background: #6e2b49; }
.fiche.module .tour.cyan   { background: #1d5560; }
.fiche.module .tour.gris   { background: #40434a; }

/* ══ LA PAGE D'UN TOPIC ════════════════════════════════════════════════════
 *
 * Deux temps — ce qui sort aujourd'hui, ce qui vient apres — et une palette de
 * blocs qu'on pose dessus. Le tableau d'avant rangeait par nature, ce qui
 * repondait a « de quel genre est ce module » quand la question est « quand ».
 *
 * PAS UNE COULEUR DE PLUS. Tout vient des variables partagees. Une page qui
 * choisit ses propres teintes, c'est le defaut que tv.ejs documente en tete :
 * on arrivait dessus comme sur un autre site. Ici, la seule chose qui porte
 * une couleur est le liseré d'« Aujourd'hui », et il porte du sens. */

/* ── LE BONJOUR ───────────────────────────────────────────────────────────
   Il dit le nom de qui regarde, puis ce que le topic fait aujourd'hui. Sans
   la seconde ligne ce serait un ornement ; avec elle, c'est la premiere
   information qu'on est venu chercher. */
/* ── ELLE PORTE LA COULEUR DU TOPIC ───────────────────────────────────────
   C'est le seul endroit de la page qui change d'un topic a l'autre, et c'est
   voulu : deux topics ouverts cote a cote doivent se distinguer avant qu'on
   lise leur nom. Les memes sept teintes que le reste du tableau de bord —
   aucune couleur nouvelle n'entre par cette porte. */
.salut {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px; margin-bottom: 14px;
  background: var(--flanc);
  border-radius: var(--rond-large);
}
.salut.bleu   { background: var(--fond-bleu); }
.salut.vert   { background: var(--fond-vert); }
.salut.ambre  { background: var(--fond-ambre); }
.salut.violet { background: var(--fond-violet); }
.salut.rose   { background: var(--fond-rose); }
.salut.cyan   { background: var(--fond-cyan); }
.salut.gris   { background: var(--fond-gris); }
.salut-face { border-radius: 50%; flex: none; }
.salut-mots { min-width: 0; }
.salut h2 { font-size: 16px; font-weight: 600; margin: 0; }
/* La voix se présente sous le bonjour. Son nom ressort, le reste s'efface :
   c'est le nom qu'on retient, pas la formule. */
/* DU BLANC TRANSLUCIDE, PAS `--faible`. Le gris du texte discret est fait pour
   le fond sombre du reste du tableau de bord ; pose sur l'ambre de CineClub ou
   le vert de Fashion, il devenait illisible. Une opacite tient sur les sept. */
.salut-voix { margin: 1px 0 0; font-size: 13px; color: rgba(255, 255, 255, .62); }
.salut-voix b { color: #fff; font-weight: 600; }

/* Le repli quand la voix n'a pas d'avatar — l'emoji du topic, dans sa
   couleur. Meme taille que la photo pour que la bande ne saute pas selon que
   l'adresse est renseignee ou non. */
/* Le disque est sombre et translucide, et non de la teinte du topic : la bande
   la porte deja en entier, une pastille de la meme couleur s'y effacerait. */
.salut-emoji {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px;
  border-radius: 50%;
  background: rgba(0, 0, 0, .28);
  font-size: 19px;
}

/* ── LE POULS DU SERVEUR ──────────────────────────────────────────────────
   SOUS-TITRE DU NOM DU SERVEUR, pas dernière ligne du menu. Il vivait en bas
   de la barre derrière un filet ; il décrit pourtant le serveur, comme le nom
   juste au-dessus de lui. Il s'aligne donc sur ce nom — l'écusson fait 36 px,
   plus 8 px de retrait et 12 px d'écart : 56 px — et la marge négative annule
   l'écart de 20 px que la barre met entre ses blocs, pour qu'il colle au nom
   au lieu de flotter entre lui et le menu.

   DEUX CHIFFRES COLLÉS, SUR UNE LIGNE COURTE. « 30 en ligne sur 178 » mettait
   trois mots gris sous un nom en gras — une légende égarée. Une jauge pleine
   largeur a suivi : pire encore, une barre de progression sous un nom de
   serveur laisse croire que quelque chose se remplit.

   Elle ne s'étire donc plus jusqu'au bord : les deux nombres se touchent, et
   la ligne s'arrête où elle a fini.

   ET ELLE EST REMONTÉE À CÔTÉ DU NOM. Sous lui, elle occupait une ligne
   entière de la barre pour cinq caractères, et poussait tout le menu d'un cran
   vers le bas. Une mesure du serveur se lit à côté du nom du serveur — le
   dernier espace libre de cette ligne était fait pour elle. */
.tete-flanc { display: flex; align-items: center; gap: 8px; }
.tete-flanc .marque { flex: 1; min-width: 0; }
/* Le nom cède avant le pouls : c'est lui qui peut être long, et un nom coupé
   reste lisible là où un compteur coupé ne veut plus rien dire. */
.tete-flanc .marque b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.pouls {
  display: flex; align-items: baseline; gap: 4px; flex: none;
  font-size: 12px; color: var(--faible);
}
.pouls b {
  color: var(--texte); font-weight: 600; font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.pouls-vif {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--vif-vert); flex: none;
  /* Un halo, pas un point peint : c'est ce qui le fait lire comme « vivant »
     plutôt que comme une puce de liste. */
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--vif-vert) 22%, transparent);
}
.pouls-sur { font-variant-numeric: tabular-nums; margin-left: -1px; }

/* ── LE VISAGE DE LA VOIX, DANS LE PANNEAU ────────────────────────────────
   Un rond et un mot. L'apercu garde sa place meme vide : sans lui la rangee
   sautait de trente pixels des qu'on posait une image, et le panneau bougeait
   sous le doigt. */
.valeur.visage { display: flex; align-items: center; gap: 10px; }
.visage-apercu {
  width: 32px; height: 32px; flex: none;
  border-radius: 50%; object-fit: cover;
  background: var(--carte);
}
.visage-apercu.vide { opacity: .45; }
.visage-choix {
  padding: 5px 10px;
  border: 1px solid var(--ligne); border-radius: var(--rond);
  font-size: 12px; color: var(--doux); cursor: pointer;
}
.visage-choix:hover { background: var(--carte-survol); color: var(--texte); }

/* ── LES DEUX TEMPS ───────────────────────────────────────────────────────
   Cote a cote sur un ecran large, l'un sous l'autre des qu'il n'y a plus la
   place. Jamais trois : « hors grille » est une bande, pas une colonne — ce
   qui n'a pas d'heure n'est pas un troisieme moment. */
/* DEUX COLONNES PARTOUT, TELEPHONE COMPRIS. Elles s'empilaient sous 280 px de
   large : on se retrouvait avec « Aujourd'hui » plein ecran et « Plus tard »
   hors de vue, alors que tout l'interet est de voir les deux d'un coup — c'est
   la comparaison qui renseigne, pas chaque liste prise a part.

   `minmax(0, 1fr)` et non `1fr` : sans le zero, une carte au nom long refuse
   de se comprimer et pousse la colonne au-dela de l'ecran. */
.deux-temps {
  display: grid; gap: 14px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (max-width: 620px) {
  .deux-temps { gap: 8px; }
  .temps { padding: 10px 8px; }
}

.temps {
  background: var(--flanc);
  border-radius: var(--rond-large);
  padding: 14px;
}
/* Pas de liseré sur « Aujourd'hui ». Il y en avait un, bleu, pour dire que
   c'est le moment où l'on est — mais l'en-tête le dit déjà en toutes lettres,
   et une barre de couleur qui répète un titre n'ajoute qu'un trait. */

.temps-tete {
  display: flex; align-items: baseline; gap: 8px;
  margin: 0 0 12px;
}
.temps-tete h2 { font-size: 14px; font-weight: 600; margin: 0; }
.temps-compte {
  margin-left: auto; min-width: 20px; text-align: center;
  padding: 1px 7px; border-radius: 999px;
  background: rgba(0, 0, 0, .25); color: var(--faible);
  font-size: 11px; font-variant-numeric: tabular-nums;
}

/* ── LA ZONE DE DÉPÔT ─────────────────────────────────────────────────────
   Au repos elle n'est rien : une pile de cartes. Elle ne se dessine que
   pendant qu'on tient un bloc — un pointillé permanent serait un cadre de plus
   a regarder les vingt-trois heures ou l'on ne depose rien. */
.depot { min-height: 56px; border-radius: var(--rond); }
.pose-en-cours .depot {
  outline: 1px dashed var(--ligne);
  outline-offset: 4px;
}
.pose-en-cours .depot.visee { outline-color: var(--bleu); }

/* ── UNE CARTE DE MODULE, EN PLUS COMPACT ─────────────────────────────────
   `fiche module` porte deja le survol, le lien qui couvre, les teintes de
   pastille et le compteur d'avance. `passage` ne fait que resserrer. */
.fiche.module.passage { padding: 10px 12px; border-radius: var(--rond); }
.fiche.module.passage h3 { font-size: 13px; margin-top: 4px; line-height: 1.3; }
.passage-rang { display: flex; align-items: center; gap: 6px; }
.passage-quand {
  flex: 1; min-width: 0; font-size: 12px; color: var(--faible);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* CE QUI EST DEJA PARTI S'EFFACE, sans disparaitre : la journee garde sa forme
   entiere, et le survol le rend lisible pour qui veut le relire. */
.fiche.module.passage.parti { opacity: .45; }
.fiche.module.passage.parti:hover { opacity: .9; }

/* ── LA CROIX SE VOIT SANS QU'ON LA CHERCHE ───────────────────────────────
   `.oter-carte` naît à `opacity: 0` et n'apparaît qu'au survol de sa carte.
   Sur les colonnes d'un topic, ça revient à cacher le seul moyen de retirer un
   module : on le cherche, on ne le trouve pas, on conclut que ça ne marche pas
   — c'est exactement ce qui a été rapporté deux fois. Elle reste discrète,
   mais elle est là. */
.fiche.module.passage .oter-carte { opacity: .4; }
.fiche.module.passage:hover .oter-carte { opacity: .75; }
.fiche.module.passage .oter-carte:hover { opacity: 1; background: var(--ligne); }

/* ── DEVANCER L'HORLOGE ───────────────────────────────────────────────────
   Discret au repos, franc au survol. C'est un geste public et sans retour :
   il ne doit pas s'attraper du coin du doigt, mais il ne doit pas non plus
   crier sur une carte qu'on lit vingt fois pour autre chose. */
.maintenant {
  flex: none;
  padding: 3px 9px;
  border: 1px solid var(--ligne);
  border-radius: 999px;
  background: none;
  color: var(--faible);
  font-size: 11px;
  cursor: pointer;
}
.maintenant:hover { background: var(--bleu); border-color: var(--bleu); color: #fff; }
.maintenant.occupe { opacity: .5; pointer-events: none; }

/* ── LA PALETTE ───────────────────────────────────────────────────────────
   Au-dessus des colonnes, et compacte : c'est une barre d'outils, pas un
   catalogue.

   ELLE ETAIT EN DESSOUS, ET C'ETAIT LE DEFAUT. Chaque module ajoute la
   repoussait d'un cran : l'outil s'eloignait a mesure qu'on s'en servait, et
   un topic charge le mettait hors de l'ecran. Au-dessus, sa place ne depend
   plus de ce qu'on a programme — et le geste va vers le bas, dans le sens ou
   l'on glisse.

   ET CHAQUE TUILE TENAIT EN TROIS LIGNES : la pastille, le nom long, la
   phrase d'aide. Six paragraphes pour une barre d'outils. Un emoji et un mot
   suffisent a reconnaitre ; la phrase reste en infobulle. */
.palette {
  padding: 10px; margin-bottom: 14px;
  background: var(--flanc);
  border-radius: var(--rond-large);
}

/* ── UNE GRILLE, ET DES TUILES QU'ON ATTRAPE ──────────────────────────────
   Elles ont ete une rangee de petites pastilles : lisible sur un grand ecran,
   intenable au pouce. La grille les repartit, et `minmax` les laisse grandir
   quand la place existe au lieu de rester minuscules dans un coin.

   56 PIXELS DE HAUT, PAS MOINS. C'est la regle que le reste du tableau de bord
   s'est deja donnee — aucune cible sous 44 px sur telephone — et une tuile
   qu'on doit viser pour la faire glisser demande davantage qu'un bouton qu'on
   tapote. */
/* ── CINQ PAR RANGEE, ET C'EST UN CHOIX ──────────────────────────────────
   C'etait `auto-fit` : la grille casait autant de tuiles que la largeur le
   permettait, sans se soucier du reste. A dix modules, ca donnait sept en haut
   et trois en bas — une rangee pleine et une rangee bancale.

   Cinq colonnes fixes donnent 5 + 5, deux rangees egales, et une seule rangee
   bien remplie tant qu'il n'y en a que cinq. Le nombre suit le projet : dix
   modules prevus, cinq par rangee.

   `minmax(0, 1fr)` et non `1fr` : sans le zero, un nom long refuse de se
   comprimer et pousse la grille hors de son cadre. */
.blocs {
  display: grid; gap: 8px;
  grid-template-columns: repeat(5, minmax(0, 1fr));
}
@media (max-width: 1100px) { .blocs { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .blocs { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.bloc {
  display: flex; align-items: center; gap: 10px;
  min-height: 56px;
  padding: 8px 14px;
  background: var(--carte);
  border: 1px solid transparent;
  border-radius: var(--rond);
  color: var(--texte);
  font-size: 14px; font-weight: 600;
  text-align: left;
  cursor: grab;
}
.bloc:hover { background: var(--carte-survol); border-color: var(--ligne); }
.bloc:active { cursor: grabbing; }
/* La pastille grandit avec la tuile : c'est elle qu'on reconnait de loin, le
   mot ne fait que confirmer. */
.bloc .tour { width: 30px; height: 30px; font-size: 16px; color: #fff; }
.bloc.saisie { opacity: .4; }
.bloc.occupe { opacity: .5; pointer-events: none; }


/* La pastille du bloc reprend les teintes des cartes : un defi est ambre dans
   la palette comme il le sera une fois pose. */
.bloc .tour.bleu   { background: #33407a; }
.bloc .tour.vert   { background: #1f5237; }
.bloc .tour.ambre  { background: #8a4508; }
.bloc .tour.violet { background: #4a3172; }
.bloc .tour.rose   { background: #6e2b49; }
.bloc .tour.cyan   { background: #1d5560; }
.bloc .tour.gris   { background: #40434a; }

/* ── LES MODULES QU'ON N'OUVRE JAMAIS, AVEC LA ROUE ───────────────────────
   L'accueil et le classement tournent sans qu'on les programme. Ils ont eu une
   bande sous les colonnes, puis une place au bord de la palette : deux fois
   trop d'espace pour deux reglages qu'on ouvre une fois par an. Ils sont
   maintenant des boutons ronds a cote de l'engrenage — meme forme, meme taille,
   l'emoji du module a la place de l'icone. */
/* ── UN OBJET, PAS UNE ACTION ─────────────────────────────────────────────
   Ces boutons-la MENENT QUELQUE PART — la page du module. La roue, juste a
   cote, ouvre un tiroir sans quitter la page. Trois ronds identiques
   promettaient le meme geste et n'en tenaient que deux tiers.

   Le fond plein et la forme ronde les rapprochent d'une pastille — une chose
   qu'on ouvre — la ou l'engrenage reste un outil pose sur le fond. */
.roue.pose {
  text-decoration: none;
  font-size: 13px; line-height: 1;
  border-radius: 50%;
  background: rgba(255, 255, 255, .08);
  opacity: .75;
}
.roue.pose:hover { opacity: 1; background: rgba(255, 255, 255, .18); }

/* Le filet qui separe les deux familles. Il ne parait que s'il y a quelque
   chose a separer — la vue ne le pose pas autrement. */
.gestes-filet {
  width: 1px; height: 18px; flex: none;
  margin: 0 2px;
  background: var(--ligne);
}

/* ── LE RÉGLAGE D'UN TOPIC ─────────────────────────────────────────────────
   Le même panneau que celui d'une rubrique, posé en tête de page : la roue
   vit dans la barre du haut, le panneau s'ouvre dessous. */
.reglage-topic { max-width: 380px; }

/* ── CE QU'ON REGARDE SANS Y TOUCHER ───────────────────────────────────────
   Le panneau de rythme d'un topic qui n'est pas le sien. `inert` fait tout le
   travail — plus de clic, plus de tabulation — mais il ne se voit pas : sans
   ce gris, on essaie, rien ne répond, et on croit à une panne. */
.proprietes.fige { opacity: .62; }
.proprietes.fige .liste-tete, .proprietes.fige .date-tete { cursor: default; }

/* La même phrase que « Topic en sommeil », mais ce n'est pas un avertissement :
   rien ne va mal, c'est seulement le topic de quelqu'un d'autre. */
.avertissement.doux { background: rgba(255,255,255,.05); color: var(--doux); border-color: var(--ligne); }

/* QUI S'EN OCCUPE : des jetons, puis un menu pour en ajouter.
   ILS PASSENT À LA LIGNE. Un nom de rôle est long et ils sont plusieurs ; une
   rangée qui ne se casse pas pousserait le menu hors du panneau. */
.equipe-valeur { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.equipe-jetons { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 5px; }
.equipe-jetons .etiquette { cursor: pointer; border: 0; }
/* Le rouge au survol dit ce que fait le clic : retirer. Sans lui, un jeton
   cliquable ressemble à une étiquette décorative. */
.equipe-jetons .etiquette:hover { background: rgba(233,90,90,.24); color: #f3a3a3; }
.equipe-vide { font-size: 11px; color: var(--doux); opacity: .7; }

.rangee .champ.court { width: 64px; flex: none; text-align: center; }
/* Le même champ court sur la page d'un module : `.rangee` ne l'y attrapait pas,
   et l'émoji se posait au-dessus du nom au lieu d'être devant.

   ET LE CHAMP LONG DOIT SE LAISSER COMPRIMER. La rangée est bien en flex, mais
   le nom gardait sa largeur pleine — 746 px à côté d'un émoji de 72 — et
   `flex-wrap` le renvoyait à la ligne. Un `flex: 1` suffit : il prend ce qui
   reste au lieu de réclamer tout. */
.valeur .champ.court { width: 64px; flex: none; text-align: center; }
.valeur.en-ligne .champ:not(.court) { flex: 1; min-width: 0; width: auto; }
.gestes .roue { width: 30px; height: 30px; }
.gestes .roue svg { width: 17px; height: 17px; }

/* ── LA PAGE D'UN MODULE, DANS LE MOULE D'UN DÉBAT ─────────────────────────
   Les rangées viennent de .proprietes, telles quelles. Ne s'ajoutent que la
   file — posée sous les réglages, à largeur de colonne — et deux détails que
   les autres pages n'ont pas. */
.topic-file { max-width: 640px; margin-top: 26px; }
.topic-file.deja-parti { margin-top: 18px; }

/* Un textarea dans une rangée : pleine largeur, comme le champ d'une question. */
.valeur textarea.champ {
  width: 100%; resize: vertical;
  font-family: inherit; font-size: 13.5px; line-height: 1.45;
}
.valeur code, .menu-val code {
  padding: 1px 5px; border-radius: 4px;
  background: rgba(0, 0, 0, .3); font-size: 11.5px;
}

/* ── LA SALLE DE PROJECTION ────────────────────────────────────────────────
   Une seule ligne, en haut de l'écran Cinéma, qui dit où la télécommande
   projette. Elle est posée là et pas dans un repli parce qu'une salle qu'on
   oublie, c'est un film lancé sur le mauvais serveur devant des gens qu'on ne
   connaît pas : ça doit se lire sans qu'on le cherche.

   Le menu lui-même est celui de controles.js, comme partout ailleurs. */
.salle-projection {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin: -8px 0 28px;
  padding: 14px 18px;
  background: var(--carte);
  border: 1px solid var(--ligne);
  border-radius: 10px;
}
.salle-mot {
  font-weight: 600;
  color: var(--texte);
  white-space: nowrap;
}
/* La liste prend la place qui reste, sans s'étirer sur toute la largeur : un
   nom de serveur suivi d'un nom de salon tient largement là-dedans.
   C'est la liste NORMALE et pas la variante `nue` : celle-ci tronque son texte
   à 130 pixels, ce qui coupait « Chez Marc · 🎬 Cinéma » en plein milieu. */
.salle-projection .liste { flex: 0 1 340px; min-width: 220px; }
.salle-projection .liste-tete { width: 100%; }
/* L'avertissement passe à la ligne sur un écran étroit plutôt que d'écraser le
   menu, et il garde la couleur du texte secondaire : c'est un rappel, pas une
   alerte. Rien n'est cassé tant qu'on n'a pas lancé. */
.salle-avis {
  flex: 1 1 100%;
  margin: 0;
  color: var(--faible);
  font-size: 14px;
}
.salle-avis strong { color: var(--texte); font-weight: 600; }

/* ── LE JOURNAL DE MODERATION : LA BARRE DE TRI ────────────────────────────
   La mise en forme des entrees est plus bas, sous « LE JOURNAL, EN LIGNES ».
   Ici ne restent que les etiquettes de filtre, qui n'ont pas change. */
.journal-filtres { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.journal-filtre {
  border: 1px solid var(--ligne);
  background: var(--aire);
  color: var(--doux);
  cursor: pointer;
  font-family: inherit;
}
.journal-filtre:hover { background: var(--carte-survol); }
/* L'etiquette active perd sa transparence : c'est le seul repere qui dit ce
   qu'on regarde, une fois la liste filtree. */
.journal-filtre.actif { border-color: var(--bleu); color: var(--texte); }


/* Les memes couleurs que les embeds Discord (COULEURS dans lib/modlog.js) :
   un rouge ici et un rouge la-bas doivent vouloir dire la meme chose. */
.etiquette.journal-arrivee { background: #1f5237; color: #7ae0a3; }
.etiquette.journal-depart { background: #3a3d43; color: #c3c8ce; }
.etiquette.journal-edition { background: #5a4718; color: #f5cd77; }
.etiquette.journal-suppression { background: #5c2427; color: #f19295; }
.etiquette.journal-sanction { background: #5a2547; color: #f19ad3; }
.etiquette.journal-alerte { background: #5c2427; color: #f19295; }

/* ── LA MEDIATHEQUE DE GIF ─────────────────────────────────────────────────
   Deux grilles sur le meme ecran : ce qu'on TROUVE (petit, dense, on survole
   et on clique) et ce qu'on A GARDE (plus grand, on le regarde vraiment).
   Les tailles different expres — la premiere est un etalage, la seconde une
   collection. */
/* ── LA PAGE D AJOUT ───────────────────────────────────────────────────────
   La recherche EN GRAND, parce que c est le geste de la page. Le personnage
   au-dessus et non a cote : il ne se saisit qu une fois par seance, alors que
   la requete change a chaque essai — les mettre sur la meme ligne donnait deux
   champs de meme poids pour deux roles tres differents. */
.ajout-tete { max-width: 860px; margin-bottom: 20px; }
.ajout-personnage { width: 100%; max-width: 340px; margin-bottom: 10px; }
.ajout-recherche { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.ajout-requete { flex: 1 1 320px; min-width: 200px; font-size: 16px; padding: 11px 14px; }
/* Le champ de fichier natif est illisible et ne se style pas. Le label porte
   l'apparence, l'input reste cache dessous et fait le travail. */
.gifs-televerser { cursor: pointer; }

.gifs-etat { margin: 12px 0 0; color: var(--faible); font-size: 14px; }
.gifs-etat-erreur { color: #f19295; }

.gifs-resultats {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 8px;
  margin-top: 14px;
  /* Un plafond, parce que quarante vignettes ANIMEES repousseraient sinon
     hors de l ecran ce qu on possede deja — l information meme qui evite le
     doublon qu on est en train de creer. */
  max-height: 40vh;
  overflow-y: auto;
  margin-bottom: 26px;
}
.gifs-trouve {
  padding: 0; border: 2px solid transparent; border-radius: var(--rond);
  background: var(--fond); cursor: pointer; overflow: hidden; line-height: 0;
}
.gifs-trouve img { width: 100%; height: 110px; object-fit: cover; display: block; }
.gifs-trouve:hover { border-color: var(--bleu); }
.gifs-encours { opacity: .5; }
/* Ce qui est deja garde reste visible mais sort du jeu : le rechercher pour
   decouvrir qu'on l'a deja pris est une perte de temps qu'on peut eviter. */
.gifs-garde { border-color: var(--vert); opacity: .45; cursor: default; }

.gifs-compte { color: var(--faible); font-size: 13px; }


.gifs-pages {
  display: flex; align-items: center; justify-content: center;
  gap: 14px; margin-top: 22px;
}

.gifs-grille {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
}
.gifs-carte {
  margin: 0; position: relative;
  background: var(--aire); border: 1px solid var(--ligne);
  border-radius: var(--rond); overflow: hidden;
}
.gifs-carte img { width: 100%; height: 130px; object-fit: cover; display: block; }
.gifs-carte figcaption { padding: 9px 11px; display: flex; flex-direction: column; gap: 3px; }
.gifs-oeuvre { font-size: 14px; font-weight: 500; }
.gifs-meta { color: var(--faible); font-size: 12px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* Le retrait ne s'affiche qu'au survol de sa carte : vingt croix rouges
   permanentes sur une grille donnent l'impression que tout est a jeter. */
.gifs-retirer {
  position: absolute; top: 6px; right: 6px;
  width: 26px; height: 26px; padding: 0;
  display: grid; place-items: center;
  border: none; border-radius: 50%;
  background: rgba(0, 0, 0, .6); color: #fff;
  cursor: pointer; opacity: 0; transition: opacity .12s;
}
.gifs-carte:hover .gifs-retirer, .gifs-retirer:focus { opacity: 1; }
.gifs-retirer:hover { background: var(--rouge); }
.gifs-retirer svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2; }

.etiquette.gifs-hors { background: #5a4718; color: #f5cd77; font-size: 11px; padding: 1px 7px; }
.etiquette.gifs-rogne { background: #33407a; color: #b3bbff; font-size: 11px; padding: 1px 7px; }

/* ══ PLANNING — LA PAGE D'ACCUEIL ═════════════════════════════════════════
   Le calendrier était parti d'ici : à sept colonnes pleine largeur, il
   affichait trois rendez-vous dans quarante-deux cases. Le tort n'était pas la
   grille, c'était sa taille. À quarante pixels par case, les six mêmes
   semaines tiennent dans une colonne et rendent enfin ce qu'une liste ne sait
   pas montrer : la régularité. */

.planning {
  display: grid;
  grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
  gap: 30px;
  align-items: start;
}
@media (max-width: 900px) { .planning { grid-template-columns: 1fr; gap: 24px; } }

/* ── La grille ─────────────────────────────────────────────────────────── */

.planning-mois { min-width: 0; }
.mois-tete { margin-bottom: 12px; }
.mois-tete b { font-size: 14px; font-weight: 600; text-transform: capitalize; }

.jours-noms, .planning-grille {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}
.jours-noms span {
  text-align: center;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--faible);
  padding-bottom: 6px;
}
.planning-grille { grid-auto-rows: 40px; }

.planning .case {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  border-radius: 6px;
  background: var(--fond);
  border: 1px solid transparent;
  font-variant-numeric: tabular-nums;
  text-decoration: none;
  color: inherit;
}
.planning .num-jour {
  font-style: normal;
  font-family: ui-monospace, Menlo, Consolas, monospace;
  font-size: 12px;
  color: var(--faible);
}
.planning .case.hors .num-jour { color: #52565e; }
.planning .case.aujourdhui { border-color: var(--bleu); }
.planning .case.aujourdhui .num-jour { color: var(--texte); font-weight: 700; }

.planning .case.plein { background: var(--carte); }
.planning .case.plein .num-jour { color: var(--texte); font-weight: 600; }

/* ── LA CASE SE CLIQUE À NOUVEAU ──────────────────────────────────────────
   Le survol et le focus étaient partis avec le lien : une case n'emmenait plus
   nulle part, et les montrer promettait un clic qui n'existait pas. Le clic
   existe de nouveau — il ne navigue pas, il désigne la journée que le panneau
   de droite détaille — donc les témoins reviennent avec lui.

   LA MARQUE DU JOUR CHOISI N'EST PAS CELLE D'AUJOURD'HUI. Aujourd'hui garde
   son liseré bleu, qui dit une date ; le jour choisi est rempli, ce qui dit un
   état de l'écran. Les deux tombent sur la même case à l'ouverture et doivent
   pouvoir se séparer dès le premier clic ailleurs. */
.planning .case { cursor: pointer; transition: background .12s, box-shadow .12s; }
.planning .case:hover { background: var(--carte-survol); }
.planning .case:focus-visible { outline: 0; box-shadow: 0 0 0 2px var(--bleu); }
.planning .case.choisi {
  background: var(--bleu);
  box-shadow: 0 0 0 1px var(--bleu);
}
.planning .case.choisi .num-jour { color: #fff; font-weight: 700; }
/* Sur le bleu plein, les pastilles de rubrique disparaîtraient : on les
   ramène en blanc, l'aplat portant déjà l'information de sélection. */
.planning .case.choisi .pt { background: rgba(255, 255, 255, .85); }
.planning .case.choisi .pt.passe { background: rgba(255, 255, 255, .45); }

.pastilles-jour { display: flex; gap: 3px; }
.planning .pt { width: 7px; height: 7px; border-radius: 50%; display: block; }

/* ── Les teintes des rubriques ─────────────────────────────────────────────
   Elles viennent de lib/debatRubriques.js — « bleu », « vert », « ambre » —
   et sont peintes avec la palette du tableau de bord : aucune couleur neuve. */

/* LES SEPT TEINTES DE lib/debatRubriques.js. Trois seulement étaient écrites :
   une rubrique en violet, rose ou cyan n'avait aucune --teinte, et tout ce qui
   s'appuie dessus retombait sur le défaut. */
/* Posee sur un element, chacune donne a tout son contenu de quoi se colorer :
   --teinte pour les melanges, --fond-teinte et --vif-teinte pour les aplats. */
.teinte-bleu   { --teinte: 121, 131, 245; --fond-teinte: var(--fond-bleu);   --vif-teinte: var(--vif-bleu); }
.teinte-vert   { --teinte:  35, 165,  90; --fond-teinte: var(--fond-vert);   --vif-teinte: var(--vif-vert); }
.teinte-ambre  { --teinte: 240, 178,  50; --fond-teinte: var(--fond-ambre);  --vif-teinte: var(--vif-ambre); }
.teinte-violet { --teinte: 168, 118, 232; --fond-teinte: var(--fond-violet); --vif-teinte: var(--vif-violet); }
.teinte-rose   { --teinte: 232, 106, 152; --fond-teinte: var(--fond-rose);   --vif-teinte: var(--vif-rose); }
.teinte-cyan   { --teinte:  66, 184, 205; --fond-teinte: var(--fond-cyan);   --vif-teinte: var(--vif-cyan); }
.teinte-gris   { --teinte: 148, 155, 164; --fond-teinte: var(--fond-gris);   --vif-teinte: var(--vif-gris); }
.planning .pt.teinte-bleu  { background: var(--bleu-clair); }
.planning .pt.teinte-vert  { background: var(--vert); }
.planning .pt.teinte-ambre { background: var(--jaune); }

/* ── Ce qui est au programme ───────────────────────────────────────────── */

.planning-suite { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
/* Une journée est un bloc : ses séances se suivent sans espace supplémentaire
   entre elles, c'est la colonne qui les espace. */
.suite-jour { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.suite-vide { margin: 0; padding: 18px 0; text-align: center; }

.suite-tete {
  margin: 0 0 2px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--faible);
}

/* PAS DE FILET COLORÉ AU BORD. Il décore sans rien apprendre. La carte est
   teintée de sa rubrique, comme l'était déjà l'ancienne carte « prochain ». */
.seance {
  --teinte: 149, 155, 164;
  display: flex;
  align-items: center;
  gap: 15px;
  background: rgba(var(--teinte), .09);
  border: 1px solid rgba(var(--teinte), .28);
  border-radius: var(--rond);
  padding: 13px 16px;
  text-decoration: none;
  color: inherit;
  transition: background .14s, border-color .14s;
}
a.seance:hover { background: rgba(var(--teinte), .15); border-color: rgba(var(--teinte), .48); }
a.seance:focus-visible { outline: 2px solid var(--bleu); outline-offset: 2px; }

.seance-h {
  flex: none;
  font-family: ui-monospace, Menlo, Consolas, monospace;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: rgb(var(--teinte));
}

.seance-corps { min-width: 0; flex: 1; }

/* LA QUESTION PASSE DEVANT. Elle était sous le nom de la rubrique — l'inverse
   de ce qu'on lit : la rubrique se voit déjà à la couleur. */
.seance-titre {
  display: block;
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -.005em;
  overflow-wrap: anywhere;
}
.seance-meta { display: block; margin-top: 3px; font-size: 12px; color: var(--faible); }
.seance-rubrique { color: rgb(var(--teinte)); font-weight: 600; }
.seance-num { font-family: ui-monospace, Menlo, Consolas, monospace; font-variant-numeric: tabular-nums; }

.seance-dans {
  flex: none;
  font-family: ui-monospace, Menlo, Consolas, monospace;
  font-size: 11.5px;
  color: var(--faible);
  white-space: nowrap;
}

.planning-vide {
  margin: 0;
  padding: 30px 20px;
  text-align: center;
  background: var(--fond);
  border: 1px dashed var(--ligne);
  border-radius: var(--rond-large);
  font-size: 13.5px;
  color: var(--faible);
}
.planning-vide b { display: block; color: var(--doux); font-weight: 600; margin-bottom: 4px; }
.planning-vide a { color: var(--bleu-clair); }

/* ══ LE MUR DES FILMS VUS ═════════════════════════════════════════════════
   La seule page du tableau de bord où l'image EST le contenu. Les affiches
   viennent de TMDB en 342 px : la colonne les suit au lieu de les étirer.

   RIEN SOUS L'AFFICHE. Titre, année et date faisaient trois lignes de texte
   sous chaque jaquette, et la grille devenait un mur de mots. Le titre est
   déjà écrit sur l'affiche ; le reste ne sert qu'au moment où l'on s'arrête
   sur un film, donc il apparaît à ce moment-là. */

.mur-films {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(164px, 1fr));
  gap: 16px;
  align-items: start;
}

/* ── LE MUR DES ENVIES ───────────────────────────────────────────────────
 *
 * Même matériau que la Galerie — des affiches — et donc même grille : on
 * reconnaît une jaquette avant d'avoir lu son titre.
 *
 * CE QUI CHANGE EST CE QU'ON VIENT Y FAIRE. La Galerie se contemple ; la
 * Wishlist sert à choisir la prochaine séance. Le titre reste donc écrit sous
 * l'affiche au lieu de se cacher dans un voile au survol, le nombre de gens
 * qui attendent est visible sans geste, et les deux boutons sont là en
 * permanence : au doigt, un geste caché derrière un survol n'existe pas. */
.mur-envies {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(164px, 1fr));
  gap: 18px 16px;
  align-items: start;
  margin-top: 22px;
}

.envie-carte { min-width: 0; }

.envie-image {
  position: relative;
  aspect-ratio: 2 / 3;
  border-radius: var(--rond-large);
  overflow: hidden;
  background: var(--carte);
  display: grid;
  place-items: center;
  margin-bottom: 9px;
}
.envie-image img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Le compteur se pose sur l'affiche, pas à côté : c'est le classement, et il
   doit se lire dans le même coup d'œil que l'image. Un fond opaque parce
   qu'une affiche peut être claire. */
.envie-compte {
  position: absolute; top: 7px; right: 7px;
  min-width: 22px; height: 22px; padding: 0 6px;
  display: grid; place-items: center;
  border-radius: 11px;
  background: rgba(10, 13, 20, .82);
  color: #fff; font-size: 12px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  backdrop-filter: blur(3px);
}

.envie-titre {
  display: block;
  font-size: 13.5px; font-weight: 600; line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.envie-pied {
  display: flex; align-items: center; gap: 6px;
  margin-top: 2px;
}
/* Le nom prend ce qui reste et se coupe ; les boutons ne bougent jamais, pour
   qu'on les retrouve à la même place d'une carte à l'autre. */
.envie-carte .envie-qui { flex: 1; min-width: 0; margin-top: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.envie-carte .envie-gestes { margin-right: -4px; }

.jaquette { min-width: 0; }

.jaquette-image {
  position: relative;
  aspect-ratio: 2 / 3;
  border-radius: var(--rond-large);
  overflow: hidden;
  background: var(--carte);
  display: grid;
  place-items: center;
  transition: transform .16s ease, box-shadow .16s ease;
}
.jaquette-image img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* L'AFFICHE MANQUANTE RESTE RECONNAISSABLE. Un cadre vide se lit comme une
   erreur de chargement ; deux lettres se lisent comme un film sans image. */
.jaquette-init { font-size: 30px; font-weight: 700; letter-spacing: -.02em; color: var(--faible); }

.jaquette-voile {
  position: absolute;
  inset: auto 0 0 0;
  padding: 30px 12px 11px;
  background: linear-gradient(to top, rgba(0,0,0,.92) 25%, rgba(0,0,0,.55) 60%, transparent);
  opacity: 0;
  transition: opacity .16s ease;
}
.jaquette-voile b {
  display: block;
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.25;
  color: #fff;
  overflow-wrap: anywhere;
}
.jaquette-voile span {
  display: block;
  margin-top: 2px;
  font-size: 11.5px;
  color: rgba(255,255,255,.72);
  font-variant-numeric: tabular-nums;
}

.jaquette:hover .jaquette-voile,
.jaquette:focus-within .jaquette-voile { opacity: 1; }

@media (prefers-reduced-motion: no-preference) {
  .jaquette:hover .jaquette-image {
    transform: translateY(-3px);
    box-shadow: 0 12px 26px rgba(0,0,0,.48);
  }
}

/* Sans survol — au doigt — le voile reste visible : il n'y a pas de second
   geste pour le faire venir. */
@media (hover: none) {
  .jaquette-voile { opacity: 1; }
}

/* ══ LES ENVIES ════════════════════════════════════════════════════════════
   Une envie partage la colonne des brouillons mais pas leur carte : elle est
   plus basse, horizontale, et ne montre qu'une vignette. La différence de
   forme dit ce qu'aucune étiquette ne dirait — qu'il n'y a rien à ouvrir, et
   rien de fixé. */

.envie {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  border-radius: var(--rond);
  background: var(--carte);
  border: 1px solid var(--bord);
}

.envie-jaquette {
  flex: 0 0 auto;
  width: 34px;
  aspect-ratio: 2 / 3;
  border-radius: 4px;
  overflow: hidden;
  background: var(--fond);
}
.envie-jaquette img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* min-width: 0 — sans lui, un titre long refuse de se tronquer et pousse les
   deux boutons hors de la colonne. */
.envie-corps { min-width: 0; flex: 1; }

.envie-corps h4 {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.envie-qui {
  display: block;
  margin-top: 1px;
  font-size: 11.5px;
  color: var(--faible);
  font-variant-numeric: tabular-nums;
}

.envie-gestes { display: flex; gap: 2px; flex: 0 0 auto; }

.envie-gestes button {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--faible);
  cursor: pointer;
  transition: background .14s ease, color .14s ease;
}
.envie-gestes svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.envie-programmer:hover { background: var(--accent-fond); color: var(--accent); }
.envie-oter:hover { color: var(--texte); }

/* Armé : la couleur change, la taille non. Un bouton qui grandit décale la
   rangée sous le curseur au moment même où l'on vise le second clic. */
.envie-oter.arme { background: var(--danger-fond); color: var(--danger); }

.envie-gestes button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ══ LE JOURNAL, EN LIGNES ═════════════════════════════════════════════════
   Chaque entrée était une carte encadrée : quarante cartes empilées, c'est
   quarante fois le même décor pour quarante fois la même structure, et l'œil
   retraverse un cadre à chaque ligne.

   Une ligne par évènement, la photo à gauche, l'heure à droite toujours au
   même endroit : on balaye une colonne du regard au lieu de lire une grille.
   Le fond n'apparaît qu'au survol — il montre où l'on est, il ne découpe pas
   la page en morceaux. */

.journal {
  list-style: none;
  margin: 0; padding: 0;
  display: flex; flex-direction: column;
}

.journal-entree {
  display: grid;
  grid-template-columns: 40px 1fr auto;
  gap: 12px;
  align-items: start;
  padding: 10px 12px;
  border-radius: var(--rond);
  transition: background .12s ease;
}
.journal-entree:hover { background: var(--aire); }
.journal-entree[hidden] { display: none; }

/* ── Qui ────────────────────────────────────────────────────────────────── */

.log-tete { position: relative; width: 40px; height: 40px; }

.log-photo {
  width: 40px; height: 40px;
  border-radius: 50%;
  object-fit: cover;
  display: grid; place-items: center;
  background: var(--carte);
  color: var(--faible);
  font-size: 13px; font-weight: 700; letter-spacing: .02em;
}

/* LA PASTILLE PORTE LE TYPE, la photo porte l'identité : deux repères qui ne
   se disputent pas, puisqu'on cherche d'abord qui, ensuite quoi. Le liseré la
   décolle de l'avatar, sinon les deux ronds se confondent. */
.log-pastille {
  position: absolute; right: -1px; bottom: -1px;
  width: 13px; height: 13px;
  border-radius: 50%;
  border: 2.5px solid var(--flanc);
  background: var(--faible);
}
.log-pastille.journal-suppression { background: var(--rouge); }
.log-pastille.journal-edition     { background: var(--jaune); }
.log-pastille.journal-arrivee     { background: var(--vert); }
.log-pastille.journal-depart      { background: var(--faible); }
.log-pastille.journal-sanction    { background: var(--rouge); }
.log-pastille.journal-alerte      { background: var(--jaune); }

/* ── Quoi ───────────────────────────────────────────────────────────────── */

.log-corps { min-width: 0; }

.log-phrase {
  margin: 2px 0 0;
  font-size: 14px; line-height: 1.4; color: var(--doux);
}
.log-phrase b { color: var(--texte); font-weight: 600; }
.log-salon { color: var(--bleu-clair); font-weight: 500; }

/* LE CONTENU DU MESSAGE EST UNE CITATION, pas le texte de la page : c'est
   quelqu'un d'autre qui l'a écrit, et le filet à gauche le dit sans guillemets
   à rallonge. */
.log-texte {
  margin: 5px 0 0;
  padding-left: 10px;
  border-left: 2px solid var(--ligne);
  font-size: 13.5px; line-height: 1.45;
  color: var(--doux);
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

.log-details {
  margin: 6px 0 0;
  display: grid; grid-template-columns: auto 1fr; gap: 2px 10px;
  font-size: 12.5px;
}
.log-details dt { color: var(--faible); }
.log-details dd { margin: 0; color: var(--doux); overflow-wrap: anywhere; }

/* ── Quand ──────────────────────────────────────────────────────────────── */

.log-quand {
  margin-top: 3px;
  font-size: 12px; color: var(--faible);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Sous 560 px, l'heure passe sous la phrase : à trois colonnes, il ne restait
   qu'une poignée de caractères pour le message lui-même. */
@media (max-width: 560px) {
  .journal-entree { grid-template-columns: 40px 1fr; }
  .log-quand { grid-column: 2; margin-top: 6px; }
}

/* ══ LE DÉFILEMENT DES FONDS ═══════════════════════════════════════════════
   LE NOM EST « DIAPO » ET NON « PLANCHE » : .planche existe déjà plus haut
   (ligne 332), c'est la bande d'affiches d'une soirée, en display:grid avec
   une hauteur imposée. Écrite plus bas, une règle .planche la repassait en
   display:block et cassait la grille des cartes du Cinéma — sans une seule
   erreur nulle part.

   LA TUILE NE CHANGE PAS DE TAILLE, c'est l'image qui s'y range. La planche
   n'est qu'un repère de position pour les points : elle n'impose ni hauteur ni
   format, et l'affiche garde le dimensionnement qu'elle avait — largeur pleine,
   hauteur libre.

   Rien ne saute d'un fond à l'autre pour autant : toutes les affiches sortent
   du même canvas de 1280×720. */

.diapo { position: relative; display: block; }
.diapo .planche-jeu { transition: opacity .18s ease; }


@media (prefers-reduced-motion: reduce) {
  .diapo .planche-jeu { transition: none; }
}

/* ══ ARRÊTER UNE PARTIE ════════════════════════════════════════════════════ */

.arreter {
  margin-left: auto;
  padding: 3px 10px;
  border: 1px solid var(--ligne);
  border-radius: 999px;
  background: transparent;
  color: var(--faible);
  font: inherit; font-size: 11.5px; font-weight: 600;
  cursor: pointer; white-space: nowrap;
  transition: background .14s ease, color .14s ease, border-color .14s ease;
}
.arreter:hover { color: var(--texte); border-color: var(--faible); }
/* Armé : la couleur change, la taille non — un bouton qui grandit décale la
   rangée sous le curseur au moment même où l'on vise le second clic. */
.arreter.arme { background: var(--rouge); border-color: var(--rouge); color: #fff; }
.arreter:disabled { opacity: .6; cursor: default; }

/* ══ LA FICHE D'UN MINI-JEU ════════════════════════════════════════════════
   CINQ RANGÉES, PAS NEUF. Une par champ alignait l'affiche, le nom, la
   commande, l'emoji, la phrase, les alias, le minimum, la couleur et les
   fonds : neuf lignes pour six métadonnées, et il fallait descendre pour
   trouver ce qu'on venait changer.

   Ce qui se lit ensemble s'édite ensemble — l'emoji ne vit jamais sans le nom,
   une commande et ses raccourcis sont la même chose. Et les fonds rejoignent
   l'affiche : la rangée de vignettes montrait en petit, dix centimètres plus
   bas, ce que l'aperçu montrait en grand.

   Le reste vient de la fiche d'une soirée : .entete, .proprietes, .champ. */

.affiche {
  position: relative;
  width: min(100%, 520px);
  border-radius: var(--rond);
  overflow: hidden;
  background: var(--fond);
  line-height: 0;
}
.affiche img { width: 100%; display: block; transition: opacity .14s ease; }

/* Pendant le survol d'un glisser : la cible doit être évidente, sinon on lâche
   à côté et il ne se passe rien. */
.affiche.survol { outline: 2px dashed var(--bleu); outline-offset: -4px; }

/* LES FLÈCHES SE POSENT SUR L'IMAGE, pas à côté : une image qu'on parcourt se
   parcourt depuis elle-même. Elles restent discrètes tant qu'on ne s'en
   approche pas — deux ronds noirs en permanence sur une affiche, c'est deux
   choses de plus à regarder. */
.affiche-fleche {
  position: absolute; top: 50%; transform: translateY(-50%);
  display: grid; place-items: center;
  width: 30px; height: 30px; padding: 0;
  border: 0; border-radius: 50%;
  background: rgba(0, 0, 0, .55); color: #fff;
  cursor: pointer; opacity: .35;
  transition: opacity .14s ease, background .14s ease;
}
.affiche:hover .affiche-fleche { opacity: 1; }
.affiche-fleche:hover { background: rgba(0, 0, 0, .78); }
.affiche-fleche:focus-visible { opacity: 1; outline: 2px solid #fff; outline-offset: 1px; }
.affiche-fleche.gauche { left: 8px; }
.affiche-fleche.droite { right: 8px; }
.affiche-fleche svg {
  width: 15px; height: 15px; fill: none; stroke: currentColor;
  stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round;
}

/* Le rang plutôt que des pastilles : « 3 / 7 » se lit d'un coup, et sept ronds
   posés sur l'affiche disaient moins pour plus de bruit. */
.affiche-rang {
  position: absolute; right: 9px; bottom: 8px;
  padding: 2px 8px; border-radius: 999px;
  background: rgba(0, 0, 0, .6);
  font-size: 11px; font-weight: 600; line-height: 1.6;
  color: #fff; font-variant-numeric: tabular-nums;
  pointer-events: none;
}

.affiche-gestes { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
/* Le label porte l'input caché : il doit se comporter comme un bouton. */
.affiche-gestes label.bouton { cursor: pointer; }

/* Une rangée qui tient plusieurs contrôles côte à côte. */
.valeur.en-ligne, .valeur .en-ligne {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}

/* .champ.court n'avait sa largeur que sous .rangee : ailleurs il retombait sur
   « .champ { width: 100% } » et passait à la ligne en pleine largeur. */
.valeur .champ.court { width: 72px; flex: none; text-align: center; }

/* ── LE TITRE EST LE CHAMP ──────────────────────────────────────────────────
   « Le nom » avait sa rangée, sous une affiche qui porte déjà le nom écrit en
   grand : on lisait deux fois la même chose. Le titre de la page EST ce champ.
   Il ne ressemble à un champ qu'au survol et au focus — le reste du temps c'est
   un titre, et c'en est un. */
/* ATTENTION AUX LARGEURS DES CHAMPS. La règle de base s'écrit
   « .champ, input[type="text"], input[type="search"], textarea { width: 100% } ».
   « input[type="text"] » vaut 0,1,1 en spécificité — plus qu'une classe seule.
   Toute règle qui veut donner une autre largeur à un champ texte doit donc
   porter au moins deux classes, ou un parent. Trois fois de suite le défaut
   s'est présenté ainsi : le champ prend toute la largeur, aucune erreur nulle
   part, et l'on cherche du côté du flex. */
.entete .titre-champ, .entete .titre-emoji {
  border: 1px solid transparent;
  border-radius: var(--rond);
  background: transparent;
  color: var(--texte);
  font: inherit;
  padding: 2px 8px;
  transition: background .14s ease, border-color .14s ease;
}
.entete .titre-champ {
  flex: 1; min-width: 0; width: auto;
  font-size: 34px; font-weight: 700; letter-spacing: -.02em;
}
/* L'emoji tient en deux caractères : lui donner la largeur d'un nom ferait
   croire qu'on y écrit une phrase. */
.entete .titre-emoji {
  flex: none; width: 54px; min-width: 0;
  font-size: 26px; text-align: center;
}

.entete .titre-champ:hover, .entete .titre-emoji:hover { background: var(--aire); }
.entete .titre-champ:focus, .entete .titre-emoji:focus {
  outline: none; background: var(--aire); border-color: var(--bleu);
}
.entete .titre-champ::placeholder { color: var(--faible); font-weight: 600; }


/* ── LES COMMANDES, EN ÉTIQUETTES ───────────────────────────────────────────
   Une ligne de texte « lg loup » demandait de savoir que l'espace sépare, et il
   fallait l'écrire sous le champ. Une étiquette montre ce qu'elle est, et sa
   croix ce qu'on peut en faire : plus rien à expliquer. */
.tags {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  padding: 5px 6px;
  border: 1px solid var(--ligne);
  border-radius: var(--rond);
  background: var(--fond);
  max-width: 520px;
}
.tags:focus-within { border-color: var(--bleu); }
/* La boîte entière renvoie au champ : le curseur doit le dire avant le clic. */
.tags { cursor: text; }
.tags .tag { cursor: default; }

.tag {
  display: inline-flex; align-items: center; gap: 3px;
  padding: 4px 5px 4px 9px;
  border-radius: 999px;
  background: var(--carte);
  color: var(--doux);
  font-size: 12.5px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
/* La première ne se retire pas : c'est le nom du dossier de fonds et la clé de
   l'historique des parties. La perdre perdrait les deux, sans rien dire. */
.tag.fige { padding-right: 9px; background: var(--ligne); color: var(--faible); }

.tag button {
  display: grid; place-items: center;
  width: 15px; height: 15px; padding: 0;
  border: 0; border-radius: 50%;
  background: transparent; color: var(--faible); cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.tag button:hover { background: var(--rouge); color: #fff; }
.tag button svg {
  width: 8px; height: 8px; fill: none; stroke: currentColor;
  stroke-width: 3; stroke-linecap: round;
}

/* Le champ d'ajout se fond dans la boîte : c'est la suite de la rangée
   d'étiquettes, pas un contrôle de plus. Un « + » en attente suffit à dire
   qu'on peut écrire là. */
.tags .tag-champ {
  flex: 1; min-width: 70px; width: auto;
  border: 0; background: transparent; color: var(--texte);
  font: inherit; font-size: 13px; padding: 4px 6px;
}
.tags .tag-champ:focus { outline: none; }
.tags .tag-champ::placeholder { color: var(--faible); font-size: 15px; }

/* input[type=color] porte le style du système : un rectangle gris à bord carré.
   On lui retire son cadre et on lui donne la forme d'une pastille. */
.p-couleur {
  flex: none;
  width: 40px; height: 32px; padding: 0;
  border: 1px solid var(--ligne); border-radius: 8px;
  background: transparent; cursor: pointer;
}
.p-couleur::-webkit-color-swatch-wrapper { padding: 3px; }
.p-couleur::-webkit-color-swatch { border: 0; border-radius: 5px; }

/* Le compte rendu défile plutôt que d'allonger la page. */
.etat-fonds {
  margin-top: 10px; max-width: 520px;
  max-height: 160px; overflow-y: auto;
  padding: 9px 11px;
  border-radius: var(--rond);
  background: var(--fond);
  font-size: 12px; color: var(--doux);
  font-variant-numeric: tabular-nums;
}
.etat-fonds p { margin: 0 0 3px; }
.etat-fonds p.petite { color: #f6c860; }
.etat-fonds p.rate { color: var(--rouge); }

/* SUPPRIMER EST EN BAS DE LA FICHE, loin d'Enregistrer qui vit dans l'en-tête.
   Deux boutons voisins dont l'un défait tout, c'est un clic de travers qui
   coûte cher. */
.bouton.danger { color: var(--faible); }
.bouton.danger:hover { color: var(--rouge); }
.bouton.danger.arme { background: var(--rouge); color: #fff; }


/* ══ ARRÊTER UNE PARTIE ════════════════════════════════════════════════════ */

.arreter {
  margin-left: auto;
  padding: 3px 10px;
  border: 1px solid var(--ligne);
  border-radius: 999px;
  background: transparent;
  color: var(--faible);
  font: inherit; font-size: 11.5px; font-weight: 600;
  cursor: pointer; white-space: nowrap;
  transition: background .14s ease, color .14s ease, border-color .14s ease;
}
.arreter:hover { color: var(--texte); border-color: var(--faible); }
/* Armé : la couleur change, la taille non. */
.arreter.arme { background: var(--rouge); border-color: var(--rouge); color: #fff; }
.arreter:disabled { opacity: .6; cursor: default; }

/* ══ LA GALERIE DES PERSONNAGES ════════════════════════════════════════════
   On arrivait sur un champ de texte et une liste déroulante native : il fallait
   connaître par cœur les soixante-six noms déjà présents. Une liste déroulante
   ne montre rien — ni combien on en a, ni à quoi ils ressemblent.

   LE VISAGE EST SON PREMIER GIF. Pas de portrait à trouver, à stocker ni à
   tenir à jour : le premier GIF de chacun le représente très bien, et il est
   déjà là. */

.filtre-gens {
  display: flex; gap: 10px; align-items: center;
  max-width: 520px; margin-bottom: 20px;
}
.filtre-gens .champ { flex: 1; }

.galerie-gens {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
}

.tete {
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  text-decoration: none; color: var(--doux);
  transition: color .14s ease;
}
.tete[hidden] { display: none; }
.tete:hover { color: var(--texte); }
.tete b { font-size: 12.5px; font-weight: 600; text-align: center; line-height: 1.25; }

/* Le GIF s'arrête tant qu'on ne le regarde pas — soixante-six animations qui
   tournent en même temps font une page qui vibre et un ventilateur qui part.
   `animation-play-state` ne s'applique pas à un GIF ; on le calme autrement,
   en le laissant tourner mais en le rendant petit et sombre au repos. */
.tete-image {
  position: relative;
  width: 100%; aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  background: var(--carte);
  filter: saturate(.7) brightness(.82);
  transition: filter .16s ease, transform .16s ease;
}
.tete-image img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tete:hover .tete-image, .tete:focus-visible .tete-image {
  filter: none;
  transform: translateY(-2px);
}
.tete:focus-visible { outline: none; }
.tete:focus-visible .tete-image { outline: 2px solid var(--bleu); outline-offset: 2px; }

.tete-compte {
  font-size: 11px; color: var(--faible);
  font-variant-numeric: tabular-nums;
}

/* ══ CE QUI A EU LIEU, DANS LE CALENDRIER ══════════════════════════════════
   Le calendrier ne portait que l'avenir : une case redevenait vide le
   lendemain de la séance, comme si le film n'avait jamais été projeté, et la
   file des débats vidée laissait un mois entier blanc.

   Or c'est sa raison d'être. « Six mercredis alignés se lisent comme une
   habitude » — et une habitude est un motif DANS LE TEMPS. Un calendrier qui
   ne montre que ce qui vient n'en montre jamais.

   Le passé reste donc, à moitié effacé : il n'appelle plus, il témoigne. */

.pastilles-jour .pt.passe { opacity: .38; }

/* Une journée qui n'a que du passé garde son fond de journée ordinaire : le
   relief de « plein » annonce quelque chose à faire. */
.case.revolu .num-jour { opacity: .8; }

/* ══ LE CLASSEUR DES ARCADES ══════════════════════════════════════════════
   Deux écrans : les dossiers, puis la grille des jeux du dossier.

   NOMS CHOISIS APRÈS VÉRIFICATION. `.vignette` et `.pastille` existent déjà
   ailleurs dans cette feuille ; s'en resservir ici aurait repeint des pages
   qui n'ont rien demandé — c'est arrivé cinq fois le 26 août 2026, avec
   `.planche` et `.panneau` notamment. `classeur`, `grille-jeux` et
   `carte-jeu` n'apparaissaient nulle part. */

.classeur {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
  gap: 16px;
  align-items: start;
}

.classeur-dossier {
  display: grid;
  gap: 6px;
  padding: 16px;
  border-radius: var(--rond-large);
  background: var(--carte);
  border: 1px solid var(--ligne);
  color: inherit;
  text-decoration: none;
  transition: transform .16s ease, border-color .16s ease;
}
.classeur-dossier:hover { transform: translateY(-2px); border-color: var(--bleu-clair); }
.classeur-dossier b { font-size: 15px; font-weight: 650; }

/* LA PILE reprend le dossier Discord : quatre cases, et on reconnaît ce qu'il
   y a dedans avant d'avoir lu le nom. */
.classeur-pile {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 4px;
  width: 62px;
  margin-bottom: 8px;
}
.classeur-carre {
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  border-radius: 7px;
  background: var(--fond);
  font-size: 14px;
  font-style: normal;
}
/* Un jeu pas encore écrit s'affiche pâle : la pile dit du premier coup d'œil
   combien du dossier tourne vraiment. */
.classeur-carre.attente { opacity: .38; }
.classeur-carre.vide { background: color-mix(in srgb, var(--fond) 60%, transparent); }

.classeur-quoi { font-size: 12.5px; color: var(--faible); line-height: 1.4; }
.classeur-compte {
  font-size: 11.5px;
  color: var(--faible);
  font-variant-numeric: tabular-nums;
}

/* ── LA GRILLE D'UN DOSSIER ─────────────────────────────────────────────── */

/* `grid-auto-rows: 1fr` égalise les hauteurs : sans lui, une description de
   deux lignes et une de quatre donnent deux cartes de tailles différentes sur
   la même rangée — exactement ce qu'on vient de supprimer par ailleurs. */
.grille-jeux {
  display: grid;
  grid-auto-rows: 1fr;
  grid-template-columns: repeat(auto-fill, minmax(178px, 1fr));
  gap: 12px;
  margin-bottom: 28px;
}

.carte-jeu {
  display: grid;
  gap: 4px;
  padding: 14px;
  border-radius: var(--rond-large);
  background: var(--carte);
  border: 1px solid var(--ligne);
}
/* TOUTES LES CARTES FONT LA MÊME TAILLE. Les gros jeux prenaient deux
   colonnes, pour dire qu'ils portent une manche entière là où un petit
   s'intercale. À l'écran ça ne se lisait pas comme une information : ça se
   lisait comme une grille mal alignée. L'égalité vaut mieux qu'un code que
   personne n'a demandé. */

.carte-jeu-emoji { font-size: 22px; font-style: normal; line-height: 1; }
.carte-jeu b { font-size: 14.5px; font-weight: 650; }
.carte-jeu-quoi { font-size: 12px; color: var(--faible); line-height: 1.4; }
.carte-jeu-etat {
  /* Poussé en bas : dans des cartes de même hauteur, l'état se lit d'un coup
     sur toute la rangée au lieu de flotter à des hauteurs différentes. */
  margin-top: auto;
  padding-top: 6px;
  font-size: 11px;
  color: var(--faible);
  font-variant-numeric: tabular-nums;
}

/* À ÉCRIRE, PAS CASSÉ. La carte reste lisible — c'est la liste de ce qui
   arrive, pas un avertissement. */
.carte-jeu.a-ecrire { border-style: dashed; }
.carte-jeu.a-ecrire .carte-jeu-emoji { opacity: .45; }
.carte-jeu.a-ecrire b { color: var(--faible); }

/* NOM CHANGÉ APRÈS COUP. Ce bloc s'appelait `.titre-section`, un nom déjà
   pris par l'entête cliquable des sections repliables — quatre pages s'en
   servent, et cette règle-ci, écrite plus bas, les aurait toutes repeintes.
   Sixième collision de la journée : chercher le nom AVANT de l'écrire. */
.intertitre {
  font-size: 13px;
  font-weight: 650;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--faible);
  margin: 0 0 12px;
}

/* ── LES TEINTES ────────────────────────────────────────────────────────
   La plaque de l'emoji prend la couleur du jeu, avec les couples déjà
   définis dans :root. On ne réécrit pas les valeurs ici : c'est en les
   réécrivant que le pavé d'Otaku avait fini par ne plus ressembler à sa
   colonne. */

.carte-jeu-emoji {
  display: grid;
  place-items: center;
  width: 38px; height: 38px;
  border-radius: 10px;
  background: var(--fond-gris);
  margin-bottom: 4px;
}
.carte-jeu.gris   .carte-jeu-emoji { background: var(--fond-gris); }
.carte-jeu.bleu   .carte-jeu-emoji { background: var(--fond-bleu); }
.carte-jeu.vert   .carte-jeu-emoji { background: var(--fond-vert); }
.carte-jeu.ambre  .carte-jeu-emoji { background: var(--fond-ambre); }
.carte-jeu.violet .carte-jeu-emoji { background: var(--fond-violet); }
.carte-jeu.rose   .carte-jeu-emoji { background: var(--fond-rose); }
.carte-jeu.cyan   .carte-jeu-emoji { background: var(--fond-cyan); }

/* Un jeu prêt porte un liseré de sa couleur vive : dans une grille où la
   plupart sont encore à écrire, c'est ce qui distingue le seul qui tourne. */
.carte-jeu:not(.a-ecrire).gris   { border-color: var(--vif-gris); }
.carte-jeu:not(.a-ecrire).bleu   { border-color: var(--vif-bleu); }
.carte-jeu:not(.a-ecrire).vert   { border-color: var(--vif-vert); }
.carte-jeu:not(.a-ecrire).ambre  { border-color: var(--vif-ambre); }
.carte-jeu:not(.a-ecrire).violet { border-color: var(--vif-violet); }
.carte-jeu:not(.a-ecrire).rose   { border-color: var(--vif-rose); }
.carte-jeu:not(.a-ecrire).cyan   { border-color: var(--vif-cyan); }

/* ── LE FIL DU CLASSEUR ─────────────────────────────────────────────────
   Deux pages derrière une seule entrée de menu : il faut bien que quelque
   chose dise laquelle. Le fil vit dans `.gestes`, donc coque.js le monte
   dans la barre du haut avec les boutons — pas de règle de position à
   écrire, et il suit la barre le jour où elle bouge. */

.fil-parent {
  color: var(--faible);
  text-decoration: none;
  font-size: 14px;
}
.fil-parent:hover { color: var(--texte); text-decoration: underline; }
.fil-parent::after {
  content: '›';
  margin: 0 4px 0 7px;
  color: var(--faible);
  text-decoration: none;
  display: inline-block;
}
.fil-ici { font-size: 14px; font-weight: 650; margin-right: 6px; }


/* ── LE TELEPHONE ────────────────────────────────────────────────────────
 *
 * Ouvert en 375 px, la barre laterale de 260 px restait plantee la et
 * poussait tout le contenu hors de l'ecran. La feuille comptait trois points
 * de rupture, aucun ne touchait la coque.
 *
 * Sous 820 px : une seule colonne, et la barre devient un tiroir. Au-dessus,
 * rien ne change. */

.burger { display: none; }

.voile {
  position: fixed; inset: 0; z-index: 39;
  background: rgba(0, 0, 0, .55);
}

@media (max-width: 820px) {
  body.app {
    grid-template-columns: 1fr;
    grid-template-rows: var(--haut-haut) 1fr;
    grid-template-areas: "haut" "aire";
  }

  /* Hors flux et hors ecran : le tiroir ne prend aucune place tant qu'on ne
     l'ouvre pas, et il glisse au lieu d'apparaitre d'un coup. */
  .flanc {
    position: fixed; z-index: 40;
    top: 0; bottom: 0; left: 0;
    width: min(82vw, 300px);
    transform: translateX(-102%);
    transition: transform .22s ease;
    box-shadow: 0 0 40px rgba(0, 0, 0, .5);
  }
  .flanc.ouvert { transform: none; }

  .burger {
    display: inline-grid; place-items: center;
    width: 38px; height: 38px; margin-right: 4px;
    background: transparent; border: 0; border-radius: 8px;
    color: inherit; cursor: pointer;
  }
  .burger:hover { background: rgba(255, 255, 255, .07); }
  .burger svg { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }

  /* Le contenu respire moins large : 32 px de marge sur un ecran de 375 en
     mangent un sixieme. */
  .aire { padding: 18px 14px 40px; }

  /* Le nom d'utilisateur en haut a droite passe a la trappe : sur 375 px, il
     vole la place du titre de la page pour ne rien dire d'utile. */
  .moi { font-size: 0; gap: 0; margin-left: 4px; flex: none; }
  .moi .pastille-avatar { font-size: .8rem; }

  /* ── LES BOUTONS DE LA PAGE RESTENT ATTEIGNABLES ──────────────────────
   *
   * Mesure en 375 px : le bord droit de `.haut` tombait a 498 px sur Cinema
   * et 575 px sur Debats. Les boutons `.gestes` etaient donc au-dela du bord,
   * invisibles et incliquables, sans que rien ne le signale : la page avait
   * simplement l'air de ne pas en avoir.
   *
   * On serre les marges, on autorise le retrecissement, et on laisse la
   * rangee defiler du doigt quand une page en a trop. */
  .haut { padding: 0 12px; gap: 10px; }

  .haut-actions {
    flex: 1 1 auto; min-width: 0;
    flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden;
    scrollbar-width: none;
  }
  .haut-actions::-webkit-scrollbar { display: none; }

  .gestes { gap: 8px; flex-wrap: nowrap; min-width: 0; }
  .haut .bouton {
    padding: 7px 12px; font-size: 13px; white-space: nowrap; flex: none;
  }

  /* SANS `min-width: 0`, UN ENFANT FLEX NE PASSE JAMAIS SOUS LA LARGEUR DE
   * SON CONTENU. C'est ce qui laissait la barre a 448 px sur Debats apres le
   * premier correctif : elle avait le droit de retrecir, mais ses enfants non. */
  .haut { overflow: hidden; }
  .haut > * { min-width: 0; }

  /* ── LE TABLEAU A COLONNES S'EMPILE ───────────────────────────────────
   *
   * Il demandait quatre colonnes de 260 px minimum, soit 1 040 px sur un
   * ecran de 375 : trois colonnes sur quatre tombaient hors de l'ecran.
   * Mesure : `section.colonne` a 552 px de bord droit sur la page Cinema.
   *
   * On ne les fait pas defiler horizontalement : comparer quatre listes cote
   * a cote n'a pas de sens sur neuf centimetres. On les empile, et chacune
   * garde son en-tete de couleur pour qu'on sache ou l'on est. */
  .tableau { grid-template-columns: 1fr; gap: 22px; }

  /* Au pouce, la ligne reserve plus de place a sa fleche. */
  .chevron-place { width: 40px; right: 4px; }
  .dossier-tete .entree { padding-right: 44px; }

  /* ── LA WISHLIST PASSE EN LIGNES ────────────────────────────────────
   *
   * Deux colonnes de 166 px laissaient 88 px au texte une fois les deux
   * boutons posés : « 4 veulent le voir » devenait « 4 veulen… », et les
   * cibles tactiles tombaient à 26 px.
   *
   * Une affiche de 40 px suffit à reconnaître un film qu'on a soi-même noté —
   * c'est la forme qu'avait déjà la colonne du tableau, et elle marchait. Le
   * mur en grand reste pour l'écran large, où il a de la place. */
  .mur-envies { grid-template-columns: 1fr; gap: 8px; margin-top: 16px; }

  .envie-carte {
    display: grid;
    grid-template-columns: 40px minmax(0, 1fr);
    column-gap: 10px;
    align-items: center;
    padding: 8px;
    border-radius: var(--rond);
    background: var(--carte);
    border: 1px solid var(--bord);
  }
  .envie-image { grid-row: 1 / 3; width: 40px; margin: 0; border-radius: 4px; }
  /* Les initiales sont calibrées pour une affiche de 164 px ; dans 40, elles
     débordaient du cadre. */
  .envie-image .jaquette-init { font-size: 14px; }
  .envie-titre { grid-column: 2; align-self: end; }
  .envie-pied { grid-column: 2; align-self: start; }

  /* Le compteur quitte l'affiche : à 40 px il la recouvrirait, et la ligne
     « 4 veulent le voir » juste à côté dit déjà le chiffre. */
  .envie-compte { display: none; }

  /* Des cibles qu'on attrape au pouce. */
  .envie-gestes button { width: 38px; height: 38px; }
  .envie-gestes svg { width: 18px; height: 18px; }

  /* La grille de résultats respire aussi : trois affiches par ligne sur un
     téléphone valent mieux que cinq illisibles. */
  .grille-oeuvres { grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 12px; }
}

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


/* ══ LA PAGE DES PARTENAIRES ═══════════════════════════════════════════════
 *
 * UNE GRILLE DE CARTES, pas une liste. Ce qu'on vient y verifier, c'est ce
 * qu'un partenaire montre : son nom, ses images, son lien. Une liste en
 * lignes rendrait les images minuscules ou les cacherait, c'est-a-dire
 * cacherait la seule chose qui distingue un dessinateur d'un autre.
 */
.mur-partenaires {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
}

.carte-partenaire {
  background: var(--carte); border: 1px solid var(--ligne);
  border-radius: 12px; padding: 14px;
  display: flex; flex-direction: column; gap: 10px;
}

/* UNE FICHE RETIREE SE VOIT SANS DISPARAITRE. Elle reste a sa place et garde
   ses images : on l'a eteinte, on ne l'a pas supprimee, et la difference doit
   se lire d'un coup d'oeil sans qu'on ait a chercher un libelle. */
.carte-partenaire.dormante { opacity: .5; }

.partenaire-tete { display: flex; align-items: center; gap: 10px; }

.partenaire-type {
  flex: none; width: 34px; height: 34px; border-radius: 9px;
  display: grid; place-items: center; font-size: 17px;
  background: var(--carte-survol);
}
.partenaire-type.violet { background: #4a3172; }
.partenaire-type.rose   { background: #6e2b49; }
.partenaire-type.bleu   { background: #33407a; }
.partenaire-type.vert   { background: #1f5237; }

.partenaire-qui { display: flex; flex-direction: column; min-width: 0; }
.partenaire-qui b { font-size: 15px; }
.partenaire-qui span {
  font-size: 12px; color: var(--faible);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* La bascule est a droite, et porte son etat en toutes lettres : une pastille
   de couleur aurait demande d'apprendre laquelle veut dire quoi. */
.bascule-fiche {
  margin-left: auto; flex: none;
  font: inherit; font-size: 12px;
  padding: 5px 10px; border-radius: 999px;
  background: none; border: 1px solid var(--ligne); color: var(--doux);
  cursor: pointer;
}
.bascule-fiche[data-actif="true"] { border-color: var(--vert); color: var(--vert); }
.bascule-fiche:disabled { opacity: .5; cursor: default; }

.partenaire-quoi { font-size: 13.5px; color: var(--doux); margin: 0; }

.partenaire-images {
  display: grid; gap: 6px;
  grid-template-columns: repeat(auto-fill, minmax(88px, 1fr));
}
.partenaire-images img {
  width: 100%; aspect-ratio: 1; object-fit: cover;
  border-radius: 8px; display: block;
}

.partenaire-lien {
  font-size: 12.5px; color: var(--bleu); text-decoration: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.partenaire-lien:hover { text-decoration: underline; }

.partenaire-gestes { display: flex; gap: 14px; }
.lien-nu.danger { color: var(--rouge); }

.partenaire-edition {
  display: flex; flex-direction: column; gap: 8px;
  padding-top: 10px; border-top: 1px solid var(--ligne);
}

/* Le tiroir d'images de l'editeur. Il se replie a zero quand il est vide :
   un cadre en pointilles sous chaque fiche sans image ferait croire a un
   emplacement manquant. */
.partenaire-tiroir { display: flex; flex-wrap: wrap; gap: 6px; }
.vignette { position: relative; width: 64px; height: 64px; }
.vignette img {
  width: 100%; height: 100%; object-fit: cover;
  border-radius: 8px; display: block;
}
.vignette-ote {
  position: absolute; top: -6px; right: -6px;
  width: 20px; height: 20px; border-radius: 50%;
  border: 0; background: var(--rouge); color: #fff;
  font: inherit; font-size: 13px; line-height: 1; cursor: pointer;
}

/* La fiche neuve, et les rangs de champs qu'elle partage avec l'editeur. */
.fiche-neuve {
  display: flex; flex-direction: column; gap: 8px;
  background: var(--carte); border: 1px solid var(--ligne);
  border-radius: 12px; padding: 14px; margin-bottom: 18px;
}
.rang-champs { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.rang-champs > .liste, .rang-champs > .champ { flex: 1 1 180px; min-width: 0; }

.erreur { color: var(--rouge); font-size: 13px; margin: 0; }

/* Sous mille pixels, une carte par ligne : deux colonnes de 320 px ne tiennent
   pas, et la grille tasserait les images a la taille d'un timbre. */
@media (max-width: 1000px) {
  .mur-partenaires { grid-template-columns: 1fr; }
}

/* Les reseaux sur la carte : les memes libelles que les boutons Discord, pour
   qu'on compose en voyant ce que la fiche montrera. */
.partenaire-reseaux { display: flex; flex-wrap: wrap; gap: 6px; }
.pastille-reseau {
  font-size: 12px; padding: 5px 10px; border-radius: 999px;
  background: var(--carte-survol); color: var(--doux);
  text-decoration: none; border: 1px solid var(--ligne);
}
.pastille-reseau:hover { color: var(--texte); border-color: var(--bleu); }

/* Dans l'editeur, un reseau par ligne : l'adresse est longue et se lit mal en
   pastille, alors qu'ici on vient justement la verifier. */
.partenaire-tiroir.vertical { flex-direction: column; gap: 4px; }
.ligne-reseau {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 8px; border-radius: 8px;
  background: var(--carte-survol); font-size: 12.5px;
}
.ligne-reseau b { flex: none; }
.ligne-url {
  flex: 1; min-width: 0; color: var(--faible);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Ici la croix est dans le flux, pas posee sur une vignette : elle reprend le
   dessin sans la position absolue. */
.ligne-reseau .vignette-ote { position: static; flex: none; }


/* ══ LA TELEVISION ═════════════════════════════════════════════════════════
 *
 * CETTE PAGE AVAIT SA PROPRE CHARTE. Elle portait un `<style>` de deux cents
 * lignes avec VINGT-CINQ couleurs ecrites en dur — des bleus nuit `#151a26`,
 * `#232c40`, `#0f1420`, un bleu vif `#3b5bdb` sur le badge « Lancer » — et
 * n'employait qu'UNE variable partagee. Le reste du tableau de bord tourne sur
 * les gris de Discord : on arrivait sur la Television comme sur un autre site.
 *
 * Tout est ici desormais, et rien ne choisit plus une couleur a la main.
 */

.tv-direct {
  display: flex; align-items: center; gap: 10px;
  background: var(--carte); border: 1px solid var(--ligne);
  border-radius: 10px; padding: 10px 14px; margin-bottom: 16px;
}
.tv-direct form { margin-left: auto; }
.tv-direct-titre { color: var(--doux); }
.tv-pastille {
  width: 8px; height: 8px; border-radius: 50%; background: var(--rouge);
  flex: none; box-shadow: 0 0 0 3px rgba(237, 66, 69, .18);
}

/* ── LA BARRE ────────────────────────────────────────────────────────────── */
.tv-barre {
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  margin-bottom: 12px;
}
.tv-cherche {
  flex: 1 1 320px; min-width: 0; position: relative;
  display: flex; align-items: center; gap: 8px;
  background: var(--carte); border: 1px solid var(--ligne);
  border-radius: 10px; padding: 0 12px; height: 42px;
}
.tv-cherche:focus-within { border-color: var(--bleu); }
.tv-cherche svg {
  width: 16px; height: 16px; flex: none;
  fill: none; stroke: var(--faible); stroke-width: 2; stroke-linecap: round;
}
.tv-cherche input {
  flex: 1; min-width: 0; background: none; border: 0; outline: none;
  font: inherit; color: var(--texte);
}
/* Le compteur vit DANS le champ : il repond a la question qu'on se pose en
   tapant, sans occuper une ligne pour lui. */
.tv-compte { font-size: 12px; color: var(--faible); flex: none; }

.tv-vers { display: flex; align-items: center; gap: 8px; flex: none; }
.tv-vers-mot { font-size: 12.5px; color: var(--faible); }
.tv-vers .liste { min-width: 140px; }

/* ── LES PUCES DE GENRE ──────────────────────────────────────────────────── */
.tv-puces { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; }
.tv-puce {
  font: inherit; font-size: 12.5px;
  padding: 6px 12px; border-radius: 999px; cursor: pointer;
  background: var(--carte); border: 1px solid var(--ligne); color: var(--doux);
}
.tv-puce:hover { background: var(--carte-survol); color: var(--texte); }
.tv-puce.actif { background: var(--bleu); border-color: var(--bleu); color: #fff; }
.tv-puce-liste { min-width: 150px; }

/* ── LA GRILLE ───────────────────────────────────────────────────────────── */
.tv-grille {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}

.tv-carte {
  position: relative; text-align: left; font: inherit; color: inherit;
  cursor: pointer; padding: 8px;
  display: flex; flex-direction: column; gap: 7px;
  background: var(--carte); border: 1px solid var(--ligne); border-radius: 10px;
}
.tv-carte:hover { border-color: var(--bleu); }
.tv-carte:focus-visible { outline: 2px solid var(--bleu); outline-offset: 1px; }
/* « Lancer » n'apparait qu'au survol : trois mille badges permanents font une
   grille qui crie, et l'on ne voit plus les logos qu'on vient parcourir. */
.tv-carte::after {
  content: 'Lancer'; position: absolute; inset: auto 10px 10px auto;
  background: var(--bleu); color: #fff;
  font-size: 11px; font-weight: 600; padding: 3px 8px; border-radius: 5px;
  opacity: 0; transition: opacity .12s; pointer-events: none;
}
.tv-carte:hover::after, .tv-carte:focus-visible::after { opacity: 1; }

/* ── LA TUILE DU LOGO ────────────────────────────────────────────────────
 *
 * CLAIRE, ET C'EST TOUT L'INTERET. Les logos de chaines sont des PNG
 * transparents dessines POUR DU BLANC. Sur le fond sombre d'avant, tous les
 * logos noirs disparaissaient : on regardait une case vide en croyant l'image
 * morte, et rien ne distinguait « pas de logo » de « logo invisible ».
 *
 * Le format est FIXE. Les logos vont du carre au panoramique : sans hauteur
 * imposee, chaque carte prenait la sienne et la grille partait en escalier. */
.tv-tuile {
  position: relative; aspect-ratio: 16 / 9;
  display: grid; place-items: center; overflow: hidden;
  border-radius: 7px;
  /* ── SOMBRE, ET LEGEREMENT PLUS CLAIR QUE LA CARTE ────────────────────
   *
   * Un noir franc collerait la tuile au fond et l'on ne verrait plus ou
   * commence le logo. Deux tons au-dessus de `--carte`, la tuile se detache
   * sans s'allumer, et le degrade tres leger empeche les quatre coins de
   * paraitre plats sur une grille de deux mille cases.
   *
   * CE QUE CE CHOIX COUTE, ET QUI EST ASSUME : les logos entierement noirs
   * du catalogue se lisent mal ici. Aucun fond ne convient aux deux — le
   * catalogue melange des logos dessines pour du blanc et d'autres pour du
   * sombre — et le fond clair, lui, effacait les logos blancs, qui sont les
   * plus nombreux. */
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .04), rgba(0, 0, 0, .10)),
    var(--fond);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .04);
}
.tv-tuile img { max-width: 82%; max-height: 82%; object-fit: contain; }
/* Les initiales quand le logo manque ou ne repond plus. Claires sur sombre,
   comme le serait un logo. */
.tv-initiale { font-weight: 700; font-size: 17px; color: var(--faible); letter-spacing: .5px; }

.tv-coeur {
  position: absolute; top: 4px; left: 4px; z-index: 1;
  width: 22px; height: 22px; border-radius: 50%;
  border: 0; cursor: pointer; font-size: 13px; line-height: 1;
  background: rgba(0, 0, 0, .45); color: #fff;
}
.tv-coeur:hover { background: rgba(0, 0, 0, .65); }
.tv-coeur.aime { color: var(--rouge); }

/* ── LE TEXTE ────────────────────────────────────────────────────────────
 *
 * Le nom seul en titre, et tout ce qui le qualifie sur UNE ligne en dessous.
 * Le catalogue ecrit « 8flix HD (1080p) » et « 100% Auto Moto TV (406p)
 * [Not 24/7] » : la definition et les crochets mangeaient la moitie de la
 * place d'un titre de deux lignes. Ils sont retires du nom et remis ici, en
 * petit — l'information reste, elle cesse d'etre au premier plan. */
.tv-nom {
  font-size: 12.5px; line-height: 1.3; color: var(--texte);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.tv-bas { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.tv-genre {
  font-size: 10.5px; color: var(--doux);
  background: var(--carte-survol); border-radius: 4px; padding: 2px 6px;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tv-qualite {
  font-size: 10px; font-weight: 600; letter-spacing: .3px;
  color: var(--faible); border: 1px solid var(--ligne);
  border-radius: 4px; padding: 1px 5px;
}
/* « par moments » plutot que « [Not 24/7] » : c'est la meme information, dans
   une langue qu'on lit sans la traduire. */
.tv-partiel { font-size: 10px; color: var(--ambre, #f0b232); }
.tv-serie { font-size: 10.5px; color: var(--vif-bleu); }

.tv-plus { display: grid; place-items: center; margin: 20px 0; }

/* Sous mille pixels, des tuiles plus petites : a 150 px de large minimum, deux
   colonnes ne tenaient pas sur un telephone. */
@media (max-width: 1000px) {
  .tv-grille { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); }
  .tv-vers { width: 100%; }
  .tv-vers .liste { flex: 1; min-width: 0; }
}

/* `.page-vide.sobre` et `.vide-gestes` vivaient ici : l'ecran « Pas encore de
   configuration » d'un topic, retire avec lui. `.page-vide` tout court reste,
   sept autres vues s'en servent. */


/* ══ AU POUCE ══════════════════════════════════════════════════════════════
 *
 * TOUT CE TABLEAU DE BORD A ETE DESSINE A LA SOURIS. Un curseur vise au pixel ;
 * un doigt couvre une pastille de sept a neuf millimetres, soit environ 44 px.
 * En dessous, on rate — ou pire, on touche le voisin.
 *
 * La mesure, sur telephone, avant ce bloc :
 *
 *   coeur d'une chaine   22 px   et il y en a cent vingt par ecran
 *   tete de liste        28 px
 *   sous-entree du menu  32 px
 *   avatar               32 px
 *   puce de genre        33 px
 *   burger               38 px
 *   entree du menu       43 px
 *
 * Pas une seule cible n'atteignait le minimum. D'ou la plainte : « les sous-
 * sections de Topics et Arcades, c'est trop petit pour etre accessible au
 * doigt ».
 *
 * ── DEUX FACONS D'AGRANDIR, ET ON CHOISIT SELON LE DESSIN ────────────────
 *
 * Quand la place existe — les lignes du menu, les rangees d'une liste — on
 * agrandit vraiment : plus de hauteur, plus de texte, ca se lit mieux aussi.
 *
 * Quand le dessin doit rester petit — le coeur pose sur un logo, la croix
 * d'une vignette — on etend la ZONE D'ECOUTE sans toucher au visuel, par un
 * pseudo-element transparent qui deborde. Le doigt trouve 44 px, l'oeil voit
 * toujours 22.
 */
@media (max-width: 1000px) {

  /* ── LE MENU ───────────────────────────────────────────────────────── */
  .entree { min-height: 48px; }

  /* Les sous-entrees etaient a 32 px, collees les unes aux autres par un
     interligne d'un pixel : rater Gaming, c'etait ouvrir Fashion. */
  .rameau {
    min-height: 44px;
    padding-top: 10px; padding-bottom: 10px;
    font-size: 14.5px;
  }
  .rameaux { gap: 3px; }
  .rameau-emoji { width: 20px; font-size: 15px; }

  .burger { width: 44px; height: 44px; }
  .moi { width: 44px; height: 44px; }

  /* ── LES LISTES DEROULANTES ────────────────────────────────────────── */
  .liste-tete { min-height: 44px; }
  .liste-choix button { min-height: 44px; }
  .date-grille button { min-height: 40px; }
  .date-heure .pas { min-width: 40px; min-height: 40px; }

  /* ── LES PUCES ET LES GESTES DE CARTE ──────────────────────────────── */
  .tv-puce { min-height: 40px; padding: 9px 14px; }
  .pastille-reseau { min-height: 38px; display: inline-flex; align-items: center; }
  .bascule-fiche { min-height: 38px; }
  .lien-nu { min-height: 40px; display: inline-flex; align-items: center; }
  .partenaire-gestes { gap: 18px; }

  /* ── LES PETITS BOUTONS POSES SUR AUTRE CHOSE ──────────────────────── */
  /* Le dessin ne bouge pas ; seule la zone d'ecoute deborde. `inset` negatif
     porte les 22 px du coeur a 44, et les 20 px de la croix a 44 aussi. */
  .tv-coeur, .vignette-ote {
    position: relative;
  }
  .tv-coeur { position: absolute; }
  .tv-coeur::after,
  .vignette-ote::after {
    content: ''; position: absolute; inset: -11px;
  }

  /* Les pastilles de couleur d'une rubrique : onze pixels, c'est un grain de
     riz. Elles restent rondes et petites, la zone s'etend autour. */
  .pastille-teinte { position: relative; }
  .pastille-teinte::after { content: ''; position: absolute; inset: -12px; }
  .nuancier { gap: 10px; }
}

/* Le ruban qui rappelle qu'on est en lecture. En tête de l'aire, avant le
   contenu de la page : c'est la première chose lue, et la seule qui explique
   pourquoi les boutons manquent ailleurs. */
.ruban-lecture { margin: 0 0 14px; }

/* La bulle qui dit pourquoi le geste n'est pas parti. En bas au centre, comme
   les messages système du reste du site : c'est une réponse à un clic, pas une
   alerte, et elle ne doit pas couvrir ce qu'on venait de lire. */
.bulle-lecture {
  position: fixed; z-index: 60; bottom: 22px; left: 50%; transform: translateX(-50%);
  max-width: min(520px, calc(100vw - 32px));
  padding: 10px 16px; border-radius: 999px;
  background: rgba(20,22,26,.96); border: 1px solid var(--ligne);
  color: var(--doux); font-size: 12px; text-align: center;
  box-shadow: 0 14px 32px rgba(0,0,0,.5);
}
