* { box-sizing: border-box; }
:root { --bg:#181818; --panel:#1f1f1f; --line:#2c2c2c; --accent:#1a73e8; --muted:#9aa0a6; }
html, body { height:100%; margin:0; overflow:hidden; }
body {
  background:var(--bg); color:#e8eaed; font:13px/1.4 system-ui, sans-serif;
  display:flex; flex-direction:column; height:100vh;
  /* L'interface occupe exactement la fenêtre ; les zones qui défilent le font
     en interne. Sans cela, les bordures des panneaux débordaient de 2 px et
     faisaient apparaître une barre de défilement sur toute la page. */
  overflow:hidden;
}
.muted { color:var(--muted); }
.hidden { display:none !important; }
button {
  background:#2a2b2e; color:#e8eaed; border:1px solid #3c4043; border-radius:6px;
  padding:6px 10px; cursor:pointer;
}
button:hover { background:#34363a; }
button.active { background:var(--accent); border-color:var(--accent); }
select, input {
  background:#202124; color:#e8eaed; border:1px solid #3c4043; border-radius:6px;
  padding:6px 8px;
}

/* Barre du haut */
#topbar { display:flex; align-items:center; gap:10px; padding:8px 12px;
  background:#202124; border-bottom:1px solid var(--line); }
.brand { font-size:15px; }
/* Photo d'en-tête : vignette ronde à gauche de la barre du haut. */
/* Logo de chaîne : l'image telle quelle (le nom est dans le fichier). */
#logo { height:48px; width:auto; max-width:120px; object-fit:contain;
  flex-shrink:0; border-radius:6px; background:#111; }
#kinds button { margin-right:4px; }
/* Le drapeau rendait le libellé trop large : il passait sur deux lignes. */
#btnLang { white-space:nowrap; flex-shrink:0; }
#search { min-width:240px; }
.spacer { flex:1; }

/* Corps : vidéo à gauche | navigation à droite */
#content { flex:1; display:flex; min-height:0; }
#player-col { flex:3; display:flex; flex-direction:column; background:#000;
  min-width:0; }
#player { flex:1; width:100%; background:#000; min-height:0; }
.player-controls { display:flex; align-items:center; gap:10px; padding:6px 10px;
  background:#0a0a0a; border-top:1px solid var(--line); }
.player-controls #playerInfo { flex:1; }
#nav { flex:2; display:flex; min-width:0; border-left:1px solid var(--line); }
#categories { width:200px; border-right:1px solid var(--line); overflow:auto;
  padding:8px; flex-shrink:0; }
#categories h3 { margin:6px 4px; }
#catList { list-style:none; margin:0; padding:0; }
#catList li { padding:6px 8px; border-radius:6px; cursor:pointer; }
#catList li:hover { background:#26282c; }
#catList li.active { background:var(--accent); }

#gridWrap { flex:1; overflow:auto; padding:12px; min-width:0; }
#grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(130px,1fr));
  gap:12px; }
.card { background:var(--panel); border:1px solid var(--line); border-radius:8px;
  overflow:hidden; cursor:pointer; }
.card:hover { border-color:var(--accent); }
.thumb-wrap { position:relative; aspect-ratio:2/3; background:#1b1b1b;
  display:flex; align-items:center; justify-content:center; color:#6b7075;
  font-weight:bold; font-size:20px; overflow:hidden; }
.thumb-wrap.live { aspect-ratio:16/9; }
.thumb-wrap .thumb { position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; background:transparent; display:block; }
.thumb-wrap.live .thumb { object-fit:contain; }
.thumb-wrap .badge { position:absolute; top:4px; right:4px; z-index:2;
  color:#fff; font-size:11px; font-weight:bold; padding:1px 6px; border-radius:5px; }
.thumb-wrap .badge.lang { right:auto; left:4px; background:#37474f; }
/* Bouton « à voir plus tard », en bas à droite de l'affiche. Discret au
   repos, net au survol ; toujours visible une fois l'élément marqué. */
.thumb-wrap .fav {
  position:absolute; bottom:4px; right:4px; z-index:3;
  width:26px; height:26px; padding:0; line-height:1;
  border-radius:50%; border:1px solid rgba(255,255,255,.35);
  background:rgba(12,14,18,.72); color:#fff; font-size:14px;
  opacity:0; transition:opacity .15s, background .15s;
}
.card:hover .thumb-wrap .fav { opacity:1; }
.thumb-wrap .fav:hover { background:rgba(26,115,232,.92); }
.thumb-wrap .fav.on { opacity:1; background:rgba(26,115,232,.92);
  border-color:#8ab4f8; }
/* Sur écran tactile il n'y a pas de survol : le bouton reste visible. */
@media (hover: none) {
  .thumb-wrap .fav { opacity:.92; }
}
.card .name { padding:6px 6px 2px; font-size:12px; line-height:1.25;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
  overflow:hidden; }
/* Rubrique d'origine, sous le titre de la vignette. Discrète : c'est une
   information de repérage, pas le sujet de la carte. */
.card .cat { padding:0 6px 5px; font-size:10.5px; color:#7f868e;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.card .epg { padding:0 6px 6px; font-size:11px; color:var(--muted);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-height:14px; }
/* Détail : bande horizontale discrète en bas */
#detail { height:150px; border-top:1px solid var(--line); display:flex;
  gap:12px; padding:10px 14px; align-items:flex-start; background:#161616; }
#dPoster { height:128px; width:auto; max-width:90px; border-radius:6px;
  background:#111; object-fit:contain; }
#detail .info { flex:1; min-width:0; overflow:auto; height:100%; }
#detail .info h2 { font-size:15px; margin:0 0 4px; }
#dPlot { color:#cfcfcf; white-space:pre-line; font-size:12px; }
#detail .actions { display:flex; flex-direction:column; gap:6px; flex-shrink:0; }
#detail .actions button { min-width:130px; text-align:left; }

/* Multi-vue */
#mosaic { position:fixed; inset:0; background:#0c0c0c; z-index:50; padding:40px 8px 8px; }
#mosaicClose { position:absolute; top:8px; right:12px; z-index:51; }
#mosaicGrid { display:grid; gap:6px; height:100%; grid-auto-flow:row dense; }
#mosaicGrid video { width:100%; height:100%; background:#000; min-height:0; }
/* Disposition « régie » : la 1re vidéo est 2× plus grosse (2×2 cellules),
   les suivantes s'alignent autour sur des cellules identiques. */
#mosaicGrid > video:first-child:not(:only-child) {
  grid-row:span 2; grid-column:span 2; }

/* Modale */
#modal { position:fixed; inset:0; background:rgba(0,0,0,.6); z-index:60;
  display:flex; align-items:center; justify-content:center; }
.modal-card { background:var(--panel); border:1px solid var(--line);
  border-radius:10px; padding:18px; width:380px; }
.modal-card label { display:block; margin:8px 0; }
.modal-card input, .modal-card select { width:100%; margin-top:3px; }
.modal-card .actions { display:flex; justify-content:flex-end; gap:8px; margin-top:14px; }

/* ---- Animation d'ouverture ------------------------------------------------
   Logo qui se révèle, trait lumineux qui s'étire, puis un slogan. Environ
   2,4 s, passable d'un clic. z-index au-dessus de tout, y compris du code
   d'accès, pour que l'ouverture reste la première chose vue. */
#splash {
  position: fixed; inset: 0; z-index: 200;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 0;
  /* Le papier peint en fond, sous un voile sombre : le motif reste perceptible
     comme texture, mais le logo et les slogans restent nets. Sans ce voile,
     le fond crème avalait le texte clair. */
  /* Le papier peint reste le fond de repli : il s'affiche si la vidéo
     n'est pas encore chargée, ou si le navigateur refuse de la lire. */
  background: url("/fond.jpg") center/cover no-repeat #0b0c0e;
  cursor: pointer;
  overflow: hidden;
}
/* La sortie n'est plus déclenchée par un délai fixe : elle suit la fin de la
   vidéo, le clic, ou le repli de sécurité — tous pilotés par app.js. */
#splash.sortie { animation: splash-sortie .5s ease-in forwards; }
#splash::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(ellipse at center,
                              rgba(10,12,15,.28) 0%, rgba(6,7,9,.70) 80%);
}
/* Boutons de contrôle, discrets, en haut à droite. */
#splashBoutons {
  position: absolute; top: 14px; right: 14px; z-index: 3;
  display: flex; gap: 8px;
}
#splashBoutons button {
  background: rgba(20,22,26,.72); border: 1px solid rgba(255,255,255,.22);
  color: #e8eaed; font-size: 12px; padding: 7px 12px; border-radius: 999px;
  backdrop-filter: blur(6px);
}
#splashBoutons button:hover { background: rgba(40,44,50,.85); }

/* Halo qui respire derrière le logo. */
#splash .halo {
  position: absolute; z-index: 2;
  width: 420px; height: 420px; border-radius: 50%;
  background: radial-gradient(circle, rgba(26,115,232,.22) 0%,
                              rgba(26,115,232,0) 65%);
  opacity: 0; animation: halo-pulse 2.2s ease-out forwards;
}
#splashLogo {
  position: relative; z-index: 2;
  height: 124px; width: auto; max-width: 62vw;
  object-fit: contain; border-radius: 12px;
  opacity: 0; transform: scale(.86) translateY(10px); filter: blur(8px);
  animation: logo-entree .95s cubic-bezier(.22,.9,.3,1) forwards;
}
/* Trait qui s'étire sous le logo, puis s'estompe. */
#splash .trait {
  position: relative; z-index: 2;
  height: 2px; width: 0; margin: 18px 0 14px;
  border-radius: 2px;
  background: linear-gradient(90deg, transparent, #4f9bff 35%,
                              #8ab4f8 50%, #4f9bff 65%, transparent);
  animation: trait-etire .85s cubic-bezier(.22,.9,.3,1) .5s forwards;
}
/* Les slogans, empilés et révélés un par un. Le décalage de chacun est posé
   en ligne par app.js (animation-delay), pour n'avoir qu'une règle ici. */
#splashSlogans {
  position: relative; z-index: 2;
  display: flex; flex-direction: column; gap: 15px;
  padding: 0 24px; max-width: 860px;
}
#splashSlogans p {
  margin: 0; text-align: center; font-size: 21px; line-height: 1.4;
  font-weight: 500; color: #f2f4f7; letter-spacing: .2px;
  /* Le voile reste léger pour laisser voir la vidéo : c'est cette ombre qui
     détache le texte des zones claires de l'image. */
  text-shadow: 0 2px 6px rgba(0,0,0,.98), 0 0 22px rgba(0,0,0,.85);
  opacity: 0; transform: translateY(14px);
  /* Entrée plus lente : la phrase se pose au lieu de surgir. */
  animation: slogan-entree 1.1s cubic-bezier(.22,.9,.3,1) forwards;
}

@keyframes logo-entree {
  0%   { opacity: 0; transform: scale(.86) translateY(10px); filter: blur(8px); }
  60%  { opacity: 1; }
  100% { opacity: 1; transform: scale(1) translateY(0); filter: blur(0); }
}
@keyframes halo-pulse {
  0%   { opacity: 0; transform: scale(.7); }
  45%  { opacity: 1; transform: scale(1); }
  100% { opacity: .55; transform: scale(1.08); }
}
@keyframes trait-etire {
  0%   { width: 0; opacity: 0; }
  55%  { opacity: 1; }
  100% { width: 260px; opacity: .85; }
}
@keyframes slogan-entree {
  0%   { opacity: 0; transform: translateY(14px); }
  100% { opacity: 1; transform: translateY(0); }
}
@keyframes splash-sortie {
  0%   { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.03); visibility: hidden; }
}

/* Mouvement réduit demandé par le système : on montre le slogan sans
   animer, et plus brièvement. */
@media (prefers-reduced-motion: reduce) {
  #splash, #splash .halo, #splashLogo, #splash .trait, #splashSlogans p {
    animation: none;
  }
  #splash { animation: splash-sortie .3s ease-in 2.4s forwards; }
  #splashLogo { opacity: 1; transform: none; filter: none; }
  #splash .halo { opacity: .55; }
  #splash .trait { width: 260px; opacity: .85; }
  /* Tous les slogans visibles d'emblée, sans mouvement. */
  #splashSlogans p { opacity: 1; transform: none; }
}

/* ---- Écrans tactiles : tablette puis téléphone ----------------------------
   L'agencement de bureau (vidéo à gauche, navigation à droite, catégories en
   colonne de 200 px) ne tient pas en largeur réduite : la grille et la
   recherche sortaient de l'écran. En dessous de 1100 px on empile donc
   verticalement — vidéo en haut, navigation dessous — et les catégories
   deviennent un bandeau qui défile horizontalement. */

@media (max-width: 1100px) {
  /* La barre du haut passe à la ligne au lieu de pousser les derniers
     boutons hors de l'écran, et les onglets s'alignent horizontalement
     (empilés, ils mangeaient toute la hauteur de la barre). */
  #topbar { flex-wrap: wrap; gap: 8px; }
  #kinds { display: flex; gap: 5px; }
  #kinds button { margin-right: 0; }
  #search { flex: 1 1 200px; min-width: 0; }
  .spacer { display: none; }

  #content { flex-direction: column; }
  /* La vidéo garde ses proportions au lieu de s'étirer sur la moitié haute. */
  #player-col { flex: none; width: 100%; }
  #player { aspect-ratio: 16/9; height: auto; width: 100%; }
  #nav { flex: 1; flex-direction: column; border-left: none;
         border-top: 1px solid var(--line); min-height: 0; }

  /* Catégories : bandeau horizontal plutôt qu'une colonne figée. */
  #categories { width: auto; flex-shrink: 0; padding: 7px 8px;
                border-right: none; border-bottom: 1px solid var(--line);
                overflow-x: auto; overflow-y: hidden; }
  #categories h3 { display: none; }
  #catList { display: flex; gap: 6px; }
  #catList li { flex-shrink: 0; white-space: nowrap; background: #26282c;
                font-size: 12px; padding: 5px 11px; }

  #gridWrap { flex: 1; min-height: 0; }
  #grid { grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
          gap: 10px; }

  /* Fiche du bas : plus compacte, actions alignées sur une ligne. */
  #detail { height: 128px; padding: 9px 11px; gap: 10px; }
  #dPoster { height: 106px; max-width: 74px; }
  #detail .actions { flex-direction: row; flex-wrap: wrap;
                     align-content: flex-start; }
  #detail .actions button { min-width: 0; padding: 6px 9px; }
}

@media (max-width: 760px) {
  /* Barre du haut : elle passe sur deux lignes, la recherche prend toute la
     largeur disponible au lieu d'être tronquée. */
  #topbar { flex-wrap: wrap; gap: 7px; padding: 7px 9px; }
  #logo { height: 34px; max-width: 70px; }
  #sourceSelect { max-width: 42vw; }
  #kinds { order: 3; width: 100%; }
  #kinds button { flex: 1; padding: 7px 4px; font-size: 12px; }
  /* Recherche et tri partagent la même ligne : une ligne de barre gagnée,
     autant de hauteur rendue à la liste des chaînes. */
  #search { order: 4; flex: 1 1 60%; }
  #sortSelect { order: 5; flex: 0 0 auto; }
  #importStatus { order: 6; font-size: 11px; }

  #grid { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
          gap: 8px; }
  #gridWrap { padding: 9px; }
  .card .name { font-size: 11px; }

  /* La fiche occupe trop de hauteur sur un téléphone : titre, résumé court
     et boutons, sans poster. */
  #detail { height: 112px; }
  #dPoster { display: none; }
  #detail .info h2 { font-size: 14px; }
  #dPlot { font-size: 11px; }

  /* Animation d'ouverture : logo et slogans réduits pour tenir sans que les
     phrases passent sur trois lignes. */
  #splashLogo { height: 92px; }
  #splash .halo { width: 280px; height: 280px; }
  #splashSlogans { gap: 11px; padding: 0 16px; }
  #splashSlogans p { font-size: 16px; line-height: 1.35; }
  #splashBoutons button { font-size: 11px; padding: 6px 10px; }

  /* Code d'accès : la boîte ne doit pas dépasser de l'écran. */
  #authGate .box { min-width: 0; width: calc(100vw - 36px); padding: 22px; }
  .modal-card { width: calc(100vw - 32px); }
}

/* Téléphone couché : la vidéo mangerait tout l'écran. On la borne pour
   laisser voir la liste des chaînes. */
@media (max-width: 1100px) and (orientation: landscape) and (max-height: 520px) {
  #player { aspect-ratio: auto; height: 46vh; }
  #detail { height: 96px; }
}

/* Préparation d'un film : voile sur le lecteur, avec une jauge qui avance.
   Un film met 20 à 50 s à se préparer (pré-téléchargement) ; sans ce retour
   visuel, l'écran noir donnait l'impression que rien ne se passait. */
#player-col { position: relative; }
#prepare {
  position: absolute; inset: 0; z-index: 20;
  display: flex; align-items: center; justify-content: center;
  background: rgba(8, 9, 11, .88);
}
#prepare .boite { width: min(420px, 82%); text-align: center; padding: 0 16px; }
#prepare h3 { margin: 0 0 8px; font-size: 16px; line-height: 1.3; }
#prepare p { margin: 6px 0 0; font-size: 12.5px; }
#prepare .jauge {
  height: 6px; margin-top: 14px; border-radius: 99px;
  background: #2a2d33; overflow: hidden;
}
#prepare #prepBarre {
  height: 100%; width: 0; border-radius: 99px;
  background: linear-gradient(90deg, #1a73e8, #8ab4f8);
  transition: width .45s ease-out;
}
/* Tant que l'avancement réel n'est pas connu, la barre ondule au lieu de
   rester figée à zéro. */
#prepare #prepBarre.indetermine {
  width: 35%; animation: jauge-va-et-vient 1.5s ease-in-out infinite;
}
@keyframes jauge-va-et-vient {
  0%   { margin-left: -35%; }
  100% { margin-left: 100%; }
}

/* ---- Assistant ------------------------------------------------------------
   Panneau latéral : le dialogue se déroule SANS masquer la grille ni la
   vidéo, contrairement à une fenêtre modale. */
#assistant {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(420px, 94vw);
  z-index: 70; display: flex; flex-direction: column;
  background: #15171b; border-left: 1px solid var(--line);
  box-shadow: -18px 0 42px rgba(0,0,0,.45);
  animation: assistant-entre .22s ease-out;
}
@keyframes assistant-entre { from { transform: translateX(100%); } }
#assistant > header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 11px 14px; border-bottom: 1px solid var(--line);
  background: #1b1e23; font-weight: 600;
}
#assistant > header button { border: none; background: transparent;
  font-size: 15px; padding: 2px 6px; }
#assistantFil { flex: 1; overflow-y: auto; padding: 14px; display: flex;
  flex-direction: column; gap: 14px; }

/* Les bulles restent sobres : l'essentiel est dans les vignettes. */
.msg { max-width: 92%; font-size: 13px; line-height: 1.5; }
.msg.moi { align-self: flex-end; background: var(--accent); color: #fff;
  padding: 8px 12px; border-radius: 14px 14px 4px 14px; }
.msg.lui { align-self: flex-start; color: #dfe3e8; }
.msg.erreur { align-self: flex-start; color: #ff8a80; font-size: 12.5px; }

/* Vignettes proposées : c'est là que se joue le choix, pas dans le texte. */
.propositions { display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 10px; margin-top: 2px; }
.prop { background: var(--panel); border: 1px solid var(--line);
  border-radius: 9px; overflow: hidden; cursor: pointer; }
.prop:hover { border-color: var(--accent); }
.prop .img { aspect-ratio: 2/3; background: #1b1b1b center/cover no-repeat;
  display: block; }
.prop .t { padding: 6px 7px 1px; font-size: 11.5px; line-height: 1.25;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; }
.prop .m { padding: 0 7px 7px; font-size: 10.5px; color: var(--muted); }

/* Puces de précision : cliquer plutôt qu'écrire. */
.puces { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 4px; }
.puces button { font-size: 12px; padding: 6px 12px; border-radius: 999px; }

#assistantForm { display: flex; gap: 8px; padding: 11px 12px;
  border-top: 1px solid var(--line); background: #1b1e23; }
#assistantInput { flex: 1; min-width: 0; }
#assistantEnvoi { width: 38px; flex-shrink: 0; font-size: 15px; }
#assistant.occupe #assistantEnvoi { opacity: .5; }

/* Trois petits points pendant que l'agent cherche. */
.reflexion { display: flex; gap: 4px; align-self: flex-start; padding: 4px 0; }
.reflexion i { width: 6px; height: 6px; border-radius: 50%; background: #6e7681;
  animation: pulse-point 1.1s ease-in-out infinite; }
.reflexion i:nth-child(2) { animation-delay: .18s; }
.reflexion i:nth-child(3) { animation-delay: .36s; }
@keyframes pulse-point {
  0%, 100% { opacity: .25; transform: translateY(0); }
  50%      { opacity: 1; transform: translateY(-3px); }
}

@media (max-width: 760px) {
  #assistant { width: 100vw; }
  .propositions { grid-template-columns: repeat(3, 1fr); }
}

/* ---- Expert cinéma vocal --------------------------------------------------
   Fenêtre modale, contrairement à l'assistant écrit : quand on parle, on ne
   fait que ça, et l'attention doit aller à la conversation. */
#live {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(6,7,9,.86); backdrop-filter: blur(5px);
  display: flex; align-items: center; justify-content: center; padding: 16px;
}
.live-carte {
  /* Hauteur libre : la fenêtre épouse son contenu au lieu de laisser un
     grand vide sous les suggestions. */
  width: min(880px, 100%); max-height: 92vh; display: flex;
  flex-direction: column; background: #16181d;
  border: 1px solid var(--line); border-radius: 16px; overflow: hidden;
  box-shadow: 0 24px 60px rgba(0,0,0,.5);
  animation: live-entre .2s ease-out;
}
@keyframes live-entre { from { opacity:0; transform: translateY(10px) scale(.98); } }
.live-carte > header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 11px 14px; border-bottom: 1px solid var(--line); font-size: 13px;
}
.live-carte > header button { border: none; background: transparent; font-size: 15px; }
/* Zone de parole : hauteur FIXE, pour que la grille de films ne se mette
   pas à sauter chaque fois que l'expert dit une phrase plus longue. */
.live-centre {
  flex-shrink: 0; padding: 18px 28px 14px; text-align: center;
  display: flex; flex-direction: column; align-items: center;
}
#liveDit {
  margin: 10px 0 0; font-size: 16px; line-height: 1.55; color: #f0f2f5;
  max-width: 62ch; height: 3.1em; overflow: hidden;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
#liveEntendu { margin: 6px 0 0; font-size: 12px; font-style: italic;
  height: 1.3em; overflow: hidden; white-space: nowrap;
  text-overflow: ellipsis; max-width: 58ch; }

/* Onde : montre que le micro capte, et que l'expert parle. */
#liveOnde { display: flex; align-items: center; justify-content: center;
  gap: 5px; height: 42px; }
#liveOnde i { width: 5px; height: 10px; border-radius: 3px; background: #3d4148;
  transition: background .2s; }
#live.ecoute #liveOnde i { background: #8ab4f8; animation: onde 1s ease-in-out infinite; }
#live.parle  #liveOnde i { background: #81c995; animation: onde .6s ease-in-out infinite; }
#liveOnde i:nth-child(2) { animation-delay: .12s; }
#liveOnde i:nth-child(3) { animation-delay: .24s; }
#liveOnde i:nth-child(4) { animation-delay: .36s; }
#liveOnde i:nth-child(5) { animation-delay: .48s; }
@keyframes onde { 0%,100% { height: 10px; } 50% { height: 34px; } }

/* Films proposés. Quatre par ligne, affiches assez grandes pour être
   reconnues d'un coup d'œil — c'est l'image qui fait choisir, pas le texte.
   On n'en garde qu'une poignée : une grille qui s'allonge sans fin devient
   illisible et noie la dernière suggestion. */
#liveFilmsZone { flex-shrink: 0; display: flex; flex-direction: column;
  padding: 0 28px 10px; }
#liveFilmsTitre { font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: #7f868e; margin: 0 0 9px; flex-shrink: 0; }
#liveFilmsZone.vide { display: none; }
#liveFilms { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px;
  align-content: start; }
#liveFilms .prop { background: var(--panel); border-radius: 10px; }
/* L'affiche garde ses proportions de jaquette : c'est elle qu'on reconnaît
   au premier regard. Avec UNE seule rangée, elle tient sans écraser le
   titre — c'était l'entassement sur deux rangées qui posait problème. */
#liveFilms .prop .img { aspect-ratio: 2/3; }
#liveFilms .prop .t { font-size: 12.5px; padding: 8px 9px 2px;
  flex-shrink: 0; }
#liveFilms .prop .m { font-size: 11px; padding: 0 9px 9px; flex-shrink: 0; }

.live-carte > footer { padding: 12px; border-top: 1px solid var(--line);
  display: flex; justify-content: center; background: #1b1e23; }
#liveMicro.coupe { background: #5a2b2b; border-color: #7a3a3a; }

@media (max-width: 760px) {
  #liveFilms { grid-template-columns: repeat(3, 1fr); }
  .live-carte { max-height: 96vh; }
}

/* Code d'accès */
#authGate { position:fixed; inset:0; z-index:100;
  display:flex; align-items:center; justify-content:center;
  /* Même papier peint que l'écran d'ouverture, un peu plus assombri :
     c'est un écran de saisie, la lisibilité prime. */
  background-image:
    radial-gradient(ellipse at center,
                    rgba(12,13,16,.80) 0%, rgba(7,8,10,.94) 72%),
    url("/fond.jpg");
  background-size: cover, cover;
  background-position: center, center;
  background-repeat: no-repeat, no-repeat; }
#authGate .box { background:#1f1f1f; padding:26px 30px; border-radius:8px;
  min-width:320px; }
#authGate h3 { margin:0 0 6px; }
#authGate input { width:100%; margin:10px 0; padding:10px; background:#2a2b2e;
  border:1px solid #3c4043; border-radius:5px; color:#e8eaed; font-size:16px; }
#authGate .actions { display:flex; justify-content:flex-end; }
#authGate #authError { color:#ff8a80; min-height:18px; font-size:13px; }
