:root {
  --blue: #00209F;
  --blue-2: #001560; /* 2e couleur du dégradé de la barre du haut — thémable, voir applyTheme() */
  --red: #D21034;
  --bg: #0b1220;
  --card: #141d33;
  --card-2: #1b2740;
  --text: #eef2ff;
  --muted: #93a1c4;
  --green: #22c55e;
  --radius: 16px;
  /* Photo de fond dédiée à la barre du haut (voir applyTopbarBgImage() dans app.js/
     admin.js) — 'none' par défaut : la barre garde alors uniquement le dégradé
     --blue/--blue-2 du thème actif, comportement strictement identique à avant cet
     ajout. --topbar-overlay assombrit légèrement la photo pour que le logo et les liens
     (Contact/Se déconnecter, toujours en texte clair) restent lisibles par-dessus
     n'importe quelle image. */
  --topbar-bg-image: none;
  --topbar-overlay: none;
  /* Accent "futuriste" (juillet 2026, voir .game-panel/.glow-card ci-dessous) — un cyan
     électrique volontairement distinct de --blue/--red pour ne pas se confondre avec les
     couleurs de marque, mais assez proche du --blue existant pour rester cohérent avec un
     thème saisonnier qui changerait --blue (voir applyThemeVars() dans app.js/admin.js :
     cette variable n'est PAS réinitialisée par changement de thème, elle reste fixe pour
     que l'habillage "futuriste" ne clignote pas d'une couleur à l'autre à chaque thème).
  */
  --accent-glow: #26d6ff;
  /* Texte adaptatif des cartes (juillet 2026, voir updateCardContrastColor() dans
     app.js/admin.js) — par défaut, identiques à --text/--muted (donc AUCUN changement
     visuel tant que l'admin n'a pas personnalisé la couleur des cartes dans Réglages).
     Une fois une couleur de carte personnalisée choisie, ces deux variables sont
     recalculées en JS pour rester lisibles dessus : blanc si la couleur est foncée,
     rouge ou bleu (celui qui contraste le mieux) si elle est pâle. */
  --card-text: var(--text);
  --card-muted: var(--muted);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  height: 100%;
}

/* Filigrane du logo, visible en fond sur tout l'écran (connexion, jeux, portefeuille,
   agent, admin...) — appliqué sur <body> donc indépendant du contenu re-rendu en JS. */
body {
  background-image: url('logo-watermark.png');
  background-repeat: no-repeat;
  background-position: center 38vh;
  background-size: min(320px, 70vw) auto;
  background-attachment: fixed;
}

#app {
  max-width: 480px;
  margin: 0 auto;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  padding-bottom: 76px;
  position: relative;
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 20px 12px;
  /* 3 couches, la première listée dessine par-dessus les suivantes : l'assombrissement
     (--topbar-overlay), puis l'éventuelle photo (--topbar-bg-image), puis le dégradé du
     thème actif en dernier recours (toujours visible si les deux premières sont 'none',
     c'est-à-dire tant qu'aucune photo de barre du haut n'a été définie). */
  background-image: var(--topbar-overlay), var(--topbar-bg-image), linear-gradient(135deg, var(--blue), var(--blue-2));
  background-size: cover, cover, auto;
  background-position: center, center, center;
  background-repeat: no-repeat, no-repeat, no-repeat;
}

.topbar h1 {
  font-size: 20px;
  margin: 0;
}

.topbar-logo {
  height: 60px;
  width: auto;
  display: block;
}

.points-pill {
  background: var(--red);
  padding: 6px 14px;
  border-radius: 999px;
  font-weight: 700;
  font-size: 14px;
}

.view {
  padding: 16px 18px 8px;
  flex: 1;
}

.card {
  background: var(--card);
  color: var(--card-text);
  border-radius: var(--radius);
  padding: 18px;
  margin-bottom: 16px;
  box-shadow: 0 2px 10px rgba(0,0,0,0.25);
}

.card h2 {
  margin: 0 0 10px;
  font-size: 17px;
}

.card p {
  color: var(--card-muted);
  font-size: 14px;
  line-height: 1.5;
  margin: 4px 0;
}

.grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.tile {
  background: var(--card-2);
  border-radius: var(--radius);
  padding: 16px;
  text-align: center;
  cursor: pointer;
  border: none;
  color: var(--card-text);
  font-size: 15px;
  font-weight: 600;
}

.tile .emoji {
  font-size: 28px;
  display: block;
  margin-bottom: 8px;
}

/* ---- Vitrine "futuriste" de l'accueil (juillet 2026) ----
   .game-hub/.game-panel remplacent les .tile plates pour les deux jeux sur l'accueil —
   chaque jeu devient une carte à part entière avec son propre badge lumineux, plutôt
   qu'un simple bouton avec une emoji. .glow-card habille la bannière de thème saisonnier
   et la carte "Défi du jour" avec le même langage visuel (bordure/lueur cyan), pour que
   les trois éléments lisent comme un seul ensemble cohérent plutôt que des ajouts
   disparates. Volontairement en CSS pur (dégradés, box-shadow, une seule keyframe) — pas
   d'image ni de police externe, cohérent avec le choix zéro-dépendance de l'app. */
.game-hub {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 16px;
}

.game-panel {
  position: relative;
  background: linear-gradient(160deg, var(--card-2), var(--card));
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius);
  padding: 18px 16px;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  color: var(--card-text);
  box-shadow: 0 0 0 1px rgba(38, 214, 255, 0.1), 0 8px 20px rgba(0, 0, 0, 0.3);
  transition: transform 0.12s ease;
}

.game-panel:active {
  transform: scale(0.97);
}

/* Halo décoratif dans le coin — purement cosmétique, ne capte jamais le clic
   (pointer-events: none), positionné en dehors du flux (inset négatif) pour ne jamais
   pousser le contenu texte. */
.game-panel::before {
  content: '';
  position: absolute;
  inset: -30% -30% auto auto;
  width: 120px;
  height: 120px;
  background: radial-gradient(circle, rgba(38, 214, 255, 0.22), transparent 70%);
  pointer-events: none;
}

.game-panel .icon-badge {
  width: 44px;
  height: 44px;
  border-radius: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 21px;
  background: linear-gradient(135deg, var(--blue), var(--blue-2));
  box-shadow: 0 0 14px rgba(38, 214, 255, 0.45);
  margin-bottom: 10px;
  position: relative;
}

.game-panel h3 {
  font-size: 15px;
  font-weight: 700;
  margin: 0 0 4px;
}

.game-panel p {
  font-size: 12px;
  color: var(--card-muted);
  margin: 0;
}

.game-panel .panel-cta {
  margin-top: 12px;
  font-size: 12px;
  font-weight: 700;
  color: var(--accent-glow);
  display: flex;
  align-items: center;
  gap: 4px;
}

/* Carte à bordure/lueur cyan — bannière de thème saisonnier et carte "Défi du jour"
   (voir renderHome() dans app.js). */
.glow-card {
  border-left: 3px solid var(--accent-glow);
  box-shadow: 0 0 16px rgba(38, 214, 255, 0.16);
}

/* Défi du jour déjà relevé aujourd'hui — bascule la lueur du cyan vers le vert de succès
   (déjà utilisé ailleurs pour les montants positifs, voir .tx-amount.pos), pour que l'état
   "gagné" soit reconnaissable d'un coup d'œil sans avoir à lire le texte. */
.glow-card.challenge-done {
  border-left-color: var(--green);
  box-shadow: 0 0 16px rgba(34, 197, 94, 0.22);
}

/* Panneau publicitaire (juillet 2026, voir renderAdOverlayIfNeeded() dans app.js) —
   image au format portrait (9:16) en surimpression, légèrement rétrécie par rapport à
   l'écran plutôt qu'en plein écran, avec un bouton (x) pour fermer. Affiché une fois par
   session, joueur comme agent — l'admin remplace l'image depuis /admin.html → Réglages. */
.ad-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.72);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  z-index: 1000;
}

.ad-panel {
  position: relative;
  width: min(78vw, 320px);
  aspect-ratio: 9 / 16;
  max-height: 82vh;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--card);
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.55);
}

.ad-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.ad-close {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

button.primary, a.primary {
  width: 100%;
  padding: 14px;
  background: var(--red);
  color: white;
  border: none;
  border-radius: 12px;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  box-sizing: border-box;
}

button.secondary {
  width: 100%;
  padding: 14px;
  background: transparent;
  color: var(--text);
  border: 1px solid var(--muted);
  border-radius: 12px;
  font-size: 15px;
  cursor: pointer;
  margin-top: 8px;
}

input, select, textarea {
  width: 100%;
  padding: 13px 14px;
  border-radius: 10px;
  border: 1px solid #2a3555;
  background: #0f1830;
  color: var(--text);
  font-size: 15px;
  margin-bottom: 12px;
}

textarea {
  font-family: inherit;
  resize: vertical;
}

/* Champ mot de passe avec bouton "œil" (voir pwdField() dans app.js/admin.js). */
.pwd-wrap {
  position: relative;
}

.pwd-wrap input {
  padding-right: 46px;
  margin-bottom: 0;
}

.pwd-wrap {
  margin-bottom: 12px;
}

.pwd-toggle {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 44px;
  padding: 0;
  margin: 0;
  border: none;
  background: transparent;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Champ téléphone avec préfixe "+509" fixe (voir phoneField() dans app.js) — le joueur
   ne tape que les 8 chiffres locaux, le "+509" n'est jamais éditable. */
.phone-wrap {
  position: relative;
  margin-bottom: 12px;
}

.phone-wrap input {
  padding-left: 58px;
  margin-bottom: 0;
}

.phone-prefix {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  color: var(--muted);
  pointer-events: none;
}

.error-banner {
  background: rgba(210,16,52,0.15);
  border: 1px solid var(--red);
  color: #ffb4c0;
  padding: 10px 12px;
  border-radius: 10px;
  font-size: 13px;
  margin-bottom: 12px;
}

.success-banner {
  background: rgba(34,197,94,0.15);
  border: 1px solid var(--green);
  color: #a7f3d0;
  padding: 10px 12px;
  border-radius: 10px;
  font-size: 13px;
  margin-bottom: 12px;
}

.choice-btn {
  width: 100%;
  text-align: left;
  padding: 14px;
  margin-bottom: 10px;
  border-radius: 12px;
  border: 1px solid #2a3555;
  background: var(--card-2);
  color: var(--card-text);
  font-size: 15px;
  cursor: pointer;
}

.choice-btn.selected {
  border-color: var(--red);
  background: rgba(210,16,52,0.2);
}

.choice-btn.correct {
  border-color: var(--green);
  background: rgba(34,197,94,0.2);
}

.choice-btn.wrong {
  border-color: var(--red);
  background: rgba(210,16,52,0.25);
}

.progress-dots {
  display: flex;
  gap: 6px;
  margin-bottom: 14px;
}

.progress-dots span {
  flex: 1;
  height: 4px;
  border-radius: 2px;
  background: #2a3555;
}

.progress-dots span.done { background: var(--red); }

.leader-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 4px;
  border-bottom: 1px solid #22304f;
  font-size: 14px;
}

.leader-row.me { color: var(--red); font-weight: 700; }

.leader-row .rank {
  width: 28px;
  color: var(--card-muted);
}

.tabbar {
  position: fixed;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 480px;
  background: var(--card);
  display: flex;
  border-top: 1px solid #22304f;
  padding: 8px 6px calc(8px + env(safe-area-inset-bottom));
}

.tabbar button {
  flex: 1;
  background: none;
  border: none;
  color: var(--card-muted);
  font-size: 11px;
  padding: 6px 2px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  cursor: pointer;
}

.tabbar button.active { color: var(--red); }
.tabbar button.active .icon { text-shadow: 0 0 10px rgba(38, 214, 255, 0.55); }
.tabbar button .icon { font-size: 20px; }

.auth-screen {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 24px;
}

.auth-logo {
  text-align: center;
  margin-bottom: 24px;
}

.auth-logo .brand {
  font-size: 30px;
  font-weight: 800;
}

.auth-logo-img {
  max-width: 260px;
  width: 70%;
  height: auto;
  display: block;
  margin: 0 auto;
}

.auth-logo .tagline {
  color: var(--muted);
  font-size: 14px;
  margin-top: 6px;
}

.link-btn {
  background: none;
  border: none;
  color: #7fa5ff;
  font-size: 14px;
  cursor: pointer;
  text-decoration: underline;
}

.timer {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--red);
}

.stat-row {
  display: flex;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid #22304f;
  font-size: 14px;
}

.tx-row {
  display: flex;
  justify-content: space-between;
  font-size: 13px;
  padding: 8px 0;
  border-bottom: 1px solid #22304f;
}

.tx-amount.pos { color: var(--green); font-weight: 700; }
.tx-amount.neg { color: var(--red); font-weight: 700; }

.center-msg {
  text-align: center;
  color: var(--muted);
  padding: 40px 10px;
}

/* Décor animé du thème saisonnier (voir applyTheme() dans app.js/admin.js) — un
   conteneur plein écran, non cliquable, ajouté une seule fois à <body>, avant #app dans
   le DOM (pas à l'intérieur, qui est entièrement remplacé à chaque rendu) pour que
   l'animation ne redémarre jamais en boucle. Placé avant #app dans le DOM donc peint en
   dessous — visible dans les espaces transparents entre les cartes, jamais par-dessus le
   contenu (même principe que le filigrane du logo sur <body>). Chaque particule dérive
   du haut vers le bas de l'écran en boucle infinie. */
#theme-particles {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

#theme-particles .particle {
  position: absolute;
  top: -10%;
  font-size: 20px;
  opacity: 0.55;
  animation: theme-drift linear infinite;
  will-change: transform;
}

@keyframes theme-drift {
  0% { transform: translateY(0) rotate(0deg); }
  100% { transform: translateY(115vh) rotate(360deg); }
}

/* Impression du "Rapport global" agents (Admin, voir renderAgentsReport() dans admin.js).
   Technique standard : on cache tout le document sauf #agents-report-printable et son
   contenu, qu'on replace en haut de la page — évite de dépendre de la structure DOM
   exacte de l'admin (topbar, tuiles de section, boutons...) qui ne doit jamais
   apparaître sur la feuille imprimée. .no-print masque en plus les contrôles
   (sélecteurs de date, bouton Imprimer lui-même) qui n'ont aucun sens sur papier. */
@media print {
  body * { visibility: hidden; }
  #agents-report-printable, #agents-report-printable * { visibility: visible; }
  #agents-report-printable {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    color: #000;
  }
  .no-print { display: none !important; }
}
