/* ==============================================================================================
 * toast.css — la notification transitoire, en un seul exemplaire
 * ==============================================================================================
 *
 * Cinq écrans affichaient la même chose de cinq façons : un bandeau qui apparaît quelques
 * secondes puis s'efface. Ils ne s'accordaient sur rien —
 *
 *   - trois ancrages : bas-droite à 106 px du bord (`.as-toast`, espace d'exécution), haut-droite
 *     à 86 px (`.studio-toast`), et le coin par défaut de Bootstrap (promptcraft, réglages,
 *     journaux) ;
 *   - deux matières : la carte blanche translucide du Prompt Studio et le bandeau sombre de
 *     l'espace d'exécution ;
 *   - cinq durées, dont aucune n'était choisie en fonction de ce qu'elle portait : 2 200 ms pour
 *     les réglages (donc pour un échec de génération de jeton), 5 000 ms pour une confirmation de
 *     copie dans les journaux — soit exactement l'inverse de ce qu'il faut ;
 *   - et deux règles concurrentes sur `.toast-icon`, un nom sans préfixe, déclarées dans
 *     `promptcraft.css` (34 px, fond sombre) et `settings.css` (28 px, fond vert).
 *
 * Le visuel retenu est celui du Prompt Studio, aux valeurs près : les 37 notifications de cet
 * écran ne changent donc pas d'apparence en changeant d'implémentation.
 *
 * ----------------------------------------------------------------------------------------------
 * Pourquoi `.app-toast` et pas `.toast`
 * ----------------------------------------------------------------------------------------------
 *
 * Bootstrap déclare `.toast:not(.show) { display: none }`. Une carte d'auteur nommée `.toast`
 * serait invisible tant que `.show` n'est pas posée par le JavaScript de Bootstrap — que ce
 * composant n'utilise pas. C'est ce piège qui a fait nommer `.as-toast` puis `.studio-toast` ;
 * il est documenté en tête de `static/css/agent-space.css`. Le nom est verrouillé par
 * `tests/test_toast_component.py`.
 *
 * ----------------------------------------------------------------------------------------------
 * Ce qu'une page a le droit de changer
 * ----------------------------------------------------------------------------------------------
 *
 * Trois variables, et trois seulement. Le reste — forme, matière, animation — est commun, sans
 * quoi le composant redeviendrait cinq composants.
 *
 *   --toast-inset          ancrage sur grand écran ; défaut haut-droite
 *   --toast-inset-mobile   ancrage sous 576 px ; défaut bas, pleine largeur
 *   --toast-surface        fond de la carte, pour un écran sombre (avec --toast-text)
 *
 * L'espace d'exécution s'en sert pour garder son coin bas-droite (`static/css/agent-space.css`) :
 *
 *   .agent-space { --toast-inset: auto 106px 26px auto; }
 *
 * L'animation d'entrée glisse depuis le bord droit, jamais depuis le haut : elle est donc juste
 * depuis les deux ancrages, sans variante à maintenir.
 *
 * Le rayon de 16 px est écrit en clair : `--radius-md` vaut 18 px, et prendre le jeton le plus
 * proche changerait la maquette validée. `tokens.css` pose d'ailleurs qu'un rayon écrit dans une
 * règle n'entre pas dans l'échelle sans décision de charte.
 *
 * Chargé par `templates/base.html`, donc présent sur toutes les pages.
 * ============================================================================================== */

#app-toasts {
  position: fixed;
  inset: var(--toast-inset, 86px 22px auto auto);
  z-index: var(--toast-z, 2700);
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  width: min(360px, calc(100vw - 40px));
  /* La pile couvre un coin de l'écran en permanence : sans cela, elle intercepterait les clics
     destinés à ce qui se trouve dessous, y compris quand elle est vide. Les cartes, elles,
     réactivent le pointeur pour leurs boutons. */
  pointer-events: none;
}

/* 2700 est choisi, pas repris de Bootstrap : la carte doit passer devant le panneau ARIA
   (`aria.css`, 2600), les surfaces de confirmation (`prompt-studio.css` et `release-popup.css`,
   2000) et les modales (1055), tout en restant sous l'infobulle flottante de l'espace d'agent
   (`agent-space.css`, 10000), qui doit rester au-dessus de tout. */

@media (max-width: 575px) {
  /* `inset` est écrit ici directement, et non via la variable de grand écran : sans cela,
     l'ancrage desktop d'une page (`.agent-space`) l'emporterait sur la valeur mobile, sa feuille
     étant chargée après celle-ci. Une page qui a besoin d'un autre dégagement en bas — une barre
     d'action mobile, par exemple — pose `--toast-inset-mobile`. */
  #app-toasts {
    inset: var(--toast-inset-mobile, auto 18px 18px 18px);
    width: auto;
  }
}

/* ----------------------------------------------------------------------------------------------
 * La carte
 * -------------------------------------------------------------------------------------------- */

.app-toast {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  padding: 0.85rem 0.9rem 0.95rem;
  border-radius: 16px;
  background: var(--toast-surface, rgba(255, 255, 255, 0.96));
  border: 1px solid var(--toast-border, rgba(74, 108, 247, 0.12));
  box-shadow: 0 18px 40px rgba(30, 40, 80, 0.18);
  backdrop-filter: blur(12px);
  overflow: hidden;
  pointer-events: auto;
  transform: translateX(120%);
  opacity: 0;
  animation: app-toast-in .35s var(--ease-out) forwards;
}

.app-toast.is-leaving {
  animation: app-toast-out .3s ease forwards;
}

@keyframes app-toast-in {
  to { transform: translateX(0); opacity: 1; }
}

@keyframes app-toast-out {
  to { transform: translateX(120%); opacity: 0; }
}

.app-toast__icon {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  font-size: 0.95rem;
  color: var(--toast-tone);
  background: var(--toast-tone-bg);
}

.app-toast__body {
  flex: 1;
  min-width: 0;
  padding-top: 4px;
}

/* Le titre n'existe que quand l'appelant en fournit un : seul promptcraft affiche deux niveaux
   de texte (« Formulaire incomplet » puis le détail de ce qui manque). */
.app-toast__title {
  margin: 0 0 2px;
  color: var(--toast-text, var(--color-ink));
  font-size: 0.86rem;
  font-weight: 600;
  line-height: 1.3;
}

.app-toast__message {
  margin: 0;
  color: var(--toast-text, var(--color-ink));
  font-size: 0.86rem;
  line-height: 1.45;
  overflow-wrap: anywhere;
}

/* Bouton d'action : « Voir » à côté d'un résultat qui vient d'arriver. Facultatif, et teinté du
   ton de la carte plutôt que de la couleur de marque — un bouton bleu sur une carte d'erreur
   lirait comme une action sans rapport. */
.app-toast__action {
  flex: 0 0 auto;
  align-self: center;
  padding: 5px 11px;
  border: 0;
  border-radius: 9px;
  color: var(--toast-tone);
  background: var(--toast-tone-bg);
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
}

.app-toast__action:hover {
  filter: brightness(0.96);
}

.app-toast__close {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 8px;
  color: var(--toast-close, var(--color-ink-soft));
  background: transparent;
  cursor: pointer;
}

.app-toast__close:hover {
  background: rgba(20, 27, 56, 0.06);
}

/* Le compte à rebours visible. Sa durée suit celle de la carte, posée par
   `static/js/core/toast.js` sur `--toast-duration` : une barre qui finit avant ou après la
   disparition ferait mentir le seul indice de temps que porte le composant. */
.app-toast__progress {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 3px;
  width: 100%;
  transform-origin: left center;
  background: var(--toast-tone-bar);
  animation: app-toast-progress var(--toast-duration, 3200ms) linear forwards;
}

@keyframes app-toast-progress {
  from { transform: scaleX(1); }
  to { transform: scaleX(0); }
}

/* ----------------------------------------------------------------------------------------------
 * Les tons
 *
 * Un ton ne pose que trois variables ; toutes les règles ci-dessus les lisent. Les verts et les
 * rouges sont écrits en clair, comme le pose `tokens.css` : le dépôt en compte trois et quatre
 * nuances, délibérément non fusionnées, et ce sont celles de la carte du Prompt Studio qui font
 * foi ici puisque c'est sa maquette qui est reprise.
 * -------------------------------------------------------------------------------------------- */

.app-toast--success {
  --toast-tone: #15965a;
  --toast-tone-bg: rgba(34, 197, 94, 0.14);
  --toast-tone-bar: linear-gradient(90deg, #23c36e, #6de67b);
}

.app-toast--danger {
  --toast-tone: #d43a4c;
  --toast-tone-bg: rgba(212, 58, 76, 0.14);
  --toast-tone-bar: linear-gradient(90deg, #e2566a, #f08a9a);
}

/* Le Prompt Studio n'avait pas d'avertissement : ce ton est composé à partir du jeton
   `--color-warning` (#f59e0b), assombri pour rester lisible sur fond blanc. */
.app-toast--warning {
  --toast-tone: #b45309;
  --toast-tone-bg: rgba(245, 158, 11, 0.16);
  --toast-tone-bar: linear-gradient(90deg, var(--color-warning), #fbd38d);
}

.app-toast--info {
  --toast-tone: var(--color-primary);
  --toast-tone-bg: rgba(74, 108, 247, 0.14);
  --toast-tone-bar: linear-gradient(90deg, var(--color-primary), var(--color-accent));
}

/* ----------------------------------------------------------------------------------------------
 * Mouvement réduit
 *
 * Les trois animations sont désactivées ensemble, et l'état final est écrit explicitement : une
 * carte dont l'animation d'entrée est coupée resterait sinon à `translateX(120%)` et `opacity: 0`,
 * c'est-à-dire invisible. La minuterie de `core/toast.js` continue de courir — c'est elle qui fait
 * disparaître la carte, pas l'animation.
 * -------------------------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .app-toast,
  .app-toast.is-leaving {
    animation: none;
    transform: none;
    opacity: 1;
  }

  .app-toast__progress {
    animation: none;
  }
}
