/* ------------------------------------------------------------- composants
   Le dessin de l'app. Rien ici ne porte de couleur brute : tout passe par les
   jetons, sinon le theme sombre se corrige a dix-huit endroits.

   L'ecran d'accueil a un seul objet principal, le solde, et tout le reste lui
   cede la place. C'est le chiffre qu'on vient chercher, et il doit se lire a
   bout de bras sans lunettes.                                                */

/* Le fond de toute l'app, y compris sous le contenu : le corps herite du blanc
   de base.css, qui ne convient qu'a la page de connexion, laquelle peint le
   sien. */
body { background: var(--fond-2); }

/* ------------------------------------------------------------------ page */

/* 100dvh et non 100 % : sous la barre du bas, quelques dizaines de pixels de
   blanc apparaissaient entre la fin du contenu et les onglets, parce que
   « 100 % » se mesure sur un corps dont la hauteur depend de son propre
   contenu. Le fond du corps est peint aussi, en ceinture. */
.page {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--fond-2);
}

.entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e-3);
  padding: var(--e-5) var(--marge-page) var(--e-3);
  background: var(--fond-2);
}

.entete h1 {
  font: var(--t-grand-titre);
  letter-spacing: -.01em;
}

.entete .qui {
  font: var(--t-secondaire);
  color: var(--texte-2);
}

.contenu {
  flex: 1;
  width: 100%;
  max-width: var(--largeur-contenu);
  margin: 0 auto;
  padding: 0 var(--marge-page) var(--e-8);
  display: flex;
  flex-direction: column;
  gap: var(--e-4);
}

/* La barre du bas mange la derniere carte sans cette reserve, et sur iPhone le
   trait d'accueil mange encore la barre. */
.avec-onglets { padding-bottom: calc(var(--hauteur-onglets) + var(--e-8) + env(safe-area-inset-bottom)); }

/* ---------------------------------------------------------------- onglets */

.onglets {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 20;
  display: flex;
  background: var(--surface);
  border-top: 1px solid var(--trait);
  padding-bottom: env(safe-area-inset-bottom);
}

.onglet {
  flex: 1;
  min-height: var(--hauteur-onglets);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  color: var(--texte-3);
  font: var(--t-legende);
  transition: color var(--d-1) var(--courbe);
}

.onglet svg { width: 24px; height: 24px; }
.onglet[aria-current="page"] { color: var(--accent-texte); }

/* ------------------------------------------------------------------ solde */

.solde {
  background: var(--surface);
  border-radius: var(--r-3);
  box-shadow: var(--ombre-1);
  padding: var(--e-6) var(--e-5) var(--e-5);
  text-align: center;
}

.solde-chiffre {
  font: var(--t-chiffre);
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}

.solde-chiffre.negatif { color: var(--danger); }

.solde-unite {
  font: var(--t-corps);
  color: var(--texte-2);
  margin-top: var(--e-1);
}

.solde-avenir {
  margin-top: var(--e-3);
  font: var(--t-mono);
  letter-spacing: var(--interlettre-legende);
  text-transform: uppercase;
  color: var(--texte-2);
}

.solde-note {
  margin-top: var(--e-2);
  font: var(--t-secondaire);
  color: var(--danger);
}

/* Les quatre lignes du compte. Une grille a deux colonnes et non un tableau :
   les valeurs s'alignent a droite quel que soit le libelle. */
.compteurs {
  margin-top: var(--e-5);
  padding-top: var(--e-4);
  border-top: 1px solid var(--trait);
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--e-2) var(--e-4);
  text-align: left;
}

.compteur-cle {
  font: var(--t-mono);
  letter-spacing: var(--interlettre-legende);
  text-transform: uppercase;
  color: var(--texte-2);
  align-self: center;
}

.compteur-valeur {
  font: var(--t-mono);
  font-size: 15px;
  color: var(--texte);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Variantes de la grille de compteurs et des lignes, pour que rien n'ait
   besoin d'un style ecrit dans le JavaScript : un style en ligne echappe au
   theme sombre, et ne se voit qu'a la nuit tombee. */
.compteurs.nue { margin-top: 0; padding-top: 0; border-top: 0; }
.ligne.seule { border-top: 0; padding-top: 0; }
.note-apres { margin-top: var(--e-3); }
.centre { text-align: center; }

/* ----------------------------------------------------------------- boutons */

.bouton {
  min-height: var(--touche);
  padding: var(--e-3) var(--e-5);
  border-radius: var(--r-rond);
  font: var(--t-corps-fort);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--e-2);
  transition: transform var(--d-1) var(--courbe), background var(--d-1) var(--courbe);
}

.bouton:active { transform: scale(.98); }
.bouton[disabled] { opacity: .45; pointer-events: none; }
.bouton.pleine { width: 100%; }

.bouton.principal { background: var(--accent); color: var(--sur-accent); }
.bouton.fort      { background: var(--fort);   color: var(--sur-fort); }
.bouton.secondaire{ background: var(--surface-2); color: var(--texte); }
.bouton.discret   { background: none; color: var(--accent-texte); padding: var(--e-2) var(--e-3); }

/* Un bouton discret reste une cible : mesure faite en 390 px, « Annuler ma
   demande » tombait a 38 px de haut et la croix de fermeture a 40 par 40. Les
   deux se touchent au pouce, dans une liste et dans un coin d'ecran, c'est-a-
   dire aux deux endroits ou l'on rate le plus souvent. */
.feuille-entete .bouton.discret { min-width: var(--touche); padding: var(--e-2); }
.bouton.danger    { background: var(--danger-doux); color: var(--danger); }

/* Le vert de l'accord. Le texte pose dessus vient d'un jeton et non d'un blanc
   ecrit en dur : en theme sombre le vert s'eclaircit, et du blanc dessus ne se
   lirait plus. */
.bouton.accord    { background: var(--ok); color: var(--sur-ok); }

/* ------------------------------------------------------------------ cartes */

.carte {
  background: var(--surface);
  border-radius: var(--r-3);
  box-shadow: var(--ombre-1);
  padding: var(--e-4) var(--e-5);
}

.carte-titre {
  font: var(--t-legende);
  letter-spacing: var(--interlettre-legende);
  text-transform: uppercase;
  color: var(--texte-2);
  margin-bottom: var(--e-3);
}

.carte + .carte { margin-top: 0; }

/* ------------------------------------------------------------------ listes */

.liste { display: flex; flex-direction: column; }

.ligne {
  display: flex;
  /* Aligne en haut, et non sur la ligne de base : dans une carte d'historique
     le titre passe a trois lignes et la pastille, etiree sur toute la hauteur,
     devenait une tache orange de la moitie de la carte. Mesure faite en 390 px. */
  align-items: flex-start;
  gap: var(--e-3);
  padding: var(--e-3) 0;
  border-top: 1px solid var(--trait);
}

.liste .ligne:first-child { border-top: 0; padding-top: 0; }

.ligne-date {
  font: var(--t-mono);
  font-size: 13px;
  color: var(--texte-2);
  white-space: nowrap;
  min-width: 92px;
}

.ligne-nom {
  flex: 1;
  min-width: 0;               /* sans lui, un nom long pousse la pastille dehors */
  font: var(--t-corps);
  display: flex;
  flex-direction: column;
  gap: 2px;
  /* « break-word » et non « anywhere » : le second casse un mot au caractere
     des que la place manque, et sur une ligne de ferie serree « Aid al-Adha »
     descendait en colonne d'une lettre par ligne. Celui-ci ne coupe que ce qui
     ne peut pas tenir autrement. */
  overflow-wrap: break-word;
}
.ligne-note { font: var(--t-secondaire); color: var(--texte-2); }

/* --------------------------------------------------------------- pastilles */

.pastille {
  display: inline-block;
  flex: none;
  align-self: flex-start;
  padding: 3px var(--e-2);
  border-radius: var(--r-rond);
  font: var(--t-legende);
  letter-spacing: var(--interlettre-legende);
  text-transform: uppercase;
  white-space: nowrap;
}

.pastille.attente  { background: var(--alerte-doux); color: var(--alerte); }
.pastille.acceptee { background: var(--ok-doux);     color: var(--ok); }
.pastille.refusee  { background: var(--danger-doux); color: var(--danger); }
.pastille.annulee  { background: var(--surface-2);   color: var(--texte-2); }
.pastille.correction { background: var(--accent-doux); color: var(--accent-texte); }
.pastille.estimee  { background: var(--surface-2);   color: var(--texte-2); }

/* ------------------------------------------------------------------ champs */

.champ { display: flex; flex-direction: column; gap: var(--e-2); }

.champ > label {
  font: var(--t-legende);
  letter-spacing: var(--interlettre-legende);
  text-transform: uppercase;
  color: var(--texte-2);
}

.champ input,
.champ textarea {
  width: 100%;
  min-height: var(--touche);
  padding: var(--e-3) var(--e-4);
  background: var(--surface);
  border: 1px solid var(--trait-fort);
  border-radius: var(--r-2);
  font: var(--t-corps);
  /* 16 px minimum sur iOS, sinon Safari zoome a la mise au point et l'ecran
     part de travers, sans revenir. --t-corps vaut 17 px : c'est deliberé. */
}

.champ textarea { min-height: 88px; resize: vertical; }
.champ input:focus-visible,
.champ textarea:focus-visible { border-color: var(--accent); }
.champ .aide { font: var(--t-secondaire); color: var(--texte-2); }
.champ .erreur { font: var(--t-secondaire); color: var(--danger); }

/* Deux dates cote a cote sur un ecran, l'une sous l'autre sur un telephone
   etroit : un champ de date natif ne descend pas sous 150 px sans se tronquer. */
.deux-champs { display: grid; grid-template-columns: 1fr; gap: var(--e-4); }
@media (min-width: 420px) { .deux-champs { grid-template-columns: 1fr 1fr; } }

/* --------------------------------------------------------------- segments */

.segments {
  display: flex;
  gap: 4px;
  padding: 4px;
  background: var(--surface-2);
  border-radius: var(--r-rond);
}

.segments button {
  flex: 1;
  /* 44 px et non 36 : le plancher tapable de toute l'app. Ces boutons n'ont
     longtemps servi qu'a choisir la matinee ou l'apres-midi, dans une feuille
     ou la suite ne les mesurait pas ; les onglets « A traiter » et « Toutes »
     les ont amenes en pleine page, et la mesure est tombee tout de suite. */
  min-height: var(--touche);
  border-radius: var(--r-rond);
  font: var(--t-secondaire);
  color: var(--texte-2);
}

.segments button[aria-pressed="true"] {
  background: var(--surface);
  color: var(--texte);
  font-weight: 600;
  box-shadow: var(--ombre-1);
}

/* ------------------------------------------------------------ interrupteur */

.bascule {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e-4);
  min-height: var(--touche);
  cursor: pointer;
}

.bascule .piste {
  flex: none;
  width: 52px; height: 32px;
  border-radius: var(--r-rond);
  background: var(--surface-3);
  position: relative;
  transition: background var(--d-2) var(--courbe);
}

.bascule .pastille-piste {
  position: absolute; top: 3px; left: 3px;
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: var(--ombre-1);
  transition: transform var(--d-2) var(--courbe);
}

.bascule input { position: absolute; opacity: 0; width: 0; height: 0; }
.bascule input:checked + .piste { background: var(--accent); }
.bascule input:checked + .piste .pastille-piste { transform: translateX(20px); }
.bascule input:focus-visible + .piste { outline: 3px solid var(--accent); outline-offset: 2px; }

/* ------------------------------------------------------------------ apercu */

.apercu {
  border-radius: var(--r-2);
  padding: var(--e-4);
  background: var(--surface-2);
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
}

.apercu .compte { font: var(--t-titre); }
.apercu .detail { font: var(--t-secondaire); color: var(--texte-2); }
.apercu.attention { background: var(--alerte-doux); }
.apercu.attention .avertissement { color: var(--alerte); font: var(--t-corps-fort); }
.apercu.refus { background: var(--danger-doux); }
.apercu.refus .avertissement { color: var(--danger); font: var(--t-corps-fort); }

/* ----------------------------------------------------------------- feuille */

.voile {
  position: fixed; inset: 0; z-index: 30;
  background: var(--voile);
  animation: paraitre var(--d-2) var(--courbe);
}

.feuille {
  position: fixed; inset: auto 0 0 0; z-index: 31;
  max-height: 92vh;
  display: flex; flex-direction: column;
  background: var(--fond-2);
  border-radius: var(--r-4) var(--r-4) 0 0;
  box-shadow: var(--ombre-3);
  animation: monter var(--d-3) var(--courbe);
}

@media (min-width: 700px) {
  .feuille {
    inset: 50% auto auto 50%;
    transform: translate(-50%, -50%);
    width: min(560px, 92vw);
    border-radius: var(--r-4);
    animation: paraitre var(--d-2) var(--courbe);
  }
}

.feuille-entete {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--e-3);
  padding: var(--e-4) var(--e-5);
  border-bottom: 1px solid var(--trait);
}

.feuille-entete h2 { font: var(--t-titre); }

.feuille-corps {
  flex: 1;
  overflow-y: auto;
  padding: var(--e-5);
  display: flex; flex-direction: column; gap: var(--e-5);
}

.feuille-pied {
  padding: var(--e-4) var(--e-5) calc(var(--e-5) + env(safe-area-inset-bottom));
  border-top: 1px solid var(--trait);
}

@keyframes monter { from { transform: translateY(100%); } to { transform: none; } }
@keyframes paraitre { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .feuille, .voile { animation: none; }
}

/* -------------------------------------------------------------- connexion */

.connexion {
  min-height: 100dvh;
  display: flex; flex-direction: column; justify-content: center;
  gap: var(--e-6);
  padding: var(--e-8) var(--marge-page) calc(var(--e-10) + env(safe-area-inset-bottom));
  background: var(--noir);
  color: var(--sur-noir);
}

.connexion .marque { font: var(--t-grand-titre); font-family: var(--police-marque); }
.connexion .marque .point { color: var(--accent); }
.connexion .phrase { font: var(--t-corps); color: var(--sur-noir-2); }
.connexion .champ > label { color: var(--sur-noir-2); }

.connexion .champ input {
  background: rgba(255, 255, 255, .08);
  border-color: rgba(255, 255, 255, .16);
  color: var(--sur-noir);
}

.connexion .aide-bas { font: var(--t-secondaire); color: var(--sur-noir-2); text-align: center; }
.connexion .erreur { color: var(--danger); font: var(--t-corps); }

/* --------------------------------------------------------------- messages */

.vide {
  text-align: center;
  padding: var(--e-10) var(--e-5);
  color: var(--texte-2);
  display: flex; flex-direction: column; gap: var(--e-2);
}

.vide .titre { font: var(--t-sous-titre); color: var(--texte); }

.bandeau {
  border-radius: var(--r-2);
  padding: var(--e-4);
  font: var(--t-secondaire);
}

.bandeau.info { background: var(--accent-doux); color: var(--accent-texte); }
.bandeau.alerte { background: var(--alerte-doux); color: var(--alerte); }

/* Le message d'attente s'est longtemps appele « attente », et la pastille d'une
   demande en attente aussi. Les quarante pixels de marge de celui-ci
   s'appliquaient donc a celle-la, qui devenait une tache orange de la moitie
   d'une carte. Rien dans le JavaScript ne le laissait voir, et la suite ne le
   voyait pas non plus : c'est la capture qui l'a montre. D'ou le nom distinct,
   et le verrou qui mesure desormais la hauteur d'une pastille. */
.chargement { padding: var(--e-10); text-align: center; color: var(--texte-3); }

/* ------------------------------------------------------------------ bureau
   Un seul point de bascule dans toute l'app, a 900 px : au-dela on est devant
   un ecran, la barre du bas devient une rangee en haut et le contenu se
   centre. Rien d'autre ne change de forme.                                   */

@media (min-width: 900px) {
  /* La barre passe en haut, sous le titre. L'ordre est pose ici et non dans le
     document : sur telephone le meme balisage doit garder la barre en bas,
     collee au pouce, et c'est le seul endroit ou la difference se lit. */
  .entete { order: -2; }
  .onglets { order: -1; }

  /* Le titre se cale sur la meme colonne que les cartes : plein bord, il
     flottait a gauche pendant que tout le reste etait centre. */
  .entete { width: 100%; max-width: var(--largeur-contenu); margin: 0 auto; padding-inline: var(--marge-page); }

  .onglets {
    position: static;
    border-top: 0;
    border-bottom: 1px solid var(--trait);
    background: var(--fond-2);
    max-width: var(--largeur-contenu);
    margin: 0 auto;
    padding: 0 var(--marge-page);
    gap: var(--e-2);
  }

  .onglet {
    flex: none;
    flex-direction: row;
    gap: var(--e-2);
    min-height: 48px;
    padding: 0 var(--e-4);
    font: var(--t-corps-fort);
    text-transform: none;
    letter-spacing: 0;
  }

  .avec-onglets { padding-bottom: var(--e-10); }
  .solde-chiffre { font-size: 80px; line-height: 80px; }

  /* Un bouton de huit cents pixels de large n'est pas plus facile a cliquer,
     il est juste plus bruyant. */
  .contenu > .bouton.pleine { width: auto; min-width: 320px; align-self: center; }
}

/* -------------------------------------------------------------- administration
   Otman a quatre ecrans a lui. Ils reprennent les memes briques que ceux de
   l'equipe : une carte, une ligne, une pastille. Ce qui suit n'ajoute que ce
   qui n'existait pas, jamais une seconde facon de dessiner la meme chose.   */

/* Une ligne entiere qui mene quelque part. Le bouton natif est remis a plat :
   il porte le texte a gauche et garde la zone tapable sur toute la largeur. */
.lien-carte {
  width: 100%;
  text-align: left;
  min-height: var(--touche);
  align-items: center;
}

/* Un mot d'alerte sous une carte. Petit, colore, jamais un aplat : la couleur
   d'etat ne couvre pas une grande surface (§ 6.9 du plan). */
.marque-alerte {
  font: var(--t-secondaire);
  color: var(--alerte);
  margin-top: var(--e-2);
}
.marque-alerte.danger { color: var(--danger); }

/* Le solde d'une personne, sur sa carte d'equipe. */
.chiffre-carte {
  font: var(--t-chiffre-2);
  flex: none;
  font-variant-numeric: tabular-nums;
}
.chiffre-carte.negatif { color: var(--danger); }

/* Deux boutons cote a cote, jamais trois : au-dela on ne lit plus lequel est
   le geste principal. Ils passent l'un sous l'autre sous 380 px. */
.deux-boutons {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--e-3);
}
@media (max-width: 379px) { .deux-boutons { grid-template-columns: 1fr; } }

/* Le mot de quelqu'un, rapporte tel quel. */
.citation {
  font: var(--t-corps);
  color: var(--texte-2);
  border-left: 2px solid var(--trait-fort);
  padding-left: var(--e-3);
}

.apercu-titre { font: var(--t-sous-titre); }

.forme { display: flex; flex-direction: column; gap: var(--e-4); }

/* Les gestes d'une ligne de ferie. Ils passent a la ligne plutot que de
   deborder : en 390 px, « Confirmer la date », « Decaler » et « Supprimer »
   ne tiennent pas cote a cote, et une page qui defile lateralement est un
   defaut, pas un compromis. */
.actions-ligne {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-1);
  width: 100%;
}
.actions-ligne .bouton.discret { min-height: var(--touche); }

/* Une ligne de ferie tient sur une ligne : date, nom, chevron. Ce qui
   concerne une date estimee, la pastille et le geste de confirmation, prend une
   seconde ligne a lui, a toutes les largeurs. Serre sur la meme ligne, le nom
   n'avait plus de place et se cassait. */
.ligne-ferie { flex-wrap: wrap; }

.ferie-estimee {
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--e-2);
  padding-left: calc(92px + var(--e-3));
}
@media (max-width: 400px) { .ferie-estimee { padding-left: 0; } }

.ligne-journal .ligne-date { min-width: 110px; }

/* Le mot de passe temporaire : lisible signe par signe, et selectionnable. */
.mot-de-passe {
  font: var(--t-mono);
  font-size: 20px;
  line-height: 28px;
  letter-spacing: .04em;
  -webkit-user-select: text;
  user-select: text;
  margin-bottom: var(--e-2);
  overflow-wrap: anywhere;
}

/* Le chevron qui dit qu'une ligne s'ouvre. Sans lui, une carte entierement
   tapable ne se distingue pas d'une carte a lire : mesure faite sur la capture
   de l'ecran Equipe, ou rien n'annoncait la fiche derriere. */
.chevron {
  width: 20px; height: 20px;
  flex: none;
  color: var(--texte-3);
}

/* Une ligne dont le texte mene ailleurs, quand la ligne porte aussi un bouton
   a elle : deux boutons imbriques ne sont pas du HTML valide. */
.lien-ligne {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--e-3);
  text-align: left;
  min-height: var(--touche);
}

/* Les alertes d'une fiche, en une liste et non en paragraphes separes.
   Trois paragraphes orange se lisaient comme trois pannes ; un bloc a filet se
   lit comme une fiche a completer. Mesure faite sur la capture en 390 px, ou
   huit fiches sur huit portaient quatre lignes orange chacune. */
.alertes {
  margin-top: var(--e-3);
  padding-left: var(--e-3);
  border-left: 2px solid var(--alerte);
  display: flex; flex-direction: column; gap: var(--e-1);
}
.alertes li { font: var(--t-secondaire); color: var(--texte-2); }
.alertes li.grave { color: var(--danger); }
