/* L'appel audio et vidéo du chat interne — de deux à six.
 *
 * ── Pourquoi une feuille à part ───────────────────────────────────────────
 *
 * `main.css` porte un mojibake ancien — 93 occurrences de « Ã© », « Â« » et
 * consorts, du Windows-1252 relu en UTF-8 — constaté octet par octet le
 * 17/10/2026. Le fichier lui-même est de l'UTF-8 valide, tout en CRLF ; c'est
 * son TEXTE qui est abîmé, pas son encodage. Une réécriture globale le
 * « réparerait » au passage et brouillerait l'historique d'un fichier que
 * trois chantiers se partagent. `finitions.css` et `chatInterne.css`, eux,
 * appartiennent à des chantiers en cours.
 *
 * Cette feuille est en UTF-8, n'est touchée que par le chantier de la visio,
 * et ne redéfinit rien de ce que les autres posent : tous ses sélecteurs
 * portent `visio`.
 *
 * ── Où la fenêtre se place, et où elle n'a pas le droit d'aller ───────────
 *
 * La position et la taille sont posées EN LIGNE par `public/js/chatVisio.js`,
 * parce qu'elles sont déplaçables à la souris et retenues d'une fois sur
 * l'autre. Ce que cette feuille fixe est ce qui ne se négocie pas : la pile,
 * les proportions, et le fait que rien ne recouvre la bande du haut.
 *
 * L'appel passe DEVANT la boîte de Lisa et celle du chat, qui vivent toutes
 * deux à z-index 1000 dans `main.css` — d'où 1200 ici. Il reste SOUS rien du
 * tout, et c'est le JavaScript qui l'empêche de monter au-dessus du bandeau
 * (46 px) et de la barre d'onglets : une règle de feuille de style ne saurait
 * pas le faire pour une fenêtre dont on choisit la position à la main.
 */

#visio-panneau {
  position: fixed;
  /* Un repli, le temps que le JavaScript pose la géométrie retenue. Jamais
     en haut : la bande d'onglets est à portée de ces 96 pixels. */
  top: 96px;
  left: 24px;
  width: 720px;
  height: 520px;
  z-index: 1200;
  display: flex;
  flex-direction: column;
  background: #ffffff;
  border: 1px solid #cbd5e1;
  border-radius: 12px;
  box-shadow: 0 18px 48px rgba(15, 23, 42, 0.28);
  padding: 12px 14px 14px;
  font-family: inherit;
  color: #0f172a;
  /* Une fenêtre qu'on redimensionne doit pouvoir rapetisser sans que son
     contenu la force à rester grande. */
  min-width: 300px;
  min-height: 220px;
  overflow: hidden;
}

#visio-panneau[data-ouvert="non"] { display: none; }

/* L'appel qui SONNE se distingue d'un appel en cours autrement que par la
   couleur seule : le filet s'épaissit et le titre change. La règle de la
   maison est qu'aucune information ne tienne à la seule teinte. */
#visio-panneau[data-sonne="oui"] {
  border-width: 3px;
  border-color: #047857;
}

/* ── L'en-tête, qui sert aussi de poignée de déplacement ─────────────────── */

.visio-entete {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
  flex: 0 0 auto;
  /* Le curseur dit que la barre se saisit. `user-select: none` évite qu'un
     déplacement sélectionne le titre au passage. */
  cursor: move;
  user-select: none;
  touch-action: none;
}

#visio-titre {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.visio-etat {
  font-size: 13px;
  color: #475569;
  white-space: nowrap;
}

/* La durée est en chiffres à chasse fixe : sans cela, elle sautille d'un
   pixel à chaque seconde et attire l'œil pour rien. */
.visio-duree {
  font-size: 13px;
  color: #334155;
  font-variant-numeric: tabular-nums;
  margin-left: auto;
}

.visio-fenetre-boutons {
  display: inline-flex;
  gap: 6px;
  flex: 0 0 auto;
}

.visio-bouton--fin {
  flex: 0 0 auto;
  min-width: 0;
  padding: 3px 9px;
  font-size: 12px;
}

/* ── Les trois états de la fenêtre ───────────────────────────────────────── */

/* RÉDUITE. L'appel continue : les liaisons, le micro et la caméra restent
   ouverts, et seule la présentation change. Ce qui subsiste est précisément
   ce qu'il faut pour le savoir d'un coup d'œil — le titre, l'état, la durée —
   plus de quoi se taire et raccrocher sans rouvrir. */
#visio-panneau[data-fenetre="reduite"] {
  top: auto;
  bottom: 16px;
  left: auto;
  right: 16px;
  width: auto;
  max-width: 420px;
  height: auto;
  min-height: 0;
  padding: 8px 12px;
}

/* « Cesser le partage » n'est PAS dans cette liste, et c'est le seul bouton
   d'action qui y échappe. Une fenêtre réduite pendant un partage d'écran
   laisserait sinon la capture en cours sans aucun moyen de l'arrêter depuis
   l'application — il resterait le bandeau du navigateur, qui n'est pas
   toujours visible selon le mode d'affichage. Une capture qu'on ne sait plus
   arrêter est exactement l'incident que ce chantier évite. */
#visio-panneau[data-fenetre="reduite"] .visio-corps,
#visio-panneau[data-fenetre="reduite"] .visio-poignee,
#visio-panneau[data-fenetre="reduite"] #visio-partager,
#visio-panneau[data-fenetre="reduite"] #visio-camera,
#visio-panneau[data-fenetre="reduite"] #visio-inviter,
#visio-panneau[data-fenetre="reduite"] #visio-ouvrir-reglages,
#visio-panneau[data-fenetre="reduite"] #visio-plein,
#visio-panneau[data-fenetre="reduite"] #visio-agrandir {
  display: none;
}

#visio-panneau[data-fenetre="reduite"] .visio-entete { margin-bottom: 0; }
#visio-panneau[data-fenetre="reduite"] .visio-commandes { margin-top: 6px; }
#visio-panneau[data-fenetre="reduite"] .visio-bouton { min-width: 0; }

/* Réduite ET en ligne : une pastille qui bat doucement. C'est un rappel, pas
   une information — tout ce qu'elle redit est déjà écrit à côté en toutes
   lettres, et `prefers-reduced-motion` l'immobilise plus bas. */
#visio-panneau[data-fenetre="reduite"][data-phase="EN_LIGNE"] .visio-etat::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 6px;
  border-radius: 50%;
  background: #047857;
  animation: visio-battement 2s ease-in-out infinite;
}

@keyframes visio-battement {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

/* PLEINE : la géométrie est posée en ligne par le JavaScript, sous la bande
   du haut dont il mesure la hauteur. Rien à faire ici que d'ôter les coins
   arrondis, qui n'ont pas de sens sur une fenêtre qui occupe la page. */
#visio-panneau[data-fenetre="pleine"] { border-radius: 8px; }

/* Le vrai plein écran du navigateur ignore la géométrie en ligne : il faut
   la neutraliser, et `!important` est ici le seul moyen de passer devant un
   attribut `style`. */
#visio-panneau:fullscreen {
  top: 0 !important;
  left: 0 !important;
  width: 100vw !important;
  height: 100vh !important;
  max-width: none;
  border-radius: 0;
  border: none;
}

/* ── Le corps ────────────────────────────────────────────────────────────── */

.visio-corps {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow-y: auto;
}

/* ── La grille des images ────────────────────────────────────────────────── */

/* Le nombre de cases est porté par `data-cases` et la disposition tranchée
   ici : une grille calculée en JavaScript se recalculerait à chaque relevé et
   ne saurait rien faire d'un redimensionnement de la fenêtre.

   À DEUX, côte à côte : c'est l'appel ordinaire, et l'on veut les deux
   visages aussi grands que possible. À TROIS et QUATRE, deux colonnes sur
   deux rangées, ce qui donne à chacun la même place — une disposition « un
   grand et deux petits » ferait du troisième arrivé un invité de second rang
   alors qu'il parle autant.

   À CINQ et SIX, trois colonnes sur deux rangées. Le principe ne change pas,
   et la règle non plus : AUCUNE CASE ORPHELINE. Six remplit la grille
   exactement ; cinq laisserait un trou en bas à droite, et un trou se lit
   comme une panne — « il manque quelqu'un, ça n'a pas marché ». Les deux
   cases de la rangée du bas s'étalent donc sur les trois colonnes, selon le
   même procédé qu'à trois.

   Pourquoi pas trois rangées de deux à six : les cases y seraient hautes et
   étroites, alors qu'un cadrage de visioconférence est large. Deux rangées de
   trois collent au format de l'image. */
.visio-grille {
  flex: 1 1 auto;
  min-height: 120px;
  display: grid;
  gap: 6px;
  background: #0f172a;
  border-radius: 8px;
  padding: 6px;
  overflow: hidden;
}

.visio-grille[data-cases="0"],
.visio-grille[data-cases="1"] { grid-template-columns: 1fr; }
.visio-grille[data-cases="2"] { grid-template-columns: 1fr 1fr; }
.visio-grille[data-cases="3"],
.visio-grille[data-cases="4"] {
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}
/* À six, trois colonnes sur deux rangées : la grille est pleine, rien à
   rattraper. */
.visio-grille[data-cases="6"] {
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

/* À trois, la dernière case prend les deux colonnes : trois cases dans une
   grille de quatre laisseraient un trou, et un trou se lit comme une panne. */
.visio-grille[data-cases="3"] .visio-case:nth-child(3) { grid-column: span 2; }

/* À cinq, même remède à l'échelle du dessus. La grille est découpée en SIX
   colonnes fines : les trois cases du haut en prennent deux chacune, les deux
   du bas en prennent trois. Personne n'est orphelin, et les deux du bas sont
   simplement un peu plus larges — ce qui se lit comme une disposition, pas
   comme une absence. */
.visio-grille[data-cases="5"] {
  grid-template-columns: repeat(6, 1fr);
  grid-template-rows: 1fr 1fr;
}
.visio-grille[data-cases="5"] .visio-case { grid-column: span 2; }
.visio-grille[data-cases="5"] .visio-case:nth-child(4),
.visio-grille[data-cases="5"] .visio-case:nth-child(5) { grid-column: span 3; }

.visio-case {
  position: relative;
  margin: 0;
  min-width: 0;
  min-height: 0;
  background: #1e293b;
  border-radius: 6px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.visio-image {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  background: #1e293b;
}

/* Pas d'image : on n'affiche pas un rectangle noir muet. La case garde sa
   place et dit pourquoi elle est vide — « Audio seul », « Connexion… »,
   « Liaison impossible avec ce poste ». */
.visio-case[data-image="non"] .visio-image { display: none; }

.visio-case-nom {
  position: absolute;
  left: 6px;
  bottom: 6px;
  max-width: calc(100% - 12px);
  padding: 2px 7px;
  font-size: 12px;
  color: #f8fafc;
  background: rgba(15, 23, 42, 0.72);
  border-radius: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.visio-case-mot {
  margin: 0;
  padding: 0 10px;
  font-size: 13px;
  color: #cbd5e1;
  text-align: center;
}

.visio-case-mot:empty { display: none; }

/* On se regarde comme dans un miroir : faute de quoi lever la main droite la
   fait paraître à gauche et le geste devient désorientant. L'image ENVOYÉE
   n'est pas retournée — ce retournement est purement visuel. */
.visio-case[data-pair="moi"] .visio-image { transform: scaleX(-1); }

/* ── Sa propre case pendant un partage d'écran ───────────────────────────── */

/* Deux règles, et aucune n'est cosmétique.

   LE MIROIR SAUTE. Le retournement ci-dessus rend un visage naturel ; il rend
   un écran partagé parfaitement illisible, texte inversé compris. C'est le
   genre de détail qu'on ne voit pas en écrivant la fonction et qui saute aux
   yeux à la première démonstration.

   `contain` ET NON `cover`. Un visage se recadre sans dommage — on perd les
   bords, où il n'y a rien. Un écran recadré perd ses bords, c'est-à-dire la
   barre d'outils, la première colonne du tableau, le menu qu'on montrait. À
   deux participants une case fait presque un carré, et `cover` y amputerait
   un écran 16/9 de plus du tiers de sa largeur. On laisse donc des bandes
   noires : une bande noire se comprend, un tableau tronqué se croit complet.

   Ces deux règles ne valent QUE pour sa propre case, parce qu'elle est la
   seule dont on sache ce qu'elle porte. Voir l'en-tête de
   `public/js/chatVisio.js` : rien n'annonce à l'autre bout qu'une case montre
   un écran, et le lui dire demanderait une sorte de signal de plus. */
.visio-case[data-pair="moi"][data-partage="oui"] .visio-image {
  transform: none;
  object-fit: contain;
  background: #0f172a;
}

/* Le bouton qui arrête le partage se distingue sans être rouge : le rouge est
   pris par « Raccrocher », à quelques pixels de là. Le filet ambre dit « il
   se passe quelque chose », pas « attention, destruction ». Et il ne tient
   pas à la seule couleur : le bouton n'EXISTE que pendant un partage. */
#visio-partage-arreter {
  background: #fef3c7;
  border-color: #d97706;
  color: #78350f;
}

#visio-partage-arreter:hover { background: #fde68a; }

.visio-case[data-pair="moi"] { outline: 2px solid #334155; outline-offset: -2px; }

/* ── Ce qui se dit ───────────────────────────────────────────────────────── */

.visio-mot {
  flex: 0 0 auto;
  margin: 0;
  padding: 9px 11px;
  background: #fef3c7;
  border-left: 3px solid #d97706;
  border-radius: 4px;
  font-size: 13px;
  line-height: 1.45;
  color: #78350f;
}

.visio-mot[hidden] { display: none; }

/* ── Les volets : ajouter quelqu'un, régler la caméra et le son ──────────── */

.visio-volet {
  flex: 0 0 auto;
  padding: 10px 12px;
  background: #f8fafc;
  border: 1px solid #e2e8f0;
  border-radius: 6px;
}

.visio-volet[hidden] { display: none; }

.visio-volet-titre {
  margin: 0 0 6px;
  font-size: 13px;
  font-weight: 600;
}

.visio-volet-mot {
  margin: 4px 0 8px;
  font-size: 12px;
  line-height: 1.45;
  color: #334155;
}

.visio-volet-mot:empty { display: none; }

.visio-ajout-liste {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.visio-ajout-bouton { flex: 0 1 auto; }

/* Un bouton d'invitation désactivé reste LISIBLE : il est en cours d'envoi,
   pas interdit. Le gris pâle habituel ferait croire à un refus silencieux,
   et c'est précisément ce que ce chantier évite. */
.visio-ajout-bouton[disabled] {
  opacity: 0.7;
  cursor: progress;
}

.visio-etiquette {
  display: block;
  margin: 8px 0 3px;
  font-size: 12px;
  font-weight: 600;
  color: #334155;
}

.visio-choix {
  display: block;
  width: 100%;
  padding: 6px 8px;
  font: inherit;
  font-size: 13px;
  color: #0f172a;
  background: #ffffff;
  border: 1px solid #cbd5e1;
  border-radius: 4px;
}

/* Là où `setSinkId` n'existe pas, le menu est retiré et remplacé par une
   phrase : un réglage qui ne règle rien est pire qu'un réglage absent. */
.visio-choix[hidden] { display: none; }

/* ── L'essai, avant d'appeler ────────────────────────────────────────────── */

.visio-essai {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid #e2e8f0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.visio-essai-image {
  width: 180px;
  max-width: 100%;
  border-radius: 6px;
  background: #1e293b;
  transform: scaleX(-1);
}

.visio-essai-image[hidden] { display: none; }

/* La barre de niveau ILLUSTRE ce que le texte dit déjà. Elle n'est jamais la
   seule information : « Le micro capte » est écrit juste en dessous, et la
   barre porte un `aria-label` chiffré. */
.visio-niveau {
  flex: 1 1 140px;
  height: 10px;
  background: #e2e8f0;
  border-radius: 5px;
  overflow: hidden;
}

.visio-niveau-barre {
  display: block;
  width: 0%;
  height: 100%;
  background: #047857;
}

/* ── Les commandes ───────────────────────────────────────────────────────── */

.visio-commandes {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}

.visio-bouton {
  flex: 1 1 auto;
  min-width: 118px;
  padding: 9px 12px;
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  color: #0f172a;
  background: #f1f5f9;
  border: 1px solid #cbd5e1;
  border-radius: 6px;
  cursor: pointer;
}

.visio-bouton:hover { background: #e2e8f0; }

.visio-bouton[hidden] { display: none; }

.visio-bouton--vert {
  background: #047857;
  border-color: #047857;
  color: #ffffff;
}
.visio-bouton--vert:hover { background: #036249; }

/* La phrase qui explique pourquoi l'image se resserre quand on est nombreux.
   Discrète, sous la grille : c'est une explication qu'on lit une fois, pas un
   indicateur à surveiller. Masquée par l'attribut `hidden` à deux, où il n'y
   a rien à justifier. */
.visio-debit {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.35;
  color: #64748b;
}
.visio-debit[hidden] { display: none; }

/* La reprise après une coupure : la grille est vide, il n'y a rien à
   regarder, et c'est le texte qui porte toute l'information. On lui laisse la
   place plutôt que d'étirer un cadre noir sur une image qui n'existe pas. */
#visio-panneau[data-phase="REPRISE"] .visio-grille { display: none; }

#visio-panneau[data-phase="REPRISE"] .visio-mot {
  font-size: 0.95rem;
  line-height: 1.5;
  padding: 16px 4px;
}

.visio-bouton--rouge {
  background: #b91c1c;
  border-color: #b91c1c;
  color: #ffffff;
}
.visio-bouton--rouge:hover { background: #991b1b; }

/* Micro coupé : l'état se lit sur le bouton lui-même, qui change de libellé,
   ET par ce filet. `aria-pressed` le dit à qui n'y regarde pas. */
#visio-micro[aria-pressed="true"],
#visio-camera[aria-pressed="true"] {
  background: #fee2e2;
  border-color: #b91c1c;
  color: #7f1d1d;
}

/* ── La poignée de redimensionnement ─────────────────────────────────────── */

/* Dessinée plutôt que figurée par un caractère : une glyphe dépendrait de la
   police installée. Elle est atteignable au clavier — `tabindex` dans le
   balisage, les flèches dans le JavaScript —, sans quoi « modifiable en
   taille » ne vaudrait que pour ceux qui ont une souris. */
.visio-poignee {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 20px;
  height: 20px;
  cursor: nwse-resize;
  touch-action: none;
  background:
    linear-gradient(135deg, transparent 0 48%, #94a3b8 48% 56%, transparent 56% 70%,
                    #94a3b8 70% 78%, transparent 78%);
}

#visio-panneau[data-fenetre="pleine"] .visio-poignee,
#visio-panneau:fullscreen .visio-poignee { display: none; }

/* ── La greffe dans l'en-tête du chat ────────────────────────────────────── */

.visio-greffe {
  display: inline-flex;
  gap: 6px;
  margin-left: auto;
}

.visio-greffe[hidden] { display: none; }

.visio-greffe-bouton {
  padding: 3px 9px;
  font: inherit;
  font-size: 12px;
  color: #0f172a;
  background: #f1f5f9;
  border: 1px solid #cbd5e1;
  border-radius: 4px;
  cursor: pointer;
}

.visio-greffe-bouton:hover { background: #e2e8f0; }

/* ── Clavier et mouvement ────────────────────────────────────────────────── */

/* L'anneau de focus est posé ici plutôt que laissé au navigateur : les
   boutons colorés en aplat avalent l'anneau par défaut de Chrome, et une
   commande qui ouvre un micro doit se voir au clavier. */
#visio-panneau button:focus-visible,
#visio-panneau select:focus-visible,
#visio-panneau .visio-poignee:focus-visible {
  outline: 3px solid #1d4ed8;
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  #visio-panneau, #visio-panneau * {
    transition-duration: 0.0001s !important;
    animation-duration: 0.0001s !important;
    animation-iteration-count: 1 !important;
  }
}

/* Sur un écran étroit, deux colonnes donneraient des vignettes de cent
   pixels. On empile, et la fenêtre prend la largeur — le JavaScript la
   borne de toute façon sous la bande du haut. */
@media (max-width: 560px) {
  #visio-panneau { padding: 10px 10px 12px; }
  .visio-grille[data-cases="2"],
  .visio-grille[data-cases="3"],
  .visio-grille[data-cases="4"] {
    grid-template-columns: 1fr;
    grid-template-rows: none;
  }
  .visio-grille[data-cases="3"] .visio-case:nth-child(3) { grid-column: auto; }
  /* À cinq et six sur un téléphone, une colonne donnerait six vignettes à
     faire défiler. Deux colonnes gardent tout le monde à l'écran, et aucune
     case n'y est orpheline puisque la sixième complète la paire. */
  .visio-grille[data-cases="5"],
  .visio-grille[data-cases="6"] {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: none;
  }
  .visio-grille[data-cases="5"] .visio-case,
  .visio-grille[data-cases="5"] .visio-case:nth-child(4) { grid-column: auto; }
  .visio-grille[data-cases="5"] .visio-case:nth-child(5) { grid-column: span 2; }
  .visio-bouton { min-width: 0; flex-basis: calc(50% - 4px); }
  .visio-essai-image { width: 100%; }
}

/* Un appel ne s'imprime pas. */
@media print {
  #visio-panneau, .visio-greffe { display: none !important; }
}
