/* ═══ Aucun zoom, nulle part ═══
     `touch-action: manipulation` supprime le zoom au double-toucher.
     `text-size-adjust` empêche iOS de grossir le texte tout seul en paysage.
     Les règles de la frise vidéo (classes) restent prioritaires sur ce `*`. */
  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; touch-action: manipulation; }
  :root{
    --bg:#0C0D0E; --bg-card: rgba(255,255,255,0.06);
    --label:#FFFFFF; --label-2: rgba(235,235,245,0.60); --label-3: rgba(235,235,245,0.30);
    --hero-gradient: linear-gradient(150deg, #2C2C34 0%, #1E1E24 40%, #141418 75%, #0C0C10 100%);
    --green:#30D158; --red:#FF453A; --orange:#FF9F0A;
    --blue:#F5A623; --purple:#E8A33D;   /* utilisées par les anneaux de l'analyse */
    --separator: rgba(84,84,88,0.40); --border: rgba(255,255,255,0.15);
  }
  html, body{
    background:#0C0D0E;     font-family:'Inter', -apple-system, BlinkMacSystemFont, "Helvetica Neue", system-ui, sans-serif;
    color:var(--label); font-size:17px; line-height:1.32; letter-spacing:-0.02em;
    -webkit-font-smoothing:antialiased; min-height:100dvh; overflow-x:hidden; position:relative;
    -webkit-text-size-adjust:100%; text-size-adjust:100%;
  }
  button{font-family:inherit; cursor:pointer; border:none; background:none; color:inherit; padding:0;}
  textarea, input{font-family:inherit; color:inherit;}

  /* ═══════════════════════════════════════════════════════════════════════
     ARRIÈRE-PLAN — écrit d'un seul jet, sans rien de superflu.
     Trois taches lumineuses floutées qui respirent lentement. C'est tout :
     un conteneur, trois éléments, trois animations. Aucune promotion GPU
     forcée, aucune enveloppe intermédiaire, aucun état figé au démarrage.
     ═══════════════════════════════════════════════════════════════════════ */
  .color-halos{
    position:fixed; inset:0; z-index:0; pointer-events:none; overflow:hidden;
  }
  .chalo{
    position:absolute; border-radius:50%; filter:blur(120px); opacity:0.8;
  }
  .chalo-1{
    top:4%; left:-14%; width:70vw; height:70vw; max-width:620px; max-height:620px;
    background:radial-gradient(circle, #25252A 0%, #1D1D20 45%, transparent 72%);
    animation:chalo1 14s ease-in-out infinite;
  }
  .chalo-2{
    bottom:-8%; right:-16%; width:75vw; height:75vw; max-width:660px; max-height:660px;
    background:radial-gradient(circle, #2A2A2F 0%, #222225 45%, transparent 72%);
    animation:chalo2 18s ease-in-out infinite;
  }
  .chalo-4{
    top:-14%; left:50%; width:120vw; height:70vw; max-width:1000px; max-height:600px;
    background:radial-gradient(circle, #28282C 0%, #1F1F23 48%, transparent 70%);
    opacity:0.9; animation:chalo3 16s ease-in-out infinite;
  }
  @keyframes chalo1{
    0%,100%{ transform:translate(0,0) scale(1); opacity:0.70; }
    50%    { transform:translate(6%,4%) scale(1.12); opacity:0.95; }
  }
  @keyframes chalo2{
    0%,100%{ transform:translate(0,0) scale(1.05); opacity:0.65; }
    50%    { transform:translate(-5%,-6%) scale(1); opacity:0.90; }
  }
  @keyframes chalo3{
    0%,100%{ transform:translateX(-50%) scale(1); opacity:0.80; }
    50%    { transform:translateX(-50%) scale(1.15); opacity:1; }
  }

  /* ═══ LE FOND, SUR MOBILE ═══

     Sur un petit écran, les halos sont éclaircis et le flou resserré : à
     120 px de flou sur 390 px de large, la tache déborde de tous les côtés et
     ne se voit plus. 90 px lui rendent une forme.

     ─── AOÛT 2026 · UN CRAN PLUS SOMBRE ───

     L'éclaircissement était trop franc : environ +17 par canal sur les trois
     halos, plus l'opacité poussée de 0,8 à 1. Le fond montait par endroits à
     #3B3B41 — assez clair pour que les cartes, dont l'intérieur descend à
     #060608, paraissent flotter sur un gris plutôt que sur du noir.

     On reprend HUIT POINTS par canal, soit à peu près la moitié du chemin vers
     les valeurs du bureau. Les halos restent visibles — le but n'était pas de
     les éteindre — mais le noir redevient le fond, et l'ambre des liserés
     ressort dessus.

     POUR AJUSTER : ce sont les six valeurs ci-dessous, et elles seules. Plus
     sombre encore, retire huit de plus à chaque paire ; les valeurs du bureau
     sont trente lignes plus haut et forment le plancher. */
  @media (max-width: 600px){
    .chalo{ opacity:1; filter:blur(90px); }
    .chalo-1{ background:radial-gradient(circle, #2E2E34 0%, #222227 45%, transparent 72%); }
    .chalo-2{ background:radial-gradient(circle, #333339 0%, #27272D 45%, transparent 72%); }
    .chalo-4{ opacity:1; background:radial-gradient(circle, #303036 0%, #24242A 48%, transparent 70%); }
  }

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

  /* ═══ Interrupteurs d'essai ═══
     Activés en ajoutant ?nofond=1 ou ?noverre=1 à la fin de l'adresse.
     Ils servent uniquement à isoler ce qui coûte cher à dessiner : on retire
     un élément, on relance, on compare. Sans ces paramètres, rien ne change. */
  body.sans-fond .color-halos{ display:none; }
  body.sans-verre .topbar-card,
  body.sans-verre .icon-pill,
  body.sans-verre .tabbar,
  body.sans-verre .login-card,
  body.sans-verre .ios-alert{
    -webkit-backdrop-filter:none !important; backdrop-filter:none !important;
    background:rgba(30,31,35,0.94) !important;
  }



  /* `100vh` dépasse l'écran réellement visible sur téléphone : il ignore la barre
     d'adresse. La page était donc TOUJOURS plus haute que l'écran, même avec deux
     dossiers, d'où ce grand vide sous la barre d'onglets. `100dvh` suit la
     hauteur réellement disponible.

     Le dégagement du bas est porté par l'écran, pas par l'app : ici il
     s'ajoutait à celui de l'écran, et les deux se cumulaient. */
  /* ═══ UNE SEULE LARGEUR, DEUX VALEURS ═══

     460 px sur téléphone, 560 au-delà de 768. UN SEUL PALIER : une tablette et
     un ordinateur reçoivent la même chose, comme demandé. Pas de zoom, pas de
     cascade de tailles — juste une colonne un peu plus large là où il y a la
     place.

     `--col` sert aussi à la barre du bas, qui vaut cette largeur moins ses
     marges. Une seule valeur à changer si tu veux ajuster. */
  :root{ --col: 460px; }
  @media (min-width: 768px){ :root{ --col: 560px; } }

  .app{
    position:relative; z-index:1; width:100%; max-width:var(--col); margin:0 auto;
    min-height:100dvh;
  }
  .topbar{ position:fixed; top:0; left:50%; transform:translateX(-50%); width:100%; max-width:var(--col); z-index:15; padding:16px 18px 0; }

  .brand .mark svg{ width:26px; height:29px; animation: logoBreath 4s ease-in-out infinite; }
  @keyframes logoBreath{
    0%,100%{ transform:scale(1); }
    50%{ transform:scale(1.06); }
  }

  /* EN COLONNE. La rangée était horizontale : les deux points se plaçaient
     À CÔTÉ de la piste au lieu d'être dessous, poussés au bord droit de
     l'écran. Un seul enfant — la barre de l'espace équipe — s'en trouve
     simplement centré, ce qu'il était déjà. */
  .topbar-row{ display:flex; flex-direction:column; align-items:center; justify-content:center; }
  /* Aucune matière ici : ni fond, ni flou, ni liseré, ni ombre. Il ne reste que
     la géométrie — la forme, la place, le remplissage.

     Le verre est posé plus bas, en un seul endroit, avec la recette exacte de
     `.glassDiv`. Tant que ces déclarations restaient là, elles s'ajoutaient à
     celle du bas : la carte portait le verre de la barre PLUS un flou de 24 px
     et une saturation de 180 % hérités de l'ancienne. Deux matières
     superposées, donc jamais celle de la barre. */
  .topbar-card{
    position:relative;
    display:flex; align-items:center;
    /* 16 px à gauche. J'étais descendu à 13 pour resserrer l'ensemble : le
       logo touchait presque le bord, et la pilule paraissait trop juste.
       À droite on garde 20 — le texte a besoin de plus d'air qu'une forme. */
    border-radius:100px; padding:10px 20px 10px 16px;
  }
  /* 9 px : le cadre épouse maintenant le dessin, la marge peut donc reprendre
     une valeur normale. À 6 px avec un cadre juste, le nom collerait au logo. */
  .topbar-left{ display:flex; align-items:center; gap:9px; }
  .logo-pill{
    display:flex; align-items:center; justify-content:center; flex-shrink:0;
    /* Calage optique fin par rapport au bloc de texte à deux lignes. */
    transform: translateY(0.1px);
  }
  .logo-pill svg{ width:23px; height:27px; }
  .topbar-title{ display:flex; flex-direction:column; line-height:1.2; }
  /* ═══ LE NOM PORTE SA PROPRE POLICE ═══

     Poppins, en graisse 400. Outfit y était d'abord — mais elle est plus
     étroite et plus dense : à 600, le mot paraissait épais. Poppins a le « a »
     à un seul étage et la rondeur de la capture, avec un trait fin.

     Elle ne sert QU'AU NOM. Le reste de l'app garde Inter, dessinée pour la
     lecture en petit sur écran — c'est ce que fait un employé debout en
     cuisine. Une police géométrique y fatigue : ses lettres se ressemblent
     trop, et le I majuscule, le l minuscule et le 1 s'y confondent. Dans une
     procédure, cette confusion coûte cher.

     Une police de marque, une police de lecture : c'est ainsi que font la
     plupart des produits. */
  .topbar-title .name, .logotype{
    font-family:'Poppins', 'Inter', system-ui, sans-serif;
    /* ═══ LA GRAISSE 500, POUR DE VRAI ═══

       Il y avait ici du 400 épaissi d'un quart de pixel par un contour tracé
       dans la couleur de la lettre. Un demi-pas, faute d'avoir chargé le 500.

       Le procédé a deux défauts : le contour est ajouté par le navigateur, pas
       dessiné par le typographe — les jonctions du « a » et du « d » s'y
       empâtent —, et `-webkit-text-stroke` n'existe pas partout, si bien que
       le mot changeait d'épaisseur d'un navigateur à l'autre.

       Le 500 est maintenant chargé et employé. Une vraie graisse, dessinée
       pour l'être. */
    font-weight:500; letter-spacing:-0.01em;
  }
  .topbar-title .name{ font-size:15.5px; }
  .topbar-title .role{ font-size:11.5px; color:var(--label-2); font-weight:500; }
  /* ═══ Le compte est partagé ═══ */
  /* Un point sur le bouton des réglages : c'est le seul endroit où l'on peut
     agir, donc le seul endroit où la pastille a un sens. */
  .icon-pill.alerte::after{
    content:''; position:absolute; top:1px; right:1px;
    width:11px; height:11px; border-radius:50%;
    background:var(--red); border:2px solid #16171B;
    animation:pastilleArrive 0.4s cubic-bezier(0.34,1.62,0.5,1) both;
  }
  @keyframes pastilleArrive{ from{ transform:scale(0); } to{ transform:none; } }

/* ═══ L'ALERTE D'ESSAI ═══
     Même motif que `.alerte-partage` — tuile de 32, titre de 14,5, deux boutons
     de 38 — mais en BLEU. L'ambre signale une faute à corriger ; la fin d'un
     essai n'en est pas une, elle était prévue depuis le premier jour. */
/* ═══ DES GENS ATTENDENT À LA PORTE ═══
     ROUGE, et non ambre. C'est la seule alerte de l'app qui coûte un client si
     on l'ignore : quelqu'un veut entrer, et il y a de l'argent en jeu. Les
     autres alertes signalent une chose à corriger ; celle-ci, une chose à
     décider. */
  .alerte-demandes{
    margin-top:14px; padding:15px; border-radius:18px;
    background:rgba(255,69,58,0.10); border:0.5px solid rgba(255,69,58,0.32);
  }
  .alerte-demandes .tete{ display:flex; align-items:flex-start; gap:11px; }
  .alerte-demandes .pic{
    width:32px; height:32px; border-radius:10px; flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
    background:rgba(255,69,58,0.16); border:0.5px solid rgba(255,69,58,0.3);
  }
  .alerte-demandes .pic svg{ width:18px; height:18px; }
  .alerte-demandes .tx{ flex:1; min-width:0; }
  .alerte-demandes .tx b{ display:block; font-size:14.5px; font-weight:700; letter-spacing:-0.02em; }
  .alerte-demandes .tx i{
    display:block; font-style:normal; font-size:12px;
    color:#FF9A92; margin-top:2px; font-weight:600;
  }
  .alerte-demandes .s{ font-size:12.5px; color:var(--label-2); line-height:1.5; margin-top:11px; }
  .alerte-demandes .actions{ display:flex; gap:8px; margin-top:13px; }
  .alerte-demandes .principal{
    flex:1; height:38px; border:none; border-radius:12px;
    background:#fff; color:#000; font-family:inherit; font-size:13px; font-weight:700;
  }
  .alerte-demandes .secondaire{
    height:38px; padding:0 15px; border-radius:12px;
    background:rgba(255,255,255,0.08); border:0.5px solid var(--border);
    color:var(--label-2); font-family:inherit; font-size:13px; font-weight:650;
  }

  /* L'alerte s'en va devant les yeux quand on dit « plus tard ». */
  .alerte-essai.part{
    animation:alertePart 0.32s cubic-bezier(0.4,0,1,1) both;
    pointer-events:none;
  }
  @keyframes alertePart{
    0%{ opacity:1; transform:scale(1); max-height:260px; }
    100%{ opacity:0; transform:scale(0.94); max-height:0;
          margin-top:0; padding-top:0; padding-bottom:0; }
  }

  .alerte-essai{
    margin-top:14px; padding:15px; border-radius:18px;
    background:rgba(245,166,35,0.10); border:0.5px solid rgba(245,166,35,0.30);
  }
  .alerte-essai .tete{ display:flex; align-items:flex-start; gap:11px; }
  .alerte-essai .pic{
    width:32px; height:32px; border-radius:10px; flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
    background:rgba(245,166,35,0.16); border:0.5px solid rgba(245,166,35,0.3);
  }
  .alerte-essai .pic svg{ width:18px; height:18px; }
  .alerte-essai .tx{ flex:1; min-width:0; }
  .alerte-essai .tx b{ display:block; font-size:14.5px; font-weight:700; letter-spacing:-0.02em; }
  .alerte-essai .tx i{
    display:block; font-style:normal; font-size:12px;
    color:var(--label-2); margin-top:2px;
  }
  .alerte-essai .s{ font-size:12.5px; color:var(--label-2); line-height:1.5; margin-top:11px; }
  .alerte-essai .s b{ color:#fff; font-weight:650; }
  .alerte-essai .actions{ display:flex; gap:8px; margin-top:13px; }
  /* Même matière que tous les gestes principaux de l'app. Il était resté blanc,
     comme l'était `.btn` avant qu'on ne le passe à l'ambre : deux styles pour un
     même rang, et l'œil ne sait plus lequel est LE geste. */
  .alerte-essai .principal{
    flex:1; height:38px; border:none; border-radius:12px;
    background:linear-gradient(135deg,#FF6A00 0%,#FF9A1F 60%,#FFAD33 100%);
    color:#2A1400; font-family:inherit; font-size:13px; font-weight:750;
    box-shadow:0 5px 15px rgba(255,122,24,0.22);
  }
  .alerte-essai .secondaire{
    height:38px; padding:0 15px; border-radius:12px;
    background:rgba(255,255,255,0.08); border:0.5px solid var(--border);
    color:var(--label-2); font-family:inherit; font-size:13px; font-weight:650;
  }
  /* La jauge des jours écoulés, comme celles des pages d'analyse. */
  .alerte-essai .jauge{
    height:5px; border-radius:3px; margin-top:11px;
    background:rgba(255,255,255,0.09); overflow:hidden;
  }
  .alerte-essai .jauge i{ display:block; height:100%; border-radius:3px; background:var(--blue); }

  /* Ce qui est fermé quand l'essai a expiré. */
  body.abo-expire [data-etab-plus]{ opacity:0.4; pointer-events:none; }

  .alerte-partage{
    margin-top:14px; padding:15px; border-radius:18px;
    background:rgba(255,159,10,0.10); border:0.5px solid rgba(255,159,10,0.30);
  }
  .alerte-partage .tete{ display:flex; align-items:flex-start; gap:11px; }
  .alerte-partage .pic{
    width:32px; height:32px; border-radius:10px; flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
    background:rgba(255,159,10,0.16); border:0.5px solid rgba(255,159,10,0.28);
  }
  .alerte-partage .pic svg{ width:18px; height:18px; }
  .alerte-partage .tx{ flex:1; min-width:0; }
  .alerte-partage .tx b{ display:block; font-size:14.5px; font-weight:700; letter-spacing:-0.02em; }
  .alerte-partage .tx i{
    display:block; font-style:normal; font-size:12px; color:var(--label-2); margin-top:2px;
  }
  .alerte-partage .s{
    font-size:12.5px; color:var(--label-2); line-height:1.5; margin-top:11px;
  }
  .alerte-partage .actions{ display:flex; gap:8px; margin-top:13px; }
  .alerte-partage .principal{
    flex:1; height:38px; border:none; border-radius:12px;
    background:#fff; color:#000; font-family:inherit; font-size:13px; font-weight:700;
  }
  .alerte-partage .secondaire{
    height:38px; padding:0 15px; border-radius:12px;
    background:rgba(255,255,255,0.08); border:0.5px solid var(--border);
    color:var(--label-2); font-family:inherit; font-size:13px; font-weight:650;
  }

  .icon-pill{
    width:46px; height:46px; border-radius:50%; display:flex; align-items:center; justify-content:center; flex-shrink:0;
    background:rgba(255,255,255,0.10); -webkit-backdrop-filter:blur(24px) saturate(180%); backdrop-filter:blur(24px) saturate(180%);
    border:0.5px solid rgba(255,255,255,0.18); color:var(--label);
    box-shadow:0 8px 28px rgba(0,0,0,0.40), 0 2px 8px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.12);
    transition: transform 0.18s cubic-bezier(0.34,1.56,0.64,1), background 0.2s;
  }
  .icon-pill:active{ transform:scale(0.88); background:rgba(255,255,255,0.2); }
  .icon-pill svg{ width:20px; height:20px; }

  /* Le bas réserve exactement la place de la barre d'onglets : sa hauteur, son
     décalage, et un peu d'air. Rien de plus — c'est constant, quel que soit le
     nombre de dossiers, puisque la barre ne change pas de taille. Le contenu,
     lui, pousse naturellement. */
  /* La barre du bas mesure 54,5 px et flotte à 20 px du bord : il faut dégager
     au moins 75 px, plus une marge d'air. Le compte était trop juste, et le
     dernier bloc — le bandeau de lecture, par exemple — passait dessous. */
  .screen{
    display:none;
    /* ═══ 74 AU LIEU DE 92 ═══

       La barre du haut occupe 16 px de marge plus 56 de pilule, soit 72. Les
       92 px laissaient donc VINGT pixels de vide sous elle, alors que le reste
       de l'app respire par des marges de 14 à 20.

       La barre du haut mesure 72 px — 16 de marge et 56 de pilule. Les deux
       points ont disparu avec le débord : c'est le bord du panneau voisin qui
       annonce désormais qu'il y en a un. Plus quinze de jeu. */
    padding:87px 20px calc(86px + max(20px, env(safe-area-inset-bottom)) + 16px);
  }

  /* La page d'analyse respire davantage : c'est une page qu'on lit, pas une
     liste qu'on parcourt. Quatre pixels de plus de chaque côté, et de l'espace
     entre les blocs. */
  /* Aucun retrait particulier, aucune compensation : l'analyse garde les 20 px
     de `.screen`, et sa carte commence exactement où commence celle de la page
     des procédures. Les bords s'alignent d'une page à l'autre. */
  /* `!important` parce que la règle de base de `.an-tete` est déclarée plus bas
     dans la feuille et l'emporterait sinon à égalité de spécificité. */
  /* Une section suit un bouton « voir plus » : 26 px suffisent, 38 creusaient un
     trou. La première section n'a ni filet ni marge, elle est en haut de page. */
  #p-global-analyse .an-tete{ margin-top:26px !important; padding-top:22px !important; }
  /* La première section n'a ni filet ni marge : elle est en haut de page.
     `:first-of-type` ne fonctionne pas ici — les `.an-tete` ne sont pas les
     premiers `div` de l'écran. On la désigne donc par sa position réelle. */
  #p-global-analyse .an-gain + .an-tete{
    margin-top:6px !important; padding-top:0 !important; border-top:none !important;
  }
  /* La barre flottante mesure 66 px : le bas de page doit la dépasser, sinon la
     dernière ligne se lit à travers le verre. */
  /* L'ESPACE DU HAUT, RAMENÉ À QUINZE PIXELS.

     La carte du logo s'arrête cinq pixels plus haut sur cette page que sur les
     autres — elle n'y porte pas le même contenu. Le retrait commun de 87 px y
     laissait donc VINGT pixels de vide au lieu de quinze.

     82 rétablit la mesure, et rapproche du même coup le bouton d'information de
     la carte : c'est le premier élément de la page, il se cale sur elle. */
  /* 87 px, comme toutes les autres. L'Analyse forçait 82 : cinq pixels plus
     haut, ce qui se voit en passant d'un onglet à l'autre — le titre saute.
     Rien ne justifiait l'exception. */
  #p-global-analyse{
    padding-bottom:calc(110px + max(20px, env(safe-area-inset-bottom))) !important;
  }
  #p-membre .an-tete{ margin-top:30px !important; padding-top:22px !important; }
  /* 0,38 s, comme les deux autres arrivées. Trois durées coexistaient pour le
     même geste — 0,55, 0,38 et 0,34 — et la différence se sentait en passant
     d'une page à l'autre : certaines paraissaient plus lourdes. */
  .screen.active{ display:block; animation: screenIn 0.38s cubic-bezier(0.32,0.72,0,1); }

  /* ═══ L'ÉCRAN QUI NAÎT DE LA CARTE TOUCHÉE ═══

     L'ancienne entrée montait de 18 px : douce, mais rien ne reliait l'écran à
     ce qu'on venait de toucher. On ne savait pas d'où il venait, donc le bouton
     retour paraissait arbitraire.

     Ici l'écran grandit DEPUIS la carte : son point d'origine est la position
     réelle de celle-ci, mesurée au moment du clic et passée en variables. Sans
     cette mesure, l'agrandissement partirait toujours du même endroit — juste
     pour la carte du milieu, faux pour toutes les autres. */
  .screen.active.nait{
    /* 0,38 s comme partout ailleurs. 0,46 se sentait plus lent — et un écran
       qui met plus longtemps à venir donne l'impression d'un chargement. */
    animation:ecranNait 0.38s cubic-bezier(0.32,0.72,0,1);
    /* Le point d'origine reste celui de la carte touchée : à cette amplitude il
       ne se voit plus vraiment, mais il ne coûte rien et donne au mouvement une
       direction plutôt qu'un simple gonflement. */
    transform-origin:var(--ox, 50%) var(--oy, 40%);
  }

  /* C'ÉTAIT ÇA, LA DEUXIÈME ANIMATION.

     Les cartes de la liste ont leur propre entrée — `cardIn`, `cardSlideIn`.
     Elles se déclenchaient PENDANT que l'écran grandissait : on voyait deux
     mouvements superposés, l'écran qui naît et les cartes qui montent dedans.

     Pendant la naissance, l'écran bouge en bloc. Son contenu ne bouge pas. */
  .screen.nait .sop-card,
  .screen.nait .emp-row,
  .screen.nait .cat-cell,
  .screen.nait .proc-rich-card,
  .screen.nait .slide-in,
  .screen.nait .contenu-entre > *,
  .screen.nait .fm-lg,
  .screen.nait .an-lig{
    animation:none !important;
  }
  /* SAUF UNE CARTE QUI S'EN VA.

     Les règles ci-dessus coupent toute animation de contenu pendant qu'un écran
     naît ou se fond — c'est ce qui évite deux mouvements superposés. Mais la
     classe `nait` reste posée jusqu'au changement d'écran suivant, et elle
     tuait donc aussi le repli d'une carte supprimée : la procédure disparaissait
     d'un coup, sans qu'on la voie partir.

     Le repli est le seul mouvement qu'on déclenche APRÈS coup, en réponse à un
     geste. Il doit passer. */
  .screen.nait .carte-part,
  .screen.fondu .carte-part{
    animation:carteSeReplie 0.44s cubic-bezier(0.4,0,0.2,1) forwards !important;
  }
  /* ═══ LE CHANGEMENT D'ONGLET ═══
     Un fondu, rien d'autre. 180 ms : assez pour que l'œil enregistre que la
     page a changé, trop court pour qu'on attende. Aucun déplacement — un
     onglet ne vient de nulle part, il remplace. */
  /* Le fondu net de 120 ms était trop sec : la page apparaissait d'un coup,
     sans qu'on la voie arriver. On garde le principe — aucun déplacement, un
     onglet ne vient de nulle part — mais on lui donne du temps et une entrée.

     260 ms, et l'écran arrive d'un demi-pas en arrière, à 98,5 %. Ce n'est pas
     un mouvement : c'est une profondeur. L'œil la lit sans pouvoir la nommer.

     La courbe part vite et finit lentement : l'essentiel du chemin est fait
     dans le premier tiers, de sorte que la page paraît réactive tout en
     s'installant en douceur. */
  /* ═══ APPARAÎTRE, PUIS GRANDIR ═══

     Les deux ne vont pas à la même vitesse, et c'est tout l'effet : la page est
     déjà entièrement visible au tiers du chemin, mais elle continue de grandir.
     On ne la voit donc jamais pâle — on la voit arriver.

     LE DOSAGE COMPTE PLUS QUE LE PRINCIPE. L'échelle partait de 0,93 : à chaque
     onglet le grossissement se remarquait, et on finissait par regarder
     l'animation au lieu de la page. À 0,965 il est présent, et jamais commenté.

     340 ms — plus long, mais le mouvement étant plus petit, l'ensemble paraît
     plus calme, pas plus lent.

     Les deux espaces partagent cette durée. L'Équipe a eu 150 ms un moment :
     trop court, la page ne paraissait plus arriver mais sauter — on y lit un
     défaut d'affichage plutôt qu'une transition. */
  .screen.fondu{ animation:ecranFondu 0.38s cubic-bezier(0.32,0.72,0,1); }
  @keyframes ecranFondu{
    0%  { opacity:0; transform:scale(0.975); }
    30% { opacity:1; }
    100%{ opacity:1; transform:none; }
  }

  /* Pendant le fondu, le contenu ne rejoue pas sa propre entrée : deux
     animations superposées feraient exactement ce qu'on cherche à éviter. */
  .screen.fondu .sop-card,
  .screen.fondu .emp-row,
  .screen.fondu .cat-cell,
  .screen.fondu .proc-rich-card,
  .screen.fondu .reg-groupe,
  .screen.fondu .an-bloc,
  .screen.fondu .hero{ animation:none !important; }

  /* ═══ LE MÊME GESTE QUE TOUTES LES AUTRES ARRIVÉES ═══

     L'écran « naissait » de la carte touchée : il partait à 32 % de sa taille,
     coins arrondis, et se dépliait. C'était joliment trouvé, mais c'était le
     SEUL endroit de l'app à faire ça — ouvrir un dossier ne ressemblait à rien
     d'autre.

     Une animation particulière se remarque ; remarquée cent fois par jour, elle
     devient une attente. Elle rejoint donc les huit autres : 0,975 à 1.

     Le nom et l'origine du mouvement restent — la carte touchée sert toujours
     de point de départ au navigateur — mais l'amplitude est celle de tout le
     reste. */
  @keyframes ecranNait{
    0%  { opacity:0; transform:scale(0.975); }
    30% { opacity:1; }
    100%{ opacity:1; transform:none; }
  }

  /* Le mouvement se coupe si le système demande moins d'animation. */
  @media (prefers-reduced-motion: reduce){
    .screen.fondu{ animation:none; }
    .screen.active.nait{ animation:none; }
  }
  .app-shell-in{ animation: appShellIn 0.65s cubic-bezier(0.22,1,0.36,1); }
  @keyframes appShellIn{
    0%  { opacity:0; transform:scale(0.975); }
    30% { opacity:1; }
    100%{ opacity:1; transform:none; }
  }

  /* ═══════════════════════════════════════════════════════════════════════
     UNE SEULE ARRIVÉE, PARTOUT

     Neuf animations différentes disaient la même chose : « une surface
     apparaît ». L'une montait de 18 px en se dé-floutant, l'autre glissait de
     côté, une troisième naissait à 32 % de sa taille. Rien ne les reliait, et
     l'app changeait de caractère d'un écran à l'autre.

     Elles partagent maintenant le même corps : opacité de 0 à 1, échelle de
     0,975 à 1. L'échelle est volontairement FAIBLE — on sent le mouvement sans
     le voir. À 94 %, il se remarque ; et une animation qu'on remarque à la
     centième fois devient une attente.

     Les noms restent, et les durées propres à chaque endroit aussi : c'est le
     GESTE qui est commun, pas le rythme. Une fenêtre peut s'ouvrir plus vite
     qu'une page sans cesser d'être la même animation.
     ═══════════════════════════════════════════════════════════════════════ */
  @keyframes screenIn{
    0%  { opacity:0; transform:scale(0.975); }
    30% { opacity:1; }
    100%{ opacity:1; transform:none; }
  }
  .same-as-title-in{ animation: screenIn 0.38s cubic-bezier(0.32,0.72,0,1) both; }
  .greeting{ font-size:14px; font-weight:600; color:var(--label-2); margin-top:6px; }
  /* La marge haute de 6 px descendait le titre sous celui des pages d'onglet.
     `letter-spacing` aligné sur `.page-tete h1` : -0,04 et non -0,02. */
  /* 24 px pour TOUS les titres de page, sans exception.

     21 était un peu juste : un titre doit se distinguer du texte courant, qui
     fait 15 à 16 px. Trois points d'écart ne suffisaient pas à établir la
     hiérarchie.

     L'approche reste à −0,03 em. À −0,04, valeur d'origine, « Codes
     d'invitation » se tassait. */
  h1.pagehead{ font-size:24px; font-weight:700; letter-spacing:-0.03em; margin:0 0 2px; }
  .detail-header h1.pagehead{ margin:0; }

  /* `pagehead-row` porte le titre ET un bouton à droite — « Gérer l'équipe »
     et son « + ». Il gardait une marge haute qui descendait le titre de 34 px
     sous celui des autres pages. */
  .pagehead-row{ margin-top:0 !important; }
  .pagehead-row h1.pagehead{ margin:0; }
  .subhead{ font-size:14px; color:var(--label-2); margin-bottom:18px; line-height:1.35; }

  /* ═══ Entreprises de l'utilisateur ═══ */
  .ent-ligne{
    display:flex; align-items:center; gap:12px; padding:14px 15px; margin-bottom:8px;
    background:var(--bg-card); border:0.5px solid var(--border); border-radius:14px;
    transition:background 0.2s;
  }
  .ent-ligne:not(.actuelle){ cursor:pointer; }
  .ent-ligne:not(.actuelle):active{ background:rgba(255,255,255,0.10); }
  .ent-ligne.actuelle{ border-color:rgba(48,209,88,0.35); }
  .ent-info{ flex:1; min-width:0; }
  .ent-nom{ font-size:15px; font-weight:650; letter-spacing:-0.02em; }
  .ent-role{ font-size:11.5px; color:var(--label-3); margin-top:2px; }
  .ent-marque{
    width:24px; height:24px; border-radius:50%; flex-shrink:0; color:#06210F;
    background:var(--green); display:flex; align-items:center; justify-content:center;
  }
  .ent-marque svg{ width:13px; height:13px; }
  .ent-basculer{
    font-size:12.5px; font-weight:650; color:var(--blue); flex-shrink:0;
  }

  /* ═══ Réordonner les étapes au doigt ═══
     Les deux flèches obligeaient à taper plusieurs fois pour déplacer une
     étape de trois rangs. Un appui long la soulève, on la pose où l'on veut. */
  .step-edit-item:active .step-grip, .step-edit-item.attrape
  /* ═══ Les étapes manuelles, en fil ═══
     Un trait relie les numéros et dit l'ordre sans qu'on ait à le lire. Une
     procédure EST une suite : la forme le montre au lieu de l'énoncer. */

  /* Le choix du type d'enregistrement. Deux blocs pleine largeur plutôt que
     deux segments : les libellés font une ligne et demie chacun. */
  /* Ce que l'IA analyse, annoncé au lieu d'être demandé. */
  .ia-ecoute{
    padding:13px 15px; border-radius:15px; margin-bottom:14px;
    background:var(--bg-card); border:0.5px solid var(--border);
  }
  .ia-ecoute .tt{
    font-size:11px; font-weight:700; color:var(--label-3);
    text-transform:uppercase; letter-spacing:0.06em; margin-bottom:8px;
  }
  .ia-ecoute .lg{ display:flex; align-items:center; gap:10px; padding:5px 0; font-size:13px; }
  .ia-ecoute .lg svg{ width:18px; height:18px; color:rgba(255,255,255,0.62); flex-shrink:0; }
  .ia-ecoute .lg span{ color:var(--label-2); line-height:1.4; }
  .ia-ecoute .lg b{ color:#fff; font-weight:650; }

  .ai-type{ display:flex; flex-direction:column; gap:8px; margin-bottom:14px; }
  .ai-type button{
    display:flex; flex-direction:column; gap:3px; width:100%;
    padding:13px 16px; border-radius:16px; text-align:left;
    background:var(--bg-card); border:0.5px solid var(--border);
    color:#fff; font-family:inherit;
  }
  .ai-type button .t{ font-size:14.5px; font-weight:650; letter-spacing:-0.02em; }
  .ai-type button .s{ font-size:12px; color:var(--label-2); line-height:1.35; }
  .ai-type button.on{ background:#fff; border-color:#fff; color:#000; }
  .ai-type button.on .s{ color:rgba(0,0,0,0.58); }
  .ai-type button:active{ opacity:0.75; }

  /* ═══ LA MARQUE DE L'IA ═══

     Un anneau de lumière, pas une icône. Il ne représente rien — ni cerveau,
     ni robot, ni étoile —, il indique. C'est le parti d'Apple : leur IA n'a
     pas de logo, elle a une lueur.

     Une seule forme à trois tailles : pastille sur une carte, icône dans un
     bouton, grand format pendant l'attente. Le trait est proportionnellement
     plus épais en petit — sans ça, le creux devient un trou dès 17 px.

     Teintes ardoise : un bleu si sombre qu'il passe pour du gris. Assez proche
     du noir et blanc de l'app pour ne pas jurer, assez distinct pour qu'on
     apprenne que cette lueur veut dire « l'IA travaille ». */
  /* Trois quarts de blanc, un éclat bleu qui passe — comme un reflet sur du
     métal poli. La couleur n'affleure que sur un quart du tour : elle donne le
     mouvement sans que l'anneau devienne bleu. */
  .ia-fig{
    --blanc:#FFFFFF; --bleu:#FFC46B;
    position:relative; display:grid; place-items:center; flex-shrink:0;
  }
  .ia-fig .lum{
    position:absolute; inset:0; border-radius:50%;
    background:conic-gradient(from 0deg,
      var(--blanc) 0deg, var(--blanc) 190deg, var(--bleu) 280deg, var(--blanc) 360deg);
    animation:iaTourne 3.6s linear infinite;
  }
  /* Le centre est VIDE, pas peint. Un disque de la couleur du fond marchait
     tant que le fond ne bougeait pas — mais sur un bouton blanc, une carte
     grise ou une image, il fallait deviner la teinte, et ça se voyait.
     Un masque évide réellement le milieu : ce qui est derrière transparaît. */

  /* Le halo se déforme DERRIÈRE l'anneau, qui reste net. Chez Apple le
     mouvement est toujours dans la lueur, jamais dans l'objet. */
  .ia-fig .halo{
    /* Serré contre l'anneau : débordant, il faisait une auréole qui attirait
       l'œil plus que la forme elle-même. */
    position:absolute; inset:-1.5px; border-radius:50%;
    filter:blur(2.5px); opacity:0.55;
    background:conic-gradient(from 180deg, transparent 0 50%, var(--bleu) 72%, var(--blanc) 90%, transparent 100%);
    animation:iaGalet 6.4s ease-in-out infinite reverse, iaTourne 5.2s linear infinite;
  }

  /* 112 px prenait la moitié de la carte. À 78, l'anneau reste le point de
     mire sans écraser le texte qui le suit — c'est lui qu'on lit. */
  .ia-fig.g{ width:78px; height:78px; --trait:9px; }
  .ia-fig.m{ width:26px;  height:26px;  --trait:5px; }
  .ia-fig.s{ width:15px; height:15px; --trait:2.6px; }

  /* Sur une carte de procédure, l'anneau se pose à côté d'un titre : il doit se
     voir sans peser. Plus petit ET plus fin — les deux ensemble, sinon un trait
     épais sur un petit cercle donne une pastille, pas un anneau. */
  .etat-proc .ia-fig.s{ width:13px; height:13px; --trait:2.1px; }
  .cat-recent-item .etat-proc .ia-fig.s{ width:11px; height:11px; --trait:1.8px; }

  .ia-fig .lum, .ia-fig .halo{
    -webkit-mask:radial-gradient(farthest-side, transparent calc(100% - var(--trait)), #000 0);
    mask:radial-gradient(farthest-side, transparent calc(100% - var(--trait)), #000 0);
  }

  /* En petit, le halo flouté ne ferait qu'une bavure. */
  .ia-fig.m .halo, .ia-fig.s .halo{ display:none; }


  @keyframes iaTourne{ to{ transform:rotate(360deg); } }
  @keyframes iaGalet{
    0%,100%{ border-radius:50% 50% 50% 50%; }
    25%{ border-radius:58% 42% 46% 54%; }
    50%{ border-radius:44% 56% 58% 42%; }
    75%{ border-radius:52% 48% 40% 60%; }
  }

  /* Le chiffre au centre du grand anneau. */
  /* Dans une carte de choix, la marque occupe la place de l'ancienne icône. */
  .mode-choice .ia-fig{ margin-bottom:2px; }
  .bande-ia .ia-fig{ flex-shrink:0; }

  /* Sur un bouton blanc, un anneau blanc n'existe pas : il ne resterait qu'une
     virgule bleue qui tourne. Le blanc y devient un bleu très pâle et le bleu
     se fonce — c'est le même dessin, transposé pour rester lisible. */
  .btn:not(.ghost) .ia-fig, .ia-fig.clair{
    --blanc:#FFE6C2; --bleu:#C77A0A;
  }

  .ia-fig.g .pct{
    position:relative; z-index:2; font-size:19px; font-weight:750;
    letter-spacing:-0.04em; font-variant-numeric:tabular-nums;
  }

  .man-lbl{
    font-size:12.5px; font-weight:650; color:var(--label-3); margin:24px 0 10px;
    display:flex; align-items:center; justify-content:space-between;
  }
  .man-lbl .n{ font-weight:600; }
  .man-champ{
    width:100%; background:rgba(255,255,255,0.05); border:0.5px solid var(--border);
    border-radius:14px; padding:14px 14px; color:#fff; font-family:inherit;
    font-size:15px; font-weight:500; letter-spacing:-0.02em;
  }
  .man-champ::placeholder{ color:var(--label-3); }
  .man-champ:focus{ outline:none; border-color:rgba(255,179,64,0.55); }

  /* L'écran de saisie respire un peu plus que les fiches de lecture : on y
     revient corriger, ajouter, supprimer — il faut de la place pour viser. */
/* Le fil se termine par « Ajouter une étape ». Les boutons qui suivent
     — tout effacer, publier — n'appartiennent plus à la liste : sans espace,
     « Ajouter une étape » et « Annuler » se lisaient comme deux choix du même
     groupe. Le blanc dit où la liste s'arrête. */
  .man-fil{ margin-bottom:8px; }

    .man-fil{ position:relative; padding-left:44px; margin-top:26px; }
  /* Le trait s'arrête avant le dernier maillon : il relie, il ne dépasse pas. */
  .man-fil::before{
    content:''; position:absolute; left:17px; top:8px; bottom:34px; width:1.5px;
    background:linear-gradient(rgba(255,255,255,0.16), rgba(255,255,255,0.04));
  }
  .man-fil .step-edit-item{
    position:relative; background:none; border:none; border-radius:0;
    padding:0 0 26px; margin:0;
  }
  .man-fil .step-num-dess{ position:absolute; left:-44px; top:-4px; width:33px; height:33px; }
  .man-fil .step-num-dess svg{ width:33px; height:33px; display:block; }
  .man-fil textarea{
    width:100%; background:none; border:none; padding:0; resize:none;
    color:#fff; font-family:inherit; font-size:14.5px; line-height:1.55;
    font-weight:500; letter-spacing:-0.02em;
  }
  .man-fil textarea:focus{ outline:none; }
  .man-fil textarea::placeholder{ color:var(--label-3); }
  .man-fil .step-bas{ display:flex; align-items:flex-end; gap:11px; margin-top:12px; }

  /* Sur l'écran de montage, la durée passe SOUS le texte et prend la ligne à
     elle seule. Le texte retrouve toute la largeur : c'est lui qu'on relit. */
  /* Le fil du montage suivait une ligne horizontale : vignette, texte, durée,
     corbeille. Sur un téléphone, le texte héritait de moins d'un tiers de la
     largeur — « Entrer la transaction » s'écrivait sur huit lignes.

     Il suit désormais la construction de la saisie manuelle : numéro à gauche,
     texte pleine largeur, durée en dessous. Ces règles arrivent après les
     anciennes et les remplacent. */
  .man-fil .etape-montage{
    display:block; padding:0 0 26px; border-radius:0;
    background:none; border:none; gap:0;
  }
  .man-fil .etape-montage .vig{ display:none; }
  .man-fil .etape-montage.sel{ background:none; border-color:transparent; }
  .man-fil .etape-montage textarea{ font-size:14.5px; font-weight:500; line-height:1.55; }

  .etape-montage .step-bas{ align-items:center; margin-top:9px; }
  .etape-montage .badge.extrait{ margin-top:0; }
  .etape-montage .sup{ margin-left:auto; }

  /* Dans le fil, la photo est un carré nu — sans son libellé à côté. Le cadre
     dit déjà ce qu'il attend, et la ligne reste courte. */
  /* La croix de retrait. Elle ne s'affiche que sur une vignette pleine : sur un
     cadre vide, elle n'aurait rien à retirer et brouillerait le geste d'ajout. */
  .step-img{ position:relative; }
  .img-oter{
    position:absolute; top:-7px; right:-7px; width:22px; height:22px;
    border-radius:50%; border:1.5px solid var(--bg); background:var(--red);
    color:#fff; font-family:inherit; font-size:14px; font-weight:700; line-height:1;
    display:flex; align-items:center; justify-content:center; padding:0; z-index:3;
  }
  .img-oter:active{ opacity:0.7; }

  .man-fil .step-img{ margin-top:0; }
  .man-fil .step-img-vignette{ width:78px; height:78px; border-radius:12px; }
  .man-fil .step-img-vignette svg{ width:22px; height:22px; }
  .man-fil .img-toucher{ display:none; }
  .man-fil .del{ margin-left:auto; }
  .man-fil .del{ margin-left:auto; }

  /* Le dernier maillon : le geste se comprend avant le texte. */
  /* Le fil de l'écran vidéo : même construction, avec la vignette à la place de
     la photo. */
  .man-fil .etape-montage .vig{
    width:78px; height:44px; border-radius:9px; overflow:hidden; flex-shrink:0;
    background:rgba(255,255,255,0.05); border:0.5px solid var(--border);
  }
  .man-fil .etape-montage .vig canvas{ width:100%; height:100%; object-fit:cover; display:block; }
  .man-fil .etape-montage.sel .step-num-dess{ filter:drop-shadow(0 0 7px rgba(255,179,64,0.5)); }
  .man-fil .sup{ margin-left:auto; background:none; border:none; padding:0; color:var(--label-3); }
  .man-fil .sup svg{ width:17px; height:17px; }

  /* La bande bleue : ce que l'IA a fait, et ce qu'on attend de vous. Elle ne
     dit pas « c'est prêt » mais « relisez » — c'est le gérant qui sait. */
  .bande-ia{
    display:flex; align-items:flex-start; gap:10px; padding:11px 13px;
    border-radius:14px; margin-top:14px; font-size:12.5px; line-height:1.45;
    color:var(--label-2);
    background:rgba(255,179,64,0.10); border:0.5px solid rgba(255,179,64,0.24);
  }
  .bande-ia b{ color:#fff; font-weight:650; }
  .bande-ia .p{
    width:7px; height:7px; border-radius:50%; background:var(--blue);
    flex-shrink:0; margin-top:5px;
  }

  /* L'étape qu'on vient d'ajouter arrive en glissant depuis le fil, avec un
     léger dépassement. Seules les DEUX propriétés que le processeur graphique
     gère seul sont animées — aucun recalcul de mise en page, donc aucun à-coup
     sur une liste de quinze étapes. */
  @keyframes etapeArrive{
    from{ opacity:0; transform:translateY(-8px) scale(0.97); }
    to{ opacity:1; transform:none; }
  }
  .man-fil .step-edit-item.neuve{
    animation:etapeArrive 0.42s cubic-bezier(0.34,1.42,0.5,1) both;
  }
  /* Le numéro arrive juste après, comme s'il se posait sur le fil. */
  .man-fil .step-edit-item.neuve .step-num-dess{
    animation:etapeArrive 0.36s cubic-bezier(0.34,1.56,0.64,1) 0.08s both;
  }

  /* Le bouton d'annulation : une icône seule, plus étroite qu'un bouton pleine
     largeur — c'est un geste ponctuel, pas une action principale. */
  .man-annuler-geste{
    width:52px !important; margin-left:auto; margin-right:auto;
    display:flex; align-items:center; justify-content:center; padding:0;
  }
  .man-annuler-geste svg{ width:19px; height:19px; }
  .man-annuler-geste:disabled{ opacity:0.3; }

  /* La zone de photos. Vide, c'est un dépôt en pointillés ; remplie, c'est une
     liste de pages qu'on réordonne. */
  .doc-photos{ position:relative; margin-top:10px; }
  .doc-photos input[type=file]{
    position:absolute; inset:0; opacity:0; width:100%; height:100%; z-index:2;
  }
  .doc-photos.remplie input[type=file]{ display:none; }
  /* La zone de dépôt du document : la même que celle de la vidéo. */
  /* Le bouton porte l'anneau, puis la coche. Même famille que celui de la page
     vidéo — mais plein, car ici c'est l'action principale. */
  .doc-generer{ display:flex; align-items:center; justify-content:center; gap:10px; }
  .doc-generer .ia-mot{ flex-shrink:0; }
  .doc-generer > span:last-child{
    transition:opacity 0.25s ease, max-width 0.35s cubic-bezier(0.32,0.72,0,1);
    max-width:280px; overflow:hidden; white-space:nowrap;
  }
  /* Pendant le travail : l'anneau seul, centré. */
  .doc-generer.travaille > span:last-child{ opacity:0; max-width:0; }
  .doc-generer.travaille{ gap:0; }
  .doc-generer .ia-coche{ display:none; width:24px; height:24px; flex-shrink:0; }
  .doc-generer .ia-coche svg{ width:24px; height:24px; display:block; }
  .doc-generer:disabled .ia-mot{ opacity:1; }
  /* Le bouton reste à pleine lumière pendant qu'il travaille.

     `.btn[disabled]` le passait à 50 % d'opacité — c'est juste pour un bouton
     qu'on ne peut PAS actionner, mais faux ici : il travaille. L'anneau qui
     tourne dit déjà qu'il est occupé ; l'assombrir en plus donne l'impression
     que le clic n'a pas pris. */
  .doc-generer.travaille[disabled],
  .doc-generer.fini[disabled]{ opacity:1; }
  .doc-generer.fini .ia-mot{ display:none; }
  .doc-generer.fini .ia-coche{
    display:block;
    animation:cocheArrive 0.45s cubic-bezier(0.34,1.5,0.64,1) both;
  }
  /* La coche PREND LA PLACE de l'anneau, elle ne se pose pas dessus.

     C'était le défaut : la coche apparaissait, l'anneau restait à tourner
     dessous, et l'on voyait deux cercles superposés avec un point brillant qui
     tournait encore autour. Trois formes pour dire une seule chose — c'est
     fini. */
  .doc-generer.fini .ia-roue,
  .doc-generer.fini .ia-mot{ opacity:0; transform:scale(0.5); }

  /* ═══ L'ÉCRAN VIDÉO ═══
     La légende vit HORS du cadre : elle explique, elle ne se touche pas. Dedans,
     il n'y a que la vidéo — ou son absence. */
  /* ═══ LA COCHE DANS LE GRAND ANNEAU ═══
     À la fin, le pourcentage s'efface et une coche prend sa place au centre.
     L'anneau reste — c'est lui qui devient le signe de l'achèvement, pas un
     autre dessin qui viendrait le remplacer. */
  /* Le passage de la zone de dépôt à l'écran d'attente. Sans mouvement, la
     page saute : on ne comprend pas qu'on vient de lancer quelque chose. */
  #ai-progress-card, #doc-attente-card{
    animation:attenteArrive 0.42s cubic-bezier(0.32,0.72,0,1) both;
  }
  @keyframes attenteArrive{
    0%  { opacity:0; transform:scale(0.975); }
    30% { opacity:1; }
    100%{ opacity:1; transform:none; }
  }

  .ia-fig .ia-coche-g{
    position:absolute; inset:0; display:none;
    align-items:center; justify-content:center;
  }
  .ia-fig .ia-coche-g svg{ width:44%; height:44%; display:block; }
  .ia-fig.fini .pct{ opacity:0; }
  .ia-fig.fini .ia-coche-g{
    display:flex;
    animation:cocheArrive 0.45s cubic-bezier(0.34,1.5,0.64,1) both;
  }
  .ia-fig .pct{ transition:opacity 0.2s ease; }
  /* L'anneau cesse de tourner : ce qui tourne dit « ça travaille ». */
  .ia-fig.fini .lum{ animation:none; }

  /* À la ligne, pas au centre : c'est un titre de section, pas une annonce. */
  .ai-legende{
    text-align:left; margin-bottom:10px;
    transition:opacity 0.25s ease, max-height 0.3s ease, margin 0.3s ease;
    max-height:90px; overflow:hidden;
  }
  /* Une fois la vidéo là, la légende n'a plus rien à dire. */
  .ai-legende.cache{ opacity:0; max-height:0; margin-bottom:0; }
  .ai-legende .t{ display:block; font-size:17px; font-weight:700; letter-spacing:-0.03em; }

  .ai-vide{
    display:block; width:100%; aspect-ratio:16/9; border-radius:16px;
    background:rgba(255,255,255,0.02);
    border:1.5px dashed rgba(255,255,255,0.16);
  }
  /* De l'air entre la vidéo et ce que l'IA analyse. */
  #ai-upload-card .ia-ecoute{ margin-top:20px; }

  .doc-zone{
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    text-align:center; padding:30px 22px; border-radius:18px;
    border:1.5px dashed rgba(255,255,255,0.16); background:rgba(255,255,255,0.02);
    margin-bottom:14px;
  }
  .doc-zone .ic{
    width:62px; height:62px; border-radius:19px; margin-bottom:14px;
    display:grid; place-items:center;
    background:rgba(255,255,255,0.05); border:0.5px solid var(--border);
    color:rgba(255,255,255,0.72);
  }
  .doc-zone .ic svg{ width:29px; height:29px; }
  .doc-zone .t{ font-size:17px; font-weight:700; letter-spacing:-0.03em; }
  .doc-zone .s{
    font-size:12.5px; color:var(--label-3); line-height:1.5;
    margin-top:5px; max-width:240px;
  }
  /* Les trois entrées rappelées en petit : discret, mais présent. */
  .doc-zone .trois{
    display:flex; align-items:center; justify-content:center; gap:16px; margin-top:16px;
  }
  /* Les trois entrées sont des BOUTONS : chacune ouvre sa voie. */
  /* Le bloc choisi ARRIVE : sans mouvement, on ne remarque pas qu'un élément
     vient d'apparaître plus bas dans la page. */
  .doc-bloc{ animation:blocArrive 0.34s cubic-bezier(0.32,0.72,0,1) both; }
  @keyframes blocArrive{
    0%{ opacity:0; transform:translateY(-8px); max-height:0; }
    100%{ opacity:1; transform:none; max-height:900px; }
  }

  .doc-zone .doc-voie{
    display:flex; flex-direction:column; align-items:center; gap:6px;
    padding:9px 12px; border-radius:12px; border:0.5px solid transparent;
    background:none; color:var(--label-3);
    font-family:inherit; font-size:11px; font-weight:650;
  }
  .doc-zone .doc-voie svg{ width:20px; height:20px; color:rgba(255,255,255,0.5); }
  .doc-zone .doc-voie.on{
    background:rgba(255,255,255,0.09); border-color:var(--border); color:#fff;
  }
  .doc-zone .doc-voie.on svg{ color:#fff; }
  .doc-zone .doc-voie:active{ transform:scale(0.94); }

  .doc-zone .trois > span{
    display:flex; flex-direction:column; align-items:center; gap:6px;
    font-size:11px; color:var(--label-3); font-weight:650;
  }
  .doc-zone .trois svg{ width:20px; height:20px; color:rgba(255,255,255,0.5); }

  .doc-photos-vide{
    border:1.5px dashed rgba(255,255,255,0.16); border-radius:18px;
    padding:24px 18px; text-align:center; background:rgba(255,255,255,0.025);
  }
  .doc-photos-vide .d{ display:block; width:46px; height:42px; margin:0 auto 10px; }
  .doc-photos-vide .d svg{ width:46px; height:42px; }
  .doc-photos-vide b{ display:block; font-size:14.5px; font-weight:650; }
  .doc-photos-vide span{
    display:block; font-size:12.5px; color:var(--label-3); margin-top:4px; line-height:1.45;
  }

  .doc-page{
    display:flex; align-items:center; gap:12px; padding:9px 10px;
    border-radius:14px; margin-bottom:8px;
    background:var(--bg-card); border:0.5px solid var(--border);
    touch-action:none;
  }
  .doc-page .rg{
    width:26px; height:26px; border-radius:50%; flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
    background:rgba(255,255,255,0.06); border:0.5px solid var(--border);
    font-size:12px; font-weight:750;
  }
  .doc-page .vg{
    width:44px; height:44px; border-radius:10px; overflow:hidden; flex-shrink:0;
    background:#000; border:0.5px solid var(--border);
  }
  .doc-page .vg img{ width:100%; height:100%; object-fit:cover; display:block; }
  .doc-page .nm{
    flex:1; min-width:0; font-size:13px; color:var(--label-2);
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  .doc-page .oter{
    flex-shrink:0; border:none; background:none; color:var(--red);
    font-family:inherit; font-size:12.5px; font-weight:650; padding:6px 4px;
  }
  .doc-page.saisie{ opacity:0.55; transform:scale(0.98); }
  .doc-photo-plus{ margin-top:4px !important; }

  /* La dossier remonte sur la ligne du titre. Elle en dit le contexte, pas
     autre chose : la mettre en dessous lui donnait le poids d'une phrase. */
  .detail-header:has(+ .titre-cat){ margin-bottom:0; }
  .titre-cat{
    margin-top:-2px; margin-left:47px; font-size:13px;
    color:var(--label-3); font-weight:600;
  }

  .vid-ia{
    display:flex; align-items:center; justify-content:center; gap:9px;
    margin-top:14px !important;
  }
  .vid-ia svg{ width:19px; height:19px; flex-shrink:0; color:var(--blue); }
  .vid-ia:disabled{ opacity:0.55; }
  .vid-ia-note{
    font-size:12px; color:var(--label-3); line-height:1.5;
    margin-top:8px; text-align:center;
  }

  .man-plus{
    position:relative; display:flex; align-items:center; gap:0;
    background:none; border:none; padding:0; width:100%; text-align:left;
    color:var(--label-2); font-family:inherit; font-size:14.5px; font-weight:600;
  }
  .man-plus .d{ position:absolute; left:-44px; top:-5px; width:33px; height:33px; }
  .man-plus .d svg{ width:33px; height:33px; display:block; }
  .man-plus:active{ opacity:0.6; }

  .step-edit-item{ touch-action:pan-y; }
  /* L'étape soulevée : elle passe au-dessus, s'agrandit à peine et porte une
     ombre portée pour qu'on sente qu'elle a quitté la pile. */
  .step-edit-item.attrape{
    position:relative; z-index:20;
    background:rgba(255,255,255,0.13);
    border-color:rgba(255,255,255,0.4);
    box-shadow:0 14px 34px rgba(0,0,0,0.5);
    transform:scale(1.025);
    transition:box-shadow 0.2s, background 0.2s, border-color 0.2s;
  }
  .step-edit-item.attrape textarea{ pointer-events:none; }
  /* Les autres coulissent pour laisser la place. */
  .step-edit-item.decale{ transition:transform 0.22s cubic-bezier(0.32,0.72,0,1); }
  .step-liste-en-cours{ -webkit-user-select:none; user-select:none; }

  /* ═══ Procédure en cours d'analyse ═══
     Une roue qui tourne pendant que l'IA travaille, puis une coche verte
     jusqu'à ce que le gérant ouvre la procédure. C'est le seul endroit où il
     apprend que son analyse est terminée s'il a quitté l'écran. */
  .etat-proc{
    width:13px; height:13px; flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
  }
  .etat-proc svg{ width:19px; height:19px; display:block; }
  .etat-proc .rot{ animation:etatTourne 1.05s linear infinite; transform-origin:center; }
  @keyframes etatTourne{ to{ transform:rotate(360deg); } }
  .etat-proc .arc{
    stroke:#fff; stroke-width:2.4; stroke-linecap:round; fill:none;
    stroke-dasharray:40 60; opacity:0.9;
  }
  .etat-proc .fond-arc{ stroke:rgba(255,255,255,0.14); stroke-width:2.4; fill:none; }
  /* La coche est posée sur un rond de verre teinté de vert : le même langage
     que les cartes de l'app, plutôt qu'une pastille pleine. */
  /* La coche reprend le blanc de la roue qui la précède. Le vert annonçait un
     succès là où il n'y a qu'un achèvement — et surtout il ne ressemblait à
     rien de ce qui tournait une seconde plus tôt : on ne voyait pas que c'était
     la même chose, arrivée au bout. */
  /* Plus de pastille grise derrière : l'anneau de l'IA n'en a pas, celui-ci
     non plus. Le trait dessine la forme, rien ne la remplit. */
  /* La coche ne surgit pas : elle se DESSINE. Le cercle fait son tour, puis le
     trait se trace — exactement le geste de l'anneau qui se dévoile pendant
     l'analyse. Le passage de l'un à l'autre se lit comme une suite, pas comme
     le remplacement d'un signe par un autre. */
  .etat-proc.prete{ width:19px; height:19px; }
  .etat-proc.prete circle{
    stroke-dasharray:66; stroke-dashoffset:66;
    animation:iaCercleTrace 0.5s cubic-bezier(0.32,0.72,0,1) both;
    transform:rotate(-90deg); transform-origin:center;
  }
  .etat-proc.prete polyline{
    stroke-dasharray:14; stroke-dashoffset:14;
    animation:iaCocheTrace 0.28s cubic-bezier(0.4,0,0.2,1) 0.34s both;
  }
  @keyframes iaCercleTrace{ to{ stroke-dashoffset:0; } }
  @keyframes iaCocheTrace{ to{ stroke-dashoffset:0; } }
  .etat-proc.prete svg{ width:19px; height:19px; }
  /* Une analyse en panne se signale, mais sans crier : même gabarit que les
     autres indicateurs, seule la couleur change. */
  .etat-proc.souci{ animation:etatArrive 0.4s cubic-bezier(0.34,1.5,0.64,1) both; }
  .cat-recent-item .etat-proc.souci svg{ width:13px; height:13px; }
  @keyframes etatArrive{ from{ transform:scale(0.5); opacity:0; } to{ transform:scale(1); opacity:1; } }
  /* Une procédure en cours d'analyse n'est pas consultable : rien à ouvrir,
     ses étapes n'existent pas encore. On la montre estompée et sourde au
     toucher, plutôt que d'ouvrir une page vide. */
  .proc-en-cours{ opacity:0.72; }
  /* Une analyse en cours reste touchable : c'est le seul moyen de l'abandonner.
     Elle est simplement estompée pour montrer qu'elle n'est pas consultable. */
  .proc-en-cours-doux{ opacity:0.72; }

  /* ═══ L'étape que la vidéo est en train de montrer ═══
     Sans repère, on lance un extrait et on perd de vue à quel texte il
     correspond — surtout sur seize étapes, où la liste défile. Un contour bleu
     suffit : c'est un état, pas une action, donc ni fond plein ni gras. */
  /* La règle de base de `.detail-step` est déclarée plus bas et pose sa propre
     bordure : on écrit donc la bordure ENTIÈRE ici, pas seulement sa couleur,
     sinon la déclaration suivante l'écrase. */
  .detail-step.en-lecture{
    border:1.5px solid rgba(255,179,64,0.62) !important;
    background:rgba(255,179,64,0.09) !important;
  }
  .detail-step.en-lecture .n{
    background:rgba(255,179,64,0.22); color:#FFD199;
  }
  .detail-step.en-lecture .badge.ok{
    background:rgba(255,179,64,0.20); color:#FFD199;
  }

  /* L'image en tête de la fiche, et sur la carte. */
  /* Une photo de téléphone est souvent en portrait : à pleine largeur, elle
     occupait tout l'écran et il fallait faire défiler pour atteindre les étapes.
     On plafonne la hauteur et on recadre — l'image sert à reconnaître la
     procédure, pas à être contemplée. */
  /* Le cadre garde toujours la même hauteur ; l'image s'y inscrit ENTIÈRE, aussi
     grande que possible. `contain` plutôt que `cover` : on montrait auparavant un
     morceau recadré, ce qui coupait le haut et le bas d'une photo verticale. Une
     image qui représente la procédure doit se voir en entier. */
  /* Plus de cadre autour de l'image : le fond gris et le filet dessinaient une
     boîte dont l'image n'occupait qu'une partie, et on voyait la boîte avant la
     photo. Il ne reste que l'image, centrée, aux angles arrondis. */
  .analyse-couv{ margin-top:14px; display:flex; align-items:center; justify-content:center; }
  .analyse-couv img{
    max-width:100%; max-height:220px; width:auto; height:auto;
    display:block; border-radius:18px;
  }

  /* ═══ Les appareils ═══ */
  .app-ligne{
    display:flex; align-items:center; gap:12px; padding:12px;
    border-radius:15px; background:var(--bg-card); border:0.5px solid var(--border);
    margin-bottom:8px;
  }
  .app-ligne.moi{ border-color:rgba(255,179,64,0.45); background:rgba(255,179,64,0.08); }
  .app-ligne.revoque{ opacity:0.5; }
  .app-ligne .ic{
    width:36px; height:36px; border-radius:11px; flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
    background:rgba(255,255,255,0.08); border:0.5px solid rgba(255,255,255,0.14);
  }
  .app-ligne .ic svg{ width:19px; height:19px; }
  .app-ligne .tx{ flex:1; min-width:0; }
  .app-ligne .nm{ display:block; font-size:14px; font-weight:650; letter-spacing:-0.02em; }
  .app-ligne .st{ display:block; font-size:11.5px; color:var(--label-3); margin-top:2px; }
  .app-ligne .ici{
    display:inline-block; margin-left:7px; padding:2px 7px; border-radius:100px;
    background:rgba(255,179,64,0.20); color:#FFD199;
    font-size:9.5px; font-weight:750; text-transform:uppercase; letter-spacing:0.04em;
    vertical-align:1px;
  }
  .app-ligne .oter{
    border:none; background:rgba(255,255,255,0.08); color:var(--red);
    font-family:inherit; font-size:11.5px; font-weight:650;
    padding:7px 12px; border-radius:100px; flex-shrink:0;
  }

  /* ═══════════════════════════════════════════════════════════════════
     L'ANALYSE, ET LA FICHE D'UN MEMBRE

     Retenue d'Apple, langage des icônes de création. Un chiffre en grand, des
     listes nues séparées par un filet, et de la respiration avant chaque
     section. Les pictogrammes reprennent les opacités des quatre modes de
     création : 16 et 26 % en retrait, 42 % pour le trait de devant.

     Aucun anneau, aucune tuile, aucun aplat de couleur : la couleur ne sert
     qu'à signaler ce qui ne va pas.
     ═════════════════════════════════════════════════════════════════ */

  .an-heros{ margin-top:30px; }
  .an-n{ font-size:78px; font-weight:800; letter-spacing:-0.065em; line-height:0.86; }
  .an-n span{ font-size:31px; font-weight:700; color:var(--label-3); letter-spacing:-0.03em; }
  .an-q{ font-size:15px; color:var(--label-2); font-weight:600; margin-top:10px; }
  /* Le même bleu que les liens de section. Le vert dit « terminé » ailleurs dans
     l'app : l'employer pour une évolution brouillerait les deux. */
  .an-ev{
    display:inline-flex; align-items:center; gap:4px; margin-top:12px;
    padding:4px 10px; border-radius:100px; font-size:11.5px; font-weight:700;
    background:rgba(255,179,64,0.14); color:#FFB340;
  }
  .an-ev.baisse{ background:rgba(255,159,10,0.14); color:var(--orange); }
  .an-dit{ font-size:14.5px; line-height:1.5; color:var(--label-2); margin-top:22px; }
  .an-dit b{ color:#fff; font-weight:700; }

  .an-trois{
    display:flex; margin-top:22px; padding:15px 0;
    border-top:0.5px solid var(--border); border-bottom:0.5px solid var(--border);
  }
  .an-trois .un{ flex:1; text-align:center; position:relative; }
  .an-trois .un + .un::before{
    content:''; position:absolute; left:0; top:2px; bottom:2px;
    width:0.5px; background:var(--border);
  }
  .an-trois .v{ font-size:19px; font-weight:750; letter-spacing:-0.035em; }
  .an-trois .v em{ font-style:normal; font-size:12px; color:var(--label-3); font-weight:650; }
  .an-trois .l{ font-size:11px; color:var(--label-3); font-weight:600; margin-top:4px; }

  /* ═══ Chaque section dans sa carte ═══
     Mêmes valeurs qu'une tuile de dossier sur la page des procédures : même
     fond, même liseret, même rayon de 16. Les deux pages emploient ainsi le
     même objet, et l'œil n'a qu'une grammaire à apprendre. */
  .an-bloc{
    background:var(--bg-card); border:0.5px solid var(--border);
    border-radius:20px; padding:15px 15px 11px; margin-bottom:14px;
  }
  /* Dans une carte, la tête de section n'a plus besoin de filet ni de grande
     marge : c'est la carte qui sépare désormais. */
  /* Il faut l'identifiant dans le sélecteur : `#p-global-analyse .an-tete` pose
     26 px de marge, et l'emporterait même avec `!important` des deux côtés — une
     règle à identifiant bat toujours une règle à classes. C'est ce qui creusait
     un grand vide en haut de chaque carte. */
  /* La tête de section porte une grande marge et un filet quand elle sépare
     deux sections d'une page. Dans une CARTE, c'est la carte qui sépare : elle
     n'a plus besoin ni de l'un ni de l'autre.

     L'accueil est ajouté ici. Sans lui, ses deux blocs héritaient de la règle
     générale — 32 px de marge et un trait au-dessus du titre, à l'intérieur
     d'une carte qui les contenait déjà. */
  #p-global-analyse .an-bloc .an-tete,
  #p-home .an-bloc .an-tete{
    margin:0 0 6px !important; padding-top:0 !important; border-top:none !important;
  }
  #p-home .an-bloc .an-plus{ margin-top:4px; margin-bottom:6px; }
  /* Les lignes perdent déjà leur carte par la règle `#p-global-analyse .cat-rank`
     plus bas : inutile de la réécrire ici. On ajuste seulement leur retrait, pour
     que leur texte s'aligne sur le titre de la carte. */
  #p-global-analyse .an-bloc .cat-rank{ padding-left:0 !important; padding-right:0 !important; }
  #p-global-analyse .an-bloc .an-plus{ margin-top:4px; margin-bottom:6px; }

  .an-tete{
    display:flex; align-items:center; gap:10px;
    margin:32px 0 2px; padding-top:20px; border-top:0.5px solid var(--border);
  }
  /* La même plaque que les cartes de dossier : une seule matière pour tout
     ce qui porte une icône dans l'app. */
  .an-ic{
    display:flex; align-items:center; justify-content:center; flex-shrink:0;
    width:34px; height:34px; border-radius:11px;
    background:linear-gradient(165deg,
      rgba(255,173,51,0.11) 0%, rgba(255,173,51,0.045) 52%, rgba(255,173,51,0.015) 100%);
    border:0.5px solid rgba(255,173,51,0.20);
  }
  .an-ic svg{ width:19px; height:18px; display:block; }
  /* Le point d'information : discret, collé au titre, et il ne prend pas la
     place du lien de tri qui reste à droite. */
  .an-aide{
    width:24px; height:24px; padding:0; border:none; background:none;
    color:var(--label-3); flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
    /* Dans l'analyse, les lignes sont aplaties et n'ont que 2 px de retrait à
       droite. La médaille fait 30 px : son centre tombe donc à 17 px du bord. Le
       bouton en fait 24, son centre à 12 — il lui faut 5 px pour s'aligner.

       J'avais calculé sur les 13 px de la règle générale, sans voir que l'analyse
       les remplace. */
    margin-right:5px;
  }
  .an-aide svg{ width:19px; height:19px; display:block; }
  .an-aide:active{ color:var(--label-2); }

  /* ═══ Voir plus ═══
     Trois lignes suffisent à répondre « qui suit ». Le reste se déplie pour ceux
     qui veulent vérifier, sans allonger la page pour tous les autres. */
  /* ═══ Les lignes de l'analyse ═══
     Sans le bloc de tête, la page n'est plus qu'une suite de listes : elles
     doivent donc être légères. Chaque ligne perd sa carte et ne garde qu'un filet
     en dessous — c'est ce qui rend une liste lisible quand il n'y a qu'elle. */
  /* Pas d'animation d'ouverture ici. Elle a du sens sur une liste qu'on vient
     de charger — les procédures qui arrivent une à une. Sur trois lignes de
     résumé dans une carte, elle fait clignoter la page à chaque retour, et le
     décalage entre les lignes donne l'impression que ça rame. */
  #p-global-analyse .emp-row,
  #p-global-analyse .cat-rank{
    background:none !important; border:none !important; border-radius:0 !important;
    border-bottom:0.5px solid rgba(255,255,255,0.055) !important;
    padding:10px 2px !important; margin:0 !important;
   animation:none !important; }
  #p-global-analyse .emp-row:last-of-type,
  #p-global-analyse .cat-rank:last-of-type{ border-bottom:none !important; }
  #p-global-analyse .cat-rank .pos{
    background:none !important; border:none !important;
    color:var(--label-3) !important; font-size:12px !important;
    width:16px !important; height:auto !important;
  }
  #p-global-analyse .cat-rank.premier .pos{ color:#fff !important; }

  /* ═══ Le temps gagné ═══
     Même grammaire que la carte « Bonjour prénom » : même écart, même marge
     intérieure, même rayon. Seul le visage laisse place à un dessin au trait,
     dans le langage des icônes de création. */
  /* Un peu plus d'air que la carte d'accueil : celle-ci porte deux phrases
     complètes, là où l'autre porte une salutation et une ligne. */
  /* ═══ LE TEMPS GAGNÉ ═══
     C'est le seul endroit de l'app qui réponde à « pourquoi je paie ». Le
     chiffre se lit donc en premier, en grand, et la phrase vient après — elle
     l'expliquait avant de le montrer. Même bord allumé aux deux angles que la
     carte d'ouverture : les deux ouvrent leur page. */
  .an-gain{
    position:relative; overflow:hidden;
    margin:0 0 22px; padding:18px 20px 20px;
    border-radius:22px;
    background:var(--hero-gradient);
    box-shadow:0 14px 34px rgba(0,0,0,0.42), 0 0 30px -14px rgba(255,122,24,0.26);
  }
  .an-gain-lueur{
    position:absolute; inset:0; border-radius:inherit; pointer-events:none;
    background:
      radial-gradient(130px 90px at 100% 0%, rgba(255,122,24,0.11), transparent 72%),
      radial-gradient(110px 80px at 0% 100%, rgba(255,154,31,0.07), transparent 72%);
  }
  .an-gain-lueur::after{
    content:''; position:absolute; inset:0; border-radius:inherit; padding:1px;
    background:linear-gradient(45deg,
      #FFB454 0%, rgba(255,173,51,0.45) 12%, rgba(255,173,51,0.05) 30%,
      rgba(255,173,51,0.05) 70%, rgba(255,173,51,0.45) 88%, #FFB454 100%);
    -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite:xor; mask-composite:exclude;
  }
  .an-gain-ic{
    display:flex; align-items:center; justify-content:center; flex-shrink:0;
    width:38px; height:38px; border-radius:12px;
    background:linear-gradient(165deg,
      rgba(255,173,51,0.11) 0%, rgba(255,173,51,0.045) 52%, rgba(255,173,51,0.015) 100%);
    border:0.5px solid rgba(255,173,51,0.20);
  }
  .an-gain-ic svg{ width:20px; height:20px; display:block; }

  /* Une seule ligne : le chiffre, puis ce qu'il compte. Il reste plus gros que
     le reste — c'est lui qu'on vient chercher — mais la phrase ne se casse
     plus en deux. */
  #an-gain-t{
    position:relative; z-index:2; margin-top:16px;
    display:flex; align-items:baseline; gap:7px;
    white-space:nowrap; letter-spacing:-0.03em;
  }
  #an-gain-t b{ font-size:21px; font-weight:800; letter-spacing:-0.045em; }
  #an-gain-t em{
    font-style:normal; font-size:14.5px; font-weight:600; color:var(--label-2);
  }
  #an-gain-s{
    position:relative; z-index:2;
    font-size:12.5px; color:var(--label-3); line-height:1.5; margin-top:9px;
  }
  #an-gain-s b{ color:var(--label-2); font-weight:650; }
  /* Aucune taille propre : la carte suit l'échelle de « Bonjour prénom » — titre
     à 16, phrase à 12,5. J'avais forcé 14,5 partout pour égaliser les deux
     lignes ; ça marchait sur cette carte, mais ça cassait le rapport que l'app
     tient partout ailleurs entre un titre et sa phrase. */

  /* Le mot d'introduction, dans la matière de la carte d'accueil. */
  .an-intro{
    padding:16px 18px; border-radius:20px; margin-top:14px;
    background:var(--hero-gradient); border:0.5px solid var(--border);
  }
  .an-intro .t{ font-size:16px; font-weight:700; letter-spacing:-0.03em; }
  .an-intro .s{ font-size:12.5px; color:var(--label-2); margin-top:5px; line-height:1.5; }
  .an-intro .s b{ color:#fff; font-weight:650; }

  /* Sur cette page, les lignes ne sont plus des cartes : un filet suffit, et
     vingt personnes restent parcourables. */
  #p-an-categories .cat-rank,
  #p-an-temps .emp-row,
  #p-an-equipe .emp-row{
    background:none !important; border:none !important; border-radius:0 !important;
    border-bottom:0.5px solid rgba(255,255,255,0.055) !important;
    padding:12px 2px !important; margin:0 !important;
  }
  #p-an-categories .cat-rank:last-of-type,
  #p-an-temps .emp-row:last-of-type,
  #p-an-equipe .emp-row:last-of-type{ border-bottom:none !important; }
  #p-an-categories .fl,
  #p-an-temps .fl,
  #p-an-equipe .fl{ color:var(--label-3); font-size:17px; flex-shrink:0; }

  /* ═══ La fiche d'un membre ═══
     Mêmes lignes sobres que la page Équipe : un filet, pas de carte. On vient de
     là, on doit s'y retrouver. */
/* ═══ La fiche d'un membre ═══ */

  /* Le poste suit le nom, séparé d'un point. Il n'est pas encadré : ce n'est
     pas une étiquette qu'on accroche à quelqu'un, c'est la suite de son nom. */
  .fm-nom-ligne{ display:flex; align-items:baseline; gap:0; min-width:0; }
  .fm-nom-ligne #fm-nom{
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis; flex-shrink:1;
  }
  .fm-nom-ligne .poste{
    font-size:14px; font-weight:600; color:var(--label-3);
    letter-spacing:-0.02em; flex-shrink:0; white-space:nowrap;
  }
  /* En CSS, l'espace qui SUIT un échappement le termine : `\00b7 ` ne rend que
     le point, l'espace est avalé. On écrit donc le caractère tel quel. */
  .fm-nom-ligne .poste:not(:empty)::before{ content:' · '; white-space:pre; }

  /* L'anneau segmenté. */
  /* ═══ L'ANNEAU N'EST PAS DANS UNE CARTE ═══

     J'avais posé une carte autour, pour aligner ces pages sur l'abonnement et
     le quota. Mais un anneau n'est pas une liste : il se suffit à lui-même, et
     l'encadrer ajoute une bordure qui n'entoure rien — juste du vide autour
     d'un cercle.

     Le cadre reste utile quand il RASSEMBLE plusieurs éléments disparates ;
     ici il n'en rassemblait qu'un. */
  .fm-segm{
    display:flex; justify-content:center;
    padding:20px 0 16px;
  }

  /* LA LISTE RESTE À PLAT. Je l'avais mise dans un bloc — mais les pages
     d'Analyse, qui portent exactement la même chose, la laissent à nu avec de
     simples filets. Deux pages sœurs doivent se ressembler ; c'est la fiche
     membre qui s'aligne, pas l'inverse. */
  .fm-segm .svg{ position:relative; width:214px; height:214px; }
  .fm-segm svg{ transform:rotate(-90deg); display:block; }
  /* Les bouts sont arrondis : chaque part se termine par un demi-cercle.
     Elle n'anime plus sa longueur — c'est le masque qui la révèle. */
  .fm-segm .arc{ stroke-linecap:round; transition:opacity 0.45s ease; }
  /* Une part trop courte pour deux bouts ronds en reçoit des droits : sinon
     l'arrondi déborde de 17 px et mord sur la couleur voisine. */
  .fm-segm .arc.droit{ stroke-linecap:butt; }

  /* L'aiguille du masque : c'est elle qui fait le tour. */
  /* L'aiguille du masque a un bout DROIT. Arrondie, sa demi-épaisseur débordait
     en arrière du point de départ — c'est-à-dire juste avant midi, là où se
     termine la dernière part. On voyait donc un fragment de la dernière couleur
     avant que l'animation ne commence. */
  .fm-segm .fm-aiguille{
    stroke-linecap:butt;
    transition:stroke-dashoffset 1.4s cubic-bezier(0.32,0.72,0,1);
  }
  .fm-segm .arc.pale{ opacity:0.20; }

  /* Sur les pages d'analyse, les parts se touchent : le doigt vise un trait de
     17 px, ce qui est étroit mais suffisant pour un anneau de 214. */
  #an-anneau-cat .arc, #an-anneau-proc .arc{ cursor:pointer; }
  #an-anneau-cat svg, #an-anneau-proc svg{ pointer-events:auto; }
  .fm-segm .dedans{
    position:absolute; inset:0; display:flex; flex-direction:column;
    align-items:center; justify-content:center;
  }
  .fm-segm .dedans .v{ font-size:36px; font-weight:800; letter-spacing:-0.05em; line-height:1; }
  .fm-segm .dedans .u{ font-size:12px; color:var(--label-3); font-weight:650; margin-top:4px; }
  /* 112 px, pas 132 : le trou de l'anneau en fait 120, et « 2 procédures sur
     10 » passait dessous. On rétrécit et on raccourcit — voir `app.js`, où le
     texte devient « 2 sur 10 lues ». */
  .fm-segm .dedans .n{
    font-size:11px; font-weight:650; margin-top:8px; max-width:112px;
    text-align:center; line-height:1.3; color:var(--label-2);
  }


  /* Les lignes du classement. */
  .fm-lg{
    display:flex; align-items:center; gap:11px; padding:11px 2px; width:100%;
    background:none; border:none; border-bottom:0.5px solid rgba(255,255,255,0.055);
    font-family:inherit; text-align:left; color:inherit;
  }
  /* `:last-of-type` compte les BALISES, pas les classes : dans une liste suivie
     du bouton « Voir les autres », il désignait le bouton et non la dernière
     ligne — qui gardait donc son filet, là où l'activité n'en avait pas. */
  .fm-lg:last-child, .fm-rep .l:last-child{ border-bottom:none; }
  .fm-lg:has(+ .fm-plus){ border-bottom:none; }
  .fm-lg:active{ opacity:0.6; }
  .fm-lg .pt{ width:11px; height:11px; border-radius:3px; flex-shrink:0; }
  .fm-lg .co{ flex:1; min-width:0; display:flex; flex-direction:column; }
  .fm-lg .nm{ font-size:14.5px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .fm-lg .st{ font-size:11.5px; color:var(--label-3); margin-top:1px; }
  .fm-lg .vl{ font-size:14px; font-weight:650; color:var(--label-2); flex-shrink:0; }
  .fm-lg.choisi .nm{ color:#fff; }


  /* Les lignes qui se déplient arrivent une à une, en glissant depuis le haut.
     Sans ça, trois lignes surgissent d'un coup et on ne sait pas si la page a
     changé ou si elle s'est rechargée. */
  @keyframes fmLigneArrive{
    from{ opacity:0; transform:translateY(-10px) scale(0.98); }
    to{ opacity:1; transform:translateY(0) scale(1); }
  }
  .fm-lg.neuve{ animation:fmLigneArrive 0.34s cubic-bezier(0.22,1,0.36,1) both; }

  /* Le bouton descend et remonte avec les lignes, au lieu de sauter d'un
     endroit à l'autre. Il fait partie du bloc, pas du décor. */
  .fm-plus.glisse{ transition:transform 0.42s cubic-bezier(0.22,1,0.36,1); }

  /* En repliant, celles qui partent s'effacent vers le haut. On les laisse en
     place le temps de l'animation, puis on redessine. */
  @keyframes fmLignePart{
    from{ opacity:1; transform:translateY(0); }
    to{ opacity:0; transform:translateY(-8px); }
  }
  .fm-lg.part{ animation:fmLignePart 0.24s ease both; pointer-events:none; }

  .fm-plus{
    width:100%; height:42px; margin-top:12px; border-radius:100px;
    background:rgba(255,255,255,0.055); border:0.5px solid var(--border);
    color:var(--label-2); font-family:inherit; font-size:13.5px; font-weight:650;
  }
  .fm-plus:active{ opacity:0.6; }

  /* Les quatre repères d'activité, tous sur le même modèle. */
  /* « Activité » reste à plat aussi, pour la même raison. */
  .fm-rep{ margin-top:6px; }
  .fm-rep .l:last-child{ border-bottom:none; }
  .fm-rep .l{
    display:flex; align-items:center; gap:11px; padding:11px 2px;
    border-bottom:0.5px solid rgba(255,255,255,0.055);
  }
  .fm-rep .l:last-child{ border-bottom:none; }
  .fm-rep .ic{
    width:28px; height:28px; border-radius:8px; flex-shrink:0; display:flex;
    align-items:center; justify-content:center;
    background:rgba(255,255,255,0.06); border:0.5px solid var(--border);
  }
  .fm-rep .ic svg{ width:14px; height:14px; color:rgba(255,255,255,0.72); }
  .fm-rep .nm{ flex:1; min-width:0; font-size:13.5px; color:var(--label-2); font-weight:600; }
  .fm-rep .vl{ font-size:13.5px; font-weight:650; flex-shrink:0; }

  .fm-trois{ display:flex; gap:8px; margin-top:16px; }
  .fm-trois .un{
    flex:1; padding:13px 10px; border-radius:14px; text-align:center;
    background:var(--bg-card); border:0.5px solid var(--border);
  }
  .fm-trois .v{ font-size:20px; font-weight:800; letter-spacing:-0.04em; }
  .fm-trois .l{ font-size:10.5px; color:var(--label-3); font-weight:600; margin-top:3px; }

  /* ═══ Le carrousel des deux périodes ═══ */

  /* Le défilement horizontal natif, avec aimantation. Les panneaux débordent
     des marges de l'écran pour que le suivant s'annonce dès qu'on effleure. */
  .fm-piste{
    display:flex; overflow-x:auto; overflow-y:hidden;
    scroll-snap-type:x mandatory; scroll-behavior:smooth;
    -webkit-overflow-scrolling:touch; scrollbar-width:none;
    margin:0 -20px; padding:0;
  }
  .fm-piste::-webkit-scrollbar{ display:none; }
  /* Aucun retrait ici : l'écran le donne déjà. Les 20 px qui restaient s'y
     ajoutaient, et le contenu des panneaux partait plus loin que les titres —
     le fameux « padding + padding ». */
  .fm-pan{
    flex:0 0 100%; min-width:100%; scroll-snap-align:center;
    padding:0;
  }

  /* La barre de position : deux traits, celui de la page active en blanc. */
  /* ═══ LA BARRE DE POSITION ═══

     Deux traits sous la piste. Celui de la page courante prend l'ambre et
     s'allonge — c'est ce qui dit où l'on est, et qu'il y a autre chose à côté.

     J'avais remplacé ça par deux boutons nommés. Le geste de glisser est plus
     juste : la barre ACCOMPAGNE le mouvement du doigt au lieu de le remplacer
     par un appui. */
  .fm-barre{ display:flex; gap:6px; justify-content:center; margin-top:20px; }
  /* Le dessin de la barre est plus bas, dans sa définition d'origine : le TRAIT
     est le `span`, et le bouton n'est que la zone qu'on touche — plus large que
     le trait, ce qui la rend atteignable au doigt. J'avais écrit une seconde
     définition ici, qui masquait le span et peignait le bouton ; les deux se
     marchaient dessus et le trait inactif disparaissait. */
  .fm-barre button{
    border:none; background:none; padding:8px 3px; cursor:pointer;
  }
  .fm-barre span{
    display:block; width:34px; height:3px; border-radius:2px;
    background:rgba(255,255,255,0.16);
    transition:background 0.28s ease, width 0.28s cubic-bezier(0.22,1,0.36,1);
  }
  .fm-barre button.on span{ background:#FFAD33; width:44px; }

  .fm-periode-mot{
    text-align:center; font-size:12px; font-weight:650; color:var(--label-3);
    margin-top:2px; letter-spacing:-0.01em;
  }

  /* Les pages d'analyse gardent les marges de l'écran, comme la carte
     « Bonjour prénom ». Seule la piste déborde — il faut qu'elle touche les
     bords pour que le panneau voisin s'annonce dès qu'on effleure. */
  /* La piste doit toucher les bords pour que le panneau voisin s'annonce dès
     qu'on effleure : elle sort donc des 20 px de l'écran, et ses panneaux les
     rendent à l'intérieur. Le compte retombe exactement sur 20. */
  /* Le contenu s'aligne sur le TEXTE de la carte « Bonjour prénom », pas sur son
     bord : c'est le texte qu'on lit, et c'est lui qui donne la colonne. La carte
     ajoute 20 px à l'écran, ces pages en font autant.

     La piste doit toucher les bords pour que le panneau voisin s'annonce dès
     qu'on effleure : elle sort des 20 px de l'écran, et ses panneaux rendent
     les 40 px à l'intérieur. */


  /* Même colonne que les deux pages d'analyse. Seul l'en-tête — bouton retour et
     nom — reste à la marge de l'écran : il appartient à la navigation. */
  .fm-lg, .fm-rep .l{ padding-left:0; padding-right:0; }
  .fm-titre{
    font-size:12px; font-weight:650; color:var(--label-3);
    margin:24px 0 4px; text-transform:uppercase; letter-spacing:0.06em;
  }

  /* La ligne, exactement celle de la page Équipe. */
  /* Les lignes sont des boutons : on les remet à plat pour qu'elles ressemblent
     à du texte et non à des contrôles. */
  button.fm-lig{
    width:100%; background:none; border:none; padding:12px 2px;
    border-bottom:0.5px solid rgba(255,255,255,0.055);
    font-family:inherit; text-align:left; color:inherit;
  }
  button.fm-lig:active{ opacity:0.6; }
  .fm-lig .co{ display:flex; flex-direction:column; }

  .fm-lig{
    display:flex; align-items:center; gap:12px; padding:12px 2px;
    border-bottom:0.5px solid rgba(255,255,255,0.055);
  }
  .fm-lig:last-child{ border-bottom:none; }
  .fm-lig .co{ flex:1; min-width:0; }
  .fm-lig .nm{ font-size:14.5px; font-weight:600; }
  .fm-lig .st{ font-size:11.5px; color:var(--label-3); margin-top:1px; }
  .fm-lig .vl{ font-size:14px; font-weight:650; color:var(--label-2); flex-shrink:0; }
  .fm-lig .fl{ color:var(--label-3); font-size:17px; flex-shrink:0; }
  .fm-lig .pt{ width:7px; height:7px; border-radius:50%; flex-shrink:0; }

  /* Le temps passé, là où la médaille se tenait. Deux lignes serrées : le
     chiffre, puis ce qu'il compte. */
  .temps-total{
    display:flex; flex-direction:column; align-items:flex-end;
    flex-shrink:0; line-height:1.15; text-align:right;
  }
  .temps-total b{ font-size:14.5px; font-weight:700; letter-spacing:-0.03em; }
  .temps-total i{ font-style:normal; font-size:10.5px; color:var(--label-3); font-weight:600; margin-top:2px; }
  .temps-total.grand b{ font-size:19px; letter-spacing:-0.04em; }
  .temps-total.grand i{ font-size:11.5px; margin-top:3px; }

  /* La ligne des pages d'analyse : la même que la page Équipe. Un filet, pas
     de carte — vingt lignes restent parcourables. */
  /* La roue de consultation, en tête de la liste des employés. */
  .emp-roue{
    display:flex; align-items:center; gap:14px; margin-bottom:6px;
    padding:15px 16px; border-radius:18px;
    background:var(--bg-card); border:0.5px solid var(--border);
  }
  .emp-roue .ga-anneau{ flex-shrink:0; }
  .emp-roue .tx{ flex:1; min-width:0; }
  .emp-roue .t{ font-size:14.5px; font-weight:650; letter-spacing:-0.02em; }
  .emp-roue .s{ font-size:12px; color:var(--label-2); margin-top:3px; line-height:1.45; }
  .emp-roue .s b{ color:#fff; font-weight:650; }
  .emp-liste .an-lig .pt{ width:7px; height:7px; border-radius:50%; flex-shrink:0; }

  /* La même barre que la recherche d'une dossier, avec son bouton à côté. */
  /* La liste des postes, dans la fenêtre d'arrivée. Des lignes pleine largeur :
     on choisit du doigt, dans une cuisine, souvent debout. */
  /* La fenêtre du choix de poste. */
  .poste-fen{ padding:0; }
  .poste-tete{ padding:24px 22px 16px; text-align:center; }
  .poste-tete .ic{
    width:52px; height:52px; border-radius:16px; margin:0 auto 14px;
    display:flex; align-items:center; justify-content:center;
    background:rgba(255,179,64,0.14); border:0.5px solid rgba(255,179,64,0.28);
    color:var(--blue);
  }
  .poste-tete .ic svg{ width:25px; height:25px; }
  .poste-tete .t{ font-size:19px; font-weight:750; letter-spacing:-0.035em; }
  .poste-tete .s{ font-size:13px; color:var(--label-2); margin-top:6px; line-height:1.45; }

  .poste-fen .poste-choix{
    max-height:min(40vh, 260px); overflow-y:auto;
    border-top:0.5px solid rgba(255,255,255,0.09);
  }
  .poste-fen .poste-choix button{
    display:flex; align-items:center; gap:12px; width:100%;
    padding:15px 22px; border:none; background:none;
    border-bottom:0.5px solid rgba(255,255,255,0.06);
    font-family:inherit; font-size:15.5px; font-weight:600; color:#fff; text-align:left;
  }
  .poste-fen .poste-choix button:last-child{ border-bottom:none; }
  .poste-fen .poste-choix .nm{ flex:1; min-width:0; }
  .poste-fen .poste-choix .r{
    width:21px; height:21px; border-radius:50%; flex-shrink:0;
    border:1.7px solid rgba(255,255,255,0.24);
  }
  .poste-fen .poste-choix button.on{ background:rgba(255,179,64,0.10); }
  .poste-fen .poste-choix button.on .r{
    border-color:var(--blue); background:var(--blue);
    display:flex; align-items:center; justify-content:center;
  }
  .poste-fen .poste-choix button.on .r::after{
    content:''; width:7px; height:7px; border-radius:50%; background:var(--bg);
  }

  .poste-pied{ padding:16px 20px 20px; }
  .poste-ok{
    width:100%; height:50px; border-radius:100px; border:none;
    background:#fff; color:#000; font-family:inherit; font-size:15.5px; font-weight:700;
  }
  /* Éteint tant que rien n'est choisi : c'est ce qui rend la réponse
     obligatoire, sans jamais avoir à l'écrire. */
  .poste-ok:disabled{ background:rgba(255,255,255,0.10); color:var(--label-3); }

  .poste-saisie{ display:flex; align-items:center; gap:9px; margin-top:16px; }
  /* La barre de recherche porte une marge basse de 12 px, utile là où elle
     surplombe une liste. Ici elle décalait le bouton vers le haut : à hauteur
     égale, deux éléments centrés ne le sont plus si l'un est plus « lourd » que
     l'autre. On l'annule. */
  .poste-saisie .search-bar{ flex:1; min-width:0; margin-bottom:0; }
  /* Même matière que le bouton principal : c'est le geste de la page. */
  .poste-ajouter{
    flex-shrink:0; height:38px; padding:0 18px; border:none; border-radius:100px;
    background:linear-gradient(135deg,#FF6A00 0%,#FF9A1F 60%,#FFAD33 100%);
    color:#2A1400; font-family:inherit; font-size:14px; font-weight:700;
    box-shadow:0 5px 15px rgba(255,122,24,0.24);
  }
  .poste-ajouter:active{ opacity:0.7; }

  /* L'état vide d'une section : le dessin, ce qui manque, le geste qui le
     résout. Centré, parce qu'il n'y a rien à aligner à gauche. */
  .an-neant{ text-align:center; padding:20px 8px 8px; }
  .an-neant .d{
    display:flex; align-items:center; justify-content:center;
    width:44px; height:40px; margin:0 auto 12px;
  }
  .an-neant .d svg{ width:44px; height:40px; display:block; }
  .an-neant .t{ font-size:14.5px; font-weight:700; letter-spacing:-0.02em; }
  .an-neant .s{
    font-size:12.5px; color:var(--label-2); line-height:1.5;
    margin-top:5px; max-width:270px; margin-left:auto; margin-right:auto;
  }
  .an-neant-btn{
    margin-top:14px; height:38px; padding:0 18px; border:none; border-radius:100px;
    background:rgba(255,255,255,0.08); border:0.5px solid var(--border); color:#fff;
    font-family:inherit; font-size:13.5px; font-weight:650;
  }
  .an-neant-btn:active{ opacity:0.65; }

  /* Le bouton d'aide, dans l'angle de la carte. La carte prend `position:relative`
     pour qu'il s'y accroche plutôt que de flotter dans l'écran. */
  #an-gain{ position:relative; }
  /* Le bouton d'aide se pose à égale distance du haut et de la droite.

     La carte a 18 px de retrait en haut et 20 à droite. Le bouton était aligné
     sur le texte, donc plus bas et plus rentré : il flottait sans s'appuyer sur
     rien. On le sort du flux et on le place en absolu, à 18 px des deux bords —
     l'œil voit alors un angle, pas un objet perdu.

     Le rond fait 26 px, son dessin 19 : les 3,5 px de vide autour ne comptent
     pas dans ce qu'on voit. On les retranche pour que la DISTANCE VISIBLE soit
     bien de 18. */
  #an-gain{ position:relative; }
  .an-gain .gain-ligne{ position:relative; z-index:2; }
  /* Contre le bord. Le rond fait 26 px pour un dessin de 19 : les 3,5 px de
     vide autour ne se voient pas, on les retranche pour que la distance
     VISIBLE au bord soit celle qu'on veut. */
  .an-gain .gain-aide{
    position:absolute; top:calc(14px - 3.5px); right:calc(12px - 3.5px);
    margin:0; z-index:3;
  }
  /* La ligne rend la place qu'occupait le bouton : sans ça, le titre garderait
     un espace vide à sa droite. */
  #an-gain .gain-ligne{ padding-right:26px; }
  /* Le bouton d'aide sur la LIGNE du titre, calé à droite. En position absolue
     dans l'angle, il flottait au-dessus du texte sans lui appartenir. */
  /* Le bouton se cale sur la PREMIÈRE ligne du titre, pas au milieu du bloc :
     `baseline` alignerait sa base sur celle du texte, ce qui le fait descendre
     quand le titre passe sur deux lignes. `flex-start` le garde en haut, et
     l'angle est là où l'œil va le chercher. */
  .gain-ligne{ display:flex; align-items:flex-start; justify-content:space-between; gap:10px; }
  .gain-ligne .t{ flex:1; min-width:0; }

  .gain-aide{
    flex-shrink:0; margin-top:-1px; width:26px; height:26px;
    border:none; background:none; padding:0; color:var(--label-3);
    display:flex; align-items:center; justify-content:center;
  }
  .gain-aide svg{ width:19px; height:19px; }
  .gain-aide:active{ opacity:0.55; }
  /* Le titre ne passe pas sous le bouton. */


/* Un peu d'air entre le mot d'introduction et le filtre : collés, on croit
     que le second commente le premier. */
  /* Le compte à gauche, le filtre à droite. `.dd-filter` prend `flex:1` par
     défaut ailleurs — ici on lui rend sa largeur naturelle, sinon il pousserait
     le compte contre le bord. */
  .an-rangee{
    display:flex; align-items:center; justify-content:space-between;
    gap:12px; margin-top:18px;
  }
  /* La marge basse de 14 px que `.dd-filter` porte partout ailleurs poussait le
     filtre sous le compte : deux rangées pour une seule idée. Dans cette rangée,
     il n'a rien à pousser — c'est la rangée elle-même qui espace. */
  .an-rangee .dd-filter{ flex:0 0 auto; margin-bottom:0; }
  .an-rangee .an-compte{ flex:1; min-width:0; }

  .an-lig{
    display:flex; align-items:center; gap:12px; width:100%;
    padding:12px 2px; background:none; border:none;
    border-bottom:0.5px solid rgba(255,255,255,0.055);
    font-family:inherit; text-align:left; color:inherit;
  }
  .an-lig:last-of-type{ border-bottom:none; }
  .an-lig:active{ opacity:0.6; }
  .an-lig .co{ flex:1; min-width:0; display:flex; flex-direction:column; }
  .an-lig .nm{ font-size:14.5px; font-weight:600; }
  .an-lig .st{ font-size:11.5px; color:var(--label-3); margin-top:1px; }
  .an-lig .vl{ font-size:14px; font-weight:650; color:var(--label-2); flex-shrink:0; }
  .an-lig .fl{ color:var(--label-3); font-size:17px; flex-shrink:0; }
  .an-seg{ margin-top:16px; }
  .an-vide{ font-size:13px; color:var(--label-3); padding:14px 2px; }

  /* Sans `flex:1`, le tri se pose juste après le compte au lieu d'être poussé
     à l'autre bout : les deux se lisent d'un seul mouvement d'œil. */
  .an-compte{
    font-size:13px; color:var(--label-3); font-weight:600;
  }

  /* Un pavé gris pleine largeur pesait autant que la liste qu'il prolonge.
     C'est devenu une ligne d'appel, comme le pied des cartes de dossier :
     un libellé, un chevron, un filet au-dessus. */
  .an-plus{
    display:flex; align-items:center; gap:7px; width:100%;
    margin-top:2px; padding:11px 0 3px;
    border:none; border-top:0.5px solid var(--separator); border-radius:0;
    background:none; color:var(--label-2);
    font-family:inherit; font-size:12px; font-weight:650;
  }
  .an-plus::after{
    content:'\203a'; margin-left:auto; color:var(--label-3);
    font-size:16px; line-height:1;
  }
  .an-plus:active{ opacity:0.6; }

  /* DEUX FILETS AU LIEU D'UN.

     La dernière ligne de la liste porte son filet du bas, et « Voir plus »
     porte le sien du haut : les deux se retrouvaient côte à côte, séparés d'un
     pixel. On retire celui de la ligne quand un « Voir plus » la suit.

     `:last-of-type` ne pouvait pas le faire : il compte les BALISES, et les
     lignes comme le bouton sont des `button`. Le dernier bouton de la liste,
     c'est « Voir plus » lui-même — jamais la ligne au-dessus. */
  .an-lig:has(+ .an-plus),
  #p-global-analyse .emp-row:has(+ .an-plus),
  #p-global-analyse .cat-rank:has(+ .an-plus){ border-bottom:none !important; }

  .an-tete b{ flex:1; font-size:16px; font-weight:700; letter-spacing:-0.025em; }
  .an-lien{
    border:none; background:none; padding:0; font-family:inherit;
    font-size:13px; color:#FFB340; font-weight:600;
  }

  /* Une ligne : médaille ou pastille, nom, détail, valeur. */
  .an-vide{ font-size:13px; color:var(--label-3); padding:16px 0; }

  /* ═══ La fiche d'un membre ═══ */
  .fm-co{ flex:1; min-width:0; }
  /* Sans cercle d'initiales, le nom prend la place : c'est lui qu'on lit. */
  .fm-nom{ font-size:26px; font-weight:700; letter-spacing:-0.03em; }
  .fm-rl{ font-size:13px; color:var(--label-3); font-weight:600; margin-top:3px; }
  .fm-serie b{ color:#fff; font-weight:700; }

  .fm-courbe{ display:flex; gap:5px; align-items:flex-end; height:52px; margin-top:6px; }
  .fm-courbe span{ flex:1; border-radius:3px; background:rgba(255,255,255,0.14); min-height:3px; }
  .fm-courbe span.haut{ background:rgba(255,255,255,0.42); }
  .fm-jours{ display:flex; gap:5px; margin-top:8px; }
  .fm-jours span{ flex:1; text-align:center; font-size:9.5px; color:var(--label-3); font-weight:650; }

  /* ═══ L'image de la procédure ═══
     Une seule image pour l'ensemble, distincte des photos d'étape. Les
     procédures sans vidéo n'avaient rien à montrer sur leur carte : une liste de
     titres se ressemble toute. */
  .couv{
    position:relative; display:flex; align-items:center; gap:12px; margin-top:14px;
    padding:11px 12px; border-radius:16px;
    background:var(--bg-card); border:0.5px solid var(--border);
  }
  .couv input[type=file]{ position:absolute; inset:0; opacity:0; width:100%; height:100%; z-index:2; }
  .couv .vign{
    width:56px; height:42px; border-radius:9px; flex-shrink:0; overflow:hidden;
    background:rgba(255,255,255,0.06); border:0.5px solid var(--border);
    display:flex; align-items:center; justify-content:center;
  }
  .couv .vign svg{ width:21px; height:21px; }
  .couv .vign img{ width:100%; height:100%; object-fit:cover; display:block; }
  .couv .tx{ flex:1; min-width:0; }
  .couv .tx .t{ display:block; font-size:13.5px; font-weight:650; letter-spacing:-0.02em; }
  .couv .tx .s{ display:block; font-size:11.5px; color:var(--label-3); line-height:1.4; margin-top:2px; }
  /* ═══ La zone d'image, sur les écrans de création ═══
     La maquette montrait une zone en pointillés, dessin centré : c'est la forme
     universelle du « déposez ici », et elle se distingue tout de suite d'un champ
     rempli. La ligne horizontale ressemblait à un réglage, pas à une invitation.

     Une fois la photo choisie, la zone redevient une ligne : il n'y a plus rien
     à déposer, seulement quelque chose à montrer. */
  #p-create-manual .couv:not(.remplie),
  .couv-depot:not(.remplie){
    flex-direction:column; text-align:center; gap:11px;
    padding:26px 18px; border-radius:18px;
    border:1.5px dashed rgba(255,255,255,0.16);
    background:rgba(255,255,255,0.025);
  }
  #p-create-manual .couv:not(.remplie) .vign,
  .couv-depot:not(.remplie) .vign{
    width:52px; height:52px; border:none; background:none;
  }
  #p-create-manual .couv:not(.remplie) .vign svg,
  .couv-depot:not(.remplie) .vign svg{ width:46px; height:46px; }
  #p-create-manual .couv:not(.remplie) .tx .t,
  .couv-depot:not(.remplie) .tx .t{ font-size:14.5px; font-weight:650; }
  #p-create-manual .couv:not(.remplie) .tx .s,
  .couv-depot:not(.remplie) .tx .s{ margin-top:4px; line-height:1.45; }

  .couv .oter{
    position:relative; z-index:3; border:none; background:rgba(255,255,255,0.10);
    color:var(--red); font-family:inherit; font-size:11.5px; font-weight:650;
    padding:6px 11px; border-radius:100px; flex-shrink:0;
  }

  /* ═══════════════════════════════════════════════════════════════════
     DÉCOUPER UNE VIDÉO — UN SEUL GESTE

     Découper à la main, c'est regarder et dire « ici ça s'arrête ». Rien d'autre.
     Le bouton fait donc les deux : il lance la vidéo, puis il ferme l'étape en
     cours à chaque appui. Comme un chronomètre de tours.

     L'ancien éditeur — frise à zoom, poignées, loupe, barre d'outils, jauge de
     couverture — demandait de comprendre le montage avant de pouvoir s'en
     servir. Ce qui a été coupé se corrige après, dans la liste : c'est là qu'on
     relit, donc c'est là qu'on rectifie.
     ═════════════════════════════════════════════════════════════════ */
  .dv-depot{ position:relative; margin-top:0; }
  .dv-depot input[type=file]{
    position:absolute; inset:0; opacity:0; width:100%; height:100%; z-index:2;
  }
  /* Même rayon que `.video-frame`, le cadre de l'écran de l'IA : les deux
     écrans accueillent une vidéo, ils doivent l'encadrer pareil. */
  .dv-cadre{
    position:relative; border-radius:16px; overflow:hidden; background:#000;
    border:0.5px solid var(--border); aspect-ratio:16/9;
    display:flex; align-items:center; justify-content:center;
    font-size:13px; color:var(--label-3);
  }
  /* Le cadre vide devient une invitation : pointillés plutôt que noir plein,
     et il se resserre — il occupait la moitié de l'écran pour ne rien dire. */
  .dv-cadre:has(.dv-vide){
    background:rgba(255,255,255,0.02); border:1.5px dashed rgba(255,255,255,0.16);
    aspect-ratio:auto; min-height:220px;
  }
  .dv-vide{
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    text-align:center; padding:26px 22px; gap:0;
  }
  .dv-vide .ic{
    width:62px; height:62px; border-radius:19px; margin-bottom:14px;
    display:grid; place-items:center;
    background:rgba(255,255,255,0.05); border:0.5px solid var(--border);
    color:rgba(255,255,255,0.72);
  }
  .dv-vide .ic svg{ width:29px; height:29px; }
  .dv-vide .t{ font-size:17px; font-weight:700; letter-spacing:-0.03em; }
  .dv-vide .s{
    font-size:12.5px; color:var(--label-3); line-height:1.5;
    margin-top:5px; max-width:240px;
  }

  .dv-cadre video{ width:100%; height:100%; display:block; object-fit:contain; }

  /* La frise fait deux centimètres : on la lit, on ne la manipule pas. */
  /* ═══ LA FRISE ═══

     Une fenêtre qui défile, et dedans une frise cinq fois plus large que
     l'écran. Sans ce zoom, une étape de trois secondes sur une vidéo de deux
     minutes fait deux pixels : on ne peut ni la voir, ni la saisir.

     Elle est aussi plus ÉPAISSE — 44 px au lieu de 26. Ce n'est pas décoratif :
     on y attrape des traits au doigt, et un doigt fait 8 mm. */
  /* « Recommencer le découpage » : en blanc plein, comme les actions principales.
     Le bouton de coupe est bleu — celui-ci ne coupe pas, il remet à zéro. */
  #dv-bouton.refaire{
    background:#fff; color:#000;
  }
  #dv-bouton.refaire svg{ fill:#000; }

  /* ═══ LE POINT DE VIGILANCE ═══
     Ambre, pas rouge : le rouge dit « erreur », or rien n'est en faute ici. On
     prévient, on n'alarme pas. Et il reste DANS l'étape — une mise en garde
     séparée de son geste se lit trop tard. */
  /* ═══ LA MARQUE « AI » DANS LES BOUTONS ═══

     Le même dégradé que l'anneau, appliqué aux lettres. Dans un bouton, l'anneau
     qui tourne entrait en concurrence avec le texte à côté : deux choses qui
     bougent, dont une qui ne veut rien dire de plus qu'un mot. Les grands
     anneaux des écrans d'attente restent, eux — là, le mouvement EST
     l'information. */
  .ia-mot{
    font-size:15px; font-weight:850; letter-spacing:0.02em;
    line-height:1; flex-shrink:0; user-select:none;
    background:linear-gradient(118deg, #FFFFFF 0%, #FFFFFF 46%, #FFC46B 100%);
    -webkit-background-clip:text; background-clip:text;
    -webkit-text-fill-color:transparent; color:transparent;
  }
  /* Sur un bouton blanc, des lettres blanches n'existent pas. */
  .btn:not(.ghost):not(.dv-ia-bas) .ia-mot{
    background:linear-gradient(118deg, #C77A0A 0%, #C77A0A 46%, #7A4A00 100%);
    -webkit-background-clip:text; background-clip:text;
  }
  /* Éteint, le bouton pâlit — la marque garde sa couleur, comme l'anneau. */
  button:disabled .ia-mot{ opacity:1; }

  .et-attention{
    display:flex; align-items:flex-start; gap:8px;
    margin-top:9px; padding:9px 11px; border-radius:11px;
    background:rgba(255,159,10,0.10);
    border:0.5px solid rgba(255,159,10,0.26);
    color:#FFB340;
  }
  .et-attention svg{ width:15px; height:15px; flex-shrink:0; margin-top:1px; }
  .et-attention span{ font-size:13px; font-weight:600; line-height:1.4; }
  /* Une étape faite estompe aussi sa mise en garde. */
  #detail-steps.etapes-fil .detail-step.faite .et-attention{ opacity:0.45; }

  .dv-vue{
    position:relative; margin-top:22px; padding:12px 0;
    overflow:hidden;
  }

  /* La piste défile sous le trait. Le retrait de la moitié de l'écran de chaque
     côté — pour que l'instant zéro puisse atteindre le centre — est posé EN
     PIXELS par le code, pas en pourcentage.

     `padding:0 50%` faisait 100 % de retrait au total : la zone de contenu
     tombait à zéro et la frise, large de 100 %, devenait invisible. */
/* ═══ LA MARGE DES PAGES D'ANALYSE ═══

     Une seule valeur commande tout : l'écran, les titres, les listes, et le
     retrait que la piste doit rendre à ses panneaux. Avant, chaque élément
     portait sa propre règle — d'où des colonnes qui ne s'alignaient pas.

     32 px plutôt que 20 : sur ces pages, il n'y a ni carte ni cadre pour tenir
     le contenu. C'est le blanc qui fait la mise en page, et il faut qu'il se
     voie. */
  #p-membre, #p-an-temps, #p-an-categories, #p-an-equipe{
    padding-left:32px; padding-right:32px;
  }
  /* Le bouton retour remonte de 5 px vers le bord. Un rond de 34 px paraissait
     plus éloigné que le texte aligné sous lui : l'œil suit le bord du cercle,
     pas celui de sa boîte. */
  #p-membre .back-btn, #p-an-temps .back-btn, #p-an-categories .back-btn,
  #p-an-equipe .back-btn, #p-membre .an-tete .back-btn{
    margin-left:-5px;
  }
  /* Les pistes touchent les bords — il faut que le panneau voisin s'annonce dès
     qu'on effleure — et leurs panneaux rendent la marge à l'intérieur. */
  #p-membre .fm-piste, #an-piste-proc, #an-piste-cat, #an-piste-eq{
    margin-left:-32px; margin-right:-32px;
  }
  /* Les pistes sortent de 32 px pour toucher les bords ; leurs panneaux les
     rendent à l'intérieur. Le compte retombe exactement sur la colonne des
     titres. */
  #p-membre .fm-piste .fm-pan,
  #an-piste-proc .fm-pan, #an-piste-cat .fm-pan, #an-piste-eq .fm-pan{
    padding-left:32px; padding-right:32px;
  }
  /* Tout le reste hérite de l'écran : aucune règle par élément, donc aucune
     colonne qui dérive. */
  #p-membre .fm-titre, #p-membre .fm-rep, #p-membre .fm-barre, #p-membre .fm-periode-mot,
  #p-an-temps .fm-titre, #p-an-temps .fm-barre, #p-an-temps .fm-periode-mot,
  #p-an-categories .fm-titre, #p-an-categories .fm-barre, #p-an-categories .fm-periode-mot,
  #p-an-equipe .fm-titre, #p-an-equipe .fm-barre, #p-an-equipe .fm-periode-mot{
    padding-left:0; padding-right:0;
  }

  .dv-piste{
    overflow-x:auto; overflow-y:hidden;
    -webkit-overflow-scrolling:touch; scrollbar-width:none;
    /* `pan-x` SEUL : la frise ne se déplace plus que sur l'horizontale. Avec
       `pinch-zoom` en plus, iOS autorisait un léger glissement vertical qui
       faisait trembler la piste sous le doigt. */
    touch-action:pan-x;
    overscroll-behavior-x:contain;
  }
  .dv-piste::-webkit-scrollbar{ display:none; }

  /* La largeur est posée EN PIXELS par le code.

     En pourcentage, elle se calculait sur la zone de contenu de la piste — que
     le retrait de la moitié de l'écran de chaque côté avait réduite à zéro. La
     frise faisait donc 500 % de rien. */
  .dv-frise{
    position:relative; height:44px; border-radius:11px;
    background:rgba(255,255,255,0.06); border:0.5px solid var(--border);
    flex-shrink:0;
  }
  .dv-fond{ position:absolute; inset:0; border-radius:11px; overflow:hidden; }
  /* Pendant le geste, la frise se signale légèrement : on sait qu'on la tient. */
  /* `touch-action:none` empêchait le défilement au doigt : il restait d'un geste
     écrit à la main, que le défilement natif a remplacé. `pan-x` autorise le
     glissement horizontal — c'est exactement ce qu'on veut — et laisse le
     pincement au navigateur. */
  .dv-frise{ touch-action:pan-x; transition:box-shadow 0.15s ease; }

  .dv-frise.tire{ box-shadow:0 0 0 1.5px rgba(255,255,255,0.28); }
  .dv-seg{
    position:absolute; top:0; bottom:0; border-right:1.5px solid var(--bg);
    background:rgba(255,179,64,0.30); display:flex; align-items:center;
    justify-content:center; font-size:9.5px; font-weight:800; color:#fff;
  }
  .dv-seg.sel{ background:rgba(255,179,64,0.62); }
  .dv-tete{
    position:absolute; top:0; bottom:0; left:0; width:2px; background:#fff; z-index:4;
    box-shadow:0 0 8px rgba(255,255,255,0.7); pointer-events:none;
  }
  .dv-tps{
    display:flex; justify-content:space-between; padding:6px 2px 0;
    font-size:11px; color:var(--label-3);
    font-family:ui-monospace, SFMono-Regular, Menlo, monospace;
  }

  /* ═══ LES TRAITS DÉPLAÇABLES ═══

     Chaque coupure porte un trait blanc qu'on peut faire glisser. Le geste est
     rare mais indispensable : on appuie toujours un peu trop tard, et sans lui
     il fallait tout refaire pour rattraper une demi-seconde.

     La zone de saisie déborde largement du trait — 22 px de large pour 2 px
     visibles. Un trait de 2 px ne se saisit pas au doigt. */
  /* La zone de saisie DÉBORDE de la frise, en haut comme en bas : 26 px de haut
     ne suffisent pas à attraper un trait au doigt. Elle fait 44 px de large et
     dépasse de 12 px de chaque côté — invisible, mais on l'attrape du premier
     coup au lieu de viser. */
  .dv-poi{
    position:absolute; top:-12px; bottom:-12px; width:44px; margin-left:-22px;
    z-index:6; cursor:ew-resize; touch-action:none;
    display:flex; align-items:center; justify-content:center;
  }
  .dv-poi::before{ margin:12px 0; }

  /* La tête de lecture, telle qu'elle était : un simple trait blanc. La pastille
     ronde que j'avais ajoutée faisait un objet de plus dans une frise qui en
     porte déjà beaucoup. Le geste se prend sur toute la frise, pas sur le trait
     — il n'a donc pas besoin d'être saisissable, ni de le montrer. */
  /* Le trait ne bouge plus : il est planté au milieu, du haut au bas de la vue.
     C'est la piste qui glisse dessous. */
  .dv-tete{
    position:absolute; top:4px; bottom:4px; left:50%; width:2.5px; margin-left:-1.25px;
    background:#fff; z-index:6; border-radius:2px;
    box-shadow:0 0 10px rgba(255,255,255,0.8);
    pointer-events:none;
  }
  /* Une petite pointe en haut, comme sur un curseur de montage. */
  .dv-tete::before{
    content:''; position:absolute; top:-4px; left:50%; margin-left:-5px;
    border-left:5px solid transparent; border-right:5px solid transparent;
    border-top:6px solid #fff;
  }

  /* Les deux outils sous la frise. */
  .dv-outils{ display:flex; align-items:center; gap:8px; padding:2px 0 0; }
  .dv-zoom, .dv-annuler{
    display:flex; align-items:center; gap:7px; padding:9px 14px;
    border-radius:100px; border:0.5px solid var(--border);
    background:rgba(255,255,255,0.06); color:var(--label-2);
    font-family:inherit; font-size:12.5px; font-weight:650;
  }
  .dv-zoom svg, .dv-annuler svg{ width:15px; height:15px; flex-shrink:0; }
  .dv-zoom .ic-serre{ display:none; }
  .dv-zoom.large .ic-large{ display:none; }
  .dv-zoom.large .ic-serre{ display:block; }
  .dv-annuler{ margin-left:auto; }
  .dv-annuler:disabled{ opacity:0.35; }
  .dv-zoom:active, .dv-annuler:not(:disabled):active{ transform:scale(0.94); }
  .dv-poi::before{
    content:''; width:2px; height:100%; border-radius:2px;
    background:#fff; box-shadow:0 0 6px rgba(0,0,0,0.5);
    transition:width 0.15s ease, box-shadow 0.15s ease;
  }
  .dv-poi::after{
    content:''; position:absolute; top:50%; margin-top:-7px;
    width:12px; height:14px; border-radius:4px; background:#fff;
    box-shadow:0 1px 4px rgba(0,0,0,0.4);
    transition:transform 0.15s cubic-bezier(0.34,1.56,0.64,1);
  }
  .dv-poi:active::after, .dv-poi.tire::after{ transform:scale(1.22); }
  .dv-poi.tire::before{ width:3px; box-shadow:0 0 12px rgba(255,255,255,0.8); }

  /* ═══ LA PRISE ═══
     Le carré visible fait 12 px, mais la zone touchable en fait 44 — la largeur
     d'un doigt. C'est déjà le cas ; ce qui manquait, c'est de le VOIR : sous
     le doigt, la poignée grossit franchement pour qu'on sache qu'on la tient. */
  .dv-poi.tire::after{
    transform:scale(1.5);
    box-shadow:0 2px 10px rgba(0,0,0,0.55), 0 0 0 4px rgba(255,255,255,0.16);
  }
  /* La piste figée ne défile plus : le défilement natif lutterait contre le
     doigt qui tire la poignée. */
  .dv-piste.fige{
    overflow-x:hidden;
    touch-action:none;
  }
  /* La poignée passe DEVANT la piste et capte le geste en premier. Sans cette
     priorité, le défilement horizontal de la piste attrapait le doigt avant
     elle : on croyait tirer la coupure, on faisait défiler la frise. */
  .dv-poi{ z-index:12; touch-action:none; }

  /* Le temps de la coupure, montré pendant qu'on la déplace. */
  .dv-poi .val{
    position:absolute; bottom:calc(100% + 7px); left:50%; transform:translateX(-50%) scale(0.9);
    padding:3px 8px; border-radius:7px; white-space:nowrap;
    background:#fff; color:#000; font-size:11px; font-weight:750;
    font-variant-numeric:tabular-nums; opacity:0; pointer-events:none;
    transition:opacity 0.14s ease, transform 0.14s cubic-bezier(0.34,1.56,0.64,1);
  }
  .dv-poi.tire .val{ opacity:1; transform:translateX(-50%) scale(1); }

  /* Le bouton de lecture, sous la frise et à gauche du temps. */
  /* Les commandes, dans le coin bas gauche de l'image. */
  .dv-cmd{
    position:absolute; left:10px; bottom:10px; z-index:5;
    display:flex; align-items:center; gap:8px;
  }
  .dv-rond{
    width:38px; height:38px; border-radius:50%; border:none; padding:0; flex-shrink:0;
    background:rgba(0,0,0,0.45); backdrop-filter:blur(18px);
    -webkit-backdrop-filter:blur(18px);
    border:0.5px solid rgba(255,255,255,0.18); color:#fff;
    display:flex; align-items:center; justify-content:center;
  }
  .dv-rond svg{ width:17px; height:17px; display:block; }
  .dv-rond:active{ transform:scale(0.9); }
  #dv-play .ic-pause{ display:none; }
  #dv-play.joue .ic-play{ display:none; }
  #dv-play.joue .ic-pause{ display:block; }

  /* « Compléter avec l'IA » au-dessus de « Publier » : sans fond ni bordure,
     pour ne pas concurrencer le bouton principal. */
  .dv-ia-bas{
    display:flex; align-items:center; justify-content:center; gap:10px;
    width:100%; padding:14px 0 13px; margin-top:14px;
    background:none; border:none; color:#fff;
    font-family:inherit; font-size:15px; font-weight:650; letter-spacing:-0.02em;
  }
  .dv-ia-bas:disabled{ color:var(--label-3); }
  /* L'anneau garde sa lumière même quand le bouton est éteint. Il était assombri
     avec le reste — or pendant le travail c'est la SEULE chose à l'écran, et une
     lumière éteinte donne l'impression que rien ne tourne. */
  .dv-ia-bas:disabled .ia-mot{ opacity:1; }
  .dv-ia-bas:active{ opacity:0.6; }

  /* TROIS ÉTATS.

     Au repos  : l'anneau et le texte.
     Pendant   : l'anneau seul — le texte disparaît, il n'y a plus rien à décider
                 et une phrase qui reste sous un bouton désactivé donne envie
                 d'appuyer encore.
     À la fin  : la coche, quelques secondes, puis retour au repos. */
/* ═══ LA MARQUE DEVIENT L'ANNEAU ═══

     Au repos, on lit « AI » : c'est le nom de ce qu'on demande. Dès qu'on
     appuie, les lettres s'effacent et l'anneau prend leur place — exactement
     leur place, puisqu'ils occupent la même case.

     Deux éléments superposés plutôt qu'un remplacement : rien ne saute, rien ne
     se décale. La marque rétrécit, l'anneau grandit, et le texte glisse hors
     champ pendant ce temps. Ce qui reste est centré. */
  /* Le bouton « Générer les étapes » suit la même métamorphose que celui du
     découpage : les lettres AI cèdent la place à l'anneau, dans la même case. */
  #ai-launch-btn .ia-case{
    display:grid; place-items:center; width:24px; height:24px; flex-shrink:0;
  }
  #ai-launch-btn .ia-mot,
  #ai-launch-btn .ia-roue,
  #ai-launch-btn .ia-coche{
    grid-area:1 / 1;
    transition:opacity 0.24s ease, transform 0.34s cubic-bezier(0.34,1.4,0.64,1);
  }
  #ai-launch-btn .ia-roue{ display:grid; opacity:0; transform:scale(0.5); }
  #ai-launch-btn .ia-coche{ display:block; opacity:0; transform:scale(0.5); width:24px; height:24px; }
  #ai-launch-btn.travaille .ia-mot{ opacity:0; transform:scale(0.5); }
  #ai-launch-btn.travaille .ia-roue{ opacity:1; transform:scale(1); }
  #ai-launch-btn.fini .ia-mot,
  #ai-launch-btn.fini .ia-roue{ opacity:0; transform:scale(0.5); }
  #ai-launch-btn.fini .ia-coche{ opacity:1; transform:scale(1); }

  .dv-ia-bas{ position:relative; }
  .dv-ia-bas .ia-mot,
  .dv-ia-bas .ia-roue{
    grid-area:1 / 1;
    transition:opacity 0.24s ease, transform 0.34s cubic-bezier(0.34,1.4,0.64,1);
  }
  /* La case commune. */
  .dv-ia-bas .ia-case{
    display:grid; place-items:center; width:24px; height:24px; flex-shrink:0;
  }
  .dv-ia-bas .ia-roue{ display:grid; opacity:0; transform:scale(0.5); }
  .dv-ia-bas.travaille .ia-mot{ opacity:0; transform:scale(0.5); }
  .dv-ia-bas.travaille .ia-roue{ opacity:1; transform:scale(1); }
  .dv-ia-bas.fini .ia-mot,
  .dv-ia-bas.fini .ia-roue{ opacity:0; transform:scale(0.5); }

  .dv-ia-bas .ia-coche{
    grid-area:1 / 1; opacity:0; transform:scale(0.5);
    transition:opacity 0.24s ease, transform 0.34s cubic-bezier(0.34,1.4,0.64,1);
    width:24px; height:24px;
  }
  .dv-ia-bas.fini .ia-coche{ display:block; opacity:1; transform:scale(1); }
  .dv-ia-bas .ia-coche svg{ width:24px; height:24px; display:block; }

  .dv-ia-bas #vid-ia-bas-txt{
    transition:opacity 0.25s ease, max-width 0.35s cubic-bezier(0.32,0.72,0,1);
    max-width:280px; overflow:hidden; white-space:nowrap;
  }
  .dv-ia-bas.travaille #vid-ia-bas-txt,
  .dv-ia-bas.fini #vid-ia-bas-txt{ opacity:0; max-width:0; }
  .dv-ia-bas.travaille, .dv-ia-bas.fini{ gap:0; }

  .dv-ia-bas.fini .ia-mot{ display:none; }
  .dv-ia-bas.fini .ia-coche{
    display:block;
    animation:cocheArrive 0.45s cubic-bezier(0.34,1.5,0.64,1) both;
  }
  @keyframes cocheArrive{
    0%{ transform:scale(0.4); opacity:0; }
    100%{ transform:scale(1); opacity:1; }
  }
  .dv-play{
    width:34px; height:34px; border-radius:50%; border:none; padding:0; flex-shrink:0;
    background:rgba(255,255,255,0.10); border:0.5px solid var(--border); color:#fff;
    display:flex; align-items:center; justify-content:center;
  }
  .dv-play svg{ width:15px; height:15px; display:block; }
  .dv-play .ic-pause{ display:none; }
  .dv-play.joue .ic-play{ display:none; }
  .dv-play.joue .ic-pause{ display:block; }
  .dv-play:active{ transform:scale(0.9); }

  .dv-geste{ padding:14px 0 4px; }
  .dv-geste button{
    width:100%; height:56px; border:none; border-radius:18px; font-family:inherit;
    font-size:16px; font-weight:750; display:flex; align-items:center;
    justify-content:center; gap:10px; background:#fff; color:#000;
    transition:background 0.18s, color 0.18s;
  }
  .dv-geste button.coupe{ background:#FFB340; color:#2E1B00; }
  .dv-geste svg{ width:21px; height:21px; }
  .dv-aide{
    font-size:11.5px; color:var(--label-3); text-align:center;
    padding:9px 18px 0; line-height:1.45;
  }

  /* L'étape en train de se faire, tant qu'on n'a pas coupé. */
  .etape-montage{
    display:flex; gap:11px; padding:10px; border-radius:15px; align-items:center;
    background:var(--bg-card); border:1px solid transparent; margin-bottom:8px;
  }
  .etape-montage.sel{ border-color:rgba(255,179,64,0.5); background:rgba(255,179,64,0.10); }
  .etape-montage .vig{
    width:56px; height:32px; border-radius:7px; flex-shrink:0; background:#000;
    border:0.5px solid var(--border); overflow:hidden;
  }
  .etape-montage .vig canvas{ width:100%; height:100%; display:block; }
  .etape-montage .tx{ flex:1; min-width:0; }
  .etape-montage textarea{
    width:100%; border:none; background:none; color:#fff; font-family:inherit;
    font-size:13.5px; font-weight:600; line-height:1.35; resize:none; padding:0; outline:none;
  }
  .etape-montage textarea::placeholder{ color:var(--label-3); font-weight:500; }
  .etape-montage i{
    display:block; font-style:normal; font-size:10.5px; color:var(--label-3);
    font-family:ui-monospace, monospace; margin-top:3px;
  }
  .etape-montage .sup{
    width:30px; height:30px; border-radius:50%; border:none; flex-shrink:0;
    background:rgba(255,255,255,0.07); color:var(--label-3);
    display:flex; align-items:center; justify-content:center;
  }
  .etape-montage .sup svg{ width:15px; height:15px; }

  .dv-encours{
    display:flex; gap:11px; padding:10px; border-radius:15px; align-items:center;
    border:1px dashed rgba(255,179,64,0.5); margin-bottom:8px;
    font-size:13.5px; font-weight:600; color:var(--label-2);
  }
  .dv-encours .vig{
    width:56px; height:32px; border-radius:7px; flex-shrink:0; background:#000;
    border:0.5px solid var(--border); overflow:hidden;
  }
  .dv-encours .vig canvas{ width:100%; height:100%; display:block; }
  .dv-encours i{
    display:block; font-style:normal; font-size:10.5px; color:var(--label-3);
    font-family:ui-monospace, monospace; margin-top:3px; font-weight:500;
  }


  /* ═══ Image d'une étape manuelle ═══
     Une photo du résultat attendu vaut souvent mieux qu'une phrase. Elle est
     facultative : l'étape reste valable sans. */
  .step-img{ display:flex; align-items:center; gap:10px; margin-top:10px; }
/* Plus petite. Dans une liste de saisie, la vignette rappelle qu'une photo
     existe — elle n'a pas à la montrer en grand : c'est le texte qu'on relit. */
    .step-img-vignette{
    width:76px; height:76px; border-radius:11px; flex-shrink:0; overflow:hidden;
    background:rgba(255,255,255,0.06); border:0.5px solid var(--border);
    display:flex; align-items:center; justify-content:center; position:relative;
  }
  .step-img-vignette img{ width:100%; height:100%; object-fit:cover; display:block; }
  .step-img-vignette svg{ width:19px; height:19px; color:var(--label-3); }
  .step-img-vignette .att{
    position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
    background:rgba(0,0,0,0.55); font-size:9px; font-weight:700;
  }
  /* ═══ La photo d'une étape ═══
     La vignette EST la commande : on la touche pour choisir, la remplacer ou la
     retirer. Le bouton séparé doublait la cible sans rien ajouter, et sur un
     téléphone deux cibles côte à côte se manquent. */
  .step-img{ display:flex; align-items:center; gap:11px; margin-top:10px; }
  .step-img-vignette{
    width:56px; height:56px; border-radius:11px; flex-shrink:0; overflow:hidden;
    background:rgba(255,255,255,0.06); border:0.5px solid var(--border);
    display:flex; align-items:center; justify-content:center; position:relative;
    transition:transform 0.16s, border-color 0.2s;
  }
  .step-img-vignette:active{ transform:scale(0.94); border-color:rgba(255,255,255,0.3); }
  .step-img-vignette img{ width:100%; height:100%; object-fit:cover; display:block; }
  .step-img-vignette svg{ width:19px; height:19px; color:var(--label-3); }
  /* Le petit « + » dit que la vignette se touche, là où un cadre vide ne dit rien. */
  .step-img-vignette .att{
    position:absolute; right:-3px; bottom:-3px; width:19px; height:19px;
    border-radius:50%; background:#fff; color:#000; border:2px solid var(--bg-card);
    display:flex; align-items:center; justify-content:center;
    font-size:13px; font-weight:700; line-height:0;
  }
  .img-toucher{
    flex:1; min-width:0; text-align:left; border:none; background:none; padding:0;
    color:var(--label-3); font-family:inherit; font-size:12.5px; font-weight:600;
  }
  .step-img input[type=file]{ display:none; }


  /* Côté employé : l'image au-dessus du texte de l'étape. */
  /* Même raison pour la photo d'une étape : elle illustre un geste, elle ne doit
     pas pousser l'étape suivante hors de l'écran. */
  /* Carrée et centrée : la photo illustre un geste, elle n'a pas à tenir toute la
     largeur ni à repousser l'étape suivante hors de l'écran. */
  /* À gauche et plus petite. Centrée et large, elle prenait le pas sur le
     texte de l'étape — or elle l'illustre, elle ne le remplace pas. Alignée sur
     la marge du texte, l'œil descend en ligne droite d'une étape à l'autre. */
  .detail-step-img{
    width:88px; height:88px; margin:10px 0 2px;
    border-radius:14px; overflow:hidden;
    border:0.5px solid var(--border); background:rgba(255,255,255,0.04);
    display:flex; align-items:center; justify-content:center;
  }
  .detail-step-img img{ width:100%; height:100%; object-fit:cover; display:block; }

  /* ═══ Disparition d'une carte ═══
     La carte se replie sur elle-même et les suivantes remontent. Sans ça, la
     procédure disparaît d'un coup et on doute d'avoir supprimé la bonne. */
  @keyframes carteSeReplie{
    0%   { opacity:1; transform:scale(1);     max-height:var(--h); margin-bottom:var(--mb); }
    45%  { opacity:0; transform:scale(0.88);  max-height:var(--h); margin-bottom:var(--mb); }
    100% { opacity:0; transform:scale(0.88);  max-height:0; margin-bottom:0; padding-top:0; padding-bottom:0; border-width:0; }
  }
  .carte-part{
    overflow:hidden; pointer-events:none;
    animation:carteSeReplie 0.44s cubic-bezier(0.4,0,0.2,1) forwards;
  }
  @media (prefers-reduced-motion: reduce){
    .carte-part{ animation-duration:0.01s; }
  }

  /* ═══ Carte de contact ═══
     Même habit que la carte d'accueil — fond sombre, texte à gauche, avatar à
     droite — mais celle-ci se touche. */
  .contact-carte{ cursor:pointer; transition:transform 0.2s cubic-bezier(0.34,1.5,0.64,1); }
  .contact-carte:active{ transform:scale(0.985); }
  .contact-carte .t{ font-size:16px; font-weight:700; letter-spacing:-0.03em; }
  .contact-carte .s{ font-size:12.5px; color:var(--label-2); margin-top:3px; line-height:1.45; }

  /* ═══ Choix de la langue ═══ */
  .langue-grille{ display:grid; grid-template-columns:repeat(2,1fr); gap:7px; }
  .langue-choix{
    display:flex; align-items:center; gap:9px; padding:10px 12px; border-radius:12px;
    border:1px solid var(--border); background:var(--bg-card); color:#fff;
    font-family:inherit; font-size:13px; font-weight:600; text-align:left;
    transition:border-color 0.2s, background 0.2s;
  }
  .langue-choix .dr{ font-size:17px; line-height:1; flex-shrink:0; }
  .langue-choix .nm{ flex:1; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .langue-choix.actif{ border-color:#fff; background:rgba(255,255,255,0.12); }
  .langue-choix .coche{ color:#FFAD33; font-weight:800; flex-shrink:0; }

  /* Le bouton de langue sur une fiche de procédure */
  .langue-proc{
    display:flex; align-items:center; gap:10px; text-align:left; margin-bottom:6px;
  }
  .langue-proc .ic{ font-size:16px; flex-shrink:0; }
  .langue-proc .tx{ flex:1; min-width:0; }
  .langue-proc .fl{ color:var(--label-3); flex-shrink:0; }
  .langue-proc.traduit{ border-color:rgba(245,166,35,0.4); background:rgba(245,166,35,0.10); }

  /* Bandeau rappelant qu'on lit une traduction */

  /* ═══ Anneau d'analyse sans avancement connu ═══
     Quand personne ne sait où en est le calcul, l'anneau tourne au lieu de se
     remplir. Un mouvement continu dit « ça travaille » sans prétendre savoir
     combien il reste — ce qu'un pourcentage, lui, prétend toujours. */
  @media (prefers-reduced-motion: reduce){
  }

  /* ═════════════════════════════════════════════════════════════════════
     LE TIROIR DES ÉTABLISSEMENTS
     Fermé, il ne montre que l'établissement courant : c'est lui le bouton. Il
     s'élargit sur place, et la carte au logo s'efface le temps du choix — rien
     n'est poussé, rien ne recouvre l'écran.
     ═══════════════════════════════════════════════════════════════════ */
  .verre-barre{
    background:rgba(255,255,255,0.10); border:0.5px solid rgba(255,255,255,0.18);
    -webkit-backdrop-filter:blur(24px) saturate(180%); backdrop-filter:blur(24px) saturate(180%);
    box-shadow:inset 0 1px 0 rgba(255,255,255,0.14);
  }
  /* ═════════════════════════════════════════════════════════════════
     LE TIROIR DES ÉTABLISSEMENTS

     Plus de pastille de verre autour : le cercle sombre occupe toute la place,
     comme le bouton des réglages à l'autre bout de la barre. Même diamètre,
     même présence.

     Le tiroir garde une largeur FIXE de 44 px dans la barre. Ce qui s'ouvre est
     posé par-dessus, en absolu : rien ne pousse, rien ne se décale, et le
     dépliage se fait vers la droite, là où se trouve la carte au logo — qui
     s'efface le temps du choix.

     Les mouvements reprennent la courbe de la barre d'onglets :
     0,44 s, cubic-bezier(0.32, 0.72, 0, 1).
     ═════════════════════════════════════════════════════════════════ */
  .topbar-row{ position:relative; }

  .tiroir-ent{
    /* 46 px : exactement le diamètre du bouton des réglages, à l'autre bout de
       la barre. Les deux ronds se répondent. */
    /* 46 px : la taille exacte du bouton des réglages. Fermé, le tiroir lui
       répond trait pour trait à l'autre bout de la barre. */
    position:relative; width:46px; height:46px; flex:0 0 46px;
    /* Le flou d'arrière-plan a besoin d'une couche à lui pour échantillonner ce
       qui passe derrière. Sans cette isolation, il peut ne rien produire selon
       l'ordre de composition — le rond apparaît alors plat, sans verre. */
    isolation:isolate;
  }
  .tiroir-ent.masque{ display:none; }

  /* Posée en absolu : sa largeur ne compte pas dans la barre, donc rien ne bouge
     quand elle s'étend.

     C'est ELLE qui porte le verre, pas les ronds : fermée, elle épouse
     exactement le cercle unique et se lit donc comme un rond de verre ; ouverte,
     elle s'étire en pastille autour de tous. Le verre se déplie avec le tiroir
     au lieu d'être répété sur chaque cercle. */
  /* Comme la carte du logo : plus aucune matière ici, seulement la géométrie.
     Le verre vient d'un seul endroit, en bas de cette feuille. */
  .tiroir-liste{
    position:absolute; left:0; top:0; z-index:12;
    display:flex; align-items:center; gap:0;
    /* Hauteur et remplissage FIXES : rien ne grossit. Seule la largeur change,
       et la pastille est ancrée à gauche — elle ne peut donc s'étendre que vers
       la droite. Fermée, elle fait 46 px de côté. */
    height:46px; padding:4px;
    border-radius:100px;
  }

  /* Le même verre que le bouton des réglages, à l'autre bout de la barre :
     mêmes valeurs exactes de teinte, de flou, de liseré et d'ombre. Les deux
     ronds sont taillés dans la même matière. */
  /* Les ronds sont transparents : le verre est derrière eux, porté par le
     tiroir. Superposer deux verres aurait doublé la teinte et le flou. */
  /* Le rond de tête passe DEVANT les autres : ils semblent alors sortir de
     derrière lui, et y rentrer à la fermeture. Sans ça ils glissaient par-dessus,
     ce qui n'évoquait rien de physique. */
  .tiroir-liste > .rond-ent{ z-index:2; }
  /* 38 px, plus 4 px de remplissage de chaque côté : la pastille fermée fait donc
     46 px, la taille du bouton des réglages. Aucun fond, aucun contour — seul le
     contenu se voit, et la pastille tient lieu de cercle. */
  .rond-ent{
    position:relative; width:38px; height:38px; flex-shrink:0; border-radius:50%;
    overflow:hidden; padding:0; display:flex; align-items:center; justify-content:center;
    background:none; border:none;
    transition:transform 0.18s cubic-bezier(0.34,1.56,0.64,1);
  }
  .rond-ent:active{ transform:scale(0.92); }
  /* L'établissement courant ne porte plus d'anneau : dans le tiroir fermé c'est
     forcément lui qu'on voit, et dans la liste la mention « actif » le dit déjà.
     Un rond identique aux autres, comme le bouton des réglages. */
  .rond-ent img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
  /* La lisibilité ne vient plus d'un fond — un fond aurait masqué le verre —
     mais d'une ombre portée sous les lettres. Elle les détache de ce qui passe
     derrière sans rien opacifier. */
  .rond-ent .ini{
    position:relative; font-size:15px; font-weight:700; letter-spacing:0.03em;
    color:#fff;
    text-shadow:0 1px 3px rgba(0,0,0,0.65), 0 0 9px rgba(0,0,0,0.45);
  }
  /* Le « + » est une action, pas un établissement : il se distingue par une
     taille moindre plutôt que par une couleur de plus. */
  .rond-ent.plus{ background:#fff; border-color:transparent; }
  /* Le « + » est noir sur blanc : l'ombre portée qui détache les initiales sur le
     verre n'a plus lieu d'être ici, et elle formait un halo autour du signe. */
  .rond-ent.plus .ini{
    color:#000; font-size:23px; font-weight:400; line-height:0; margin-top:-1px;
    text-shadow:none;
  }

  /* Les autres établissements et le « + » restent dans le document en
     permanence : c'est ce qui permet de les animer à la fermeture autant qu'à
     l'ouverture. Les retirer les faisait disparaître d'un coup. */
  /* Le groupe des autres se replie sur zéro : sans ça il garderait sa largeur,
     et le verre resterait étiré même tiroir fermé. */
  /* La largeur du verre suit : à l'ouverture elle part devant pour faire de la
     place, à la fermeture elle attend que les ronds soient rentrés. */
  /* Un filet de verre entre chaque rond. L'espacement vit À L'INTÉRIEUR du groupe
     qui se replie : posé sur la liste, il aurait subsisté tiroir fermé et la
     pastille n'aurait plus été un cercle parfait. */
  /* AUCUN remplissage ici, et l'écart est porté par les ronds eux-mêmes. Un
     remplissage ne descend jamais sous sa valeur, même avec `max-width:0` : le
     groupe replié gardait donc 4 px, la pastille faisait 50 px de large pour 46
     de haut, et n'était plus un cercle. Une marge, elle, disparaît avec le
     contenu qu'elle espace. */
  .tiroir-autres{
    display:flex; align-items:center; gap:0;
    max-width:0; overflow:hidden;
    transition:max-width 0.44s cubic-bezier(0.32,0.72,0,1);
  }
  .tiroir-ent.ouvert .tiroir-autres{ max-width:300px; }
  /* UNE SEULE COURBE pour tout ce qui bouge ici : celle de la barre d'onglets,
     0,44 s et cubic-bezier(0.32, 0.72, 0, 1). Les ronds avaient un ressort que
     la carte au logo n'avait pas — les deux moitiés du geste ne s'accordaient
     donc jamais. Même courbe, même durée : un seul mouvement. */
  .tiroir-autres .rond-ent{
    margin-left:4px;
    opacity:0; transform:scale(0.55) translateX(-16px); pointer-events:none;
    transition:opacity 0.44s cubic-bezier(0.32,0.72,0,1),
               transform 0.44s cubic-bezier(0.32,0.72,0,1);
  }
  .tiroir-ent.ouvert .tiroir-autres .rond-ent{
    opacity:1; transform:none; pointer-events:auto;
  }

  /* Le rond de tête se creuse légèrement quand le tiroir est ouvert : il cède la
     place, et l'état se lit sans ornement supplémentaire. */
  .tiroir-liste > .rond-ent{
    transition:transform 0.44s cubic-bezier(0.32,0.72,0,1);
  }
  .tiroir-ent.ouvert .tiroir-liste > .rond-ent{ transform:scale(0.94); }

  /* La cascade. Les délais s'inversent selon le sens : à l'ouverture les ronds
     arrivent de gauche à droite, à la fermeture ils partent de droite à gauche.
     Sans ça, refermer serait la lecture à l'envers du même mouvement. */
  /* La cascade. Les délais s'inversent selon le sens : à l'ouverture les ronds
     arrivent de gauche à droite, à la fermeture ils partent de droite à gauche.
     Les pas sont resserrés — 40 millisecondes — pour que l'ensemble se lise
     comme un seul geste et non comme quatre départs séparés. */
  /* La cascade. Les délais s'inversent selon le sens : à l'ouverture les ronds
     arrivent de gauche à droite APRÈS le départ de la carte, à la fermeture ils
     partent de droite à gauche AVANT son retour. */
  /* Un souffle de décalage, pas une cascade : 30 millisecondes. Assez pour que
     les ronds ne partent pas d'un bloc, trop peu pour qu'on compte les départs. */
  .tiroir-autres .rond-ent:nth-child(1){ transition-delay:0.06s; }
  .tiroir-autres .rond-ent:nth-child(2){ transition-delay:0.03s; }
  .tiroir-autres .rond-ent:nth-child(n+3){ transition-delay:0s; }
  .tiroir-ent.ouvert .tiroir-autres .rond-ent:nth-child(1){ transition-delay:0s; }
  .tiroir-ent.ouvert .tiroir-autres .rond-ent:nth-child(2){ transition-delay:0.03s; }
  .tiroir-ent.ouvert .tiroir-autres .rond-ent:nth-child(3){ transition-delay:0.06s; }
  .tiroir-ent.ouvert .tiroir-autres .rond-ent:nth-child(n+4){ transition-delay:0.09s; }

  /* La carte au logo s'efface pendant le choix : c'est sa place qu'on occupe.
     L'ordre compte. À l'ouverture elle part la première, sans délai, et les ronds
     la suivent : la place se libère avant qu'on l'occupe. À la fermeture c'est
     l'inverse — elle attend que les ronds soient rentrés. Sans cet ordre, les
     deux se croisaient au milieu du geste. */
  /* La carte et la pastille bougent EXACTEMENT ensemble : même courbe, même
     durée, aucun décalage, dans les deux sens. J'avais essayé de les faire se
     succéder ; ça donnait deux gestes au lieu d'un. L'une se retire pendant que
     l'autre s'étend, au même rythme : c'est un échange, et ça se lit comme tel. */
  .topbar-card{
    transition:opacity 0.44s cubic-bezier(0.32,0.72,0,1),
               transform 0.44s cubic-bezier(0.32,0.72,0,1);
  }
  .tiroir-ent.ouvert ~ .topbar-card{
    opacity:0; transform:translateX(12px); pointer-events:none;
  }

  @media (prefers-reduced-motion: reduce){
    .tiroir-autres .rond-ent, .topbar-card{ transition:none; }
  }

  /* ═══ Bandeau de blocage ═══
     Un chargement qui n'aboutit pas ne dit rien de lui-même : l'écran reste
     gris, et personne ne sait pourquoi. Ce bandeau transforme un silence en
     symptôme lisible, avec de quoi le transmettre. */
  .bandeau-bloc{
    display:none; position:fixed; left:12px; right:12px; bottom:96px; z-index:500;
    padding:14px 16px; border-radius:18px;
    background:rgba(255,69,58,0.14); border:0.5px solid rgba(255,69,58,0.34);
    -webkit-backdrop-filter:blur(20px); backdrop-filter:blur(20px);
    box-shadow:0 16px 40px rgba(0,0,0,0.5);
  }
  .bandeau-bloc.on{ display:block; animation:bandeauArrive 0.4s cubic-bezier(0.34,1.4,0.5,1) both; }
  @keyframes bandeauArrive{
    0%  { opacity:0; transform:scale(0.975); }
    30% { opacity:1; }
    100%{ opacity:1; transform:none; }
  }
  .bandeau-bloc .t{ font-size:14px; font-weight:700; letter-spacing:-0.02em; margin-bottom:5px; }
  .bandeau-bloc .s{
    font-family:ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size:10.5px; line-height:1.5; color:var(--label-2);
    white-space:pre-wrap; word-break:break-word; max-height:120px; overflow-y:auto;
    -webkit-user-select:text; user-select:text;
  }

  /* ═══════════════════════════════════════════════════════════════════════
     LA PAGE ABONNEMENT

     CE BLOC AVAIT DISPARU. En retirant les paliers de zoom, mon découpage a
     emporté tout ce qui le précédait — le style des offres. La page continuait
     de s'afficher, mais sans aucune mise en forme : du texte nu et des icônes
     en pleine taille, faute de dimension imposée.

     Il est réécrit d'après ce que le balisage attend. Si certains détails
     diffèrent de l'original, dis-le-moi : je n'avais aucune copie pour le
     restaurer à l'identique.
     ═══════════════════════════════════════════════════════════════════════ */

  /* ═══ TOUT DANS UNE SEULE CARTE ═══

     `.abo-scene` n'avait plus que `position:relative` : le titre, l'offre, les
     garanties et le bouton flottaient les uns sous les autres sur le fond de la
     page, sans rien qui les rassemble. Ce n'était pas voulu — le fond faisait
     partie du bloc perdu en retirant le zoom, et je l'ai réécrit sans lui.

     La carte les tient ensemble : on lit UNE proposition, pas cinq morceaux.
     Le fond est un cran au-dessus du noir de la page — assez pour détacher,
     pas assez pour concurrencer la carte d'offre qui vit dedans. */
  .abo-scene{
    /* Quatre pixels séparaient le titre « Abonnement » de la carte : les deux
       se touchaient, et le titre paraissait collé dessus plutôt que posé
       au-dessus. Dix-huit suffisent à les séparer sans les éloigner. */
    margin-top:18px;
    position:relative;
    background:linear-gradient(165deg, #141418 0%, #0F0F13 55%, #0B0B0E 100%);
    border-radius:26px;
    padding:22px 16px 18px;
    box-shadow:inset 0 0 0 0.5px rgba(255,255,255,0.07),
               0 10px 34px rgba(0,0,0,0.34);
  }
  .abo-halo{
    position:absolute; top:-40px; left:50%; transform:translateX(-50%);
    width:280px; height:220px; pointer-events:none; z-index:0;
    background:radial-gradient(ellipse at center,
      rgba(255,154,31,0.16), rgba(255,154,31,0) 68%);
    filter:blur(8px);
  }
  .abo-hi{ position:relative; z-index:1; text-align:center; margin-bottom:20px; }
  .abo-hi h2{
    font-size:24px; font-weight:750; letter-spacing:-0.045em; line-height:1.18;
    margin-bottom:8px;
  }
  .abo-hi p{ font-size:13.5px; line-height:1.5; color:var(--label-3); }

  /* ── UNE OFFRE ── */
  /* ═══ PLUS SOMBRE QUE LES AUTRES CARTES ═══

     Elle prenait le gris des cartes ordinaires. Or celles-ci portent une liste
     ou un résumé, tandis que celle-ci EST la page : on ne vient ici que pour
     elle. Un fond plus profond la détache du reste et fait ressortir l'ambre,
     qui perdait de sa force sur un gris moyen.

     Un dégradé plutôt qu'un aplat : il donne de la matière sur une carte aussi
     haute, là où une couleur unique paraîtrait plate. */
  .offre-carte{
    position:relative; z-index:1;
    background:linear-gradient(160deg,#16161A 0%,#111114 52%,#0B0B0E 100%);
    border-radius:22px;
    padding:20px 18px; margin-bottom:12px;
    box-shadow:inset 0 0 0 0.5px rgba(255,255,255,0.07),
               0 8px 26px rgba(0,0,0,0.32);
  }
  /* Celle qu'on recommande porte le liseré ambre : c'est le seul signal, et il
     suffit. Son fond descend un cran plus bas encore — c'est ce qui fait
     ressortir le liseré. */
  .offre-carte.vedette{
    background:linear-gradient(150deg,#191920 0%,#0F0F13 48%,#08080A 100%);
    box-shadow:inset 0 0 0 1px rgba(255,173,51,0.42),
               0 16px 42px rgba(0,0,0,0.5);
  }
  .offre-carte.actuelle{ box-shadow:inset 0 0 0 1px rgba(255,255,255,0.16); }

  .offre-ruban{
    position:absolute; top:-9px; left:18px;
    padding:4px 11px; border-radius:100px;
    background:linear-gradient(135deg,#E85D00,#FF9A1F);
    font-size:10.5px; font-weight:750; letter-spacing:0.04em;
    text-transform:uppercase; color:#2A1400;
  }

  .offre-tete{ display:flex; align-items:flex-start; gap:12px; }
  .offre-txt{ flex:1; min-width:0; }
  .offre-nom{
    display:block; font-size:18px; font-weight:750; letter-spacing:-0.03em;
  }
  .offre-taille{
    display:block; font-size:11.5px; line-height:1.4; color:var(--label-3);
    margin-top:3px;
  }
  .offre-prix{ flex-shrink:0; text-align:right; white-space:nowrap; }
  .offre-prix .v{ font-size:26px; font-weight:800; letter-spacing:-0.045em; }
  .offre-prix .u{
    display:block; font-size:10.5px; font-weight:650; color:var(--label-3);
    margin-top:1px;
  }

  .offre-parmembre{
    margin-top:12px; padding-top:12px;
    border-top:0.5px solid var(--border);
    font-size:12.5px; line-height:1.45; color:var(--label-2);
  }
  .offre-parmembre b{ color:var(--label-1); font-weight:700; }

  .offre-etiq{
    margin:16px 0 10px; font-size:11px; font-weight:750;
    letter-spacing:0.06em; text-transform:uppercase; color:var(--label-3);
  }

  /* ── LES AVANTAGES ── */
  .offre-phares{ display:flex; flex-direction:column; gap:9px; }
  .offre-phare{ display:flex; align-items:center; gap:10px; }
  /* LA TAILLE DU PICTO EST INDISPENSABLE. Sans elle, un SVG sans hauteur
     déclarée s'affiche à sa taille naturelle — c'est ce qui donnait les
     symboles géants au milieu de la page. */
  .offre-phare .p{
    width:22px; height:22px; flex-shrink:0;
    display:grid; place-items:center; color:var(--label-2);
  }
  .offre-phare .p svg{ width:18px; height:18px; display:block; }
  .offre-phare .t{ font-size:13.5px; font-weight:600; }
  .offre-phare.vedette .p{ color:#FFAD33; }
  .offre-phare.vedette .t{ color:var(--label-1); font-weight:700; }

  .offre-aussi{
    margin-top:14px; font-size:12px; line-height:1.5; color:var(--label-3);
  }

  /* ── LE RYTHME DE PAIEMENT ── */
  .offre-rythme{ display:flex; flex-direction:column; gap:8px; margin-top:16px; }
  .rlg{
    display:flex; align-items:center; gap:11px; width:100%; text-align:left;
    padding:12px 14px; border-radius:14px;
    border:0.5px solid var(--border); background:rgba(255,255,255,0.03);
    font-family:inherit; color:var(--label-2);
    transition:border-color 0.2s, background 0.2s;
  }
  .rlg.on{
    border-color:rgba(255,173,51,0.5); background:rgba(255,173,51,0.07);
  }
  .rlg .rd{
    width:18px; height:18px; border-radius:50%; flex-shrink:0;
    display:grid; place-items:center;
    box-shadow:inset 0 0 0 1.5px rgba(255,255,255,0.22);
  }
  .rlg.on .rd{ box-shadow:inset 0 0 0 1.5px #FFAD33; }
  .rlg .rd i{
    width:9px; height:9px; border-radius:50%; display:block;
    background:transparent; transition:background 0.2s;
  }
  .rlg.on .rd i{ background:#FFAD33; }
  .rlg .tx{ flex:1; min-width:0; }
  .rlg .tx b{ display:block; font-size:13.5px; font-weight:700; color:var(--label-1); }
  .rlg .tx span{ display:block; font-size:11px; color:var(--label-3); margin-top:1px; }

  /* ── LE BOUTON ── */
  .offre-cta{
    width:100%; height:50px; margin-top:18px; border:none; border-radius:15px;
    font-family:inherit; font-size:14.5px; font-weight:750;
    background:linear-gradient(135deg,#E85D00,#F58A15 62%,#FF9F26);
    color:#2A1400;
  }
  .offre-carte:not(.vedette) .offre-cta{
    background:rgba(255,255,255,0.08); color:var(--label-1);
  }
  .offre-cta.encours{
    background:none; color:#FFB340;
    box-shadow:inset 0 0 0 1px rgba(255,179,64,0.35);
  }
  .offre-cta:active{ opacity:0.85; }

  /* ═══ LES AUTRES OFFRES SONT REPLIÉES ═══

     Elles s'affichaient toutes, sous un bouton « Voir les autres offres » qui
     n'avait donc plus rien à montrer. L'app posait pourtant déjà une classe
     `ouvert` sur la liste — c'est le style qui manquait, emporté avec le bloc
     que j'ai perdu tout à l'heure.

     `grid-template-rows` plutôt que `max-height` : on n'a pas à deviner une
     hauteur, et le dépliage reste juste quel que soit le nombre d'offres. */
  #abo-liste{
    display:grid; grid-template-rows:0fr;
    transition:grid-template-rows 0.42s cubic-bezier(0.32,0.72,0,1),
               opacity 0.3s ease, margin-top 0.42s cubic-bezier(0.32,0.72,0,1);
    opacity:0; margin-top:0;
  }
  #abo-liste > *{ overflow:hidden; min-height:0; }
  #abo-liste.ouvert{ grid-template-rows:1fr; opacity:1; margin-top:12px; }

  /* ── LE BAS DE PAGE ── */
  .abo-conf{
    display:flex; justify-content:center; gap:14px; flex-wrap:wrap;
    margin-top:14px; font-size:11.5px; font-weight:600; color:var(--label-3);
  }
  .abo-egal{
    margin-top:14px; padding:13px 15px; border-radius:16px;
    background:rgba(255,173,51,0.06);
    box-shadow:inset 0 0 0 0.5px rgba(255,173,51,0.16);
    font-size:12.5px; line-height:1.5; text-align:center; color:var(--label-2);
  }
  .abo-egal b{ color:var(--label-1); font-weight:750; }

  /* ═══════════════════════════════════════════════════════════════════════
     LE ZOOM DE BUREAU A ÉTÉ RETIRÉ

     `body{ zoom }` agrandissait tout de 1,3 à 2 selon la largeur de l'écran.
     L'intention était bonne — une colonne de téléphone perdue au milieu d'un
     grand écran n'est pas lisible de loin. Le résultat ne l'était pas.

     `zoom` MENT AUX MESURES. `getBoundingClientRect` rend des pixels zoomés,
     `style.left` s'écrit en pixels CSS : tout code qui mesure puis positionne
     se trompe d'un facteur deux. La barre du bas posait son dernier onglet à
     2 092 px pour une barre qui s'arrête à 1 214, et le clic tombait à côté.
     J'ai corrigé la barre — mais la même erreur guette partout ailleurs, à
     chaque fois qu'on mesurera quelque chose.

     Sans zoom, l'app garde sa colonne de 460 px sur tous les écrans. Plus
     petite sur un grand moniteur, mais JUSTE : ce qu'on mesure est ce qu'on
     voit. Un bandeau invite à passer sur le téléphone, pour qui ouvre l'app
     sur un ordinateur.
     ═══════════════════════════════════════════════════════════════════════ */


  .offre-gerer{
    width:100%; margin-top:10px; padding:11px 0;
    border:none; background:none;
    color:var(--label-2); font-family:inherit;
    font-size:13px; font-weight:600; text-decoration:underline;
    text-underline-offset:3px; text-decoration-color:var(--label-3);
  }
  .offre-gerer:active{ opacity:0.55; }
  .offre-gerer:disabled{ color:var(--label-3); text-decoration:none; }

  .offre-cta.encours{
    background:rgba(255,255,255,0.10);
    color:var(--label-2);
    border:0.5px solid var(--border);
    font-weight:650;
  }

  .offre-rythme{
    display:flex; gap:8px; margin-top:16px;
    padding-top:16px; border-top:0.5px solid var(--border);
  }
  .offre-rythme .rlg{
    flex:1; display:flex; align-items:center; gap:9px;
    padding:11px 12px; border-radius:14px; text-align:left;
    background:rgba(255,255,255,0.04); border:1px solid transparent;
    color:#fff; font-family:inherit;
  }
  .offre-rythme .rlg.on{
    border-color:rgba(255,255,255,0.45); background:rgba(255,255,255,0.09);
  }
  .offre-rythme .rlg:active{ transform:scale(0.98); }
  .offre-rythme .rd{
    width:18px; height:18px; border-radius:50%; flex-shrink:0;
    border:1.5px solid var(--label-3);
    display:flex; align-items:center; justify-content:center;
  }
  .offre-rythme .rlg.on .rd{ border-color:#fff; background:#fff; }
  .offre-rythme .rd i{ width:7px; height:7px; border-radius:50%; background:#000; display:none; }
  .offre-rythme .rlg.on .rd i{ display:block; }
  .offre-rythme .tx b{ display:block; font-size:13px; font-weight:700; }
  .offre-rythme .tx span{ display:block; font-size:10.5px; color:var(--label-3); margin-top:1px; }
  .offre-rythme .rlg.on .tx span{ color:var(--label-2); }

  .offre-annuel{ font-size:11.5px; color:var(--label-3); text-align:center; margin-top:11px; }
  .offre-annuel b{ color:#FFB340; font-weight:700; }

  /* ═══════════════════════════════════════════════════════════════════
     LES RÉGLAGES

     La grammaire d'iOS : des GROUPES de lignes, chacune avec sa tuile colorée à
     gauche, son libellé, sa valeur à droite et son chevron. Un filet sépare les
     lignes d'un même groupe ; un titre en petites capitales annonce chaque
     groupe ; une note explicative peut suivre.

     L'ordre suit celui d'Apple : qui vous êtes, puis ce que vous gérez, puis ce
     que vous payez, puis vos préférences, puis l'aide, et le départ en dernier.
     ═════════════════════════════════════════════════════════════════ */

  /* La fiche du haut : qui vous êtes. */
  .reg-identite{
    display:flex; align-items:center; gap:14px; width:100%; margin-top:14px;
    padding:15px 15px; border-radius:22px;
    background:var(--bg-card); border:0.5px solid var(--border);
    font-family:inherit; text-align:left; color:#fff;
    transition:transform 0.15s cubic-bezier(0.34,1.56,0.64,1);
  }
  .reg-identite:active{ transform:scale(0.99); }
  /* L'initiale porte la matière de la marque, comme les plaques des lignes en
     dessous. Le verre blanc d'avant appartenait à l'ancienne barre du haut, et
     il ne restait plus que là. */
  .reg-identite .av{
    width:52px; height:52px; border-radius:50%; flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
    font-size:18px; font-weight:750; letter-spacing:0.03em; color:#FFAD33;
    background:linear-gradient(165deg,
      rgba(255,173,51,0.13) 0%, rgba(255,173,51,0.05) 52%, rgba(255,173,51,0.015) 100%);
    border:0.5px solid rgba(255,173,51,0.22);
  }
  .reg-identite .tx{ flex:1; min-width:0; }
  .reg-identite .nm{
    display:block; font-size:17px; font-weight:750; letter-spacing:-0.03em;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  .reg-identite .st{
    display:block; font-size:12.5px; color:var(--label-3); margin-top:3px;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  .reg-identite .fl{ color:var(--label-3); font-size:19px; flex-shrink:0; }

  /* Le titre d'un groupe. */
  .reg-titre{
    font-size:11px; font-weight:750; color:var(--label-3);
    text-transform:uppercase; letter-spacing:0.06em;
    margin:22px 4px 8px;
  }

  /* Le groupe : une carte qui tient plusieurs lignes. */
  .reg-groupe{
    border-radius:20px; overflow:hidden;
    background:var(--bg-card); border:0.5px solid var(--border);
  }
  .reg-ligne{
    display:flex; align-items:center; gap:12px; width:100%;
    padding:11px 14px 11px 12px; border:none; background:none;
    font-family:inherit; text-align:left; color:#fff;
    transition:background 0.18s;
  }

  .reg-ligne:active{ background:rgba(255,255,255,0.06); }
  /* Le filet s'arrête à l'aplomb du texte, pas de la tuile : c'est ce qui donne
     le rythme des réglages d'iOS. */
  .reg-filet{ height:0.5px; background:var(--border); margin-left:58px; }

  /* La tuile reprend le verre de l'app plutôt que les aplats colorés d'iOS, et
     le glyphe est dessiné au trait comme les icônes de création : contour de
     devant à 78 %, second plan à 32 %. */
  /* La même plaque que partout : dossiers, sections d'analyse, réglages.
     Une seule matière pour tout ce qui porte une icône. */
  .reg-ic{
    width:34px; height:34px; border-radius:11px; flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
    background:linear-gradient(165deg,
      rgba(255,173,51,0.11) 0%, rgba(255,173,51,0.045) 52%, rgba(255,173,51,0.015) 100%);
    border:0.5px solid rgba(255,173,51,0.20);
  }
  .reg-ic svg{ width:19px; height:19px; display:block; }

  .reg-nm{ flex:1; min-width:0; font-size:15px; font-weight:600; letter-spacing:-0.02em; }
  .reg-val{
    font-size:14px; color:var(--label-3); flex-shrink:0;
    max-width:45%; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  .reg-val.mono{
    font-family:ui-monospace, SFMono-Regular, Menlo, monospace;
    letter-spacing:0.14em; color:#fff; font-weight:650;
  }
  .reg-ligne .fl{ color:var(--label-3); font-size:19px; flex-shrink:0; }
  /* Une ligne qui détruit n'a ni tuile ni chevron : rien à explorer, seulement
     un acte. Elle est centrée et rouge, comme chez Apple. */
  .reg-ligne.danger{ justify-content:center; padding:13px 14px; }
  /* `flex:0` mettait la base à zéro : le libellé se repliait sur lui-même.
     `flex:none` le laisse à sa largeur naturelle. */
  .reg-ligne.danger .reg-nm{
    flex:none; white-space:nowrap;
    font-size:15px; font-weight:650; color:var(--red);
  }

  .reg-note{
    font-size:12px; color:var(--label-3); line-height:1.5;
    margin:8px 6px 0; text-align:left;
  }
  .reg-version{
    font-size:11.5px; color:var(--label-3); text-align:center; margin-top:26px;
  }

  /* La liste des établissements adopte la même carte groupée. */
  .etab-ligne{
    display:flex; align-items:center; gap:12px; width:100%; padding:11px 13px;
    border-radius:16px; background:var(--bg-card); border:0.5px solid var(--border);
    margin-bottom:8px; font-family:inherit; text-align:left; color:#fff;
    transition:transform 0.15s cubic-bezier(0.34,1.56,0.64,1);
  }
  .etab-ligne:active{ transform:scale(0.985); }
  .etab-ligne .rond-ent{
    width:42px; height:42px;
    background:rgba(255,255,255,0.10);
    -webkit-backdrop-filter:blur(24px) saturate(180%); backdrop-filter:blur(24px) saturate(180%);
    border:0.5px solid rgba(255,255,255,0.18);
    box-shadow:inset 0 1px 0 rgba(255,255,255,0.12);
  }
  .etab-ligne .rond-ent .ini{ font-size:13px; }
  .etab-ligne .rond-ent.plus{ background:#fff; border-color:transparent; }
  .etab-ligne .rond-ent.plus .ini{
    color:#000; font-size:26px; font-weight:400; line-height:0; margin-top:-1px; text-shadow:none;
  }
  .etab-ligne .tx{ flex:1; min-width:0; }
  .etab-ligne .nm{
    display:block; font-size:14.5px; font-weight:650; letter-spacing:-0.02em;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  .etab-ligne .st{ display:block; font-size:12px; color:var(--label-3); margin-top:3px; }
  .etab-ligne .st b{ color:var(--blue); font-weight:650; }
  .etab-ligne .ici{
    display:inline-block; margin-left:7px; padding:2px 7px; border-radius:100px;
    background:rgba(48,209,88,0.16); color:var(--green);
    font-size:9.5px; font-weight:750; text-transform:uppercase; letter-spacing:0.04em;
    vertical-align:2px;
  }
  .etab-ligne .fl{ color:var(--label-3); font-size:18px; flex-shrink:0; }
  .etab-ligne.ajout{ border-style:dashed; background:none; }

  /* ═══ Les offres ═══
     Chaque offre porte une icône dans la langue des quatre modes de création :
     fiches en retrait à 16 et 26 %, celle de devant à 42 % sur un fond à 5 %,
     et le signe distinctif en blanc plein. Ce qui change d'une offre à l'autre,
     c'est le NOMBRE de fiches — une, deux, plusieurs, un réseau. Le dessin dit
     donc la même chose que le prix. */
  /* ═══ La page des offres ═══
     Ces règles avaient disparu en réécrivant le bloc voisin : la page s'affichait
     sans son cadre, sans son halo et sans ses rassurances. */
  /* Le bleu du halo, et lui seul. Le vert dit « terminé » ailleurs dans l'app :
     l'employer ici pour un prix brouillerait les deux. */
  .offre-annuel b{ color:#FFB340; font-weight:700; }

  @keyframes contenuEntre{
    from{ opacity:0; transform:translateY(12px); }
    to{ opacity:1; transform:none; }
  }
  .contenu-entre > *{
    animation:contenuEntre 0.5s cubic-bezier(0.22,1,0.36,1) both;
  }
  /* Un léger décalage entre les blocs : ils arrivent de haut en bas, comme on
     lit. Au-delà du quatrième on n'échelonne plus, sinon le bas de l'écran
     attendrait trop longtemps. */
  .contenu-entre > *:nth-child(1){ animation-delay:0s; }
  .contenu-entre > *:nth-child(2){ animation-delay:0.05s; }
  .contenu-entre > *:nth-child(3){ animation-delay:0.1s; }
  .contenu-entre > *:nth-child(n+4){ animation-delay:0.14s; }

  @media (prefers-reduced-motion: reduce){
    .contenu-entre > *{ animation:none; }
  }

  /* ═══ Tiroir des langues, sur la fiche d'une procédure ═══
     Il réutilise les classes du tiroir des établissements : même verre, même
     dépliage, même cascade. Une seule mécanique à comprendre et à maintenir. */
  /* Le tiroir de langue est un outil de lecture, pas une navigation : il se tient
     un cran en dessous de celui des établissements. */
  .tiroir-langue{ margin-bottom:6px; width:38px; height:38px; flex:0 0 38px; }

  /* Ce tiroir-ci est à droite de l'écran : il doit s'ouvrir vers la GAUCHE, sinon
     il sort de la page. On ancre la liste à droite et on inverse l'ordre des
     ronds, pour que la langue courante reste sous le doigt. */
  .tiroir-langue .tiroir-liste{ left:auto; right:0; flex-direction:row-reverse; }
  .tiroir-langue .tiroir-autres{ flex-direction:row-reverse; }
  .tiroir-langue .tiroir-autres .rond-ent{ margin-left:0; margin-right:4px; }
  .tiroir-langue .tiroir-autres .rond-ent{ transform:scale(0.55) translateX(16px); }
  .tiroir-langue.ouvert .tiroir-autres .rond-ent{ transform:none; }
  .tiroir-langue .tiroir-liste{ height:38px; padding:3px; }
  .tiroir-langue .rond-ent{ width:32px; height:32px; }
  .tiroir-langue .rond-ent .code{ font-size:10.5px; }
  .tiroir-langue .rond-ent .code{
    position:relative; font-size:12px; font-weight:750; letter-spacing:0.03em;
    color:#fff; text-shadow:0 1px 3px rgba(0,0,0,0.65), 0 0 9px rgba(0,0,0,0.45);
  }

  /* Pendant la traduction, le globe tourne. Un mouvement continu dit « ça
     travaille » sans prétendre savoir combien de temps ça prendra. */
  /* ═══ LE GLOBE TOURNE SUR SON AXE ═══

     Il pivotait comme une roue : le dessin entier faisait un tour, méridien
     compris. Un globe ne fait pas ça — son contour reste immobile, c'est ce
     qu'il y a DESSUS qui défile.

     On anime donc le seul méridien, en écrasant son ellipse jusqu'à la ligne
     puis en la rouvrant de l'autre côté. C'est exactement ce que fait un
     méridien qui passe devant nous.

     Deux règles se contredisaient aussi sur la taille — 17 px dans l'une,
     21 dans l'autre. Un carré qui n'en est pas un tourne de travers. */
  .tiroir-langue .rond-ent .terre{
    width:21px; height:21px; display:block; position:relative;
  }
  .tiroir-langue .rond-ent .terre ellipse{
    transform-origin:12px 12px;
    transform-box:view-box;
  }
  .tiroir-langue .rond-ent.patiente .terre ellipse{
    animation:meridien 1.5s ease-in-out infinite;
  }
  @keyframes meridien{
    0%,100%{ transform:scaleX(1); }
    50%    { transform:scaleX(0.06); }
  }

  .tiroir-langue .rond-ent.patiente{ opacity:0.75; }
  @media (prefers-reduced-motion: reduce){
  }

  /* ═══ Liste des établissements dans les réglages ═══
     Chaque ligne annonce l'ACTION possible, pas seulement l'état. « Aucun logo ·
     initiales utilisées » décrivait une situation sans dire qu'on pouvait la
     changer ; « ajouter un logo » le dit, et se voit parce que c'est en bleu. */
  .etab-ligne{
    display:flex; align-items:center; gap:12px; width:100%; padding:11px 13px;
    border-radius:16px; background:var(--bg-card); border:0.5px solid var(--border);
    margin-bottom:8px; font-family:inherit; text-align:left; color:#fff;
    transition:transform 0.15s cubic-bezier(0.34,1.56,0.64,1);
  }
  .etab-ligne:active{ transform:scale(0.985); }
  /* Hors du tiroir, le rond n'a pas de verre derrière lui : il le porte
     lui-même, aux valeurs exactes du bouton des réglages. */
  .etab-ligne .rond-ent{
    width:42px; height:42px;
    /* Hors du tiroir il n'y a pas de pastille derrière : le rond porte donc
       lui-même le verre, sinon il ne se verrait pas. */
    background:rgba(255,255,255,0.10);
    -webkit-backdrop-filter:blur(24px) saturate(180%); backdrop-filter:blur(24px) saturate(180%);
    border:0.5px solid rgba(255,255,255,0.18);
    box-shadow:inset 0 1px 0 rgba(255,255,255,0.12);
  }
  .etab-ligne .rond-ent .ini{ font-size:13px; }
  .etab-ligne .rond-ent.plus{ background:#fff; border-color:transparent; }
  .etab-ligne .tx{ flex:1; min-width:0; }
  .etab-ligne .nm{
    display:block; font-size:14.5px; font-weight:650; letter-spacing:-0.02em;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  .etab-ligne .st{ display:block; font-size:12px; color:var(--label-3); margin-top:3px; }
  .etab-ligne .st b{ color:var(--blue); font-weight:650; }
  .etab-ligne .ici{
    display:inline-block; margin-left:7px; padding:2px 7px; border-radius:100px;
    background:rgba(48,209,88,0.16); color:var(--green);
    font-size:9.5px; font-weight:750; text-transform:uppercase; letter-spacing:0.04em;
    vertical-align:2px;
  }
  .etab-ligne .fl{ color:var(--label-3); font-size:18px; flex-shrink:0; }
  .etab-ligne.ajout{ border-style:dashed; background:none; }

  /* ═══ Recherche dans l'équipe ═══ */
  .pm-recherche{
    position:relative; display:flex; align-items:center; gap:9px; margin-top:14px;
    padding:0 12px; height:44px; border-radius:14px;
    background:var(--bg-card); border:0.5px solid var(--border);
    color:var(--label-3);
  }
  .pm-recherche svg{ width:17px; height:17px; flex-shrink:0; }
  .pm-recherche input{
    flex:1; min-width:0; height:100%; border:none; background:none; padding:0;
    color:#fff; font-family:inherit; font-size:15px;
  }
  .pm-recherche input::placeholder{ color:var(--label-3); }
  .pm-recherche input::-webkit-search-cancel-button{ display:none; }
  .pm-recherche .vider{
    display:none; border:none; background:rgba(255,255,255,0.12); color:#fff;
    width:22px; height:22px; border-radius:50%; font-size:15px; line-height:0;
    flex-shrink:0; font-family:inherit;
  }
  .pm-recherche.remplie .vider{ display:flex; align-items:center; justify-content:center; }

  /* Changer le rang : même tuile de verre que les réglages, glyphe au trait.
     Pas de vert ni de rouge — monter et descendre ne sont ni un succès ni un
     danger, ce sont deux mouvements symétriques. */
  .pm-rang{
    width:34px; height:34px; border-radius:10px; flex-shrink:0; border:none; padding:0;
    display:flex; align-items:center; justify-content:center;
    background:rgba(255,255,255,0.08);
    border:0.5px solid rgba(255,255,255,0.14);
    box-shadow:inset 0 1px 0 rgba(255,255,255,0.10);
    transition:transform 0.15s cubic-bezier(0.34,1.56,0.64,1);
  }
  .pm-rang:active{ transform:scale(0.9); }
  .pm-rang svg{ width:18px; height:18px; display:block; }


  /* ═══ Changement de rôle ═══
     Même forme que la carte d'accueil : le texte à gauche, le visage à droite
     avec sa pastille verte. On ne crée pas un objet de plus pour une occasion
     unique — on réutilise celui que la personne connaît déjà. */
  .fond-promu{
    position:fixed; inset:0; z-index:460; display:flex; align-items:center; justify-content:center;
    padding:24px; background:rgba(0,0,0,0.6);
    -webkit-backdrop-filter:blur(16px); backdrop-filter:blur(16px);
    opacity:0; pointer-events:none; transition:opacity 0.3s ease;
  }
  .fond-promu.on{ opacity:1; pointer-events:auto; }
  .fen-promu{
    position:relative; width:100%; max-width:360px;
    transform:scale(0.92) translateY(14px); opacity:0;
    transition:transform 0.46s cubic-bezier(0.34,1.4,0.5,1), opacity 0.32s ease;
  }
  .fond-promu.on .fen-promu{ transform:none; opacity:1; }
  /* La carte reprend l'accueil, avec un fond un cran plus présent : c'est un
     moment, pas une ligne de plus dans une liste.

     `:not(.hero)` : la fenêtre « aucune entreprise » emploie la MÊME classe
     avec l'ancienne forme et son image. Sans cette exception, ce fond
     écraserait celui de `.hero` sur la carte de promotion. */
  .promu-carte:not(.hero){ background:linear-gradient(160deg,#1E2026,#141519); }

  /* La carte de promotion arrive avec un léger rebond : c'est une annonce, elle
     mérite d'être remarquée. L'animation portait sur l'avatar, qui n'existe
     plus — elle porte maintenant sur la carte entière. */
  .fen-promu .hero.promu-carte{
    animation:promuArrive 0.62s cubic-bezier(0.34,1.42,0.5,1) 0.05s both;
  }

  @keyframes promuArrive{
    from{ opacity:0; transform:scale(0.94) translateY(10px); }
    to{ opacity:1; transform:none; }
  }
  .fen-promu .avert{
    font-size:11.5px; color:var(--label-3); line-height:1.45;
    margin-top:12px; text-align:center;
  }
  @media (prefers-reduced-motion: reduce){
    .fen-promu .hero.promu-carte{ animation:none; }
  }

  /* ═══ Fenêtre d'un établissement ═══ */
  .fond-etab{
    position:fixed; inset:0; z-index:420; display:flex; align-items:center; justify-content:center;
    padding:24px; background:rgba(0,0,0,0.55);
    -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px);
    opacity:0; pointer-events:none; transition:opacity 0.28s ease;
  }
  .fond-etab.on{ opacity:1; pointer-events:auto; }
  .fen-etab{
    width:100%; max-width:340px; padding:24px 20px 18px; border-radius:26px; text-align:center;
    background:var(--hero-gradient); border:0.5px solid var(--border);
    box-shadow:0 24px 60px rgba(0,0,0,0.6);
    /* LE MÊME GESTE QUE LES PAGES. Elle montait de 12 px depuis 92 %, avec un
       rebond — un mouvement bien plus marqué que celui des écrans, alors que
       c'est la même chose qui se produit : une surface arrive.

       Elle garde en revanche son fond assombri : c'est lui qui dit « ceci vous
       interrompt, répondez ». Le voile des pages ne s'y ajoute pas, il ferait
       double emploi. */
    transform:scale(0.975); opacity:0;
    transition:transform 0.38s cubic-bezier(0.32,0.72,0,1), opacity 0.3s ease;
  }
  .fond-etab.on .fen-etab{ transform:none; opacity:1; }
  .fen-etab h3{ font-size:19px; font-weight:800; letter-spacing:-0.035em; margin-bottom:4px; }
  .fen-etab .s{ font-size:12.5px; color:var(--label-2); line-height:1.45; margin-bottom:18px; }
  .fen-etab input[type=text]{ margin-bottom:0; }

  .etab-depot{
    position:relative; width:96px; height:96px; margin:0 auto 8px; border-radius:50%;
    overflow:hidden; padding:0; display:flex; align-items:center; justify-content:center;
    background:linear-gradient(160deg,#24262C,#15161A);
    border:1.5px dashed rgba(255,255,255,0.28); color:rgba(255,255,255,0.5);
    transition:border-color 0.2s, transform 0.18s cubic-bezier(0.34,1.56,0.64,1);
  }
  .etab-depot:active{ transform:scale(0.96); }
  .etab-depot.rempli{ border-style:solid; border-color:rgba(255,255,255,0.4); }
  .etab-depot img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
  .etab-depot .mono{ font-size:28px; font-weight:750; letter-spacing:0.04em; color:rgba(255,255,255,0.5); }
  .etab-depot .appareil{
    position:absolute; inset:0; display:flex; flex-direction:column;
    align-items:center; justify-content:center; gap:5px;
  }
  .etab-depot .appareil svg{ width:22px; height:22px; }
  .etab-depot .appareil span{ font-size:9.5px; font-weight:650; color:rgba(255,255,255,0.4); }
  .etab-depot.rempli .appareil{ display:none; }
  .etab-legende{ font-size:12px; font-weight:600; color:var(--label-2); margin-bottom:16px; }
  .etab-legende button{
    border:none; background:none; font-family:inherit; font-size:12px;
    font-weight:700; color:var(--blue); padding:0;
  }

  /* ═══ Coche de fin d'analyse ═══
     Même langue que les icônes des modes : cercles en retrait à 16 et 26 %, celui
     de devant à 42 %, et le signe en blanc plein. Le trait de la coche se dessine
     au lieu d'apparaître — c'est le moment où l'analyse aboutit, il mérite ce
     dixième de seconde. */
  .coche-dessin{ width:66px; height:60px; margin:0 auto 12px; }
  .coche-dessin svg{ width:100%; height:100%; display:block; overflow:visible; }
  .coche-dessin .trace{
    stroke-dasharray:22; stroke-dashoffset:22;
    animation:cocheTrace 0.5s cubic-bezier(0.65,0,0.35,1) 0.15s forwards;
  }
  @keyframes cocheTrace{ to{ stroke-dashoffset:0; } }
  .coche-dessin .signe{ animation:debutSigne 5.4s ease-in-out infinite; transform-origin:center; }
  @media (prefers-reduced-motion: reduce){
    .coche-dessin .trace{ animation:none; stroke-dashoffset:0; }
    .coche-dessin .signe{ animation:none; }
  }

  /* ═══ Création à partir d'un document ═══ */
  .doc-ou{
    display:flex; align-items:center; gap:12px; margin:16px 0 14px;
    font-size:11px; font-weight:700; color:var(--label-3);
    text-transform:uppercase; letter-spacing:0.06em;
  }
  .doc-ou::before, .doc-ou::after{
    content:''; flex:1; height:0.5px; background:rgba(255,255,255,0.12);
  }
  .doc-fichier-etat{
    display:flex; align-items:center; gap:11px; margin-top:10px;
    padding:11px 13px; border-radius:13px;
    background:var(--bg-card); border:0.5px solid var(--border);
  }
  .doc-fichier-etat .ic{ font-size:19px; flex-shrink:0; }
  .doc-fichier-etat .tx{ flex:1; min-width:0; }
  .doc-fichier-etat .n{
    font-size:13.5px; font-weight:650; white-space:nowrap;
    overflow:hidden; text-overflow:ellipsis;
  }
  .doc-fichier-etat .s{ font-size:11.5px; color:var(--label-3); margin-top:2px; }

  /* ═══ Accueil après un scan ═══
     Une fenêtre à elle, pas une boîte de dialogue ordinaire : c'est le premier
     contact avec la procédure, il vaut mieux qu'il soit accueillant. */
  .bienvenue-fond{
    position:fixed; inset:0; z-index:400; display:flex; align-items:center; justify-content:center;
    padding:26px; background:rgba(0,0,0,0.55);
    -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px);
    opacity:0; transition:opacity 0.28s ease;
  }
  .bienvenue-fond.shown{ opacity:1; }
  .bienvenue{
    width:100%; max-width:330px; padding:26px 22px 20px; border-radius:26px; text-align:center;
    background:var(--hero-gradient); border:0.5px solid var(--border);
    box-shadow:0 24px 60px rgba(0,0,0,0.6);
    transform:scale(0.9) translateY(14px); opacity:0;
    transition:transform 0.42s cubic-bezier(0.34,1.4,0.5,1), opacity 0.3s ease;
  }
  .bienvenue-fond.shown .bienvenue{ transform:scale(1) translateY(0); opacity:1; }
  .bienvenue .salut{
    width:72px; height:72px; margin:0 auto 14px;
    background:url('data:image/webp;base64,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') center/contain no-repeat;
    filter:drop-shadow(0 8px 18px rgba(0,0,0,0.4));
    animation:salutArrive 0.7s cubic-bezier(0.22,1,0.36,1) 0.1s both;
  }
  @keyframes salutArrive{
    0%   { opacity:0; transform:scale(0.7) rotate(-10deg); }
    60%  { opacity:1; transform:scale(1.06) rotate(3deg); }
    100% { opacity:1; transform:scale(1) rotate(0); }
  }
  .bienvenue h3{ font-size:20px; font-weight:800; letter-spacing:-0.035em; margin-bottom:5px; }
  .bienvenue .intro{ font-size:12.5px; color:var(--label-2); line-height:1.45; }
  .bienvenue .proc{
    margin:16px 0 4px; padding:13px 15px; border-radius:15px;
    background:rgba(255,255,255,0.07); border:0.5px solid var(--border);
  }
  .bienvenue .proc .t{ font-size:16px; font-weight:700; letter-spacing:-0.03em; }
  .bienvenue .proc .c{ font-size:11.5px; color:var(--label-3); margin-top:3px; }
  /* Version sobre, pour quelqu'un qui connaît déjà : une coche, pas un Memoji. */
  .bienvenue .code-ic{
    width:54px; height:54px; margin:0 auto 14px; border-radius:50%;
    display:flex; align-items:center; justify-content:center;
    font-size:25px; font-weight:800; color:#06210F; background:var(--green);
    box-shadow:0 0 0 6px rgba(48,209,88,0.14);
    animation:salutArrive 0.5s cubic-bezier(0.22,1,0.36,1) both;
  }
  .bienvenue-fond.sobre .bienvenue{ padding-top:22px; }
  .bienvenue .btn{ margin-top:16px; }
  .bienvenue .refus{
    display:block; width:100%; margin-top:10px; padding:9px; border:none; background:none;
    font-family:inherit; font-size:13px; font-weight:600; color:var(--label-2);
  }
  @media (prefers-reduced-motion: reduce){
    .bienvenue, .bienvenue .salut{ transition:none; animation:none; }
  }

  /* ═══ Détail d'un échec d'analyse ═══
     La cause exacte est écrite en base par la fonction serveur. La montrer ici
     évite d'avoir à ouvrir Supabase pour comprendre ce qui s'est passé. */
  .ai-detail{
    margin-top:14px; padding:12px 13px; border-radius:14px;
    background:rgba(255,69,58,0.08); border:0.5px solid rgba(255,69,58,0.22);
    text-align:left;
  }
  .ai-detail .t{
    font-size:10px; font-weight:750; color:var(--label-3);
    text-transform:uppercase; letter-spacing:0.05em; margin-bottom:7px;
  }
  .ai-detail pre{
    font-family:ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size:10.5px; line-height:1.5; color:var(--label-2);
    white-space:pre-wrap; word-break:break-word; margin-bottom:10px;
    max-height:190px; overflow-y:auto;
    -webkit-user-select:text; user-select:text;
  }

  /* ═══ Titre de section avec un bouton d'aide ═══ */
  .titre-avec-aide{ display:flex; align-items:center; gap:7px; margin:22px 0 10px; }
  .btn-aide{
    width:22px; height:22px; border-radius:50%; flex-shrink:0; border:none; padding:0;
    background:rgba(255,255,255,0.09); color:var(--label-2);
    display:flex; align-items:center; justify-content:center;
    transition:background 0.2s, color 0.2s, transform 0.16s cubic-bezier(0.34,1.5,0.64,1);
  }
  .btn-aide svg{ width:13px; height:13px; }
  .btn-aide:active{ transform:scale(0.88); background:rgba(255,255,255,0.2); color:#fff; }

  /* ═══ Explication des médailles ═══ */
  .med-liste{ display:flex; flex-direction:column; gap:2px; }

  /* ═══ Mon activité (espace équipe) ═══ */
  /* Les trois tuiles n'affichaient pas la même chose — un anneau de 58 px d'un
     côté, un chiffre de l'autre — et leurs libellés se retrouvaient à des
     hauteurs différentes. Une zone haute de même taille les remet d'aplomb. */
  .ma-haut{ height:58px; display:flex; align-items:center; justify-content:center; }

  /* ═══ La médaille de série ═══
     Du verre teinté, pas du métal : le même vocabulaire que les barres et les
     cartes de l'app. La teinte, le liseré et la lueur viennent du palier, portés
     par des variables — une seule règle sert donc aux six paliers. */
  /* La médaille n'est plus qu'un cadre : le fond, le bord et la lumière sont
     dans le dessin lui-même. Un rond en CSS par-dessus un hexagone en SVG
     aurait rogné les pointes. */

  /* Ouverture en buée : la médaille arrive floue et légèrement trop grande,
     puis la netteté vient. Le chiffre ne s'inscrit qu'une fois la matière posée. */

  .ma-serie-mot{
    font-size:12.5px; color:var(--label-2); line-height:1.45; margin-top:12px; text-align:center;
  }
  .ma-serie-mot b{ color:#fff; font-weight:650; }

  .ma-ligne{
    display:flex; align-items:center; gap:12px; padding:12px 14px; margin-bottom:8px;
    background:var(--bg-card); border:0.5px solid var(--border); border-radius:14px;
  }
  .ma-ligne .rang{
    width:22px; flex-shrink:0; font-size:11px; font-weight:800;
    color:var(--label-3); text-align:center;
  }
  .ma-ligne .info{ flex:1; min-width:0; display:block; }
  .ma-ligne .nom{ display:block; font-size:14px; font-weight:650; letter-spacing:-0.02em;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .ma-ligne .quand{ display:block; font-size:11.5px; color:var(--label-3); margin-top:2px; }
  .ma-ligne .duree{ font-size:14px; font-weight:750; flex-shrink:0; }
  .ma-ligne .jauge{ height:4px; border-radius:4px; background:rgba(255,255,255,0.09);
    margin-top:6px; overflow:hidden; }
  .ma-ligne .jauge i{ display:block; height:100%; border-radius:4px; }
  .ma-vide{ font-size:12.5px; color:var(--label-2); line-height:1.5; padding:2px 0 6px; }

  /* ═══ Bloc du visiteur ═══
     Aucune carte floutée : ce serait un faux verrou, puisqu'il faudrait
     d'abord charger les données pour les masquer. On dit simplement ce qui
     existe et comment y accéder. */
  .visiteur{
    margin-top:16px; padding:16px 18px; border-radius:20px;
    background:var(--bg-card); border:0.5px solid var(--border);
  }
  .visiteur-tete{ display:flex; align-items:flex-start; gap:13px; }
  .visiteur-cadenas{
    width:38px; height:38px; border-radius:12px; flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
    background:rgba(255,255,255,0.08); color:var(--label-2);
  }
  .visiteur-cadenas svg{ width:19px; height:19px; }
  .visiteur-txt{ flex:1; min-width:0; }
  .visiteur-txt .t{ font-size:14.5px; font-weight:700; letter-spacing:-0.02em; }
  .visiteur-txt .s{ font-size:12.5px; color:var(--label-2); margin-top:3px; line-height:1.45; }
  .visiteur-code{ display:flex; gap:8px; margin-top:14px; }
  .visiteur-code input[type=text]{
    flex:1; min-width:0; width:auto; margin:0; text-align:center;
    font-size:19px; font-weight:700; letter-spacing:0.3em;
  }
  .visiteur-code .btn{ width:auto; flex-shrink:0; padding:0 18px; }

  /* Bandeau affiché quand on arrive par un QR code sans être connecté. */
  .qr-bandeau{
    display:flex; flex-direction:column; gap:3px; margin-bottom:18px;
    padding:13px 15px; border-radius:14px;
    background:linear-gradient(150deg, rgba(48,209,88,0.16), rgba(48,209,88,0.04));
    border:0.5px solid rgba(48,209,88,0.3);
  }
  .qr-bandeau b{ font-size:14.5px; font-weight:700; letter-spacing:-0.02em; }
  .qr-bandeau span{ font-size:12.5px; color:var(--label-2); line-height:1.45; }

  /* ═══════════════════════════════════════════════════════════════════════
     ÉDITEUR DE CLIP — pièces ajoutées
     Les deux pastilles de bornes, la loupe, la bande de couverture et les
     avertissements. Le tout partagé par les deux éditeurs (création et
     modification), d'où des classes plutôt que des identifiants.
     ═══════════════════════════════════════════════════════════════════════ */
  /* Les deux bornes tiennent sur une seule ligne, libellé et valeur à la même
     hauteur : deux cartes empilées prenaient trois fois la place pour la même
     information. */
  .ed-bornes{ display:none; align-items:center; gap:8px; margin-top:10px; }
  .ed-bornes.on{ display:flex; }
  .ed-borne{
    flex:1; min-width:0; display:flex; align-items:center; gap:7px;
    height:38px; padding:0 12px; border-radius:11px; font-family:inherit;
    background:var(--bg-card); border:1px solid var(--border);
    transition:border-color 0.2s, background 0.2s;
  }
  .ed-borne.actif{ border-color:#fff; background:rgba(255,255,255,0.12); }
  .ed-borne .k{ font-size:10px; font-weight:750; color:var(--label-3);
    text-transform:uppercase; letter-spacing:0.05em; flex-shrink:0; }
  .ed-borne.actif .k{ color:rgba(255,255,255,0.75); }
  .ed-borne .v{ font-size:15px; font-weight:800; letter-spacing:-0.03em; color:#fff; }
  .ed-fleche{ font-size:13px; color:var(--label-3); flex-shrink:0; }

  .ed-loupe-bloc{ display:none; margin-top:12px; }
  .ed-loupe-bloc.on{ display:block; }
  .ed-loupe-titre{ font-size:11px; font-weight:750; color:var(--label-3);
    text-transform:uppercase; letter-spacing:0.05em; margin-bottom:7px; }
  .ed-loupe{
    position:relative; height:56px; border-radius:12px; overflow:hidden;
    background:rgba(255,255,255,0.04); border:0.5px solid var(--border);
    touch-action:none; cursor:grab;
  }
  .ed-loupe .bande{ position:absolute; top:0; bottom:0; display:flex; }
  .ed-loupe .bande i{ flex-shrink:0; height:100%; }
  .ed-loupe .axe{
    position:absolute; left:50%; top:0; bottom:0; width:2px; background:#fff;
    transform:translateX(-50%); z-index:3; pointer-events:none;
  }
  .ed-loupe .axe::before{
    content:''; position:absolute; top:0; left:-5px; width:12px; height:5px;
    border-radius:0 0 3px 3px; background:#fff;
  }
  .ed-loupe .zone{ position:absolute; top:0; bottom:0; background:rgba(48,209,88,0.16);
    z-index:1; pointer-events:none; }
  .ed-loupe .grad{ position:absolute; bottom:2px; font-size:8.5px;
    color:rgba(255,255,255,0.45); transform:translateX(-50%); z-index:2; pointer-events:none; }
  .ed-aide{ font-size:11px; color:var(--label-3); text-align:center; margin-top:6px; }

  .ed-couv{ display:none; height:6px; border-radius:6px; overflow:hidden; margin-top:14px; gap:1px; }
  .ed-couv.on{ display:flex; }
  .ed-couv i{ display:block; }
  .ed-legende{ display:none; gap:12px; margin-top:7px; font-size:10px; color:var(--label-3); }
  .ed-legende.on{ display:flex; }
  .ed-legende span{ display:flex; align-items:center; gap:4px; }
  .ed-legende i{ width:7px; height:7px; border-radius:2px; display:block; }
  .ed-alertes{ margin-top:11px; }
  .ed-alerte{
    display:flex; align-items:center; gap:9px; padding:9px 11px; border-radius:12px;
    font-size:12px; margin-bottom:6px; background:rgba(255,159,10,0.12);
    border:0.5px solid rgba(255,159,10,0.28);
  }
  .ed-alerte.grave{ background:rgba(255,69,58,0.12); border-color:rgba(255,69,58,0.3); }
  .ed-ok{
    display:flex; align-items:center; gap:8px; padding:10px 12px; border-radius:12px;
    font-size:12px; background:rgba(48,209,88,0.12);
    border:0.5px solid rgba(48,209,88,0.28); margin-top:11px;
  }
  /* La poignée verdit quand l'aimant l'accroche à la borne d'une voisine. */
  .clip-handle.colle .grip{ background:var(--green); }

  /* ═══ État de lecture ═══
     Ce n'est plus l'employé qui déclare avoir compris : l'app constate qu'il
     est resté sur la fiche. Le bandeau montre donc un état, pas une action. */
  .lecture-etat{
    display:flex; align-items:center; gap:14px;
    padding:14px 16px; border-radius:18px;
    background:var(--bg-card); border:0.5px solid var(--border);
    transition:background 0.5s ease, border-color 0.5s ease;
  }
  .lecture-etat.faite{
    background:linear-gradient(150deg, rgba(48,209,88,0.18), rgba(48,209,88,0.04));
    border-color:rgba(48,209,88,0.32);
  }
  .lecture-anneau{ position:relative; width:44px; height:44px; flex-shrink:0; }
  .lecture-anneau svg{ transform:rotate(-90deg); display:block; }
  .lecture-anneau .piste{ stroke:rgba(255,255,255,0.10); }
  /* Le trait glisse jusqu'à sa nouvelle position, dans les deux sens : cocher
     l'avance, décocher le fait reculer. La courbe part vite et finit doucement,
     comme les anneaux d'activité d'Apple. */
  .lecture-anneau .valeur{
    stroke-linecap:round;
    transition: stroke-dashoffset 0.62s cubic-bezier(0.32,0.72,0,1), stroke 0.4s ease;
  }

  /* Le chiffre bascule : il sort par le haut, revient par le bas. */
  @keyframes anneauBascule{
    0%{ transform:translateY(0); opacity:1; }
    45%{ transform:translateY(-7px); opacity:0; }
    55%{ transform:translateY(7px); opacity:0; }
    100%{ transform:translateY(0); opacity:1; }
  }
  .lecture-anneau .dedans.bascule{ animation:anneauBascule 0.32s ease both; }
  .lecture-anneau .dedans{
    position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
    font-size:13px; font-weight:800; letter-spacing:-0.03em;
  }
  .lecture-txt{ flex:1; min-width:0; }
  .lecture-txt .t{ font-size:15px; font-weight:700; letter-spacing:-0.025em; }
  .lecture-txt .s{ font-size:12px; color:var(--label-2); margin-top:2px; }
  /* Petit sursaut au moment où la consultation est enregistrée. */
  .lecture-etat.pointe{ animation:lecturePointe 0.55s cubic-bezier(0.34,1.5,0.64,1); }
  @keyframes lecturePointe{ 0%{ transform:scale(1); } 45%{ transform:scale(1.035); } 100%{ transform:scale(1); } }
  @media (prefers-reduced-motion: reduce){ .lecture-etat.pointe{ animation:none; } }

  /* ═══ Fiche d'un membre ═══ */
  .mf-tete{
    display:flex; align-items:center; gap:14px; margin-top:14px;
    padding:16px 18px; border-radius:20px;
    background:var(--hero-gradient); border:0.5px solid var(--border);
  }

  .mf-resume{ flex:1; min-width:0; font-size:12.5px; color:var(--label-2); line-height:1.45; }
  .mf-resume b{ color:#fff; font-weight:650; }
  .mf-chiffre{ font-size:23px; font-weight:850; letter-spacing:-0.045em; }
  .mf-ligne{
    display:flex; align-items:baseline; justify-content:space-between; gap:12px;
    padding:9px 0; border-top:0.5px solid rgba(255,255,255,0.07);
  }
  .mf-ligne:first-child{ border-top:none; }
  .mf-ligne .k{ font-size:12.5px; color:var(--label-2); }
  .mf-ligne .v{ font-size:13px; font-weight:650; text-align:right; }
  .emp-row{ cursor:pointer; }

  /* ═══ Utilisateurs de l'entreprise ═══ */
  /* La ligne s'ouvre : on le montre à l'appui, comme partout ailleurs. */
  /* ═══ LA LIGNE N'EST PLUS CLIQUABLE, ET ELLE NE DOIT PLUS EN AVOIR L'AIR ═══

     Le clic n'ouvre plus la fiche — cette page sert à administrer, pas à
     consulter. Mais le style disait encore le contraire : curseur en main,
     enfoncement à l'appui. On touchait, l'étape s'enfonçait, rien ne se
     passait. Pire qu'une ligne inerte : une ligne qui promet.

     Seuls les boutons de rôle et de retrait réagissent désormais. */

  .pm-ligne{
    display:flex; align-items:center; gap:12px; padding:12px 14px; margin-bottom:8px;
    background:var(--bg-card); border:0.5px solid var(--border); border-radius:14px;
  }
  /* ═══ DEUX COULEURS, DEUX RÔLES ═══

     La gestion et l'équipe portaient deux ambres presque identiques — #F0A030
     et #E8A33D. Indiscernables dans une liste : il fallait lire le rôle écrit
     sous chaque nom pour savoir qui pouvait quoi.

     L'ÉQUIPE garde l'ambre, la couleur de l'app. LA GESTION prend l'indigo :
     assez éloigné pour se voir d'un coup d'œil, assez sobre pour ne pas
     hurler. Le contraste ne repose pas sur la seule teinte — le fond de la
     gestion est nettement plus sombre, ce qui reste lisible pour qui distingue
     mal les couleurs. */
  .pm-av{
    width:38px; height:38px; border-radius:50%; flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
    font-size:13px; font-weight:750; color:#2A1400;
    background:linear-gradient(155deg, #FFCE8A, #F0A030);
  }
  .pm-av.chef{
    color:#EAEAF2;
    background:linear-gradient(155deg, #5B62C4, #3A3F8F);
    box-shadow:inset 0 0 0 0.5px rgba(255,255,255,0.16);
  }
  .pm-info{ flex:1; min-width:0; }
  .pm-nom{ font-size:14.5px; font-weight:650; letter-spacing:-0.02em; }
  .pm-soi{
    font-size:10px; font-weight:700; color:var(--label-3); text-transform:uppercase;
    letter-spacing:0.05em; margin-left:5px;
  }
  .pm-role{ font-size:11.5px; color:var(--label-3); margin-top:2px; }
  .pm-suppr{
    width:34px; height:34px; border-radius:50%; flex-shrink:0; border:none;
    background:rgba(255,69,58,0.14); color:var(--red);
    display:flex; align-items:center; justify-content:center;
    transition:transform 0.16s cubic-bezier(0.34,1.5,0.64,1), background 0.2s;
  }
  .pm-suppr:active{ transform:scale(0.88); background:rgba(255,69,58,0.24); }
  .pm-suppr svg{ width:16px; height:16px; }

  /* ═══ Page Analyse ═══ */
  .ga-segments{
    position:relative; display:flex; gap:0; padding:3px; border-radius:100px;
    background:rgba(255,255,255,0.07); margin:14px 0 16px;
  }
  .ga-segments::before{
    content:''; position:absolute; top:3px; bottom:3px; left:3px;
    width:var(--largeur, 0px); transform:translateX(var(--depart, 0px));
    background:rgba(255,255,255,0.92); border-radius:100px; z-index:0;
    transition:transform 0.44s cubic-bezier(0.32,0.72,0,1),
               width 0.44s cubic-bezier(0.32,0.72,0,1);
  }
  .ga-segments.sans-glisse::before{ transition:none; }
  .ga-segments button{
    position:relative; z-index:1; flex:1; text-align:center;
    font-family:inherit; font-size:12.5px; font-weight:600;
    padding:8px 0; border:none; border-radius:100px; background:none;
    color:var(--label-2); transition:color 0.28s ease;
  }
  .ga-segments button.active{ color:#000; }

  @media (prefers-reduced-motion: reduce){
    .ga-segments::before{ transition:none; }
  }

  /* Recherche discrète : pas d'encadré marqué, juste un fond légèrement
     éclairci qui s'affirme quand le champ prend le focus. */
  .recherche-fine{
    display:flex; align-items:center; gap:9px; height:38px; padding:0 13px;
    margin:14px 0 4px; border-radius:100px;
    background:rgba(255,255,255,0.05); border:0.5px solid transparent;
    transition:background 0.25s, border-color 0.25s;
  }
  .recherche-fine:focus-within{ background:rgba(255,255,255,0.09); border-color:var(--border); }
  .recherche-fine svg{ width:15px; height:15px; color:var(--label-3); flex-shrink:0; }
  /* Le sélecteur d'attribut est indispensable : sans lui, la règle générale
     `input[type=text]` déclarée plus bas l'emporte à spécificité égale et le
     champ retrouve sa bordure, son fond et sa largeur pleine. */
  .recherche-fine input[type=text]{
    flex:1; min-width:0; width:auto; height:auto;
    background:none; border:none; outline:none; border-radius:0;
    font-family:inherit; font-size:16px; color:#fff; padding:0; margin:0;
  }
  .recherche-fine input[type=text]:focus{ background:none; border:none; }
  .recherche-fine input[type=text]::placeholder{ color:var(--label-3); font-size:13.5px; }

  .ga-trio{ display:flex; gap:9px; }
  .ga-tuile{
    flex:1; display:flex; flex-direction:column; align-items:center;
    padding:15px 6px 13px; background:var(--bg-card);
    border:0.5px solid var(--border); border-radius:18px;
  }
  .ga-anneau{ position:relative; width:58px; height:58px; }
  .ga-anneau svg{ transform:rotate(-90deg); display:block; }
  .ga-anneau .piste{ stroke:rgba(255,255,255,0.10); }
  /* L'anneau se remplit à l'affichage, comme dans l'app Forme. */
  .ga-anneau .valeur{
    stroke-linecap:round;
    animation:gaRemplir 1.4s cubic-bezier(0.32,0.72,0,1) both;
  }
  @keyframes gaRemplir{ from{ stroke-dashoffset:var(--vide); } to{ stroke-dashoffset:var(--cible); } }
  .ga-anneau .dedans{
    position:absolute; inset:0; display:flex; flex-direction:column; align-items:center;
    justify-content:center; line-height:1;
    font-size:17px; font-weight:850; letter-spacing:-0.04em;
  }
  /* Une unité sous le chiffre, quand le chiffre seul serait ambigu. */
  .ga-anneau .unite{
    font-size:8.5px; font-weight:700; letter-spacing:0.04em; text-transform:uppercase;
    color:var(--label-3); margin-top:2px;
  }
  .ga-libelle{
    font-size:9.5px; font-weight:700; color:var(--label-3); margin-top:9px;
    text-transform:uppercase; letter-spacing:0.045em;
  }
  .ga-detail{ font-size:12px; color:var(--label-3); margin-top:12px; line-height:1.45; }

  @media (prefers-reduced-motion: reduce){ .ga-anneau .valeur{ animation:none; } }

  .hero-card{ position:relative; background:var(--hero-gradient); border:0.5px solid rgba(255,255,255,0.15);
    border-radius:20px; padding:20px 18px; margin-bottom:14px; overflow:hidden; box-shadow:0 8px 24px rgba(0,0,0,0.35); }
  .hero-card .lbl{ font-size:11px; text-transform:uppercase; letter-spacing:0.6px; color:rgba(255,255,255,0.55); font-weight:500; margin-bottom:10px; }
  .hero-card .num{ font-size:44px; font-weight:700; color:#fff; letter-spacing:-1.2px; }
  .hero-card .sub{ font-size:13px; color:rgba(255,255,255,0.55); margin-top:4px; font-weight:500; }
  .hero-card .bar{ height:10px; background:rgba(255,255,255,0.18); border-radius:100px; overflow:hidden; margin-top:14px; }
  .hero-card .bar-fill{ height:100%; background:#fff; border-radius:100px; box-shadow:0 0 12px rgba(255,255,255,0.55); }

  .section-title{ display:flex; align-items:center; justify-content:space-between; font-size:13px; font-weight:600; color:var(--label-2); margin:20px 0 10px; }
  /* ═══ Pourquoi pas de `backdrop-filter` ici ═══
     Ces classes couvrent les cartes de dossiers, de procédures, les lignes
     d'employés : sur un seul écran, ça fait dix à vingt éléments. Chacun
     obligeait Safari à photographier le fond, le flouter sur 20px et le
     resaturer — par-dessus trois halos déjà flous et en mouvement. C'est ce
     qui figeait l'app pendant plusieurs secondes après le chargement.
     Et comme ce filtre resaturait les halos derrière chaque carte, le fond de
     l'app ne ressemblait pas à celui de l'écran de chargement, qui n'a aucune
     carte par-dessus. Flouter un dégradé déjà très doux ne change quasiment
     rien à l'œil : on garde donc le fond translucide, sans le filtre.
     Le verre dépoli reste sur les rares éléments fixes : barre du haut,
     pastille des réglages, barre d'onglets, carte de connexion, alertes. */
  .card, .sop-card, .emp-row, .cat-cell{
    background:var(--bg-card);
    border:0.5px solid var(--border); border-radius:16px;
  }
  .sop-card{ padding:14px 16px; margin-bottom:8px; display:flex; justify-content:space-between; align-items:center; gap:10px; cursor:pointer;
    transition: transform 0.15s cubic-bezier(0.34,1.56,0.64,1); }
  .sop-card:active{ transform:scale(0.97); }
  /* L'animation d'entrée ne joue QUE sur ce qui vient d'apparaître. Elle était
     posée sur toutes les cartes : elle rejouait à chaque retour sur la page, et
     finissait par ne plus rien signifier. */
  .sop-card.neuf, .emp-row.neuf, .cat-cell.neuf, .proc-rich-card.neuf{
    animation:cardIn 0.45s cubic-bezier(0.32,0.72,0,1) both;
  }

  /* La sortie. Une dossier qui s'efface parce que sa dernière procédure part
     doit se voir partir — sinon on doute d'avoir supprimé la bonne chose. */
  /* Le départ ANNULE l'arrivée.

     Une cellule peut porter `neuf` et `part` en même temps : elle vient
     d'apparaître, et on supprime aussitôt sa dernière procédure. Les deux
     animations se jouaient alors ensemble — elle grandissait en rétrécissant,
     d'où ce sursaut. La règle plus spécifique l'emporte. */
  .sop-card.part, .emp-row.part, .cat-cell.part, .proc-rich-card.part,
  .sop-card.neuf.part, .emp-row.neuf.part,
  .cat-cell.neuf.part, .proc-rich-card.neuf.part{
    animation:cardOut 0.3s cubic-bezier(0.4,0,1,1) both;
    pointer-events:none;
  }
  @keyframes cardOut{
    0%{ opacity:1; transform:scale(1); max-height:200px; }
    100%{ opacity:0; transform:scale(0.92); max-height:0;
          margin-top:0; margin-bottom:0; padding-top:0; padding-bottom:0; }
  }

  /* Quelqu'un qui a demandé moins de mouvement n'en reçoit aucun. */
  @media (prefers-reduced-motion: reduce){
    .sop-card.neuf, .emp-row.neuf, .cat-cell.neuf, .proc-rich-card.neuf,
    .sop-card.part, .emp-row.part, .cat-cell.part, .proc-rich-card.part{
      animation:none;
    }
  }

@keyframes cardIn{
    0%  { opacity:0; transform:scale(0.975); }
    30% { opacity:1; }
    100%{ opacity:1; transform:none; }
  }
  @keyframes cardSlideIn{
    0%{ opacity:0; transform:translateX(24px) scale(0.96); }
    100%{ opacity:1; transform:translateX(0) scale(1); }
  }
  .slide-in{ animation: cardSlideIn 0.4s cubic-bezier(0.22,1,0.36,1) both; }
  .sop-card .title{ font-size:15px; font-weight:600; letter-spacing:-0.01em; }
  .sop-card .meta{ font-size:12px; color:var(--label-2); margin-top:3px; }
  .badge{ font-size:11px; padding:5px 10px; border-radius:100px; white-space:nowrap; font-weight:600; }
  .badge.ok{background:rgba(48,209,88,0.16); color:var(--green);}
  /* La pastille d'un extrait vidéo. Elle portait le vert de « terminé », ce qui
     laissait croire à une étape validée : c'est seulement un moment de la vidéo.
     Le bleu de l'étape en cours de lecture est le bon signal — les deux parlent
     de la même chose. */
  /* La durée de l'extrait passe SOUS le texte de l'étape. À côté, elle
     rognait la largeur du texte : sur un téléphone, une phrase de dix mots
     passait sur deux lignes pour lui faire place. En dessous, elle ne coûte
     rien à la lecture et se touche aussi bien. */
  .badge.extrait{
    background:rgba(255,179,64,0.16); color:#FFB340;
    display:inline-flex; align-items:center; margin-top:7px;
  }
  .et-co .badge.extrait{ display:inline-flex; }
  .et-co p + .badge.extrait{ margin-top:8px; }
  .badge.pending{background:rgba(255,159,10,0.16); color:var(--orange);}
  .badge.drift{background:rgba(255,69,58,0.16); color:var(--red);}

  .card{padding:16px; margin-bottom:12px;}
  label.f{ display:block; font-size:12px; font-weight:600; color:var(--label-2); margin-bottom:8px; }
  textarea, input[type=text], input[type=email], input[type=password], input[type=file]{
    width:100%; font-size:16px; border:0.5px solid var(--border); border-radius:12px; padding:12px;
    background:rgba(255,255,255,0.04); color:var(--label);
  }
  textarea:focus, input:focus{ outline:none; border-color:rgba(255,255,255,0.4); background:rgba(255,255,255,0.07); }
  ::placeholder{color:var(--label-3);}

  /* ═══ LE BOUTON PRINCIPAL ═══
     Il était blanc. « Créer une procédure » est ambre depuis la carte
     d'ouverture — deux styles pour un même rang, et l'œil ne savait plus
     lequel est LE geste de la page. Un seul désormais, partout.

     Texte sombre et non blanc : à cette clarté d'orange, du blanc perdrait le
     contraste que le noir garde sans effort. */
  .btn{ font-size:14px; font-weight:700; letter-spacing:-0.02em;
    background:linear-gradient(135deg,#FF6A00 0%,#FF9A1F 60%,#FFAD33 100%);
    color:#2A1400; padding:11px 20px; border-radius:100px; border:none;
    box-shadow:0 6px 18px rgba(255,122,24,0.26), 0 2px 6px rgba(0,0,0,0.28);
    transition: transform 0.18s cubic-bezier(0.34,1.56,0.64,1), box-shadow 0.15s; }
  .btn:active{ transform:scale(0.94); box-shadow:0 3px 10px rgba(255,122,24,0.22); }
  .btn.small{ padding:9px 16px; font-size:12.5px; }
  .btn.ghost{ background:rgba(255,255,255,0.10); color:var(--label); box-shadow:none; border:0.5px solid var(--border); }
  .btn.block{width:100%; text-align:center;}
  .btn[disabled]{opacity:0.5;}

  .video-frame{ background:#000; border:0.5px solid var(--border); border-radius:16px; aspect-ratio:16/9;
    display:flex; align-items:center; justify-content:center; color:rgba(255,255,255,0.5); font-size:13px; overflow:hidden; position:relative; }
  .video-frame video{width:100%; height:100%; object-fit:contain;}

  .step-edit-item{ background:var(--bg-card); border:0.5px solid var(--border); border-radius:16px; padding:14px; margin-bottom:10px; }
  /* Le champ occupait toute la ligne sans se distinguer du reste : on ne voyait
     pas où écrire, ni jusqu'où. Il a maintenant son propre cadre, comme tous les
     champs de l'app, et il s'étend en hauteur à mesure qu'on tape. */
  .step-edit-item .step-row-top{ display:flex; align-items:flex-start; gap:10px; margin-bottom:10px; }
  .step-edit-item textarea{
    min-height:44px; padding:11px 12px !important;
    border-radius:12px !important;
    background:rgba(255,255,255,0.06) !important;
    border:0.5px solid rgba(255,255,255,0.14) !important;
    font-size:15px !important; line-height:1.45 !important;
    transition:border-color 0.2s, background 0.2s;
  }
  .step-edit-item textarea:focus{
    outline:none;
    border-color:rgba(255,179,64,0.55) !important;
    background:rgba(255,179,64,0.07) !important;
  }
  .step-edit-item textarea::placeholder{ color:var(--label-3); }
  .step-edit-item .step-num{
    width:24px; height:24px; border-radius:50%; background:rgba(255,255,255,0.1); color:#fff;
    display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:700; flex-shrink:0; margin-top:2px;
  }
  .step-edit-item .range{ font-size:10.5px; font-weight:600; color:var(--label-2); background:rgba(255,255,255,0.06); padding:3px 7px; border-radius:6px; flex-shrink:0; }
  .step-edit-item textarea{
    flex:1; background:none; border:none; font-size:16px; padding:0; resize:none; overflow:hidden;
    line-height:1.4; font-family:inherit; color:var(--label); min-height:22px;
  }
  .step-edit-item .step-row-bottom{ display:flex; align-items:center; gap:8px; padding-left:34px; }
  .step-edit-item .del{ color:var(--red); font-size:18px; flex-shrink:0; margin-left:auto; padding:4px;
    display:flex; align-items:center; justify-content:center; }
  .step-edit-item .del svg{ width:17px; height:17px; }

  /* ═══ Timeline façon CapCut ═══ */
  .capcut-wrap{ margin-top:12px; }

  .capcut-controls{ display:flex; align-items:center; gap:10px; margin-bottom:10px; }
  .capcut-play-btn{
    width:36px; height:36px; border-radius:50%; background:#fff; color:#000;
    display:flex; align-items:center; justify-content:center; flex-shrink:0;
    transition: transform 0.15s cubic-bezier(0.34,1.56,0.64,1);
  }
  .capcut-play-btn:active{ transform:scale(0.9); }
  .capcut-play-btn svg{ width:16px; height:16px; }
  .capcut-play-btn #capcut-play-icon{ margin-left:2px; }
  .capcut-current-time, .capcut-duration{ font-size:12px; color:var(--label-2); font-variant-numeric:tabular-nums; }
  .capcut-duration-sep{ font-size:12px; color:var(--label-3); }

  .capcut-timeline{
    position:relative; height:64px; border-radius:12px; overflow:hidden;
    background:#000; border:0.5px solid var(--border);
    touch-action:pan-y; cursor:pointer; user-select:none;
  }
  /* En mode réglage de clip, on laisse déborder pour que les deux poignées
     restent entièrement attrapables, même collées au tout début ou à la fin. */
  .capcut-timeline.clipmode{ overflow:visible; }
  .capcut-timeline.clipmode .capcut-track,
  .capcut-timeline.clipmode .capcut-markers{ border-radius:12px; overflow:hidden; }
  .capcut-track{ position:absolute; inset:0; display:flex; pointer-events:none; }
  .capcut-track img{ flex:1; height:100%; object-fit:cover; display:block; border-right:1px solid rgba(0,0,0,0.4); }
  .capcut-markers{ position:absolute; inset:0; pointer-events:none; }
  .capcut-marker{
    position:absolute; top:0; bottom:0; width:2px; background:#fff;
    box-shadow:0 0 4px rgba(255,255,255,0.8);
  }
  .capcut-playhead{
    position:absolute; top:-4px; bottom:-4px; width:3px; background:var(--red); z-index:3;
    box-shadow:0 0 8px rgba(255,69,58,0.8); pointer-events:none;
  }
  .capcut-playhead-handle{
    position:absolute; top:-6px; left:50%; transform:translateX(-50%);
    width:16px; height:10px; background:var(--red); border-radius:4px;
  }
  .capcut-hint{ font-size:11px; color:var(--label-3); text-align:center; margin-top:8px; }
  .cut-toolbar{ display:flex; gap:8px; margin-top:10px; flex-wrap:wrap; }

  /* ═══ Sélection de clip : deux poignées que l'on écarte ou resserre ═══ */
  .capcut-timeline.clipmode{ touch-action:none; }
  /* La bande de l'étape choisie ressort par un liseré clair par-dessus sa
     couleur : on sait laquelle on règle sans perdre le repère de couleur. */
  .clip-band.sel{ box-shadow:inset 0 0 0 1.5px rgba(255,255,255,0.9); }
    /* Chaque étape porte deux bords marqués : son entrée à gauche, sa sortie à
     droite, dans sa couleur. On voit donc les bornes de toutes les étapes en
     même temps, pas seulement celles de l'étape choisie. */
  .clip-band{
    -webkit-user-select:none; user-select:none; pointer-events:auto;
    position:absolute; top:0; bottom:0; background:rgba(255,255,255,0.10);
    border-left:3px solid rgba(255,255,255,0.5); border-right:3px solid rgba(255,255,255,0.5);
    border-radius:2px;
  }
  .clip-band span{ position:absolute; top:4px; left:4px; font-size:9px; font-weight:800; color:#fff;
    background:rgba(0,0,0,0.65); border-radius:4px; padding:1px 5px; }
  .clip-mask{ position:absolute; top:0; bottom:0; background:rgba(0,0,0,0.6); pointer-events:none; z-index:2; display:none; }
  .clip-sel{ position:absolute; top:0; bottom:0; z-index:3; display:none; pointer-events:none;
    border-top:2px solid #fff; border-bottom:2px solid #fff; background:rgba(255,255,255,0.06); }
  .clip-mask.on, .clip-sel.on{ display:block; }
  .clip-handle{ position:absolute; top:-1px; bottom:-1px; width:26px; z-index:6; display:none;
    align-items:center; justify-content:center; touch-action:none; cursor:ew-resize; }
  .clip-handle.on{ display:flex; }
  .clip-handle .grip{ width:16px; height:100%; background:#fff; border-radius:6px;
    display:flex; align-items:center; justify-content:center; box-shadow:0 2px 10px rgba(0,0,0,0.7); }
  .clip-handle .grip::after{ content:''; width:2px; height:20px; background:rgba(0,0,0,0.35); border-radius:2px; }
  .clip-handle.dragging .grip{ background:#F5A623; }
  .clip-info{ display:flex; justify-content:space-between; align-items:center; gap:10px;
    margin-top:10px; font-size:11.5px; color:var(--label-2); font-variant-numeric:tabular-nums; }
  .clip-info b{ color:#fff; font-weight:700; }

  /* ═══ Boîte de confirmation façon iOS ═══ */
/* ═══ LA FENÊTRE PROCÉDO ═══
     Le halo est ce qu'on ne trouve nulle part ailleurs : c'est lui qui fait
     reconnaître l'application, même sur une question banale. Sa couleur suit la
     nature de l'acte — rouge quand c'est irréversible, vert quand c'est
     accompli, bleu le reste du temps. */
  .fen-pro{
    position:relative; width:100%; max-width:318px;
    border-radius:26px; overflow:hidden;
    background:linear-gradient(168deg, #1D1E23, #141518);
    border:0.5px solid rgba(255,255,255,0.14);
    box-shadow:0 28px 66px rgba(0,0,0,0.66);
    transform:scale(0.94); opacity:0;
    transition:transform 0.28s cubic-bezier(0.34,1.4,0.64,1), opacity 0.22s ease;
  }
  .ios-alert-backdrop.shown .fen-pro{ transform:scale(1); opacity:1; }
  .ios-alert-backdrop.closing .fen-pro{ transform:scale(0.95); opacity:0; transition-duration:0.16s; }

  .fen-halo{
    position:absolute; top:-72px; left:50%; transform:translateX(-50%);
    width:250px; height:145px; pointer-events:none; filter:blur(26px);
  }
  .fen-halo.bleu { background:radial-gradient(ellipse, rgba(255,179,64,0.34), transparent 68%); }
  .fen-halo.rouge{ background:radial-gradient(ellipse, rgba(255,69,58,0.30), transparent 68%); }
  .fen-halo.vert { background:radial-gradient(ellipse, rgba(48,209,88,0.28), transparent 68%); }

  .fen-co{ position:relative; padding:26px 22px 18px; text-align:center; }
  .fen-ic{
    width:54px; height:54px; border-radius:18px; margin:0 auto 15px;
    display:grid; place-items:center; color:#fff;
    background:rgba(255,255,255,0.07); border:0.5px solid var(--border);
  }
  .fen-ic svg{ width:25px; height:25px; display:block; }
  .fen-ic.rouge{ background:rgba(255,69,58,0.14); border-color:rgba(255,69,58,0.34); color:#FF6961; }
  .fen-ic.vert { background:rgba(48,209,88,0.14); border-color:rgba(48,209,88,0.32); color:#5FDE84; }

  .fen-t{ font-size:18.5px; font-weight:800; letter-spacing:-0.038em; line-height:1.25; }
  .fen-s{
    font-size:13.5px; color:var(--label-2); line-height:1.5; margin-top:8px;
    white-space:pre-line;
  }

  /* Les boutons sont EMPILÉS. Côte à côte, on tape à côté une fois sur dix — et
     une fois sur dix, ici, c'est une procédure effacée par erreur. */
  .fen-ac{ display:flex; flex-direction:column; gap:8px; padding:0 18px 18px; }
  .fen-p{
    width:100%; height:48px; border:none; border-radius:15px;
    background:#fff; color:#000; font-family:inherit; font-size:15px; font-weight:750;
  }
  .fen-p.rouge{ background:#FF453A; color:#fff; }
  .fen-p:active{ transform:scale(0.98); }
  .fen-a{
    width:100%; height:44px; border-radius:15px;
    border:0.5px solid var(--border); background:rgba(255,255,255,0.05);
    color:var(--label-2); font-family:inherit; font-size:14px; font-weight:650;
  }
  .fen-a:active{ background:rgba(255,255,255,0.09); }

  /* Le champ de saisie prend la place du dessin : une tuile au-dessus d'un
     champ ferait deux points d'attention là où il n'y a qu'une chose à faire. */
  .fen-champ{
    width:100%; height:46px; margin-top:16px; padding:0 14px;
    border-radius:14px; border:0.5px solid var(--border);
    background:rgba(255,255,255,0.06); color:#fff;
    font-family:inherit; font-size:15px; text-align:center;
  }
  .fen-champ:focus{
    outline:none; border-color:rgba(255,179,64,0.5);
    background:rgba(255,179,64,0.08);
  }
  .fen-champ::placeholder{ color:var(--label-3); }

  /* La mention d'acceptation, sous le bouton d'inscription. Discrète mais
     lisible : la loi demande qu'elle soit accessible avant l'action, pas qu'elle
     crie. Le lien, lui, se voit. */
  .cgu-mention{
    font-size:11.5px; color:var(--label-3); line-height:1.5;
    text-align:center; margin-top:12px; padding:0 6px;
  }
  .cgu-mention a{ color:var(--blue); font-weight:650; text-decoration:none; }
  .cgu-mention a:active{ opacity:0.6; }

  /* Un lien qui se comporte comme une ligne de réglage. */
  a.reg-ligne{ text-decoration:none; }

  /* Une précision collée au titre, en petit. La page ne montre QUE l'espace
     équipe : sans cette mention, un gérant qui ne se voit pas dans la liste
     croit à un oubli. */
  .titre-precision{
    display:block; font-size:11.5px; font-weight:600;
    color:var(--label-3); letter-spacing:-0.01em; margin-top:1px;
  }

  /* ═══ L'ÉCRAN « AUCUNE ENTREPRISE » ═══

     Une image à lui seul, plus grande que l'avatar habituel. C'est le premier
     écran que voit quelqu'un qui n'a encore rien : autant qu'il soit accueillant
     plutôt qu'administratif.

     `#fond-orphelin` cible cet écran ET LUI SEUL — le même personnage sert
     ailleurs, sur la carte de promotion et la fiche de contact, où il ne doit
     pas changer. */
  #fond-orphelin .promu-carte .accueil-av{
    width:104px; height:104px;
    /* Le RACCOURCI `background`, et non `background-image`. La règle générale
       utilise le raccourci : il redéfinit TOUTES les propriétés d'arrière-plan
       d'un coup, image comprise. Écrire `background-image` seul ne suffisait
       donc pas — l'ancienne image revenait par le raccourci. */
    background:url('aucune-entreprise.png') center/contain no-repeat;
    margin-right:-6px;   /* l'image a sa propre marge : on la rattrape */
  }
  /* La pastille verte n'a plus lieu d'être : elle signalait une personne
     joignable, pas une invitation à entrer. */
  #fond-orphelin .promu-carte .accueil-av .dispo{ display:none; }

  /* La carte respire : l'image prend plus de place, le texte doit suivre. */
  #fond-orphelin .promu-carte{ align-items:center; padding-top:20px; padding-bottom:20px; }

  /* ═══ UN ÉTABLISSEMENT QUI S'EN VA ═══
     Il se rétracte devant les yeux plutôt que de disparaître entre deux images.
     Trois cents millisecondes suffisent à lever le doute sur ce qu'on a
     supprimé. */
  [data-etab].part{
    animation:etabPart 0.32s cubic-bezier(0.4,0,1,1) both;
    pointer-events:none;
  }
  @keyframes etabPart{
    0%{ opacity:1; transform:scale(1); }
    100%{ opacity:0; transform:scale(0.7); }
  }

  /* Le passage à l'autre entreprise. Le fondu évite le clignotement d'un écran
     qui se vide puis se remplit : on comprend qu'on CHANGE d'endroit, au lieu
     de croire à une panne. */
  body.bascule-etab #gestion-app,
  body.bascule-etab #equipe-app,
  body.bascule-etab #tabbar{ opacity:0; transform:scale(0.985);
    transition:opacity 0.2s ease, transform 0.3s cubic-bezier(0.32,0.72,0,1); }
  #gestion-app, #equipe-app, #tabbar{
    transition:opacity 0.32s ease, transform 0.4s cubic-bezier(0.32,0.72,0,1);
  }

  @media (prefers-reduced-motion: reduce){
    [data-etab].part{ animation:none; }
    body.bascule-etab #gestion-app,
    body.bascule-etab #equipe-app,
    body.bascule-etab #tabbar{ transition:none; }
  }

  .ios-alert-backdrop{
    position:fixed; inset:0; z-index:200; display:flex; align-items:center; justify-content:center; padding:24px;
    background:rgba(0,0,0,0.45); -webkit-backdrop-filter:blur(2px); backdrop-filter:blur(2px);
    opacity:0; transition:opacity 0.22s ease;
  }
  .ios-alert-backdrop.shown{ opacity:1; }
  /* La fenêtre était un calque d'iOS : 272 px de large, boutons à 17 px, bleu
     système. Elle passe aux mesures de l'app — rayon de 20 comme les cartes,
     texte à la même échelle, notre bleu. Une boîte empruntée se remarque. */
  .ios-alert{
    width:100%; max-width:310px; border-radius:20px; overflow:hidden; text-align:center;
    background:rgba(44,44,48,0.86); -webkit-backdrop-filter:blur(22px) saturate(180%); backdrop-filter:blur(22px) saturate(180%);
    box-shadow:0 20px 60px rgba(0,0,0,0.6);
    transform:scale(1.16); opacity:0;
    transition: transform 0.26s cubic-bezier(0.22,1,0.36,1), opacity 0.2s ease;
  }
  .ios-alert-backdrop.shown .ios-alert{ transform:scale(1); opacity:1; }
  .ios-alert-choix{ display:flex; flex-direction:column; }
  .ios-alert-choix button{
    height:48px; border:none; background:none; color:var(--blue);
    font-family:inherit; font-size:15.5px; font-weight:650;
    border-top:0.5px solid rgba(255,255,255,0.14);
  }
  .ios-alert-choix button:active{ background:rgba(255,255,255,0.07); }
  .ios-alert-choix button.danger{ color:var(--red); }
  .ios-alert-choix button.annuler{ font-weight:650; }

  .ios-alert-champ{
    width:100%; margin-top:13px; height:42px; padding:0 13px;
    border-radius:11px; border:0.5px solid rgba(255,255,255,0.18);
    background:rgba(255,255,255,0.08); color:#fff;
    font-family:inherit; font-size:16px; text-align:center;
  }
  .ios-alert-champ:focus{ outline:none; border-color:rgba(255,255,255,0.42); }
  .ios-alert-backdrop.closing .ios-alert{ transform:scale(0.95); opacity:0; transition-duration:0.16s; }
  .ios-alert-body{ padding:22px 20px 19px; }
  .ios-alert-title{ font-size:16.5px; font-weight:750; letter-spacing:-0.03em; margin-bottom:6px; }
  .ios-alert-msg{ font-size:13px; line-height:1.5; color:var(--label-2); }
  .ios-alert-actions{ display:flex; border-top:0.5px solid rgba(255,255,255,0.18); }
  .ios-alert-actions button{
    flex:1; padding:15px 8px; font-family:inherit; font-size:15.5px; font-weight:650; letter-spacing:-0.025em;
    color:var(--blue); background:none; transition:background 0.12s;
  }
  .ios-alert-actions button:active{ background:rgba(255,255,255,0.10); }
  .ios-alert-actions button + button{ border-left:0.5px solid rgba(255,255,255,0.18); }
  .ios-alert-actions button.danger{ color:var(--red); font-weight:700; }

  /* ═══ Commandes de clip, façon CapCut ═══ */
  .clip-tools{ display:none; grid-template-columns:repeat(4, 1fr); gap:8px; margin-top:12px; }
  .clip-tools.on{ display:grid; }
  .clip-tool{
    display:flex; flex-direction:column; align-items:center; gap:5px; padding:10px 4px;
    background:var(--bg-card); border:0.5px solid var(--border); border-radius:14px;
    font-size:10.5px; font-weight:600; color:var(--label); line-height:1.1; text-align:center;
    transition: transform 0.15s cubic-bezier(0.34,1.56,0.64,1), background 0.15s;
  }
  .clip-tool:active{ transform:scale(0.93); background:rgba(255,255,255,0.14); }
  .clip-tool svg{ width:19px; height:19px; }
  .clip-tool[disabled]{ opacity:0.35; }
  .clip-done-btn{ display:none; width:100%; margin-top:10px; }
  .clip-done-btn.on{ display:block; }

  .step-edit-item{ cursor:pointer; transition: border-color 0.18s, background 0.18s; }
  .step-edit-item.selected{ border-color:rgba(255,255,255,0.55); background:rgba(255,255,255,0.07); }
  
  
  
  

  .cat-rank{
    display:flex; align-items:center; gap:12px; padding:12px 14px; margin-bottom:8px;
    background:var(--bg-card); border:0.5px solid var(--border); border-radius:14px;
  }
  .cat-rank .pos{
    width:22px; height:22px; border-radius:50%; flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
    font-size:11px; font-weight:800; background:rgba(255,255,255,0.12); color:#fff;
  }
  .cat-rank.premier .pos{ background:#fff; color:#000; }
  /* Les lignes du temps de lecture s'ouvrent : on le montre à l'appui, comme
     partout ailleurs dans l'app. Les dossiers, elles, ne bougent pas. */
  .cat-rank.cliquable{ cursor:pointer; transition:transform 0.16s, background 0.2s; }
  .cat-rank.cliquable:active{ transform:scale(0.985); background:rgba(255,255,255,0.07); }
  .cat-rank .infos{ flex:1; min-width:0; }
  .cat-rank .nom{ font-size:14px; font-weight:600; }
  .cat-rank .detail{ font-size:11px; color:var(--label-2); margin-top:2px; }
  .cat-rank .jauge{ height:4px; border-radius:4px; background:rgba(255,255,255,0.10); margin-top:7px; overflow:hidden; }
  .cat-rank .jauge i{ display:block; height:100%; border-radius:4px; transition:width 0.6s cubic-bezier(0.22,1,0.36,1); }
  .cat-rank .taux{ font-size:15px; font-weight:800; font-variant-numeric:tabular-nums; flex-shrink:0; }

  .stats-row{ display:grid; grid-template-columns:repeat(3,1fr); gap:10px; margin-bottom:6px; }
  .stat-mini{ background:var(--bg-card); border:0.5px solid var(--border); border-radius:14px; padding:12px 8px; text-align:center; }
  .stat-mini .num{ font-size:20px; font-weight:700; }
  .stat-mini .lbl{ font-size:10.5px; color:var(--label-2); margin-top:2px; }

  .emp-row{ display:flex; align-items:center; gap:9px; padding:8px 13px; margin-bottom:4px;
    animation: cardIn 0.45s cubic-bezier(0.32,0.72,0,1) both; }
  .emp-row-sous{
    display:block; font-size:11.5px; color:var(--label-3);
    font-weight:500; margin-top:1px;
  }

  .emp-row-name{ font-size:13.5px; font-weight:600; flex:1; }
  .emp-row-date{ font-size:11.5px; color:var(--label-2); }
  .check{ width:22px; height:22px; border-radius:50%; border:2px solid var(--separator); flex-shrink:0;
    transition: transform 0.3s cubic-bezier(0.34,1.56,0.64,1), background 0.2s, border-color 0.2s; }
  .check.done{ animation: checkPop 0.4s cubic-bezier(0.34,1.56,0.64,1); }
  @keyframes checkPop{
    0%{ transform:scale(0.6); }
    60%{ transform:scale(1.15); }
    100%{ transform:scale(1); }
  }
  .check.done{ background:var(--green); border-color:var(--green); position:relative; }

  .check.done::after{ content:'✓'; color:#000; font-size:12px; font-weight:700; position:absolute; top:50%; left:50%; transform:translate(-50%,-52%); }

  /* ═══ Fiche QR ═══ Une vraie plaque blanche, comme celle qu'on imprimera.
     La carte n'utilise volontairement PAS le verre dépoli des autres cartes :
     sur Safari, un `backdrop-filter` sur le parent d'un élément blanc avec
     ombre portée donne des rendus incohérents. Fond plein, rendu fiable. */
  .qr-card{
    padding:18px; text-align:center;
    background:rgba(255,255,255,0.055);
    -webkit-backdrop-filter:none; backdrop-filter:none;
  }
  .qr-plaque{
    background:#fff; border-radius:18px; padding:18px 16px 14px;
    width:100%; max-width:236px; margin:0 auto 14px;
    box-shadow:0 10px 26px rgba(0,0,0,0.34);
  }
  .qr-frame{
    position:relative; width:100%; max-width:168px; margin:0 auto;
    aspect-ratio:1 / 1;
  }
  .qr-visual{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center; }
  .qr-visual canvas{ width:100% !important; height:100% !important; display:block; max-width:100%; }
  @supports not (aspect-ratio: 1 / 1){
    .qr-frame{ height:168px; }
  }
  .qr-corner{ position:absolute; width:16px; height:16px; border:2.5px solid rgba(20,21,24,0.22); }
  .qr-corner.tl{ top:-7px; left:-7px; border-right:0; border-bottom:0; border-top-left-radius:7px; }
  .qr-corner.tr{ top:-7px; right:-7px; border-left:0; border-bottom:0; border-top-right-radius:7px; }
  .qr-corner.bl{ bottom:-7px; left:-7px; border-right:0; border-top:0; border-bottom-left-radius:7px; }
  .qr-corner.br{ bottom:-7px; right:-7px; border-left:0; border-top:0; border-bottom-right-radius:7px; }
  .qr-plaque-title{
    color:#0C0D0E; font-size:14.5px; font-weight:700; line-height:1.25;
    margin-top:16px; word-break:break-word;
  }
  .qr-plaque-sub{ color:rgba(20,21,24,0.45); font-size:11px; font-weight:500; margin-top:4px; }
  .qr-plaque-mark{
    display:flex; align-items:center; justify-content:center; gap:5px;
    margin-top:12px; padding-top:11px; border-top:1px solid rgba(20,21,24,0.10);
  }
  /* La plaque porte le logo en image, comme le reste — la règle visait encore
     le SVG du « P ». 11 sur 15, au rapport 0,706 du dessin. */
  .qr-plaque-mark svg{ width:9px; height:11px; }
  .qr-plaque-mark img{ width:11px; height:15px; object-fit:contain; display:block; }
  .qr-plaque-mark span{ color:rgba(20,21,24,0.4); font-size:10px; font-weight:700; letter-spacing:0.01em; }
  .qr-hint{ font-size:12px; color:var(--label-2); margin-bottom:12px; line-height:1.4; }

  .plan-card{
    background:var(--bg-card);
    border:0.5px solid var(--border); border-radius:16px; padding:14px 16px; margin-bottom:8px;
    transition: transform 0.18s cubic-bezier(0.34,1.56,0.64,1), border-color 0.2s;
  }
  .plan-card.active{ border-color:rgba(255,255,255,0.5); }
  .plan-card:active{ transform:scale(0.98); }
  .plan-head{ display:flex; justify-content:space-between; align-items:center; }
  .plan-name{ font-size:15px; font-weight:700; display:flex; align-items:center; }
  .plan-price{ font-size:15px; font-weight:700; }
  .plan-price span{ font-size:11px; font-weight:500; color:var(--label-2); }
  .plan-desc{ font-size:12px; color:var(--label-2); margin-top:4px; }

  /* ═══════════════════════════════════════════════════════════════════════
     TOUTES LES PAGES COMMENCENT À LA MÊME HAUTEUR

     Deux formes d'en-tête coexistent : `page-tete` sur les pages d'onglet, et
     `detail-header` — bouton retour plus titre — sur les pages qu'on ouvre.

     Elles ne se ressemblaient pas. Le titre des secondes était forcé à 20 px
     dans le balisage, sur VINGT-CINQ pages, contre 26 pour les premières. Et
     leur rembourrage haut de 2 px les descendait de six pixels de plus.

     Résultat : « Procédures » commençait à 87 px en 26 px, « Abonnement » à
     93 px en 20 px. Passer de l'une à l'autre faisait sauter le titre et
     changer sa taille.

     Le rembourrage passe à zéro, et le titre prend 26 px comme les autres. Le
     bouton retour reste aligné dessus par `align-items:center`. */
  .detail-header{ display:flex; align-items:center; gap:10px; margin-bottom:4px; }
  .back-btn{ width:34px; height:34px; border-radius:50%; display:flex; align-items:center; justify-content:center; background:var(--bg-card); border:0.5px solid var(--border); flex-shrink:0; }
  .back-btn svg{width:16px; height:16px;}
  /* ═══ Le fil des étapes, côté équipe ═══
     La même forme qu'à la création : un trait relie les cases, et l'ordre se voit
     sans qu'on ait à le lire. */
  #detail-steps.etapes-fil,
  #analyse-steps-list.etapes-fil{ position:relative; padding-left:45px; margin-top:4px; }
  #detail-steps.etapes-fil::before,
  #analyse-steps-list.etapes-fil::before{
    content:''; position:absolute; left:16px; top:9px; bottom:18px; width:1.5px;
    background:linear-gradient(rgba(255,255,255,0.16), rgba(255,255,255,0.04));
  }
  /* L'employé lit debout, souvent d'assez loin, et son doigt doit trouver la
     bonne case du premier coup. On desserre légèrement : 28 px entre les étapes
     au lieu de 20, et un peu d'air entre les lignes du texte. C'est un écran de
     lecture, pas un écran de saisie. */
  #detail-steps.etapes-fil .detail-step,
  #analyse-steps-list.etapes-fil .detail-step{
    position:relative; background:none !important; border:none !important;
    border-radius:0 !important; padding:0 0 28px !important; margin:0 !important;
  }
  #detail-steps.etapes-fil .detail-step p,
  #analyse-steps-list.etapes-fil .detail-step p{ line-height:1.55; }
  #detail-steps.etapes-fil .detail-step.en-lecture::after,
  #analyse-steps-list.etapes-fil .detail-step.en-lecture::after{
    content:''; position:absolute; left:-55px; top:-5px; bottom:16px; width:2.5px;
    border-radius:2px; background:var(--blue);
  }
  .et-co{ flex:1; min-width:0; }

  /* La case. Elle porte le numéro tant qu'elle n'est pas cochée : on ne perd pas
     le repère de l'ordre en gagnant celui de l'avancement. */
  /* La case n'est plus qu'un cadre : c'est l'hexagone dessiné qui porte la forme,
     la matière et le chiffre. Même dessin qu'à la création, même vocabulaire. */
  /* Le numéro de la fiche gestion. Il n'avait aucune règle : les styles du fil
     sont écrits pour `.man-fil`, et cette liste porte `.etapes-fil`. Le dessin
     sortait donc sans taille ni position — invisible ou déformé. */
  #analyse-steps-list.etapes-fil .step-num-dess{
    position:absolute; left:-45px; top:-4px; width:33px; height:33px; line-height:0;
  }
  #analyse-steps-list.etapes-fil .step-num-dess svg{ width:33px; height:33px; display:block; }

  .et-coche{
    position:absolute; left:-45px; top:-4px; width:33px; height:33px;
    border:none; background:none; padding:0; line-height:0;
    display:flex; align-items:center; justify-content:center;
    transition:transform 0.18s cubic-bezier(0.34,1.56,0.64,1);
  }
  .et-coche svg{ width:33px; height:33px; display:block; }
  .et-coche:active{ transform:scale(0.86); }
  /* Une étape faite s'efface un peu : l'œil va d'abord à ce qui reste.

     L'IMAGE S'EFFACE AUSSI. Seul le texte pâlissait, et une photo restée en
     pleine lumière au-dessus d'un texte éteint attirait l'œil vers l'étape
     qu'on venait justement de terminer. */
  /* Le texte pâlit en même temps que le chiffre devient coche. Il restait au
     gris ordinaire des étapes — rien ne le distinguait d'une étape non faite,
     alors que c'est le premier signal qu'on perçoit. La transition sur la
     couleur le fait glisser plutôt que sauter. */
  #detail-steps.etapes-fil .detail-step p{ transition:color 0.24s ease; }
  #detail-steps.etapes-fil .detail-step.faite p{ color:var(--label-3); }
  #detail-steps.etapes-fil .detail-step .detail-step-img,
  #detail-steps.etapes-fil .detail-step .detail-step-video{
    transition:opacity 0.3s ease;
  }
  #detail-steps.etapes-fil .detail-step.faite .detail-step-img,
  #detail-steps.etapes-fil .detail-step.faite .detail-step-video{
    opacity:0.42;
  }

  .detail-step{ transition:border-color 0.3s ease, background 0.3s ease; background:var(--bg-card); border:0.5px solid var(--border); border-radius:16px; padding:14px 16px; margin-bottom:8px; display:flex; gap:12px; align-items:flex-start; }
  .detail-step .n{ width:24px; height:24px; border-radius:50%; background:rgba(255,255,255,0.1); color:#fff; display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:700; flex-shrink:0; }
  /* `pre-line` conserve les retours à la ligne saisis à la rédaction : le HTML
     les avale sinon, et une étape écrite en plusieurs lignes arrivait en un seul
     bloc. Les espaces multiples restent réduits. */
  .detail-step p{ font-size:14px; line-height:1.45; white-space:pre-line; }
  /* Le bandeau ne s'affiche qu'une fois la procédure consultée. Pendant les
     30 secondes, l'employé ne voit aucun décompte : il lit, c'est tout. */
  .confirm-bar{ margin-top:20px; margin-bottom:8px; display:none; }

  /* La ligne du titre des étapes accueille le sélecteur de langue à droite. */
  /* 6 px sous le titre au lieu de 10. Avec les 16 px de la zone des étapes,
     l'écart total tombe à 22 px — contre 28 avant. Le titre et la première
     étape appartiennent au même bloc de lecture ; les séparer davantage les
     faisait paraître étrangers l'un à l'autre. */
  .detail-etapes-tete{ margin-top:22px; margin-bottom:4px; }
  .detail-etapes-tete .tiroir-langue{ margin-bottom:0; }
  .confirm-bar.visible{ display:block; }
  .confirm-bar.visible .lecture-etat{ animation:bandeauArrive 0.5s cubic-bezier(0.22,1,0.36,1) both; }
  @keyframes bandeauArrive{
    from{ opacity:0; transform:translateY(10px); }
    to  { opacity:1; transform:translateY(0); }
  }
  @media (prefers-reduced-motion: reduce){
    .confirm-bar.visible .lecture-etat{ animation:none; }
  }

  .view-toggle{
    display:flex; gap:2px; background:var(--bg-card); border:0.5px solid var(--border);
    border-radius:100px; padding:3px; margin-bottom:16px;
  }
  .view-toggle button{
    flex:1; text-align:center; font-size:12px; font-weight:600; padding:8px 4px;
    border-radius:100px; color:var(--label-2);
  }
  .view-toggle button.active{ background:#fff; color:#000; }

  /* ═══ Bascule de période ═══
     Même animation que la barre d'onglets : une pastille blanche qui GLISSE
     jusqu'au segment choisi, avec le même ressort. L'ancien effet changeait
     brutalement la couleur de fond de chaque bouton — trois clignotements au
     lieu d'un mouvement. */
  .filter-chips{
    position:relative; display:flex; gap:0; padding:3px; border-radius:100px;
    background:rgba(255,255,255,0.07); border:0.5px solid rgba(255,255,255,0.10);
  }
  /* La pastille est un seul élément qui se déplace, pas trois fonds qui
     s'allument : c'est ce qui donne le glissement. */
  .filter-chips::before{
    content:''; position:absolute; top:3px; bottom:3px; left:3px;
    width:var(--largeur, 0px); transform:translateX(var(--depart, 0px));
    background:#fff; border-radius:100px; z-index:0;
    transition:transform 0.44s cubic-bezier(0.32,0.72,0,1),
               width 0.44s cubic-bezier(0.32,0.72,0,1);
  }
  .filter-chips.sans-glisse::before{ transition:none; }
  .filter-chips button{
    position:relative; z-index:1; flex:1; min-width:0; text-align:center;
    font-family:inherit; font-size:11.5px; font-weight:650;
    padding:7px 10px; border:none; border-radius:100px; background:none;
    color:rgba(235,235,245,0.62); white-space:nowrap;
    transition:color 0.28s ease;
  }
  .filter-chips button.active{ color:#000; }

  @media (prefers-reduced-motion: reduce){
    .filter-chips::before{ transition:none; }
  }

  /* ═══ Carte d'accueil ═══
     L'avatar parle dans une bulle, comme dans une messagerie. Le chiffre est
     dit dans la phrase plutôt qu'affiché dans un anneau : c'est ce qui fait la
     différence entre un tableau de bord et un accueil. */
  /* Le message d'abord, l'avatar en fin de ligne : on lit ce qui est dit avant
     de voir qui le dit. */
  .accueil{
    display:flex; align-items:center; gap:14px;
    padding:15px 20px; margin-bottom:14px; border-radius:20px;
    background:var(--hero-gradient);
    border:0.5px solid var(--border);
  }
  .accueil-texte{ flex:1; min-width:0; }
  .accueil-texte .t{ font-size:16px; font-weight:700; letter-spacing:-0.03em; }
  .accueil-texte .s{ font-size:12.5px; color:var(--label-2); margin-top:3px; line-height:1.45; }
  .accueil-texte .s b{ color:#fff; font-weight:650; }
  /* L'avatar est une image intégrée à la page : rien à télécharger, elle est là
     dès la première image affichée. Découpée en rond à 128px, elle reste nette
     jusqu'à un écran à trois fois la densité. */
  /* Pas de découpe circulaire : l'image porte déjà son disque bleu, et la main
     qui dépasse en bas à gauche en fait partie. Un `border-radius` la coupait.
     `contain` plutôt que `cover` pour la même raison. */
  /* Deux avatars, deux usages. La carte d'accueil garde la version découpée en
     rond : elle voisine avec des anneaux et des pastilles, une forme ronde s'y
     accorde. La carte de contact, elle, montre l'image entière — avec la main
     qui dépasse — parce qu'elle est le sujet de la carte, pas un ornement. */
  /* Une image, deux tailles. Le fichier contient déjà son disque bleu, la main
     qui dépasse et une marge tout autour — mesurée pour qu'un cercle inscrit ne
     coupe plus rien. On n'applique donc AUCUNE découpe : ni masque à l'image, ni
     `border-radius` au CSS. C'est le seul moyen que la main reste entière. */
  /* Deux avatars, deux messages. La carte d'accueil salue : pouce levé. La carte
     de contact interroge : main au menton. Aucune découpe sur ni l'une ni
     l'autre — les fichiers portent déjà leur disque et leur marge. */
  .accueil-av{
    position:relative; width:70px; height:70px; flex-shrink:0; cursor:pointer;
    background:url('data:image/webp;base64,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') center/contain no-repeat;
    filter:drop-shadow(0 4px 10px rgba(0,0,0,0.32));
    transition:transform 0.2s cubic-bezier(0.34,1.5,0.64,1);
  }
  .contact-carte .accueil-av{
    width:74px; height:74px;
    background-image:url('data:image/webp;base64,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');
  }
  /* La carte de contact : image entière, sans découpe. */
  
  .accueil-av:active{ transform:scale(0.93); }
  .accueil-av .dispo{
    position:absolute; right:5px; bottom:9px; width:12px; height:12px; border-radius:50%;
    background:var(--green); box-shadow:0 0 0 2.5px #1A1B1F;
  }
  /* ═══════════════════════════════════════════════════════════════════════
     LA CARTE D'OUVERTURE

     Elle a pris la place de la salutation. Une salutation ne fait rien ; celle-ci
     nomme ce que la page permet et porte le geste principal — créer.

     Les teintes viennent du logo, et de lui seul. Aucune ne sert ailleurs à
     signaler quoi que ce soit : c'est du décor, il peut donc être coloré sans
     brouiller la grammaire des alertes.
     ═══════════════════════════════════════════════════════════════════════ */
  .hero{
    position:relative; overflow:hidden;
    margin-bottom:16px; padding:22px 20px 22px;
    border-radius:24px;
    /* ═══ UN NOIR PLUS PROFOND QUE LES AUTRES CARTES ═══

       `--hero-gradient` part de #2C2C34, un gris déjà clair. Sur les cartes de
       contenu c'est juste : elles doivent se détacher du fond. Ici non — cette
       carte porte un bord allumé et un dessin lumineux, et un intérieur gris
       les affadissait tous les deux.

       On descend à #17171B / #060608 : le contraste avec le liseré ambre et le
       dessin double, sans que rien d'autre change. Le dégradé garde le même
       angle et la même progression — c'est la même lumière, sur une matière
       plus sombre. */
    background:linear-gradient(150deg, #17171B 0%, #101014 40%, #0A0A0D 75%, #060608 100%);
    border:none;
    /* Une lueur ambre très basse sous la carte : c'est elle qui la détache du
       fond, comme sur la référence. */
    box-shadow:0 18px 44px rgba(0,0,0,0.50), 0 0 38px -14px rgba(255,122,24,0.30);
  }

  /* Le liseré s'allume aux deux angles opposés, comme une lumière rasante.
     Deux dégradés sur un même calque, plutôt qu'une bordure colorée : une
     bordure serait uniforme, et l'effet vient justement de son irrégularité. */
  /* Une clarté diffuse dans les deux angles éclairés, très retenue : elle
     prolonge la ligne du bord vers l'intérieur sans colorer le fond. */
  .hero-lueur{
    position:absolute; inset:0; border-radius:inherit; pointer-events:none;
    background:
      radial-gradient(150px 110px at 100% 0%, rgba(255,122,24,0.14), transparent 72%),
      radial-gradient(130px 100px at 0% 100%, rgba(255,154,31,0.09), transparent 72%);
  }

  /* LE BORD.

     La ligne claire s'allume à DEUX ANGLES OPPOSÉS — haut droit et bas gauche —
     et s'éteint au milieu des côtés. C'est une lumière rasante : elle accroche
     là où la surface tourne, pas partout.

     Un dégradé à 45° donne exactement ça : ses deux extrémités tombent sur ces
     deux angles, son milieu sur les deux autres. Le masque en `exclude` ne
     garde que l'épaisseur du contour — un dégradé ne peut pas se poser sur une
     `border`, il faut évider le centre. */
  .hero-lueur::after{
    content:''; position:absolute; inset:0; border-radius:inherit;
    padding:1.1px;
    background:linear-gradient(45deg,
      #FFB454 0%, rgba(255,173,51,0.55) 12%, rgba(255,173,51,0.06) 30%,
      rgba(255,173,51,0.06) 70%, rgba(255,173,51,0.55) 88%, #FFB454 100%);
    -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite:xor; mask-composite:exclude;
  }

  /* Le texte occupe toute la largeur : le dessin qui lui prenait la droite a
     été retiré. Une colonne étroite n'aurait plus rien à éviter, elle ne ferait
     que couper les phrases plus tôt. */
  .hero-txt{ position:relative; z-index:2; }
  .hero p{ max-width:30ch; }

  .hero h2{
    font-size:23px; font-weight:750; letter-spacing:-0.035em; line-height:1.15;
    margin-bottom:8px;
  }
  .hero p{
    font-size:13.5px; line-height:1.45; color:var(--label-2);
    margin-bottom:18px;
  }

  /* Texte sombre sur l'orange : à cette luminosité, du blanc perdrait le
     contraste que le noir garde sans effort. */
  .hero-actions{ display:flex; align-items:center; gap:10px; }


  .hero-cta{
    display:inline-flex; align-items:center; justify-content:center; gap:9px;
    flex:1; min-width:0;
    height:48px; padding:0 18px; border:none; border-radius:15px;
    background:linear-gradient(135deg,#FF6A00 0%,#FF9A1F 60%,#FFAD33 100%);
    color:#2A1400; font-family:inherit; font-size:14.5px; font-weight:750;
    letter-spacing:-0.02em;
    white-space:nowrap;
    box-shadow:0 8px 22px rgba(255,122,24,0.28);
    transition:transform 0.16s cubic-bezier(0.34,1.56,0.64,1), box-shadow 0.2s;
  }
  .hero-cta svg{ width:17px; height:17px; }
  .hero-cta:active{ transform:scale(0.96); box-shadow:0 4px 12px rgba(255,122,24,0.24); }

  /* Le second geste : même hauteur, aucune couleur pleine. Il se voit, il ne
     réclame pas. */
  .hero-qr{
    display:flex; align-items:center; justify-content:center; flex-shrink:0;
    width:48px; height:48px; border-radius:15px; padding:0;
    background:rgba(255,255,255,0.055);
    border:0.5px solid rgba(255,173,51,0.30);
    color:#FFAD33;
    transition:transform 0.16s cubic-bezier(0.34,1.56,0.64,1), background 0.2s;
  }
  .hero-qr svg{ width:21px; height:21px; }
  .hero-qr:active{ transform:scale(0.92); background:rgba(255,173,51,0.14); }

  /* Le dessin déborde volontairement à droite et en bas : il donne de la
     profondeur sans réclamer de la place. */
  /* Écran étroit : le dessin recule pour que le texte respire. */
  @media (max-width: 360px){
    .hero h2{ font-size:19.5px; }
    .hero-cta{ height:44px; padding:0 17px; font-size:14px; }
  }

  @media (prefers-reduced-motion: reduce){
    .hero-cta{ transition:none; }
  }

  .list-tools{ display:flex; align-items:center; gap:10px; margin-bottom:14px; }
  .list-tools .dd-filter{ margin-bottom:0; flex:1; min-width:0; }


  .dd-filter{ position:relative; margin-bottom:14px; }
  .dd-trigger{
    display:flex; align-items:center; justify-content:space-between; width:100%;
    font-family:inherit; font-size:13.5px; font-weight:600; color:var(--label);
    background:none; border:none; padding:4px 0; cursor:pointer;
  }
  .dd-trigger svg{ width:14px; height:14px; color:var(--label); flex-shrink:0; transition:transform 0.2s; margin-left:10px; }
  .dd-trigger.open svg{ transform:rotate(180deg); }
  .dd-menu{
    display:none; position:absolute; top:100%; left:0; right:0; margin-top:8px;
    background:#1C1D20; border:0.5px solid var(--border); border-radius:14px;
    overflow:hidden; z-index:30; box-shadow:0 10px 30px rgba(0,0,0,0.5);
  }
  .dd-menu.open{ display:block; animation: authFormIn 0.2s cubic-bezier(0.22,1,0.36,1); }
  .dd-menu button{
    display:block; width:100%; text-align:left; font-family:inherit; font-size:13.5px; font-weight:500;
    color:var(--label-2); background:none; border:none; padding:12px 16px; border-bottom:0.5px solid var(--separator);
  }
  .dd-menu button:last-child{ border-bottom:none; }
  .dd-menu button.selected{ color:#fff; font-weight:700; }
  .dd-menu button:active{ background:rgba(255,255,255,0.06); }

  .search-bar{ display:flex; align-items:center; gap:8px; background:var(--bg-card); border:0.5px solid var(--border); border-radius:100px; padding:0 14px; height:38px; margin-bottom:12px; }

  .mode-choice-card{ cursor:pointer; transition: transform 0.15s cubic-bezier(0.34,1.56,0.64,1), opacity 0.2s; }
  .mode-choice-card:active{ transform:scale(0.98); }
  .mode-choice-card.disabled{ opacity:0.4; pointer-events:none; }
  .mode-choice-row{ display:flex; align-items:center; gap:14px; }
  /* Les modes portaient des émojis — rendus différemment sur chaque appareil, et
     jamais alignés entre eux. Ce sont désormais des tuiles arrondies à dégradé,
     comme les rangées des réglages d'iOS : même gabarit, même épaisseur de trait,
     une couleur par mode pour qu'on les distingue d'un coup d'œil. */
  /* Les icônes des modes reprennent la langue du dessin d'accueil : trait blanc,
     opacités étagées pour la profondeur, aucun aplat de couleur. Les fiches du
     fond sont à 16 et 26 %, celle de devant à 42 % avec un fond à 5 %, et le
     signe distinctif en blanc plein — exactement les valeurs du dessin. */
  .mode-choice-icon{
    flex-shrink:0; width:46px; height:44px;
    display:flex; align-items:center; justify-content:center;
    transition:transform 0.15s cubic-bezier(0.34,1.56,0.64,1);
  }
  .mode-choice-icon svg{ width:44px; height:42px; display:block; overflow:visible; }
  .mode-choice-card:active .mode-choice-icon{ transform:scale(0.94); }
  .mode-choice-text{ flex:1; }
  .mode-choice-title{ font-size:14.5px; font-weight:700; }
  .mode-choice-desc{ font-size:12px; color:var(--label-2); margin-top:2px; }
  .mode-choice-arrow{ font-size:22px; color:var(--label-2); flex-shrink:0; }

  .cat-grid{ display:grid; grid-template-columns:repeat(2,1fr); gap:10px; margin-bottom:14px; }
  /* ═══ Coquilles d'attente ═══
     Affichées à la place des vraies cartes tant que la base n'a pas répondu.
     La connexion à Supabase demande une à deux secondes au premier appel, et
     aucune ligne de code ne peut l'accélérer. Autant montrer l'app tout de
     suite, en creux, plutôt qu'un écran vide. */
  /* Les faux blocs de chargement ont été retirés : leur style part avec eux.
     Un jeu de règles qui ne s'applique plus à rien fait douter du reste. */
  .sq-bloc{ background:rgba(255,255,255,0.08); border-radius:8px; }

  .cat-cell, .proc-rich-card{
    padding:15px 15px 14px; text-align:left; transition: transform 0.15s cubic-bezier(0.34,1.56,0.64,1);
    position:relative; overflow:hidden;
  }
  .cat-cell:active, .proc-rich-card:active{ transform:scale(0.97); }
  .proc-rich-card{ margin-bottom:12px; }
  /* L'icône et le compteur s'alignent en HAUT, pas au centre : le compteur
     est une étiquette, il se pose au coin, il ne flotte pas à mi-hauteur d'une
     tuile de 46 px. */
  .cat-top{ display:flex; align-items:flex-start; justify-content:space-between; margin-bottom:16px; }
  /* L'anneau coloré retiré, l'icône flottait dans une boîte de 46 px vide.
     Elle occupe désormais toute la place : un dossier de 30 px posé dans une
     tuile de 46, comme les icônes des réglages. */
  /* Le conteneur épousait la taille de l'ancien anneau : 46 px pour un dessin
     de 26, donc dix pixels de vide tout autour. Il ne mesure plus rien — c'est
     le dessin qui donne la taille, et la carte se resserre d'autant. */
  .cat-ring-wrap{ position:relative; flex-shrink:0; display:flex; }
  .cat-ring-wrap svg{ width:46px; height:46px; transform:rotate(-90deg); }
  .cat-ring-bg{ fill:none; stroke:rgba(255,255,255,0.08); stroke-width:3; }
  .cat-ring-fill{ fill:none; stroke-width:3; stroke-linecap:round; transition:stroke-dashoffset 0.6s cubic-bezier(0.32,0.72,0,1); }
  .cat-icon{ display:flex; align-items:center; justify-content:center; font-size:24px; }

  /* Quand le conteneur porte un anneau, le dessin se pose DEDANS — sinon il
     s'affiche à côté. Le sélecteur ne vise que ce cas : ailleurs le conteneur
     n'a pas de taille, et c'est le dessin qui la donne. */
  .cat-ring-wrap > svg ~ .cat-icon{ position:absolute; inset:0; }
  /* Le fichier et la coche reprennent la langue des icônes de mode : trait
     blanc, mêmes épaisseurs, mêmes opacités. À 18 pixels on ne peut pas étager
     trois plans comme sur les grandes icônes — on garde le contour de devant
     à 75 % et les lignes de contenu à 35 %, ce qui donne le même grain. */
  /* `.cat-ring-wrap svg` fait tourner l'anneau de − 90° pour que sa jauge parte
     du haut. Ce sélecteur atteignait AUSSI le svg de l'icône, qui était donc
     affichée couchée. C'est pour ça qu'elle n'a jamais semblé droite, quel que
     soit le dessin. */
  .cat-icon svg{ width:26px; height:26px; display:block; transform:none; }
  /* Sur la fiche d'une procédure, le dessin va un cran plus loin : la carte est
     pleine largeur, elle a la place, et c'est le seul repère visuel de la ligne. */
  /* La fiche d'une procédure : 29 px côté équipe, où c'est le seul repère de la
     ligne. Côté gestion on garde la taille d'origine — la carte y porte déjà
     l'état de l'analyse, l'icône n'a pas à dominer. */
  #equipe-app .proc-rich-card .cat-icon svg{ width:26px; height:26px; }
  /* En gestion le dessin vit dans l'anneau coloré : il ne peut pas grandir
     autant, sinon il touche le trait. 20 px laissent l'anneau respirer. */
  #gestion-app .proc-rich-card .cat-icon svg{ width:20px; height:20px; }
  /* ═══════════════════════════════════════════════════════════════════════
     LA CARTE D'UNE CATÉGORIE

     Le dossier dans une pastille teintée, un compteur au coin, le nom, les
     derniers titres, et une ligne d'appel en pied. Cette dernière manquait :
     rien ne disait que la carte s'ouvrait.

     Le pied est poussé en bas par `margin-top:auto`. Sans lui, deux cartes
     voisines de contenus inégaux verraient leur ligne d'appel à des hauteurs
     différentes — et c'est justement la ligne qu'on balaye du regard.
     ═══════════════════════════════════════════════════════════════════════ */
  /* LES DEUX GRILLES, PAS UNE SEULE.

     Cette règle ne visait que `#cat-grid`, la grille de la gestion. La grille
     de l'équipe — `#e-cat-grid` — porte pourtant les mêmes cartes : elle
     n'héritait ni de la colonne, ni du retrait, ni du rayon. Les cartes
     paraissaient « presque pareilles », ce qui est pire que différentes.

     Un sélecteur par identifiant est un piège de ce genre : il marche jusqu'au
     jour où le même objet apparaît ailleurs. */
  #cat-grid .cat-cell,
  #e-cat-grid .cat-cell{
    display:flex; flex-direction:column;
    padding:14px 14px 0; border-radius:20px;
  }

  /* ═══ LA PLAQUE DU DOSSIER ═══
     Un fondu, et c'est tout. Pas de halo, pas d'éclat sur l'arête, pas de
     lueur sur le dessin : la teinte s'éteint simplement du haut vers le bas,
     et un filet très fin ferme la forme. C'est ce qui donne la matière sans
     que la plaque se mette à briller — quatre cartes par écran, quatre halos
     auraient fait un sapin. */
  .cat-ic{
    display:flex; align-items:center; justify-content:center; flex-shrink:0;
    width:40px; height:40px; border-radius:13px;
    background:linear-gradient(165deg,
      rgba(255,173,51,0.11) 0%, rgba(255,173,51,0.045) 52%, rgba(255,173,51,0.015) 100%);
    border:0.5px solid rgba(255,173,51,0.20);
  }
  .cat-ic svg{ width:21px; height:21px; display:block; }

  .cat-pied{
    display:flex; align-items:center; gap:7px;
    margin-top:auto; padding:10px 0 12px;
    border-top:0.5px solid var(--separator);
    font-size:11.5px; font-weight:600; color:var(--label-2);
  }
  .cat-pied svg{ width:14px; height:14px; flex-shrink:0; }
  .cat-pied span:not(.fl){ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .cat-pied .fl{ margin-left:auto; color:var(--label-3); font-size:16px; line-height:1; }

  /* Les titres récents respirent avant le pied. Les deux grilles, là encore. */
  #cat-grid .cat-recent,
  #e-cat-grid .cat-recent{ padding-bottom:11px; }

  /* ═══════════════════════════════════════════════════════════════════════
     LA CARTE D'UNE PROCÉDURE

     Même grammaire que la dossier : la plaque à gauche, le nom, un filet, et
     un pied. Ce qui change, c'est ce que dit le pied — ici le suivi de lecture,
     la seule chose qu'un gérant vient vérifier.

     La jauge porte la couleur du taux, pas celle de la marque : c'est un
     signal, pas un décor. Vert au-dessus de 70 %, ambre au-dessus de 30,
     rouge en dessous.
     ═══════════════════════════════════════════════════════════════════════ */
  .proc-rich-card{ padding:14px 14px 0; border-radius:20px; }

  .proc-tete{ display:flex; align-items:center; gap:12px; }
  .proc-co{ flex:1; min-width:0; }
  .proc-nom{
    display:flex; align-items:center; gap:6px;
    font-size:15.5px; font-weight:700; letter-spacing:-0.03em;
  }
  .proc-nom .txt{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .proc-meta{ font-size:11.5px; color:var(--label-3); font-weight:600; margin-top:3px; }
  .proc-fl{ color:var(--label-3); font-size:18px; line-height:1; flex-shrink:0; }

  .proc-pied{
    display:flex; align-items:center; gap:10px;
    margin-top:13px; padding:11px 0 13px;
    border-top:0.5px solid var(--separator);
  }
  .proc-jauge{
    flex:1; min-width:0; height:5px; border-radius:3px; overflow:hidden;
    background:rgba(255,255,255,0.08);
  }
  .proc-jauge i{ display:block; height:100%; border-radius:3px; }
  .proc-taux{
    font-size:11.5px; font-weight:650; flex-shrink:0;
    font-variant-numeric:tabular-nums;
  }
  .proc-taux b{ font-weight:750; }
  .proc-taux em{ font-style:normal; color:var(--label-3); font-weight:600; }

  .cat-badge{
    font-size:11px; font-weight:700; margin-top:3px; background:rgba(255,255,255,0.08); color:var(--label-2);
    padding:4px 9px; border-radius:100px; flex-shrink:0;
  }
  /* Le nom et son indicateur d'état partagent une ligne : le texte prend la
     place disponible, l'icône se cale juste à sa suite. */
  /* Le nom prend plus de corps : c'est la seule chose qu'on cherche en
     balayant la grille. */
  .cat-name{
    display:flex; align-items:center; gap:6px; margin-bottom:3px;
    font-size:16px; font-weight:700; letter-spacing:-0.03em; color:var(--label);
  }
  .cat-name .txt{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .cat-recent-item .txt{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  /* Dans la liste des titres récents, le texte est plus petit : l'indicateur
     se met à l'échelle pour ne pas écraser la ligne. */
  .cat-recent-item .etat-proc{ width:11px; height:11px; }
  .cat-recent-item .etat-proc svg{ width:13px; height:13px; }
  .cat-recent-item .etat-proc.prete{ width:13px; height:13px; }
  .cat-recent-item .etat-proc.prete svg{ width:13px; height:13px; }
  .cat-pct-row{ display:flex; align-items:baseline; gap:5px; margin-bottom:8px; }
  .cat-pct{ font-size:20px; font-weight:800; letter-spacing:-0.02em; }
  /* Côté équipe, le compteur est un rapport (« 2/2 lues ») et non un
     pourcentage : il tient sur la même ligne à une taille plus mesurée. */
  .cat-pct-label{ font-size:10.5px; color:var(--label-3); }
  .cat-date{ font-size:10.5px; font-weight:600; color:var(--label-3); margin-top:4px; font-variant-numeric:tabular-nums; }
  .carte-categorie{ font-size:11px; font-weight:600; color:var(--label-3); margin-top:3px; }
  .cat-recent{ border-top:0.5px solid var(--separator); padding-top:9px; margin-top:10px; }
  /* Le titre d'une procédure récente et, le cas échéant, son état d'analyse :
     l'indicateur se cale juste au bout du texte, pas au bout de la carte. */
  .cat-recent-item{
    display:flex; align-items:center; gap:5px;
    font-size:10.5px; color:var(--label-2);
    padding:2px 0;
  }
  .cat-cell.active{ border-color:#fff; background:rgba(255,255,255,0.14); }
  .search-bar svg{width:15px; height:15px; color:var(--label-2); flex-shrink:0;}
  .search-bar input{background:none; border:none; font-size:16px; width:100%;}


  /* ═══ Le viseur ═══ */
  .scan-result{ margin-top:18px; background:var(--bg-card); border:0.5px solid var(--border); border-radius:16px; padding:16px; display:flex; align-items:center; gap:12px; }
  .scan-result .icon{ width:38px; height:38px; border-radius:12px; background:var(--green); display:flex; align-items:center; justify-content:center; flex-shrink:0; }
  .scan-result .icon svg{width:20px; height:20px; color:#000;}
  .scan-vue{
    /* Aucune marge haute : le viseur commence à la même ligne que la carte
       « Bonjour prénom » de la page des procédures. Passer d'un onglet à l'autre
       ne doit pas faire sauter le contenu. */
    position:relative; margin-top:0; height:calc(100vh - 280px);
    max-height:460px; min-height:320px;
    border-radius:26px; overflow:hidden; background:#000;
    border:0.5px solid var(--border);
  }
  .scan-vue video{ width:100%; height:100%; object-fit:cover; display:block; }

  /* La cible éclaircit la zone utile et assombrit le reste. L'ombre portée
     démesurée est le moyen le plus simple de noircir tout ce qui l'entoure
     sans ajouter d'élément par-dessus la vidéo. */
  .scan-cible{
    position:absolute; left:50%; top:40%; transform:translate(-50%, -50%);
    width:min(62vw, 200px); aspect-ratio:1/1; border-radius:26px;
    background:rgba(255,255,255,0.08);
    box-shadow:0 0 0 9999px rgba(0,0,0,0.45);
    pointer-events:none;
  }
  .scan-cible .c{ position:absolute; width:30px; height:30px; border-color:#fff; border-style:solid; }
  .scan-cible .tl{ top:-2px; left:-2px; border-width:3.5px 0 0 3.5px; border-top-left-radius:14px; }
  .scan-cible .tr{ top:-2px; right:-2px; border-width:3.5px 3.5px 0 0; border-top-right-radius:14px; }
  .scan-cible .bl{ bottom:-2px; left:-2px; border-width:0 0 3.5px 3.5px; border-bottom-left-radius:14px; }
  .scan-cible .br{ bottom:-2px; right:-2px; border-width:0 3.5px 3.5px 0; border-bottom-right-radius:14px; }

  /* Le titre et la consigne, en bas de l'image. Un dégradé sous eux les détache
     du fond quelle que soit la scène filmée — un plan de travail blanc rendrait
     du texte blanc illisible. */
  .scan-mot{
    position:absolute; left:0; right:0; bottom:0;
    padding:48px 24px 70px; text-align:center; pointer-events:none;
    background:linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.62) 58%, rgba(0,0,0,0.78) 100%);
  }
  /* La même écriture que les titres de page : même taille, même graisse, même
     resserrement. Un texte posé sur une image n'a pas de raison d'avoir sa
     propre typographie. */
  /* Exactement `.pagehead` et `.subhead`, l'ombre en plus. Un titre posé sur une
     image n'a pas de raison d'avoir sa propre typographie — seule l'ombre
     s'ajoute, pour qu'il reste lisible sur une scène claire. */
  .scan-mot b{
    display:block; font-size:20px; font-weight:700; letter-spacing:-0.025em;
    line-height:1.2; text-shadow:0 2px 16px rgba(0,0,0,0.85);
  }
  .scan-mot span{
    display:block; font-size:13px; color:var(--label-2); margin-top:4px;
    line-height:1.35; text-shadow:0 2px 12px rgba(0,0,0,0.85);
  }

  /* Le message d'échec. Il respire : collé sous le viseur, il ressemblait à une
     légende de l'image alors que c'est lui qu'il faut lire. */
  .scan-echec{
    margin-top:26px; padding:22px 20px; border-radius:20px;
    background:var(--bg-card); border:0.5px solid var(--border);
  }
  .scan-echec .ic{
    width:46px; height:46px; border-radius:14px; margin:0 auto 14px;
    display:flex; align-items:center; justify-content:center;
    background:rgba(255,69,58,0.13); border:0.5px solid rgba(255,69,58,0.26);
    color:var(--red);
  }
  .scan-echec .ic svg{ width:23px; height:23px; }
  .scan-echec .t{ font-size:16px; font-weight:750; letter-spacing:-0.03em; text-align:center; }
  .scan-echec .s{
    font-size:13px; color:var(--label-2); line-height:1.5;
    margin-top:7px; text-align:center;
  }
  .scan-echec .pas{
    margin:18px 0 0; padding:0; list-style:none;
    counter-reset:pas;
  }
  .scan-echec .pas li{
    position:relative; counter-increment:pas;
    padding:11px 0 11px 38px; font-size:13.5px; line-height:1.45;
    border-bottom:0.5px solid rgba(255,255,255,0.055);
  }
  .scan-echec .pas li:last-child{ border-bottom:none; }
  .scan-echec .pas li::before{
    content:counter(pas); position:absolute; left:0; top:10px;
    width:24px; height:24px; border-radius:50%;
    display:flex; align-items:center; justify-content:center;
    font-size:12px; font-weight:750; color:var(--label-2);
    background:rgba(255,255,255,0.07); border:0.5px solid var(--border);
  }
  .scan-echec .pas b{ font-weight:700; color:#fff; }
  .scan-echec .repli{
    font-size:12px; color:var(--label-3); line-height:1.45; margin-top:14px;
    padding-top:13px; border-top:0.5px solid rgba(255,255,255,0.055);
  }
  .scan-echec .btn{ margin-top:18px; }

  /* Les deux commandes aux deux coins de l'image. */
  .scan-outils{
    position:absolute; left:16px; right:16px; bottom:16px;
    display:flex; justify-content:space-between; align-items:center;
  }
  .scan-cam{
    width:44px; height:44px; border-radius:50%; border:none; padding:0;
    background:rgba(255,255,255,0.16); backdrop-filter:blur(20px);
    -webkit-backdrop-filter:blur(20px);
    display:flex; align-items:center; justify-content:center; color:#fff;
  }
  .scan-cam svg{ width:20px; height:20px; display:block; }
  .scan-cam .ic-off{ display:none; }
  /* Éteinte, la commande passe en plein : c'est un état, pas une action
     disponible. La même bascule que la lampe. */
  .scan-cam.eteinte{ background:#fff; color:#000; }
  .scan-cam.eteinte .ic-on{ display:none; }
  .scan-cam.eteinte .ic-off{ display:block; }
  .scan-cam:active{ transform:scale(0.92); }

  .scan-lampe{
    width:44px; height:44px; border-radius:50%; border:none; padding:0;
    background:rgba(255,255,255,0.16); backdrop-filter:blur(20px);
    display:flex; align-items:center; justify-content:center; color:#fff;
  }
  /* Le dessin d'une torche est plus haut que large : centré sur sa boîte, il
     paraît posé trop bas dans le rond. On le remonte d'un pixel. */
  .scan-lampe svg{ width:20px; height:20px; display:block; margin-top:-1px; }
  .scan-lampe.on{ background:#fff; color:#000; }
  .scan-lampe:active{ transform:scale(0.92); }


  .note{ font-size:12.5px; color:var(--label-2); margin-top:14px; }

  .empty-state{ text-align:center; padding:36px 20px 20px; }
  .empty-state h3{ font-size:16px; font-weight:700; margin-bottom:6px; }
  .empty-state p{ font-size:13px; color:var(--label-2); max-width:250px; margin:0 auto; line-height:1.5; }

  /* ═══ Premier écran, quand rien n'existe encore ═══
     Centré verticalement dans la place laissée par la barre du haut et la
     barre d'onglets, avec un dessin au trait au-dessus du texte. */
  /* La hauteur est MESURÉE, pas devinée : `100vh - 300px` supposait une hauteur
     fixe pour ce qui précède, et le dessin se retrouvait trop haut sur un grand
     écran, coupé sur un petit. La variable est posée au rendu, à partir de la
     position réelle de la grille et de la hauteur réelle de la barre.
     `dvh` plutôt que `vh` : sur téléphone, `vh` ignore la barre d'adresse. */
  /* LE BLOC OCCUPE LA PLACE ENTRE LES FILTRES ET LA BARRE, et son contenu s'y
     centre. Le rembourrage du bas tient compte du bouton + flottant : sans
     lui, la dernière ligne passait DESSOUS et devenait illisible — c'est ce
     qu'on voyait sur la page vide.

     84 px : la hauteur du bouton plus sa marge, et de quoi respirer. */
  /* ═══════════════════════════════════════════════════════════════════════
     LA HAUTEUR NE SE MESURE PLUS, ELLE SE DÉDUIT

     Un script mesurait la position du bloc et en tirait sa hauteur. Il tournait
     TROP TARD : pendant deux cents millisecondes, le bloc gardait sa valeur de
     repli, trop grande — le dessin paraissait bas et la page défilait. Puis un
     glissement déclenchait un nouveau calcul, et tout se remettait en place
     d'un coup. C'est précisément ce qu'on voyait.

     Le CSS sait faire ça sans rien mesurer. L'écran devient une colonne, la
     grille prend la place qui reste, le bloc la remplit. Aucun délai possible :
     c'est vrai dès la première image.

     `:has()` limite tout ça au seul cas du bloc d'accueil — les pages qui ont
     du contenu gardent leur disposition en grille, intacte.
     ═══════════════════════════════════════════════════════════════════════ */
  .screen.active:has(#cat-grid .debut),
  .screen.active:has(#e-cat-grid .debut){
    display:flex; flex-direction:column;
    /* SANS CETTE HAUTEUR, RIEN NE S'ÉTIRE. Une colonne souple ne distribue que
       la place qu'elle a — et un écran ne fait par défaut que la hauteur de son
       contenu. La grille restait donc collée sous les filtres, et le dessin
       remontait de 130 px.

       `100dvh` avec un modèle de boîte à bordure : le rembourrage du bas, qui
       réserve la barre et le bouton, est compris dedans. La page tient donc
       exactement dans la fenêtre. */
    min-height:100dvh;
  }
  #cat-grid:has(.debut),
  #e-cat-grid:has(.debut){
    flex:1 1 auto; display:flex; min-height:0;
  }

  .debut{
    grid-column:1/-1; display:flex; flex-direction:column;
    align-items:center; justify-content:center; text-align:center;
    /* `flex:1` quand la grille est en colonne souple ; la valeur de repli ne
       sert plus que si `:has()` n'est pas reconnu. */
    flex:1 1 auto; width:100%;
    min-height:var(--debut-h, 0);
    /* ═══ UN REMBOURRAGE ÉGAL, PARCE QUE LA HAUTEUR EST DÉJÀ JUSTE ═══

       Il valait 84 px en bas, pour dégager le bouton + flottant. Mais la
       hauteur du bloc, elle, s'arrête DÉJÀ au bouton : le calcul retranche le
       rembourrage de l'écran, qui réserve exactement cette place. Les 84 px
       faisaient donc double emploi, et poussaient le contenu 31 px trop haut.

       Vingt pixels partout. Le contenu se centre alors dans la place réelle —
       du haut de la grille au bouton — et ne le touche jamais. */
    padding:20px;
  }
  /* La consigne finale, plus discrète que le paragraphe : c'est une indication
     de geste, pas une explication. */
  .debut .fleche b{ color:#FFAD33; font-weight:800; }
  .debut-dessin{ position:relative; width:132px; height:120px; margin-bottom:26px; }
  .debut-dessin .lueur{
    position:absolute; left:50%; top:52%; transform:translate(-50%,-50%);
    width:150%; height:150%; border-radius:50%; pointer-events:none;
    background:radial-gradient(circle, rgba(255,255,255,0.13) 0%, transparent 66%);
    filter:blur(14px); animation:debutLueur 4.5s ease-in-out infinite;
  }
  .debut-dessin svg{ position:relative; width:100%; height:100%; overflow:visible; }
  /* Les deux fiches du fond montent doucement, décalées l'une de l'autre. */
  .debut-dessin .fond-2{ animation:debutFlotte 5.4s ease-in-out infinite; }
  .debut-dessin .fond-1{ animation:debutFlotte 5.4s ease-in-out -1.8s infinite; }
  .debut-dessin .devant{ animation:debutFlotte 5.4s ease-in-out -3.4s infinite; }
  .debut-dessin .signe{ animation:debutSigne 5.4s ease-in-out infinite; transform-origin:center; }
  /* Le même battement discret sur le signe des icônes de mode. */
  .mode-choice-icon .signe{ animation:debutSigne 5.4s ease-in-out infinite; transform-origin:center; }
  @media (prefers-reduced-motion: reduce){ .mode-choice-icon .signe{ animation:none; } }
  @keyframes debutFlotte{ 0%,100%{ transform:translateY(0); } 50%{ transform:translateY(-4px); } }
  @keyframes debutLueur{ 0%,100%{ opacity:0.55; } 50%{ opacity:1; } }
  @keyframes debutSigne{ 0%,100%{ opacity:0.75; } 50%{ opacity:1; } }
  @media (prefers-reduced-motion: reduce){
    .debut-dessin *{ animation:none !important; }
  }
  .debut h3{ font-size:19px; font-weight:750; letter-spacing:-0.03em; margin-bottom:8px; }
  .debut p{ font-size:13.5px; color:var(--label-2); max-width:260px; margin:0 auto; line-height:1.55; }
  .debut .fleche{
    margin-top:22px; max-width:250px; line-height:1.5; text-align:center;
    font-size:12px; font-weight:600; color:var(--label-3);
  }
  .debut .fleche svg{ width:13px; height:13px; animation:debutDescend 2.2s ease-in-out infinite; }
  @keyframes debutDescend{ 0%,100%{ transform:translateY(0); opacity:0.6; } 50%{ transform:translateY(3px); opacity:1; } }
  .error-msg{ font-size:13px; color:var(--red); margin-top:8px; }

  /* La carte est centrée, puis remontée de CINQ PIXELS.

     J'avais mis 6 % de la hauteur d'écran — une cinquantaine de pixels sur un
     iPhone. C'était le décalage qu'on donne à un bloc pour corriger le centre
     optique, mais ici il se voyait : la carte paraissait posée en haut plutôt
     que centrée.

     Cinq pixels en valeur fixe, et non en pourcentage : à cette échelle, un
     pourcentage n'a plus de sens — cinq pixels doivent rester cinq pixels sur
     tous les écrans. */
  .login-wrap{ position:fixed; inset:0; display:flex; align-items:center; justify-content:center; padding:24px; overflow:hidden; touch-action:none; }
  .login-wrap > .login-card{ transform:translateY(-5px); }

  /* ═══ Apparition du logo ═══
     Le logo arrive légèrement flou et plus petit, monte et se met au net.
     Tout se joue sur l'opacité, la transformation et le flou : rien qui
     oblige le navigateur à redessiner un tracé image par image, contrairement
     à l'animation de contour d'avant. Elle n'est lancée qu'une fois l'écran
     réellement peint, sinon son horloge tourne pendant que rien ne s'affiche. */
  /* Le cadre était de 30 × 35 — la proportion du « P », plus haut que large.
     Le nouveau ruban est CARRÉ : gardé dans l'ancien cadre, il aurait été
     écrasé ou réduit. */
  .boot-logo{
    position:relative; width:29px; height:41px; margin:0 auto 14px;
    display:flex; align-items:center; justify-content:center; opacity:0;
  }
  .boot-logo svg{ width:100%; height:100%; position:relative; z-index:1; }
  /* `object-fit: contain` : le dessin garde ses proportions quoi qu'il arrive.
     Sans lui, une image carrée dans un cadre non carré se déforme. */
  .boot-logo img.boot-fill{
    width:100%; height:100%; object-fit:contain;
    position:relative; z-index:1; display:block;
  }
  .boot-fill{ opacity:1; }
  .boot-glow{
    position:absolute; width:170%; height:170%; border-radius:50%;
    background:radial-gradient(circle, rgba(255,255,255,0.30) 0%, transparent 68%);
    filter:blur(8px); opacity:0;
  }

  .boot-logo.play{ animation: logoDoux 0.85s cubic-bezier(0.16,1,0.3,1) both; }
  @keyframes logoDoux{
    0%   { opacity:0; transform:scale(0.7) translateY(7px); filter:blur(4px); }
    100% { opacity:1; transform:scale(1) translateY(0); filter:blur(0); }
  }
  /* Le halo suit le même geste, puis s'efface. */
  .boot-logo--once.play .boot-glow{ animation: logoLueur 1.15s ease-out both; }
  @keyframes logoLueur{
    0%   { opacity:0; transform:scale(0.7); }
    45%  { opacity:0.85; transform:scale(1); }
    100% { opacity:0; transform:scale(1.12); }
  }

  /* Variante de la barre du haut. Déclarée APRÈS `.boot-logo` : à specificité
     égale c'est la dernière règle qui l'emporte, et sa taille doit gagner.

     AUCUNE ANIMATION ICI. Le logo de l'écran de démarrage a la sienne — il est
     seul à l'écran, il annonce l'app. Celui de la barre du haut est un repère
     permanent : le faire grandir et se dé-flouter à chaque ouverture attirait
     l'œil sur un élément qui n'a rien à dire, pendant que le reste chargeait. */
  /* Le cadre suit le RAPPORT du dessin — 0,74, soit 25 sur 34. Forcé en carré,
     il ajoutait 149 px de vide de chaque côté dans l'image : c'est ce vide,
     et non la marge, qui éloignait le logo du nom. */
  /* 22 sur 28, au rapport 0,773 du dessin.

     ═══ ET L'ALIGNEMENT ═══

     Pas de décalage vertical : j'en avais ajouté deux pixels en croyant le
     dessin déséquilibré. Mesuré, son centre de gravité est à 0,6 % du centre
     géométrique — il est droit. Les deux pixels ne corrigeaient rien, ils
     désalignaient. */
  /* 22 sur 31 : le nouveau dessin est plus étroit — rapport 0,706 contre 0,773.
     Garder 24 l'aurait élargi de deux pixels, donc déformé. */
  .boot-logo--topbar{ width:22px; height:31px; margin:0; opacity:1; }
  .boot-logo--topbar.play{ animation:none; }

  @media (prefers-reduced-motion: reduce){
    .boot-logo{ opacity:1; }
    .boot-logo.play, .boot-logo--topbar.play, .boot-logo--once.play .boot-glow{ animation:none !important; }
  }

  @keyframes spin{ to{ transform:rotate(360deg); } }

  .btn-spinner{
    display:inline-block; width:15px; height:15px; border-radius:50%;
    border:2px solid rgba(0,0,0,0.25); border-top-color:#000;
    animation: spin 0.7s linear infinite; vertical-align:middle;
  }
  .btn.ghost .btn-spinner{ border-color:rgba(255,255,255,0.25); border-top-color:#fff; }
  .btn[data-loading="true"]{ pointer-events:none; opacity:0.85; }
  .login-card{ width:100%; max-width:360px; max-height:92vh; overflow-y:auto; background:var(--bg-card); border:0.5px solid var(--border); border-radius:20px; padding:28px 24px;
    -webkit-backdrop-filter:blur(20px) saturate(180%); backdrop-filter:blur(20px) saturate(180%); touch-action:pan-y; }

  .auth-toggle{
    position:relative; display:flex; gap:0; background:rgba(255,255,255,0.06); border:0.5px solid var(--border);
    border-radius:100px; padding:4px; margin-bottom:22px;
  }
  /* La pastille qui glisse sous l'onglet choisi. Elle était blanche — la
     dernière surface de l'app à l'être, alors que tous les gestes principaux
     sont passés à l'ambre. Un blanc isolé au milieu d'une page orange se lit
     comme un oubli. */
  .auth-toggle-indicator{
    position:absolute; top:4px; left:4px; width:calc(50% - 4px); height:calc(100% - 8px);
    background:linear-gradient(135deg,#FF6A00 0%,#FF9A1F 60%,#FFAD33 100%);
    border-radius:100px; z-index:0;
    box-shadow:0 4px 14px rgba(255,122,24,0.26);
    transition: transform 0.4s cubic-bezier(0.34,1.56,0.64,1);
  }
  .auth-toggle-btn{
    position:relative; z-index:1; flex:1; text-align:center; font-size:13px; font-weight:600; padding:9px 0;
    border-radius:100px; color:var(--label-2); transition: color 0.3s ease;
  }
  /* Texte sombre sur l'orange, comme sur les boutons : à cette clarté, du
     blanc perdrait le contraste que le noir garde sans effort. */
  .auth-toggle-btn.active{ color:#2A1400; font-weight:750; }

  .auth-form-wrap{ position:relative; }
  .auth-form{ display:none; }
  .auth-form.active{ display:block; animation: authFormIn 0.45s cubic-bezier(0.22,1,0.36,1); }
  @keyframes authFormIn{
    0%  { opacity:0; transform:scale(0.975); }
    30% { opacity:1; }
    100%{ opacity:1; transform:none; }
  }
  .login-card h1{ font-size:22px; margin-bottom:6px; }
  .login-card .subhead{margin-bottom:20px;}

  /* Exactement le verre de `.topbar-card` : même fond, même flou, même
     saturation. J'avais renforcé les valeurs pour compenser un effet perçu plus
     faible sur une grande surface — mais deux éléments qui se font face en haut
     et en bas de l'écran doivent porter la même matière, pas une matière
     corrigée. */
  /* Le bouton principal porte les deux dessins ; l'espace courant décide lequel
     se montre. */
  #tabbar .ic-equipe{ display:none; }
  #tabbar[data-espace="equipe"] #tb-analyse{ display:none; }
  #tabbar[data-espace="equipe"] .ic-gestion{ display:none; }
  #tabbar[data-espace="equipe"] .ic-equipe{ display:block; }

  /* L'ancienne barre était une pilule de 100 px de rayon, en `display:flex` avec
     un `gap` de 22 px. Elle imposait sa largeur à la nouvelle, qui n'en faisait
     plus que 220 au lieu de 374. Retirée. */
  /* La règle d'origine, avec son identifiant. J'avais réécrit une version sans
     identifiant : moins spécifique, elle était écrasée par ce qui suit, et le
     groupe perdait son verre — il ne restait que les ronds. */
  /* Cette règle imposait `display:flex` et un `gap` par IDENTIFIANT — plus
   lourd qu'une classe. La barre ne faisait plus que 220 px au lieu de 374,
   et les cinq onglets se serraient au milieu sans qu'aucune erreur ne le
   signale. La mise en page appartient désormais à `.tabbar` seule. */

  /* ═══ Barre d'onglets (les deux espaces) ═══
     Deux éléments distincts : un groupe en verre qui contient les onglets, et
     un bouton d'action détaché à droite. L'onglet actif ne reçoit pas une
     pastille par-dessus — c'est lui qui se déploie, prend un fond blanc et
     laisse apparaître son libellé. La largeur s'anime, d'où l'effet de
     glissement d'un onglet à l'autre. */
  /* Cette règle imposait la mise en page par IDENTIFIANT — plus lourd qu'une
     classe. La barre ne faisait que 220 px au lieu de 374, les cinq onglets se
     serraient au milieu, et rien ne le signalait : un identifiant l'emporte
     silencieusement sur une classe.
     La mise en page appartient désormais à `.tabbar` seule. */
  /* ═══ Frise zoomable ═══
     C'est la convention de toutes les applications de montage : la frise n'est
     pas figée à la largeur de l'écran, on l'agrandit et on la fait défiler.
     À ×8, une seconde occupe huit fois plus de place — on cale au dixième sans
     loupe. La fenêtre garde la tête de lecture visible en la suivant. */
  .frise-fenetre{
    overflow-x:auto; overflow-y:visible; -webkit-overflow-scrolling:touch;
    scrollbar-width:none; padding:6px 0;
  }
  .frise-fenetre::-webkit-scrollbar{ display:none; }
  .frise-fenetre .capcut-timeline{ min-width:100%; }

  .zoom-frise{ display:flex; align-items:center; gap:7px; margin-top:9px; }
  .zoom-btn{
    width:32px; height:32px; border-radius:10px; flex-shrink:0;
    border:0.5px solid var(--border); background:rgba(255,255,255,0.08);
    color:#fff; font-size:16px; font-weight:700; font-family:inherit;
  }
  .zoom-btn:active{ background:rgba(255,255,255,0.18); }
  .zoom-btn:disabled{ opacity:0.3; }
  .zoom-val{ font-size:12px; font-weight:700; color:var(--label-2); min-width:26px; text-align:center; }
  /* « Étapes liées » : le montage par report, là encore une convention des vraies
     applications. Quand c'est actif, déplacer une borne déplace celle de la
     voisine : la vidéo reste couverte, aucun trou ne peut apparaître. */
  .zoom-lien{
    margin-left:auto; height:32px; padding:0 13px; border-radius:10px;
    border:0.5px solid var(--border); background:rgba(255,255,255,0.08);
    color:var(--label-2); font-size:11.5px; font-weight:650; font-family:inherit;
  }
  .zoom-lien.active{ background:rgba(255,255,255,0.9); color:#000; border-color:transparent; }

  /* Deux réglages à ne pas confondre : la TEINTE opacifie, le FLOU brouille.
     Une teinte basse laisse voir à travers, un flou élevé rend illisible ce
     qu'on voit. On veut les deux : 7 % de teinte pour la transparence, 50 px
     de flou pour que le fond ne soit plus qu'une tache de couleur. */
  /* Le verre du groupe. Ce sélecteur était coupé en deux par le commentaire qui
     suit : le navigateur lisait un sélecteur inachevé et jetait la règle avec.
     Le groupe n'avait donc AUCUN fond — il ne restait que les ronds blancs. */

  /* ═══ Pourquoi le libellé est en position absolue ═══
     Faire varier `max-width` sur le texte le rognait progressivement : on
     voyait les lettres se faire couper, ce qui ne ressemble à rien de naturel.
     Le libellé est donc sorti du flux et ne fait plus qu'apparaître en fondu
     avec un léger glissement — deux propriétés que le processeur graphique
     gère seul, sans recalcul de mise en page.
     Seule la largeur du bouton s'anime, et elle est mesurée à l'ouverture pour
     coller exactement au texte. */
  
  
  /* L'icône reste à sa place, elle glisse juste un peu vers la gauche. */
  
  
  .tab-label{
    position:absolute; left:42px; top:50%; white-space:nowrap;
    font-size:14px; font-weight:650; letter-spacing:-0.02em;
    opacity:0; transform:translate(-8px, -50%);
    transition: opacity 0.18s ease, transform 0.18s ease;
  }
  /* Le texte n'arrive qu'une fois la pilule ouverte, et repart aussitôt. */
  
  /* Le bouton d'action, détaché du groupe. */
  
  /* Le bouton principal est un rond : son dessin se centre. Il héritait du
     `margin-left` de 12,5 px prévu pour les onglets, où l'icône doit laisser la
     place au libellé qui glisse à sa droite. */
  
  /* Un pouce de moins et un pixel plus bas : le « + » et le QR paraissaient
     légèrement hauts dans leur rond, et un peu gros pour lui. */
  

  .tab-pill{
    position:absolute; top:0; left:0; width:44px; height:44px; border-radius:100px;
    background:rgba(255,255,255,0.26); pointer-events:none; opacity:0;
    transition: transform 0.45s cubic-bezier(0.34,1.4,0.5,1), opacity 0.25s ease;
  }
  /* Onglets sans texte : icône seule, en ligne quand l'onglet dort, pleine et
     blanche quand on est sur la page. Deux tracés superposés dans chaque
     bouton, on montre l'un ou l'autre. */
  .tab-round{ position:relative; z-index:1; width:44px; height:44px; border-radius:100px;
    display:flex; align-items:center; justify-content:center; padding:0;
    transition: transform 0.18s cubic-bezier(0.34,1.56,0.64,1), color 0.25s; }
  .tab-round:active{ transform:scale(0.88); }
  .tab-round svg{ width:23px; height:23px; }
  .tab-round--secondary{ background:none; border:none; color:rgba(235,235,245,0.6); }
  .tab-round--secondary.active{ color:#fff; }
  .tab-round .ico-plein{ display:none; }
  .tab-round.active .ico-ligne{ display:none; }
  .tab-round.active .ico-plein{ display:block; }
  .tab-round--primary{ background:#fff; color:#000; width:44px; height:44px; padding:0; box-shadow:0 4px 12px rgba(255,255,255,0.2), 0 2px 6px rgba(0,0,0,0.25); border:0.5px solid rgba(255,255,255,0.4); }
  .tab-round--primary svg{ width:23px; height:23px; }



/* ═══════════════════════════════════════════════════════════════════════
   LA BARRE DU HAUT, CENTRÉE

   Le bouton des réglages est parti — ils ont leur onglet dans la barre du
   bas maintenant, et deux entrées pour la même page se contredisaient.

   Ce qui reste — le logo et le nom — se centre. Aligné à gauche, l'espace
   laissé par le bouton disparu se lisait comme un manque.
   ═══════════════════════════════════════════════════════════════════════ */
.topbar-row{justify-content:center}
.topbar-card{
  /* La carte ne s'étire plus sur toute la largeur : elle prend la taille de
     son contenu, ce qui permet de la centrer vraiment. */
  flex:0 0 auto;
  justify-content:center;
}
.topbar-left{justify-content:center}

/* Le tiroir de l'entreprise sort du flux.

   Il occupait 46 px dans la rangée et poussait la carte de 28 px vers la
   droite — elle paraissait centrée sur la place restante, pas sur l'écran.
   Posé en absolu à gauche, il garde sa place à l'œil sans peser sur le
   centrage. */
.topbar-row > .tiroir-ent{
  position:absolute;left:0;top:50%;transform:translateY(-50%);
}



/* ═══════════════════════════════════════════════════════════════════════
   LA CARTE DU LOGO — la matière de la navbar

   Elle avait son propre verre : blanc à 10 %, flou de 24 px, bordure à 18 %.
   La barre du bas, elle, utilise le verre `liquid-glass` : teinte à 6 %,
   ombre interne de 17 px en creux, et une réfraction en filtre SVG.

   Deux verres différents dans un même écran, et l'œil sent que ce sont deux
   objets — alors que ce sont deux éléments de la même interface. On aligne
   la carte sur la barre.
   ═══════════════════════════════════════════════════════════════════════ */
/* ═══ UNE SEULE COUCHE ═══

   La carte empilait trois plans : l'élément, une teinte en `::before`, et le
   verre en `::after` au plan −1. Trois surfaces à la même place, dont une
   DERRIÈRE le parent — et selon le navigateur, l'arête se détachait du reste,
   comme un contour posé en arrière-plan.

   Tout est maintenant sur l'élément lui-même : le fond, le flou, le creux et
   l'arête. Une seule surface, rien qui puisse se décaler. */
.topbar-card{
  background-color:rgba(var(--tint-color, 255,255,255), var(--tint-opacity, .06));
  -webkit-backdrop-filter:var(--verre-bar);
  backdrop-filter:var(--verre-bar);
  border:none;
  box-shadow:
    0 4px var(--outer-shadow-blur, 17px) rgba(0,0,0,.18),
    inset 0 0 var(--shadow-blur, 17px) var(--shadow-spread, -8px) var(--shadow-color, #000);
}
/* Le même liseré que la barre du bas : une seule valeur sur tout le tour. Les
   deux pièces sont de la même matière — leurs bords doivent se ressembler. */
.topbar-card::after{
  content:''; position:absolute; inset:0; z-index:3;
  border-radius:inherit; pointer-events:none;
  /* Un trait fin, D'UNE SEULE ÉPAISSEUR. Le dégradé d'avant faisait paraître
     le haut plus épais que le bas — l'œil lit une variation de clarté comme
     une variation d'épaisseur. Voir le même réglage sur `.glassDiv` dans
     index.html : les deux pièces doivent se ressembler exactement. */
  padding:1px;
  background:rgba(255,255,255,0.16);
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor; mask-composite:exclude;
}

/* À haute densité, un demi-pixel s'affiche vraiment : le trait s'affine sans
   se rompre. En dessous, 1 px — un demi tomberait entre deux rangées.

   Placé APRÈS la règle de base : à spécificité égale, c'est le dernier écrit
   qui l'emporte. Posé avant, il ne servait à rien. */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi){
  .topbar-card::after{ padding:0.5px; }
}


/* ═══════════════════════════════════════════════════════════════════════
   LE HAUT DE PAGE — les deux blocs collés, centrés ensemble

   Le tiroir de l'entreprise était sorti du flux pour ne pas décaler la carte.
   Résultat : les deux flottaient séparément, l'un à gauche, l'autre au milieu.

   Ils reviennent tous les deux dans la ligne, séparés de 8 px, et c'est le
   COUPLE qui se centre. Deux objets de même matière posés côte à côte se
   lisent comme un seul ensemble.
   ═══════════════════════════════════════════════════════════════════════ */
.topbar-row > .tiroir-ent{
  /* Retour dans le flux : c'est ce qui permet au couple de se centrer. */
  position:relative;left:auto;top:auto;transform:none;
  flex:0 0 auto;
}
.topbar-row{
  display:flex;align-items:center;justify-content:center;
  /* 8 px : assez pour qu'on distingue deux surfaces, trop peu pour qu'on les
     lise comme deux objets séparés. */
  gap:8px;
}


/* ═══════════════════════════════════════════════════════════════════════
   LE TIROIR DE L'ENTREPRISE — la matière de la barre

   La carte du logo avait déjà été alignée ; le tiroir, non. Il gardait son
   verre d'origine — blanc à 10 %, flou de 24 px, bordure à 18 % — pendant
   que sa voisine et la barre du bas partagent le verre `liquid-glass`.

   Trois surfaces dans un même écran, deux matières : l'œil le sent avant
   de savoir pourquoi.

   Rien n'est touché côté barre : on reprend seulement ses variables.
   ═══════════════════════════════════════════════════════════════════════ */
.tiroir-liste{
  /* Ni fond ni bordure propres : tout vient des pseudo-éléments, comme dans
     `.glassDiv`. Une bordure par-dessus le creux ferait un double contour. */
  background:none;
  border:none;
  isolation:isolate;
  box-shadow:0 4px var(--outer-shadow-blur, 17px) rgba(0,0,0,.18);
}
/* La teinte et le creux : c'est l'ombre interne en négatif qui donne son
   épaisseur au verre. Sans elle, on obtient une vitre plate. */
.tiroir-liste::before{
  content:'';position:absolute;inset:0;z-index:1;
  border-radius:inherit;pointer-events:none;
  box-shadow:inset 0 0 var(--shadow-blur, 17px) var(--shadow-spread, -8px)
             var(--shadow-color, #000);
  background-color:rgba(var(--tint-color, 255,255,255), var(--tint-opacity, .06));
}
/* La réfraction : le même filtre SVG que la barre. Il déforme ce qui passe
   dessous au lieu de simplement le flouter. */
.tiroir-liste::after{
  content:'';position:absolute;inset:0;z-index:-1;
  border-radius:inherit;
  backdrop-filter:var(--verre-bar);
  -webkit-backdrop-filter:var(--verre-bar);
}
/* Le contenu passe au-dessus de la teinte. */
.tiroir-liste > *{position:relative;z-index:2}


/* ═══════════════════════════════════════════════════════════════════════════
   LE MOT D'OUVERTURE DE LA PAGE ÉQUIPE

   Il ouvre sa page comme la carte du temps ouvre l'analyse : même bord allumé
   aux deux angles, même fond. Les trois pages complètes se ressemblent, et
   celle-ci ne devait pas rester la seule à porter une simple carte grise.
   ═══════════════════════════════════════════════════════════════════════════ */
/* Le même noir profond que la carte d'ouverture : ces deux-là portent le bord
   allumé, elles doivent avoir le même fond. Sans quoi l'une paraîtrait creusée
   et l'autre posée. */
.an-intro-cadre{
  position:relative; overflow:hidden;
  border:none; border-radius:22px; padding:16px 18px 17px;
  background:linear-gradient(150deg, #17171B 0%, #101014 40%, #0A0A0D 75%, #060608 100%);
  box-shadow:0 14px 34px rgba(0,0,0,0.42), 0 0 30px -14px rgba(255,122,24,0.26);
}
.an-intro-cadre .t, .an-intro-cadre .s{ position:relative; z-index:2; }

/* Les titres de section des trois pages : mêmes petites capitales, même gris. */
#p-an-equipe .fm-titre, #p-an-categories .fm-titre, #p-an-temps .fm-titre{
  margin-top:26px;
}


/* La carte « Écrivez-nous » ouvre une conversation : elle reçoit le même bord
   allumé que les cartes qui ouvrent une page. Son avatar et son texte passent
   au-dessus de la lueur. */
.contact-carte.an-intro-cadre{ padding:16px 18px; }
.contact-carte.an-intro-cadre .accueil-texte,
.contact-carte.an-intro-cadre .accueil-av{ position:relative; z-index:2; }


/* ═══════════════════════════════════════════════════════════════════════════
   LES SOUS-PAGES DES RÉGLAGES

   Sept pages qui se ressemblent : un titre, une carte, un geste. Elles avaient
   chacune leur rayon, leur remplissage et leur champ. Elles partagent
   maintenant les mêmes, ceux du reste de l'app.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Le rayon des cartes : 20, comme les dossiers, les blocs d'analyse et les
   groupes de réglages. */
#p-reg-compte .card, #p-reg-code .card, #p-reg-etabs .card{ border-radius:20px; }

/* Les champs de saisie. Le liseré s'éclaire en ambre à la frappe : c'est le
   seul moment où l'app doit dire « c'est ici que vous écrivez ». */
#p-reg-compte .f input, .poste-saisie input, #p-reg-etabs input{
  border-radius:14px;
  transition:border-color 0.18s, background 0.18s;
}
#p-reg-compte .f input:focus, .poste-saisie input:focus, #p-reg-etabs input:focus{
  border-color:rgba(255,173,51,0.55);
  background:rgba(255,173,51,0.05);
  outline:none;
}

/* Le mot d'introduction des sous-pages reste une carte simple : elles
   expliquent, elles n'ouvrent rien. Le bord allumé est réservé aux cartes qui
   mènent quelque part. */
#p-reg-postes .an-intro, #p-reg-etabs .an-intro{ border-radius:20px; }

/* Le code d'invitation : les chiffres portent la matière de la marque. C'est
   la seule chose à lire sur cette page, et on la recopie à la main. */
#settings-code{
  background:linear-gradient(135deg,#FF6A00 0%,#FF9A1F 55%,#FFAD33 100%);
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent;
}

/* Les langues : même rayon, et la langue choisie s'entoure d'ambre au lieu de
   blanc. */
.langue-choix{ border-radius:14px; }
.langue-choix.actif{
  border-color:rgba(255,173,51,0.45);
  background:rgba(255,173,51,0.07);
}


/* ═══════════════════════════════════════════════════════════════════════════
   LA CARTE DE L'ACCUEIL

   Même matière et même bord que celle des Procédures, composition inverse :
   le dessin d'abord, le texte ensuite. Les deux cartes ont la même peau, pas
   la même forme — c'est ce qui empêche les deux pages de se confondre.
   ═══════════════════════════════════════════════════════════════════════════ */
.hero-ia{ padding:12px 0 16px; }
.hero-ia .hero-txt{ padding:0 20px; }
.hero-ia h2{ font-size:19px; letter-spacing:-0.045em; margin-bottom:6px; }
/* Plus de bouton dessous : la phrase n'a plus rien à espacer. */
.hero-ia p{ font-size:13px; margin-bottom:0; }
.hero-ia .hero-cta{ height:44px; font-size:14px; }

/* 74 % de la largeur, centrée. À 100 % la carte montait à 430 px et mangeait
   la moitié de l'écran ; ici elle en fait 383 et le reste de la page tient
   encore. L'image respire au lieu de remplir.

   `width` et `height` sont déclarés dans le balisage : sans eux, la page se
   décale au moment où l'image arrive, et le titre saute sous les yeux. */
/* 56 %, la valeur d'origine. L'image ne remplit plus la carte : elle
   l'illustre. Une illustration au trait supporte mal d'être trop grande — le
   vide autour d'elle fait partie du dessin.

   Les marges lui donnent de l'air. Elles sont ASYMÉTRIQUES — 6 px en haut,
   18 en bas — parce que la carte porte déjà 12 px de rembourrage au-dessus :
   sans cette compensation, l'espace du haut faisait 26 px contre 16 en bas, et
   l'image paraissait poussée vers le titre. */
.hero-img{
  display:block; width:62%; height:auto;
  margin:8px auto 18px;
  pointer-events:none; user-select:none;
}

@media (max-width: 360px){
  .hero-ia h2{ font-size:18.5px; }
  .hero-img{ width:72%; }
}




/* ═══════════════════════════════════════════════════════════════════════════
   LE BOUTON DE CRÉATION, EN GOUTTE

   BLOC ENTIER, RÉÉCRIT D'UN SEUL TENANT. Il avait été retouché sept fois par
   petits bouts, et chaque retouche déplaçait un réglage sans voir les autres :
   un cou qui démarrait à 22 px de haut — donc qui APPARAISSAIT d'un coup —
   pendant que le bouton était encore caché derrière la barre.

   Tout est ici, dans l'ordre où ça se lit. Ne pas modifier une valeur sans
   relire les trois autres qui en dépendent.

   Trois plans : la MATIÈRE sous la barre, la BARRE, le BOUTON net au-dessus.
   C'est cet empilement qui fait la traversée — aucun masque.
   ═══════════════════════════════════════════════════════════════════════════ */
:root{
  --plus-bas:max(23px, calc(env(safe-area-inset-bottom, 0px) + 12px));
  --plus-larg:86px;
  --plus-cx:50%;
  --plus-h:46px;
  /* Repos : entièrement sous l'arête, donc hors du cadre. `100%` vaut la
     hauteur du bouton — il est exactement caché quelle qu'elle soit. */
  --plus-repos:100%;
  --plus-monte:-6px;
  /* UNE SEULE COURBE, UNE SEULE DURÉE, pour l'aller comme pour le retour.
     C'est ce qui garantit qu'ils se répondent. */
  /* ═══ LA CHUTE, DANS LES DEUX SENS ═══

     C'est la courbe de la disparition d'origine, celle qui avait été validée :
     260 ms, avec une amorce en sens inverse — le premier point de contrôle est
     NÉGATIF. Le bouton recule d'abord de quelques pixels, puis part. C'est
     cette anticipation qui donne le poids ; sans elle on n'a qu'un glissement.

     L'ENTRÉE PORTE LA COURBE INVERSE, ce qui est la même chose jouée à
     l'envers : on retourne une courbe de Bézier en échangeant ses points et en
     les soustrayant à un. (0,5 · −0,2 · 0,9 · 0,6) devient donc
     (0,1 · 0,4 · 0,5 · 1,2).

     Recopier la courbe telle quelle serait une faute : l'amorce pousserait le
     bouton VERS LE BAS, hors du cadre où il est invisible — mesuré, 188 ms sans
     que rien ne bouge. Renversée, l'amorce devient un dépassement à l'arrivée,
     et le bouton part sur-le-champ. Même mouvement, sens opposé. */
  --plus-duree:0.26s;
  --plus-courbe:cubic-bezier(0.5, -0.2, 0.9, 0.6);
  /* CALME, PAS SEC.

     La courbe précédente — (0,1 · 0,4 · 0,5 · 1,2) — était l'inverse exacte de
     la sortie. Mathématiquement juste, mais l'inverse d'une amorce est un
     DÉPART SEC : le bouton s'élançait à pleine vitesse dès la première image,
     puis claquait sur un dépassement. D'où l'impression de brusquerie.

     Celle-ci part de rien et finit sur rien — lente aux deux bouts, ample au
     milieu, sans dépassement. C'est la même sensation posée que la sortie,
     obtenue autrement : là c'est l'amorce qui calme, ici c'est le démarrage
     progressif. */
  --plus-courbe-entree:cubic-bezier(0.5, 0.02, 0.25, 1);

  /* ═══ CE QUI RENDAIT L'ENTRÉE BRUSQUE N'ÉTAIT PAS LA COURBE ═══

     Le bouton partait à 62 % de sa taille : soixante pour cent de croissance en
     un tiers de seconde. Quelle que soit la courbe, une telle variation d'aire
     se lit comme un surgissement — l'œil est bien plus sensible au changement
     de TAILLE qu'au déplacement.

     Il part maintenant de 88 %. Le mouvement reste, la brusquerie s'en va.
     C'est aussi pour cette raison que la durée monte à 420 ms : le geste est
     désormais assez discret pour qu'on puisse le prendre son temps. */
  /* L'ENTRÉE EST PLUS LONGUE QUE LA SORTIE : 340 ms contre 260.

     Ce n'est pas une inattention. On regarde une chose qui arrive, on ne
     regarde pas une chose qui s'en va : un objet qui paraît a besoin qu'on le
     voie venir, le même objet qui sort n'a plus rien à dire.

     À ne pas confondre avec le temps PERÇU. Entre le doigt et le premier
     mouvement, l'app change de page, redessine la liste et repose la barre —
     de soixante à cent cinquante millisecondes selon la charge. Du clic au
     bouton posé, on est donc autour de 420, pas de 340. Raccourcir cette
     valeur ne raccourcit que sa part. */
  --plus-duree-entree:0.42s;
}

/* LA MATIÈRE EST COUPÉE À L'ARÊTE, COMME LE BOUTON.

   Elle s'étendait jusqu'au bas de l'écran, sous la barre. Or la barre est du
   VERRE : elle laisse passer la lumière. On voyait donc une lueur orange
   derrière la navbar pendant toute l'animation — une flaque qui n'avait rien
   à faire là.

   Le cadre s'arrête à l'arête haute. La matière n'existe plus qu'au-dessus,
   elle sort du bord et rien ne transparaît. */
.liquide{
  position:fixed; left:0; right:0; top:0;
  bottom:calc(var(--plus-bas) + var(--bar-h));
  overflow:hidden; z-index:9;
  pointer-events:none; filter:url(#fusion);
  visibility:hidden;
}
body.plus-vu .liquide, body.plus-part .liquide{ visibility:visible; }

/* Le socle prend racine SUR l'arête et pousse vers le haut. Ses coordonnées
   sont celles du cadre, dont le bas est désormais cette arête. */
.socle{
  position:absolute; left:var(--plus-cx); transform:translateX(-50%);
  bottom:0;
  width:calc(var(--plus-larg) * 0.5); height:0;
  border-radius:20px 20px 0 0; background:#F58A15;
}

/* LE COU DE LA VERSION VALIDÉE, RENDU TEL QUEL.

   Il naît étroit — douze pixels —, monte à 44, puis s'écrase en s'élargissant
   à 85 % de la largeur du bouton avant de disparaître. Cette dernière image est
   l'essentiel : c'est l'éclaboussure, la matière qui s'étale au contact.

   Ni le fil de six pixels qui casse, ni l'enflure ronde : entre les deux. */
/* PLUS D'ÉTALEMENT, ET UNE SEULE SUITE POUR LES DEUX SENS.

   L'avant-dernière image couchait la matière sur 85 % de la largeur du bouton :
   une barre large et plate, seize pixels de haut, qui surgissait au ras de la
   navbar en fin de disparition. Passée au filtre de fusion, elle devenait une
   tache lumineuse apparue d'un coup.

   Cette suite-ci est SYMÉTRIQUE — elle part de rien, monte, revient à rien — et
   ne dépasse jamais 26 px de large. Jouée dans un sens ou dans l'autre, on voit
   la même chose, et rien n'apparaît brusquement. */
@keyframes couGoutte{
  0%  { height:0;    width:16px; }
  45% { height:42px; width:26px; }
  100%{ height:0;    width:16px; }
}
/* ═══ LE COU N'A PAS LE MÊME TEMPO DANS LES DEUX SENS ═══

   À L'ENTRÉE, 60 ms de retard : le bouton doit avoir franchi l'arête avant que
   la matière ne se montre, sinon on voit la goutte avant le rectangle.

   À LA SORTIE, aucun retard et c'est plus court. Le cadre coupe le bouton dès
   qu'il repasse sous l'arête — vers soixante millisecondes — alors que le cou
   culminait à deux cents. On voyait donc la goutte s'agiter SEULE, sans le
   rectangle : les deux sens paraissaient différents alors que la courbe était
   la même.

   Le cou vit maintenant pendant que le bouton est encore là. Ce n'est pas une
   asymétrie de style, c'est la conséquence du découpage. */
/* La suite étant symétrique, les deux sens partagent la même — et `couEntree`,
   qui existait pour éviter l'éclaboussure à l'entrée, n'a plus de raison
   d'être. Une clé de moins à tenir en accord avec sa jumelle. */
/* La matière suit le bouton : même durée que lui, dans chaque sens. Les laisser
   diverger, c'est ce qui donnait l'impression de deux animations distinctes. */
body.plus-vu .socle{
  animation:couGoutte 0.42s cubic-bezier(0.4, 0, 0.3, 1);
}
body.plus-part .socle{
  animation:couGoutte 0.26s cubic-bezier(0.4, 0, 0.3, 1);
}

/* La bulle double le bouton dans la matière. Même cadre, donc même repère :
   l'arête de la barre. */
.bulle{
  position:absolute; left:var(--plus-cx); bottom:0;
  width:var(--plus-larg); height:var(--plus-h);
  border-radius:calc(var(--plus-h) / 2); background:#F58A15;
  transform:translate(-50%, var(--plus-repos)) scale(0.88);
  transition:transform var(--plus-duree) var(--plus-courbe);
}

/* Le cadre s'arrête à l'arête haute et masque ce qui dépasse en dessous : le
   bouton n'existe à l'écran qu'à partir du moment où il émerge. Il couvre tout
   l'écran, donc il ne doit rien intercepter. */
.plus-cadre{
  position:fixed; left:0; right:0; top:0;
  bottom:calc(var(--plus-bas) + var(--bar-h));
  overflow:hidden; z-index:11; pointer-events:none;
}

.plus-flot{
  position:absolute; left:var(--plus-cx); bottom:0;
  width:var(--plus-larg); height:var(--plus-h); border:none;
  border-radius:calc(var(--plus-h) / 2);
  display:grid; place-items:center;
  background:linear-gradient(135deg, #E85D00 0%, #F58A15 62%, #FF9F26 100%);
  color:#2A1400;
  box-shadow:0 6px 16px rgba(0,0,0,0.34), 0 2px 10px rgba(255,122,24,0.16);
  transform:translate(-50%, var(--plus-repos)) scale(0.88);
  opacity:0; pointer-events:none;
  /* L'opacité monte presque d'un coup à l'aller — le rectangle doit être solide
     avant que le cou n'apparaisse — et s'éteint en retard au retour, quand il
     est déjà rentré sous l'arête. */
  transition:transform var(--plus-duree) var(--plus-courbe),
             opacity 0.04s linear 0.20s;
}
.plus-flot svg{ width:21px; height:21px; display:block; }

body.plus-vu .bulle,
body.plus-vu .plus-flot{ transform:translate(-50%, var(--plus-monte)) scale(1); }
body.plus-vu .bulle{ transition:transform var(--plus-duree-entree) var(--plus-courbe-entree); }
body.plus-vu .plus-flot{
  opacity:1; pointer-events:auto;
  transition:transform var(--plus-duree-entree) var(--plus-courbe-entree),
             opacity 0.04s linear;
}
.plus-flot:active{ transform:translate(-50%, var(--plus-monte)) scale(0.94); }

@media (prefers-reduced-motion: reduce){
  .bulle, .plus-flot{ transition:none; }
  .socle{ animation:none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   LES ACTIVITÉS

   Rien de neuf : les lignes empruntent `an-lig`, les blocs `an-bloc`, la page
   la mise en page de « Procédures » vue depuis l'analyse. Seule la pastille
   d'icône est propre aux activités — les événements sont de natures
   différentes, et le dessin les distingue sans qu'on ait à lire.
   ═══════════════════════════════════════════════════════════════════════════ */
.act-lig .act-ic{
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
  width:30px; height:30px; border-radius:10px;
  background:rgba(255,255,255,0.05);
  color:var(--label-2);
}
.act-lig .act-ic svg{ width:16px; height:16px; display:block; }
/* LE MÊME BLANC QUE LES LIGNES DU BLOC AU-DESSUS.

   La phrase était en gris avec le seul nom en blanc — l'idée étant de faire
   ressortir la personne. Mais les lignes des « Dernières procédures créées »,
   juste au-dessus, sont blanches d'un bout à l'autre : deux blocs voisins de
   même construction, l'un lisible et l'autre en retrait, et le second passait
   pour secondaire alors qu'il ne l'est pas.

   Tout est blanc. Le nom garde son gras — à luminosité égale, la graisse
   suffit à le détacher. */
.act-lig .nm{ font-weight:400; color:var(--label-1); }
.act-lig .nm b{ font-weight:700; }

/* Une seule couleur, pour un seul cas : quelqu'un attend d'entrer et ça coûte
   de l'argent. Les autres événements sont des faits, pas des alertes — les
   teinter tous reviendrait à n'en signaler aucun. */
.act-refus{
  background:rgba(255,154,31,0.12) !important;
  color:#FFAD33 !important;
}

#p-activites{ padding-left:32px; padding-right:32px; }
#p-activites .back-btn{ margin-left:-5px; }

/* Le groupement par jour. Sans ces en-têtes, quarante lignes se ressemblent
   toutes et l'œil n'a plus de prise. */
.act-jour{
  font-size:11.5px; font-weight:750; letter-spacing:0.05em; text-transform:uppercase;
  color:var(--label-3); margin:22px 0 2px;
}
#activites-tout > .act-jour:first-of-type{ margin-top:14px; }

/* ═══════════════════════════════════════════════════════════════════════════
   UN SEUL TRAIT DE CONTOUR DANS TOUTE L'APP

   La barre du bas et la carte du logo portent le filet clair : ce sont les deux
   pièces de verre, posées PAR-DESSUS la page, et l'arête dit qu'elles flottent.

   Les cartes, elles, sont dans le flux. Leur donner un contour les découpe
   comme des vignettes ; c'est le fond plus clair et l'ombre qui doivent les
   détacher. Un trait partout ne détache plus rien.
   ═══════════════════════════════════════════════════════════════════════════ */
.an-bloc,
.card,
.cat-cell,
.proc-rich-card,
.reg-groupe,
.reg-identite,
.an-intro{
  border-color:transparent !important;
}


/* ═══════════════════════════════════════════════════════════════════════════
   LA BARRE DU HAUT

   La matière de la barre du bas : même verre, même filet, mêmes variables. Les
   deux pièces flottent au-dessus de la page et doivent se ressembler — c'est
   ce qui dit qu'elles ne font pas partie du contenu.
   ═══════════════════════════════════════════════════════════════════════════ */
/* ═══ LA PISTE DU HAUT ═══
   Deux panneaux, chacun de la largeur visible, calés au centre par le
   navigateur. La carte d'origine à gauche, les établissements à droite. */
.haut-piste{
  display:flex; width:100%; min-width:0;
  overflow-x:auto; overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory;
  scrollbar-width:none; -ms-overflow-style:none;
}
.haut-piste::-webkit-scrollbar{ display:none; }
/* LE VOISIN DÉPASSE.

   84 % au lieu de 100, et la piste rend les 8 % restants en retrait de chaque
   côté : le panneau suivant montre son bord. C'est la seule marque qui ne soit
   pas un SYMBOLE de ce qu'on peut faire, mais la chose elle-même — on voit
   qu'il y a quelque chose, on n'a pas à l'interpréter.

   Elle ne coûte rien en hauteur : les deux points sont retirés, la barre
   retrouve ses 72 px. */
.haut-pan{
  flex:0 0 84%;
  display:flex; justify-content:center;
  scroll-snap-align:center; scroll-snap-stop:always;
}
.haut-piste{ padding-inline:8%; }

.topbar-pilule{
  position:relative; isolation:isolate;
  display:flex; align-items:center; gap:8px;
  padding:7px; border-radius:100px;
  box-shadow:0 4px var(--outer-shadow-blur, 17px) rgba(0,0,0,0.18),
             inset 0 0 0 0.5px var(--filet);
}
.topbar-pilule::before{
  content:''; position:absolute; inset:0; z-index:1; border-radius:inherit;
  background-color:rgba(var(--tint-color), var(--tint-opacity));
  box-shadow:inset 0 0 var(--shadow-blur) var(--shadow-spread) var(--shadow-color);
  pointer-events:none;
}
.topbar-pilule::after{
  content:''; position:absolute; inset:0; z-index:-1; border-radius:inherit;
  -webkit-backdrop-filter:var(--verre-bar); backdrop-filter:var(--verre-bar);
}
.etab-ronds{ display:flex; align-items:center; gap:8px; }

.rond-etab{
  position:relative; z-index:2; flex-shrink:0;
  width:42px; height:42px; border-radius:50%; border:none;
  display:grid; place-items:center; overflow:hidden;
  background:rgba(255,255,255,0.05);
  box-shadow:inset 0 0 0 0.5px rgba(255,255,255,0.10);
  transition:transform 0.16s cubic-bezier(0.34,1.5,0.64,1), box-shadow 0.2s;
}
.rond-etab:active{ transform:scale(0.93); }
.rond-etab img{ width:100%; height:100%; object-fit:cover; display:block; }
.rond-logo{ display:grid; place-items:center; width:24px; height:24px; }
.rond-logo svg{ width:100%; height:100%; display:block; }
.rond-init{
  font-size:14px; font-weight:750; letter-spacing:0.02em; color:var(--label-3);
}

/* L'établissement ouvert porte la marque ; les autres restent en retrait. Une
   pastille par entreprise, toutes identiques, ne dirait pas où l'on est. */
.rond-etab.actif{
  background:linear-gradient(165deg, rgba(255,173,51,0.14), rgba(255,173,51,0.03));
  box-shadow:inset 0 0 0 0.5px rgba(255,173,51,0.30);
}
.rond-etab.actif .rond-init{
  background:linear-gradient(135deg,#FF6A00,#FF9A1F 60%,#FFAD33);
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent;
}

/* Le « + » reste neutre : ajouter n'est pas le geste courant. */
.rond-plus{ color:var(--label-2); }
.rond-plus svg{ width:18px; height:18px; display:block; }

/* ═══ L'APPROCHE, À CHAQUE CHANGEMENT DE PAGE ═══
   280 ms depuis 90 %, sans déplacement : la pilule ne vient de nulle part,
   elle est déjà là. Même profondeur que le fondu des pages, et les deux se
   terminent ensemble. */
/* ═══ UN FONDU LÉGER, JAMAIS UNE ABSENCE ═══

   L'approche repartait de zéro à chaque page : la barre disparaissait puis
   revenait, et ce clignotement se remarque sur un objet permanent.

   Elle descend maintenant à 25 %, pas à 0, et sans changer de taille. On voit
   qu'il s'est passé quelque chose ; on ne la voit jamais absente. */
.haut-piste.approche{ animation:pilFondu 0.20s ease-out; }
@keyframes pilFondu{
  from{ opacity:0.25; }
  to{ opacity:1; }
}
@media (prefers-reduced-motion: reduce){
  .haut-piste.approche{ animation:none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   LE TITRE DE LA PAGE PROCÉDURES

   Même graisse et même taille que « Paramètres » ou « Activités » : les pages
   qui portent un titre le portent de la même façon, sinon chacune paraît venir
   d'une app différente.
   ═══════════════════════════════════════════════════════════════════════════ */
/* LA MÊME ÉCRITURE QUE « PROCÉDO / ESPACE GESTION ».

   La carte du haut pose le modèle : un nom en 700, une seconde ligne plus
   légère en 500, dans le gris de second plan. Les titres de page reprennent
   exactement ces graisses et ces couleurs — seule la taille change, parce
   qu'un titre de page n'est pas une étiquette de barre.

   Le titre était en 800 et son compte en 600 : plus lourds tous les deux que
   le modèle, et la parenté ne se lisait pas. */
.page-tete{ margin:0 0 18px; }
/* 24 px, comme `h1.pagehead`. Ces trois titres — « Procédures », « Analyse »
   et le salut de l'Équipe — vivent dans `.page-tete` plutôt que de porter la
   classe `pagehead`, et ils échappaient donc à la règle centrale. */
.page-tete h1{
  font-size:24px; font-weight:700; letter-spacing:-0.03em; line-height:1.1;
}
/* L'ÉCART SOUS LE TITRE, POSÉ AU MÊME ENDROIT POUR LES DEUX PAGES.

   Sur Analyse, le compte est enveloppé dans `.tete-bas` — qui porte la marge.
   Sur Procédures, le compte est un `p` nu : il n'en avait aucune, et le chiffre
   collait au titre. Les deux valeurs vivaient à deux endroits différents, donc
   elles divergeaient.

   La marge est maintenant portée par CE QUI SUIT le titre, quel qu'il soit. */
.page-tete h1 + *{ margin-top:8px; }
.page-tete p{
  font-size:13px; color:var(--label-2); font-weight:500;
}
/* Le compte et son bouton d'explication sur la même ligne. Le rond de 26 px
   porte 3,5 px de vide autour de son dessin : on les retranche pour que le
   trait s'aligne sur la hauteur du texte, pas sur sa boîte. */
.page-tete .tete-bas{
  display:flex; align-items:center; gap:7px;
}
/* Le rond fait 26 px, le texte 17 : sans cela il étire la ligne et pousse le
   compte quatre pixels plus bas que sur les autres pages. Les marges négatives
   le retirent du calcul de hauteur — il reste visible, il ne compte plus. */
.page-tete .tete-bas .an-aide{
  position:static; margin:-5px 0 -5px -1px;
}


/* La pastille « non lu » a été retirée : sur une carte qui ne montre que trois
   procédures, presque toutes en portaient une — un signal qui s'allume partout
   ne distingue plus rien. Le compte à lire est dit en haut de la page. */


/* ═══════════════════════════════════════════════════════════════════════════
   COCHER UNE ÉTAPE : LE REPLI ET LE RAPPEL
   ═══════════════════════════════════════════════════════════════════════════ */

/* Le repli en deux temps : l'étape s'éteint sur place, PUIS se rétracte. Les
   deux à la fois donneraient un escamotage ; l'un après l'autre laisse le
   temps de voir ce qui part.

   PAS D'`overflow:hidden` ICI. La case numérotée est à −45 px de la carte et la
   barre de lecture à −55 : toutes deux vivent DEHORS. Découper la carte les
   faisait disparaître — les chiffres cliquables comme le repère de position.
   Le découpage n'est posé que pendant le repli, quand l'étape s'en va de toute
   façon. */
.detail-step{
  /* `transform` MANQUAIT dans cette liste. L'étape portait bien un
     `translateY(-26px)` au départ — mais sans transition pour l'accompagner,
     elle sautait de sa place à 26 px plus haut entre deux images. On ne voyait
     donc qu'un fondu, jamais la montée.

     0,26 s : un peu plus long que le fondu de 0,22, pour que le mouvement se
     poursuive une fraction après que l'étape a disparu. C'est ce décalage qui
     donne l'impression qu'elle s'échappe plutôt qu'elle s'éteint. */
  transition:opacity 0.22s ease,
             transform 0.26s cubic-bezier(0.32,0.72,0,1),
             max-height 0.30s cubic-bezier(0.32,0.72,0,1),
             margin-bottom 0.30s cubic-bezier(0.32,0.72,0,1),
             padding 0.30s cubic-bezier(0.32,0.72,0,1),
             border-color 0.3s ease, background 0.3s ease;
}
.detail-step.et-part{ opacity:0; overflow:hidden; }
/* LE REPLI DOIT ÊTRE AUSSI SPÉCIFIQUE QUE LA RÈGLE DU FIL.

   Dans le fil, l'étape porte `padding:0 0 28px !important` — et ce sélecteur
   commence par un IDENTIFIANT. Mon `.detail-step.et-repli !important` ne
   pouvait pas l'emporter : à `!important` égal, c'est la spécificité qui
   tranche, et un identifiant bat deux classes.

   Résultat : vingt-huit pixels de rembourrage survivaient au repli et
   laissaient une bande vide là où l'étape venait de se ranger. Très visible
   sur les étapes à photo, dont on voyait le socle rester en place.

   Les sélecteurs reprennent donc les mêmes identifiants. */
.detail-step.et-repli,
#detail-steps.etapes-fil .detail-step.et-repli,
#analyse-steps-list.etapes-fil .detail-step.et-repli{
  max-height:0 !important; overflow:hidden !important;
  margin-top:0 !important; margin-bottom:0 !important;
  padding-top:0 !important; padding-bottom:0 !important;
  border-width:0 !important;
}

/* Le rappel. Il s'ouvre vers le bas quand la première étape est cochée, et se
   referme quand on décoche tout. */
/* L'ÉCART SOUS LE RAPPEL.

   Dix pixels seulement, et les étapes du fil n'ont aucune marge haute : la
   première se collait donc au rappel, comme si elle en faisait partie. Or ce
   sont deux choses distinctes — ce qui est rangé, et ce qui reste à faire.

   Vingt-quatre pixels : assez pour qu'on lise deux blocs, pas assez pour qu'on
   croie à un manque.

   L'écart est porté par le CONTENEUR, et le rappel n'a plus de marge propre.
   Les deux ensemble ne s'additionnaient pas — des marges verticales voisines
   FUSIONNENT, et seule la plus grande comptait : 16 px au lieu des 26 que je
   croyais poser. */
#etapes-rappel:not(:empty){ margin-bottom:24px; }

.fait-rappel{
  display:flex; align-items:center; gap:10px; width:100%; text-align:left;
  padding:11px 14px; border:none;
  border-radius:14px; background:rgba(255,255,255,0.045);
  color:var(--label-2); font-family:inherit; font-size:12.5px; font-weight:600;
}
.fait-rappel .p{
  width:22px; height:22px; border-radius:50%; flex-shrink:0;
  display:grid; place-items:center;
  background:rgba(255,173,51,0.14);
}
.fait-rappel .p svg{ width:15px; height:15px; display:block; }
.fait-rappel b{ color:var(--label-1); font-weight:700; }
/* La flèche pivote : c'est elle qui dit si la pile est ouverte. */
.fait-rappel .fl{
  margin-left:auto; color:var(--label-3); font-size:17px; line-height:1;
  transition:transform 0.3s cubic-bezier(0.32,0.72,0,1);
}
.fait-rappel.ouvert .fl{ transform:rotate(90deg); }
.fait-rappel:active{ opacity:0.7; }


/* ═══════════════════════════════════════════════════════════════════════════
   LA COCHE S'ÉCRIT, L'ÉTAPE SE RANGE (variante A)

   Le chiffre et la coche vivent SUPERPOSÉS dans le même bouton. C'est ce qui
   permet de les échanger : un remplacement de contenu ne peut pas s'animer.

   Les sélecteurs partent de `#detail-steps`. Sans cet identifiant, les règles
   du fil — qui en portent un — l'emportaient, et le chiffre restait visible
   sous la coche : on voyait les deux à la fois, en olive.
   ═══════════════════════════════════════════════════════════════════════════ */
#detail-steps .et-coche{ display:grid; place-items:center; }
#detail-steps .et-coche .num,
#detail-steps .et-coche .ok{
  grid-area:1 / 1; display:grid; place-items:center;
  transition:opacity 0.2s, transform 0.34s cubic-bezier(0.34,1.5,0.6,1);
}
#detail-steps .et-coche .ok{ opacity:0; transform:scale(0.82); }

/* Le trait de la coche se DESSINE : sa longueur sert de pointillé, qu'on fait
   défiler jusqu'à zéro. 320 ms — le temps de voir l'action, pas seulement son
   résultat. Le rond, lui, arrive avec l'opacité : c'est le geste d'écriture
   qu'on montre, pas l'apparition du jeton. */
#detail-steps .et-coche .ok svg path{
  stroke-dasharray:16; stroke-dashoffset:16;
  transition:stroke-dashoffset 0.32s cubic-bezier(0.5,0,0.2,1) 0.06s;
}
#detail-steps .detail-step.faite .et-coche .num{ opacity:0; transform:scale(0.6); }
#detail-steps .detail-step.faite .et-coche .ok{ opacity:1; transform:scale(1); }
#detail-steps .detail-step.faite .et-coche .ok svg path{ stroke-dashoffset:0; }

/* L'étape monte vers le rappel en s'effaçant : c'est là qu'elle se range. */
#detail-steps .detail-step.et-part{ transform:translateY(-26px) scale(0.94); }


/* ═══════════════════════════════════════════════════════════════════════════
   RIEN, PUIS TOUT

   Pendant le chargement l'écran ne montre que ses halos : ni barre du haut, ni
   barre du bas, ni contenu. Puis tout paraît ENSEMBLE.

   C'est un choix contre l'affichage progressif. Montrer la charpente d'abord,
   puis la remplir, donnait trois états successifs — une page à moitié
   construite, des cadres vides, enfin le contenu. Trois choses à regarder pour
   une seule arrivée.

   `opacity` et non `display` : les éléments gardent leur place, donc leurs
   dimensions sont mesurables. La barre du bas en a besoin — son calcul de
   géométrie lit sa largeur, et sur un élément masqué elle vaut zéro. C'est
   exactement le défaut qui empilait les onglets à gauche.

   Les deux espaces partagent cette règle : rien ne les distingue au démarrage.
   ═══════════════════════════════════════════════════════════════════════════ */
#gestion-app, #equipe-app, #bar{
  transition:opacity 0.42s cubic-bezier(0.32, 0.72, 0, 1);
}
body.chargement #gestion-app,
body.chargement #equipe-app,
body.chargement #bar{
  /* `!important` ET `animation:none`. Les deux espaces portent une animation
     d'entrée propre (`app-shell-in`), et une animation l'emporte TOUJOURS sur
     une déclaration ordinaire : le voile ne tenait que sur la barre, l'app
     passait au travers et se montrait pendant le chargement.

     On coupe donc l'animation pendant l'attente. C'est le voile qui fait
     l'entrée, une seule fois, pour tout le monde en même temps. */
  opacity:0 !important;
  animation:none !important;
  pointer-events:none;
}
@media (prefers-reduced-motion: reduce){
  #gestion-app, #equipe-app, #bar{ transition:none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   L'INVITE SOUS « ÉCRIVEZ-NOUS »

   La carte entière est cliquable, mais rien ne le disait : pas de bouton, pas
   de chevron, juste un titre et un paragraphe — donc rien qui ressemble à une
   commande. On peut la lire dix fois sans penser à la toucher.

   Une main qui appuie et trois mots règlent ça. L'ambre parce que c'est le
   seul geste de la carte : ailleurs sur cette page, l'ambre marque déjà ce
   qu'on peut faire.
   ═══════════════════════════════════════════════════════════════════════════ */
.contact-invite{
  display:inline-flex; align-items:center; gap:7px;
  margin-top:12px;
  font-size:12.5px; font-weight:650; letter-spacing:-0.01em;
  color:#FFAD33;
}
.contact-invite svg{ width:17px; height:17px; flex-shrink:0; display:block; }

/* La main appuie, doucement et sans fin. Deux pixels : assez pour attirer
   l'œil de biais, trop peu pour qu'on la regarde. */
.contact-invite svg{ animation:mainAppuie 2.6s ease-in-out infinite; }
@keyframes mainAppuie{
  0%, 62%, 100% { transform:translateY(0); }
  72%           { transform:translateY(2px); }
  82%           { transform:translateY(0); }
}
@media (prefers-reduced-motion: reduce){
  .contact-invite svg{ animation:none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   LES ÉTABLISSEMENTS, DANS LA CARTE DES RÉGLAGES

   Une rangée de cercles et un « + » au bout, puis la phrase qui explique ce
   que coûte un second établissement. Tout tient dans une carte : la page
   séparée d'avant ne portait que trois lignes.
   ═══════════════════════════════════════════════════════════════════════════ */
.etab-carte{
  background:var(--bg-card); border-radius:18px;
  padding:15px 16px 14px; margin-bottom:14px;
}
.etab-rang{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }

.etab-rond{
  position:relative; flex-shrink:0;
  width:46px; height:46px; border-radius:50%; border:none; overflow:hidden;
  display:grid; place-items:center;
  background:rgba(255,255,255,0.05);
  box-shadow:inset 0 0 0 0.5px rgba(255,255,255,0.10);
  font-family:inherit; font-size:15px; font-weight:750; letter-spacing:0.02em;
  color:var(--label-3);
  transition:transform 0.16s cubic-bezier(0.34,1.5,0.64,1), box-shadow 0.2s;
}
.etab-rond img{ width:100%; height:100%; object-fit:cover; display:block; }
.etab-rond:active{ transform:scale(0.93); }

/* Celui où l'on est porte la marque ; les autres restent en retrait. Sans
   cela, rien ne dirait dans quel établissement on travaille. */
.etab-rond.actif{
  background:linear-gradient(165deg, rgba(255,173,51,0.14), rgba(255,173,51,0.03));
}
/* L'ANNEAU PAR-DESSUS L'IMAGE.

   Il était posé en ombre interne : un logo en `object-fit:cover` la recouvrait
   entièrement, et le cercle actif ne se distinguait plus des autres dès qu'il
   portait une image. Un pseudo-élément passe au-dessus. */
.etab-rond.actif::after{
  content:''; position:absolute; inset:0; border-radius:50%;
  box-shadow:inset 0 0 0 2px rgba(255,173,51,0.85);
  pointer-events:none;
}
.etab-rond.actif span{
  background:linear-gradient(135deg,#FF6A00,#FF9A1F 60%,#FFAD33);
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent;
}

/* Le « + » en pointillé : il annonce une place vide, pas un objet existant.
   Plein, il aurait le poids d'un établissement de plus. */
.etab-plus{
  flex-shrink:0; width:46px; height:46px; border-radius:50%;
  display:grid; place-items:center;
  background:none; border:1.5px dashed rgba(255,255,255,0.18);
  color:var(--label-2);
  transition:transform 0.16s cubic-bezier(0.34,1.5,0.64,1),
             border-color 0.2s, color 0.2s;
}
.etab-plus svg{ width:19px; height:19px; display:block; }
.etab-plus:active{ transform:scale(0.93); }
.etab-plus:hover{ border-color:rgba(255,173,51,0.45); color:#FFAD33; }

.etab-note{
  margin-top:13px; font-size:12px; line-height:1.5; color:var(--label-3);
}
.etab-note b{ color:var(--label-2); font-weight:700; }


/* ═══════════════════════════════════════════════════════════════════════════
   CHANGER D'ENTREPRISE

   Le contenu s'écarte, puis le nouveau arrive en cascade — cette seconde
   moitié existait déjà (`contenu-entre`), il manquait la première.

   L'écran RECULE en s'effaçant : trois pour cent, pas davantage. C'est ce que
   fait iOS quand une vue passe au second plan, et c'est ce mouvement — pas le
   fondu — qui dit qu'on quitte quelque chose plutôt qu'on l'efface.

   Les deux barres ne bougent pas. Elles ne changent pas d'entreprise : elles
   encadrent celle qu'on regarde.
   ═══════════════════════════════════════════════════════════════════════════ */
.screen.bascule-part{
  /* ═══ ON VA À CÔTÉ, PAS PLUS LOIN ═══

     Le contenu reculait à 97 % — presque le geste d'arrivée d'une page, en
     plus discret. Rien ne disait qu'on changeait d'ENTREPRISE plutôt que de
     page.

     Il sort maintenant par la GAUCHE. Aucun autre écran de l'app ne se déplace
     horizontalement : le mouvement latéral est donc réservé à ça, et se
     reconnaît sans qu'on ait à l'apprendre. Vingt-six pixels — assez pour se
     voir, trop peu pour donner le mal de mer. */
  opacity:0;
  transform:translateX(-26px);
  transition:opacity 0.18s ease-out,
             transform 0.2s cubic-bezier(0.32, 0.72, 0, 1);
  pointer-events:none;
}

/* Et le nouveau contenu entre par la DROITE. Sans ce second temps, l'ancien
   partait de côté et le nouveau apparaissait sur place — un demi-geste. */
.bascule-en-cours .screen.active:not(.bascule-part){
  animation:basculeEntre 0.3s cubic-bezier(0.32, 0.72, 0, 1) both;
}
@keyframes basculeEntre{
  from{ opacity:0; transform:translateX(26px); }
  to{ opacity:1; transform:none; }
}
/* ═══ LA TRANSITION NE VAUT QUE POUR LA BASCULE D'ÉTABLISSEMENT ═══

   Elle était posée sur `.screen` — donc sur TOUS les écrans, en permanence.
   Résultat : à chaque changement de page, deux mouvements se superposaient sur
   les mêmes propriétés — l'animation d'arrivée de 0,34 s, et cette transition
   de 0,18 s. C'est ce qu'on sentait comme « une animation en plus ».

   Elle n'existe que pour une chose : ramener l'écran à sa taille après un
   changement d'établissement, quand `bascule-part` est retirée. On la limite
   donc à ce moment-là, en la posant sur le PARENT — la classe est présente
   pendant la bascule et absente le reste du temps. */
.bascule-en-cours .screen{
  transition:opacity 0.18s ease-out, transform 0.18s cubic-bezier(0.32,0.72,0,1);
}

@media (prefers-reduced-motion: reduce){
  .screen.bascule-part{ transition:none; }
  .bascule-en-cours .screen{ transition:none; }
  .bascule-en-cours .screen.active:not(.bascule-part){ animation:none; }
}


/* La carte d'ouverture SANS son dessin. « Créer des procédures avec l'IA »
   porte une image de 700 px ; « Quel est votre rôle ici ? » n'en a pas — et
   sans elle, le rembourrage du haut, prévu pour dégager le dessin, laissait
   un vide au-dessus du titre. */
.hero.hero-sans-image{ padding:20px; }
.hero.hero-sans-image .hero-txt{ margin-top:0; }

/* ═══════════════════════════════════════════════════════════════════════════
   LA CARTE DE BUREAU

   Dans l'angle haut droit, là où la colonne de 460 px laisse du vide. Elle ne
   couvre rien et n'attend rien : l'app reste entière et utilisable derrière.
   ═══════════════════════════════════════════════════════════════════════════ */
.pc-coin{
  position:fixed; z-index:60;
  top:26px; right:26px; width:196px;
  padding:18px 18px 16px;
  border-radius:22px; text-align:center;
  background:linear-gradient(150deg,#1E1E24 0%,#141418 50%,#0C0C10 100%);
  box-shadow:0 16px 44px rgba(0,0,0,0.5),
             inset 0 0 0 0.5px rgba(255,255,255,0.10);
  /* Elle arrive après l'app : posée en même temps, elle se disputerait
     l'attention avec la page qui se dévoile. */
  animation:pcCoinArrive 0.5s cubic-bezier(0.32,0.72,0,1) 0.6s both;
}
.pc-coin[hidden]{ display:none; }
@keyframes pcCoinArrive{
    0%  { opacity:0; transform:scale(0.975); }
    30% { opacity:1; }
    100%{ opacity:1; transform:none; }
}

.pc-tete{
  display:flex; align-items:center; gap:9px;
  text-align:left; margin-bottom:14px;
}
/* Le cinquième logo — la carte de bureau. 15 sur 21, au rapport 0,706 du
   dessin : la règle visait un SVG de proportions différentes. */
.pc-logo{ width:15px; height:21px; flex-shrink:0; display:block; object-fit:contain; }
.pc-tete b{
  font-size:12.5px; font-weight:700; line-height:1.3;
  letter-spacing:-0.01em; color:var(--label-1);
}

/* Le code sur fond CLAIR : les appareils photo lisent mal un code clair sur
   fond sombre. C'est la seule pièce blanche de l'app, et elle l'est pour une
   raison. */
.pc-qr{
  width:160px; height:160px; margin:0 auto 11px;
  display:grid; place-items:center;
  border-radius:14px; background:#F5F5F7; padding:14px;
}
.pc-qr canvas{ display:block; width:100%; height:100%; }

.pc-sous{
  display:block; font-size:11px; font-weight:600; line-height:1.4;
  color:var(--label-3);
}

/* Sous 900 px elle n'a rien à dire : on EST sur le bon appareil. */
@media (max-width: 899px){ .pc-coin{ display:none !important; } }
@media (prefers-reduced-motion: reduce){ .pc-coin{ animation:none; } }


/* ═══════════════════════════════════════════════════════════════════════════
   LE VOILE D'ARRIVÉE

   Un noir qui monte à moitié puis redescend, le temps qu'une surface arrive.
   C'est la moitié la plus importante de l'animation : le grossissement seul
   laisse deux surfaces à plat, le voile leur donne un dessus et un dessous.

   Il passe SOUS les deux barres — elles ne changent pas d'écran, elles
   encadrent celui qu'on regarde, et les voir clignoter à chaque page serait
   pénible.
   ═══════════════════════════════════════════════════════════════════════════ */
.voile-arrivee{
  position:fixed; inset:0;
  /* z-index 9 : SOUS les deux barres. La barre du bas est à 10, celle du haut
     à 15 — je l'avais posé à 14, ce qui assombrissait la barre du bas à chaque
     page. Or elle ne change pas d'écran : elle encadre celui qu'on regarde, et
     la voir clignoter cent fois par service serait pénible.

     Au-dessus du contenu (z-index 1) et des halos : c'est bien lui qu'on
     assombrit. */
  z-index:9;
  background:#000; opacity:0; pointer-events:none;
}
.voile-arrivee.joue{
  animation:voileArrivee 0.38s cubic-bezier(0.32, 0.72, 0, 1) both;
}
@keyframes voileArrivee{
  0%   { opacity:0; }
  38%  { opacity:0.42; }
  100% { opacity:0; }
}
@media (prefers-reduced-motion: reduce){
  .voile-arrivee.joue{ animation:none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   VOS ANALYSES VIDÉO

   Une carte, un anneau, un chiffre. L'ambre montre ce qui RESTE : l'anneau
   maigrit à mesure du mois, ce qui se lit sans compter.
   ═══════════════════════════════════════════════════════════════════════════ */
/* Pas de carte non plus ici — même raison que pour la fiche membre. L'anneau
   porte tout le sens ; l'encadrer ne fait qu'ajouter une bordure autour du
   vide. */
.quota-carte{ padding:14px 2px 4px; text-align:center; }
.quota-attente{ padding:40px 10px; font-size:13px; color:var(--label-3); }

.quota-anneau{ position:relative; display:grid; place-items:center; margin-bottom:14px; }
/* Le quart de tour : sans lui, l'anneau démarre à trois heures. */
.quota-anneau svg{ display:block; transform:rotate(-90deg); }
.quota-anneau .piste{ stroke:rgba(255,255,255,0.07); }
.quota-anneau .part{
  stroke-linecap:round;
  transition:stroke-dashoffset 1.1s cubic-bezier(0.32, 0.72, 0, 1);
}
.quota-dedans{ position:absolute; text-align:center; width:150px; }
.quota-dedans .gros{
  font-size:52px; font-weight:750; letter-spacing:-0.05em; line-height:1;
}
.quota-dedans .unite{
  font-size:12.5px; color:var(--label-2); font-weight:650;
  margin-top:4px; line-height:1.3;
}
.quota-dedans .sous{
  font-size:12px; color:var(--label-3); font-weight:600; margin-top:9px;
}

/* L'illimité est un ARGUMENT, pas une note. Il tient donc dans un encadré
   ambre, au-dessus de la mention — pas mêlé à elle. */
.quota-illimite{
  display:flex; align-items:flex-start; gap:10px; text-align:left;
  margin-top:18px; padding:13px 14px; border-radius:16px;
  background:rgba(255,173,51,0.06);
  box-shadow:inset 0 0 0 0.5px rgba(255,173,51,0.16);
  font-size:12.5px; line-height:1.5; color:var(--label-2);
}
.quota-illimite b{ color:var(--label-1); font-weight:700; }
.quota-illimite .ic{ flex-shrink:0; font-size:17px; color:#FFAD33; line-height:1.15; }

/* Le bouton n'apparaît QUE sous cinq analyses. Ailleurs il serait de la
   réclame ; ici c'est un service — la personne va se trouver bloquée. */
.quota-cta{
  width:100%; height:46px; margin-top:12px; border:none; border-radius:14px;
  font-family:inherit; font-size:14px; font-weight:750;
  background:linear-gradient(135deg,#E85D00,#F58A15 62%,#FF9F26); color:#2A1400;
}
.quota-cta:active{ opacity:0.85; }

.quota-pied{
  margin-top:16px; padding-top:15px;
  border-top:0.5px solid rgba(255,255,255,0.07);
  font-size:12.5px; line-height:1.5; color:var(--label-3);
}
.quota-pied b{ color:var(--label-2); font-weight:700; }

@media (prefers-reduced-motion: reduce){
  .quota-anneau .part{ transition:none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   L'ÉCRAN DE CHOIX : LE LOGO ET LE NOM SUR UNE LIGNE

   Le logo était posé au-dessus du mot, comme un blason. Côte à côte, on lit
   une signature — la même que dans la barre du haut de l'app, ce qui rend
   l'arrivée dans l'app moins brutale.
   ═══════════════════════════════════════════════════════════════════════════ */
.choix-marque{
  display:flex; align-items:center; justify-content:center;
  gap:11px; margin-bottom:6px;
}
/* La marge du bas appartenait au logo, qui n'est plus seul sur sa ligne. */
.choix-marque .boot-logo{ margin:0; }
/* ═══ LA TAILLE VENAIT DE LA CARTE, QUI N'EXISTE PLUS ═══

   `Standix` est un `h1`, et sa taille lui venait de `.login-card h1{
   font-size:22px }`. En retirant le cadre de l'écran de choix, on a retiré
   cette règle avec lui : le mot serait repassé à la taille par défaut d'un
   `h1`, soit 32 px, avec ses marges de bloc.

   On la pose donc ici, où elle aurait dû être depuis le début : la taille de la
   marque ne dépend pas de la boîte qui la contient. */
.choix-marque .logotype{ font-size:22px; margin:0; }


/* ═══════════════════════════════════════════════════════════════════════════
   L'ESPACE ÉQUIPE RESPIRE UN PEU PLUS SOUS LA BARRE

   Dix-neuf pixels séparaient la pilule du logo et le « Bonjour ». C'est la
   valeur commune aux deux espaces — mais ici le titre est un salut, pas une
   étiquette de section : il ouvre la page plutôt qu'il ne la range. Il lui
   faut le recul qu'on donne à une phrase qu'on adresse à quelqu'un.

   La règle ne vise QUE `#equipe-app` : l'espace Gestion garde ses 19 px, et
   ses quinze pages restent alignées entre elles.
   ═══════════════════════════════════════════════════════════════════════════ */
/* Le `.page-tete` n'est pas enfant direct de l'écran : il vit dans
   `#e-bloc-categories`. Le sélecteur descendant l'atteint quel que soit le
   nombre de niveaux, et `:first-child` garantit qu'on ne vise que le premier
   de la page — pas un en-tête de section plus bas. */
#equipe-app .page-tete{
  margin-top:11px;
}


/* ═══════════════════════════════════════════════════════════════════════════
   L'ÉCRAN DE CHOIX : DEUX LIGNES PAR BOUTON

   Le bouton porte maintenant son nom ET ce qu'on trouve derrière. Il lui faut
   donc une hauteur libre plutôt que la hauteur fixe des boutons ordinaires.

   La marge de 10 px était posée en style direct sur le premier bouton ; elle
   passe ici, où elle se lit avec le reste.
   ═══════════════════════════════════════════════════════════════════════════ */
/* `.btn.block` impose `text-align:center` et gagne par spécificité — deux
   classes contre une. On redouble donc la nôtre pour l'emporter, plutôt que de
   modifier `.btn.block`, qui sert à quinze autres boutons dans l'app. */
/* ═══════════════════════════════════════════════════════════════════════════
   L'ÉCRAN DE CHOIX · DEUX CARTES, SANS CADRE AUTOUR

   Les deux boutons pleine largeur empilés sont devenus deux cartes verticales
   posées côte à côte, DIRECTEMENT SUR LE FOND.

   PLUS DE `login-card` AUTOUR. Deux cartes dans une carte, c'était une boîte
   dans une boîte — et le cadre volait 48 px de largeur à un écran qui n'en a
   pas de trop. Les cartes gagnent ces 48 px : 168 px par colonne sur un
   iPhone, 133 px sur un iPhone SE, contre 150 et 114 avant.

   LA MATIÈRE EST CELLE DE LA CARTE « BONJOUR ». Même fond dégradé, même liseré
   allumé aux deux angles opposés, même lueur portée. C'est `.hero` qui la
   définit, et on la reprend ici au lieu de la redessiner : le jour où tu
   changeras l'une, l'autre suivra.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ═══ L'ÉCRAN DE CHOIX PREND LA PLACE ═══

   Il était borné à 380 px dans une enveloppe qui prend elle-même 24 px de
   chaque côté : sur un iPhone de 390, les deux cartes se partageaient 342 px
   et flottaient au milieu d'un écran vide.

   Ce n'est pas une page de contenu — c'est un aiguillage, la première chose
   qu'on voit, et il n'y a que deux choses à y faire. Elles doivent occuper
   l'écran, pas s'y blottir.

   `#choice-screen` porte la classe `.login-wrap`, partagée avec l'écran de
   connexion : on ne desserre QUE celui-ci. La connexion garde ses 24 px, elle
   contient des champs de saisie qui ont besoin de cette marge. */
#choice-screen{ padding:18px 14px; }
.choix-ecran{
  width:100%; max-width:460px; text-align:center;
}

/* Le titre d'accueil. Le mot « Standix » porte la classe `logotype` dans le
   balisage : il hérite de Poppins 500 comme la marque juste au-dessus. On ne
   lui ajoute ici que la couleur — la police vient de l'autre règle, et c'est
   volontaire pour qu'un changement de police de marque se propage. */
.choix-bienvenue{
  font-size:25px; font-weight:700; letter-spacing:-0.035em;
  line-height:1.2; margin:16px 0 8px;
}
.choix-bienvenue .logotype{
  font-size:inherit;
  background:linear-gradient(135deg,#FFC46B,#FF6A00);
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent;
}

.choix-duo{
  display:grid; grid-template-columns:repeat(2, minmax(0, 1fr)); gap:14px;
  align-items:stretch;
  /* ═══ L'ÉCART QUI SÉPARE LA QUESTION DE LA RÉPONSE ═══

     14 px, c'était l'écart entre deux lignes d'un même paragraphe. « Choisissez
     votre espace pour continuer » se lisait donc comme une légende des cartes,
     collée à elles, alors que c'est la question à laquelle elles répondent.

     Une question et ses réponses ne sont pas au même niveau : il faut un blanc
     qui marque le passage de l'une aux autres. C'est le seul endroit de cet
     écran où l'espacement porte du sens plutôt que du confort.

     `clamp` parce que la valeur ne peut pas être fixe : 30 px sur un iPhone SE
     rognent la hauteur des cartes, alors que sur un grand téléphone il en
     faudrait davantage pour que le blanc se voie. */
  margin-top:clamp(20px, 4.2vh, 34px);
}

/* ═══ LA CARTE ═══

   `min-width:0` N'EST PAS DÉCORATIF. Sans lui, la carte déborde de sa colonne
   et pousse tout l'écran vers la droite. `minmax(0, 1fr)` fixe la largeur de la
   COLONNE, mais l'élément posé dedans garde `min-width:auto` : il refuse de
   descendre sous sa largeur minimale intrinsèque et sort du cadre. Le défaut ne
   se voit que sur un écran étroit — à 390 px tout semblait aller, à 320 px rien
   ne tenait.

   `overflow:visible` malgré le `.hero` d'origine qui coupe : la pastille
   « Recommandé » est posée à cheval sur le bord haut et serait tranchée. */
.choix-carte{
  display:flex; flex-direction:column; align-items:flex-start;
  position:relative; overflow:visible;
  height:auto; text-align:left; min-width:0;
  /* ═══ PLUS DE RÉSERVE EN HAUT ═══

     Les 34 px du haut n'étaient pas de l'air : ils réservaient la place de la
     pastille « Recommandé », qui n'existe plus. Les garder aurait laissé un
     vide inexpliqué au-dessus de l'icône.

     Le rembourrage est maintenant régulier — un peu plus en bas, pour que la
     flèche ne touche pas le bord. Une carte aux marges égales se lit comme une
     carte ; une carte plus creuse en haut se lit comme une carte mal remplie. */
  /* La carte grandit avec l'écran ; le rembourrage suit. Une carte plus large
     avec les mêmes marges paraît creuse au centre et serrée sur les bords. */
  padding:22px 18px 24px;
  /* ═══ LA HAUTEUR SUIT LA FENÊTRE ═══

     Sans plancher, la carte se règle sur son contenu : deux lignes de
     description donnent une carte basse, perdue dans un écran de 800 px.

     `min()` borne les deux extrêmes — 40 % de la hauteur utile sur un grand
     téléphone, jamais plus de 300 px sur une tablette où ce serait démesuré. */
  min-height:min(38vh, 290px);
  border-radius:22px;
  border:none;
  /* Le fond de `.hero`, à l'identique. */
  background:linear-gradient(150deg, #17171B 0%, #101014 40%, #0A0A0D 75%, #060608 100%);
  color:var(--label);
  transition:transform 0.18s ease;
}
.choix-carte .cc-t,
.choix-carte .cc-s{ max-width:100%; overflow-wrap:break-word; }
.choix-carte:active{ transform:scale(0.975); }

/* Le contenu passe AU-DESSUS du calque de liseré, qui couvre toute la carte.

   ⚠ `.cc-reco` EST EXCLUE, ET CE N'EST PAS UN DÉTAIL. Ce sélecteur pèse (0,2,0)
   contre (0,1,0) pour `.cc-reco` : sans l'exclusion, il lui imposait
   `position:relative` et la pastille retombait dans le flux. Elle prenait alors
   une ligne entière en tête de carte — mesuré : 235 px de haut au lieu de 93 sur
   un iPhone SE, et les deux cartes ne s'alignaient plus. Le défaut ne se voyait
   qu'une fois les cartes empilées. */
.choix-carte > *:not(.hero-lueur):not(.cc-reco){ position:relative; z-index:1; }

/* ═══ LES DEUX COULEURS ═══

   `.hero-lueur` et son `::after` portent déjà la mécanique : un calque en
   position absolue, un contour évidé par masque, deux angles allumés. On ne
   redéfinit ici que les COULEURS — la géométrie reste celle du hero.

   Gestion en ambre, Équipe en blanc. Ce n'est pas qu'une différence de teinte :
   l'ambre est la couleur des gestes de l'app, le blanc celle de la lecture. Les
   deux espaces se distinguent donc par ce qu'ils font, pas par une hiérarchie. */
.choix-carte--ambre{
  box-shadow:0 16px 38px rgba(0,0,0,0.50), 0 0 34px -12px rgba(255,122,24,0.32);
}
.choix-carte--blanc{
  box-shadow:0 16px 38px rgba(0,0,0,0.50), 0 0 34px -12px rgba(255,255,255,0.16);
}
.choix-carte--blanc .hero-lueur{
  background:
    radial-gradient(150px 110px at 100% 0%, rgba(255,255,255,0.10), transparent 72%),
    radial-gradient(130px 100px at 0% 100%, rgba(255,255,255,0.06), transparent 72%);
}
.choix-carte--blanc .hero-lueur::after{
  background:linear-gradient(45deg,
    #FFFFFF 0%, rgba(255,255,255,0.50) 12%, rgba(255,255,255,0.06) 30%,
    rgba(255,255,255,0.06) 70%, rgba(255,255,255,0.50) 88%, #FFFFFF 100%);
}

/* ═══ LA PASTILLE « RECOMMANDÉ » ═══

   Posée à cheval sur le bord haut. `left:50%` + `translateX(-50%)` la centre
   quelle que soit la longueur du mot — utile le jour où il sera traduit, car
   « Recommended » et « Recomendado » ne font pas la même largeur. */
.cc-reco{
  position:absolute; top:-10px; left:50%; transform:translateX(-50%);
  z-index:2;
  display:inline-flex; align-items:center; gap:4px;
  padding:3.5px 9px; border-radius:999px;
  background:#2A1B0C; border:0.5px solid rgba(255,150,40,0.45);
  color:#FFAD33;
  font-size:9px; font-weight:800; letter-spacing:0.07em; text-transform:uppercase;
  white-space:nowrap;
}
.cc-reco svg{ width:9px; height:9px; flex:0 0 9px; display:block; }

/* ═══ LE ROND DE L'ICÔNE ═══

   Un cercle vide, pas une pastille pleine : sur un fond aussi sombre, un
   cercle plein attirerait plus l'œil que le titre qu'il surmonte, et l'ordre de
   lecture s'inverserait. */
.cc-rond{
  display:flex; align-items:center; justify-content:center;
  width:46px; height:46px; flex:0 0 46px;
  border-radius:50%;
  border:1px solid rgba(255,255,255,0.16);
  color:var(--label-2);
  margin-bottom:18px;
}
.cc-rond svg{ width:23px; height:23px; display:block; }
.choix-carte--ambre .cc-rond{ border-color:rgba(255,150,40,0.50); color:#FFAD33; }
.choix-carte--blanc .cc-rond{ border-color:rgba(255,255,255,0.34); color:var(--label); }

/* L'enveloppe du texte. En deux colonnes elle ne fait rien — un bloc pleine
   largeur, comme si elle n'existait pas. Empilée, elle devient la colonne
   souple entre l'icône et la flèche. Sans elle, le titre et la description
   seraient deux colonnes distinctes de la rangée. */
.cc-txt{ display:block; width:100%; }

.cc-t{
  display:block; font-size:14.5px; font-weight:700; letter-spacing:-0.025em;
  line-height:1.25; margin-bottom:7px;
}
.cc-s{
  display:block; font-size:11.5px; font-weight:500; line-height:1.4;
  color:var(--label-2);
}

/* La flèche est poussée en bas par `margin-top:auto`. Les deux cartes font la
   même hauteur — la grille l'impose — donc les deux flèches s'alignent, même
   quand une description tient sur trois lignes et l'autre sur deux. */
.cc-fleche{
  display:flex; align-items:center; justify-content:center;
  width:38px; height:38px; flex:0 0 38px;
  /* ═══ LA FLÈCHE REJOINT LA COLONNE ═══

     Elle était centrée alors que l'icône, le titre et la description sont à
     gauche. Un seul élément désaligné dans une carte qui en compte quatre
     suffit à la faire paraître bancale, sans qu'on sache dire pourquoi.

     Pourquoi la gauche plutôt que tout centrer : la description fait deux à
     trois lignes, et un paragraphe centré se lit moins bien qu'un paragraphe
     aligné — l'œil doit rechercher le début de chaque ligne. On aligne donc la
     flèche sur le texte, pas l'inverse. */
  margin-top:auto; align-self:flex-start;
  padding-top:0;
  border-radius:50%;
  border:1px solid rgba(255,255,255,0.16);
  color:var(--label-2);
}
.cc-fleche svg{ width:17px; height:17px; display:block; }
.choix-carte--ambre .cc-fleche{ border-color:rgba(255,150,40,0.50); color:#FFAD33; }
.choix-carte--blanc .cc-fleche{ border-color:rgba(255,255,255,0.34); color:var(--label); }
/* Un plancher d'air au-dessus de la flèche. `margin-top:auto` la pousse en bas,
   mais si la description remplit la carte, les deux se touchent. */
.cc-fleche{ margin-top:auto; }
.cc-s + .cc-fleche{ margin-top:18px; }
.choix-carte .cc-fleche{ margin-bottom:0; }

/* ═══════════════════════════════════════════════════════════════════════════
   LES PETITS ÉCRANS · UNE CARTE PAR LIGNE

   Deux colonnes au-dessus de 384 px, deux rangées en dessous.

   ─── POURQUOI 384 ET PAS 360 ───

   Il y a deux iPhone SE. Le premier fait 320 px de large, les suivants 375.
   Une coupure à 360 aurait laissé le SE moderne — de loin le plus répandu — en
   deux colonnes de 158 px, ce qui n'est pas ce qui est demandé. 384 attrape les
   deux, et laisse tranquilles les iPhone courants à 390 et 393 px. La marge est
   mince, six pixels, mais aucun téléphone ne tombe dedans.

   ─── POURQUOI LA CARTE PASSE EN LIGNE ───

   Empilée, une carte occupe toute la largeur : garder l'icône au-dessus du
   titre et la flèche en dessous donnerait 200 px de haut par carte. Deux
   cartes plus l'en-tête dépassent alors la hauteur utile d'un SE, et l'écran
   de choix — celui qui doit se lire d'un coup — demanderait de faire défiler.

   En ligne, la carte tombe à 76 px : icône à gauche, texte au milieu, flèche à
   droite. Les deux tiennent, l'en-tête aussi, et rien ne défile.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 384px){
  .choix-bienvenue{ font-size:22px; }

  /* Empilées, les cartes sont plus basses et l'écran plus court : on garde la
     séparation mais on la resserre, sinon elle mange la place des cartes. */
  .choix-duo{ grid-template-columns:1fr; gap:10px; margin-top:clamp(16px, 3vh, 24px); }

  .choix-carte{
    flex-direction:row; align-items:center;
    /* Empilées, les cartes sont larges et basses : le rembourrage suit une
       autre logique qu'en colonnes, et la flèche se recentre verticalement
       puisqu'elle est à droite du texte et non en dessous. */
    /* ⚠ ON ANNULE LE PLANCHER DE HAUTEUR. Il vaut 38 % de la fenêtre pour les
       cartes en colonnes, où il les empêche de paraître écrasées. Empilées,
       elles sont larges et basses : le même plancher en faisait deux pavés de
       300 px qui débordaient de l'écran. */
    min-height:0;
    padding:16px 16px 16px 15px;
    text-align:left;
  }

  /* La pastille passe dans l'angle : sur une carte large et basse, la garder
     centrée sur le bord haut la poserait au milieu de rien. */
  .cc-reco{ left:auto; right:13px; transform:none; top:-9px; }

  .cc-rond{
    width:42px; height:42px; flex:0 0 42px;
    margin-bottom:0; margin-right:12px;
  }
  .cc-rond svg{ width:19px; height:19px; }

  /* `min-width:0` de nouveau : sans lui, la colonne du texte refuse de
     descendre sous la longueur de sa plus longue ligne et pousse la flèche
     hors de la carte. Même piège que sur la grille, un cran plus bas. */
  .cc-txt{ flex:1 1 auto; min-width:0; width:auto; }
  .cc-t{ font-size:14px; margin-bottom:3px; }
  .cc-s{ font-size:11px; line-height:1.35; }

  .cc-fleche{
    width:32px; height:32px; flex:0 0 32px;
    margin-top:0; margin-left:14px; align-self:center;
  }
  .cc-fleche svg{ width:15px; height:15px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   LES DEUX CODES D'INVITATION

   Le style du code était écrit en attribut, directement sur la balise. Il
   passe ici : deux codes le partagent maintenant, et une valeur recopiée à
   deux endroits finit toujours par diverger.

   0.22em d'approche et non 0.28 : six caractères prennent plus de place que
   cinq, et le code débordait sur un écran de 320 px.
   ═══════════════════════════════════════════════════════════════════════════ */
.code-gros{
  font-size:34px; font-weight:850; letter-spacing:0.22em;
  margin:10px 0 16px; word-break:break-all;
}
.sect-tt{
  font-size:11.5px; font-weight:700; letter-spacing:0.08em; text-transform:uppercase;
  color:var(--label-3); margin:26px 0 10px 2px;
}
.cg-txt{ font-size:14px; color:var(--label-2); line-height:1.5; margin-bottom:14px; }
/* Le temps restant. Il vire à l'ambre le dernier jour — c'est le moment où le
   gérant doit savoir que son invitation va tomber. */
.cg-reste{ font-size:12.5px; color:var(--label-3); margin-bottom:14px; }
.cg-reste.bientot{ color:var(--or2, #FFAD33); }

/* ═══════════════════════════════════════════════════════════════════════════
   LE DÉTAIL D'UNE PROCÉDURE

   ═══ POURQUOI SEULEMENT L'ESPACE ÉQUIPE ═══

   J'ai d'abord appliqué la même règle aux deux. Le résultat était mauvais côté
   Gestion : cette page ne s'arrête pas aux étapes, elle porte AUSSI le QR code
   et son encadré. Forcée sur un écran, la liste se réduisait à une seule ligne
   écrasée entre la vidéo et le QR.

   Les deux pages n'ont pas le même contenu, elles ne peuvent pas avoir la même
   disposition. Celle de l'Équipe ne montre que les étapes : elle peut tenir
   sur un écran. Celle de la Gestion continue de défiler normalement.

   ═══ LA PAGE TIENT SUR UN ÉCRAN ═══

   Elle ne défile pas. À l'intérieur, deux parties : un en-tête figé — titre,
   dossier, vidéo — et la liste des étapes, seule zone mobile.

   `min-height:0` sur la liste : sans lui, un enfant en `flex` refuse de
   devenir plus petit que son contenu, et c'est la page entière qui reprend le
   défilement. C'est le piège classique de cette disposition.

   ═══ LA LIGNE DE FONDU ═══

   Juste sous la vidéo, invisible. Les étapes s'y effacent en montant, et
   réapparaissent en descendant.

   14 px, réglage « court et franc » : l'étape disparaît vite, sans traîner
   à moitié lisible. En PIXELS et non en pourcentage — un pourcentage tomberait
   au milieu de la dernière étape sur une liste courte, et elle paraîtrait
   effacée alors qu'il n'y a rien après.
   ═══════════════════════════════════════════════════════════════════════════ */
/* ═══ `.active` SUR CHAQUE RÈGLE ═══

   J'avais écrit `#e-detail{ display:flex }` sans condition. Un écran inactif
   est masqué par `display:none` — ma règle l'écrasait, et la page de détail
   restait visible sous le QR code, sous les réglages, et en bas de la liste.

   Toutes les règles ci-dessous ne valent donc que pour l'écran ACTIF. */
#e-detail.active{
  /* La hauteur descend jusqu'au BAS DE L'ÉCRAN, pas jusqu'à la barre : on
     retire seulement les 87 px du haut. La liste passe ainsi derrière la
     navigation, qui flotte au-dessus d'elle. */
  height:calc(100dvh - 87px);
  display:flex; flex-direction:column;
  overflow:hidden;
  margin-top:87px;
  padding-top:0; padding-bottom:0;
}
/* Le corps de la page ne défile plus tant qu'on est sur un détail. Sans cette
   règle, l'app garde sa hauteur habituelle et la fenêtre défile par-dessus la
   page figée — on voyait le bas d'une autre page apparaître. */
/* `body` ET `html` : sur mobile, c'est souvent l'élément racine qui défile, pas
   le corps. Bloquer l'un sans l'autre laisse la page bouger malgré tout.

   `position:fixed` sur le corps est le seul verrou vraiment sûr sur iOS, où
   Safari ignore `overflow:hidden` dans certains cas. La largeur explicite
   l'empêche de se rétracter une fois sorti du flux. */
html:has(#e-detail.active),
/* ═══ LE VERROU QUI CASSAIT LES CLICS ═══

   J'avais posé `position:fixed; inset:0` sur le corps, pour empêcher la page
   de défiler derrière la liste. Ça marchait — et ça cassait tout le reste.

   Un corps en `fixed` sort du flux : sa hauteur ne correspond plus à celle du
   contenu, et le navigateur calcule mal où se trouvent les éléments. Les
   boutons répondaient donc au deuxième ou au troisième doigt, jamais au
   premier — le point touché ne tombait pas là où le navigateur croyait qu'il
   était.

   `overflow:hidden` seul suffit à bloquer le défilement. C'est ce qu'il aurait
   fallu poser dès le départ ; le `fixed` était une précaution de trop, prise
   pour un problème iOS que je n'avais pas constaté. */
body:has(#e-detail.active){
  overflow:hidden;
  overscroll-behavior:none;
}
/* ═══ LE CONTENEUR AUSSI ═══

   `#equipe-app` descendait à 931 px pour une fenêtre de 844 : il additionnait
   la hauteur de l'écran et le rembourrage de la barre du haut. Le document
   gardait donc 87 px de défilement résiduel — invisible à l'œil, mais assez
   pour que la page glisse sous le doigt et que le navigateur refuse les clics
   sur une cible « qui bouge ».

   On le borne à la fenêtre le temps de cette page. */
body:has(#e-detail.active) #equipe-app{
  height:100dvh;
  overflow:hidden;
}


/* L'en-tête figé : tout ce qui n'est pas la liste. */
#e-detail.active > *{ flex:0 0 auto; }

/* La vidéo est bornée : sans plafond, une vidéo verticale prendrait tout
   l'écran et il ne resterait rien pour les étapes. */
#e-detail.active .video-frame video{ max-height:30dvh; }

/* ═══ LA ZONE QUI DÉFILE ═══

   Elle contient la liste ET le bloc « Procédure terminée ». Les deux défilent
   ensemble : le bloc de fin arrive APRÈS la dernière étape, comme une
   conclusion — c'est ce qu'on attend au bout d'une lecture.

   Posé en dehors, il aurait occupé le bas de l'écran en permanence, y compris
   quand il reste six étapes à lire.

   La zone descend jusqu'en bas de l'écran : `flex:1 1 auto` lui donne tout
   l'espace restant sous la vidéo. */
#e-detail.active .zone-etapes{
  flex:1 1 auto;
  min-height:0;                /* le piège du flex — voir plus haut */
  overflow-y:auto;
  -webkit-overflow-scrolling:touch;
  overscroll-behavior:contain; /* le défilement ne se propage pas à la page */
  /* 18 px en haut, inchangé. J'avais tenté 16 pour resserrer davantage : la
     marge entre le fondu et le premier cercle tombait à 2 px, et le cercle
     commençait à s'estomper.

     Le resserrement se prend donc UNIQUEMENT sur la marge du titre, qui n'a
     pas cette contrainte. L'écart total passe quand même de 28 à 22 px.

     122 px en bas : la hauteur de la barre de navigation. La zone descend
     jusqu'au bord de l'écran — c'est son CONTENU qui s'arrête au-dessus de la
     barre, pour que la dernière étape reste lisible. */
  padding-top:18px;
  padding-bottom:122px;

  mask-image:linear-gradient(180deg,
    transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%);
  -webkit-mask-image:linear-gradient(180deg,
    transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%);
}
/* Le bloc de fin respire après la dernière étape. */
#e-detail.active .zone-etapes .confirm-bar{ margin-top:22px; }

/* ═══ L'ÉCART SOUS « ÉTAPES DE LA PROCÉDURE » ═══

   Trente-six pixels séparaient le bas du texte du haut de la première étape.
   Beaucoup trop : le titre et la première étape appartiennent au même bloc de
   lecture, et cet écart les faisait paraître étrangers l'un à l'autre.

   ─── D'OÙ VENAIENT CES 36 PIXELS ───

   Quatre sources, et la plus grosse n'était pas une marge :

     10 px  du VIDE DANS LA LIGNE DU TITRE. Le sélecteur de langue fait 38 px
            de haut, le texte n'en occupe que 18. La ligne est un `flex` centré
            verticalement : le globe commande la hauteur, et le texte flotte au
            milieu avec 10 px de vide au-dessous. C'est la cause principale, et
            elle est invisible quand on cherche des marges.
      4 px  `margin-bottom` de la ligne du titre
     18 px  `padding-top` de la zone qui défile
      4 px  `margin-top` du fil des étapes

   ─── CE QUI EST TOUCHÉ, ET CE QUI NE L'EST PAS ───

   Les 18 px de la zone RESTENT. Ils sont commandés par le fondu de 14 px, qui
   est une décision arrêtée. À 16 px, la marge entre le fondu et le premier
   cercle tombe à 2 px et le cercle commence à s'estomper. On n'y touche pas.

   Le globe GARDE ses 38 px. Réduire une cible tactile pour gagner de la place
   est un mauvais échange : on lit cette page debout, entre deux tâches. On
   annule seulement la hauteur qu'il IMPOSE À LA LIGNE, par une marge négative
   verticale — le globe déborde de sa ligne, ce qui ne se voit pas puisqu'il
   n'y a rien à côté.

   Résultat : 36 px → 22 px. La zone de 18 px reste la plus grosse part, et
   c'est normal : c'est elle qui porte le fondu.

   Portée limitée à `#e-detail` : la fiche de gestion emploie les mêmes classes
   et n'a pas été demandée. */
#e-detail.active .detail-etapes-tete{ margin-bottom:0; }
#e-detail.active .detail-etapes-tete .tiroir-langue{
  margin-top:-6px; margin-bottom:-6px;   /* ligne : 38 px → 26 px */
}
#e-detail.active #detail-steps.etapes-fil{ margin-top:0; }

/* ═══ LA BARRE DE DÉFILEMENT EST INVISIBLE ═══

   Trois écritures, parce qu'aucune ne suffit seule : `scrollbar-width` pour
   Firefox, `-webkit-scrollbar` pour Safari et Chrome, `-ms-overflow-style`
   pour les anciens Edge. La zone défile toujours — on ne cache que la barre. */
#e-detail.active .zone-etapes{
  scrollbar-width:none;
  -ms-overflow-style:none;
}
#e-detail.active .zone-etapes::-webkit-scrollbar{ width:0; height:0; display:none; }

/* ═══ UNE ÉTAPE COCHÉE RESTE EN PLACE ═══

   Le chiffre devient une coche, l'étape passe en gris. Elle ne se replie plus :
   on garde son avancement sous les yeux. */
#detail-steps.etapes-fil .detail-step.faite{
  opacity:0.42;
  transition:opacity 0.34s cubic-bezier(0.32,0.72,0,1);
}

/* ═══════════════════════════════════════════════════════════════════════════
   « POURQUOI LA LIMITE DE 90 MO ? »

   Le lien dans le message d'avertissement, et le tableau de la fenêtre.

   Le sélecteur part de `.fen-co` : cette classe centre tout son contenu, et sa
   règle vit dans un bloc `@media` — ce qui la rend plus spécifique qu'un
   sélecteur simple. Deux classes contre une, et le centrage cède. C'est juste
   pour une question courte, faux pour un tableau à deux colonnes.
   ═══════════════════════════════════════════════════════════════════════════ */
.lien-info{
  background:none; border:none; padding:0; cursor:pointer;
  font:inherit; color:var(--or2, #FFAD33); text-decoration:underline;
  text-underline-offset:2px;
}
.fen-co .fen-html,
.fen-co .fen-html *{ text-align:left; }
.fen-html{ margin-top:4px; }
.pq-p{ font-size:13.5px; line-height:1.5; color:var(--label-2); margin-bottom:14px; }
.pq-t{
  font-size:11px; font-weight:700; letter-spacing:0.07em; text-transform:uppercase;
  color:var(--label-3); margin-bottom:6px;
}
/* Chaque ligne : la source à gauche, la durée à droite. Le filet les sépare
   sans les enfermer dans un tableau — deux colonnes suffisent. */
.pq-l{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  font-size:13.5px; color:var(--label-2);
  padding:9px 0; border-top:0.5px solid var(--border);
}
.pq-l:first-of-type{ border-top:none; }
.pq-l b{ color:var(--label-1); font-weight:700; white-space:nowrap; }
.pq-fin{ margin-top:16px; margin-bottom:0; }


/* ═══════════════════════════════════════════════════════════════════════════
   LE RÉSUMÉ DE L'ENTREPRISE

   Il occupe la place de l'ancienne carte illustrée, et en garde la forme :
   même fond, même liseré ambre, même lueur. Ce qui change, c'est le contenu —
   des chiffres au lieu d'un dessin.
   ═══════════════════════════════════════════════════════════════════════════ */
.resume-ent{ padding:18px 20px 16px; }

.re-tete{ display:flex; align-items:center; gap:9px; margin-bottom:16px; }
/* `min-width:0` et les points de suspension : sans eux, un prénom long pousse
   « 11 membres » à la ligne suivante et la tête de carte se dédouble. Le
   prénom se tronque, le total ne bouge pas — c'est le bon arbitrage : on sait
   toujours à qui on parle, même tronqué, et le chiffre doit rester lisible. */
.re-salut{
  font-size:20px; font-weight:700; letter-spacing:-0.03em;
  min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
/* L'emoji ne suit pas la graisse du texte : il garde sa taille propre et un
   léger décalage vers le haut, sinon il pend sous la ligne de base. */
.re-main{ font-size:18px; line-height:1; transform:translateY(-1px); }
/* Le total, poussé à droite. `margin-left:auto` plutôt qu'un
   `justify-content:space-between` sur le parent : l'emoji doit rester COLLÉ au
   prénom, et `space-between` l'aurait envoyé au milieu. */
.re-total{
  margin-left:auto; flex-shrink:0;
  font-size:12.5px; color:var(--label-2);
  font-variant-numeric:tabular-nums; white-space:nowrap;
}

/* ═══ LA RÉPARTITION ═══

   Trois cases de même taille pour un total et ses deux parts : le même poids
   visuel donné à 11 qu'à 3 et 8, alors que 11 EST 3 + 8. La barre montre la
   proportion, ce que trois nombres alignés obligeaient à calculer de tête.

   Les largeurs viennent de `flex` posé en ligne par le JavaScript, avec les
   effectifs bruts comme valeurs : trois et huit donnent d'eux-mêmes 27 % et
   73 %. Aucun pourcentage n'est calculé nulle part — c'est le moteur de mise
   en page qui divise, et il ne se trompe pas d'arrondi. */
.re-chiffres{ margin-bottom:2px; }
.re-barre{
  display:flex; gap:3px; height:8px; margin-bottom:9px;
  border-radius:5px; overflow:hidden;
}
.re-barre i{ display:block; min-width:3px; }
/* ═══ LE MÊME AMBRE QUE L'ANCIENNE CARTE ═══

   J'avais employé `--orange` (#FF9F0A), qui n'est pas l'ambre de l'app. Le
   dégradé ci-dessous est recopié à l'identique de l'ancienne règle `.re-c b`,
   celle qui colorait les trois grands chiffres — même angle, mêmes deux
   arrêts. La carte change de forme, pas de couleur.

   135° sur un segment large donne un dégagement franc de gauche à droite :
   c'est le même geste que sur les chiffres, à l'horizontale. */
.re-sg{ background:linear-gradient(135deg,#FFC46B,#FF6A00); }
.re-se{ background:rgba(255,255,255,0.17); }

.re-leg{ display:flex; gap:16px; font-size:12px; color:var(--label-2); }
/* Sans `nowrap`, « 3 gestion » se casse entre le chiffre et le mot dès que la
   place manque, et la légende occupe quatre lignes au lieu d'une. */
.re-leg span{ white-space:nowrap; }
.re-leg b{ font-weight:700; font-variant-numeric:tabular-nums; }
/* Le chiffre de la gestion porte le dégradé découpé sur le texte — exactement
   le traitement des anciens grands chiffres, à une autre échelle. */
.re-leg b.g{
  background:linear-gradient(135deg,#FFC46B,#FF6A00);
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent;
}
.re-leg b.e{ color:var(--label); }

/* Les postes. Une ligne chacun, le nom à gauche et le compte à droite —
   la disposition d'un relevé, qui se lit en diagonale. */
.re-postes{ margin-top:16px; }
.re-t{
  font-size:10.5px; font-weight:700; letter-spacing:0.09em; text-transform:uppercase;
  color:var(--label-3); margin-bottom:6px;
}
.re-p{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  font-size:13.5px; color:var(--label-2);
  padding:7px 0; border-top:0.5px solid var(--border);
}
/* ═══ LE TRAIT MANQUANT SOUS LA DERNIÈRE LIGNE VISIBLE ═══

   `:first-of-type` se calcule PAR PARENT. Le tiroir en est un : sa première
   ligne était donc, elle aussi, « la première de son type », et perdait son
   trait — exactement celui qui devait la séparer de la dernière ligne restée
   visible au-dessus. Ouvrir le tiroir laissait un blanc à la jonction.

   Le sélecteur d'enfant direct règle la question : seule la première ligne de
   la LISTE perd son trait, jamais celle du tiroir. */
.re-postes > .re-p:first-of-type{ border-top:none; }
/* ═══ ET ON LE REMET FRANCHEMENT DANS LE TIROIR ═══

   La règle du dessus suffit en théorie : `>` ne vise que les enfants directs,
   donc la première ligne du tiroir — qui est une petite-fille — garde son
   trait. En théorie.

   En pratique, ce trait a manqué deux fois. Une règle qui repose sur l'ABSENCE
   d'une correspondance est fragile : il suffit qu'un sélecteur voisin change,
   ou qu'une feuille arrive dans un autre ordre, pour qu'elle se remette à
   mordre. Et le défaut est discret — un trait manquant à la jonction, qu'on ne
   voit qu'en ouvrant le tiroir.

   On l'affirme donc au lieu de compter dessus. Deux déclarations pour le même
   résultat, mais la seconde ne peut pas être défaite par accident. */
.re-tiroir-in > .re-p:first-of-type{ border-top:0.5px solid var(--border); }
.re-p b{ color:var(--label-1); font-weight:700; font-variant-numeric:tabular-nums; }
/* « Sans poste » n'est pas un poste, c'est un reste. Grisé pour qu'il se lise
   comme un rappel et non comme une cinquième fonction de l'équipe — mais bien
   présent : sept personnes sans poste, c'est sept fiches à remplir, et c'est la
   seule ligne de cette carte sur laquelle on peut agir aujourd'hui.

   PAS DE GRAISSE. `.re-p b` met le compte en 700 : sur une ligne grise, ça
   donnait un reste plus appuyé que les vrais postes, exactement l'inverse de
   l'intention. Et `nowrap` sur les deux mots, qui n'ont aucune raison de se
   séparer. */
.re-p.vide span,
.re-p.vide b{ color:var(--label-3); font-weight:400; white-space:nowrap; }

/* ═══════════════════════════════════════════════════════════════════════════
   COLLER PLUSIEURS VIDÉOS

   L'outil est SÉPARÉ des trois cartes de mode par un trait, et il ne porte pas
   leur habit. C'est voulu : ce n'est pas une quatrième façon de créer une
   procédure, c'est un préalable qu'on emploie avant d'en créer une. Lui donner
   la même carte l'aurait rangé parmi des choix qui s'excluent, alors qu'il ne
   s'oppose à aucun.
   ═══════════════════════════════════════════════════════════════════════════ */
.outil-sep{
  height:0.5px; background:var(--separator);
  margin:26px 2px 16px;
}
/* Plus sobre que les cartes de mode : pas de fond, un simple contour. Il se
   remarque moins, et c'est le but — on ne le cherche que quand on en a besoin. */
.outil-card{
  background:transparent;
  box-shadow:inset 0 0 0 0.5px var(--border);
}

.coller-item{
  display:flex; align-items:center; gap:8px;
  padding:10px 12px; margin-bottom:8px;
  background:var(--bg-card); border:0.5px solid var(--border); border-radius:14px;
}
.coller-rang{
  flex:0 0 22px; width:22px; height:22px; border-radius:50%;
  background:rgba(255,255,255,0.10); color:var(--label);
  font-size:11.5px; font-weight:700; line-height:22px; text-align:center;
}
/* `min-width:0` : sans lui, un nom de fichier long refuse de se tronquer et
   pousse les trois boutons hors de la carte. Le même piège que sur la grille
   de l'écran de choix. */
.coller-nom{ flex:1 1 auto; min-width:0; display:block; }
.coller-nom .txt{
  display:block; font-size:13px; font-weight:600;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.coller-meta{
  display:block; font-size:11px; color:var(--label-2); margin-top:2px;
  font-variant-numeric:tabular-nums;
}
.coller-fleche{
  flex:0 0 30px; width:30px; height:30px; border-radius:9px;
  background:rgba(255,255,255,0.07); border:none; color:var(--label);
  font-size:14px; line-height:1;
}
.coller-fleche[disabled]{ opacity:0.28; }
.coller-fleche.retirer{ color:var(--red); }

.coller-tot{
  display:flex; align-items:baseline; justify-content:space-between;
  font-size:13px; color:var(--label-2);
  padding:6px 0; border-top:0.5px solid var(--separator);
}
.coller-tot:first-child{ border-top:none; }
.coller-tot b{ color:var(--label); font-weight:700; font-variant-numeric:tabular-nums; }

/* ═══ LE TIROIR DES POSTES ═══

   ANIMER VERS UNE HAUTEUR AUTOMATIQUE N'EST PAS POSSIBLE en CSS : `height:auto`
   n'est pas une valeur qu'on peut interpoler. Les deux contournements habituels
   sont mauvais — un `max-height` généreux fait démarrer l'animation en retard
   et sa durée dépend du nombre de lignes ; mesurer la hauteur en JavaScript
   oblige à recalculer à chaque changement de contenu.

   `grid-template-rows` de `0fr` à `1fr` s'anime, LUI, et donne exactement la
   hauteur du contenu. L'enfant a besoin de `min-height:0` et d'`overflow:hidden`
   pour accepter d'être écrasé — sans ces deux lignes, il garde sa hauteur
   naturelle et le tiroir ne se ferme pas. */
.re-tiroir{
  display:grid; grid-template-rows:0fr;
  transition:grid-template-rows 0.28s cubic-bezier(0.32,0.72,0,1);
}
.re-tiroir.ouvert{ grid-template-rows:1fr; }
.re-tiroir-in{ min-height:0; overflow:hidden; }

/* Le bouton se lit comme une ligne de plus, pas comme une action : il prolonge
   la liste au lieu de s'y opposer. D'où la même hauteur, le même alignement,
   et la couleur secondaire. */
.re-plus{
  display:flex; align-items:center; gap:5px;
  width:100%; padding:8px 0 2px; margin:0;
  background:none; border:none;
  color:var(--label-2); font-size:12.5px; font-weight:600;
  letter-spacing:-0.01em; text-align:left;
}
.re-plus svg{
  width:14px; height:14px; flex:0 0 14px;
  transition:transform 0.28s cubic-bezier(0.32,0.72,0,1);
}
/* Le chevron pointe vers le bas quand il y a à ouvrir, vers le haut quand il y
   a à refermer. C'est le seul indice que le bouton n'est pas un lien. */
.re-plus[aria-expanded="true"] svg{ transform:rotate(180deg); }
.re-plus:active{ opacity:0.6; }


/* ═══ LA ZONE DE TEXTE DU DOCUMENT ═══

   Sa hauteur est pilotée par `ajusterHauteurTexte`, mais le CSS pose le
   plancher et le confort de lecture.

   `min-height` PLUTÔT QUE `rows` : l'attribut fixe une hauteur en lignes que
   le JavaScript doit ensuite écraser, ce qui produit un saut visible au
   premier affichage. Un plancher en pixels ne saute pas.

   `resize:vertical` reste : quelqu'un qui veut voir plus que le plafond peut
   tirer le coin. On ajuste automatiquement, on n'interdit pas. */
#doc-texte{
  /* ═══ `border-box`, SANS QUOI LE PLAFOND EST FAUX ═══

     Les champs de l'app n'ont pas de `box-sizing` déclaré : ils sont donc en
     `content-box`, où la hauteur posée s'AJOUTE au rembourrage et à la bordure.
     Le JavaScript calculait un plafond de 440 px et obtenait une boîte de 466 —
     vingt-cinq de trop, soit exactement les 2 × 12 px de rembourrage et le
     filet.

     Vingt-cinq pixels ne se voient pas sur un champ. Sur un plafond censé
     laisser le bouton visible, ils le repoussent d'autant. */
  box-sizing:border-box;
  min-height:150px;
  line-height:1.55;
  resize:vertical;
  /* Sans transition : la hauteur change à chaque frappe, et l'animer ferait
     traîner le champ derrière le curseur. */
  transition:none;
}
