/*
 * Polices Chirp (charte docs/brand/charte-chirp.html, section 04). Pas de
 * `next/font` ici : Thymeleaf/CSS pur, sans etape de build - contrairement a
 * l'app web (globals.css), donc l'import de la charte tel quel plutot qu'un
 * auto-hebergement.
 */
@import url('https://fonts.googleapis.com/css2?family=Baloo+2:wght@700&family=Manrope:wght@400;500;600&display=swap');

/*
 * Palette Chirp — remplace « noir + rouge » (v précédente), constitution
 * Principe VI toujours en vigueur. Source : docs/brand/charte-chirp.html,
 * section 06 « Fiche résumé ».
 *
 * Source partagee : ces valeurs sont aussi definies dans le theme Tailwind de
 * l'app web (apps/sports-league-app/web/src/app/globals.css). Si une valeur
 * change ici, elle change la-bas.
 *
 * SOMBRE = DEFAUT (charte section 03, "marque nuit de patinoire").
 *
 * Deux rouges, pas un seul (charte section 03) :
 *   --accent         rouge vif, GROS TEXTE / GRAPHISME SEULEMENT - jamais du
 *                     texte courant.
 *   --accent-strong   rouge profond, tout ce qui porte un vrai texte lisible
 *                     (fond de bouton avec --accent-text dessus).
 * --ember n'est JAMAIS du texte (charte : "au trait seulement").
 *
 * --danger et --danger-text NE SONT PAS dans la charte (aucun jeton d'erreur
 * fourni) - choix ajoute ici, signale a l'auteur de la charte plutot
 * qu'invente en silence. Ambre distinct des deux rouges en teinte (~35 deg
 * contre ~350 deg) ET en luminance.
 *
 * REGLE : --border ne porte JAMAIS de texte. Bordures, separateurs, decor.
 *
 * Contrastes mesures (WCAG 2.2, seuil AA = 4.5:1 texte courant, 3:1 grand
 * texte et elements non textuels) :
 *
 *   SOMBRE (defaut)  text/ink            18.09:1   OK
 *                     text/surface        16.39:1   OK
 *                     text-muted/ink       7.47:1   OK
 *                     accent-text/accent-strong (bouton)  5.84:1  OK
 *                     accent-strong/ink (lien)             3.35:1  OK-3:1 seult
 *                     danger/ink                           8.18:1  OK
 *                     danger-text/danger (bouton)          8.18:1  OK
 *                     link/surface (lien)                  5.50:1  OK
 *                     ok/surface                          10.17:1  OK
 *
 *   CLAIR             text/ink            17.00:1   OK
 *                     text/surface        18.23:1   OK
 *                     text-muted/ink       5.35:1   OK
 *                     accent-text/accent-strong (bouton)  5.84:1  OK
 *                     accent-strong/ink (lien)             5.44:1  OK
 *                     danger/ink                           7.86:1  OK
 *                     danger-text/danger (bouton)         10.50:1  OK
 *                     link/surface (lien)                  5.44:1  OK
 *                     ok/surface                           5.02:1  OK
 *
 *   NON-TEXTE (seuil 3:1, SC 1.4.11) - mesure sur la surface reellement
 *   bordee, et non sur --ink. Cette section manquait : un tableau qui ne
 *   liste que des paires de TEXTE ne peut pas rattraper un champ sans bord,
 *   et c'est exactement par la que les defauts sont passes.
 *
 *   SOMBRE           border-control/surface (champ)       3.09:1  OK
 *                    border-control/surface-2 (champ rempli) 3.04:1  OK
 *                    focus/surface (anneau)               6.28:1  OK
 *                    ember/surface                        6.28:1  OK
 *   CLAIR            border-control/surface (champ)       3.24:1  OK
 *                    border-control/surface-2 (champ rempli) 3.14:1  OK
 *                    focus/surface (anneau)               4.24:1  OK
 *                    ember/surface                        4.24:1  OK
 *
 * A NOTER (ecart de la charte, pas invente) : --accent-strong comme texte
 * COURANT (pas un bouton) ne passe l'AA texte (4.5:1) qu'en mode clair
 * (5.44:1) - en sombre il tombe a 3.35:1. La charte ne donne qu'un seul ratio
 * (5,4:1) sans preciser qu'il ne vaut que pour le clair. Ici `a { color:
 * var(--accent); }` reste la variante FAIBLE (graphisme) par defaut - voir
 * plus bas.
 *
 * Reverifier ces valeurs avant de toucher a une couleur.
 */
:root {
  /* Sans ça, le navigateur peint ses propres commandes en clair sous ce thème
     sombre - et l'autofill repeint le formulaire de connexion en lavande chez
     tout utilisateur qui revient avec un mot de passe enregistré. */
  color-scheme: dark;

  --ink: #0b0c0f;
  --surface: #17181d;
  --surface-2: #1f2127;
  --text: #f5f6f8;
  --text-muted: #9ca0aa;
  --accent: #e01b3d;
  --accent-strong: #c81430;
  --accent-text: #ffffff;
  --ember: #ff6b47;
  --border: rgba(245, 246, 248, 0.1);
  /* Un champ ou un bouton a son propre seuil (3:1, SC 1.4.11) que le filet
     décoratif --border n'atteint pas : il mesurait 1,31:1, et les deux champs
     de /login n'avaient donc pas de bord visible. */
  --border-control: rgba(245, 246, 248, 0.35);
  --focus: #ff6b47;
  --danger: #e0993a;
  /* Était #ffffff : blanc sur cet ambre donne 2,39:1, et c'est le bouton
     « Supprimer mon compte » qui le portait. Encre sur ambre : 8,18:1. */
  --danger-text: #0b0c0f;
  --ok: #4ade80;
  /* --accent en lien donne 3,71:1 sur la carte, et --accent-strong 3,04:1 :
     les deux rouges de la charte échouent en sombre. Rouge éclairci, même
     famille, 5,50:1. */
  --link: #ff4d6a;

  /*
   * DEUX rayons, et ils disent deux choses différentes :
   *   --radius-card     une SURFACE qui porte du contenu (la carte)
   *   --radius-control  quelque chose qui se clique ou se remplit
   *
   * Le second existait déjà en fait, écrit « 8px » à la main sur les champs,
   * les boutons et les alertes - trois endroits qui pouvaient dériver sans
   * qu'aucun diff ne le montre. Même découpage et mêmes valeurs que le
   * `@theme` de globals.css côté app web : c'est le même produit.
   *
   * --radius reste, en alias : rien ne justifie de renommer une variable
   * utilisée par un seul sélecteur.
   */
  --radius-card: 10px;
  --radius-control: 8px;

  /*
   * Jumeaux des jetons de mouvement de globals.css, même règle que les
   * couleurs et les rayons : les VALEURS sont identiques des deux côtés.
   *
   * La courbe s'écrit en clair, jamais `ease-out`. Le mot-clé CSS nu vaut
   * cubic-bezier(0, 0, 0.58, 1) ; l'utilitaire `ease-out` de Tailwind, que
   * l'app web compile de son côté, vaut cubic-bezier(0, 0, 0.2, 1). Les deux
   * fichiers écrivaient bien « ease-out », et le même bouton rouge freinait
   * quand même différemment sur les deux moitiés du produit. C'est exactement
   * l'arrondi silencieux que controls.ts raconte avoir corrigé sur les
   * rembourrages, revenu par la propriété de durée.
   */
  --motion-fast: 120ms;
  --motion-entrance: 240ms;
  --motion-emphasis: 900ms;
  --motion-ease: cubic-bezier(0, 0, 0.2, 1);
  --motion-emphasis-ease: cubic-bezier(0.16, 1, 0.3, 1);
  --radius: var(--radius-card);
  --space: 1rem;
  --measure: 26rem;
}

@media (prefers-color-scheme: light) {
  :root {
    color-scheme: light;

    --ink: #f7f7f5;
    --surface: #ffffff;
    --surface-2: #efeeea;
    --text: #14151a;
    --text-muted: #63666f;
    --accent: #e01b3d;
    --accent-strong: #c81430;
    --accent-text: #ffffff;
    /* #ff6b47 tombe à 2,82:1 sur blanc - sous le seuil non textuel. */
    --ember: #d94a24;
    --border: rgba(20, 21, 26, 0.12);
    /* 0,48 : a 0,46 le bord tombait a 2,97:1 sur surface-2. Suit globals.css. */
    --border-control: rgba(20, 21, 26, 0.48);
    /* Valait #c81430, soit exactement --accent-strong : l'anneau de focus
       avait la couleur de la face du bouton qu'il entoure. Suit --ember dans
       les deux modes, pour que l'affordance s'apprenne. */
    --focus: #d94a24;
    /* Assombri : écart de luminance avec --accent-strong porte de 1,45:1 à
       1,80:1, ce que la note sur la daltonie en tête de fichier promet. */
    --danger: #5a3800;
    --danger-text: #ffffff;
    --ok: #15803d;
    --link: #c81430;
  }
}

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

body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 2rem 1rem;
  background: var(--ink);
  color: var(--text);
  font: 400 16px/1.55 'Manrope', ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
}

.card {
  width: 100%;
  max-width: var(--measure);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 2rem;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 1.5rem;
}

/* Meme hauteur que BrandMark.tsx cote app web (h-4). A 0,75rem les deux barres
   se confondent en une seule masse : la marque perd ce qu'elle dit. Le mot
   reste a 0,75rem -- c'est un reperage, pas un titre, et le h1 en dessous doit
   rester la premiere chose qu'on lit. */
.brand-mark {
  height: 1rem;
  width: auto;
  flex-shrink: 0;
}

h1 {
  font-family: 'Baloo 2', ui-sans-serif, sans-serif;
  font-size: 1.5rem;
  line-height: 1.2;
  margin: 0 0 0.5rem;
  letter-spacing: -0.02em;
}

.lede {
  margin: 0 0 1.75rem;
  color: var(--text-muted);
}

.field { margin-bottom: 1.25rem; }

label {
  display: block;
  font-size: 0.875rem;
  font-weight: 500;
  margin-bottom: 0.375rem;
}

input[type="email"],
input[type="password"],
input[type="text"] {
  width: 100%;
  padding: 0.7rem 0.85rem;
  font: inherit;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border-control);
  border-radius: var(--radius-control);
}

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

.hint {
  display: block;
  margin-top: 0.375rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

/*
 * Hierarchie de boutons. `button` seul etait `width: 100%` : sur /account les
 * deux formulaires se lisaient comme deux actions principales, et sur
 * /account/sessions chaque appareil recevait un bloc pleine largeur. Pire,
 * la suppression definitive du compte portait exactement le meme habit que
 * « Enregistrer le nom ».
 *
 * Trois niveaux, et la largeur devient explicite (.btn-block) au lieu d'etre
 * imposee a tout le monde.
 */
button,
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.7rem 1.1rem;
  font: inherit;
  font-weight: 600;
  color: var(--accent-text);
  background: var(--accent-strong);
  border: 1px solid transparent;
  border-radius: var(--radius-control);
  cursor: pointer;
  text-decoration: none;
  transition-property: color, background-color, border-color, opacity, filter;
  transition-duration: var(--motion-fast);
  transition-timing-function: var(--motion-ease);
}

/* Les pages d'authentification n'ont qu'une action : elle occupe la carte. */
.btn-block { width: 100%; }

/*
 * Champ de mot de passe avec bouton « afficher » : le bouton se pose dans le
 * champ, sans en prendre l'habit d'action principale. Caché sans script, il
 * n'apparaît que lorsque le basculement fonctionne.
 */
.password { position: relative; }
.password input[type="password"],
.password input[type="text"] { padding-right: 2.75rem; }
.reveal {
  position: absolute;
  top: 50%;
  right: 0.35rem;
  transform: translateY(-50%);
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  color: var(--text-muted);
  background: transparent;
  border-color: transparent;
  border-radius: var(--radius-control);
}
.reveal:hover { color: var(--text); background: transparent; filter: none; }
.reveal svg { width: 1.25rem; height: 1.25rem; }
/* `hidden` ne cache pas un SVG en ligne : la feuille UA ne vise que les éléments HTML. */
.reveal svg[hidden] { display: none; }

/* Action secondaire : presente, jamais concurrente de l'action principale. */
.btn-quiet {
  color: var(--text);
  background: transparent;
  border-color: var(--border-control);
  font-weight: 500;
}

.btn-quiet:hover { background: var(--surface-2); filter: none; }

/* Action destructrice. Contrastes mesures plus haut dans ce fichier. */
.btn-danger {
  color: var(--danger-text);
  background: var(--danger);
}

/* Le pas irreversible se declare avant de se remplir : bordure seule tant que
   la page n'est pas la confirmation elle-meme. */
.btn-danger-quiet {
  color: var(--danger);
  background: transparent;
  border-color: var(--danger);
  font-weight: 500;
}

.btn-danger-quiet:hover { background: transparent; filter: brightness(1.15); }

button:hover,
.btn:hover { filter: brightness(1.08); }

button:disabled,
.btn:disabled {
  cursor: not-allowed;
  opacity: 0.5;
  filter: none;
}

/* role="alert" sur ce conteneur : les erreurs sont annoncees, pas seulement
   colorees (FR-037 / SC-010). */
.alert {
  padding: 0.75rem 0.9rem;
  margin-bottom: 1.25rem;
  border-radius: var(--radius-control);
  border: 1px solid var(--border);
  font-size: 0.9375rem;
}

.alert-error {
  border-color: var(--danger);
  color: var(--danger);
}

/* Le succès ne se dit pas en rouge de marque : « Adresse confirmée » arrivait
   dans un cadre rouge, la couleur de l'échec partout ailleurs en logiciel. Le
   marqueur ::before porte l'état en FORME autant qu'en couleur - une bordure
   rouge/ambre de 1px était la seule différence entre succès et erreur, donc
   invisible en daltonie rouge-vert. */
.alert-ok {
  border-color: var(--ok);
  color: var(--ok);
}

.alert-ok::before {
  content: "\2713\00a0";
  font-weight: 700;
}

.alert-error::before {
  content: "\26a0\00a0";
  font-weight: 700;
}

/*
 * Connexion par un fournisseur externe. Aucun style propre : ce sont des actions
 * secondaires (.btn-quiet), séparées de l'action principale par le même filet que
 * les liens de bas de carte. Les marques des fournisseurs ne sont pas reproduites
 * — un logo Google exige de respecter sa charte, et un logo approximatif est pire
 * qu'un bouton sobre qui dit ce qu'il fait.
 */
.social {
  margin-top: 1.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--border);
  display: grid;
  gap: 0.625rem;
}

/* Les deux régions se suivent : un seul filet entre elles, pas deux. */
.social + .links { border-top: 0; padding-top: 0; margin-top: 1.25rem; }

.links {
  margin-top: 1.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--border);
  font-size: 0.9375rem;
  display: flex;
  justify-content: space-between;
  gap: 1rem;
}

/* Jeton dédié, ni --accent (3,71:1 en sombre) ni --accent-strong (3,04:1) :
   les deux rouges de la charte échouent comme texte de lien sur la carte. Le
   souligné évite en plus que le lien ne tienne qu'à la teinte. */
a { color: var(--link); text-decoration: underline; }

/*
 * RÉDUIRE le mouvement, pas tout retirer — même argument, mot pour mot, que
 * globals.css. Ce bloc était un `transition: none` général, c'est-à-dire tout
 * le contraire : il supprimait le fondu de 120 ms par lequel un bouton accuse
 * le survol et l'appui, le seul retour visuel qu'un contrôle a répondu. La
 * même personne, avec le même réglage, avait donc un bouton vivant dans l'app
 * et un bouton mort sur la page de connexion. Un seul produit.
 *
 * Couleur, opacité et filtre restent ; déplacement et animation sont coupés —
 * ce qui neutralise bien le `settle` de .alert, qui monte de 0,25 rem, et
 * c'est ce que son commentaire annonce plus bas.
 */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-property: color, background-color, border-color, opacity, filter !important;
  }
}

/* ==========================================================================
   Espace compte — /account, /account/sessions, /account/delete
   --------------------------------------------------------------------------
   La carte de 26rem appartient aux inconnus : sur /login on n'a pas encore
   d'identite, et il n'y a rien a naviguer. /account en heritait par accident,
   ce qui coutait au visiteur son chemin de retour — la barre de l'app web
   pointe ici, et cette page ne pointait nulle part.

   L'espace connecte a donc sa propre coquille : une barre reprenant le
   vocabulaire de NavBar.tsx (meme marque a gauche, meme deconnexion a droite),
   puis des sections separees par des filets. Pas de cartes empilees : la carte
   est deja la grammaire des pages d'authentification, la reprendre ici
   brouillerait les deux.
   ========================================================================== */

body.app {
  display: block;
  place-items: initial;
  padding: 0;
  background: var(--surface);
}

.wrap {
  width: 100%;
  max-width: 52rem;
  margin-inline: auto;
  padding-inline: 1.25rem;
}

@media (min-width: 40rem) {
  .wrap { padding-inline: 2rem; }
}

/* --- Barre --------------------------------------------------------------- */

.appbar {
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}

.appbar .wrap {
  display: flex;
  align-items: center;
  gap: 1rem;
  min-height: 3.5rem;
}

/* Le retour vers l'app ligue. C'est aussi la marque : deux roles, un seul
   element, parce qu'un visiteur qui cherche la sortie cherche le logo. */
.appbar-home {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text);
  text-decoration: none;
  margin-right: auto;
}

.appbar-home {
  transition-property: color, background-color, border-color, opacity, filter;
  transition-duration: var(--motion-fast);
  transition-timing-function: var(--motion-ease);
}

.appbar-home:hover { color: var(--accent-strong); }

.appbar form { display: flex; }

.icon {
  width: 1rem;
  height: 1rem;
  flex-shrink: 0;
}

/* --- En-tete de page ----------------------------------------------------- */

.page { padding-block: 2.5rem 4rem; }

.page h1 {
  font-size: 1.75rem;
  margin: 0 0 0.75rem;
}

/* Qui tu es, en une ligne : adresse, etat de confirmation, anciennete. */
.identity {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
  margin: 0 0 2.5rem;
  color: var(--text-muted);
  font-size: 0.9375rem;
}

.identity-sep {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--border);
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.125rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.8125rem;
}

.badge-ok { border-color: var(--accent-strong); color: var(--text); }
.badge-todo { border-color: var(--danger); color: var(--danger); }

/* --- Sections ------------------------------------------------------------ */

.row {
  display: grid;
  gap: 0.75rem 3rem;
  padding-block: 2rem;
  border-top: 1px solid var(--border);
}

@media (min-width: 44rem) {
  .row {
    grid-template-columns: 13rem minmax(0, 1fr);
    padding-block: 2.5rem;
  }
}

.row h2 {
  font-size: 1rem;
  font-weight: 600;
  margin: 0 0 0.375rem;
  letter-spacing: -0.01em;
}

.row-note {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.875rem;
  max-width: 32ch;
}

/* Les champs restent lisibles meme quand la colonne est large : un mot de
   passe ne se saisit pas dans un champ de 40rem. */
.control { max-width: var(--measure); }

.control .field:last-of-type { margin-bottom: 1rem; }

/* --- Liste des sessions -------------------------------------------------- */

.things { list-style: none; margin: 0; padding: 0; }

.thing {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  padding-block: 1rem;
  border-top: 1px solid var(--border);
}

.thing:first-child { border-top: 0; }

.thing-main { margin-right: auto; }

.thing-main strong { display: block; font-weight: 600; }

.thing .hint { margin-top: 0.125rem; }

/* --- Consequences (suppression) ------------------------------------------ */

.consequences {
  margin: 0 0 1.25rem;
  padding: 0;
  list-style: none;
  max-width: 60ch;
}

.consequences li {
  padding-left: 1.25rem;
  margin-bottom: 0.5rem;
  position: relative;
}

.consequences li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 0.4rem;
  height: 1px;
  background: var(--text-muted);
}

/* Rangee d'actions : l'irreversible d'abord, la sortie a cote. */
.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  margin-top: 2rem;
}

/*
 * « C'est irreversible » etait rendu dans le gris des notes secondaires : la
 * phrase qui porte toute la page en etait la plus discrete. Elle reprend le
 * corps de texte et son poids.
 */
.warning {
  margin: 0;
  font-weight: 600;
  max-width: 60ch;
}

/* --- Zone destructrice --------------------------------------------------- */

/* Separee par du vide, pas par une couleur d'alarme : la page ne crie pas,
   elle ecarte. La couleur arrive sur la page de confirmation, ou elle porte
   une decision reelle. */
.row-danger { margin-top: 1.5rem; }

.row-danger h2 { color: var(--danger); }

/* --- Retours ------------------------------------------------------------- */

/* Le seul moment anime de la page : la confirmation qui apparait apres un
   enregistrement. Neutralise par la garde prefers-reduced-motion plus haut. */
.alert { animation: settle var(--motion-entrance) var(--motion-emphasis-ease); }

@keyframes settle {
  from { opacity: 0; transform: translateY(-0.25rem); }
}

.control .alert:last-child { margin-bottom: 0; }
