/* ==========================================================================
   EmuHub — feuille de style unique (hub + lecteur)
   Theme sombre par defaut ; theme clair via [data-theme="clair"] sur <html>.
   Aucune ressource externe : system-ui, pas de police distante.
   ========================================================================== */

:root {
  --fond: #101014;
  --fond-2: #17171d;
  --fond-3: #1f1f27;
  --texte: #e8e8ec;
  --texte-2: #a8a8b4;
  --accent: #7c5cff;
  --accent-2: #9d85ff;
  --bord: #2a2a34;
  --ombre: 0 4px 16px rgba(0, 0, 0, .45);
  --rayon: 10px;
}

html[data-theme="clair"] {
  --fond: #f4f4f7;
  --fond-2: #ffffff;
  --fond-3: #ececf2;
  --texte: #1a1a20;
  --texte-2: #5a5a68;
  --accent: #5b3fd4;
  --accent-2: #7458e8;
  --bord: #d4d4de;
  --ombre: 0 4px 14px rgba(30, 30, 60, .12);
}

* { box-sizing: border-box; }

/* Un element [hidden] doit rester cache meme si une regle display
   (flex, grid...) le rendrait visible par defaut. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--fond);
  color: var(--texte);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  min-height: 100vh;
}

button {
  font: inherit;
  color: inherit;
  background: var(--fond-3);
  border: 1px solid var(--bord);
  border-radius: var(--rayon);
  padding: 8px 14px;
  cursor: pointer;
}

button:hover { border-color: var(--accent); }

button:focus-visible,
a:focus-visible,
input:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Barre du haut (hub + lecteur)
   -------------------------------------------------------------------------- */

.barre-haute {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  background: var(--fond-2);
  border-bottom: 1px solid var(--bord);
  position: sticky;
  top: 0;
  z-index: 20;
  flex-wrap: wrap;
}

.logo {
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: .4px;
  color: var(--accent-2);
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}

.barre-haute .titre-jeu {
  font-size: 1rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.barre-haute .flexeur { flex: 1; }

/* Champ de recherche */
.recherche {
  flex: 1 1 220px;
  min-width: 160px;
  max-width: 520px;
}

.recherche input {
  width: 100%;
  padding: 9px 14px;
  border-radius: var(--rayon);
  border: 1px solid var(--bord);
  background: var(--fond);
  color: var(--texte);
  font: inherit;
}

.bouton-rond {
  padding: 8px 10px;
  line-height: 0;
  flex: none;
}

.bouton-rond svg { display: block; }

/* --------------------------------------------------------------------------
   Hub : filtres
   -------------------------------------------------------------------------- */

.barre-filtres {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 12px 16px;
  border-bottom: 1px solid var(--bord);
  background: var(--fond-2);
}

.filtre-pf {
  padding: 6px 12px;
  font-size: .9rem;
  border-radius: 999px;
  background: var(--fond-3);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.filtre-pf[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent-2);
  color: #fff;
}

.filtre-pf .nb { opacity: .75; font-size: .8rem; }

.barre-filtres select {
  font: inherit;
  padding: 6px 10px;
  border-radius: var(--rayon);
  border: 1px solid var(--bord);
  background: var(--fond-3);
  color: var(--texte);
  margin-left: auto;
}

@media (max-width: 640px) {
  .barre-filtres select { margin-left: 0; }
}

/* --------------------------------------------------------------------------
   Hub : etats (chargement, erreur, vide)
   -------------------------------------------------------------------------- */

.etat {
  padding: 48px 16px;
  text-align: center;
  color: var(--texte-2);
}

.etat .grand { font-size: 1.1rem; color: var(--texte); margin-bottom: 8px; }

.etat .spin {
  display: inline-block;
  width: 22px; height: 22px;
  border: 3px solid var(--bord);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: rotation 1s linear infinite;
  margin-bottom: 12px;
}

@keyframes rotation { to { transform: rotate(360deg); } }

/* --------------------------------------------------------------------------
   Hub : grille de vignettes
   -------------------------------------------------------------------------- */

.grille {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 14px;
  padding: 16px;
}

@media (max-width: 480px) {
  .grille { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); padding: 10px; gap: 10px; }
}

.carte {
  position: relative;
  background: var(--fond-2);
  border: 1px solid var(--bord);
  border-radius: var(--rayon);
  overflow: hidden;
  cursor: pointer;
  text-decoration: none;
  color: inherit;
  display: block;
  transition: transform .12s ease, border-color .12s ease;
}

.carte:hover, .carte:focus-visible {
  transform: translateY(-3px);
  border-color: var(--accent);
}

.carte .vignette {
  width: 100%;
  aspect-ratio: 3 / 4;
  background: var(--fond-3);
  display: block;
  object-fit: cover;
}

.carte .vignette img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Placeholder genere quand il n'y a pas de couverture */
.carte .placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 10px;
  font-weight: 700;
  font-size: .95rem;
  color: var(--texte-2);
  background:
    linear-gradient(160deg, var(--fond-3), var(--fond-2));
  overflow: hidden;
}

.carte .bas {
  padding: 8px 10px 10px;
}

.carte .titre {
  font-size: .88rem;
  font-weight: 600;
  line-height: 1.25;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  min-height: 2.3em;
}

.carte .pf {
  font-size: .75rem;
  color: var(--texte-2);
  margin-top: 3px;
  text-transform: uppercase;
  letter-spacing: .5px;
}

/* Bouton coeur (favori) */
.btn-coeur {
  position: absolute;
  top: 6px;
  right: 6px;
  z-index: 2;
  width: 34px; height: 34px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(0, 0, 0, .55);
  border: 1px solid rgba(255, 255, 255, .18);
  color: #fff;
}

.btn-coeur:hover { background: rgba(0, 0, 0, .75); border-color: var(--accent); }

.btn-coeur[aria-pressed="true"] { color: #ff5d8f; }

html[data-theme="clair"] .btn-coeur {
  background: rgba(255, 255, 255, .8);
  border-color: rgba(0, 0, 0, .15);
  color: #333;
}

html[data-theme="clair"] .btn-coeur[aria-pressed="true"] { color: #e0245e; }

/* Bouton "charger plus" */
.zone-plus {
  display: flex;
  justify-content: center;
  padding: 8px 16px 40px;
}

.zone-plus button { font-size: 1rem; padding: 10px 26px; }

/* --------------------------------------------------------------------------
   Lecteur (jeu.html)
   -------------------------------------------------------------------------- */

.page-lecteur {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
}

/* Le conteneur du jeu DOIT avoir une taille (piege #2 d'EmulatorJS) :
   #ecran a une hauteur flex explicite, #game en occupe 100 %. */
#ecran {
  flex: 1;
  min-height: 0;
  background: #000;
  position: relative;
}

#game {
  width: 100%;
  height: 100%;
}

/* Rendu net des pixels ; EmulatorJS gere le ratio d'aspect du canvas
   lui-meme, on ne force que le lissage ici. */
#game canvas {
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}

.message-lecteur {
  position: absolute;
  top: 12px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(0, 0, 0, .75);
  color: #fff;
  padding: 8px 16px;
  border-radius: 999px;
  font-size: .9rem;
  max-width: 90%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  z-index: 30;
  transition: opacity .4s;
}

/* Panneau des sauvegardes serveur */
.panneau {
  position: absolute;
  top: 52px;
  right: 12px;
  width: min(360px, calc(100vw - 24px));
  max-height: 60vh;
  overflow: auto;
  background: var(--fond-2);
  border: 1px solid var(--bord);
  border-radius: var(--rayon);
  box-shadow: var(--ombre);
  padding: 12px;
  z-index: 25;
}

.panneau h2 {
  font-size: .95rem;
  margin: 0 0 8px;
}

.panneau ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.panneau li {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--fond-3);
  border-radius: 8px;
  padding: 6px 10px;
  font-size: .85rem;
}

.panneau li .infos {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.panneau li .infos .date {
  display: block;
  color: var(--texte-2);
  font-size: .75rem;
}

.panneau .vide { color: var(--texte-2); font-size: .85rem; padding: 6px 2px; }

.panneau button { padding: 5px 10px; font-size: .8rem; }

/* Modal commandes */
.modal-fond {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 40;
  padding: 16px;
}

.modal {
  background: var(--fond-2);
  border: 1px solid var(--bord);
  border-radius: var(--rayon);
  padding: 20px;
  max-width: 480px;
  width: 100%;
  max-height: 80vh;
  overflow: auto;
}

.modal h2 { margin-top: 0; }

.modal table {
  border-collapse: collapse;
  width: 100%;
  font-size: .9rem;
}

.modal th, .modal td {
  text-align: left;
  padding: 5px 8px;
  border-bottom: 1px solid var(--bord);
}

.modal th { color: var(--texte-2); font-weight: 600; }

.modal .fermer { margin-top: 14px; }

kbd {
  background: var(--fond-3);
  border: 1px solid var(--bord);
  border-radius: 5px;
  padding: 1px 6px;
  font-family: inherit;
  font-size: .85em;
}

/* --- Phase 3 : contexte non isole + A propos ------------------------- */

/* Information (pas une erreur) : HTTP simple -> pas de multi-thread. */
.info-contexte {
  background: var(--fond-3);
  border-bottom: 1px solid var(--bord);
  color: var(--texte-2);
  font-size: .85rem;
  line-height: 1.45;
  padding: 8px 16px;
  text-align: center;
}

#modal-a-propos { z-index: 60; }
#modal-a-propos h3 { margin-bottom: 6px; }
#modal-a-propos .a-propos-intro { margin-top: 0; }
#modal-a-propos code {
  background: var(--fond-3);
  border-radius: 4px;
  padding: 1px 5px;
  font-size: .85em;
}
#modal-a-propos .note-pwa {
  color: var(--texte-2);
  font-size: .85rem;
  border-top: 1px solid var(--bord);
  padding-top: 10px;
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* --- Phase 4 : manettes ------------------------------------------------- */

/* Bouton « Manette » du lecteur : etat visible clair (gamepad virtuel
   affiche). */
#btn-manette[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent-2);
  color: #fff;
}

/* --- Gamepad virtuel : hauteur du conteneur ------------------------------
   Le CSS d'EmulatorJS definit :
     .ejs_virtualGamepad_parent { width:100%; position:absolute; bottom:50px }
   SANS HAUTEUR. Or ses enfants (.ejs_virtualGamepad_left / _right /
   _top / _bottom) sont en position:absolute et se positionnent par
   rapport a ce parent : avec une hauteur nulle, ils sont calcules
   50px SOUS le bord du parent, donc hors de l'ecran.

   Mesure avant correction : .ejs_virtualGamepad_parent faisait
   390x0 sur un ecran de 390 px de large : le gamepad etait bien cree
   (8 boutons, D-PAD) mais invisible.

   On lui donne une hauteur qui contient le D-PAD (125px) et les
   boutons A/B/X/Y (130px). */
#game .ejs_virtualGamepad_parent {
  height: 200px;
  bottom: 0;
  z-index: 2;
  pointer-events: none;   /* le conteneur ne capte pas les touches */
}

/* Les enfants, eux, les captent. */
#game .ejs_virtualGamepad_parent > * {
  pointer-events: auto;
}

/* Les zones tactiles du joystick et du D-PAD ne doivent pas derouter
   le scroll de la page. */
#game .ejs_dpad_main,
#game .ejs_virtualGamepad_button {
  touch-action: none;
}

/* Le gamepad virtuel d'EmulatorJS vit DANS #game (.ejs_virtualGamepad_parent,
   position absolute, sans z-index) : il ne peut jamais recouvrir la barre
   du lecteur (sticky, z-index 20), le panneau des sauvegardes (z-index 25),
   les messages (z-index 30) ni les modals (z-index 40), tous hors de #game.
   Le canvas garde toute la zone de jeu : le gamepad est une superposition,
   on ne redimensionne rien. */

/* Appareil tactile (pointeur grossier ET ecran etroit) : le bouton
   « Manette » se contente d'un accent discret, le gamepad est deja
   affiche automatiquement. Cette media query est le meme critere que
   celui evalue par js/jeu.js (matchMedia) : CSS et JS restent
   coherents sans aucune mesure en boucle. */
@media (pointer: coarse) and (max-width: 900px) {
  .barre-haute { gap: 8px; padding: 8px 10px; }
  .barre-haute button { padding: 7px 10px; font-size: .88rem; }
}
/* --- Invite de demarrage ---------------------------------------------------
   Superposee a la zone de jeu, elle disparait au premier appui. */
.invite-demarrage {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(8, 8, 10, 0.82);
  cursor: pointer;
  z-index: 5;
}
.invite-demarrage[hidden] { display: none; }
.invite-contenu { text-align: center; }
.invite-icone {
  display: block;
  font-size: 3rem;
  line-height: 1;
  margin-bottom: 0.5rem;
  color: var(--accent, #7c5cff);
}
.invite-titre {
  margin: 0 0 0.35rem;
  font-size: 1.15rem;
  font-weight: 600;
}
.invite-sous-titre {
  margin: 0;
  font-size: 0.85rem;
  opacity: 0.75;
}

/* --- Plein ecran --------------------------------------------------------
   EmulatorJS demande le plein ecran sur son "parent", qui est #game
   (le selecteur passe a EJS_player). Sans regle :fullscreen, #game
   garde la taille de son conteneur dans la flexbox (#ecran) : le jeu
   reste affiche dans une bande de 554 px sur 720, et le plein ecran
   ne change RIEN a l'image. */

#game:fullscreen,
#game:-webkit-full-screen,
#game:-moz-full-screen {
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
  background: #000;
}

/* Le conteneur parent aussi, sinon il garde sa taille et le canvas
   reste centre dans une zone etroite. */
#ecran:has(#game:fullscreen),
#ecran:has(#game:-webkit-full-screen) {
  padding: 0;
  gap: 0;
}

/* En plein ecran, la barre de boutons du lecteur doit disparaitre
   (le hub garde son propre bouton pour sortir). */
body:has(#game:fullscreen) .barre-haute,
body:has(#game:-webkit-full-screen) .barre-haute {
  display: none;
}

/* Safari mobile : requestFullscreen sur un div n'est pas supporte
   (seul <video> peut passer en plein ecran). Le canvas est alors
   mis en plein ecran "a la main" par le CSS : on compense. */
@supports not (top: 0) {
  #game canvas { max-width: 100%; max-height: 100%; }
}

/* --- Chaine de taille EmulatorJS ------------------------------------------
   EmulatorJS insere sa structure DANS #game (le selecteur passe a
   EJS_player) :
       #game > .ejs_parent > .ejs_game > .ejs_canvas > <canvas>
   Son CSS (.ejs_parent, .ejs_game, .ejs_canvas) est charge par
   jeu.html. On fixe la chaine nous-memes pour que le jeu occupe TOUTE
   la zone de jeu, quels que soient les styles par defaut du core. */

#game,
#game .ejs_parent,
#game .ejs_game,
#game .ejs_canvas,
#game .ejs_canvas_parent {
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
}

/* Le canvas garde son RATIO D'ASPECT.
   .ejs_canvas de l'EmulatorJS impose width:100%; height:100% : le
   canvas 320x240 du NES se retrouvait etire en 390x651 sur mobile
   (ratio 4:3 -> 0,6), donc l'image etait DEFORMEE.

   ATTENTION : object-fit NE MARCHE PAS sur un <canvas> (c'est un
   contenu bitmap, pas un element remplace comme <img> ou <video> :
   le navigateur ignore la propriete). La seule facon de preserver le
   ratio est de NE PAS l'etirer : on lui donne la taille maximale
   possible dans les deux sens, en gardant son ratio natif.

   Le ratio est impose par EmulatorJS via les attributs width/height
   du canvas, que le navigateur utilise pour l'aspect-ratio
   automatique. */
#game canvas {
  display: block;
  margin: 0 auto;
  /* Le canvas grandit JUSQU'AU PLEIN de la zone, en gardant son
     ratio natif (que le navigateur lit dans les attributs
     width/height du canvas).
     - width:100% + height:auto  -> le canvas prend toute la largeur
       et deduit la hauteur du ratio (320x240 -> 390x292).
     - max-height:100% borne le resultat : sur un ecran bas, le
       canvas est plus haut que la zone, donc il est reduit a la
       hauteur disponible, et le ratio est alors conserve par
       max-width:100% qui reduit aussi la largeur.
     C'est la technique standard pour une image/canvas dans un
     conteneur de ratio different. */
  width: 100%;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  object-fit: initial;
  background: transparent;
}

/* --- La barre de menus d'EmulatorJS ---------------------------------------
   EmulatorJS ajoute sa propre barre en bas de l'ecran (bouton de
   volume, de menu, version du core...). Sur mobile elle RECOUVRE le bas
   de la zone de jeu, la ou le gamepad virtuel est pose (D-PAD,
   Select/Start). Elle est en plus inutile ici : le hub a ses propres
   boutons (Plein ecran, Muet, Sauver l'etat, Commandes...).

   On la masque. Le menu contextuel d'EmulatorJS (le hamburger) reste
   accessible : il est dans le coin superieur droit du canvas, hors de
   la barre. */
#game .ejs_menu_bar,
#game .ejs_big_screen .ejs_menu_bar,
#game .ejs_small_screen .ejs_menu_bar {
  display: none !important;
}
