/*!
 * Atlas — gestionnaire immobilier. Version 1.85.0.
 * Copyright (c) 2026 Systegon. Tous droits reserves.
 *
 * Ce fichier et son contenu sont protégés par le droit d'auteur
 * (code de la propriété intellectuelle, art. L112-2 et L122-6).
 * Leur reproduction, adaptation ou réutilisation, même partielle,
 * est interdite sans autorisation écrite de Systegon.
 *
 * https://atlas.systegon.com — contact-atlas@systegon.com
 */

/* ══════════════════════════════════════════════════════════════════════════
   LE MOUVEMENT — ce qui fait qu'un logiciel paraît vivant
   ══════════════════════════════════════════════════════════════════════════

   Atlas était juste, et parfaitement immobile : les écrans apparaissaient
   d'un bloc, les chiffres s'affichaient déjà écrits, les jauges naissaient
   pleines. Rien n'était faux — mais rien ne disait non plus ce qui venait de
   changer, ni où regarder.

   TROIS RÈGLES, et elles sont exigeantes :

   1. LE MOUVEMENT DIT QUELQUE CHOSE. Une carte qui entre indique qu'elle
      arrive ; un chiffre qui monte indique qu'il vient d'être calculé ; une
      jauge qui se remplit donne la mesure. Une animation qui n'apprend rien
      est une animation qu'on retire.

   2. RIEN N'EST JAMAIS CACHÉ PAR UNE ANIMATION. Toutes les apparitions
      partent d'une animation CSS qui SE JOUE TOUJOURS : si le script ne
      s'exécute pas, si l'animation est refusée, si la page est imprimée,
      l'élément est visible. On ne pose jamais un `opacity:0` durable en
      attendant qu'un script veuille bien le retirer — c'est ainsi qu'on rend
      un écran blanc chez quelqu'un dont on n'avait pas prévu le cas.

   3. QUI N'EN VEUT PAS N'EN A PAS. `prefers-reduced-motion` coupe tout.
      `--mouvement` module l'ampleur de tout ce qui suit ; il valait autrefois
      autre chose que 1 selon la « parure » choisie — ces parures ont été
      retirées, la variable reste, parce qu'elle est le seul endroit où régler
      le rythme d'un coup si l'envie revient.

   ═══════════════════════════════════════════════════════════════════════ */

/* CETTE FEUILLE SE CHARGE AVANT `univers.css`, ET CE N'EST PAS UN DÉTAIL.
   `:root` et `[data-univers="…"]` ciblent le même élément avec la même
   spécificité : c'est donc l'ordre de déclaration qui tranche. Chargée après,
   la valeur par défaut ci-dessous écraserait celle qu'un monde voudrait poser
   — c'est exactement ce qui était arrivé aux quatre parures d'alors, qui
   avaient toutes fini avec le même rythme. */
:root{
  /* L'ampleur du mouvement, réglée par la parure. 1 = le rythme d'Atlas. */
  --mouvement:1;
  /* La durée de référence, d'où toutes les autres se déduisent. */
  --duree:calc(var(--mouvement) * 340ms);
  --duree-courte:calc(var(--mouvement) * 180ms);
  /* Une courbe qui démarre franchement et se pose : celle d'un objet qui a
     une masse, pas d'un rideau qu'on tire. */
  --elan:cubic-bezier(.22,.68,.32,1);
}

/* ──────────────────────────────────────────────────────────────────────────
   L'ENTRÉE EN CASCADE
   ──────────────────────────────────────────────────────────────────────────
   Les blocs d'un écran ne se posent pas tous en même temps : quelques
   dizaines de millisecondes les séparent, et l'œil suit l'ordre de lecture
   au lieu de tout recevoir d'un coup.

   `both` garde l'état de départ pendant le délai — c'est ce qui rend la
   cascade possible — mais l'animation EST LANCÉE : elle finit donc toujours,
   même si la personne ne fait rien, même si le script s'arrête après.
   ────────────────────────────────────────────────────────────────────────── */
@keyframes mvt-entree{
  from{opacity:0;transform:translateY(calc(var(--mouvement) * 10px));}
  to{opacity:1;transform:none;}
}
.mvt-entree{
  animation:mvt-entree var(--duree) var(--elan) both;
  animation-delay:calc(var(--i,0) * var(--mouvement) * 45ms);
}

/* Une ligne qui vient d'être ajoutée à une liste : elle glisse depuis le bord
   au lieu d'apparaître au milieu des autres. */
@keyframes mvt-ligne{
  from{opacity:0;transform:translateX(calc(var(--mouvement) * -14px));}
  to{opacity:1;transform:none;}
}
.mvt-ligne{animation:mvt-ligne var(--duree) var(--elan) both;}

/* Ce qui vient de changer de valeur : un bref halo, puis plus rien. Sert au
   montant d'un lot qui passe à « réglé », au compteur de notifications. */
@keyframes mvt-pouls{
  0%{box-shadow:0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent);}
  100%{box-shadow:0 0 0 calc(var(--mouvement) * 12px) transparent;}
}
.mvt-pouls{animation:mvt-pouls calc(var(--duree) * 2.2) ease-out 1;}

/* ──────────────────────────────────────────────────────────────────────────
   LES JAUGES
   ──────────────────────────────────────────────────────────────────────────
   Une jauge qui naît pleine ne se lit pas : on voit un bloc coloré. Une jauge
   qui monte jusqu'à sa valeur donne la mesure, parce que l'œil suit la course
   et retient où elle s'arrête. La largeur finale reste celle que le script a
   posée — on n'anime que le chemin pour y arriver.
   ────────────────────────────────────────────────────────────────────────── */
.auj-jauge-part,.pb-barre-jauge,.ly-jauge-part,.rg-jauge-part,.coff-jauge-part{
  transition:width calc(var(--duree) * 2) var(--elan);
}

/* ──────────────────────────────────────────────────────────────────────────
   LE GESTE : CE QU'ON TOUCHE RÉPOND
   ──────────────────────────────────────────────────────────────────────────
   Un bouton qui ne bouge pas sous le doigt laisse croire, une demi-seconde,
   qu'on l'a manqué — et l'on appuie deux fois. L'enfoncement est court et
   net : il confirme, il ne décore pas.
   ────────────────────────────────────────────────────────────────────────── */
.btn,.icon-btn,.card,.user-row,.ly-lot,.auj-carte,.par-carte{
  transition:transform var(--duree-courte) var(--elan),
             box-shadow var(--duree-courte) var(--elan),
             border-color var(--duree-courte) ease,
             background-color var(--duree-courte) ease;
}
.btn:active,.icon-btn:active{transform:scale(calc(1 - .03 * var(--mouvement)));}

/* L'onde partie du point touché. Posée par mouvement.js, qui écrit les
   coordonnées du clic : c'est le seul moyen qu'elle naisse SOUS le doigt et
   non au centre du bouton. */
@keyframes mvt-onde{
  from{opacity:.38;transform:scale(0);}
  to{opacity:0;transform:scale(1);}
}
.mvt-onde{
  position:absolute;border-radius:50%;pointer-events:none;
  background:currentColor;
  animation:mvt-onde calc(var(--duree) * 1.6) var(--elan) forwards;
}
/* L'onde a besoin d'un repère : sans lui, elle se placerait par rapport à la
   page. `overflow:hidden` la découpe à la forme du bouton — angles compris,
   donc elle suit la parure. */
.btn,.icon-btn{position:relative;overflow:hidden;}

/* ──────────────────────────────────────────────────────────────────────────
   LES CHIFFRES QUI SE POSENT
   ──────────────────────────────────────────────────────────────────────────
   Un total qui compte jusqu'à sa valeur se remarque, et l'on comprend qu'il
   vient d'être calculé. Les chiffres doivent alors occuper une largeur fixe,
   sinon le nombre tremble pendant qu'il monte.
   ────────────────────────────────────────────────────────────────────────── */
.mvt-compte{font-variant-numeric:tabular-nums;}

/* ──────────────────────────────────────────────────────────────────────────
   LE SQUELETTE — ce qu'on montre pendant qu'on charge
   ──────────────────────────────────────────────────────────────────────────
   Un écran vide pendant deux secondes est indiscernable d'un écran en panne.
   Le squelette dit « ça vient », et dessine déjà la forme de ce qui arrive :
   au moment où les données se posent, rien ne saute.
   ────────────────────────────────────────────────────────────────────────── */
@keyframes mvt-lueur{
  from{background-position:-160% 0;}
  to{background-position:260% 0;}
}
.mvt-squelette{
  border-radius:var(--r-sm,10px);
  background:linear-gradient(90deg,
    var(--surface2) 0%, color-mix(in srgb, var(--ink) 9%, var(--surface2)) 45%, var(--surface2) 90%);
  background-size:220% 100%;
  animation:mvt-lueur calc(var(--mouvement) * 1250ms) linear infinite;
  min-height:14px;
}
.mvt-squelette-bloc{display:flex;flex-direction:column;gap:10px;}
.mvt-squelette-bloc .mvt-squelette:nth-child(2){width:72%;}
.mvt-squelette-bloc .mvt-squelette:nth-child(3){width:48%;}

/* ──────────────────────────────────────────────────────────────────────────
   D'UNE PAGE À L'AUTRE — ESSAYÉ, PUIS RETIRÉ
   ──────────────────────────────────────────────────────────────────────────
   Atlas est fait de vraies pages, et chaque navigation est un bref
   clignotement. `@view-transition{navigation:auto}` le remplace par un fondu,
   en trois lignes, sans une ligne de script. C'était tentant.

   POURQUOI ON NE LE GARDE PAS. Dès qu'une navigation en interrompt une autre
   — un clic pendant qu'une page charge, et c'est le cas de tous nos bancs —
   le navigateur écrit « Transition was skipped » dans la console. Ce n'est
   pas une erreur de notre code, mais nos bancs comptent les erreurs de
   console, et ils en trouvaient une sur chaque enchaînement de pages.

   Un défaut qui apparaît partout finit par ne plus rien signaler : on
   s'habitue à la ligne rouge, et le jour où elle dit autre chose, personne ne
   la lit. Trois lignes de fondu ne valent pas d'aveugler les bancs.
   ────────────────────────────────────────────────────────────────────────── */

/* ──────────────────────────────────────────────────────────────────────────
   QUI N'EN VEUT PAS N'EN A PAS
   ──────────────────────────────────────────────────────────────────────────
   Ce réglage n'est pas un détail de confort : le mouvement déclenche des
   malaises chez une partie des gens (troubles vestibulaires, migraines). Tout
   s'arrête — et surtout, tout reste VISIBLE : les animations d'apparition se
   contentent de finir immédiatement.
   ────────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce){
  .mvt-entree,.mvt-ligne,.mvt-pouls{animation:none !important;opacity:1 !important;transform:none !important;}
  .mvt-squelette{animation:none !important;}
  .mvt-onde{display:none !important;}
  .btn:active,.icon-btn:active{transform:none !important;}
  *{transition-duration:.01ms !important;}
}
