/*
  css/base.css
  Reinitialisation, styles globaux partages par tous les ecrans (layout racine,
  typographie de base, elements de formulaire).
  Depend de css/tokens.css (variables de design). Ne doit jamais
  definir de couleurs ou d'espacements en dur : passer par les tokens.
*/

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  height: 100%;
  color: var(--color-text);
  background-color: var(--color-bg);
  font-family: var(--font-family-base);
  font-size: var(--font-size-md);
  line-height: var(--line-height-normal);
  -webkit-text-size-adjust: 100%;
}

body {
  min-height: 100%;
  min-height: 100dvh;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  color: var(--color-text);
  background-color: var(--color-bg);
}

#app-root {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  position: relative;
  min-height: 0;
  width: 100%;
}

#app-root[aria-busy="true"] {
  opacity: 0.7;
  transition: opacity var(--duration-fast) var(--easing-standard);
}

h1,
h2,
h3,
h4,
p {
  margin: 0;
}

button {
  font: inherit;
  color: inherit;
  cursor: pointer;
  border: none;
  background: none;
  padding: 0;
  margin: 0;
  text-align: center;
  touch-action: manipulation;
}

/* Composant transverse ".btn" : socle commun a tous les boutons de
   l'application (menu, createRoom, joinRoom, lobby, game, vote, results,
   settings appliquent tous "btn" en plus d'un modificateur de couleur -
   btn-primary/btn-secondary/btn-ghost - defini dans menu.css - et/ou d'une
   classe de geometrie propre a l'ecran). Avant ce correctif (audit alpha,
   voir AUDIT_ALPHA.md), cette classe etait referencee comme "deja definie
   ici" par les commentaires d'en-tete de game.css et settings.css mais
   n'existait nulle part dans le projet : chaque ecran s'en sortait en
   dupliquant sa propre geometrie (aucun rendu casse), mais la classe
   partagee prevue par l'architecture n'existait que de nom. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  border-radius: var(--radius-lg);
  transition: background-color var(--duration-fast) var(--easing-standard),
    opacity var(--duration-fast) var(--easing-standard);
}

.btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

a {
  color: var(--color-primary);
  text-decoration: underline;
  text-underline-offset: var(--space-1);
}

a:focus-visible,
button:focus-visible {
  outline: none;
}

img,
svg {
  display: block;
  max-width: 100%;
}

[hidden] {
  display: none !important;
}

/* ---------------------------------------------------------------------------
   BETA B2 — Indicateur de statut reseau (networkStatus.js).
   Badge fixe en haut a droite, discret (8px de point colore), s'etend pour
   afficher un texte uniquement en mode reconnecting/offline.
   --------------------------------------------------------------------------- */
.network-indicator {
  position: fixed;
  top: calc(var(--space-2) + var(--space-safe-top));
  right: calc(var(--space-2) + var(--space-safe-right));
  z-index: var(--z-toast);
  display: flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-full);
  background-color: var(--color-surface-raised);
  box-shadow: var(--shadow-sm);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  pointer-events: none;
  transition: opacity var(--duration-base) var(--easing-standard);
}

.network-indicator[data-status="online"] {
  opacity: 0.5;
}

.network-indicator__dot {
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  flex-shrink: 0;
}

.network-indicator__dot--online {
  background-color: var(--color-success);
}

.network-indicator__dot--reconnecting {
  background-color: var(--color-warning);
  animation: network-pulse 1.2s ease-in-out infinite;
}

.network-indicator__dot--offline {
  background-color: var(--color-danger);
}

.network-indicator__label {
  white-space: nowrap;
}

.network-indicator[data-status="online"] .network-indicator__label {
  display: none;
}

@keyframes network-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.3; }
}

@media (prefers-reduced-motion: reduce) {
  .network-indicator__dot--reconnecting {
    animation: none;
  }
}

/* ---------------------------------------------------------------------------
   BETA B4 — Notifications transitoires (js/core/toast.js). Empilees en haut
   de l'ecran, sous le badge reseau. L'animation d'entree/sortie utilise
   exclusivement transform/opacity (jamais de recalcul de mise en page) et
   sa duree provient de --duration-base (tokens.css) : deja neutralisee a
   0ms par [data-reduce-motion="true"] (accessibility.css) ET par
   prefers-reduced-motion via la regle generique plus haut dans ce fichier
   -- aucune media query supplementaire necessaire ici.
   --------------------------------------------------------------------------- */
.toast-container {
  position: fixed;
  top: calc(var(--space-10) + var(--space-safe-top));
  left: 50%;
  transform: translateX(-50%);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  pointer-events: none;
  max-width: calc(100vw - var(--space-4));
}

.toast {
  margin: 0;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  background-color: var(--color-surface-raised);
  color: var(--color-text);
  box-shadow: var(--shadow-md);
  font-size: var(--font-size-sm);
  text-align: center;
  animation: toast-in var(--duration-base) var(--easing-standard);
}

.toast--leaving {
  animation: toast-out var(--duration-base) var(--easing-standard) forwards;
}

@keyframes toast-in {
  from { opacity: 0; transform: translateY(-8px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes toast-out {
  from { opacity: 1; transform: translateY(0); }
  to { opacity: 0; transform: translateY(-8px); }
}

/* ---------------------------------------------------------------------------
   R2 (PWA) — Bannere de mise a jour du service worker (js/core/pwaUpdate.js).
   Fixee en bas de l'ecran (jamais en haut : ne doit jamais chevaucher le
   badge reseau ni les notifications toast). Purement informative et
   ignorable — jamais de rechargement sans clic explicite sur "Mettre a
   jour", voir PWA_ARCHITECTURE.md section 3.6.
   --------------------------------------------------------------------------- */
.pwa-update-banner {
  position: fixed;
  left: 50%;
  bottom: calc(var(--space-4) + var(--space-safe-bottom));
  transform: translateX(-50%);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  width: calc(100vw - var(--space-6));
  max-width: 24rem;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface-raised);
  box-shadow: var(--shadow-lg);
  animation: toast-in var(--duration-base) var(--easing-standard);
}

.pwa-update-banner__text {
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--color-text);
  text-align: center;
}

.pwa-update-banner__actions {
  display: flex;
  gap: var(--space-2);
}

/* ---------------------------------------------------------------------------
   R4 (Ads) — Emplacements publicitaires reserves (js/core/ads.js). Voir
   ADS_ARCHITECTURE.md section 1. Taille et position stables des le
   montage : ni la banniere Menu ni l'interstitiel ne doivent jamais
   provoquer de saut de mise en page, que le contenu soit l'espace reserve
   neutre actuel ou une future creature reelle de dimensions comparables.
   --------------------------------------------------------------------------- */
.ad-slot {
  width: 100%;
  border-radius: var(--radius-md);
  background-color: var(--color-surface-sunken);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.ad-slot--banner {
  max-width: var(--layout-content-max-width);
  /* ~50px : format banniere mobile standard (320x50), reserve qu'un
     placement reel occupe une hauteur comparable, jamais davantage. */
  min-height: 3.125rem;
}

.ad-slot__placeholder {
  margin: 0;
  padding: var(--space-2);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  text-align: center;
}

/* Interstitiel : reutilise .menu-modal/.menu-modal__overlay/.menu-modal__panel
   (css/menu.css) - seuls ces ajustements sont propres au format. */
.ad-interstitial__panel {
  min-height: 60vh;
  max-height: 80vh;
  justify-content: center;
}

.ad-interstitial__label {
  font-size: var(--font-size-lg);
}

/* ---------------------------------------------------------------------------
   R4 (Ads) — Modale de consentement RGPD (js/core/consentDialog.js). Reutilise
   .menu-modal (css/menu.css). Voir ADS_ARCHITECTURE.md section 2.4 : les
   deux boutons de decision doivent avoir un poids visuel strictement egal
   (meme largeur, meme hauteur, meme style de bouton plein) - le bouton de
   fermeture neutre est volontairement distinct (coin, discret) pour ne
   jamais rivaliser avec Accepter/Refuser.
   --------------------------------------------------------------------------- */
.consent-dialog__more-toggle {
  padding: var(--space-1) var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--color-primary);
  text-decoration: underline;
}

.consent-dialog__more-text {
  font-size: var(--font-size-sm);
}

.consent-dialog__actions {
  display: flex;
  gap: var(--space-3);
  width: 100%;
}

.consent-dialog__accept,
.consent-dialog__refuse {
  flex: 1 1 0;
  min-height: var(--touch-target-comfortable);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-medium);
}

.consent-dialog__close {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--touch-target-min);
  height: var(--touch-target-min);
  color: var(--color-text-muted);
}
