/* ===== Les mouvements du chat =====
   Regroupés ici plutôt que dispersés : une animation isolée se règle à l'aveugle,
   alors qu'un écran se juge sur la cohérence de ses vitesses. Deux durées, pas
   douze — 0,2 s pour ce qui apparaît, 0,3 s pour ce qui se déplace — et une seule
   courbe, la même partout, pour que tout semble mû par la même main.

   Tout est désactivé sous `prefers-reduced-motion` : le mouvement est un confort,
   jamais une information. Ce qui bouge ici ne porte aucun sens à lui seul. */

.ch {
    --ch-vite: 0.2s;
    --ch-lent: 0.3s;
    --ch-elan: cubic-bezier(0.16, 1, 0.3, 1);
}

/* La colonne de gauche s'ouvre : la grille glisse au lieu de sauter d'un cran. */
.ch { transition: grid-template-columns var(--ch-lent) var(--ch-elan); }
.ch.est-tiree { transition: none; }        /* pendant le glisser, zéro retard */

.ch-side-ligne { animation: ch-glisse-gauche var(--ch-lent) var(--ch-elan) both; }
.ch-side-ligne.est-neuve .ch-side-item { opacity: 0.55; }

/* Le passage barre seule -> écran de travail. */
.ch.est-actif .ch-travail { animation: ch-monte var(--ch-lent) var(--ch-elan) both; }
.ch-vide > * { animation: ch-monte var(--ch-lent) var(--ch-elan) both; }
.ch-vide > *:nth-child(2) { animation-delay: 0.04s; }
.ch-vide > *:nth-child(3) { animation-delay: 0.08s; }

/* Le tableau de bord : les blocs arrivent l'un après l'autre, très légèrement
   décalés. Le décalage dit « ça vient d'être calculé », l'apparition en masse
   donne l'impression d'un écran qui clignote. */
.ch-panneau.est-actif .ch-bloc { animation: ch-monte var(--ch-vite) var(--ch-elan) both; }
.ch-panneau.est-actif .ch-bloc:nth-child(2) { animation-delay: 0.05s; }
.ch-panneau.est-actif .ch-bloc:nth-child(3) { animation-delay: 0.1s; }
.ch-panneau.est-actif .ch-bloc:nth-child(n+4) { animation-delay: 0.15s; }

/* Les barres poussent depuis la gauche : on voit la comparaison se construire. */
.ch-panneau.est-actif .ch-barre i { animation: ch-pousse 0.45s var(--ch-elan) both; }
.ch-colonne { transition: height var(--ch-lent) var(--ch-elan); }

/* La courbe se dessine. `stroke-dasharray` en unités de viewBox : 2000 dépasse
   la longueur de n'importe quel tracé ici, donc le trait part bien de zéro. */
.ch-panneau.est-actif .ch-graphe .trace {
    stroke-dasharray: 2000; animation: ch-trace 0.9s ease-out both;
}
.ch-panneau.est-actif .ch-graphe .pt { animation: ch-point var(--ch-vite) var(--ch-elan) both; }
.ch-graphe .pt { transition: r 0.12s ease; }

/* Le verdict et les onglets. */
.ch-onglet { transition: background var(--ch-vite) ease, color var(--ch-vite) ease; }
.ch-verdict { animation: ch-monte var(--ch-lent) var(--ch-elan) both; }

/* Le journal : la coche qui remplace la puce mérite d'être vue. */
.ch-etape.est-faite .ch-etape-puce::before { animation: ch-coche var(--ch-vite) var(--ch-elan) both; }
.ch-pensee-corps { transition: opacity var(--ch-vite) ease; }

@keyframes ch-monte {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: none; }
}
@keyframes ch-glisse-gauche {
    from { opacity: 0; transform: translateX(-10px); }
    to { opacity: 1; transform: none; }
}
@keyframes ch-pousse { from { width: 0 !important; } }
@keyframes ch-trace { from { stroke-dashoffset: 2000; } to { stroke-dashoffset: 0; } }
@keyframes ch-point { from { opacity: 0; transform: scale(0.4); } to { opacity: 1; transform: none; } }
@keyframes ch-coche { from { opacity: 0; transform: scale(0.5); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
    .ch, .ch * { animation: none !important; transition: none !important; }
    .ch-graphe .trace { stroke-dasharray: none; }
}

/* ── Le dossier en cours de composition ────────────────────────────────────
   Le livrable de ce produit EST un document. L'attente montre donc une feuille
   qui s'écrit, pas un rond qui tourne — un rond peut attendre n'importe quoi.

   Deux mouvements, et c'est délibéré. Les traits se remplissent l'un après
   l'autre : ça raconte l'écriture, mais ça s'arrête entre deux cycles. Un
   balayage traverse la feuille EN CONTINU par-dessus : lui ne se repose jamais,
   donc à n'importe quel instant on voit que ça travaille. La première version
   n'avait que les traits, et restait figée 1,3 s sur 3,4 — la moitié du temps,
   l'écran avait l'air planté. */
.ch-compo, .ch-etapes { display: none; }
.ch-modale.est-travail .ch-compo { display: block; }
.ch-modale.est-travail .ch-etapes { display: block; }

.ch-feuille {
    position: relative; overflow: hidden;
    width: 8.5rem; height: 11rem; margin: 0.4rem auto 1.3rem;
    padding: 0.9rem 0.85rem; border: 1px solid var(--mr-border-strong);
    border-radius: 3px; background: var(--mr-surface-card);
    display: flex; flex-direction: column; gap: 0.42rem;
    box-shadow: 0 1px 0 var(--mr-border), 3px 3px 0 -1px var(--mr-surface-sunken);
}

/* Le balayage : une bande claire qui descend sans fin. C'est LUI qui dit
   « ça travaille » ; les traits, eux, disent « un document s'écrit ». */
.ch-feuille::after {
    content: ''; position: absolute; inset: -30% 0 auto 0; height: 45%;
    background: linear-gradient(180deg,
        transparent, color-mix(in srgb, var(--mr-text-strong) 9%, transparent), transparent);
    animation: ch-balayage 1.5s linear infinite;
}
@keyframes ch-balayage {
    0%   { transform: translateY(0); }
    100% { transform: translateY(340%); }
}

/* Chaque trait part de zéro et s'étire. Largeurs finales irrégulières : des
   lignes identiques font un code-barres, pas un texte. Le cycle est court et
   le palier bref — on doit voir écrire, pas attendre. */
.ch-feuille i {
    display: block; height: 5px; border-radius: 2px;
    background: var(--mr-border-strong); width: 0;
    animation: ch-trait 2.2s ease-out infinite;
}
.ch-feuille .titre { height: 9px; background: var(--mr-text-strong); --fin: 72%; }
.ch-feuille .l1 { --fin: 100%; animation-delay: 0.14s; }
.ch-feuille .l2 { --fin: 84%;  animation-delay: 0.24s; }
.ch-feuille .bloc {
    height: 2.1rem; --fin: 100%; animation-delay: 0.36s;
    background: var(--mr-surface-sunken); border: 1px solid var(--mr-border);
}
.ch-feuille .l3 { --fin: 96%; animation-delay: 0.54s; }
.ch-feuille .l4 { --fin: 100%; animation-delay: 0.64s; }
.ch-feuille .l5 { --fin: 58%;  animation-delay: 0.74s; }

@keyframes ch-trait {
    0%       { width: 0;              opacity: 0; }
    8%       { opacity: 1; }
    45%, 82% { width: var(--fin, 100%); opacity: 1; }
    100%     { width: var(--fin, 100%); opacity: 0; }
}

/* Les trois temps, qui s'allument à tour de rôle. Ils disent ce qu'on fabrique —
   « les prompts prêts à coller » vaut mieux qu'un pourcentage dont personne ne
   sait s'il est honnête. Le point de tête grossit quand c'est son tour. */
.ch-etapes {
    list-style: none; margin: 0 auto 1.2rem; padding: 0;
    display: flex; flex-direction: column; gap: 0.32rem; width: max-content;
}
.ch-etapes li {
    font-family: var(--mr-mono); font-size: var(--ch-fs-2xs); letter-spacing: 0.04em;
    color: var(--mr-text-muted);
    display: flex; align-items: center; gap: 0.55rem;
    animation: ch-etape 2.7s ease-in-out infinite;
}
.ch-etapes li::before {
    content: ''; width: 5px; height: 5px; border-radius: 50%;
    background: currentColor; flex: none;
    animation: ch-puce 2.7s ease-in-out infinite; animation-delay: inherit;
}
.ch-etapes li:nth-child(2) { animation-delay: 0.9s; }
.ch-etapes li:nth-child(2)::before { animation-delay: 0.9s; }
.ch-etapes li:nth-child(3) { animation-delay: 1.8s; }
.ch-etapes li:nth-child(3)::before { animation-delay: 1.8s; }

@keyframes ch-etape {
    0%, 100%  { opacity: 0.3; }
    8%, 30%   { opacity: 1; color: var(--mr-text-strong); }
}
@keyframes ch-puce {
    0%, 100% { transform: scale(1); }
    8%, 30%  { transform: scale(1.7); }
}

.ch-modale.est-travail .ch-modale-titre,
.ch-modale.est-travail .ch-modale-texte { text-align: center; }

/* Le point qui respire à côté du titre. */
.ch-modale.est-travail .ch-modale-titre::after {
    content: ''; display: inline-block; margin-left: 0.5rem;
    width: 0.35rem; height: 0.35rem; border-radius: 50%;
    background: currentColor; vertical-align: middle;
    animation: ch-pulse-dossier 1.1s ease-in-out infinite;
}
@keyframes ch-pulse-dossier {
    0%, 100% { opacity: 0.25; transform: scale(0.75); }
    50%      { opacity: 1;    transform: scale(1.15); }
}

/* Quelqu'un qui demande moins d'animations a une bonne raison. On garde
   l'information — la feuille et les étapes restent lisibles, figées. */
@media (prefers-reduced-motion: reduce) {
    .ch-feuille::after { animation: none; opacity: 0; }
    .ch-feuille i { animation: none; width: var(--fin, 100%); opacity: 1; }
    .ch-etapes li, .ch-etapes li::before { animation: none; opacity: 0.8; }
    .ch-modale.est-travail .ch-modale-titre::after { animation: none; opacity: 0.7; }
}

/* ===== Le tiroir des données, sous 1100px =====
   Un seul geste, deux pièces solidaires : le bouton monte de la barre du bas
   vers l'en-tête du fil, et le panneau sort de derrière cette même barre en le
   suivant. Ils partagent durée et courbe, sinon on voit deux mouvements au lieu
   d'un tiroir qu'on tire.

   TROISIÈME DURÉE, et c'est assumé : le fichier n'en veut que deux, mais elles
   valent pour des déplacements de quelques dizaines de pixels. Ici le bouton
   traverse plus de 600 px. À 0,3 s la même distance se lit comme un saut, pas
   comme un glissement. */
.ch { --ch-tiroir: 0.52s; }

@media (max-width: 1100px) {
    /* La barre du bas passe AU-DESSUS du panneau et reçoit un fond opaque :
       c'est ce qui fait que le tiroir a l'air de sortir de derrière elle plutôt
       que de traverser la saisie. */
    .ch-rail-bas {
        /* `z-index` sans `position` : c'est un element flex, et la propriete
           s'y applique quand meme. Le positionner ferait de lui le bloc
           contenant du bouton, qui doit se caler sur `.ch-travail` une fois
           deplie ; il atterrissait 660px trop bas. */
        z-index: 56;
        background: var(--mr-surface-sunken);
    }

    /* Fermé, le panneau est descendu d'exactement sa propre hauteur : son haut
       se trouve alors où était le bouton. Pas d'opacité dans l'affaire, un
       tiroir ne se dissout pas, il coulisse. */
    .ch-bord {
        transform: translateY(100%);
        transition: transform var(--ch-tiroir) var(--ch-elan),
                    visibility var(--ch-tiroir);
    }

    .ch.donnees-ouvertes .ch-bord { transform: none; }

    .ch-bascule {
        transition: transform var(--ch-tiroir) var(--ch-elan),
                    color 0.15s ease, border-color 0.15s ease;
    }
}

@media (prefers-reduced-motion: reduce) {
    .ch-bord, .ch-bascule { transition: none; }
    .ch-bord { transform: none; }
}
