@import url("https://fonts.googleapis.com/css2?family=Spectral:wght@400;500;600&family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap");

/* ==================================================================
   Ilari · feuille de style
   Palette inspirée de Battle for Azeroth (Kul Tiras / azérite) :
   marine profond, sarcelle, or en accent rare. Priorité à la lisibilité :
   fonds opaques, contrastes tenus, or réservé à l'état actif et aux
   valeurs clés.
   ================================================================== */

:root {
  /* Fonds · opaques, pas de translucide ni de flou */
  --bg: #0d141c;
  --bg-panel: #131c26;
  --bg-card: #121a23;
  --bg-subtle: #182230;
  --bg-hover: #1a2534;

  /* Traits */
  --border: #253140;
  --border-strong: #35455a;
  --border-accent: #6a5525;

  /* Accents */
  --gold: #c9a24a;
  --gold-bright: #e6cb8b;
  --teal: #56a0ad;
  --teal-dim: #2c4b56;
  --steel: #a9b8c8;
  --green: #74c091;
  --red: #dd8f8f;

  /* Texte · contrastes relevés par rapport à l'ancienne palette */
  --text: #eef2f6;
  --text-soft: #c3cedb;
  --text-dim: #93a3b4;

  --radius: 12px;
  --radius-sm: 8px;

  --font-ui: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-display: "Spectral", Georgia, serif;
  --font-mono: "IBM Plex Mono", ui-monospace, monospace;
}

* {
  box-sizing: border-box;
}

/* Toute la feuille est en rem : la base pilote l'échelle d'un seul endroit. */
html {
  font-size: 18px;
}

body {
  margin: 0;
  min-height: 100vh;
  font-family: var(--font-ui);
  font-size: 1rem;
  color: var(--text);
  line-height: 1.6;
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

a {
  color: var(--teal);
}

a:hover {
  color: var(--gold-bright);
}

.page {
  max-width: 1360px;
  margin: 0 auto;
  padding: 32px 40px 80px;
}

/* ---------- En-tête ---------- */

.top-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding-bottom: 20px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
}

.brand img {
  width: 32px;
  height: 32px;
}

.brand h1 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--text);
}

.clock {
  display: flex;
  align-items: baseline;
  gap: 12px;
  text-align: right;
}

.clock .time {
  font-family: var(--font-mono);
  font-size: 1.15rem;
  font-weight: 500;
  color: var(--text);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.clock .date {
  font-size: 0.85rem;
  color: var(--text-dim);
  text-transform: capitalize;
}

/* Latence serveur. Chiffre discret, couleur portée par la pastille : le nombre
   change toutes les 2 secondes, un texte coloré clignoterait dans le coin de l'œil. */
.ping {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  cursor: default;
}

.ping-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--text-dim);
  flex-shrink: 0;
}

.ping-bon .ping-dot {
  background: var(--green);
  box-shadow: 0 0 6px rgba(116, 192, 145, 0.45);
}

.ping-moyen .ping-dot {
  background: var(--gold);
}

.ping-mauvais .ping-dot,
.ping-hors-ligne .ping-dot {
  background: var(--red);
}

.ping-hors-ligne .ping-value {
  color: var(--red);
}

/* ---------- Navigation ---------- */
/* Onglets soulignés plutôt que pastilles : moins de formes, plus lisible. */

.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 40px;
  border-bottom: 1px solid var(--border);
}

.tabs a {
  padding: 11px 18px;
  text-decoration: none;
  color: var(--text-dim);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  font-size: 1.02rem;
  font-weight: 500;
  transition: color 0.12s ease, border-color 0.12s ease;
}

.tabs a:hover {
  color: var(--text);
}

.tabs a.active {
  color: var(--gold-bright);
  border-bottom-color: var(--gold);
}

/* ---------- Titres de page ---------- */
/* Alignés à gauche : le regard part toujours du même point. */

/* Niveau page : or. C'est le seul niveau à le porter, avec les valeurs clés. */
.greeting,
.section-heading {
  font-family: var(--font-display);
  font-size: 2.05rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--gold-bright);
  text-align: left;
  margin: 0 0 26px;
}

.greeting .greeting-name {
  color: var(--gold-bright);
}

/* ---------- Grilles ---------- */

/* Trois colonnes plutôt que quatre : des cartes plus larges et mieux espacées. */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(380px, 1fr));
  gap: 28px;
}

.dashboard-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px;
}

.card--wide {
  grid-column: 1 / -1;
  min-height: 220px;
}

/* .card n'a par elle-même aucune marge (voir la règle .card plus haut) : elle
   compte entièrement sur .grid pour être espacée de ses voisines. Plusieurs
   pages posent pourtant deux .card directement l'une après l'autre, hors
   d'une .grid (ex. "Serveur"/"Classement" dans discord-niveaux.js, les deux
   sections de requetes-ia.js...) · sans marge, elles se retrouvaient collées,
   comme fusionnées. Règle générale plutôt qu'un correctif par page : même
   espacement que .grid (28px), neutralisé quand les deux cartes sont déjà
   dans une .grid pour ne pas cumuler les deux espacements (03/09/2026). */
.card + .card {
  margin-top: 28px;
}
.grid > .card + .card {
  margin-top: 0;
}

/* État Discord (01/09/2026) : "Profil du bot" est une carte pleine largeur
   posée AVANT la grille "État machine"/"État Discord", pas dedans (voir
   charger() dans discord.js) · sans ceci, .card n'a aucune marge propre et
   les deux se retrouvaient collées, comme fusionnées. Même espacement que
   .grid pour rester cohérent visuellement. Même souci et même correctif pour
   #machine-root/#machine-stats côté Administration (voir admin-system.js) :
   une grille suivie ou précédée d'une carte pleine largeur, hors de la
   grille elle-même.
*/
#discord-root,
#machine-root,
#machine-stats {
  display: flex;
  flex-direction: column;
  gap: 28px;
}

/* ---------- Cartes ---------- */

.card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 24px 26px;
}

/* Niveau carte : or, entre le titre de page et les intertitres internes.
   La hiérarchie se lit à la taille, l'or restant réservé aux niveaux de titre. */
.card h2,
.card h3 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.7rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--gold-bright);
}

/* Niveau bloc : sarcelle, pour trancher avec le blanc du contenu. */
.card h4 {
  margin: 0 0 10px;
  font-size: 1.06rem;
  font-weight: 600;
  color: var(--teal);
}

.card > h2 + *,
.card > h3 + * {
  margin-top: 18px;
}

.card-subtitle {
  display: block;
  margin: 5px 0 0;
  font-family: var(--font-ui);
  font-size: 0.95rem;
  font-weight: 400;
  color: var(--text-dim);
}

h2 .card-subtitle,
h3 .card-subtitle,
h4 .card-subtitle {
  display: inline;
  margin-left: 10px;
}

.card-heading-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.muted-note {
  color: var(--text-dim);
  font-size: 0.88rem;
}

.empty-state {
  color: var(--text-dim);
  font-size: 0.9rem;
  line-height: 1.5;
}

/* !important nécessaire (01/09/2026) : un sélecteur d'ID (ex. #discord-root)
   a une spécificité plus forte qu'une classe et l'emportait sur ce
   display:none dès qu'il posait lui-même un display · les sous-onglets se
   chevauchaient au lieu de se cacher. .is-hidden doit gagner partout, sans
   exception, c'est tout son rôle. */
.is-hidden {
  display: none !important;
}

/* ---------- Météo ---------- */

.weather-main {
  display: flex;
  align-items: center;
  gap: 14px;
}

.weather-icon {
  display: inline-flex;
  color: var(--teal);
}

.weather-icon svg {
  width: 32px;
  height: 32px;
}

.weather-main .temp {
  font-family: var(--font-mono);
  font-size: 2rem;
  font-weight: 400;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.weather-sub {
  margin-top: 10px;
  color: var(--text-dim);
  font-size: 0.9rem;
}

/* ---------- Agenda du jour ---------- */

.event-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.event-list li {
  display: flex;
  gap: 16px;
  align-items: baseline;
  font-size: 0.94rem;
  padding: 7px 0;
}

.event-time {
  font-family: var(--font-mono);
  font-size: 0.86rem;
  color: var(--teal);
  font-variant-numeric: tabular-nums;
  min-width: 44px;
  flex-shrink: 0;
}

.event-title {
  color: var(--text-soft);
  overflow-wrap: break-word;
  min-width: 0;
}

.event-allday .event-time,
.event-allday .event-title {
  font-weight: 600;
  color: var(--text);
}

.event-list li.event-divider {
  display: block;
  height: 1px;
  background: var(--border);
  margin: 8px 0;
  padding: 0;
  list-style: none;
}

/* ---------- Actualités ---------- */

.news-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
}

.news-list li {
  border-left: none;
  border-bottom: 1px solid var(--border);
  padding: 12px 0;
  font-size: 0.92rem;
}

.news-list li:first-child {
  padding-top: 0;
}

.news-list li:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.news-list a {
  color: var(--text-soft);
  text-decoration: none;
}

.news-list a:visited {
  color: var(--text-dim);
}

.news-list a:hover {
  color: var(--gold-bright);
}

.news-list .news-source {
  display: block;
  margin-bottom: 3px;
  color: var(--text-dim);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.badge {
  display: inline-block;
  font-size: 0.7rem;
  padding: 2px 8px;
  border-radius: 4px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  color: var(--text-dim);
  margin-left: 8px;
}

/* ---------- Sous-onglets ---------- */

.sub-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 24px;
}

.sub-tab {
  background: none;
  border: 1px solid var(--border);
  color: var(--text-dim);
  padding: 9px 20px;
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 0.98rem;
  font-weight: 500;
  cursor: pointer;
  transition: color 0.12s ease, border-color 0.12s ease, background 0.12s ease;
}

.sub-tab:hover {
  color: var(--text);
  background: var(--bg-hover);
}

.sub-tab.active {
  color: var(--text);
  border-color: var(--border-strong);
  background: var(--bg-subtle);
}

/* ---------- Boutons ---------- */

.modal-btn {
  padding: 9px 18px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}

/* Sans ceci, un bouton désactivé garde exactement les couleurs de sa
   variante (ex. modal-btn--primary reste doré) · rien ne distinguait un
   bouton qu'on ne peut pas encore cliquer d'un bouton prêt (03/09/2026,
   Morey, pour le bouton Valider de Combo). L'important gagne sur toutes
   les variantes de couleur, sans exception. */
.modal-btn:disabled {
  background: var(--bg-subtle) !important;
  border-color: var(--border) !important;
  color: var(--text-dim) !important;
  cursor: not-allowed;
}

.modal-btn--ghost {
  background: none;
  border-color: var(--border);
  color: var(--text-soft);
}

.modal-btn--ghost:hover {
  color: var(--text);
  background: var(--bg-hover);
  border-color: var(--border-strong);
}

.modal-btn--primary {
  background: var(--gold);
  color: #1a1305;
  font-weight: 600;
}

.modal-btn--primary:hover {
  background: var(--gold-bright);
}

.modal-btn--small {
  padding: 7px 14px;
  font-size: 0.85rem;
}

.modal-btn--danger {
  background: none;
  border: 1px solid #5a3a3a;
  color: var(--red);
}

.modal-btn--danger:hover {
  background: #2a1c1c;
  border-color: #7a4d4d;
}

/* ---------- Bascule Pro / Perso et profil ---------- */

.mode-toggle {
  background: none;
  border: 1px solid var(--border);
  color: var(--text-soft);
  padding: 8px 16px;
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 0.88rem;
  font-weight: 500;
  cursor: pointer;
  margin-right: 4px;
}

.mode-toggle:hover {
  color: var(--gold-bright);
  border-color: var(--border-accent);
  background: var(--bg-hover);
}

.profile-tab-wrap {
  position: relative;
}

.profile-tab {
  background: none;
  border: 1px solid var(--border);
  color: var(--text-soft);
  padding: 8px 16px;
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 0.88rem;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.profile-tab svg {
  width: 15px;
  height: 15px;
}

.profile-tab:hover {
  color: var(--text);
  border-color: var(--border-strong);
  background: var(--bg-hover);
}

.profile-menu {
  position: absolute;
  right: 0;
  top: 100%;
  margin-top: 8px;
  background: var(--bg-panel);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55);
  min-width: 230px;
  overflow: hidden;
  z-index: 30;
}

.profile-menu.is-hidden {
  display: none;
}

.profile-menu button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 11px 16px;
  background: none;
  border: none;
  color: var(--text-soft);
  font-family: inherit;
  font-size: 0.9rem;
  cursor: pointer;
}

.profile-menu button:hover {
  background: var(--bg-hover);
  color: var(--text);
}

/* ---------- Connexion ---------- */

.login-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.login-card {
  width: 100%;
  max-width: 380px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 40px 36px;
  text-align: center;
}

.login-logo {
  width: 44px;
  height: 44px;
  margin-bottom: 16px;
}

.login-card h1 {
  margin: 0 0 28px;
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: 500;
  color: var(--text);
}

.login-card form {
  display: flex;
  flex-direction: column;
  gap: 0;
  text-align: left;
}

/* `.login-card form` (ci-dessus) a une spécificité plus forte que `.is-hidden`
   seul (0,1,1 contre 0,1,0) : sans cette règle, le formulaire d'inscription
   masqué restait affiché en `flex` par-dessus celui de connexion. */
.login-card form.is-hidden {
  display: none;
}

.login-card label {
  font-size: 0.82rem;
  color: var(--text-dim);
  margin-top: 14px;
  margin-bottom: 6px;
}

.login-card input {
  /* Le formulaire est une colonne flex : ses enfants directs s'étirent seuls,
     mais un champ imbriqué garderait sa largeur intrinsèque (~221 px). */
  width: 100%;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 11px 14px;
  font-family: inherit;
  font-size: 0.95rem;
}

.login-card input:focus {
  outline: none;
  border-color: var(--teal);
}

.login-error {
  min-height: 1.2em;
  color: var(--red);
  font-size: 0.85rem;
  margin: 12px 0 0;
}

.login-submit {
  width: 100%;
  margin-top: 24px;
  padding: 12px;
}

#register-retour {
  width: 100%;
  margin-top: 10px;
  padding: 12px;
}

/* ---------- Formulaires ---------- */

.field-label {
  display: block;
  font-size: 0.85rem;
  color: var(--text-dim);
  margin: 16px 0 6px;
}

.form-row {
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
}

.form-field {
  flex: 1;
  min-width: 220px;
}

.form-field input {
  width: 100%;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 11px 14px;
  color: var(--text);
  font-family: inherit;
  font-size: 0.95rem;
}

.form-field input:focus {
  outline: none;
  border-color: var(--teal);
}

.form-error {
  color: var(--red);
  font-size: 0.88rem;
  min-height: 1.2em;
  margin: 10px 0 0;
}

.form-success {
  color: var(--green);
  font-size: 0.88rem;
  margin: 10px 0 0;
}

.form-success:empty {
  display: none;
}

#suggestion-form input:not([type="file"]),
#suggestion-form textarea {
  width: 100%;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 11px 14px;
  font-family: inherit;
  font-size: 0.95rem;
}

#suggestion-form input:not([type="file"]):focus,
#suggestion-form textarea:focus {
  outline: none;
  border-color: var(--teal);
}

/* 4 types depuis l'ajout de Report (01/09/2026) : deux rangées de deux,
   plus lisible qu'une rangée de 4 serrée autour de "Fonctionnalité". */
#suggestion-form .mode-choice {
  max-width: 420px;
  grid-template-columns: 1fr 1fr;
}

#suggestion-form #suggestion-envoyer {
  margin-top: 16px;
}

.form-status {
  font-size: 0.9rem;
  color: var(--text-dim);
  margin: 12px 0 0;
  min-height: 1.2em;
}

.form-status.is-success {
  color: var(--green);
}

.form-status.is-error {
  color: var(--red);
}

.form-subheading,
.section-subheading {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--teal);
  margin: 28px 0 12px;
}

.pw-label {
  display: block;
  font-size: 0.82rem;
  color: var(--text-dim);
  margin: 14px 0 6px;
}

/* ---------- Modales ---------- */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(6, 10, 15, 0.78);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Un vrai modal doit toujours passer au-dessus de tout le reste, y
     compris le panier « Ventes de la semaine » (z-index 300) · sinon un
     modal ouvert depuis une ligne du panier (ex. modifier la date d'une
     vente) apparaît grisé, écrasé sous le fond du panier. */
  z-index: 400;
  padding: 20px;
}

.modal-card {
  background: var(--bg-panel);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  padding: 28px;
  width: 100%;
  max-width: 440px;
  max-height: 90vh;
  overflow-y: auto;
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6);
}

.modal-card h3 {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--text);
}

.modal-sub {
  margin: 0 0 18px;
  color: var(--text-dim);
  font-size: 0.88rem;
}

.modal-card textarea,
.modal-card input:not([type="checkbox"]):not([type="radio"]),
.modal-card select {
  width: 100%;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 11px 14px;
  font-size: 0.95rem;
  font-family: inherit;
}

.modal-card textarea {
  resize: vertical;
  min-height: 90px;
}

.modal-card textarea:focus,
.modal-card input:focus,
.modal-card select:focus {
  outline: none;
  border-color: var(--teal);
}

.modal-card select option {
  background: var(--bg-panel);
  color: var(--text);
}

.modal-card--wide {
  max-width: 540px;
}

.modal-card--report {
  max-width: 660px;
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 20px;
}

/* Sur mobile, toute modale (déclarer une vente, une rupture, une anomalie...)
   devient un tiroir ancré en bas plutôt qu'une fenêtre centrée : plus facile
   à atteindre au pouce, et les boutons restent au-dessus du clavier virtuel
   au lieu de se retrouver quelque part au milieu de l'écran (04/09/2026). */
@media (max-width: 640px) {
  .modal-overlay {
    align-items: flex-end;
    padding: 0;
  }

  .modal-card {
    max-width: 100%;
    border-radius: 20px 20px 0 0;
    padding: 22px 20px calc(20px + env(safe-area-inset-bottom, 0px));
    animation: ilari-sheet-in 0.18s ease-out;
  }

  .modal-card::before {
    content: "";
    display: block;
    width: 36px;
    height: 4px;
    margin: -10px auto 16px;
    border-radius: 999px;
    background: var(--border-strong);
  }

  .modal-actions .modal-btn {
    flex: 1;
    min-height: 46px;
  }

  .modal-card textarea,
  .modal-card input:not([type="checkbox"]):not([type="radio"]),
  .modal-card select {
    padding: 13px 14px;
  }
}

@keyframes ilari-sheet-in {
  from {
    transform: translateY(16px);
    opacity: 0;
  }
  to {
    transform: none;
    opacity: 1;
  }
}

/* ---------- Tableau de stock ---------- */

.stock-meta {
  color: var(--text-dim);
  font-size: 0.88rem;
  margin: 0 0 18px;
}

.table-wrap {
  overflow-x: auto;
}

.stock-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
}

.stock-table th {
  text-align: left;
  padding: 11px 10px;
  color: var(--teal);
  font-size: 0.82rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  border-bottom: 1px solid var(--border-strong);
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
}

.stock-table th:hover {
  color: var(--text);
}

.stock-table td {
  padding: 13px 10px;
  border-bottom: 1px solid var(--border);
  color: var(--text-soft);
}

.stock-table tbody tr:hover {
  background: var(--bg-hover);
}

.stock-table tbody tr.row-anomaly {
  background: #221a0d;
  box-shadow: inset 3px 0 0 var(--gold);
}

.stock-table tbody tr.row-anomaly:hover {
  background: #2b210f;
}

.status-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  margin-right: 9px;
  vertical-align: middle;
}

.status-en_stock {
  background: var(--green);
}

.status-sur_commande {
  background: var(--gold);
}

.status-indisponible {
  background: var(--red);
}

.status-inconnu,
.status-erreur {
  background: var(--text-dim);
}

.stock-search {
  width: 100%;
  max-width: 340px;
  padding: 10px 14px;
  margin-bottom: 18px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-subtle);
  color: var(--text);
  font-family: inherit;
  font-size: 0.92rem;
}

.stock-search-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.stock-search-row .stock-search {
  margin-bottom: 18px;
}

.stock-search-row .modal-btn {
  margin-bottom: 18px;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.stock-search-row .modal-btn svg {
  width: 16px;
  height: 16px;
}

.stock-search::placeholder {
  color: var(--text-dim);
}

.stock-search:focus {
  outline: none;
  border-color: var(--teal);
}

.clickable-row {
  cursor: pointer;
  /* L'appui long doit ouvrir notre menu, pas la bulle de sélection de texte
     ou le menu natif du navigateur/OS. */
  -webkit-touch-callout: none;
  user-select: none;
}

/* ---------- Colonnes figées (desktop) ---------- */
/* Avec des cellules Évolution/Prix élargies par une promotion (bulle, prix
   barré...), le tableau dépasse largement la largeur de l'écran · la
   colonne Actions ajoutée en bout de ligne se retrouvait alors hors champ,
   invisible sans faire défiler jusqu'au bout (05/09/2026, signalé par
   Morey : "je regardais JBL SARAWAK... j'ai aucun changement"). Produit et
   Actions restent maintenant visibles pendant le défilement horizontal. */

.stock-table th:first-child,
.stock-table td:first-child {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--bg-card);
  box-shadow: 6px 0 6px -6px rgba(0, 0, 0, 0.4);
}

.stock-table th:last-child,
.stock-table td:last-child {
  position: sticky;
  right: 0;
  z-index: 2;
  background: var(--bg-card);
  box-shadow: -6px 0 6px -6px rgba(0, 0, 0, 0.4);
}

.stock-table tbody tr:hover td:first-child,
.stock-table tbody tr:hover td:last-child {
  background: var(--bg-hover);
}

.stock-table tbody tr.row-anomaly td:first-child,
.stock-table tbody tr.row-anomaly td:last-child {
  background: #221a0d;
}

.stock-table tbody tr.row-anomaly:hover td:first-child,
.stock-table tbody tr.row-anomaly:hover td:last-child {
  background: #2b210f;
}

/* ---------- Bouton d'actions visible par ligne (desktop) ---------- */
/* Le clic droit / appui long reste disponible, mais n'était pas découvrable :
   ce bouton donne le même menu sans avoir à le deviner (04/09/2026). */

.col-actions,
.col-actions-head {
  text-align: center;
  width: 44px;
}

.row-kebab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  color: var(--text-soft);
  cursor: pointer;
}

.row-kebab:hover {
  border-color: var(--border-strong);
  background: var(--bg-hover);
  color: var(--text);
}

.row-kebab svg {
  width: 15px;
  height: 15px;
}

/* ---------- Fiches produit (mobile) ---------- */
/* Sous 640px, le tableau à 7 colonnes (défilement horizontal seul jusque-là)
   devient une liste de fiches repliées · voir cardHtml() dans stock.js, qui
   réutilise les mêmes fonctions de cellule (donc les mêmes bulles promo /
   vendeur) que le tableau. Les deux vues coexistent dans le DOM, une seule
   visible à la fois via ce media query (04/09/2026). */

.stock-cards {
  display: none;
}

@media (max-width: 640px) {
  .table-wrap {
    display: none;
  }

  .stock-cards {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

  .stock-card {
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-card);
    overflow: hidden;
  }

  .stock-card.is-anomaly {
    background: #221a0d;
    box-shadow: inset 3px 0 0 var(--gold);
  }

  .stock-card-main {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 13px 14px;
    cursor: pointer;
    min-height: 44px;
  }

  .stock-card-info {
    flex: 1;
    min-width: 0;
  }

  .stock-card-name {
    font-size: 0.94rem;
    font-weight: 500;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .stock-card-sub {
    margin-top: 2px;
    font-size: 0.76rem;
    color: var(--text-dim);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .stock-card-price {
    flex-shrink: 0;
    text-align: right;
  }

  .stock-card-main .chevron {
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    color: var(--text-dim);
    transition: transform 0.15s ease;
  }

  .stock-card.is-open .stock-card-main .chevron {
    transform: rotate(180deg);
  }

  .stock-card-detail,
  .stock-card-actions {
    display: none;
    padding: 12px 14px 14px;
    border-top: 1px solid var(--border);
  }

  .stock-card.is-open .stock-card-detail {
    display: block;
  }

  .stock-card.is-open .stock-card-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
    border-top: none;
    padding-top: 2px;
  }

  .stock-card-detail-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 7px 0;
    font-size: 0.86rem;
  }

  .stock-card-detail-row + .stock-card-detail-row {
    border-top: 1px solid var(--border);
  }

  .stock-card-detail-label {
    color: var(--text-dim);
    font-size: 0.78rem;
    flex-shrink: 0;
  }

  .stock-card-actions button {
    padding: 8px 13px;
    min-height: 38px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--bg-subtle);
    color: var(--text-soft);
    font-family: inherit;
    font-size: 0.78rem;
    font-weight: 500;
    cursor: pointer;
  }

  .stock-card-actions button:hover {
    border-color: var(--border-strong);
    color: var(--text);
  }

  .stock-card-actions .actions-menu-danger {
    color: var(--red);
    border-color: #5a3a3a;
  }

  /* « Voir la fiche produit » ouvre la modale complète (Ventes/Prix/Ailleurs),
     seul accès à cette fiche sur mobile depuis que le tableau y est masqué :
     détaché visuellement des actions de gestion, sur sa propre ligne. */
  .stock-card-actions button[data-action="open-detail"] {
    flex: 1 1 100%;
    padding: 4px 0 8px;
    min-height: 0;
    border: none;
    border-radius: 0;
    background: none;
    color: var(--teal);
    font-weight: 600;
    text-align: left;
  }
}

.row-icon {
  position: relative;
  margin-right: 6px;
  cursor: default;
  display: inline-flex;
  vertical-align: middle;
  color: var(--text-dim);
}

.row-icon svg {
  width: 15px;
  height: 15px;
}

.row-icon.anomaly-icon {
  color: var(--gold);
  cursor: help;
}

.row-icon[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: 130%;
  left: 0;
  width: max-content;
  max-width: 240px;
  white-space: normal;
  background: var(--bg-panel);
  border: 1px solid var(--border-strong);
  color: var(--text);
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  font-size: 0.78rem;
  line-height: 1.45;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  opacity: 0;
  transform: translateY(4px);
  pointer-events: none;
  transition: opacity 0.12s ease, transform 0.12s ease;
  z-index: 20;
}

.row-icon[data-tooltip]:hover::after {
  opacity: 1;
  transform: translateY(0);
}

/* Le menu du tableau JBL SARAWAK s'ouvre au clic droit (ou à l'appui long
   sur mobile) plutôt qu'à un bouton dédié · sans colonne fixe à sa taille,
   il se positionne là où le clic a eu lieu plutôt que dans une cellule. */
.actions-menu {
  position: fixed;
  z-index: 200;
  background: var(--bg-panel);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55);
  min-width: 200px;
  overflow: hidden;
}

.actions-menu button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 10px 14px;
  background: none;
  border: none;
  color: var(--text-soft);
  font-family: inherit;
  font-size: 0.88rem;
  cursor: pointer;
}

.actions-menu button:hover {
  background: var(--bg-hover);
  color: var(--text);
}

.actions-menu.is-hidden {
  display: none;
}

.actions-menu-danger {
  color: var(--red);
  border-top: 1px solid var(--border);
}

.actions-menu-danger:hover {
  background: #2a1c1c;
  color: var(--red);
}

/* ---------- Statistiques de vente ---------- */

/* Repli mobile des cartes de "Graphique" · voir setupChartAccordion() dans
   sales-charts.js. Masqué sur desktop : le bouton n'apparaît que sous
   640px, tout reste affiché normalement au-delà. */
.chart-collapse-btn {
  display: none;
}

@media (max-width: 640px) {
  .chart-collapse-head {
    cursor: pointer;
  }

  .chart-collapse-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: none;
    color: var(--text-dim);
    cursor: pointer;
    transition: transform 0.15s ease;
  }

  .chart-collapse-btn svg {
    width: 16px;
    height: 16px;
  }

  #chart-view .card.is-collapsed .chart-collapse-btn {
    transform: rotate(180deg);
  }

  .chart-collapsible {
    margin-top: 16px;
  }

  /* Contenu masqué sans toucher à la hauteur propre du conteneur du canevas
     Chart.js (320-340px, fixée en style inline) : seul cet ancêtre est
     clippé, ce qui évite qu'un graphique replié au chargement se retrouve
     mesuré à 0 par Chart.js. */
  #chart-view .card.is-collapsed .chart-collapsible {
    max-height: 0;
    overflow: hidden;
    margin-top: 0;
  }
}

.month-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 12px;
}

.month-stat-card {
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 16px 14px;
  text-align: left;
}

.month-stat-card .month-label {
  font-size: 0.75rem;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 8px;
}

.month-stat-card .month-basket {
  font-family: var(--font-mono);
  font-size: 1.2rem;
  font-weight: 500;
  color: var(--gold-bright);
  font-variant-numeric: tabular-nums;
}

.month-stat-card .month-days {
  font-size: 0.78rem;
  color: var(--text-dim);
  margin-top: 6px;
}

.leaderboard-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 24px;
}

.leaderboard h3 {
  margin: 0 0 14px;
  font-family: var(--font-ui);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-dim);
}

.leaderboard-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.leaderboard-list li {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 0.9rem;
}

.leaderboard-rank {
  font-family: var(--font-mono);
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  min-width: 16px;
  font-size: 0.82rem;
}

.leaderboard-name {
  flex: 1;
  overflow-wrap: break-word;
  color: var(--text-soft);
}

.leaderboard-bar {
  height: 5px;
  border-radius: 999px;
  background: var(--teal);
}

.leaderboard-volume {
  font-family: var(--font-mono);
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  font-size: 0.82rem;
}

/* ---------- Fiche produit ---------- */

.product-modal-card {
  max-width: 580px;
}

.product-modal-description {
  display: flex;
  gap: 20px;
  align-items: flex-start;
  font-size: 0.92rem;
  color: var(--text-soft);
}

.product-modal-description p {
  margin: 0 0 10px;
}

.product-modal-image {
  width: 120px;
  height: 120px;
  object-fit: contain;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}

.product-modal-image--empty {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
  font-size: 0.75rem;
  text-align: center;
}

#product-modal-body {
  margin-top: 18px;
  min-height: 100px;
}

.price-delta {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 8px;
  border-radius: 4px;
  font-size: 0.78rem;
  font-weight: 600;
}

.price-delta--up {
  color: var(--red);
  background: #2a1c1c;
}

.price-delta--down {
  color: var(--green);
  background: #172519;
}

/* ---------- Déconnexion pour inactivité ---------- */

.logout-countdown {
  margin: 20px 0 4px;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 3rem;
  font-weight: 500;
  color: var(--gold-bright);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.logout-countdown .unit {
  font-size: 1.4rem;
  color: var(--text-dim);
  margin-left: 3px;
}

/* ---------- Arrivages ---------- */

/* Quatre niveaux de lecture, quatre traitements distincts :
   semaine en or, jour en sarcelle, produit en clair, prix en or monospace. */

.arrival-week {
  margin-top: 40px;
}

.arrival-week:first-of-type {
  margin-top: 24px;
}

/* Sélecteur à deux classes : la règle générique `.card h4` l'emporterait sinon
   et ramènerait le titre à 0.95rem en blanc. */
.card .arrival-week-title {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin: 0;
  padding-bottom: 12px;
  border-bottom: 2px solid var(--gold);
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 600;
  color: var(--gold-bright);
}

.arrival-week-title .muted-note {
  font-family: var(--font-ui);
  font-size: 0.92rem;
}

.arrival-week .empty-state {
  margin-top: 14px;
  font-style: italic;
}

.arrival-days {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 20px;
}

.arrival-day {
  padding: 14px 0 14px 18px;
  border-left: 3px solid var(--teal-dim);
}

.arrival-day h5 {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin: 0 0 10px;
  font-size: 1.12rem;
  font-weight: 600;
  color: var(--teal);
  text-transform: capitalize;
}

.arrival-day h5 .muted-note {
  font-size: 0.88rem;
  text-transform: none;
}

/* Le jour courant se démarque des autres jours. */
.arrival-day.is-today {
  border-left-color: var(--gold);
  background: rgba(201, 162, 74, 0.05);
}

.arrival-day.is-today h5 {
  color: var(--gold-bright);
}

.arrival-day .detail-title {
  font-size: 1rem;
  color: var(--text);
}

.arrival-day .detail-meta {
  font-family: var(--font-mono);
  font-size: 1rem;
  font-weight: 600;
  color: var(--gold-bright);
}

.arrival-count {
  margin-left: auto;
  padding: 2px 11px;
  border-radius: 999px;
  border: 1px solid var(--teal-dim);
  background: rgba(86, 160, 173, 0.12);
  font-family: var(--font-mono);
  font-size: 0.84rem;
  font-weight: 500;
  color: var(--teal);
}

.arrival-week-title .arrival-count {
  border-color: var(--border-accent);
  background: rgba(201, 162, 74, 0.12);
  color: var(--gold-bright);
  font-size: 0.92rem;
}

.arrival-day.is-today .arrival-count {
  border-color: var(--border-accent);
  background: rgba(201, 162, 74, 0.12);
  color: var(--gold-bright);
}

/* ---------- Légende de graphique, cliquable ---------- */

.chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 14px;
}

.chart-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: none;
  color: var(--text-soft);
  font-family: inherit;
  font-size: 0.88rem;
  cursor: pointer;
  transition: opacity 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}

.chart-legend-item:hover {
  border-color: var(--border-strong);
  color: var(--text);
}

/* Série isolée : mise en avant. Les autres s'effacent sans disparaître. */
.chart-legend-item.is-isolated {
  border-color: var(--gold);
  color: var(--gold-bright);
}

.chart-legend-item.is-muted {
  opacity: 0.35;
}

.chart-legend-dot {
  width: 11px;
  height: 11px;
  border-radius: 3px;
  flex-shrink: 0;
}

/* ---------- Compte rendu de vérification ---------- */

.report-summary {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  margin: 18px 0 8px;
}

.report-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 14px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  text-align: center;
}

.report-stat-value {
  font-family: var(--font-mono);
  font-size: 1.3rem;
  color: var(--gold-bright);
  font-variant-numeric: tabular-nums;
}

.report-stat-label {
  font-size: 0.76rem;
  color: var(--text-dim);
  line-height: 1.3;
}

.report-body {
  max-height: 46vh;
  overflow-y: auto;
  margin-top: 8px;
  padding-right: 6px;
}

/* Une grille, pas un flex : sans largeur plancher, un intitulé long réduisait
   la colonne de gauche à un mot par ligne. */
.report-body .detail-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px 18px;
  align-items: baseline;
}

.report-body .detail-title {
  overflow-wrap: anywhere;
}

.report-body .detail-meta {
  white-space: nowrap;
  font-size: 0.82rem;
}

.report-heading {
  margin: 18px 0 4px;
  font-size: 0.98rem;
}

.report-heading--ok {
  color: var(--green);
}

.report-heading--todo {
  color: var(--text-dim);
}

.report-category {
  display: block;
  font-size: 0.78rem;
  color: var(--text-dim);
}

.report-footnote {
  margin-top: 20px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
  line-height: 1.5;
}

/* ---------- Bandeau d'information ---------- */

.notice {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 18px 22px;
  margin: 0 0 24px;
  border-radius: var(--radius);
  border: 1px solid var(--border-accent);
  background: #1d1a12;
}

.notice-icon {
  display: inline-flex;
  flex-shrink: 0;
  color: var(--gold);
  margin-top: 2px;
}

.notice-icon svg {
  width: 22px;
  height: 22px;
}

.notice-title {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--gold-bright);
}

.notice-body {
  margin: 0;
  font-size: 0.94rem;
  color: var(--text-soft);
  line-height: 1.5;
}

/* ---------- Colonnes Évolution et Prix ---------- */

.evolution-cell,
.price-cell {
  white-space: nowrap;
}

.price-evolution {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}

.price-evolution .price-delta {
  margin-left: 0;
}

.price-evolution-from {
  color: var(--text-dim);
  text-decoration: line-through;
}

.price-evolution-arrow {
  color: var(--text-dim);
}

.price-evolution-to {
  color: var(--text);
  font-weight: 500;
}

.price-current {
  font-family: var(--font-mono);
  font-size: 0.92rem;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

/* En promotion : le prix passe au vert, l'ancien reste barré à côté. */
.price-current--promo {
  color: var(--green);
  font-weight: 600;
}

.price-promo {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
}

.price-was {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
  text-decoration: line-through;
}

.promo-info {
  position: relative;
  display: inline-flex;
  align-items: center;
  color: var(--green);
  cursor: help;
}

.promo-info svg {
  width: 16px;
  height: 16px;
}

.promo-info:focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: 2px;
  border-radius: 50%;
}

/* Bulle détaillée : plusieurs lignes hiérarchisées, là où un pseudo-élément
   ne pouvait afficher qu'une chaîne de texte tassée. */
/* Ancrée à droite : la colonne Prix est en bord de tableau, une bulle ouverte
   vers la droite sortait de l'écran. */
.promo-tip {
  position: absolute;
  bottom: calc(100% + 10px);
  right: -10px;
  z-index: 30;
  display: flex;
  flex-direction: column;
  gap: 7px;
  width: max-content;
  max-width: 300px;
  padding: 14px 16px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--bg-panel);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.55);
  white-space: normal;
  text-align: left;
  opacity: 0;
  transform: translateY(4px);
  pointer-events: none;
  transition: opacity 0.12s ease, transform 0.12s ease;
}

.promo-info:hover .promo-tip,
.promo-info:focus-visible .promo-tip {
  opacity: 1;
  transform: translateY(0);
}

/* Vendeur tiers : information neutre, pas une bonne nouvelle comme une promo.
   La colonne Évolution n'étant pas en bord de tableau, la bulle s'ouvre à droite. */
.promo-info--seller {
  color: var(--steel);
  margin-right: 6px;
}

.promo-tip--left {
  right: auto;
  left: -10px;
}

.promo-tip-title {
  font-size: 0.94rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--gold-bright);
}

.promo-tip-title--absent {
  font-weight: 400;
  letter-spacing: 0;
  color: var(--text-dim);
  font-style: italic;
}

.promo-tip-line {
  font-size: 0.86rem;
  color: var(--text-soft);
  line-height: 1.45;
}

.promo-tip-line strong {
  color: var(--text);
}

.promo-tip-prices {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

.promo-tip-was {
  font-size: 0.88rem;
  color: var(--text-dim);
  text-decoration: line-through;
}

.promo-tip-arrow {
  color: var(--text-dim);
}

.promo-tip-now {
  font-size: 1rem;
  font-weight: 600;
  color: var(--green);
}

.promo-tip-saving {
  font-size: 0.82rem;
  color: var(--text-dim);
}

.promo-badge {
  padding: 1px 8px;
  border-radius: 4px;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--green);
  background: #172519;
}

.mail-test-bar {
  display: flex;
  align-items: center;
  gap: 14px;
  justify-content: flex-start;
  margin: 48px 0 8px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
}

#test-mail-status {
  font-size: 0.88rem;
  color: var(--text-dim);
}

/* ---------- Progression du scan ---------- */

#stock-meta {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-start;
}

.scan-progress-label {
  color: var(--text-soft);
  font-size: 0.92rem;
}

.scan-progress-bar {
  display: block;
  width: 100%;
  max-width: 420px;
  height: 6px;
  border-radius: 999px;
  background: var(--bg-subtle);
  overflow: hidden;
}

.scan-progress-bar span {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--teal);
  transition: width 0.4s ease;
}

/* ---------- Tableaux de données ---------- */

.data-table {
  width: 100%;
  border-collapse: collapse;
}

.data-table th,
.data-table td {
  padding: 10px 0;
  text-align: left;
  vertical-align: baseline;
  border-bottom: 1px solid var(--border);
  font-size: 0.94rem;
}

.data-table tr:last-child th,
.data-table tr:last-child td {
  border-bottom: none;
}

.data-table th {
  width: 45%;
  padding-right: 24px;
  font-weight: 400;
  color: var(--text-dim);
}

.data-table td {
  color: var(--text);
}

/* ---------- Listes détaillées ---------- */

.detail-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.detail-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  padding: 11px 0;
  border-bottom: 1px solid var(--border);
}

.detail-row:last-child {
  border-bottom: none;
}

.detail-title {
  color: var(--text-soft);
  font-size: 0.94rem;
  min-width: 0;
}

.detail-meta {
  font-family: var(--font-mono);
  color: var(--text-dim);
  font-size: 0.85rem;
  text-align: right;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}

/* ---------- Calendrier ---------- */

.week-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 12px;
  align-items: start;
}

.day-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 14px;
  min-height: 160px;
}

.day-card.is-past {
  opacity: 0.62;
}

.day-card.is-today {
  border-color: var(--border-accent);
  background: #181a15;
}

.day-card-head {
  margin-bottom: 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}

.day-card-head h3 {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.82rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-dim);
}

.day-card.is-today .day-card-head h3 {
  color: var(--gold-bright);
}

.day-date {
  margin: 4px 0 0;
  font-family: var(--font-mono);
  font-size: 1.1rem;
  color: var(--text);
}

.day-event-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.day-event {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.day-event-time {
  font-family: var(--font-mono);
  font-size: 0.76rem;
  color: var(--teal);
  font-variant-numeric: tabular-nums;
}

.day-event-title {
  font-size: 0.88rem;
  color: var(--text-soft);
  overflow-wrap: anywhere;
  line-height: 1.4;
}

.day-event--allday .day-event-title {
  font-weight: 600;
  color: var(--text);
}

.day-empty {
  margin: 0;
  font-size: 0.85rem;
  color: var(--text-dim);
}

/* ---------- Overwatch ---------- */

.hero-portrait {
  width: 32px;
  height: 32px;
  border-radius: 6px;
  object-fit: cover;
  border: 1px solid var(--border);
  flex-shrink: 0;
}

.hero-favorite {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 16px 0;
}

.hero-favorite .hero-portrait {
  width: 56px;
  height: 56px;
  border-radius: 8px;
}

.hero-favorite-name {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--text);
}

.hero-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Le nom prend sa largeur naturelle : en « 1fr » avec nowrap, il débordait sur
   la colonne de statistiques au lieu de la repousser. */
.hero-row {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr);
  align-items: center;
  gap: 16px;
  padding: 11px 0;
  border-bottom: 1px solid var(--border);
}

.hero-row:last-child {
  border-bottom: none;
}

.hero-name {
  font-size: 1.16rem;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}

.hero-stats {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 0 8px;
  font-family: var(--font-mono);
  font-size: 0.84rem;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

/* Séparateur discret entre un total et sa moyenne, ou entre deux mesures. */
.stat-separator {
  color: var(--border-strong);
  user-select: none;
}

.stat-value {
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  margin-right: 8px;
}

.data-table .stat-separator {
  margin-right: 8px;
}

.stat-subheading {
  margin: 28px 0 12px;
  font-size: 0.86rem;
  color: var(--teal);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
}

/* ---------- WoW ---------- */

.wow-character-header {
  display: flex;
  align-items: center;
  gap: 20px;
}

.wow-avatar {
  width: 64px;
  height: 64px;
  border-radius: 10px;
  object-fit: cover;
  border: 1px solid var(--border);
  flex-shrink: 0;
}

/* ---------- WoW Challenge ---------- */

.challenge-top {
  display: flex;
  gap: 36px;
  margin-bottom: 8px;
}

.challenge-top-col {
  flex: 1;
  min-width: 0;
}

.challenge-top-col h2 {
  font-size: 1.1rem;
}

.challenge-header-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.challenge-top-divider {
  width: 1px;
  background: var(--border);
  align-self: stretch;
}

.challenge-sheet-table td {
  font-size: 0.94rem;
  padding: 7px 0;
}

.challenge-progress-bar {
  width: 100%;
  height: 8px;
  border-radius: 999px;
  border: none;
  background: var(--bg-subtle);
  overflow: hidden;
  margin-top: 14px;
}

.challenge-progress-fill {
  height: 100%;
  background: var(--gold);
  border-radius: 999px;
  transition: width 0.3s ease;
}

.challenge-progress-value {
  margin: 14px 0 0;
  font-family: var(--font-mono);
  font-size: 1.6rem;
  font-weight: 500;
  color: var(--gold-bright);
  font-variant-numeric: tabular-nums;
}

.challenge-progress-value .unit {
  font-size: 1.1rem;
  margin-left: 2px;
  color: var(--text-dim);
}

.challenge-extensions-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}

.challenge-tile {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 16px 16px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-card);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.12s ease, background 0.12s ease;
}

.challenge-tile:hover {
  border-color: var(--border-strong);
}

.challenge-tile-status {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.challenge-tile-name {
  font-size: 0.98rem;
  color: var(--text);
  font-weight: 500;
}

.challenge-tile-level {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--text-dim);
}

.challenge-tile--done .challenge-tile-status {
  color: var(--green);
}

.challenge-tile--current {
  border-color: var(--border-accent);
  background: #181a15;
}

.challenge-tile--current .challenge-tile-status {
  color: var(--gold-bright);
}

.challenge-tile--locked {
  opacity: 0.5;
}

.challenge-tile.is-viewing {
  border-color: var(--teal);
}

.challenge-tile-bar {
  display: block;
  width: 100%;
  height: 3px;
  margin-top: 10px;
  border-radius: 999px;
  background: var(--bg-subtle);
  overflow: hidden;
}

.challenge-tile-bar span {
  display: block;
  height: 100%;
  background: var(--gold);
  border-radius: 999px;
}

.challenge-nav {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  margin-top: 24px;
}

.challenge-page {
  flex: 1;
  min-width: 0;
}

.challenge-page-title {
  margin: 8px 0 4px;
  text-align: left;
}

.challenge-page-sub {
  text-align: left;
  font-size: 0.95rem;
  color: var(--text-dim);
  margin: 0 0 28px;
}

.challenge-block-title {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--text);
  margin: 32px 0 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}

.challenge-block-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.challenge-block-header .challenge-block-title {
  margin-bottom: 0;
  padding-bottom: 0;
  border-bottom: none;
  flex: 1;
}

.challenge-rules-note {
  font-style: normal;
  color: var(--text-dim);
  font-size: 0.94rem;
  margin: 0 0 16px;
}

.challenge-rules-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 4px 32px;
}

.challenge-rules-list li {
  position: relative;
  padding: 6px 0 6px 18px;
  font-size: 0.94rem;
  color: var(--text-soft);
}

.challenge-rules-list li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 15px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--teal);
}

.challenge-rules-list li.is-emphasis {
  font-weight: 600;
  color: var(--text);
}

.challenge-rules-list li.is-emphasis::before {
  background: var(--gold);
}

.challenge-arrow {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text-soft);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  position: sticky;
  top: 24px;
}

.challenge-arrow:hover:not(:disabled) {
  border-color: var(--border-strong);
  background: var(--bg-hover);
  color: var(--text);
}

.challenge-arrow:disabled {
  opacity: 0.3;
  cursor: default;
}

.challenge-locked-note {
  color: var(--gold-bright);
  font-size: 0.92rem;
  margin: 0 0 16px;
}

.challenge-categories {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px 36px;
}

.challenge-categories.is-locked {
  opacity: 0.5;
  pointer-events: none;
}

.challenge-category h4 {
  font-family: var(--font-ui);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 0 0 10px;
  color: var(--text-dim);
}

.challenge-category-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.challenge-category-head h4 {
  margin: 0;
}

.challenge-manual {
  margin-top: 28px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: flex-start;
}

.challenge-arbitration {
  margin-bottom: 20px;
}

.challenge-arbitration select {
  width: 100%;
  max-width: 340px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 10px 14px;
  font-size: 0.92rem;
  font-family: inherit;
}

.challenge-arbitration select:focus {
  outline: none;
  border-color: var(--teal);
}

/* ---------- Objectifs ---------- */

.objective-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.objective-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 8px 8px 6px;
  border-radius: 6px;
}

.objective-row.is-clickable {
  cursor: pointer;
}

.objective-row.is-clickable:hover {
  background: var(--bg-hover);
}

.objective-checkbox {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  border-radius: 5px;
  border: 1px solid var(--border-strong);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--green);
  font-size: 0.8rem;
  font-weight: 700;
}

.objective-row.is-done .objective-checkbox {
  border-color: var(--green);
  background: #172519;
}

.objective-label {
  flex: 1;
  font-size: 0.94rem;
  color: var(--text-soft);
}

.objective-row.is-done .objective-label {
  color: var(--text-dim);
  text-decoration: line-through;
}

.objective-note {
  display: block;
  margin-top: 2px;
  color: var(--text-dim);
  font-size: 0.84rem;
  font-style: normal;
}

.objective-auto {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 7px;
  border-radius: 4px;
  border: 1px solid var(--border);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
  vertical-align: middle;
}

.objective-counter {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.counter-btn {
  width: 24px;
  height: 24px;
  border-radius: 5px;
  border: 1px solid var(--border);
  background: none;
  color: var(--text-soft);
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
}

.counter-btn:hover {
  border-color: var(--border-strong);
  background: var(--bg-hover);
  color: var(--text);
}

.counter-value {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--text-dim);
  min-width: 46px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.objective-row.is-done .counter-value {
  color: var(--green);
}

/* ---------- Administration ---------- */

.user-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 20px;
}

.user-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 16px;
}

.user-card-head h3 {
  margin: 0;
}

.user-role {
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 4px;
  border: 1px solid var(--border);
  color: var(--text-dim);
  white-space: nowrap;
}

.user-role--admin {
  color: var(--gold-bright);
  border-color: var(--border-accent);
}

.perm-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 0 24px;
  margin: 12px 0 18px;
}

.perm-option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 0;
  font-size: 0.92rem;
  color: var(--text-soft);
  cursor: pointer;
}

.perm-option input {
  width: 16px;
  height: 16px;
  accent-color: var(--gold);
  flex-shrink: 0;
}

.perm-mode {
  margin-left: auto;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-dim);
  white-space: nowrap;
}

.perm-group {
  display: flex;
  flex-direction: column;
}

.perm-option--nested {
  padding-left: 26px;
  font-size: 0.85rem;
}

.perm-option--nested input:disabled {
  cursor: not-allowed;
  opacity: 0.4;
}

.user-card-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 18px;
}

/* ==================================================================
   Responsive
   ================================================================== */

@media (max-width: 1100px) {
  .week-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 900px) {
  /* Marque + bascule + administration + compte + horloge : en dessous de cette
     largeur les cinq blocs ne tiennent plus côte à côte. Le repli se déclenchait
     à 640 px, ce qui laissait l'en-tête à l'étroit entre les deux. */
  .top-bar {
    flex-wrap: wrap;
    gap: 12px;
    min-height: 0;
  }

  .challenge-extensions-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .challenge-top {
    flex-direction: column;
    gap: 24px;
  }

  .challenge-top-divider {
    width: auto;
    height: 1px;
  }
}

@media (max-width: 640px) {
  .page {
    padding: 20px 16px 48px;
  }

  .top-bar {
    flex-wrap: wrap;
    gap: 12px;
  }

  .clock {
    text-align: left;
  }

  .brand h1 {
    font-size: 1.3rem;
  }

  .tabs a {
    padding: 9px 12px;
    font-size: 0.88rem;
  }

  .greeting,
  .section-heading {
    font-size: 1.45rem;
  }

  .dashboard-grid {
    grid-template-columns: 1fr;
  }

  .week-grid {
    grid-template-columns: 1fr;
  }

  /* WoW Challenge : les cadres pleine épaisseur (bordure + fond + gros
     padding) prennent trop de place utile sur un petit écran · allégés
     plutôt que retirés, pour garder le regroupement visuel sans le poids. */
  #challenge-root .card {
    padding: 14px 12px;
  }

  .challenge-page-title {
    font-size: 1.3rem;
  }

  .challenge-progress-value {
    font-size: 2rem;
  }

  .challenge-extensions-grid {
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
  }

  .challenge-tile {
    padding: 10px 10px 8px;
  }

  .challenge-tile-name {
    font-size: 0.85rem;
  }

  .challenge-categories {
    grid-template-columns: 1fr;
    gap: 18px;
  }

  .challenge-rules-list li {
    font-size: 0.88rem;
  }

  .objective-row {
    padding: 7px 4px;
    gap: 8px;
  }

  .objective-label {
    font-size: 0.88rem;
  }
}

@media (max-width: 620px) {
  .week-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 520px) {
  .hero-row {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .hero-stats {
    grid-column: 2;
    text-align: left;
  }
}

/* ---------- Dimensionnement des pictogrammes ---------- */
/* flex-shrink: 0 sur tous les SVG : dans un conteneur flex étroit (bouton
   compteur, puce de source), ils étaient comprimés en largeur et déformés. */
.counter-btn svg,
.objective-checkbox svg,
.source-icon svg,
.price-evolution-arrow svg,
.promo-tip-arrow svg {
  flex-shrink: 0;
}

/* Les symboles d'interface sont des SVG : ils héritent de la couleur du
   contexte mais pas de sa taille, qui doit donc être posée à chaque emplacement. */

.price-evolution-arrow,
.promo-tip-arrow {
  display: inline-flex;
  align-items: center;
}

.price-evolution-arrow svg,
.promo-tip-arrow svg {
  width: 15px;
  height: 15px;
}

.objective-checkbox svg {
  width: 13px;
  height: 13px;
}

.counter-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.counter-btn svg {
  width: 13px;
  height: 13px;
}

/* Puce des sources : le losange du logo sert de repère de liste. */
.source-icon {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  color: var(--gold);
}

.source-icon svg {
  width: 17px;
  height: 17px;
}

#sources-list li {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* ---------- Accès à l'administration (en-tête) ---------- */
/* Même gabarit que le bouton de compte, sarcelle plutôt que gris : c'est une
   destination, pas un menu, et elle doit se distinguer sans crier. */

.admin-tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-soft);
  text-decoration: none;
  font-size: 0.88rem;
  white-space: nowrap;
  transition: color 0.12s ease, border-color 0.12s ease, background 0.12s ease;
}

.admin-tab svg {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  color: var(--teal);
}

.admin-tab:hover {
  color: var(--text);
  border-color: var(--border-strong);
  background: var(--bg-hover);
}

.admin-tab.is-active {
  color: var(--gold-bright);
  border-color: var(--border-accent);
  background: var(--bg-subtle);
}

.admin-tab.is-active svg {
  color: var(--gold);
}

/* ---------- Sous-onglets d'un groupe (Jeux) ---------- */
/* Deux niveaux se croisent sur ces pages : le groupe (changer de page) et les
   sous-onglets internes (changer de vue, ex. les personnages WoW). Deux rangées
   de pastilles identiques seraient illisibles, alors la règle est : souligné =
   on change de page, pastille = on change de vue. L'or reste au niveau
   principal, la sarcelle marque ce second niveau. */

.sub-tabs--group {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  margin: -28px 0 34px;
  padding-left: 4px;
}

.sub-tabs--group a.sub-tab {
  background: none;
  border: none;
  border-radius: 0;
  border-bottom: 2px solid transparent;
  padding: 7px 15px;
  font-size: 0.95rem;
  color: var(--text-dim);
  text-decoration: none;
}

.sub-tabs--group a.sub-tab:hover {
  background: none;
  color: var(--text);
}

.sub-tabs--group a.sub-tab.active {
  background: none;
  color: var(--teal);
  border-bottom-color: var(--teal);
}

/* ---------- Panneau de diagnostic ---------- */
/* Des lignes libellé / valeur plutôt qu'un tableau : la colonne de droite porte
   des contenus de nature très différente (pastille, durée, chemin de fichier)
   qu'un alignement strict rendrait plus difficiles à parcourir. */

.diag-ligne {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  gap: 18px;
  align-items: baseline;
  padding: 9px 0;
  border-bottom: 1px solid var(--border);
}

.diag-ligne:last-child {
  border-bottom: none;
}

.diag-label {
  color: var(--text-soft);
  font-size: 0.95rem;
}

/* `flex-wrap` est ce qui manquait : une pastille + une note un peu longues
   (chemin de fichier, "X utilisés sur Y, Z libres"...) débordaient l'une sur
   l'autre au lieu de passer à la ligne · c'est ça, le chevauchement signalé
   (10/09/2026, Morey). La note repasse aussi en bloc dédié plutôt que de
   rester collée à la pastille sur la même ligne. */
.diag-valeur {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  justify-content: flex-end;
  text-align: right;
  font-family: var(--font-mono);
  font-size: 0.9rem;
  color: var(--text);
  min-width: 0;
}

.diag-note {
  display: block;
  flex-basis: 100%;
  font-family: var(--font-ui);
  font-size: 0.82rem;
  color: var(--text-dim);
  white-space: normal;
  overflow-wrap: break-word;
}

.diag-frais {
  color: var(--green);
}

/* Trois états seulement, avec un seuil chiffré derrière chacun. */
.diag-etat {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
}

.diag-etat--bon {
  color: var(--green);
  background: rgba(116, 192, 145, 0.13);
}

.diag-etat--attention {
  color: var(--gold-bright);
  background: rgba(201, 162, 74, 0.15);
}

.diag-etat--alerte {
  color: var(--red);
  background: rgba(221, 143, 143, 0.15);
}

/* ---------- Tests ---------- */

.diag-test {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 16px 20px;
  align-items: center;
  padding: 16px 0;
  border-bottom: 1px solid var(--border);
}

.diag-test:last-child {
  border-bottom: none;
}

.diag-test-texte strong {
  font-size: 1.02rem;
  color: var(--text);
}

.diag-test-texte p {
  margin: 4px 0 0;
  font-size: 0.88rem;
  color: var(--text-dim);
  line-height: 1.45;
}

.diag-test-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

.diag-test-resultat {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  padding: 11px 14px;
  border-radius: var(--radius-sm);
  border-left: 3px solid var(--border-strong);
  background: var(--bg-subtle);
  font-size: 0.9rem;
}

.diag-test-resultat--ok {
  border-left-color: var(--green);
}

.diag-test-resultat--echec {
  border-left-color: var(--red);
}

.diag-test-verdict {
  font-weight: 600;
  white-space: nowrap;
}

.diag-test-resultat--ok .diag-test-verdict {
  color: var(--green);
}

.diag-test-resultat--echec .diag-test-verdict {
  color: var(--red);
}

.diag-test-resume {
  color: var(--text-soft);
}

.diag-test-details {
  flex-basis: 100%;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  margin-top: 4px;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--text-dim);
}

.diag-test-details em {
  font-style: normal;
  color: var(--teal);
}

/* ---------- Journaux ---------- */

.journal {
  margin: 0;
  padding: 14px 16px;
  max-height: 460px;
  overflow: auto;
  border-radius: var(--radius-sm);
  background: #0a1017;
  border: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  line-height: 1.6;
  color: var(--text-soft);
  white-space: pre;
}

.journal-controles {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
}

.journal-controles .field-label {
  margin: 0;
}

.journal-controles select {
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-subtle);
  color: var(--text);
  font-family: inherit;
}

/* ---------- Aperçu de message ---------- */

.modal-card--large {
  max-width: 780px;
  width: 92vw;
}

.mail-apercu {
  width: 100%;
  height: 52vh;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
}

/* ---------- Passage d'une page à l'autre ---------- */
/* Chaque onglet est une vraie page : le navigateur remplace le document entier.
   Ces règles suppriment les deux gênes visibles · le blanc entre les documents,
   et la mise en page qui se réajuste quand l'en-tête se remplit. */

/* Fondu enchaîné entre documents au lieu d'un remplacement sec.
   Ignoré par les navigateurs qui ne le gèrent pas : rien ne casse sans lui. */
@view-transition {
  navigation: auto;
}

@media (prefers-reduced-motion: reduce) {
  @view-transition {
    navigation: none;
  }
}

/* L'en-tête et la barre d'onglets sont remplis par JavaScript. Sans hauteur
   réservée, le contenu descendait d'un cran au moment où ils apparaissaient. */
.tabs {
  min-height: 53px;
}

.greeting:empty::before,
.section-heading:empty::before {
  content: "\00a0";
}

/* Hauteur mesurée de l'en-tête une fois complet : sans elle, l'arrivée des
   boutons faisait descendre toute la page de 8 px. */
.top-bar {
  min-height: 63px;
}

/* L'horloge ne se disloque pas quand la place manque : c'est la barre entière
   qui passe à la ligne, pas l'heure qui se sépare de sa date. */
.clock {
  flex-shrink: 0;
}

.clock > * {
  white-space: nowrap;
}

/* ---------- Choix du mode à la connexion ---------- */
/* Deux pastilles côte à côte plutôt qu'une liste déroulante : le choix est
   binaire et doit se voir d'un coup d'œil avant de valider. */

.mode-choice {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 18px;
}

.mode-choice-btn {
  padding: 11px 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text-dim);
  font-family: inherit;
  font-size: 0.98rem;
  font-weight: 500;
  cursor: pointer;
  transition: color 0.12s ease, border-color 0.12s ease, background 0.12s ease;
}

.mode-choice-btn:hover {
  color: var(--text);
  background: var(--bg-hover);
}

.mode-choice-btn.is-active {
  color: var(--gold-bright);
  border-color: var(--border-accent);
  background: var(--bg-subtle);
}

.mode-choice-btn:focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: 2px;
}

/* Le formulaire est centré ; ces libellés doivent suivre les champs. */
.login-card .field-label {
  display: block;
  text-align: left;
}

/* Point d'attention à côté d'« Identifiant » (01/09/2026) : Ilari n'accepte
   pas les adresses mail, seulement un pseudo · même triangle « ! » que le
   reste du site (voir ICONS.warning), pas une bulle générique inventée pour
   l'occasion. */
.login-champ-label .row-icon {
  margin-left: 6px;
}

/* ---------- Bandeau « serveur injoignable » ---------- */
/* Posé au-dessus de tout, sans masquer la page : les données déjà affichées
   restent lisibles, c'est leur fraîcheur qui n'est plus garantie. */

.bandeau-panne {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 12px 20px;
  background: #3a2020;
  border-bottom: 1px solid var(--red);
  color: var(--text);
  font-size: 0.92rem;
  text-align: center;
}

.bandeau-panne-pastille {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--red);
  flex-shrink: 0;
  animation: pulsation-panne 1.4s ease-in-out infinite;
}

.bandeau-panne.est-revenu {
  background: #1d3227;
  border-bottom-color: var(--green);
}

.bandeau-panne.est-revenu .bandeau-panne-pastille {
  background: var(--green);
  animation: none;
}

@keyframes pulsation-panne {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.3; }
}

@media (prefers-reduced-motion: reduce) {
  .bandeau-panne-pastille {
    animation: none;
  }
}

/* ---------- Panneau Discord ---------- */
/* Le profil reprend la mise en page d'une fiche Discord : bannière pleine
   largeur, avatar à cheval dessus. C'est le repère visuel attendu. */

.card--profil-discord {
  padding: 0;
  overflow: hidden;
}

.discord-banniere {
  display: block;
  width: 100%;
  height: 160px;
  object-fit: cover;
}

.discord-banniere--vide {
  background: linear-gradient(135deg, var(--bg-subtle), var(--teal-dim));
}

.discord-identite {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 0 26px 18px;
  margin-top: -38px;
}

.discord-avatar {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  border: 5px solid var(--bg-card);
  background: var(--bg-card);
  flex-shrink: 0;
}

.discord-noms {
  display: flex;
  flex-direction: column;
  padding-top: 42px;
}

.discord-nom {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 600;
  color: var(--gold-bright);
  line-height: 1.2;
}

.discord-tag {
  font-family: var(--font-mono);
  font-size: 0.86rem;
  color: var(--text-dim);
}

.discord-badge {
  align-self: flex-end;
  margin-bottom: 4px;
  padding: 3px 11px;
  border-radius: 999px;
  background: rgba(86, 160, 173, 0.16);
  color: var(--teal);
  font-size: 0.78rem;
  font-weight: 600;
}

.discord-meta {
  padding: 0 26px 20px;
}

.discord-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}

.discord-incident {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 11px 14px;
  margin-bottom: 8px;
  border-left: 3px solid var(--red);
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
}

@media (max-width: 640px) {
  .discord-identite {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }

  .discord-noms {
    padding-top: 0;
  }
}

/* ---------- Liste des commandes du bot ---------- */

.commande {
  padding: 15px 0;
  border-bottom: 1px solid var(--border);
}

.commande:last-child {
  border-bottom: none;
}

.commande-entete {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.commande-nom {
  font-family: var(--font-mono);
  font-size: 1.08rem;
  font-weight: 600;
  color: var(--gold-bright);
}

.commande-portee {
  padding: 2px 10px;
  border-radius: 999px;
  background: rgba(86, 160, 173, 0.14);
  color: var(--teal);
  font-size: 0.78rem;
}

.commande-reservee {
  padding: 2px 10px;
  border-radius: 999px;
  background: rgba(201, 162, 74, 0.15);
  color: var(--gold-bright);
  font-size: 0.78rem;
}

.commande-description {
  margin: 6px 0 0;
  color: var(--text-soft);
  font-size: 0.95rem;
}

/* Les paramètres sont décalés : ils appartiennent à la commande au-dessus. */
.commande-options {
  margin-top: 10px;
  padding-left: 16px;
  border-left: 2px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.commande-option {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  font-size: 0.88rem;
}

.commande-option code {
  font-family: var(--font-mono);
  color: var(--text);
}

.commande-option-type {
  font-size: 0.78rem;
  color: var(--teal);
}

/* ---------- Niveaux du bot : tuiles, jauges, classement ---------- */

/* Tuiles de chiffres clés. Le nombre porte l'attention, le libellé reste discret. */
.tuiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 14px;
  margin-top: 8px;
}

.tuile {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
}

.tuile-valeur {
  font-family: var(--font-mono);
  font-size: 1.5rem;
  font-weight: 500;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
}

.tuile-libelle {
  font-size: 0.82rem;
  color: var(--text-dim);
}

/* Une tuile qui porte une jauge (Server Statut, 10/09/2026) lui laisse un peu
   d'air plutôt que de la coller au libellé. */
.tuile > .jauge {
  margin-top: 6px;
}

/* Jauge : piste creuse et discrète, remplissage fin à extrémité arrondie ancré
   à gauche. La couleur est portée par la barre seule ; les chiffres restent en
   encre de texte pour que la valeur se lise sans dépendre de la teinte. */
.jauge {
  display: block;
  width: 100%;
  height: 6px;
  border-radius: 3px;
  background: var(--bg-hover);
  overflow: hidden;
}

.jauge-remplissage {
  display: block;
  height: 100%;
  min-width: 4px;
  border-radius: 0 3px 3px 0;
  background: var(--gold);
}

.membre-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--bg-subtle);
}

.membre-avatar--petit {
  width: 26px;
  height: 26px;
}

.membre-pseudo {
  font-weight: 600;
  color: var(--text);
}

.membre-detail {
  font-size: 0.8rem;
  color: var(--text-dim);
}

.niveau-pastille {
  padding: 3px 11px;
  border-radius: 999px;
  background: rgba(86, 160, 173, 0.15);
  color: var(--teal);
  font-family: var(--font-mono);
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
}

/* Boost XP en cours (bonusActif, fiche membre) · teinte or pour se distinguer
   du niveau, disparaît de lui-même à la prochaine ouverture une fois expiré. */
.bonus-actif-pastille {
  padding: 3px 11px;
  border-radius: 999px;
  background: rgba(201, 162, 74, 0.15);
  color: var(--gold-bright);
  font-family: var(--font-mono);
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
}

/* ---------- Classement ---------- */

.classement-ligne {
  display: grid;
  grid-template-columns: 34px auto minmax(0, 1fr) minmax(0, 1.2fr) auto auto;
  align-items: center;
  gap: 14px;
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}

.classement-ligne:last-child {
  border-bottom: none;
}

.classement-rang {
  font-family: var(--font-mono);
  font-size: 1rem;
  color: var(--text-dim);
  text-align: center;
}

/* Seuls les trois premiers portent une couleur, et seulement sur le médaillon. */
.classement-rang--1,
.classement-rang--2,
.classement-rang--3 {
  width: 28px;
  height: 28px;
  line-height: 28px;
  border-radius: 50%;
  font-weight: 700;
  color: var(--bg);
}

.classement-rang--1 { background: var(--gold-bright); }
.classement-rang--2 { background: var(--steel); }
.classement-rang--3 { background: #a97a4a; }

/* Classement des cartes (« qui a le plus ») · deux listes côte à côte, plus
   légères que le classement des niveaux (pas d'avatar ni de progression) donc
   pas la peine de réutiliser sa grille à 6 colonnes. */
.carte-classement-grille {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 24px;
  margin-top: 12px;
}

.carte-classement-bloc h4 {
  margin: 0 0 8px;
  font-size: 1rem;
}

.carte-classement-ligne {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}

.carte-classement-ligne:last-child {
  border-bottom: none;
}

.carte-classement-ligne .membre-pseudo {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.carte-classement-valeur {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--text-dim);
  white-space: nowrap;
}

.carte-classement-ligne--soi {
  background: var(--bg-hover);
  border-radius: var(--radius-sm);
  padding-left: 8px;
  padding-right: 8px;
}

.carte-classement-ligne--soi .membre-pseudo {
  color: var(--gold-bright);
}

.classement-membre,
.classement-progression {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.classement-xp {
  font-family: var(--font-mono);
  font-size: 0.92rem;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---------- Tableau des niveaux ---------- */

.table-wrap {
  overflow-x: auto;
}

.tableau {
  width: 100%;
  border-collapse: collapse;
}

.tableau th {
  text-align: left;
  padding: 10px 14px 10px 0;
  border-bottom: 1px solid var(--border-strong);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--teal);
  white-space: nowrap;
}

.tableau td {
  padding: 11px 14px 11px 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.92rem;
  vertical-align: middle;
}

.tableau .col-nombre {
  text-align: right;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.tableau .col-jauge {
  min-width: 190px;
}

.niveaux-membre {
  display: flex;
  align-items: center;
  gap: 10px;
  white-space: nowrap;
}

/* ---------- Console du journal ---------- */

.journal-flux {
  max-height: 520px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #0a1017;
}

.journal-ligne {
  display: grid;
  grid-template-columns: auto auto auto minmax(0, 1fr) auto auto;
  align-items: baseline;
  gap: 12px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--border);
  font-size: 0.85rem;
}

.journal-ligne:last-child {
  border-bottom: none;
}

/* Un passage de niveau se repère au filet et au fond, pas seulement au texte. */
.journal-ligne--passage {
  border-left: 3px solid var(--gold);
  background: rgba(201, 162, 74, 0.07);
}

.journal-heure {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--text-dim);
}

/* Les sources gardent chacune un libellé écrit : la couleur seule ne porte
   jamais l'information. */
.journal-source {
  padding: 1px 9px;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 600;
  white-space: nowrap;
}

.source--message { background: rgba(86, 160, 173, 0.16); color: var(--teal); }
.source--vocal { background: rgba(116, 192, 145, 0.16); color: var(--green); }
.source--admin { background: rgba(201, 162, 74, 0.16); color: var(--gold-bright); }

.journal-pseudo {
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}

.journal-detail {
  color: var(--text-dim);
  font-size: 0.82rem;
  min-width: 0;
}

.journal-gain {
  font-family: var(--font-mono);
  color: var(--green);
  white-space: nowrap;
}

.journal-niveau {
  font-size: 0.8rem;
  color: var(--text-dim);
  white-space: nowrap;
}

.journal-ligne--passage .journal-niveau {
  color: var(--gold-bright);
  font-weight: 600;
}

/* ---------- Simulateur ---------- */

.simu-champs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 16px;
  margin-top: 8px;
}

.simu-champ {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.simu-champ input {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 0.95rem;
}

.simu-champ input:focus {
  outline: none;
  border-color: var(--teal);
}

.simu-case {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 18px;
  color: var(--text-soft);
}

.simu-actions {
  margin: 20px 0 4px;
}

.simu-bilan {
  display: flex;
  align-items: center;
  gap: 22px;
  flex-wrap: wrap;
  margin-top: 20px;
  padding: 18px;
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
}

.simu-etat {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 190px;
  flex: 1;
}

.simu-niveau {
  font-family: var(--font-display);
  font-size: 1.5rem;
  color: var(--gold-bright);
}

.simu-gain {
  font-family: var(--font-mono);
  font-size: 1.5rem;
  color: var(--green);
  white-space: nowrap;
}

.simu-passage {
  margin-top: 12px;
  color: var(--gold-bright);
  font-weight: 600;
}

@media (max-width: 900px) {
  .classement-ligne {
    grid-template-columns: 30px auto minmax(0, 1fr) auto;
  }

  .classement-progression {
    grid-column: 1 / -1;
  }

  /* Sans placement explicite, ces deux derniers éléments retombaient dans la
     colonne 30px du rang (prévue pour un simple chiffre) et débordaient l'un
     sur l'autre. */
  .niveau-pastille {
    grid-column: 2 / 3;
  }

  .classement-xp {
    grid-column: 3 / -1;
    justify-self: end;
  }

  .journal-ligne {
    grid-template-columns: auto auto minmax(0, 1fr) auto;
  }

  .journal-detail {
    grid-column: 1 / -1;
  }

  .journal-gain {
    grid-column: 1 / 2;
  }

  .journal-niveau {
    grid-column: 2 / -1;
  }
}

/* ---------- Fiche d'un membre ---------- */

.est-cliquable {
  cursor: pointer;
  transition: background 0.12s ease;
}

.classement-ligne.est-cliquable:hover,
tr.est-cliquable:hover {
  background: var(--bg-hover);
}

.est-cliquable:focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: -2px;
  border-radius: var(--radius-sm);
}

.fiche-membre {
  text-align: left;
}

.fiche-entete {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-bottom: 20px;
}

.membre-avatar--grand {
  width: 78px;
  height: 78px;
}

.fiche-identite {
  display: flex;
  flex-direction: column;
  gap: 7px;
  align-items: flex-start;
}

.fiche-pseudo {
  font-family: var(--font-display);
  font-size: 1.7rem;
  font-weight: 600;
  color: var(--gold-bright);
  line-height: 1.1;
}

.fiche-progression {
  display: flex;
  flex-direction: column;
  gap: 7px;
  margin-bottom: 20px;
}

.fiche-progression-texte {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.fiche-membre h4 {
  margin: 24px 0 10px;
  font-size: 1.04rem;
  font-weight: 600;
  color: var(--teal);
}

.fiche-activites {
  max-height: 260px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #0a1017;
}

.fiche-activite {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr) auto auto;
  align-items: baseline;
  gap: 12px;
  padding: 8px 13px;
  border-bottom: 1px solid var(--border);
  font-size: 0.85rem;
}

.fiche-activite:last-child {
  border-bottom: none;
}

.fiche-activite--passage {
  border-left: 3px solid var(--gold);
  background: rgba(201, 162, 74, 0.07);
}

@media (max-width: 640px) {
  .fiche-activite {
    grid-template-columns: auto auto minmax(0, 1fr);
  }
}

/* ---------- Accès invité ---------- */

.login-separateur {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 22px 0 16px;
  color: var(--text-dim);
  font-size: 0.82rem;
}

.login-separateur::before,
.login-separateur::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

.login-invite {
  width: 100%;
  padding: 12px;
}

/* "Créer un compte" passe au-dessus de "Se connecter en tant qu'invité"
   (Morey, 01/09/2026) : l'écart qui séparait avant creer-compte de la note
   invité se met maintenant entre les deux boutons. */
#login-creer-compte {
  margin-bottom: 10px;
}

.login-invite-note {
  margin: 10px 0 0;
  font-size: 0.8rem;
  color: var(--text-dim);
  line-height: 1.45;
}

/* ---------- Réglages d'équilibrage ---------- */
/* Libellé et explication à gauche, valeur alignée à droite : on parcourt la
   colonne des valeurs sans lire tous les intitulés. */

.reglage {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 18px;
  align-items: baseline;
  padding: 11px 0;
  border-bottom: 1px solid var(--border);
}

.reglage:last-child {
  border-bottom: none;
}

.reglage-texte {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.reglage-libelle {
  color: var(--text);
  font-size: 0.98rem;
}

.reglage-valeur {
  font-family: var(--font-mono);
  font-size: 1rem;
  color: var(--gold-bright);
  white-space: nowrap;
  text-align: right;
}

/* ---------- Formulaire des réglages ---------- */

.reglages-form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 18px;
  margin-top: 6px;
}

.reglage-champ {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.reglage-champ-libelle {
  font-size: 0.92rem;
  color: var(--text-soft);
}

.reglage-champ input {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  color: var(--gold-bright);
  font-family: var(--font-mono);
  font-size: 0.98rem;
}

.reglage-champ input:focus {
  outline: none;
  border-color: var(--teal);
}

.param-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.historique-ligne {
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}

.historique-ligne:last-child {
  border-bottom: none;
}

.historique-entete {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 3px;
}

/* ---------- Bandeau positif (arrivage) ---------- */
/* Même structure que .notice, en vert plutôt qu'en or : c'est une bonne
   nouvelle, pas un avertissement, et la couleur doit le dire d'un coup d'œil. */

.notice--succes {
  border-color: var(--green);
  background: #12241a;
}

.notice--succes .notice-icon {
  color: var(--green);
}

.notice--succes .notice-title {
  color: var(--green);
}

/* ---------- Espace vendeur : actions et panier ---------- */

.vendeur-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 32px;
}

/* Sur mobile, une action principale pleine largeur puis les deux secondaires
   côte à côte, plutôt que 3 boutons de largeurs disparates qui se
   réorganisent au hasard du flex-wrap (04/09/2026). */
@media (max-width: 640px) {
  .vendeur-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 9px;
    margin-bottom: 24px;
  }

  .vendeur-actions .modal-btn {
    min-height: 46px;
    text-align: center;
  }

  #btn-declarer-vente {
    grid-column: 1 / -1;
  }

  /* Le panier passe en barre flottante ancrée en bas de l'écran, toujours
     accessible sans remonter en haut de page. */
  #panier-ouvrir {
    position: fixed;
    left: 16px;
    right: 16px;
    bottom: 16px;
    z-index: 250;
    justify-content: center;
    padding: 13px 18px;
    border-radius: 999px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  }

  #ruptures-root {
    padding-bottom: 76px;
  }
}

.panier-bouton {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  color: var(--text);
  font-family: inherit;
  font-size: 0.92rem;
  cursor: pointer;
  transition: border-color 0.12s ease, background 0.12s ease;
}

.panier-bouton:hover {
  border-color: var(--border-strong);
  background: var(--bg-hover);
}

.panier-bouton svg {
  width: 18px;
  height: 18px;
  color: var(--gold);
  flex-shrink: 0;
}

/* Panneau coulissant façon panier de commerce : fond assombri, tiroir ancré
   à droite. Le fond ferme au clic, comme n'importe quel panier en ligne. */
.panier-overlay {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  justify-content: flex-end;
}

.panier-overlay.is-hidden {
  display: none;
}

.panier-fond {
  position: absolute;
  inset: 0;
  background: rgba(6, 10, 15, 0.6);
}

.panier-panneau {
  position: relative;
  width: min(420px, 100vw);
  height: 100%;
  background: var(--bg-panel);
  border-left: 1px solid var(--border-strong);
  display: flex;
  flex-direction: column;
  box-shadow: -20px 0 40px rgba(0, 0, 0, 0.4);
  animation: glisser-panier 0.18s ease-out;
}

@keyframes glisser-panier {
  from { transform: translateX(24px); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}

.panier-entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 22px;
  border-bottom: 1px solid var(--border);
}

.panier-entete h3 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.4rem;
  color: var(--gold-bright);
}

.panier-fermer {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text-dim);
  cursor: pointer;
}

.panier-fermer:hover {
  color: var(--text);
  background: var(--bg-hover);
}

.panier-fermer svg {
  width: 16px;
  height: 16px;
}

#panier-corps {
  flex: 1;
  overflow-y: auto;
  padding: 20px 22px;
}

.panier-semaines {
  width: 100%;
  margin-bottom: 16px;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  color: var(--text);
  font-family: inherit;
}

.panier-total {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 16px 18px;
  margin-bottom: 20px;
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
}

.panier-total .tuile-valeur {
  color: var(--gold-bright);
  font-size: 1.6rem;
}

.panier-jour {
  margin-bottom: 18px;
}

.panier-jour h4 {
  margin: 0 0 8px;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--teal);
}

.panier-liste {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.panier-ligne {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto auto auto;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.9rem;
}

.panier-badge-brouillon {
  display: inline-block;
  margin-left: 6px;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(201, 162, 74, 0.15);
  color: var(--gold-bright);
  font-size: 0.72rem;
  font-weight: 600;
  white-space: nowrap;
}

.panier-valider {
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text-soft);
  font-family: inherit;
  font-size: 0.78rem;
  cursor: pointer;
  white-space: nowrap;
}

.panier-valider:hover {
  border-color: var(--border-accent);
  color: var(--gold-bright);
}

.panier-ligne:last-child {
  border-bottom: none;
}

.panier-heure {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--text-dim);
}

.panier-nom {
  color: var(--text-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.panier-prix {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--text);
  white-space: nowrap;
}

.panier-supprimer,
.panier-modifier-date {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--text-dim);
  cursor: pointer;
}

.panier-supprimer:hover {
  color: var(--red);
  background: var(--bg-hover);
}

.panier-modifier-date:hover {
  color: var(--teal);
  background: var(--bg-hover);
}

.panier-supprimer svg,
.panier-modifier-date svg {
  width: 12px;
  height: 12px;
}

/* Sur mobile, la grille à 6 colonnes serrait tout sur une seule ligne · un
   nom de produit un peu long finissait tronqué. Réordonné en 2 lignes par
   simple flexbox (mêmes éléments, même ordre dans le DOM) : le nom sur sa
   propre ligne, puis l'heure et les actions groupées en dessous (04/09/2026). */
@media (max-width: 640px) {
  .panier-ligne {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    row-gap: 4px;
    column-gap: 10px;
    padding: 10px 0;
  }

  .panier-nom {
    order: 1;
    flex: 1 1 100%;
    white-space: normal;
  }

  .panier-heure {
    order: 2;
    margin-right: auto;
  }

  .panier-prix {
    order: 3;
  }

  .panier-valider {
    order: 4;
  }

  .panier-modifier-date {
    order: 5;
  }

  .panier-supprimer {
    order: 6;
  }
}

/* ---------- Ruptures ---------- */

.ruptures-liste {
  display: flex;
  flex-direction: column;
}

.rupture-ligne {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 16px;
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}

.rupture-ligne:last-child {
  border-bottom: none;
}

.rupture-pastille {
  padding: 4px 12px;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
}

.rupture-niveau--mag {
  color: var(--gold-bright);
  background: rgba(201, 162, 74, 0.15);
}

.rupture-niveau--graveson {
  color: var(--red);
  background: rgba(221, 143, 143, 0.15);
}

/* Le plus sévère se distingue par un fond plein, pas seulement une nuance :
   c'est le seul niveau souvent national, il doit sauter aux yeux en premier. */
.rupture-niveau--hb2 {
  color: var(--bg);
  background: var(--red);
}

.rupture-nom {
  font-weight: 500;
  color: var(--text);
}

.rupture-date {
  display: flex;
  flex-direction: column;
  gap: 3px;
  align-items: flex-end;
}

.rupture-date-input {
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  color: var(--text);
  font-family: inherit;
  font-size: 0.85rem;
}

/* ---------- Choix du niveau de rupture (formulaire) ---------- */

.rupture-choix {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin: 8px 0 18px;
}

.rupture-option {
  display: flex;
  align-items: flex-start;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color 0.12s ease, background 0.12s ease;
}

.rupture-option:has(input:checked) {
  border-color: var(--border-accent);
  background: var(--bg-subtle);
}

.rupture-option input {
  margin-right: 8px;
  margin-top: 2px;
  accent-color: var(--gold);
}

.rupture-option strong {
  color: var(--text);
  font-size: 0.92rem;
}

@media (max-width: 640px) {
  .rupture-choix {
    grid-template-columns: 1fr;
  }

  /* Chaque rupture devient une petite carte à 2 lignes (pastille + nom, puis
     retour prévu + bouton) plutôt qu'un simple empilement vertical des 4
     cellules · même éléments, replacés par grille CSS (04/09/2026). */
  .rupture-ligne {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 8px 10px;
    padding: 13px 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-card);
    margin-bottom: 8px;
  }

  .rupture-pastille {
    grid-column: 1;
    grid-row: 1;
  }

  .rupture-nom {
    grid-column: 2 / span 2;
    grid-row: 1;
    min-width: 0;
    overflow-wrap: break-word;
  }

  .rupture-date {
    grid-column: 1 / span 2;
    grid-row: 2;
    flex-direction: row;
    align-items: center;
    gap: 8px;
    /* Un item de grille garde par défaut sa largeur de contenu minimale
       (min-width: auto), jamais recalculée pour un conteneur flex imbriqué :
       le label "Retour prévu" + la largeur native du sélecteur de date
       dépassaient alors la colonne, chevauchant le bouton "Réapprovisionné"
       à côté (18/09/2026, Morey : « sur mobile les menus se chevauchent »).
       min-width: 0 laisse enfin la ligne se comprimer comme le reste. */
    min-width: 0;
  }

  .rupture-resoudre {
    grid-column: 3;
    grid-row: 2;
    justify-self: end;
    align-self: center;
  }

  /* Le sélecteur de date lui-même doit pouvoir se comprimer en dessous de sa
     largeur native (souvent ~150 px selon le navigateur) : sans ça, c'est LUI
     qui déborde de .rupture-date même une fois celle-ci compressible. */
  .rupture-date .diag-note {
    flex-shrink: 0;
  }

  .rupture-date-input {
    min-width: 0;
    flex: 1;
  }

  /* La règle de base retire le bas de bordure du dernier élément (liste sans
     carte) : ici chaque ligne EST une carte, la dernière en a autant besoin
     que les autres. */
  .rupture-ligne:last-child {
    border-bottom: 1px solid var(--border);
  }

  .panier-panneau {
    width: 100vw;
  }
}

/* ==================================================================
   Cartes à collectionner
   ================================================================== */

/* ---------- Effort communautaire (16/09/2026) ---------- */
/* Encore au-dessus de la bannière de tirages ci-dessous (voir rendreCadreCartes) -
   reste visible sur tous les sous-onglets, pas seulement « Ma collection ». */

.effort-carte {
  background: var(--bg-panel);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  padding: 14px 20px 16px;
  margin-bottom: 12px;
}

.effort-titre {
  margin: 0 0 12px;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 600;
  color: var(--gold-bright);
}

.effort-frise {
  display: flex;
  align-items: center;
}

.effort-trait {
  flex-shrink: 0;
  width: 28px;
  height: 2px;
  background: var(--border);
  margin: 0 -2px;
}

.effort-trait--fait {
  background: var(--gold);
}

.effort-etape {
  position: relative;
  flex: 1;
  display: flex;
  justify-content: center;
  min-width: 0;
}

.effort-rond {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-subtle);
  border: 1.5px solid var(--border);
  color: var(--text-dim);
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.effort-rond--fait {
  background: var(--gold);
  border-color: var(--gold);
  color: #1a1305;
}

.effort-etape:hover .effort-rond {
  transform: scale(1.14);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
}

.effort-rond svg {
  width: 20px;
  height: 20px;
}

/* Infobulle posée au survol, en CSS pur. */
.effort-bulle {
  position: absolute;
  bottom: calc(100% + 12px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  width: 220px;
  background: var(--bg-panel);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.12s ease, transform 0.12s ease;
  z-index: 5;
  text-align: left;
}

.effort-etape:hover .effort-bulle {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
}

.effort-bulle::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-top-color: var(--border-strong);
}

.effort-bulle-recompense {
  font-size: 0.74rem;
  font-weight: 600;
  color: var(--gold-bright);
  margin-bottom: 4px;
}

.effort-bulle-objectif {
  font-size: 0.8rem;
  color: var(--text);
  margin-bottom: 8px;
  line-height: 1.35;
}

.effort-bulle-barre-piste {
  height: 5px;
  border-radius: 999px;
  background: var(--border);
  overflow: hidden;
  margin-bottom: 3px;
}

.effort-bulle-barre-remplie {
  height: 100%;
  background: var(--gold);
  border-radius: 999px;
}

.effort-bulle-chiffre {
  font-size: 0.72rem;
  color: var(--text-dim);
  font-family: var(--font-mono);
  margin-bottom: 9px;
}

.effort-bulle-chiffre--complet {
  color: var(--gold-bright);
}

.effort-bulle-info {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  font-size: 0.68rem;
  color: var(--text-dim);
  line-height: 1.4;
}

.effort-bulle-info svg {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
  margin-top: 1px;
}

/* ---------- Reveal de cartes (récompenses, tirages, boosters) ---------- */
/* Réutilise la mise en page de la fiche carte (voir ouvrirDetailCarte,
   .carte-detail-card) - pastille de rareté, nom dans sa couleur, univers et
   type, description, passif/utilisable - Morey (18/09/2026) a demandé que le
   reveal ressemble à la fiche plutôt qu'à un simple visuel de carte, plus
   large pour que tout tienne, avec le même comportement mobile (le
   bottom-sheet de .modal-card sur petit écran s'applique donc aussi ici). */

.reveal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(6, 10, 15, 0.82);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 400;
  padding: 20px;
}

/* Resserrée de 480 à 400 px avec la refonte du 17/09/2026 : la carte étant
   devenue un objet encadré plus étroit, une modale large lui laissait deux
   bandes vides sur les côtés. */
.reveal-detail-modal {
  max-width: 400px;
}

.reveal-titre {
  margin: 0 0 14px;
  font-family: var(--font-display);
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--gold-bright);
  text-align: center;
}

/* Porte la transition ET le clic pour avancer : tout le contenu de la fiche
   glisse d'un bloc, texte compris (Morey, 16/09/2026 : pas de retournement,
   juste une glissade vers la carte suivante). */
#reveal-contenu {
  position: relative;
  cursor: pointer;
  transition: transform 0.22s ease, opacity 0.22s ease;
}

#reveal-contenu.reveal-transition--partante {
  transform: translateX(-38px) scale(0.97);
  opacity: 0;
}

#reveal-contenu.reveal-transition--arrivante {
  animation: revealEntree 0.26s ease;
}

@keyframes revealEntree {
  from {
    transform: translateX(38px) scale(0.97);
    opacity: 0;
  }
  to {
    transform: translateX(0) scale(1);
    opacity: 1;
  }
}

/* ----- Refonte du 17/09/2026 (Morey) : la carte du reveal devient un objet
   encadré plutôt qu'un panneau. Tout ce qui suit est porté par `.reveal-cadre`
   et ses descendants, JAMAIS par les classes partagées (.carte-detail-*,
   .carte-image-cadre) : la fiche carte ordinaire d'ouvrirDetailCarte réutilise
   exactement les mêmes, et ne doit pas changer d'allure. ----- */

/* La bordure de rareté entoure TOUTE la carte, illustration et textes
   compris · avant, seule la vignette en portait une. */
.reveal-cadre {
  padding: 5px;
  border-radius: 14px;
  background: var(--rarete, var(--border-strong));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--rarete) 26%, transparent), 0 10px 30px rgba(0, 0, 0, 0.45);
}

/* Le dégradé prismatique déjà validé pour les tuiles Mythiques, jamais un
   aplat rose · même trois arrêts, même diagonale (voir .carte-tuile--mythique). */
.reveal-cadre--mythique {
  background: linear-gradient(135deg, #82e1dc 0%, #b5c7f1 50%, #f1aadd 100%);
}

/* `overflow: hidden` fait tenir l'illustration dans l'arrondi intérieur :
   c'est ce qui lui permet de toucher le cadre sans déborder des coins. */
.reveal-cadre-interieur {
  background: var(--bg-card);
  border-radius: 9px;
  overflow: hidden;
}

/* Seul le bloc de texte est rembourré · l'illustration, elle, va au bord. */
.reveal-corps {
  padding: 13px;
}

/* L'illustration ne déborde plus de la carte (elle passait en
   `calc(100% + 56px)` via .carte-detail-card, soit ~496 px de large sur une
   modale de 480) et n'est plus carrée : une fenêtre un peu moins haute, qui
   laisse la place aux textes sans faire défiler la modale. */
.reveal-cadre .carte-image-cadre {
  margin: 0;
  width: 100%;
  aspect-ratio: 308 / 250;
}

/* Pastille et nom réellement alignés : `align-self: flex-start` collait la
   pastille en haut de la ligne pendant que le nom, plus grand, se centrait
   plus bas (signalé par Morey le 16/09/2026). */
.reveal-cadre .carte-pastille-rarete {
  align-self: center;
  margin: 0;
}

.reveal-cadre .carte-detail-entete {
  gap: 10px;
  margin-bottom: 0;
}

/* Les blocs internes n'ont plus à se décaler : c'est `.reveal-corps` qui
   porte désormais le rembourrage commun. */
.reveal-cadre .carte-bloc,
.reveal-cadre .carte-detail-mode,
.reveal-cadre .carte-quantite-ligne {
  margin-left: 0;
  margin-right: 0;
}

/* Banderole « Nouveau » : horizontale, centrée sur la moitié de la largeur,
   posée au-dessus du cadre (Morey, 16/09/2026). Remplace le badge en
   diagonale, qui débordait du coin haut gauche. Les encoches aux deux bouts
   lui donnent sa forme de banderole sans rien ajouter au balisage. */
.reveal-banderole {
  position: relative;
  z-index: 3;
  /* « La moitié de la fenêtre » se compte sur la MODALE, pas sur sa zone de
     contenu : un simple `50 %` se résout contre celle-ci (largeur moins les
     28 px de rembourrage de chaque côté) et ne donnait que 43 % du bandeau
     attendu. Les 28 px rajoutés compensent exactement ce rembourrage. */
  width: calc(50% + 28px);
  margin: 0 auto -11px;
  padding: 6px 0;
  background: var(--gold);
  color: #1a1305;
  font-weight: 700;
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-align: center;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45);
  pointer-events: none;
  /* Encoches en V aux deux bouts · les points dupliqués de la première
     version rendaient un simple rectangle, l'effet banderole ne se voyait
     pas du tout (constaté à la capture, pas à la lecture du code). */
  clip-path: polygon(0 0, 100% 0, calc(100% - 13px) 50%, 100% 100%, 0 100%, 13px 50%);
}

/* Effet CHANCE / passif déclenché à l'obtention - jamais les deux raisons
   d'être fières l'une sur l'autre, chacune sa ligne. */
.reveal-badge-info {
  margin: 10px 0 0;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  font-size: 0.82rem;
  line-height: 1.4;
  text-align: left;
}

.reveal-badge-chance {
  background: color-mix(in srgb, var(--teal) 18%, var(--bg-subtle));
  border: 1px solid var(--teal);
  color: var(--text);
}

.reveal-badge-effet {
  background: color-mix(in srgb, var(--gold) 15%, var(--bg-subtle));
  border: 1px solid var(--gold);
  color: var(--gold-bright);
}

.reveal-hint {
  font-size: 0.76rem;
  color: var(--text-dim);
  text-align: center;
  margin: 16px 0 18px;
  min-height: 1.2em;
}

.reveal-points {
  display: flex;
  justify-content: center;
  gap: 6px;
  margin-bottom: 16px;
}

.reveal-point {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--border);
  flex-shrink: 0;
}

.reveal-point--fait {
  background: var(--gold);
}

.reveal-point--actif {
  background: var(--gold-bright);
}

.reveal-fermer-btn {
  display: block;
  width: 100%;
  padding: 9px 18px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  background: var(--gold);
  color: #1a1305;
  font-weight: 600;
  font-size: 0.9rem;
  font-family: inherit;
  cursor: pointer;
}

.reveal-fermer-btn:disabled {
  background: var(--bg-subtle);
  color: var(--text-dim);
  border-color: var(--border);
  cursor: not-allowed;
}

/* Au-dessus des sous-onglets (voir rendreCadreCartes) : reste visible qu'on
   soit sur « Ma collection », le Classement ou l'Administration. */
.carte-tirages-banniere {
  margin-bottom: 12px;
  padding: 10px 16px;
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-size: 0.88rem;
  text-align: center;
}

.carte-tirages-banniere--dispo {
  background: color-mix(in srgb, var(--gold) 15%, var(--bg-subtle));
  border-color: var(--gold);
  color: var(--gold-bright);
  font-weight: 600;
}

/* Ouvrir tirages/boosters depuis le site (17/09/2026) : la bannière porte
   directement le bouton, plus juste un texte. */
.carte-tirages-banniere--ouvrable {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 12px;
}

.modal-actions--colonne {
  flex-direction: column;
  align-items: stretch;
}

.quantite-picker {
  display: flex;
  gap: 10px;
  align-items: center;
  margin: 14px 0 10px;
}

.quantite-picker input {
  width: 90px !important;
  text-align: center;
}

.quantite-picker .modal-btn {
  flex-shrink: 0;
}

.carte-grille {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 16px;
  margin-top: 12px;
}

/* Sur un écran assez large pour ça, 5 colonnes fixes plutôt que le nombre
   variable renvoyé par auto-fill (6 sur un écran de bureau classique) -
   des cartes plus grandes, illustration et texte plus lisibles. En dessous,
   la grille reste responsive via auto-fill (moins de colonnes, jamais 5
   colonnes écrasées sur un petit écran). */
@media (min-width: 1000px) {
  .carte-grille {
    grid-template-columns: repeat(5, 1fr);
  }
}

/* Sur mobile, la vignette est devenue compacte (image + titre, le reste
   passe dans la fiche au clic · voir ouvrirDetailCarte) : 4 colonnes fixes
   tiennent, là où le texte complet d'avant aurait forcé 1 seule colonne. */
@media (max-width: 640px) {
  .carte-grille {
    grid-template-columns: repeat(4, 1fr);
    gap: 8px;
  }

  .carte-tuile {
    border-width: 3px;
  }

  .carte-tuile .carte-titre {
    margin: 6px 6px 4px;
    font-size: 0.78rem;
    letter-spacing: 0.01em;
  }

  .carte-quantite-mini {
    margin: 0 6px 6px;
    font-size: 0.7rem;
  }
}

/* "Ma collection" sur mobile passe en liste (13/09/2026, maquette validée par
   Morey) : la grille à 4 colonnes ci-dessus tronquait les noms et le texte
   des rubans (Non découverte/Découverte/Obtenu). Une ligne par carte, avec
   la même grille CSS que la version bureau (mêmes éléments, replacés par
   grid-template-areas) · rien à dupliquer côté JS, tuileCarte() reste
   identique aux deux tailles d'écran. Scopé à #collection-grille : les
   autres grilles de cartes (Night Market, Boutique, Combo) gardent leur
   rendu actuel, elles n'ont pas été revues ici. */
@media (max-width: 640px) {
  #collection-grille .carte-grille {
    grid-template-columns: 1fr;
    gap: 8px;
  }

  #collection-grille .carte-tuile {
    display: grid;
    grid-template-columns: 60px 1fr auto;
    grid-template-areas:
      "image ruban chevron"
      "image titre chevron"
      "image qte chevron";
    align-items: center;
    gap: 3px 12px;
    padding: 8px;
  }

  #collection-grille .carte-image-cadre {
    grid-area: image;
    width: 60px;
  }

  #collection-grille .carte-tuile .carte-ruban {
    grid-area: ruban;
    justify-self: start;
    justify-content: flex-start;
    padding: 2px 6px;
    font-size: 0.62rem;
  }

  #collection-grille .carte-tuile .carte-titre {
    grid-area: titre;
    margin: 0;
    font-size: 1rem;
  }

  #collection-grille .carte-quantite-mini {
    grid-area: qte;
    margin: 0;
  }

  #collection-grille .carte-tuile-chevron {
    grid-area: chevron;
    display: flex;
  }
}

.carte-tuile-chevron {
  display: none;
  flex: 0 0 auto;
  color: var(--text-dim);
}

.carte-tuile-chevron svg {
  width: 18px;
  height: 18px;
  transform: rotate(-90deg);
}

.carte-tuile {
  display: flex;
  flex-direction: column;
  background: var(--bg-subtle);
  border: 6px solid var(--rarete, var(--border));
  border-radius: var(--radius-sm);
  overflow: hidden;
  padding-bottom: 10px;
  transition: box-shadow 0.12s ease;
}

/* Mythique (0.2, voir COORDINATION.md section 1) : Discord n'affiche qu'une
   couleur unie dans l'embed (fallback #F1AADD envoyé par le bot dans
   --rarete), mais le site peut afficher le vrai dégradé prismatique.
   Recette validée par Morey le 27/08 : diagonale 135deg, 3 arrêts exacts. Le
   fond doit rester repeint en --bg-subtle (deuxième calque, clip padding-box)
   pour ne pas perdre le fond de la tuile · seule la bordure porte le dégradé. */
.carte-tuile--mythique {
  border: 6px solid transparent;
  background:
    linear-gradient(var(--bg-subtle), var(--bg-subtle)) padding-box,
    linear-gradient(135deg, #82e1dc 0%, #b5c7f1 50%, #f1aadd 100%) border-box;
}

/* Cliquable (voir ouvrirDetailCarte) : anneau dans la couleur de rareté au
   survol/focus, plutôt que le fond uni réutilisé pour les lignes de tableau
   · une bordure déjà colorée dans --rarete ne se prête pas au même effet. */
.carte-tuile.est-cliquable:hover,
.carte-tuile.est-cliquable:focus-visible {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--rarete) 60%, transparent);
  outline: none;
}

/* Plus grisée qu'avant (13/09/2026, Morey) : une carte découverte mais pas
   en main doit clairement se distinguer d'une carte possédée, le simple
   opacity: 0.6 d'origine passait trop inaperçu. */
.carte-tuile--non-obtenue {
  opacity: 0.45;
  filter: grayscale(65%);
}

/* Bannière d'état (10/09/2026, Morey ; corrigé le 13/09/2026) : juste
   au-dessus de l'avatar, un état parmi trois · non découverte (rouge),
   découverte mais aucun exemplaire EN MAIN actuellement (blanc, y compris
   une carte déjà revendue), ou au moins un exemplaire possédé maintenant
   (vert). */
.carte-ruban {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  font-size: 0.65rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 3px 4px;
}

.carte-ruban svg {
  width: 12px;
  height: 12px;
  flex: 0 0 auto;
}

.carte-ruban--rouge {
  color: var(--red);
  background: color-mix(in srgb, var(--red) 18%, transparent);
}

.carte-ruban--blanc {
  color: var(--text);
  background: color-mix(in srgb, var(--text) 12%, transparent);
}

.carte-ruban--vert {
  color: var(--green);
  background: color-mix(in srgb, var(--green) 18%, transparent);
}

/* Bannière de récompense de découverte (10/09/2026) : même gabarit que
   .carte-tirages-banniere--dispo (déjà doré/cliquable), juste un curseur et
   un léger surlignage au survol pour signaler qu'il y a une action derrière. */
.carte-decouvertes-banniere:hover,
.carte-decouvertes-banniere:focus-visible {
  background: color-mix(in srgb, var(--gold) 24%, var(--bg-subtle));
  outline: none;
}

.carte-decouvertes-modal {
  max-width: 480px;
}

.carte-decouvertes-liste {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-height: 340px;
  overflow-y: auto;
  margin: 14px 0;
}

.carte-decouverte-ligne {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px;
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
}

.carte-decouverte-ligne .carte-image-cadre {
  width: 52px;
  flex: 0 0 auto;
  border-radius: var(--radius-sm);
}

.carte-decouverte-info {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.carte-decouverte-nom {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--text);
  overflow-wrap: anywhere;
}

.carte-decouverte-info .carte-pastille-rarete {
  align-self: flex-start;
  margin: 0;
}

.carte-quantite-mini {
  margin: 0 10px 8px;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--gold-bright);
}

.carte-valeur-mini {
  margin-left: 2px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 400;
  color: var(--text-dim);
}

/* Fiche détaillée ouverte au clic sur une vignette (voir ouvrirDetailCarte).
   Image bord à bord en haut de la modale, texte dans le padding habituel. */
.carte-detail-card {
  padding-top: 0;
}

.carte-detail-card .carte-image-cadre {
  margin: 0 -28px 16px;
  width: calc(100% + 56px);
}

.carte-detail-card .carte-bloc {
  margin-left: 0;
  margin-right: 0;
}

.carte-detail-card .carte-pastille-rarete {
  margin-left: 0;
}

.carte-detail-card .carte-quantite-ligne {
  margin-left: 0;
  margin-right: 0;
  margin-bottom: 12px;
}

/* Pastille + nom sur une ligne, séparateur en dessous (15/09/2026, Morey) :
   remplace l'ancien h3 seul + pastille sur sa propre ligne. */
.carte-detail-entete {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 10px 10px;
}

.carte-detail-entete .carte-pastille-rarete {
  margin: 0;
  flex-shrink: 0;
}

.carte-detail-nom {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 600;
  line-height: 1.2;
}

.carte-detail-separateur {
  border: none;
  border-top: 1px solid var(--border);
  margin: 0 10px 14px;
}

/* Bloc Passif / Utilisable : même traitement que les cartes du marché
   (fond légèrement distinct), pour bien séparer les deux modes d'une carte
   qui a les deux à la fois. */
.carte-detail-mode {
  margin: 0 10px 12px;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
}

.carte-detail-mode-titre {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 4px;
  font-size: 0.76rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--gold-bright);
}

.carte-info-bulle {
  display: inline-flex;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1.2px solid var(--text-dim);
  align-items: center;
  justify-content: center;
  font-size: 0.62rem;
  font-weight: 700;
  font-style: italic;
  font-family: Georgia, serif;
  color: var(--text-dim);
  cursor: help;
  text-transform: none;
  letter-spacing: normal;
}

/* Modale ouverte au clic sur une tuile (voir ouvrirDecouvreurs). */
.carte-decouvreurs-info {
  color: var(--text-dim);
}

.carte-decouvreurs-premiere {
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  background: rgba(201, 162, 74, 0.15);
  border: 1px solid var(--gold);
  color: var(--gold-bright);
  font-weight: 600;
}

.carte-image-cadre {
  width: 100%;
  aspect-ratio: 1 / 1;
  background: var(--bg-panel);
  overflow: hidden;
}

.carte-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Calque prismatique des Mythiques (13/09/2026) · repris du rendu Discord
   (voir lib/cartes/prisme.js côté bot) : portrait éclairci, spectre à 7 arrêts
   en diagonale haut-gauche → bas-droit. Reproduit en CSS (mix-blend-mode)
   plutôt que servi en image pré-rendue : le site et le bot ne partagent pas
   de disque.

   ATTÉNUÉ LE 17/09/2026 (Morey : « l'effet multicolore en diagonale est trop
   fort, sur le site uniquement ») : opacité de 0,5 à 0,3. Le site diverge
   donc volontairement du rendu Discord, qui garde sa recette d'origine · une
   illustration occupe bien plus de place ici que dans un embed, le même
   spectre y écrasait le dessin. Ne pas « réaligner » les deux par souci de
   cohérence, l'écart est voulu. */
.carte-image-cadre--prisme {
  position: relative;
}

.carte-image-cadre--prisme .carte-image {
  filter: brightness(1.22);
}

.carte-image-prisme-calque {
  position: absolute;
  inset: 0;
  pointer-events: none;
  mix-blend-mode: hard-light;
  opacity: 0.3;
  background: linear-gradient(
    135deg,
    #ff4d4d 0%,
    #ffb24d 16%,
    #ffe94d 33%,
    #5cffb0 50%,
    #4dc9ff 66%,
    #8a4dff 83%,
    #ff4dc8 100%
  );
}

/* Aucune vraie image chargée pour une carte non découverte (voir tuileCarte) :
   le dérivé flouté du serveur en arrière-plan CSS (jamais une balise <img>,
   voir imageCadre) · assez dégradé pour ne rien révéler, juste une touche de
   couleur et de forme derrière une teinte de rareté. */
.carte-image-cadre--inconnue {
  background-color: var(--bg-panel);
  background-size: cover;
  background-position: center;
  position: relative;
}

.carte-image-cadre--inconnue::after {
  content: "";
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--rarete) 25%, transparent);
}

/* Sélecteur renforcé : la règle générale .card h4 (plus spécifique qu'une
   classe seule) gagnerait sinon sur la couleur et la taille. */
.carte-tuile .carte-titre {
  margin: 10px 10px 4px;
  font-family: var(--font-display);
  font-size: 1.3rem;
  font-weight: 700;
  color: #ffffff;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.carte-bloc {
  margin: 0 10px 8px;
}

.carte-bloc:last-of-type {
  flex-grow: 1;
}

.carte-bloc-titre {
  margin: 0 0 2px;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-dim);
}

.carte-bloc-texte {
  margin: 0;
  font-size: 0.85rem;
  color: var(--text-soft);
  /* Le masquage produit une longue suite de « ? » sans espace, donc sans point
     de coupure : sur une seule ligne et tronqué plutôt que de déborder du
     cadre. S'adapte à la largeur réelle de la carte, jamais un compte de
     caractères codé en dur qui serait faux à une autre taille d'écran. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Texte réel une fois la carte découverte : lisible en entier, plus besoin
   de tenir sur une ligne. */
.carte-bloc-texte--complet {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  overflow-wrap: break-word;
}

.carte-pastille-rarete {
  align-self: flex-start;
  margin: 0 10px 4px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--rarete);
  background: color-mix(in srgb, var(--rarete) 18%, transparent);
}

.carte-debug-banniere {
  padding: 8px 12px;
  background: rgba(86, 160, 173, 0.12);
  border: 1px solid var(--teal-dim);
  border-radius: var(--radius-sm);
  color: var(--teal);
}

.carte-quantite-ligne {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin: 0 10px;
}

.carte-quantite {
  font-weight: 600;
  color: var(--gold-bright);
}

.carte-non-obtenue {
  font-size: 0.82rem;
  color: var(--text-dim);
}

.carte-valeur-xp {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  color: var(--text-dim);
  white-space: nowrap;
}

/* ---------- Administration ---------- */

.carte-admin-liste {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 12px;
}

.carte-admin-ligne {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px;
  background: var(--bg-subtle);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
}

.carte-admin-vignette {
  width: 48px;
  height: 48px;
  border-radius: var(--radius-sm);
  object-fit: cover;
  background: var(--bg-panel);
  flex-shrink: 0;
}

.carte-admin-info {
  flex-grow: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* utilite (21/08/2026) : texte calculé par le bot pour cette carte précise -
   sur sa propre ligne sous les badges, plutôt que coincé entre eux. */
.carte-admin-utilite {
  flex-basis: 100%;
  font-size: 0.82rem;
  color: var(--text-dim);
}

.carte-admin-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}

.carte-badge-non-codee {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--red);
  background: rgba(221, 143, 143, 0.15);
  cursor: help;
}

.carte-badge-auto {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--gold-bright);
  background: rgba(201, 162, 74, 0.15);
  cursor: help;
}

.carte-checkbox-utilisable {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 10px 0;
  font-size: 0.92rem;
  color: var(--text-soft);
}

.carte-checkbox-utilisable input {
  accent-color: var(--gold);
}

/* ---------- Widget de recadrage ---------- */

.cropper-vide {
  padding: 16px;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-sm);
  text-align: center;
}

.cropper-zone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.cropper-cadre {
  width: 320px;
  height: 320px;
  max-width: 100%;
  overflow: hidden;
  position: relative;
  border-radius: var(--radius-sm);
  background: var(--bg-panel);
  border: 1px solid var(--border-strong);
  cursor: grab;
  touch-action: none;
}

.cropper-cadre:active {
  cursor: grabbing;
}

.cropper-image {
  position: absolute;
  top: 50%;
  left: 50%;
  user-select: none;
  pointer-events: none;
}

.cropper-zone input[type="range"] {
  width: 100%;
  accent-color: var(--gold);
}

.carte-recherche {
  display: block;
  width: 100%;
  max-width: 340px;
  padding: 10px 14px;
  margin: 12px 0;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-subtle);
  color: var(--text);
  font-family: inherit;
  font-size: 0.92rem;
}

/* ---------- Équilibrage des prix ---------- */

.equilibrage-bloc {
  padding: 12px;
  margin-bottom: 12px;
  border-left: 4px solid var(--rarete, var(--border));
  background: var(--bg-subtle);
  border-radius: var(--radius-sm);
}

.equilibrage-bloc:last-child {
  margin-bottom: 0;
}

.equilibrage-bloc h4 {
  margin: 0 0 8px;
  color: var(--rarete, var(--teal));
}

.equilibrage-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 10px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}

.equilibrage-stat strong {
  color: var(--text);
  margin-left: 4px;
}

.equilibrage-liste {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.equilibrage-ligne {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 0.92rem;
}

.equilibrage-nom {
  color: var(--text-soft);
}

.equilibrage-prix {
  color: var(--gold-bright);
  font-weight: 600;
  white-space: nowrap;
}

/* ---------- Aide « Lier mon discord » ---------- */

.discord-link-aide {
  margin: 8px 0;
  padding: 10px 12px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.discord-link-aide summary {
  cursor: pointer;
  font-size: 0.9rem;
  color: var(--teal);
  font-weight: 600;
}

.discord-link-aide p {
  margin: 8px 0 0;
  font-size: 0.85rem;
  color: var(--text-soft);
  line-height: 1.5;
}

.discord-link-preview {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 8px 0;
  padding: 8px;
  background: var(--bg-subtle);
  border-radius: var(--radius-sm);
}

/* ---------- Requête IA ---------- */

.requete-ia-intro {
  max-width: 640px;
  margin-bottom: 24px;
  line-height: 1.5;
}

.requete-ia-texte {
  width: 100%;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 12px 14px;
  font-family: inherit;
  font-size: 0.95rem;
  resize: vertical;
  min-height: 100px;
}

.requete-ia-texte:focus {
  outline: none;
  border-color: var(--teal);
}

#requete-ia-form .modal-btn {
  margin-top: 14px;
}

#requetes-ia-root {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.requete-ia-ligne {
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}

.requete-ia-ligne:last-child {
  border-bottom: none;
}

.requete-ia-ligne-entete {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
  flex-wrap: wrap;
}

.requete-ia-statut {
  padding: 4px 12px;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
}

.requete-ia-statut--nouveau {
  color: var(--gold-bright);
  background: rgba(201, 162, 74, 0.15);
}

.requete-ia-statut--en_cours {
  color: var(--teal);
  background: rgba(86, 160, 173, 0.15);
}

.requete-ia-statut--termine {
  color: var(--green);
  background: rgba(116, 192, 145, 0.15);
}

.requete-ia-date {
  color: var(--text-dim);
  font-size: 0.85rem;
}

.requete-ia-id {
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  cursor: help;
}

.requete-ia-urgent-btn {
  margin-left: auto;
  padding: 4px 12px;
  border-radius: 999px;
  border: 1px solid var(--red);
  background: transparent;
  color: var(--red);
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s ease;
}

.requete-ia-urgent-btn:hover {
  background: rgba(221, 143, 143, 0.15);
}

.requete-ia-urgent-btn:disabled {
  opacity: 0.6;
  cursor: default;
}

.requete-ia-urgent-badge {
  margin-left: auto;
  padding: 4px 12px;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
  color: var(--red);
  background: rgba(221, 143, 143, 0.15);
}

.requete-ia-texte-affiche {
  margin: 0;
  color: var(--text-soft);
  line-height: 1.5;
  white-space: pre-wrap;
}

.requete-ia-reponse {
  margin: 10px 0 0;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  color: var(--text);
  font-size: 0.92rem;
  line-height: 1.5;
}

.requete-ia-joindre {
  display: inline-flex;
  margin-top: 12px;
  cursor: pointer;
  user-select: none;
}

.requete-ia-apercu {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 12px;
}

.requete-ia-apercu-item {
  position: relative;
  width: 72px;
  height: 72px;
}

.requete-ia-apercu-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
}

.requete-ia-apercu-retirer {
  position: absolute;
  top: -6px;
  right: -6px;
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background: var(--red);
  color: var(--bg);
  cursor: pointer;
}

.requete-ia-apercu-retirer svg {
  width: 11px;
  height: 11px;
}

.requete-ia-images {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 10px;
}

.requete-ia-vignette {
  width: 90px;
  height: 90px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  cursor: pointer;
}

/* Recherche/filtres 0.2 de « Ma collection » (voir COORDINATION.md section
   7). Même vocabulaire visuel que les champs de .modal-card (fond/bordure),
   mais hors modale · redéclaré ici plutôt que réutilisé, .modal-card cible
   spécifiquement les champs à l'intérieur d'une modale. */
.carte-filtres {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin: 14px 0;
}

.carte-filtres input[type="search"],
.carte-filtres select {
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 9px 12px;
  font-size: 0.9rem;
  font-family: inherit;
}

.carte-filtres input[type="search"] {
  flex: 1 1 220px;
  min-width: 160px;
}

.carte-filtres input[type="search"]:focus,
.carte-filtres select:focus {
  outline: none;
  border-color: var(--teal);
}

.carte-filtre-tri {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.88rem;
  color: var(--text-dim);
  white-space: nowrap;
}

/* Onglet Combo (squelette 0.2, voir COORDINATION.md section 5) : un bloc par
   emplacement (Personnages / Lieu / Objet), réutilise .carte-grille pour les
   tuiles à l'intérieur. */
.combo-emplacement {
  margin-top: 18px;
}

.combo-emplacement h4 {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0 0 6px;
}

/* Sélection de l'univers (Morey, 30/08/2026) : le <select> natif restait
   blanc par défaut, hors du thème sombre du reste du site · même traitement
   que .modal-card select. */
#combo-univers {
  display: block;
  width: 100%;
  max-width: 320px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 10px 14px;
  font-size: 0.95rem;
  font-family: inherit;
  margin-top: 6px;
}

#combo-univers:focus {
  outline: none;
  border-color: var(--teal);
}

/* Ligne cliquable de "Mes combos" (Morey, 30/08/2026) : cliquer choisit
   l'univers, exactement comme le <select> ci-dessus · le bouton Démonter à
   côté n'est pas concerné, il reste hors de .combo-ligne-choisir. */
.combo-ligne-choisir {
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: background 0.12s ease;
}

.combo-ligne-choisir:hover,
.combo-ligne-choisir:focus-visible {
  background: var(--bg-panel);
  outline: none;
}

.combo-tuile-conteneur {
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: box-shadow 0.12s ease;
}

/* Carte non possédée listée dans le panneau (Morey, 01/09/2026) : visible
   (floutée ou non selon la découverte, voir tuileComboCarte) mais pas un
   choix possible · pas de curseur pointeur ni d'anneau de survol. */
.combo-tuile--non-possedee {
  cursor: default;
}

/* :not(.combo-tuile--selectionnee) est nécessaire, pas cosmétique : sans lui,
   .combo-tuile-conteneur:hover (spécificité 0,2,0) l'emportait sur
   .combo-tuile--selectionnee seule (0,1,0) et effaçait visuellement l'anneau
   doré dès que le curseur restait sur la carte · la sélection semblait
   disparaître au survol alors qu'elle restait active en mémoire. */
.combo-tuile-conteneur:hover:not(.combo-tuile--selectionnee):not(.combo-tuile--non-possedee),
.combo-tuile-conteneur:focus-visible:not(.combo-tuile--selectionnee):not(.combo-tuile--non-possedee) {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--rarete) 60%, transparent);
  outline: none;
}

.combo-tuile--selectionnee {
  box-shadow: 0 0 0 3px var(--gold-bright, var(--gold));
}

/* Un emplacement de combo (Morey, 30/08/2026) : un seul cadre · vide (gros
   "?") ou rempli (la carte choisie) · plutôt que la liste complète des
   possibilités affichée jusque-là. Même largeur qu'une cellule de
   .carte-grille pour rester visuellement cohérent avec le reste du site. */
.combo-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  max-width: 180px;
  margin-top: 10px;
}

.combo-slot .carte-tuile {
  width: 100%;
}

.carte-tuile--vide {
  border-style: dashed;
  border-color: var(--border);
}

.combo-slot-cadre {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2.6rem;
  font-weight: 700;
  color: var(--text-dim);
}

.combo-slot-bouton {
  width: 100%;
}

/* Panneau "Choisir un..." (Morey, 30/08/2026) : recherche + grille des
   cartes compatibles avec cet emplacement (possédées, sélectionnables ; les
   autres floutées ou en clair non cliquable selon la découverte · voir
   tuileComboCarte), ouvert sous le cadre au clic sur son bouton. */
.combo-picker {
  margin-top: 14px;
  padding: 14px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.combo-picker-barre {
  display: flex;
  gap: 8px;
  align-items: center;
}

.combo-picker-recherche {
  flex: 1 1 auto;
  min-width: 0;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 9px 12px;
  font-size: 0.9rem;
  font-family: inherit;
}

.combo-picker-recherche:focus {
  outline: none;
  border-color: var(--teal);
}

.combo-picker .carte-grille {
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 12px;
}

/* Night Market (0.3) : même carcasse que .combo-slot (carte + bouton en
   dessous), pas une mise en page à part. */
.night-market-tuile {
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* Un élément de grille CSS a par défaut min-width:auto · sa colonne ne peut
     pas rétrécir sous la largeur de son contenu le plus large. Avec le titre
     passé en white-space:nowrap juste en dessous, un nom de carte long
     devenait justement ce contenu impossible à rétrécir, et élargissait toute
     la colonne au détriment des autres (repéré par Morey : le correctif du
     titre sur une ligne avait transformé le bug de hauteur en bug de largeur,
     encore pire). min-width:0 rend la priorité à la grille : la colonne
     garde sa largeur 1fr, c'est le texte qui se tronque dedans. */
  min-width: 0;
}

.night-market-tuile .carte-tuile {
  width: 100%;
}

.night-market-bouton {
  width: 100%;
}

.night-market-achete {
  text-align: center;
  padding: 10px;
  font-size: 0.85rem;
  color: var(--text-dim);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

/* Retournement 3D (03/09/2026, Morey) : .night-market-carte porte la
   perspective, .night-market-carte-inner tourne (preserve-3d), chaque face a
   backface-visibility:hidden pour ne jamais montrer son dos à l'endroit. Le
   recto reste en flux normal (c'est lui qui donne sa hauteur au conteneur),
   le dos est calé dessus en position:absolute · pas de hauteur figée en dur
   à maintenir en synchro avec le contenu réel de la carte. */
.night-market-carte {
  perspective: 900px;
  cursor: pointer;
}

.night-market-carte:not([data-night-market-flip]) {
  cursor: default;
}

.night-market-carte-inner {
  position: relative;
  transition: transform 0.6s cubic-bezier(0.4, 0.15, 0.2, 1);
  transform-style: preserve-3d;
}

.night-market-carte.est-revele .night-market-carte-inner {
  transform: rotateY(180deg);
}

.night-market-face {
  backface-visibility: hidden;
  border-radius: var(--radius-sm);
}

.night-market-face--dos {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--bg-panel), var(--bg-subtle));
  border: 1px solid var(--border);
}

.night-market-face--recto {
  transform: rotateY(180deg);
}

/* Bug signalé par Morey le 03/09/2026 : une carte plus haute que ses voisines
   dans la grille, alors que toutes montrent encore leur dos. Cause : le recto
   reste en flux normal même caché (c'est lui qui donne sa hauteur au
   conteneur, voir plus haut) · un nom de carte assez long pour passer sur 2
   lignes rendait CETTE case plus haute que les autres, invisible tant que
   rien n'est retourné. Le dos doit avoir l'air d'un jeu de cartes uniforme :
   le titre reste sur une seule ligne (tronqué, "...") dans cette face
   précise, jamais dans .carte-tuile en général ailleurs sur le site. */
.night-market-face--recto .carte-titre {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Le losange du dos reprend le vocabulaire du logo (voir icons.js) : un
   losange tracé, un cœur plein · jamais un cercle. */
.night-market-dos-losange {
  position: relative;
  width: 44%;
  aspect-ratio: 1 / 1;
  border: 2px solid var(--gold);
  transform: rotate(45deg);
}

.night-market-dos-losange::after {
  content: "";
  position: absolute;
  inset: 24%;
  background: var(--gold);
  opacity: 0.35;
}

/* Gerbe de particules au retournement · de petits losanges (même motif),
   position: fixed ajoutés à <body> et retirés après coup, purement décoratif. */
.night-market-particules {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 300;
}

.night-market-particule {
  position: fixed;
  width: 7px;
  height: 7px;
  margin: -3.5px 0 0 -3.5px;
  background: var(--gold-bright);
  transform: rotate(45deg);
  animation: night-market-particule-vol 0.55s ease-out forwards;
}

@keyframes night-market-particule-vol {
  from {
    transform: translate(0, 0) rotate(45deg) scale(1);
    opacity: 1;
  }
  to {
    transform: translate(var(--dx), var(--dy)) rotate(45deg) scale(0.2);
    opacity: 0;
  }
}

/* Boutique (0.3) : pas de retournement ni de rareté, un article se lit tout
   de suite · carte simple, même famille que .carte-tuile côté bordure et
   padding, sans en reprendre la classe (pas de --rarete à porter ici). */
.boutique-tuile {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

/* Sélecteur renforcé : la règle générale .card h4 (color: teal, police UI) est
   plus spécifique qu'une classe seule et l'emporterait sinon · même piège que
   .carte-tuile .carte-titre plus haut dans ce fichier. */
.boutique-tuile .boutique-titre {
  font-family: var(--font-display);
  font-size: 1rem;
  color: var(--text);
}

.boutique-description {
  font-size: 0.85rem;
  color: var(--text-dim);
  line-height: 1.5;
  flex: 1;
}

.boutique-prix {
  font-weight: 600;
  color: var(--gold-bright);
}

.boutique-bouton {
  width: 100%;
}

.boutique-repetable {
  font-size: 0.75rem;
  color: var(--text-dim);
  margin: 0;
}

/* Article permanent déjà possédé : la tuile reste lisible mais s'efface un
   peu, plus de bouton "Acheter" à sa place. */
.boutique-tuile--possede {
  opacity: 0.65;
}

.boutique-statut {
  width: 100%;
  text-align: center;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-size: 0.85rem;
}

.boutique-boost-actif {
  font-size: 0.82rem;
  color: var(--gold-bright);
  margin: -4px 0 4px;
}

/* Le mot "CHANCE" dans le libellé des deux articles concernés · gras
   souligné au survol/focus, même bulle d'explication que .row-icon plus haut
   dans ce fichier, adaptée à un mot en ligne plutôt qu'à une icône. */
.mot-chance {
  position: relative;
  font-weight: 700;
  text-decoration: underline dotted;
  cursor: help;
}

.mot-chance[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: 130%;
  left: 50%;
  transform: translate(-50%, 4px);
  width: max-content;
  max-width: 260px;
  white-space: normal;
  background: var(--bg-panel);
  border: 1px solid var(--border-strong);
  color: var(--text);
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  font-size: 0.78rem;
  line-height: 1.45;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease, transform 0.12s ease;
  z-index: 20;
}

.mot-chance[data-tooltip]:hover::after,
.mot-chance[data-tooltip]:focus-visible::after {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* « Voir la collection de... » (03/09/2026) · même carcasse que .combo-picker. */
.voir-autre-panneau {
  margin-top: 14px;
  padding: 14px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.voir-autre-barre {
  display: flex;
  gap: 8px;
  align-items: center;
}

.voir-autre-recherche {
  flex: 1 1 auto;
  min-width: 0;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 9px 12px;
  font-size: 0.9rem;
  font-family: inherit;
}

.voir-autre-recherche:focus {
  outline: none;
  border-color: var(--teal);
}

.voir-autre-liste {
  margin-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 280px;
  overflow-y: auto;
}

.voir-autre-ligne {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text);
  font-family: inherit;
  font-size: 0.9rem;
  text-align: left;
  cursor: pointer;
}

.voir-autre-ligne:hover,
.voir-autre-ligne:focus-visible {
  background: var(--bg-hover);
  outline: none;
}

.voir-autre-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}

.voir-autre-avatar--vide {
  background: var(--bg-subtle);
  border: 1px solid var(--border);
}

/* Bandeau persistant tant qu'on consulte la collection d'un autre membre.
   position: sticky (pas fixed) : il réserve sa propre place dans le flux, pas
   besoin de compenser avec un padding ailleurs sur la page · même famille
   dorée que .modal-btn--primary (le bouton de connexion). */
.voir-autre-bandeau {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 10px 16px;
  background: var(--gold);
  color: #1a1305;
  font-size: 0.9rem;
  font-weight: 500;
  text-align: center;
}

.voir-autre-bandeau-avatar {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  object-fit: cover;
}

.voir-autre-bandeau #voir-autre-retour {
  border-color: rgba(26, 19, 5, 0.35);
  color: #1a1305;
}

.voir-autre-bandeau #voir-autre-retour:hover {
  background: rgba(26, 19, 5, 0.1);
}

/* ---------- Marché : graphique agrandi + barre de zoom (15/09/2026) ---------- */
/* Remplace les 4 filtres fixes 6h/12h/1j/7j, jugés illisibles : le graphique
   prend toute la hauteur disponible et se pilote au zoom/déplacement. */

.marche-graphique {
  position: relative;
  width: 100%;
  height: min(70vh, 620px);
  min-height: 360px;
  touch-action: none; /* le cliquer-glisser pilote le zoom, pas le scroll */
  cursor: grab;
}

.marche-graphique:active {
  cursor: grabbing;
}

.marche-zoom-barre {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}

.marche-zoom-barre label {
  flex: 0 0 auto;
  min-width: 68px;
  font-size: 0.85rem;
  color: var(--muted, #93a3b4);
}

.marche-zoom-barre input[type="range"] {
  flex: 1 1 auto;
  min-width: 0;
}

.marche-zoom-valeur {
  flex: 0 0 auto;
  min-width: 78px;
  text-align: right;
  font-size: 0.85rem;
  color: var(--muted, #93a3b4);
  font-variant-numeric: tabular-nums;
}

/* ---------- Bouton « Suggestion » flottant (15/09/2026) ---------- */
/* Remplace le sous-onglet « Suggestions & Report ». Présent sur Rosée et sur
   Cartes à collectionner. Se réduit à sa seule icône sur mobile pour ne pas
   manger l'écran. */

.suggestion-flottante {
  position: fixed;
  right: clamp(10px, 2.5vw, 26px);
  bottom: clamp(10px, 2.5vw, 26px);
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: clamp(8px, 1.4vw, 11px) clamp(12px, 1.8vw, 17px);
  border: 0;
  border-radius: 999px;
  background: #e8c547;
  color: #2a2205;
  font-family: inherit;
  font-size: clamp(0.76rem, 1.4vw, 0.88rem);
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.42);
  transition: transform 0.14s ease, box-shadow 0.14s ease, background 0.14s ease;
}

.suggestion-flottante:hover {
  background: #f0d365;
  transform: translateY(-1px);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5);
}

.suggestion-flottante:active {
  transform: translateY(0);
}

/* Mobile : plus que l'icône, dans une pastille ronde volontairement petite. */
@media (max-width: 768px) {
  .suggestion-flottante {
    width: 40px;
    height: 40px;
    padding: 0;
    justify-content: center;
    gap: 0;
    font-size: 1.05rem;
  }

  .suggestion-flottante-texte {
    display: none;
  }
}

.suggestion-modal-carte {
  position: relative;
}

.suggestion-modal-fermer {
  position: absolute;
  top: 10px;
  right: 14px;
  border: 0;
  background: transparent;
  color: var(--muted, #93a3b4);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 6px;
}

.suggestion-modal-fermer:hover {
  color: var(--txt, #dfe7ef);
  background: rgba(255, 255, 255, 0.06);
}

/* ---------- Administration : inventaire des cartes à effet (15/09/2026) ---------- */

.effets-table-conteneur {
  overflow-x: auto;
  margin-top: 16px;
}

.effets-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.86rem;
  min-width: 760px;
}

.effets-table th {
  text-align: left;
  padding: 9px 12px;
  border-bottom: 1px solid var(--bord, #2c3846);
  color: var(--muted, #93a3b4);
  font-size: 0.74rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

.effets-table td {
  padding: 11px 12px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  vertical-align: top;
}

.effets-table tr:hover td {
  background: rgba(255, 255, 255, 0.02);
}

.effet-nom {
  font-weight: 600;
  margin-bottom: 3px;
}

.effet-meta {
  color: var(--muted, #93a3b4);
  font-size: 0.79rem;
  line-height: 1.4;
}

.effet-code {
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: 0.76rem;
  background: rgba(255, 255, 255, 0.06);
  padding: 1px 6px;
  border-radius: 4px;
}

.effet-desc {
  color: var(--muted, #93a3b4);
  max-width: 320px;
}

.effet-tag {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 20px;
  font-size: 0.72rem;
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid var(--bord, #2c3846);
  color: var(--muted, #93a3b4);
  margin: 0 3px 3px 0;
}

.effet-tag--passif {
  border-color: #5da472;
  color: #7ec48f;
}

.effet-tag--utilisable {
  border-color: #56a0ad;
  color: #72bcc9;
}

/* ---------- Marché : liste à cocher des univers (15/09/2026) ---------- */
/* Remplace la légende Chart.js : chercher la bonne courbe à masquer dans une
   légende de quinze entrées était pénible. */

.marche-univers {
  border: 1px solid var(--bord, #2c3846);
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 12px;
}

.marche-univers-entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 8px;
  font-size: 0.8rem;
  color: var(--muted, #93a3b4);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.marche-univers-actions {
  display: flex;
  gap: 12px;
  text-transform: none;
  letter-spacing: 0;
}

.lien-bouton {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: #72bcc9;
  cursor: pointer;
  text-decoration: underline;
}

.lien-bouton:hover {
  color: #9ad4de;
}

.marche-univers-liste {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(165px, 1fr));
  gap: 4px 12px;
}

.marche-univers-item {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 0.84rem;
  cursor: pointer;
  padding: 2px 0;
  min-width: 0;
}

.marche-univers-item input {
  flex: 0 0 auto;
  cursor: pointer;
}

.marche-univers-pastille {
  flex: 0 0 auto;
  width: 11px;
  height: 11px;
  border-radius: 3px;
}

.marche-univers-nom {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Marché : marque les univers volontairement stables (peu de cartes). */
.marche-univers-calme {
  flex: 0 0 auto;
  font-size: 0.68rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #7ec48f;
  border: 1px solid #3f6b4e;
  border-radius: 20px;
  padding: 0 6px;
  line-height: 1.5;
}

/* ---------- Marché des univers : la page joueur (0.4) ---------- */

.marche-grille {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
  gap: 12px;
}

.marche-carte {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
}

.marche-carte-entete {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.marche-carte-nom {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.marche-carte-valeur {
  font-family: var(--font-mono);
  font-size: 1.45rem;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
}

.marche-carte-dev {
  font-size: 0.84rem;
  font-variant-numeric: tabular-nums;
}

/* La fenêtre d'une heure est la seconde ligne : plus petite que celle des
   24 h, qui reste la lecture principale d'un univers (16/09/2026). */
.marche-carte-dev--heure {
  font-size: 0.76rem;
  opacity: 0.85;
}

.marche-carte-etats:empty {
  display: none;
}

.marche-carte button {
  /* auto et non une valeur fixe : les cartes d'une même rangée sont déjà
     étirées à la même hauteur par la grille, mais leur contenu varie (crise,
     "déjà mise dessus"...). Sans ça, chaque bouton restait collé à son propre
     contenu, désaligné avec ses voisins. */
  margin-top: auto;
  width: 100%;
}

.marche-mise-nom {
  font-weight: 600;
}

.marche-etat {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 20px;
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-size: 0.72rem;
  font-weight: 600;
  white-space: nowrap;
  margin: 0 3px 3px 0;
}

.marche-etat--crise {
  border-color: #7a3f3f;
  color: var(--red);
}

.marche-etat--tendance {
  border-color: #3f6b4e;
  color: var(--green);
}

/* Le direct doit se repérer d'un coup d'oeil : pastille qui bat. */
.marche-bouton-live.modal-btn--danger::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  margin-right: 7px;
  vertical-align: middle;
  animation: marche-battement 1.4s ease-in-out infinite;
}

@keyframes marche-battement {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.25; }
}

@media (prefers-reduced-motion: reduce) {
  .marche-bouton-live.modal-btn--danger::before {
    animation: none;
  }
}

.marche-banniere-crise {
  border-color: #7a3f3f;
  color: var(--red);
}
