/* ==========================================================================
   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 : l'en-tete de page et 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.

   TROIS ETATS, un seul balisage : `data-live="attente" | "direct" | "fini"`
   pose sur <body>. Sous Divi ce sera une classe de corps posee en PHP selon
   l'horaire de l'emission, pas un selecteur de maquette.
   ========================================================================== */

/* ==========================================================================
   L1. EN-TETE DE PAGE
   --------------------------------------------------------------------------
   Bandeau court, et c'est delibere : ce qu'on vient voir est le lecteur, il
   doit tenir dans le premier ecran. Meme recette de fond que .gi-arch-head
   pour que les deux pages se reconnaissent, mais moitie moins haut.
   ========================================================================== */
.gi-live-head {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: clamp(1.5rem, 1.1rem + 1.6vw, 2.5rem);
  background:
    radial-gradient(70% 130% at 12% 0%, rgba(198, 165, 93, 0.10), transparent 62%),
    radial-gradient(60% 120% at 92% 100%, rgba(228, 105, 74, 0.08), transparent 66%),
    linear-gradient(180deg, var(--gi-ink-950), var(--gi-ink-900) 100%);
}

.gi-live-head::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: linear-gradient(90deg,
    transparent, var(--gi-line-strong) 22%, var(--gi-line-strong) 78%, transparent);
  z-index: 5;
}

/* FLEX ET NON GRID, pour la meme raison que sur l'archive : quand le bloc de
   droite disparait, une piste de grille vaut zero mais garde son gap. */
.gi-live-head__inner {
  position: relative;
  z-index: 4;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--sp-5) var(--sp-8);
  flex-wrap: wrap;
}
.gi-live-head__text { flex: 1 1 22rem; min-width: 0; }
.gi-live-head__aside { flex: 0 1 25rem; min-width: 0; }

.gi-live-head__title {
  font-family: var(--gi-font-display);
  font-size: var(--fs-t-lg);
  font-weight: 700;
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-caps-lg);
  color: var(--gi-sand-50);
  text-wrap: balance;
}

.gi-live-head__desc {
  margin-top: var(--sp-3);
  max-width: 46ch;
  font-size: var(--fs-base);
  color: var(--gi-text-muted);
}

/* Ornement repris a l'identique de l'archive : une seule signature de titre
   sur tout le site. */
.gi-live-head__ornament {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin-top: var(--sp-4);
}
.gi-live-head__ornament::before,
.gi-live-head__ornament::after {
  content: "";
  height: 1px;
  background: linear-gradient(90deg, var(--gi-gold-600), transparent);
}
.gi-live-head__ornament::before { width: 54px; }
.gi-live-head__ornament::after {
  width: 100%;
  max-width: 220px;
  background: linear-gradient(90deg, var(--gi-gold-800), transparent);
}
.gi-live-head__star {
  width: 13px;
  height: 13px;
  flex: none;
  background: var(--gi-gold-500);
  -webkit-mask: var(--gi-star) center / contain no-repeat;
          mask: var(--gi-star) center / contain no-repeat;
}

/* ==========================================================================
   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 {
  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 widgetbot,
.gi-live-chat__frame .gi-live-chat__scroll {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
/* L'element <widgetbot> se pose PAR-DESSUS le faux fil et reste sans fond :
   si le script du CDN ne charge pas, aucun iframe n'est cree, l'element est
   transparent et c'est le faux fil qu'on voit. Lui donner une couleur de fond
   ferait perdre ce repli. */
.gi-live-chat__frame widgetbot { z-index: 2; display: block; }
.gi-live-chat__frame 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 : l'en-tete passe en pile, le panneau d'horaire prend la
       largeur --- */
@media (max-width: 760px) {
  .gi-live-head__inner { flex-direction: column; align-items: stretch; }
  .gi-live-head__aside { flex: 1 1 auto; }
  .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));
}
