/* ==========================================================================
   GIFR, refonte 2026 : page « Lives officiels »
   --------------------------------------------------------------------------
   A charger APRES gi-tokens.css et gi-accueil.css. Ne redefinit aucun token.

   Reprend telles quelles les briques deja portees : .gi-panel, .gi-count,
   .gi-dot-live, .gi-btn, .gi-corners, .gi-grain, .gi-vignette.
   Ce fichier n'ajoute que ce qui manquait : la scene, c'est-a-dire le lecteur
   et le chat cote a cote.

   LA PAGE NE PORTE QUE CA, et c'est un choix du 29/07/2026 : une section de
   codes et une grille de rediffusions avaient ete dessinees, puis retirees.
   Personne n'aura le temps de saisir des codes pendant une emission, et une
   promesse tenue a moitie vaut moins que pas de promesse. Si elles reviennent
   un jour, elles sont dans l'historique de ce fichier.

   Paliers : 1280, 1080, 760, 620, 400. Ce sont ceux de gi-accueil.css, aucun
   palier neuf n'a ete invente.

   QUATRE ETATS DANS LA MAQUETTE, un seul balisage : `data-live="aucun" |
   "attente" | "direct" | "fini"` pose sur <body>, et un filtre CSS qui n'en
   montre qu'un. SUR LE SITE, NON : le serveur ne rend que la variante courante,
   il n'y a pas de variante cachee dans la page. Le filtre reste pour que la
   maquette vive sans WordPress.
   ========================================================================== */

/* ==========================================================================
   L1. L'EN-TETE DE PAGE A ETE RETIREE LE 30/07/2026
   --------------------------------------------------------------------------
   Un bandeau portait l'intitule, le titre « Lives officiels », un chapo, un
   ornement et le panneau d'horaire. Le panneau est parti le matin, faute d'un
   planning Twitch exploitable ; le bandeau qui restait paraissait vide, et
   l'utilisateur l'a retire dans la journee. La page commence donc directement
   sur la scene.

   LE <h1> A DEMENAGE, il n'a pas disparu : c'est le titre de la barre du
   lecteur, `.gi-live-bar__title`, qui le porte maintenant. Une page sans titre
   de niveau 1 est un trou pour le referencement et pour les lecteurs d'ecran,
   et ce n'etait pas un prix a payer pour gagner de la place.

   Tout le CSS de ce bandeau est dans l'historique de ce fichier. Ce qui a ete
   garde : `.gi-badge`, le filtre `[data-live-only]` et `.gi-live-when`, qui
   servent encore -- la pastille dans la barre, le filtre pour la maquette, et
   le panneau d'horaire que son raccourci peut remettre le jour ou la chaine
   officielle remplira son planning.
   ========================================================================== */

/* ==========================================================================
   L2. LES ETATS : PASTILLES, FILTRE ET PANNEAU D'HORAIRE
   ========================================================================== */
.gi-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0.34rem 0.8rem;
  border-radius: var(--r-pill);
  font-family: var(--gi-font-display);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
}
.gi-badge--live {
  color: #F5AE99;
  background: rgba(228, 105, 74, 0.16);
  box-shadow: inset 0 0 0 1px rgba(228, 105, 74, 0.40);
}
.gi-badge--soon {
  color: var(--gi-gold-300);
  background: rgba(198, 165, 93, 0.14);
  box-shadow: inset 0 0 0 1px rgba(198, 165, 93, 0.36);
}
.gi-badge--off {
  color: var(--gi-sand-300);
  background: rgba(241, 233, 218, 0.06);
  box-shadow: inset 0 0 0 1px rgba(241, 233, 218, 0.14);
}
.gi-badge svg { width: 13px; height: 13px; }

/* Chaque etat ne montre que ses propres blocs.

   DEUX CROCHETS POUR LA MEME CHOSE, ET C'EST VOULU : `data-live` sur <body>
   dans la maquette, classe `gifr-live-*` sur le site, parce que WordPress pose
   des classes de corps et non des attributs. Les deux jeux de selecteurs
   coexistent pour que la maquette reste ouvrable sans WordPress. */
[data-live="aucun"]   [data-live-only]:not([data-live-only~="aucun"]),
[data-live="attente"] [data-live-only]:not([data-live-only~="attente"]),
[data-live="direct"]  [data-live-only]:not([data-live-only~="direct"]),
[data-live="fini"]    [data-live-only]:not([data-live-only~="fini"]),
.gifr-live-aucun   [data-live-only]:not([data-live-only~="aucun"]),
.gifr-live-attente [data-live-only]:not([data-live-only~="attente"]),
.gifr-live-direct  [data-live-only]:not([data-live-only~="direct"]),
.gifr-live-fini    [data-live-only]:not([data-live-only~="fini"]) { display: none !important; }

/* Le panneau d'horaire reutilise .gi-panel : aucun fond neuf. */
.gi-live-when__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
}
.gi-live-when__title {
  font-family: var(--gi-font-title);
  font-size: var(--fs-md);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--gi-sand-50);
}
.gi-live-when__date {
  margin-top: 0.15rem;
  font-size: var(--fs-xs);
  color: var(--gi-text-faint);
}
/* Le compte a rebours est celui du panneau de bannieres, .gi-count, repris
   sans une ligne de neuf. Il n'a ici pas de filet superieur puisqu'il ouvre
   le bloc et ne suit aucune liste. */
.gi-live-when .gi-count { margin-top: var(--sp-4); }

/* ==========================================================================
   L3. LA SCENE : LECTEUR A GAUCHE, CHAT A DROITE
   --------------------------------------------------------------------------
   Deux colonnes, chacune une pile de deux blocs : une barre de tete puis un
   corps. Les deux barres ont la meme hauteur minimale, donc les deux corps
   demarrent et finissent au meme pixel sans qu'aucune hauteur ne soit ecrite
   en dur.

   LA HAUTEUR VIENT DU LECTEUR, jamais du chat. Le lecteur porte un
   `aspect-ratio` : sa hauteur se deduit de sa largeur. Le chat, lui, ne doit
   surtout pas grandir avec son contenu, sinon il etirerait la rangee et
   casserait le format du lecteur. D'ou le `min-height: 0` et le corps de chat
   en position absolue dans son cadre.
   ========================================================================== */
.gi-live {
  position: relative;

  /* --- LARGEUR DE LA SCENE, decidee ici et nulle part ailleurs ------------
     La scene ne suit PAS le conteneur large de 1760 px du reste du site :
     elle va jusqu'aux bords, a une marge courte pres. Un lecteur video n'est
     pas une colonne de lecture, rien ne justifie de le brider a la longueur
     de ligne confortable d'un paragraphe. Choix du 29/07/2026.

     MAIS ELLE NE VA PAS JUSQU'A DEBORDER DE L'ECRAN EN HAUTEUR. Le lecteur
     est en 16:9 : chaque pixel de largeur en coute neuf seiziemes en hauteur.
     Sur un ecran large et bas, la pleine largeur mettrait l'image plus haute
     que la fenetre. D'ou un BUDGET DE HAUTEUR, `--gi-live-h-max`, dont on
     deduit la largeur maximale de la scene entiere.

     LE PLAFOND EST SUR LA SCENE, PAS SUR LE LECTEUR, et c'est ce qui a change
     apres mesure : plafonner le lecteur seul le centrait dans sa colonne et
     ouvrait un vide entre l'image et le chat. Plafonner la scene garde les
     deux colles et centre l'ensemble. */
  --gi-live-chat-w: 380px;
  --gi-live-h-max: min(82vh, 1100px);
  --gi-live-scene-w: calc(var(--gi-live-h-max) * 16 / 9
                          + var(--gi-live-chat-w) + var(--sp-5));

  /* HAUTEUR COMMUNE DES DEUX BARRES DE TETE. Mesuree, pas devinee : la barre
     de gauche rend 50 px de contenu, celle du chat 47. Sans ce plancher
     partage, les deux corps demarraient a 40 px d'ecart et le haut du chat
     flottait sous le haut du lecteur. */
  --gi-live-head-h: 3.25rem;
  /* `isolation: isolate` ET LE CANEVAS A ZERO, pas a -1. La section forme son
     propre contexte d'empilement, donc un rang negatif enverrait les
     poussieres derriere le fond de page, ou personne ne les verrait. Zero les
     place au-dessus du fond et sous le grain, le vignetage et la scene, qui
     valent 2, 3 et 4. Meme raisonnement que le corps d'article. */
  isolation: isolate;
  padding-block: clamp(1.6rem, 1.2rem + 1.8vw, 2.6rem);

  /* LE FOND EST ECRIT ICI, ET NON LAISSE AU FOND DE PAGE. Le premier jet n'en
     posait aucun : dans la maquette, le `--gi-ink-900` du <body> traversait et
     tout allait bien. Sur le site, Divi peint chacune de ses sections en blanc
     (`.et_pb_section { background-color: #fff }`), et la scene s'est retrouvee
     sur fond blanc, poussieres comprises.

     Le degrade PART de `--gi-ink-900`, la couleur ou finit celui du bandeau
     juste au-dessus : la couture entre les deux sections ne se voit pas. */
  background:
    radial-gradient(58% 90% at 84% 2%, rgba(177, 137, 221, 0.09), transparent 68%),
    radial-gradient(50% 80% at 6% 98%, rgba(198, 165, 93, 0.07), transparent 70%),
    linear-gradient(180deg, var(--gi-ink-900), var(--gi-ink-950) 100%);
}

/* La gouttiere du conteneur tombe a une marge courte, POUR CETTE SECTION
   SEULEMENT : le bandeau de titre garde la sienne, il porte du texte. Sans
   cette regle, `max-width: none` ne servirait a rien, les 2,5rem de gouttiere
   laisseraient 80 px de vide contre les bords. */
.gi-live > .gi-container--wide {
  max-width: none;
  padding-inline: clamp(0.75rem, 0.4rem + 0.6vw, 1.25rem);
}

/* LES POUSSIERES DU FOND. Le canevas est pose par la table `FONDS` de
   gi-ui.js, pas ecrit dans le balisage : un seul endroit decide quels fonds en
   portent, pour tout le site. Le moteur se coupe tout seul sous 900 px de
   large et sur `prefers-reduced-motion`.

   `inset: 0` ET NON collant, contrairement au corps d'article et aux archives.
   Ces deux-la font plusieurs milliers de pixels de haut, d'ou le canevas
   collant d'un ecran. La scene des lives ne depasse jamais un ecran et demi :
   l'etirer coute peu et evite la mecanique de collage. */
.gi-live__particules {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.gi-live-stage {
  /* Meme plafond et meme centrage que la note qui la suit : leurs bords
     gauche et droit doivent tomber au meme pixel. */
  max-width: var(--gi-live-scene-w);
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--gi-live-chat-w);
  gap: var(--sp-5);
  align-items: stretch;
}

.gi-live-main,
.gi-live-side {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  min-width: 0;
  min-height: 0;
}

/* --- Barre de tete, commune aux deux colonnes --- */
.gi-live-bar {
  display: flex;
  align-items: center;
  gap: var(--sp-3) var(--sp-4);
  flex-wrap: wrap;
  min-height: var(--gi-live-head-h);
}
.gi-live-bar__text { min-width: 0; flex: 1 1 14rem; }
.gi-live-bar__title {
  /* C'EST LE <h1> DE LA PAGE depuis que le bandeau est parti. La remise a plat
     est donc obligatoire et non cosmetique : un theme, et Divi en particulier,
     donne a un <h1> sa propre taille, sa propre graisse, une marge et un
     `padding-bottom`. Tout est redeclare ici, y compris ce qui semble aller de
     soi, parce que la valeur heritee depend du theme et pas de nous. */
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
  font-family: var(--gi-font-title);
  font-size: var(--fs-md);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--gi-sand-50);
}
.gi-live-bar__meta {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  margin-top: 0.15rem;
  font-size: var(--fs-xs);
  color: var(--gi-text-faint);
}
.gi-live-bar__meta svg { width: 13px; height: 13px; }
.gi-live-bar__tools {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  margin-left: auto;
}

/* --- Le lecteur --- */
.gi-live-player {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  /* AUCUN PLAFOND ICI, il est sur la scene. Un `max-height` pose sur le
     lecteur seul le centre dans sa colonne et ouvre un vide entre l'image et
     le chat : mesure, puis deplace. Si on en remet un un jour, il faut
     imperativement le doubler d'un `max-width` calcule depuis la meme valeur,
     sinon le format 16:9 se casse et l'image s'etire. */
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--gi-ink-950);
  box-shadow: inset 0 0 0 1px var(--gi-line), var(--sh-3);
}
/* MEME REGLE QU'AU CADRE DE CHAT, ET POUR LA MEME RAISON : pas de combinateur
   d'enfant. Sur le site, l'iframe est rendue par le raccourci `[gifr_live
   bloc="lecteur"]` a l'interieur du `.et_pb_text_inner` de Divi. Elle n'est
   donc jamais fille directe de `.gi-live-player`, qui est le module. */
.gi-live-player iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Substitut de maquette. N'existe QUE dans la maquette : sur le site, c'est
   l'iframe Twitch qui occupe ce cadre. Garde le meme format pour que la
   mesure des hauteurs reste valable. */
.gi-live-mock {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: var(--sp-4);
  text-align: center;
  padding: var(--sp-5);
  background:
    radial-gradient(60% 70% at 50% 40%, rgba(177, 137, 221, 0.20), transparent 70%),
    linear-gradient(150deg, var(--gi-ink-800), var(--gi-ink-950));
}
.gi-live-mock__play {
  display: grid;
  place-items: center;
  width: 76px;
  height: 76px;
  border-radius: 50%;
  color: var(--gi-gold-300);
  background: rgba(8, 14, 20, 0.55);
  box-shadow: inset 0 0 0 1px var(--gi-line-strong), var(--glow-gold);
}
.gi-live-mock__play svg { width: 30px; height: 30px; }
.gi-live-mock__label {
  font-family: var(--gi-font-display);
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--gi-sand-200);
}
.gi-live-mock__hint {
  max-width: 40ch;
  font-size: var(--fs-xs);
  color: var(--gi-text-faint);
}

/* Etat hors emission : meme cadre, fond plus sobre, un appel a l'action. */
.gi-live-mock--off {
  background:
    radial-gradient(60% 70% at 50% 30%, rgba(198, 165, 93, 0.12), transparent 70%),
    linear-gradient(150deg, var(--gi-ink-850), var(--gi-ink-950));
}

/* --- Le chat --- */
/* .gi-panel donne le fond et le filet. On ne reprend ici que la mise en
   colonne et le rognage du cadre. */
.gi-live-chat.gi-panel {
  padding: var(--sp-4);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  /* `flex: 1` ET `min-height: 0`. Le premier fait remplir la rangee de
     grille, sans quoi le panneau s'arrete a la hauteur de son texte et
     laisse un trou de 250 px sous le chat. Le second l'autorise a etre plus
     court que son contenu, ce qui est la condition pour que le cadre
     defile au lieu de pousser. */
  flex: 1 1 auto;
  min-height: 0;
}
.gi-live-chat__head {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding-bottom: var(--sp-3);
  min-height: var(--gi-live-head-h);
  border-bottom: 1px solid var(--gi-line-soft);
}
/* Interlignes resserres sur les deux lignes de tete : c'est ce qui fait
   tenir le bloc sous le plancher commun de --gi-live-head-h. */
.gi-live-chat__title {
  font-family: var(--gi-font-display);
  font-size: 0.92rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: var(--ls-caps-md);
  color: var(--gi-sand-50);
}
.gi-live-chat__sub {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: 0.1rem;
  font-size: var(--fs-xs);
  line-height: 1.3;
  color: var(--gi-text-faint);
}
.gi-live-chat__dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--el-dendro);
  flex: none;
}
/* --- Le selecteur de chat ---
   Deux boutons dans une pilule, l'actif en or plein. Meme vocabulaire visuel
   que la barre de maquette et que les etiquettes de categorie : rien de neuf
   a apprendre pour le visiteur. */
.gi-live-chat__id { min-width: 0; }
.gi-chat-switch {
  display: flex;
  gap: 2px;
  margin-left: auto;
  flex: none;
  padding: 2px;
  border-radius: var(--r-pill);
  background: rgba(8, 14, 20, 0.55);
  box-shadow: inset 0 0 0 1px var(--gi-line-soft);
}
.gi-chat-switch button {
  padding: 0.3rem 0.72rem;
  border-radius: var(--r-pill);
  font-family: var(--gi-font-display);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--gi-sand-300);
  cursor: pointer;
  transition: color var(--t-fast), background-color var(--t-fast);
}
.gi-chat-switch button:hover { color: var(--gi-sand-50); }
.gi-chat-switch button[aria-pressed="true"] {
  color: var(--gi-ink-950);
  background: linear-gradient(160deg, var(--gi-gold-300), var(--gi-gold-500));
}

/* CHAQUE CHAT NE MONTRE QUE SES PROPRES BLOCS. Meme mecanique que le filtre
   des etats d'emission : un attribut sur le panneau, un `data-chat-only` sur
   ce qui en depend, et pas une ligne de JS pour montrer ou cacher.

   Le cadre masque l'est en `display: none`, donc il ne mesure rien et ne
   dispute pas sa hauteur a l'autre : celui qui reste prend toute la place
   disponible par son `flex: 1 1 0`. */
[data-chat="gifr"]   [data-chat-only]:not([data-chat-only~="gifr"]),
[data-chat="twitch"] [data-chat-only]:not([data-chat-only~="twitch"]) { display: none !important; }

/* Le pied de panneau porte un lien : sur fond sombre il est en or, jamais en
   bronze, l'inverse de la regle du papier. */
.gi-live-chat__foot a { color: var(--gi-gold-400); text-decoration: underline; }
.gi-live-chat__foot a:hover { color: var(--gi-gold-200); }

/* La pastille du chat officiel prend la teinte de Twitch, celle du notre reste
   verte : la couleur dit lequel des deux on regarde, avant meme de lire. */
.gi-live-chat__dot--tw { background: var(--el-electro); }

/* Les pseudonymes du chat officiel ne sont pas dores : l'or est notre accent,
   pas celui de Twitch. */
.gi-msg__who--tw { color: var(--el-electro); }

/* LE CADRE. C'est lui qui recevra l'embarquement WidgetBot. Il ne mesure
   jamais son contenu : `flex: 1 1 0` plus `min-height: 0`, et le corps du
   chat en absolu. Sans cela, une conversation longue etirerait la colonne et
   le lecteur perdrait son format 16:9. */
.gi-live-chat__frame {
  position: relative;
  flex: 1 1 0;
  min-height: 16rem;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: rgba(8, 14, 20, 0.55);
  box-shadow: inset 0 0 0 1px var(--gi-line-soft);
}
/* PAS DE COMBINATEUR D'ENFANT ICI, ET C'EST UNE LECON DU PORTAGE. Sur le site,
   ces trois pieces ne sont PAS des enfants directs du cadre : le module Texte
   de Divi glisse son `.et_pb_text_inner` entre le module et son contenu, et le
   raccourci qui rend l'iframe ajoute encore son enveloppe. `display: contents`
   efface ces enveloppes a l'affichage mais NE CHANGE RIEN AUX SELECTEURS : un
   `>` ne peut pas les traverser. Ecrit en enfant direct, ce bloc marchait dans
   la maquette et ne s'appliquait jamais sur le site, ou l'iframe se posait
   alors en bloc de 150 px de haut au lieu de remplir le cadre. */
.gi-live-chat__frame iframe,
.gi-live-chat__frame .gi-live-chat__wb,
.gi-live-chat__frame .gi-live-chat__scroll {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
/* ROGNAGE DE L'EN-TETE DE WIDGETBOT, pour retirer le bouton hamburger.
   -------------------------------------------------------------------------
   LE PROBLEME. L'embarquement WidgetBot affiche sa propre barre de titre, avec
   un hamburger qui ouvre la LISTE DES SALONS du serveur. Le visiteur peut donc
   partir lire n'importe quel salon public du Discord GIFR depuis la page des
   lives, ce qui n'est pas l'objectif : on veut le salon des lives, et lui seul.

   POURQUOI ON EN EST REDUITS A DU ROGNAGE. WidgetBot n'expose AUCUNE option
   pour ca. Les attributs documentes sont server, channel, thread, username,
   avatar, token, notifications, notificationtimeout, width, height et shard :
   rien sur la navigation. L'adresse de l'iframe est
   `e.widgetbot.io/channels/<serveur>/<salon>` et n'accepte aucun parametre. Et
   c'est un iframe d'un autre domaine : notre CSS n'entre pas dedans, il n'y a
   pas de « masquer la barre » possible depuis l'exterieur.

   Ce qui reste faisable est de la faire sortir du cadre par le haut, et de
   laisser `overflow: hidden` du cadre la couper. Le bouton disparait ET devient
   incliquable, ce qu'un simple cache par-dessus n'aurait pas garanti.

   C'EST L'ENVELOPPE QUI EST ROGNEE, PAS L'ELEMENT <widgetbot>, et c'est la
   correction du 30/07 au soir. Le premier jet decalait et agrandissait
   `<widgetbot>` lui-meme : le decalage passait, l'agrandissement non, et il
   manquait exactement une hauteur d'en-tete en bas du cadre. Motif : le script
   de WidgetBot recopie les attributs `width` et `height` de l'element en STYLE
   EN LIGNE, et un style en ligne gagne sur toute regle de feuille. Notre
   `height: calc(100% + ...)` etait donc ecrase par un `height: 100%`.

   Une enveloppe a nous, que le script ne touche pas, porte le rognage ; l'element
   remplit cette enveloppe, y compris quand il est dimensionne en ligne. Aucun
   `!important` a placer, et rien qui depende de ce que le script decide.

   ON NE PERD RIEN D'UTILE : cette barre ne portait que le nom du salon, que
   notre propre en-tete de panneau annonce deja, et les deux boutons de
   navigation dont on ne veut pas.

   UN SEUL NOMBRE A REGLER, et il est ici. 48 px est la hauteur d'un en-tete de
   salon Discord, que WidgetBot reprend. S'il en reste une lisiere en haut du
   cadre, augmenter ; si le premier message est coupe, diminuer.

   ET LA LIMITE, A SAVOIR : c'est le rendu d'un service tiers. S'il change sa
   mise en page, ce nombre devient faux. La seule maitrise reelle est cote
   Discord : le hamburger ne liste que les salons LISIBLES par le visiteur, donc
   par `@everyone` pour un visiteur non connecte. Resserrer les permissions
   `@everyone` du serveur est le seul verrou qui ne depende pas de WidgetBot. */
.gi-live-chat__frame {
  --gi-wb-entete: 48px;
}
.gi-live-chat__frame .gi-live-chat__wb {
  top: calc(-1 * var(--gi-wb-entete));
  bottom: auto;
  height: calc(100% + var(--gi-wb-entete));
  z-index: 2;
}
/* L'element remplit son enveloppe. Le `display: block` est indispensable :
   <widgetbot> est un element inconnu du navigateur, donc en ligne par defaut, et
   une hauteur ne s'applique pas a un element en ligne.

   IL RESTE SANS FOND, et c'est le repli sans une ligne de JS : le faux fil de
   discussion est dessous, dans le flux, et cette enveloppe par-dessus. Si le
   script du CDN ne charge pas, aucun iframe n'est cree, tout reste transparent
   et c'est le faux fil qu'on voit. Donner un fond ici ferait perdre ce filet. */
.gi-live-chat__wb widgetbot {
  display: block;
  width: 100%;
  height: 100%;
}
.gi-live-chat__wb widgetbot iframe {

  width: 100% !important;
  height: 100% !important;
  border: 0;
  display: block;
}
.gi-live-chat__scroll {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding: var(--sp-4);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.gi-live-chat__foot {
  font-size: 0.68rem;
  line-height: 1.5;
  color: var(--gi-sand-600);
}

/* Faux messages : illustration de maquette. L'interieur du chat reel est
   peint par WidgetBot, pas par cette feuille. Ce bloc sert a juger le cadre,
   pas les bulles. */
.gi-msg { display: flex; gap: var(--sp-3); }
.gi-msg__avatar {
  display: grid;
  place-items: center;
  width: 30px; height: 30px;
  flex: none;
  border-radius: 50%;
  overflow: hidden;
  background: linear-gradient(150deg, var(--thumb-a, var(--el-hydro)), var(--thumb-b, var(--el-cryo)));
}
.gi-msg__avatar svg { width: 18px; height: 18px; color: rgba(8, 14, 20, 0.6); }
.gi-msg__body { min-width: 0; }
.gi-msg__who {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  flex-wrap: wrap;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--gi-gold-300);
}
.gi-msg__when { font-size: 0.62rem; font-weight: 400; color: var(--gi-sand-600); }
.gi-msg__text {
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--gi-sand-200);
  overflow-wrap: anywhere;
}
.gi-msg__text code {
  padding: 0.05rem 0.3rem;
  border-radius: var(--r-xs);
  font-family: var(--gi-font-display);
  font-size: 0.8em;
  letter-spacing: var(--ls-wide);
  color: var(--gi-gold-200);
  background: rgba(198, 165, 93, 0.14);
}

/* ==========================================================================
   L4. RETOUR AU CONTENEUR NORMAL
   --------------------------------------------------------------------------
   La page s'ouvre en large. `data-etroit` sur <body>, pose par le bouton de la
   barre, lui rend la laisse de 1760 px du reste du site. Un seul attribut,
   deux declarations, aucune hauteur calculee en JS.

   LE BUDGET DE HAUTEUR RESTE ACTIF EN MODE NORMAL, et ce n'est pas inutile :
   sur une fenetre basse, 1680 px de conteneur donneraient encore une image
   plus haute que la vitre. Le plafond de scene prend alors le relais et centre
   l'ensemble dans le conteneur.
   ========================================================================== */
body[data-etroit] .gi-live > .gi-container--wide {
  max-width: var(--gi-container-wide);
  padding-inline: var(--gi-gutter);
}

/* Les deux libelles et les deux icones vivent dans le balisage, le CSS choisit
   selon aria-pressed. Le JS n'ecrit pas un mot. */
[data-largeur-toggle] [data-quand="etroit"],
[data-largeur-toggle] .ico-large,
[data-largeur-toggle][aria-pressed="true"] [data-quand="large"],
[data-largeur-toggle][aria-pressed="true"] .ico-etroit { display: none; }
[data-largeur-toggle][aria-pressed="true"] [data-quand="etroit"] { display: inline; }
[data-largeur-toggle][aria-pressed="true"] .ico-large { display: block; }


/* ==========================================================================
   L5. RESPONSIVE
   ========================================================================== */

/* --- 1280 px : le chat se resserre, le lecteur garde la priorite --- */
@media (max-width: 1280px) {
  .gi-live { --gi-live-chat-w: 330px; }
}

/* --- 1080 px : une seule colonne. Le chat passe SOUS le lecteur et prend
       une hauteur fixe : il n'a plus de voisin dont copier la hauteur. --- */
@media (max-width: 1080px) {
  /* LE PLAFOND SAUTE EN MEME TEMPS QUE LA DEUXIEME COLONNE. Son calcul
     additionne la largeur du chat : une fois le chat passe SOUS le lecteur,
     cette addition n'a plus de sens et bornerait la scene trop tot. */
  .gi-live { --gi-live-scene-w: none; }
  .gi-live-stage {
    grid-template-columns: minmax(0, 1fr);
  }
  .gi-live-chat.gi-panel { height: 30rem; }
  /* Le bouton de largeur n'a plus d'objet : la scene occupe deja toute la
     largeur disponible et le chat est passe sous le lecteur. */
  .gi-live-bar__tools [data-largeur-toggle] { display: none; }
}

/* --- 760 px : la boite d'outils prend la largeur --- */
@media (max-width: 760px) {
  .gi-live-bar__tools { margin-left: 0; width: 100%; }
  .gi-live-chat.gi-panel { height: 26rem; }
}

/* --- 400 px : le compte a rebours passe en deux rangees de deux --- */
@media (max-width: 400px) {
  .gi-live-when .gi-count__grid { grid-template-columns: repeat(2, 1fr); }
}

/* ==========================================================================
   L6. OUTIL DE MAQUETTE, A NE PAS PORTER
   --------------------------------------------------------------------------
   La barre de boutons n'existe que dans ce fichier de demonstration. Sur le
   site, l'etat est pose une fois pour toutes en classe de corps, par PHP.
   Le FILTRE des etats, lui, est en partie L2 : il sert des deux cotes.
   ========================================================================== */
.gi-demo {
  position: sticky;
  top: 0;
  z-index: var(--z-modal);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: 0.6rem var(--gi-gutter);
  background: #1B0F0F;
  box-shadow: inset 0 -1px 0 rgba(228, 105, 74, 0.45);
}
.gi-demo__label {
  margin-right: var(--sp-3);
  font-family: var(--gi-font-display);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: #F5AE99;
}
.gi-demo button {
  padding: 0.4rem 0.85rem;
  border-radius: var(--r-pill);
  font-family: var(--gi-font-body);
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--gi-sand-300);
  background: rgba(241, 233, 218, 0.05);
  box-shadow: inset 0 0 0 1px rgba(241, 233, 218, 0.12);
  cursor: pointer;
  transition: color var(--t-fast), background-color var(--t-fast);
}
.gi-demo button:hover { color: var(--gi-sand-50); }
.gi-demo button[aria-pressed="true"] {
  color: var(--gi-ink-950);
  background: linear-gradient(160deg, var(--gi-gold-300), var(--gi-gold-500));
}
