:root {
    --teal:      #083639;
    --teal-rgb:  8, 54, 57;
    --violet:    #2f0634;
    --violet-rgb:47, 6, 52;
    --encre:     #f2eefb;
    --sourdine:  #a99fc4;

    --teal-bulle-rgb:   77, 110, 112;
    --violet-bulle-rgb: 105, 76, 109;
  }

  * { box-sizing: border-box; }

  /* Couleur de sélection de texte : fond noir presque opaque, texte dans
     le même vert-clair que les chiffres de l'horloge (.segments-actifs). */
  ::selection {
    background: rgba(0, 0, 0, .8);
    color: #cfeadf;
  }
  ::-moz-selection {
    background: rgba(0, 0, 0, .8);
    color: #cfeadf;
  }

  html, body {
    margin: 0;
    height: 100%;
    overflow: hidden;
    font: 15px/1.5 -apple-system, "Segoe UI", Georgia, serif;
    color: var(--encre);
  }

  body {
    background: linear-gradient(135deg, var(--teal) 0%, var(--violet) 100%) #000000;
    position: relative;
  }

  #lueur {
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background:
      radial-gradient(1500px 500px at 50% -10%, #E1A02738, transparent 60%),
      radial-gradient(2000px 500px at 50% 110%, #E1A02738, transparent 40%),
      radial-gradient(900px 600px at 0 110%, #E1A02738, transparent 60%),
      radial-gradient(900px 600px at 100% 110%, #E1A02738, transparent 60%);
  }

  #braises, #galaxie {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
  }
  #braises { z-index: 0; filter: blur(3px); }
  #galaxie { z-index: 1; }

  #etat, #horloge, #local, #bascule, #conversation { z-index: 2; }

  #etat {
    position: fixed;
    top: 1.4rem;
    right: 50%;
    transform: translateX(50%);
    margin: 0;
    font-size: .78rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--sourdine);
    text-align: center;
    pointer-events: none;
    transition: color .3s, right .3s linear, transform .3s linear;
  }

  #horloge {
    position: fixed;
    top: 1.4rem;
    left: calc(1.6rem - 10px);
    margin: 0;
    font-family: 'DSEG7 Classic', 'Courier New', monospace;
    pointer-events: none;
  }

  .cadran {
    position: relative;
    display: block;
    width: max-content;
    white-space: nowrap;
    line-height: 1.15;
  }

  .cadran--heure { font-size: 2.4rem; }

  .ligne-heure {
    display: flex;
    align-items: center;
    gap: .9rem;
  }

  .cadran--date {
    font-family: -apple-system, "Segoe UI", Georgia, serif;
    font-size: .95rem;
    margin-top: .35rem;
    margin-left: 5px;
    min-height: 1.15em;
    letter-spacing: .04em;
    text-transform: uppercase;
  }

  .segments-fond {
    color: rgba(169, 159, 196, .12);
  }

  #deuxpoints {
    animation: clignoter 1s steps(1, end) infinite;
  }
  @keyframes clignoter {
    50%, 100% { opacity: 0; }
  }
  @media (prefers-reduced-motion: reduce) {
    #deuxpoints { animation: none; }
  }

  .segments-actifs {
    position: absolute;
    top: 0;
    left: 0;
    color: #cfeadf;
    text-shadow: 0 0 .35em rgba(126, 224, 201, .55);
  }

  #bloc-indicateurs {
    display: flex;
    flex-direction: column;
    width: fit-content;
    gap: .5rem;
  }

  #indicateurs {
    display: flex;
    align-items: flex-start;
    gap: 1.1rem;
    margin-top: .5rem;
    margin-left: 5px;
  }

  #barre-andromeda {
    width: 100%;
    opacity: 0;
    transition: opacity .4s ease;
  }
  #barre-andromeda.actif { opacity: 1; }

  .barre-andromeda-entete {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: .5rem;
    margin-bottom: .3rem;
    font-family: -apple-system, "Segoe UI", Georgia, serif;
    font-size: .58rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--sourdine);
  }
  .barre-andromeda-valeur {
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    color: var(--encre);
  }
  body.mode-ios .barre-andromeda-entete {
    font-size: .5rem;
  }

  .barre-andromeda-piste {
    width: 100%;
    height: 6px;
    border-radius: 3px;
    background: rgba(169, 159, 196, .15);
    overflow: hidden;
  }
  #barre-andromeda-remplissage {
    height: 100%;
    width: 0%;
    border-radius: 3px;
    background: #7ee0c9;
    transition: width .6s ease, background-color .6s ease;
  }
  #barre-andromeda-remplissage.niveau-moyen { background: #e0b76a; }
  #barre-andromeda-remplissage.niveau-eleve { background: #e37a5e; }

  .jauge-groupe {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .3rem;
  }

  #niveau-voix {
    display: flex;
    align-items: flex-end;
    gap: 3px;
    height: 14px;
    margin-top: 0;
    margin-left: 0;
    opacity: .35;
    transition: opacity .3s ease;
  }
  #niveau-voix.actif { opacity: 1; }

  #niveau-voix span {
    width: 3px;
    min-height: 2px;
    height: calc(var(--hauteur, 0.15) * 100%);
    border-radius: 2px;
    background: var(--sourdine);
    transition: height .08s ease-out, background-color .3s ease;
  }
  #niveau-voix.actif span {
    background: #7ee0c9;
    box-shadow: 0 0 .3em rgba(126, 224, 201, .5);
  }
  @media (prefers-reduced-motion: reduce) {
    #niveau-voix span { transition: background-color .3s ease; }
  }

  .jauge {
    position: relative;
    width: 56px;
    height: 56px;
    opacity: 0;
    transition: opacity .4s ease;
  }
  .jauge.actif { opacity: 1; }

  body.mode-ios .jauge {
    width: 48px;
    height: 48px;
  }

  .jauge svg {
    width: 100%;
    height: 100%;
    transform: rotate(-90deg);
  }
  .jauge circle {
    fill: none;
    stroke-width: 3;
  }
  .jauge .jauge-fond {
    stroke: rgba(169, 159, 196, .15);
  }
  .jauge .jauge-remplissage {
    stroke: #7ee0c9;
    stroke-linecap: round;
    stroke-dasharray: 97.39;
    stroke-dashoffset: 97.39;
    transition: stroke-dashoffset .6s ease, stroke .6s ease;
  }
  .jauge.niveau-moyen .jauge-remplissage  { stroke: #e0b76a; }
  .jauge.niveau-eleve .jauge-remplissage  { stroke: #e37a5e; }

  .jauge-valeur {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: 0;
    color: var(--encre);
  }

  .jauge-etiquette {
    font-family: -apple-system, "Segoe UI", Georgia, serif;
    font-size: .62rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--sourdine);
  }
  body.mode-ios .jauge-etiquette {
    font-size: .52rem;
  }

  #bascule {
    position: fixed;
    left: 1.6rem;
    bottom: 1.6rem;
    width: 3.6rem;
    height: 3.6rem;
    border-radius: 50%;
    /* État "muet" (par défaut) : bordure du même rouge que l'icône. */
    border: 1px solid rgba(227,122,94,.4);
    background: rgba(255,255,255,.05);
    backdrop-filter: blur(6px);
    color: var(--encre);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
    touch-action: none;
    /* Pas d'animation de taille/position (comme les deux autres boutons) :
       seuls les changements d'état (fond, bordure, halo) sont transitionnés. */
    transition: background .2s, border-color .2s, box-shadow .3s;
  }
  #bascule svg {
    width: 1.5rem;
    height: 1.5rem;
    /* Icône "muet" (état par défaut, micro barré) : rouge, pleine
       opacité. L'icône "écoute" (voir .actif plus bas) reste verte,
       également en pleine opacité — inchangée. */
    color: #e37a5e;
    transition: color .2s;
  }
  #bascule:hover { border-color: rgba(227,122,94,.7); }
  #bascule:focus-visible { outline: 2px solid var(--encre); outline-offset: 3px; }
  #bascule.actif {
    border-color: #7ee0c9;
    box-shadow: 0 0 1.4rem rgba(126,224,201,.35);
  }
  #bascule.actif svg { color: #7ee0c9; }
  /* Mode iOS (push-to-talk) uniquement : seulement deux états, blanc/crème
     au repos (avec ou sans autorisation micro) et vert pendant l'appui —
     jamais de rouge/barré ici (voir configurerPourIOS() dans app.js, qui
     force l'icône pleine dès l'activation du mode iOS). Le contour reste
     le même gris/blanc translucide que ses deux voisins (pas de rouge),
     sauf pendant l'appui où il repasse au vert. Chaque règle .actif est
     répétée ici avec une spécificité plus élevée pour gagner sur l'état
     "au repos" ci-dessus quand les deux s'appliquent à la fois. */
  body.mode-ios #bascule {
    border-color: rgba(242,238,251,.25);
  }
  body.mode-ios #bascule:hover {
    border-color: rgba(242,238,251,.5);
  }
  body.mode-ios #bascule svg {
    color: var(--encre);
  }
  body.mode-ios #bascule.actif {
    border-color: #7ee0c9;
  }
  body.mode-ios #bascule.actif svg {
    color: #7ee0c9;
  }

  #ouvrir-fichiers-bouton,
  #chat-bouton {
    position: fixed;
    bottom: 1.6rem;
    width: 3.6rem;
    height: 3.6rem;
    z-index: 2;
    border-radius: 50%;
    border: 1px solid rgba(242,238,251,.25);
    background: rgba(255,255,255,.05);
    backdrop-filter: blur(6px);
    color: var(--encre);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    -webkit-user-select: none;
    user-select: none;
    transition: background .2s, border-color .2s, opacity .3s ease, transform .3s ease;
  }
  /* Sur bureau, les trois boutons sont alignés sur une même colonne à
     gauche, empilés de bas en haut : toggle voix, explorateur, chat. La
     vue réduite et le mode iOS gardent leur propre positionnement
     (déclaré plus bas) et restent inchangés. */
  #ouvrir-fichiers-bouton {
    left: 1.6rem;
    bottom: 6.2rem;
  }
  #chat-bouton {
    left: 1.6rem;
    bottom: 10.8rem;
  }
  #ouvrir-fichiers-bouton svg,
  #chat-bouton svg {
    width: 1.5rem;
    height: 1.5rem;
  }
  #ouvrir-fichiers-bouton:hover,
  #chat-bouton:hover {
    border-color: rgba(242,238,251,.5);
  }
  #ouvrir-fichiers-bouton:focus-visible,
  #chat-bouton:focus-visible {
    outline: 2px solid var(--encre);
    outline-offset: 3px;
  }

  #local {
    display: none;

    position: fixed;
    left: 1.6rem;
    bottom: 5.6rem;
    font-size: .72rem;
    letter-spacing: .04em;
    color: var(--sourdine);
    background: none;
    border: none;
    cursor: pointer;
    padding: .2rem 0;
    opacity: .75;
    transition: opacity .2s, color .2s;
  }
  #local:hover { opacity: 1; }
  #local.actif { color: #7ee0c9; opacity: 1; }
  #local[disabled] { opacity: .35; cursor: default; }

  /* Nombre (0 → 1) piloté par .pas-en-bas sur #conversation, utilisé dans
     ses dégradés de masque pour faire apparaître/disparaître en douceur le
     fondu du bas (voir #conversation plus bas) : sans ce @property, une
     custom property ne s'anime pas, elle bascule net. */
  @property --bas-fondu-force {
    syntax: '<number>';
    inherits: false;
    initial-value: 0;
  }

  #conversation {
    position: fixed;
    right: 1.4rem;
    /* Démarre sous l'horloge et les jauges disque/ram/cpu (#horloge), pas
       depuis le tout haut de l'écran : #conversation ne peut ainsi plus
       géométriquement chevaucher les indicateurs, quelle que soit la
       hauteur du fondu ci-dessous (avant, avec top:0, seul le masque
       cachait les bulles qui montaient jusque-là — ça ne cachait bien que
       si le fondu était pile assez grand, ce qui a causé les allers-retours
       précédents). */
    top: 5rem;
    bottom: 0;
    padding-bottom: 1.6rem;
    width: min(20rem, calc(100vw - 3rem));
    display: flex;
    /* column-reverse (plutôt que column + justify-content:flex-end) : avec
       flex-end, le contenu qui déborde au-delà du haut du conteneur devient
       inatteignable au scroll (bug connu de flexbox, le scroll ne peut pas
       aller "en négatif"). En column-reverse, le début de l'axe principal
       est en bas, donc les bulles s'y collent naturellement quand il y en a
       peu, ET le débordement se fait dans le sens normal du scroll,
       parfaitement atteignable. Voir ajouterBulle() dans app.js, qui insère
       chaque nouvelle bulle en premier enfant pour que l'ordre visuel reste
       correct avec column-reverse. */
    flex-direction: column-reverse;
    gap: .55rem;
    padding-top: 15vh;
    overflow-y: auto;
    overflow-x: hidden;
    /* Défilable pour remonter voir les anciennes bulles, mais sans jamais
       afficher de scrollbar. */
    scrollbar-width: none;
    -ms-overflow-style: none;
    -webkit-overflow-scrolling: touch;
    /* Cliquable/défilable sur toute sa surface (nécessaire sur iOS : au
       toucher, un ancêtre pointer-events:none empêche le défilement même
       si l'élément touché est lui-même pointer-events:auto — contrairement
       à la souris/molette sur desktop qui s'en accommodait). Le seul
       élément recouvert est #etat, un simple texte sans interaction, donc
       aucune perte fonctionnelle. */
    pointer-events: auto;
    /* --bas-fondu-force (0 → 1, voir @property plus haut) contrôle
       l'opacité du point de départ (0%, le bas) du masque : à 0, ce point
       est noir plein (aucun effet, comme avant .pas-en-bas) ; à 1, il est
       transparent (fondu visible sur les 5 premiers %). Comme c'est une
       propriété animable (via @property), la transition ci-dessous fait
       apparaître/disparaître ce fondu en douceur au lieu d'un bascule net. */
    -webkit-mask-image: linear-gradient(to top, rgba(0, 0, 0, calc(1 - var(--bas-fondu-force))) 0%, black 5%, black 60%, transparent 85%);
            mask-image: linear-gradient(to top, rgba(0, 0, 0, calc(1 - var(--bas-fondu-force))) 0%, black 5%, black 60%, transparent 85%);
    /* Fine bordure en bas, invisible par défaut : n'apparaît que via
       .pas-en-bas (posée par app.js quand on n'est pas au dernier message),
       pour indiquer qu'il y a du contenu plus récent sous le défilement. */
    border-bottom: 1px solid transparent;
    --bas-fondu-force: 0;
    /* Transition douce sur top/padding/masque/bordure quand on passe le
       seuil de 700px (redimensionnement de la fenêtre), ou que
       .pas-en-bas s'active/se désactive. */
    transition: top .3s ease, padding-top .3s ease, border-color .35s ease,
      --bas-fondu-force .35s ease,
      -webkit-mask-image .3s ease, mask-image .3s ease;
  }
  /* Pas tout en bas du défilement (posé par app.js) : fine bordure claire +
     léger fondu supplémentaire tout en bas, en plus du fondu du haut déjà
     en place, pour signaler qu'il y a des messages plus récents en dessous.
     Transition douce grâce à --bas-fondu-force (voir ci-dessus). */
  #conversation.pas-en-bas {
    border-bottom-color: rgba(242, 238, 251, .3);
    --bas-fondu-force: 1;
  }
  #conversation::-webkit-scrollbar {
    display: none;
  }
  /* Vue desktop pleine (fenêtre large, >700px, hors iOS) uniquement :
     #conversation est étroit et collé à droite, l'horloge/les jauges sont
     en haut à gauche — aucun chevauchement horizontal possible ici, donc
     pas besoin de marge en haut : les messages peuvent remonter jusqu'en
     haut de la fenêtre. Un fondu léger reste présent (sur les derniers 8%
     du haut, contre 25% ailleurs) pour que les bulles apparaissent
     progressivement plutôt que de couper net. (Sans effet sur la vue
     réduite en dessous de 700px, ni sur iOS : body.mode-ios #conversation
     reste prioritaire grâce à sa spécificité plus élevée, même sur un iPad
     large.) */
  @media (min-width: 701px) {
    #conversation {
      top: 0;
      /* Symétrique au padding-bottom (1.6rem) de la règle de base. */
      padding-top: 1.6rem;
      -webkit-mask-image: linear-gradient(to top, rgba(0, 0, 0, calc(1 - var(--bas-fondu-force))) 0%, black 5%, black 92%, transparent 100%);
              mask-image: linear-gradient(to top, rgba(0, 0, 0, calc(1 - var(--bas-fondu-force))) 0%, black 5%, black 92%, transparent 100%);
    }
  }

  .bulle {
    max-width: 88%;
    padding: .6rem .85rem;
    border-radius: 1.1rem;
    font-size: .88rem;
    line-height: 1.4;
    backdrop-filter: blur(18px) saturate(1.3);
    -webkit-backdrop-filter: blur(18px) saturate(1.3);
    box-shadow: 0 2px 14px rgba(0,0,0,.35);
    animation: apparition .35s ease-out;
    word-wrap: break-word;
    flex: none;
    -webkit-user-select: text;
    user-select: text;
    /* Autorise le geste de défilement vertical natif (au lieu d'un
       défilement horizontal ambigu) sans empêcher l'appui long pour
       sélectionner le texte. */
    touch-action: pan-y;
  }

  @keyframes apparition {
    from { opacity: 0; transform: translateY(.5rem); }
    to   { opacity: 1; transform: translateY(0); }
  }

  .bulle.vous {
    align-self: flex-end;
    background: rgba(var(--teal-bulle-rgb), .88);
    border: 1px solid rgba(126,224,201,.4);
    border-bottom-right-radius: .3rem;
  }
  .bulle.vous::first-letter {
    text-transform: uppercase;
  }

  .bulle.guideon {
    align-self: flex-start;
    background: rgba(var(--violet-bulle-rgb), .88);
    border: 1px solid rgba(220,170,255,.35);
    border-bottom-left-radius: .3rem;
  }

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

  @media (max-width: 700px) {
    #etat {
      right: 1.4rem;
      transform: translateX(0);
      text-align: right;
    }

    /* Même disposition qu'en vue bureau : les trois boutons alignés en
       colonne à gauche (de bas en haut : toggle voix, explorateur, chat),
       juste avec les tailles/tarifs déjà en place pour cette largeur. */
    #bascule {
      width: 2.6rem;
      height: 2.6rem;
      left: .9rem;
      bottom: .9rem;
    }
    #bascule svg {
      width: 1.15rem;
      height: 1.15rem;
      transform: translate(1px, 1px);
    }

    #ouvrir-fichiers-bouton,
    #chat-bouton {
      left: .9rem;
      width: 2.6rem;
      height: 2.6rem;
    }
    #ouvrir-fichiers-bouton {
      bottom: 4.1rem;
    }
    #chat-bouton {
      bottom: 7.3rem;
    }
    #ouvrir-fichiers-bouton svg,
    #chat-bouton svg {
      width: 1.15rem;
      height: 1.15rem;
    }

    #lueur {
      display: none;
    }
  }

  body.mode-ios {
    --ios-bouton-bas:   calc(2.6rem - 10px);
    --ios-bouton-taille: 5.4rem;
  }

  body.mode-ios #lueur {
    display: none;
  }

  body.mode-ios #bascule {
    left: 50%;
    top: auto;
    bottom: var(--ios-bouton-bas);
    transform: translateX(-50%);
    width: var(--ios-bouton-taille);
    height: var(--ios-bouton-taille);
  }
  body.mode-ios #bascule svg {
    width: 2.3rem;
    height: 2.3rem;
    transform: none;
  }

  body.mode-ios #ouvrir-fichiers-bouton,
  body.mode-ios #chat-bouton {
    bottom: var(--ios-bouton-bas);
    /* Environ 3/4 de la taille du bouton "push to talk" (--ios-bouton-taille
       reste inchangée : elle sert aussi au calcul de bottom ci-dessous pour
       #conversation, basé sur la hauteur du bouton central). */
    width: 4.05rem;
    height: 4.05rem;
  }
  /* Explorateur en coin bas-gauche et chat en coin bas-droite, avec la
     même marge que --ios-bouton-bas des deux côtés (gauche/bas pour l'un,
     droite/bas pour l'autre) : coins symétriques, indépendants du bouton
     central (bascule) qui reste centré et inchangé. */
  body.mode-ios #ouvrir-fichiers-bouton {
    left: var(--ios-bouton-bas);
    right: auto;
  }
  body.mode-ios #chat-bouton {
    right: var(--ios-bouton-bas);
    left: auto;
  }
  body.mode-ios #ouvrir-fichiers-bouton svg,
  body.mode-ios #chat-bouton svg {
    width: 1.7rem;
    height: 1.7rem;
  }

  body.mode-ios #conversation {
    left: 0;
    right: 0;
    width: auto;
    /* Même raison qu'en desktop : sous l'horloge/les jauges, pas depuis le
       haut de l'écran, pour que #conversation ne les chevauche plus du
       tout géométriquement. Valeur augmentée (10rem -> 12rem) pour laisser
       la place à la barre Andromeda ajoutée sous les jauges. */
    top: 12rem;
    /* Zone légèrement plus basse qu'avant (1rem de moins ici), compensée
       par le padding-bottom ci-dessous pour que les bulles restent à peu
       près à la même hauteur visuelle malgré tout. */
    bottom: calc(var(--ios-bouton-bas) + var(--ios-bouton-taille) + 1rem + 10px - 1rem);
    /* #conversation démarre déjà sous l'horloge/les jauges (top:10rem
       ci-dessus), donc plus besoin d'une grosse marge de sécurité ici. */
    padding: 4rem 1.2rem 1rem;
    -webkit-mask-image: linear-gradient(to top, rgba(0, 0, 0, calc(1 - var(--bas-fondu-force))) 0%, black 5%, black 78%, transparent 96%);
            mask-image: linear-gradient(to top, rgba(0, 0, 0, calc(1 - var(--bas-fondu-force))) 0%, black 5%, black 78%, transparent 96%);
  }
  body.mode-ios .bulle {
    max-width: min(26rem, 85%);
  }

  #poignee-deconnexion {
    display: none;
  }
  body.mode-ios:not(.verrouille) #poignee-deconnexion {
    display: block;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 26px;
    z-index: 5;
    touch-action: none;
  }

  #volet-deconnexion {
    display: none;
  }
  body.mode-ios:not(.verrouille) #volet-deconnexion {
    display: flex;
    justify-content: center;
    align-items: center;
    position: fixed;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: min(94vw, 400px);
    height: 0;
    overflow: hidden;
    background: rgba(10, 8, 16, .82);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border-radius: 0 0 28px 28px;
    z-index: 4;
    pointer-events: none;
  }

  #bouton-deconnexion-volet {
    width: 4.2rem;
    height: 4.2rem;
    border-radius: 50%;
    border: none;
    background: #e74c3c;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transform: scale(0);
    box-shadow: 0 4px 18px rgba(231, 76, 60, .45);
    pointer-events: none;
  }

  @keyframes rebondBoutonVolet {
    0%   { transform: scale(1); }
    40%  { transform: scale(1.22); }
    70%  { transform: scale(.92); }
    100% { transform: scale(1); }
  }
  #bouton-deconnexion-volet.rebond {
    animation: rebondBoutonVolet .4s ease-out;
  }
  @media (prefers-reduced-motion: reduce) {
    #bouton-deconnexion-volet.rebond { animation: none; }
  }

  #poignee-fermeture-volet {
    position: absolute;
    bottom: .9rem;
    left: 50%;
    transform: translateX(-50%);
    width: 2.6rem;
    height: 4px;
    border-radius: 2px;
    background: rgba(255, 255, 255, .55);
    opacity: 0;
    transition: opacity .3s ease;
  }
  #volet-deconnexion.ouvert #poignee-fermeture-volet {
    opacity: 1;
  }

  /* ===== Dépôt de fichiers (drag & drop) ===== */

  #overlay-televersement {
    position: fixed;
    inset: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(8, 10, 14, .55);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s ease;
  }
  #overlay-televersement.actif {
    opacity: 1;
    pointer-events: auto;
  }

  #overlay-televersement-contenu {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    padding: 3rem 4rem;
    border: 2px dashed rgba(126, 224, 201, .55);
    border-radius: 1.6rem;
    color: var(--encre);
    background: rgba(var(--teal-rgb), .25);
    transform: scale(.94);
    transition: transform .25s cubic-bezier(.34, 1.45, .64, 1);
  }
  #overlay-televersement.actif #overlay-televersement-contenu {
    transform: scale(1);
    animation: respirationDepot 1.8s ease-in-out infinite;
  }
  #overlay-televersement-contenu svg {
    color: #7ee0c9;
    filter: drop-shadow(0 0 .6em rgba(126, 224, 201, .5));
    animation: rebondFleche 1.4s ease-in-out infinite;
  }
  #overlay-televersement-contenu span {
    font-size: 1.05rem;
    letter-spacing: .03em;
    text-align: center;
  }

  @keyframes respirationDepot {
    0%, 100% { border-color: rgba(126, 224, 201, .55); }
    50%      { border-color: rgba(126, 224, 201, .95); }
  }
  @keyframes rebondFleche {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-6px); }
  }
  @media (prefers-reduced-motion: reduce) {
    #overlay-televersement-contenu,
    #overlay-televersement-contenu svg { animation: none; }
  }

  body.mode-ios #overlay-televersement,
  body.verrouille #overlay-televersement,
  body.verrouille #gestionnaire-fichiers,
  body.verrouille #apercu-fichier,
  body.verrouille #chat-popup {
    display: none;
  }

  /* #ouvrir-fichiers-bouton, #chat-bouton et #bascule restent dans le flux
     (display:none ne peut pas s'animer) : au verrouillage, ils disparaissent
     via un fondu opacity/transform synchronisé, comme #horloge/#etat/#local/
     #conversation dans login.css. */
  body.verrouille #ouvrir-fichiers-bouton,
  body.verrouille #chat-bouton,
  body.verrouille #bascule {
    opacity: 0;
    transform: scale(.85);
    pointer-events: none;
  }

  /* ===== Gestionnaire de fichiers ===== */

  #gestionnaire-fichiers {
    position: fixed;
    inset: 0;
    z-index: 15;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(8, 10, 14, .5);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s ease;
  }
  #gestionnaire-fichiers.ouvert {
    opacity: 1;
    pointer-events: auto;
  }

  /* Système "verre" sombre façon Finder (dark mode), partagé par les deux
     fenêtres fichiers. Les teintes d'accent reprennent celles déjà
     utilisées par les jauges (Disque/RAM/CPU) pour garder une identité
     visuelle unique, et tout reste en transparence légère pour l'effet
     vitre dépoli. */
  #gestionnaire-fenetre,
  #apercu-fenetre,
  #chat-fenetre {
    --verre-fond:        rgba(30, 30, 33, .5);
    --verre-fond-teinte: rgba(20, 20, 23, .4);
    --verre-bordure:     rgba(255, 255, 255, .12);
    --verre-texte:       rgba(245, 245, 247, .92);
    --verre-sourdine:    rgba(235, 235, 245, .55);
    --verre-accent:      126, 224, 201;
    --verre-accent-2:    224, 183, 106;
    --verre-danger:      227, 122, 94;

    --tag-rouge:  #ff453a;
    --tag-orange: #ff9f0a;
    --tag-jaune:  #ffd60a;
    --tag-vert:   #32d74b;
    --tag-bleu:   #0a84ff;
    --tag-violet: #bf5af2;
  }

  #gestionnaire-fenetre {
    width: min(52rem, 92vw);
    height: min(36rem, 84vh);
    display: flex;
    flex-direction: column;
    border-radius: 1rem;
    overflow: hidden;
    border: 1px solid var(--verre-bordure);
    background: var(--verre-fond-teinte);
    backdrop-filter: blur(34px) saturate(180%);
    -webkit-backdrop-filter: blur(34px) saturate(180%);
    box-shadow: 0 20px 60px rgba(0, 0, 0, .55), inset 0 1px 0 rgba(255, 255, 255, .07);
    transform: scale(.92) translateY(10px);
    transition: transform .3s cubic-bezier(.34, 1.45, .64, 1), width .3s ease, height .3s ease, border-radius .3s ease;
  }
  #gestionnaire-fenetre.plein-ecran {
    width: 100vw;
    height: 100vh;
    border-radius: 0;
  }
  #gestionnaire-fichiers.ouvert #gestionnaire-fenetre {
    transform: scale(1) translateY(0);
  }

  #gestionnaire-entete {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: .65rem 1rem;
    border-bottom: 1px solid rgba(0, 0, 0, .07);
    background: var(--verre-fond);
  }
  #gestionnaire-feux {
    position: absolute;
    left: .9rem;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    gap: .45rem;
  }
  .feu {
    width: .7rem;
    height: .7rem;
    padding: 0;
    border: none;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: default;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .06);
    transition: filter .15s ease, transform .15s ease, width .2s ease, height .2s ease, background .2s ease;
  }
  .feu svg {
    display: none;
  }
  .feu-rouge {
    background: rgba(var(--verre-danger), .85);
    cursor: pointer;
  }
  .feu-jaune {
    background: rgba(var(--verre-accent-2), .85);
    cursor: pointer;
  }
  .feu-verte {
    background: rgba(var(--verre-accent), .85);
    cursor: pointer;
  }
  .feu-rouge:hover,
  .feu-jaune:hover,
  .feu-verte:hover {
    filter: brightness(1.12);
    transform: scale(1.08);
  }

  #gestionnaire-titre {
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .01em;
    color: var(--verre-texte);
  }

  /* Bouton "Partager" : import depuis la pellicule, iOS uniquement (pas de
     glisser-déposer possible sur iOS). Masqué par défaut, positionné et
     affiché seulement en body.mode-ios, juste à gauche du bouton de
     fermeture. */
  #gestionnaire-partager {
    display: none;
  }

  #apercu-fermer {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.7rem;
    height: 1.7rem;
    flex: none;
    border-radius: 50%;
    border: 1px solid var(--verre-bordure);
    background: rgba(255, 255, 255, .1);
    color: var(--verre-texte);
    cursor: pointer;
    transition: background .2s, border-color .2s, transform .25s;
  }
  #apercu-fermer:hover {
    background: rgba(255, 255, 255, .2);
    transform: rotate(90deg);
  }

  #gestionnaire-corps {
    position: relative;
    flex: 1;
    display: flex;
    overflow: hidden;
  }

  #gestionnaire-barre-laterale {
    width: 11.5rem;
    flex: none;
    display: flex;
    flex-direction: column;
    gap: .1rem;
    padding: .9rem .6rem;
    background: var(--verre-fond);
    border-right: 1px solid var(--verre-bordure);
    overflow-y: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  #gestionnaire-barre-laterale::-webkit-scrollbar {
    display: none;
  }
  /* Sur bureau, ces deux groupes sont invisibles à la mise en page : leurs
     boutons s'écoulent directement dans la colonne de la barre latérale,
     exactement comme avant. En vue réduite/iOS, ils redeviennent deux
     vraies barres positionnées indépendamment (voir plus bas). */
  #gestionnaire-filtres-groupe,
  #gestionnaire-tags-groupe {
    display: contents;
  }
  .gestionnaire-section-titre {
    padding: .3rem .5rem .45rem;
    font-size: .66rem;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--verre-sourdine);
  }
  .gestionnaire-filtre {
    display: flex;
    align-items: center;
    gap: .55rem;
    padding: .4rem .55rem;
    border: none;
    border-radius: .5rem;
    background: transparent;
    color: var(--verre-texte);
    font: inherit;
    font-size: .82rem;
    text-align: left;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
  }
  .gestionnaire-filtre svg {
    width: 15px;
    height: 15px;
    flex: none;
    color: var(--verre-sourdine);
    transition: color .15s ease;
  }
  .gestionnaire-filtre:hover {
    background: rgba(255, 255, 255, .1);
  }
  .gestionnaire-filtre.actif {
    background: rgba(126, 224, 201, .18);
    color: rgb(126, 224, 201);
  }
  .gestionnaire-filtre.actif:hover {
    background: rgba(126, 224, 201, .26);
  }
  .gestionnaire-filtre.actif svg {
    color: rgb(126, 224, 201);
  }

  .gestionnaire-tag {
    display: flex;
    align-items: center;
    gap: .55rem;
    padding: .4rem .55rem;
    border: none;
    border-radius: .5rem;
    background: transparent;
    color: var(--verre-texte);
    font: inherit;
    font-size: .82rem;
    text-align: left;
    cursor: pointer;
    transition: background .15s ease;
  }
  .gestionnaire-tag:hover {
    background: rgba(255, 255, 255, .1);
  }
  .gestionnaire-tag.actif {
    background: rgba(255, 255, 255, .16);
  }

  .tag-pastille {
    display: inline-block;
    width: 13px;
    height: 13px;
    border-radius: 50%;
    flex: none;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .18);
  }
  .tag-pastille--tous {
    background: transparent;
    box-shadow: inset 0 0 0 1.5px var(--verre-sourdine);
  }
  .tag-pastille[data-couleur="rouge"]  { background: var(--tag-rouge); }
  .tag-pastille[data-couleur="orange"] { background: var(--tag-orange); }
  .tag-pastille[data-couleur="jaune"]  { background: var(--tag-jaune); }
  .tag-pastille[data-couleur="vert"]   { background: var(--tag-vert); }
  .tag-pastille[data-couleur="bleu"]   { background: var(--tag-bleu); }
  .tag-pastille[data-couleur="violet"] { background: var(--tag-violet); }

  #gestionnaire-principal {
    position: relative;
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
    padding: 1.2rem;
    background: var(--verre-fond-teinte);
  }
  #gestionnaire-principal::-webkit-scrollbar {
    display: none;
  }
  #gestionnaire-grille,
  #gestionnaire-chargement {
    flex: 0 0 auto;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
    gap: 1.3rem .6rem;
  }
  #gestionnaire-vide,
  #gestionnaire-chargement,
  #gestionnaire-compte {
    display: none;
    text-align: center;
    color: var(--verre-sourdine);
  }
  #gestionnaire-compte {
    /* margin-top: auto le colle en bas de #gestionnaire-principal tant que
       la grille ne remplit pas tout l'espace ; s'il y a débordement, la
       marge auto n'a plus de place à absorber et il redescend simplement
       juste sous la grille, avec le padding-top comme espacement minimal. */
    margin-top: auto;
    padding-top: 1rem;
    font-size: .8rem;
  }
  #gestionnaire-fichiers:not(.vide):not(.chargement) #gestionnaire-compte {
    display: block;
  }
  #gestionnaire-vide {
    flex-direction: column;
    align-items: center;
    gap: .6rem;
    font-size: 1.1rem;
  }
  #gestionnaire-vide svg {
    width: 2.6rem;
    height: 2.6rem;
    color: var(--verre-sourdine);
  }
  #gestionnaire-fichiers.vide #gestionnaire-vide {
    display: flex;
  }
  /* Centre #gestionnaire-vide dans l'espace libre de #gestionnaire-principal
     (entre la barre de tags et le dock du bas), au lieu de le laisser
     collé en haut avec une simple marge. */
  #gestionnaire-fichiers.vide #gestionnaire-principal {
    display: flex;
    align-items: center;
    justify-content: center;
  }
  /* #gestionnaire-grille (vide mais toujours présent dans le DOM) peut
     malgré tout occuper une largeur via son grid-template-columns en
     auto-fill, ce qui décentrait horizontalement #gestionnaire-vide à côté
     de lui : on le retire complètement de la mise en page ici. */
  #gestionnaire-fichiers.vide #gestionnaire-grille {
    display: none;
  }
  #gestionnaire-fichiers.chargement #gestionnaire-chargement {
    display: grid;
  }

  /* ===== Icônes de fichiers ===== */

  .fichier-item {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: .4rem;
    border-radius: .6rem;
    cursor: pointer;
    animation: apparitionFichier .3s ease-out backwards;
    transition: background .15s ease;
  }
  .fichier-item:hover {
    background: rgba(255, 255, 255, .1);
  }
  @keyframes apparitionFichier {
    from { opacity: 0; transform: translateY(.4rem) scale(.94); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
  }
  .fichier-item.suppression {
    animation: disparitionFichier .25s ease forwards;
  }
  @keyframes disparitionFichier {
    to { opacity: 0; transform: scale(.85); }
  }
  @media (prefers-reduced-motion: reduce) {
    .fichier-item { animation: none; }
  }

  .fichier-vignette {
    position: relative;
    width: 76px;
    height: 76px;
    border-radius: .65rem;
    overflow: hidden;
    background: rgba(0, 0, 0, 0.3);
    border: 1px solid rgba(0, 0, 0, .08);
    box-shadow: 0 1px 3px rgba(0, 0, 0, .08);
    transition: transform .2s ease, box-shadow .2s ease;
  }
  .fichier-item:hover .fichier-vignette {
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(0, 0, 0, .16);
  }
  .fichier-vignette img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }

  .fichier-icone {
    position: relative;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    background: linear-gradient(180deg, rgba(255, 255, 255, .5) 0%, rgba(241, 241, 244, .3) 100%);
  }
  .fichier-icone::before {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 0 16px 16px 0;
    border-color: transparent rgba(0, 0, 0, .1) transparent transparent;
  }
  .fichier-icone::after {
    content: '';
    position: absolute;
    top: 14px;
    left: 14px;
    right: 20px;
    height: 30px;
    background-image: repeating-linear-gradient(to bottom, rgba(0, 0, 0, .12) 0, rgba(0, 0, 0, .12) 2px, transparent 2px, transparent 7px);
  }
  .fichier-icone span {
    position: relative;
    font-size: .58rem;
    font-weight: 700;
    letter-spacing: .02em;
    color: var(--verre-sourdine);
    text-transform: uppercase;
    padding: 3px 6px 6px;
    text-align: center;
    word-break: break-all;
  }

  .fichier-nom {
    margin-top: .45rem;
    max-width: 88px;
    font-size: .74rem;
    line-height: 1.25;
    color: var(--verre-texte);
    text-align: center;
    display: -webkit-box;
    line-clamp: 2;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    word-break: break-word;
  }

  /* Squelette de chargement : tuiles vides scintillantes affichées à la
     place du texte "Chargement…", le temps que la liste des fichiers
     arrive du serveur. Mêmes dimensions que .fichier-vignette/.fichier-nom
     pour que la grille ne "saute" pas quand les vraies tuiles apparaissent. */
  .fichier-squelette {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: .4rem;
  }
  .fichier-squelette-vignette,
  .fichier-squelette-nom {
    border-radius: .5rem;
    background: linear-gradient(90deg, rgba(255, 255, 255, .06) 25%, rgba(255, 255, 255, .16) 50%, rgba(255, 255, 255, .06) 75%);
    background-size: 200% 100%;
    animation: scintillementSquelette 1.6s ease-in-out infinite;
  }
  .fichier-squelette-vignette {
    width: 76px;
    height: 76px;
    border-radius: .65rem;
  }
  .fichier-squelette-nom {
    margin-top: .55rem;
    width: 60px;
    height: .6rem;
  }
  @keyframes scintillementSquelette {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
  }
  @media (prefers-reduced-motion: reduce) {
    .fichier-squelette-vignette,
    .fichier-squelette-nom {
      animation: none;
    }
  }

  /* ===== Popup d'aperçu ===== */

  #apercu-fichier {
    position: fixed;
    inset: 0;
    z-index: 25;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(4, 5, 8, .68);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s ease;
  }
  #apercu-fichier.ouvert {
    opacity: 1;
    pointer-events: auto;
  }

  #apercu-fenetre {
    position: relative;
    width: min(30rem, 90vw);
    max-height: 86vh;
    display: flex;
    flex-direction: column;
    border-radius: 1rem;
    overflow: hidden;
    border: 1px solid var(--verre-bordure);
    background: var(--verre-fond-teinte);
    backdrop-filter: blur(34px) saturate(180%);
    -webkit-backdrop-filter: blur(34px) saturate(180%);
    box-shadow: 0 20px 60px rgba(0, 0, 0, .6), inset 0 1px 0 rgba(255, 255, 255, .07);
    transform: scale(.9);
    transition: transform .3s cubic-bezier(.34, 1.45, .64, 1);
  }
  #apercu-fichier.ouvert #apercu-fenetre {
    transform: scale(1);
  }

  #apercu-fermer {
    position: absolute;
    top: .7rem;
    right: .7rem;
    z-index: 1;
  }

  #apercu-media {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 10rem;
    max-height: 56vh;
    background: rgba(0, 0, 0, .05);
    overflow: hidden;
  }
  #apercu-media img {
    max-width: 100%;
    max-height: 56vh;
    object-fit: contain;
    display: block;
  }
  #apercu-media .fichier-icone {
    width: 8rem;
    height: 8rem;
    border-radius: .9rem;
    margin: 2.4rem 0;
  }
  #apercu-media .fichier-icone::before {
    border-width: 0 26px 26px 0;
  }
  #apercu-media .fichier-icone::after {
    top: 22px;
    left: 22px;
    right: 30px;
    height: 46px;
    background-image: repeating-linear-gradient(to bottom, rgba(0, 0, 0, .12) 0, rgba(0, 0, 0, .12) 3px, transparent 3px, transparent 10px);
  }
  #apercu-media .fichier-icone span {
    font-size: .95rem;
  }

  #apercu-bas {
    padding: 1rem 1.2rem 1.2rem;
    display: flex;
    flex-direction: column;
    gap: .8rem;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(255, 255, 255, 0.05);
  }
  #apercu-nom {
    font-size: .92rem;
    font-weight: 600;
    color: var(--verre-texte);
    line-height: 1.3;
    word-break: break-word;
  }
  #apercu-infos {
    display: flex;
    gap: .9rem;
    font-size: .78rem;
    color: var(--verre-sourdine);
  }

  #apercu-actions {
    display: flex;
    gap: .6rem;
    flex-wrap: wrap;
  }
  .apercu-bouton {
    flex: 1;
    min-width: 6rem;
    text-align: center;
    padding: .55rem .8rem;
    border-radius: .6rem;
    border: none;
    background: rgba(255, 255, 255, .1);
    color: rgba(245, 245, 247, .7);
    font: inherit;
    font-size: .82rem;
    text-decoration: none;
    cursor: pointer;
    transition: background .2s, color .2s, transform .15s;
  }
  .apercu-bouton:hover {
    background: rgba(255, 255, 255, .18);
    color: rgba(245, 245, 247, .95);
  }
  .apercu-bouton:active {
    transform: scale(.96);
    background: rgba(255, 255, 255, .24);
  }
  .apercu-bouton--danger {
    background: rgba(var(--verre-danger), .18);
    color: rgba(255, 255, 255, .85);
  }
  .apercu-bouton--danger:hover {
    background: rgba(var(--verre-danger), .34);
    color: rgba(255, 255, 255, .98);
  }
  .apercu-bouton--danger.confirmation {
    background: rgba(var(--verre-danger), .35);
    border-color: rgba(var(--verre-danger), .8);
    color: rgba(255, 255, 255, .96);
    animation: pulsationDanger 1s ease-in-out infinite;
  }
  @keyframes pulsationDanger {
    0%, 100% { box-shadow: 0 0 0 rgba(227, 122, 94, 0); }
    50%      { box-shadow: 0 0 .8em rgba(227, 122, 94, .45); }
  }
  @media (prefers-reduced-motion: reduce) {
    .apercu-bouton--danger.confirmation { animation: none; }
  }
  .apercu-bouton--accent {
    border-color: rgba(var(--verre-accent), .35);
    background: rgba(var(--verre-accent), .18);
    color: rgb(var(--verre-accent));
    font-weight: 600;
  }
  .apercu-bouton--accent:hover {
    border-color: rgba(var(--verre-accent), .6);
    background: rgba(var(--verre-accent), .28);
  }
  #chat-envoyer {
    opacity: .85;
  }
  #chat-envoyer:disabled {
    opacity: .4;
    cursor: not-allowed;
  }

  #apercu-tags {
    display: flex;
    align-items: center;
    gap: .55rem;
    flex-wrap: wrap;
  }
  .apercu-tags-titre {
    font-size: .72rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--verre-sourdine);
    flex: none;
    margin-right: .15rem;
  }
  .apercu-tag {
    width: 13px;
    height: 13px;
    flex: none;
    padding: 0;
    border-radius: 50%;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
  }
  .apercu-tag::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .18);
  }
  .apercu-tag[data-tag="rouge"]::before  { background: var(--tag-rouge); }
  .apercu-tag[data-tag="orange"]::before { background: var(--tag-orange); }
  .apercu-tag[data-tag="jaune"]::before  { background: var(--tag-jaune); }
  .apercu-tag[data-tag="vert"]::before   { background: var(--tag-vert); }
  .apercu-tag[data-tag="bleu"]::before   { background: var(--tag-bleu); }
  .apercu-tag[data-tag="violet"]::before { background: var(--tag-violet); }
  .apercu-tag.actif::after {
    content: '';
    position: relative;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: rgba(0, 0, 0, .55);
  }

  #apercu-favori {
    width: 1.4rem;
    height: 1.4rem;
    margin-left: auto;
    flex: none;
    padding: 0;
    border: none;
    background: none;
    color: var(--verre-sourdine);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: color .2s ease;
  }
  #apercu-favori:hover {
    color: var(--verre-texte);
  }
  #apercu-favori.actif {
    color: rgb(var(--verre-accent-2));
  }
  #apercu-favori:active svg {
    animation: popEtoile .35s ease-out;
  }
  @keyframes popEtoile {
    0%   { transform: scale(1); }
    40%  { transform: scale(1.3); }
    100% { transform: scale(1); }
  }
  #apercu-favori svg {
    width: 18px;
    height: 18px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linejoin: round;
  }
  #apercu-favori.actif svg {
    fill: currentColor;
  }

  /* ===== Popup de chat écrit ===== */

  #chat-popup {
    position: fixed;
    inset: 0;
    z-index: 25;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(4, 5, 8, .68);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s ease;
  }
  #chat-popup.ouvert {
    opacity: 1;
    pointer-events: auto;
  }

  #chat-fenetre {
    position: relative;
    width: min(28rem, 90vw);
    display: flex;
    flex-direction: column;
    gap: .8rem;
    padding: 1.2rem;
    border-radius: 1rem;
    border: 1px solid var(--verre-bordure);
    background: var(--verre-fond-teinte);
    backdrop-filter: blur(34px) saturate(180%);
    -webkit-backdrop-filter: blur(34px) saturate(180%);
    box-shadow: 0 20px 60px rgba(0, 0, 0, .6), inset 0 1px 0 rgba(255, 255, 255, .07);
    transform: scale(.9);
    transition: transform .3s cubic-bezier(.34, 1.45, .64, 1);
  }
  #chat-popup.ouvert #chat-fenetre {
    transform: scale(1);
  }

  #chat-texte {
    width: 100%;
    min-height: 2.6rem;
    max-height: 240px;
    padding: .7rem .85rem;
    border-radius: .7rem;
    border: 1px solid rgba(255, 255, 255, .18);
    background: rgba(255, 255, 255, .06);
    color: var(--verre-texte);
    font: inherit;
    font-size: .88rem;
    line-height: 1.4;
    resize: none;
    overflow-y: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  #chat-texte::-webkit-scrollbar {
    display: none;
  }
  #chat-texte::placeholder {
    color: var(--verre-sourdine);
  }
  #chat-texte:focus {
    outline: none;
    border-color: rgba(126, 224, 201, .5);
    background: rgba(255, 255, 255, .1);
  }

  #chat-actions {
    display: flex;
    gap: .6rem;
  }

  /* ===== Explorateur en vue réduite / iOS : dock façon app mobile =====
     La liste des filtres (Tous/Favoris/Images/Documents) devient un dock
     fixe en bas, icône + libellé, comme un menu d'onglets mobile. La liste
     des tags devient une barre fine et fixe en haut, à la place d'un champ
     de recherche. Les fichiers occupent le milieu. Ce bloc de règles est
     dupliqué pour la media query <700px et pour le mode iOS car les deux
     contextes ne se recouvrent pas toujours (iPad en @media large, etc). */
  @media (max-width: 700px) {
    /* Collé aux bords de l'écran, sans marge ni coins arrondis — comme le
       mode plein écran du bureau (voir #gestionnaire-fenetre.plein-ecran). */
    #gestionnaire-fenetre {
      position: fixed;
      inset: 0;
      width: auto;
      height: auto;
      border-radius: 0;
    }
    #gestionnaire-taille-normale,
    #gestionnaire-plein-ecran {
      display: none;
    }
    /* Un peu plus de hauteur pour que le bouton de retour, plus grand
       que les feux d'origine, respire au lieu de toucher les bords. */
    #gestionnaire-entete {
      padding: 1rem;
      /* Même couleur opaque exacte que les dock du haut/bas (voir
         #gestionnaire-tags-groupe / #gestionnaire-filtres-groupe) : la
         valeur de --verre-fond seule ne donne pas le même rendu ici car
         elle se superpose au flou de la fenêtre différemment selon ce
         qu'il y a derrière. */
      background: rgb(30, 30, 33);
      /* Supprimé : cette ligne, distincte de la bordure de
         #gestionnaire-tags-groupe qui chevauche déjà l'en-tête, était la
         source du liseré résiduel. */
      border-bottom: none;
    }
    #gestionnaire-titre {
      font-size: 1.05rem;
    }
    /* Bouton de retour à droite, dans le même style que #apercu-fermer
       (cercle translucide + croix qui tourne au survol) plutôt que le
       rond rouge "feu" d'origine. */
    #gestionnaire-feux {
      left: auto;
      right: .9rem;
    }
    #gestionnaire-fermer {
      width: 2.2rem;
      height: 2.2rem;
      border-radius: 50%;
      border: 1px solid var(--verre-bordure);
      background: rgba(255, 255, 255, .1);
      box-shadow: none;
      transition: background .2s, border-color .2s, transform .25s;
    }
    #gestionnaire-fermer svg {
      display: block;
      width: 16px;
      height: 16px;
      color: var(--verre-texte);
    }
    #gestionnaire-fermer:hover {
      background: rgba(255, 255, 255, .2);
      transform: rotate(90deg);
      filter: none;
    }

    #gestionnaire-barre-laterale {
      display: contents;
    }

    #gestionnaire-tags-groupe {
      display: flex;
      position: absolute;
      /* -1px : chevauche légèrement l'en-tête pour éliminer un liseré de
         1px causé par l'arrondi des sous-pixels entre les deux blocs. La
         hauteur compense d'1px pour que le bord bas reste exactement à
         2.4rem (sinon un liseré identique apparaît juste en dessous, sur
         le fond translucide de #gestionnaire-principal). */
      top: -1px;
      left: 0;
      right: 0;
      z-index: 2;
      height: calc(2.4rem + 1px);
      align-items: center;
      justify-content: center;
      gap: .5rem;
      padding: 0 .8rem;
      /* Opaque (contrairement à --verre-fond, semi-transparent) : cette
         barre survole la grille de fichiers qui défile juste en dessous,
         alors que la barre de titre n'a rien derrière elle — même teinte
         que celle-ci, mais sans laisser transparaître les fichiers. */
      background: rgb(30, 30, 33);
      border-bottom: 1px solid var(--verre-bordure);
    }
    #gestionnaire-tags-groupe .gestionnaire-section-titre,
    #gestionnaire-tags-groupe .gestionnaire-label {
      display: none;
    }
    #gestionnaire-tags-groupe .gestionnaire-tag {
      width: 1.8rem;
      height: 1.8rem;
      padding: 0;
      justify-content: center;
      border-radius: 50%;
    }

    #gestionnaire-filtres-groupe {
      display: flex;
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 2;
      height: 4.5rem;
      align-items: stretch;
      justify-content: space-around;
      /* Opaque, même raison que #gestionnaire-tags-groupe ci-dessus. */
      background: rgb(30, 30, 33);
      border-top: 1px solid var(--verre-bordure);
    }
    #gestionnaire-filtres-groupe .gestionnaire-section-titre {
      display: none;
    }
    #gestionnaire-filtres-groupe .gestionnaire-filtre {
      flex: 1;
      flex-direction: column;
      justify-content: center;
      gap: .2rem;
      border-radius: 0;
      padding: .3rem 0;
    }
    #gestionnaire-filtres-groupe .gestionnaire-filtre.actif {
      background: transparent;
    }
    #gestionnaire-filtres-groupe .gestionnaire-filtre svg {
      width: 22px;
      height: 22px;
    }
    #gestionnaire-filtres-groupe .gestionnaire-label {
      font-size: .6rem;
      color: var(--verre-sourdine);
    }
    #gestionnaire-filtres-groupe .gestionnaire-filtre.actif .gestionnaire-label {
      color: rgb(126, 224, 201);
    }

    #gestionnaire-principal {
      padding: calc(2.4rem + .8rem) .8rem calc(4.5rem + .6rem);
    }

    #gestionnaire-grille,
    #gestionnaire-chargement {
      grid-template-columns: repeat(auto-fill, minmax(70px, 1fr));
    }
    .fichier-vignette,
    .fichier-squelette-vignette {
      width: 68px;
      height: 68px;
    }
    .fichier-nom {
      max-width: 70px;
      font-size: .68rem;
    }
    .fichier-squelette-nom {
      width: 50px;
    }
    /* 10 tuiles de squelette en desktop, mais seulement 8 en vue réduite :
       les 2 dernières sont simplement masquées ici plutôt que dupliquer le
       markup selon la vue. */
    #gestionnaire-chargement .fichier-squelette:nth-child(n+9) {
      display: none;
    }
    /* Léger réglage vertical de l'extension affichée sur l'icône générique,
       vue réduite uniquement (desktop inchangé). */
    .fichier-icone span {
      transform: translateY(2px);
    }
  }

  body.mode-ios #gestionnaire-fenetre {
    position: fixed;
    inset: 0;
    width: auto;
    height: auto;
    border-radius: 0;
    border: none;
  }

  /* Sous 16px, Safari zoome automatiquement la page à la mise au point
     d'un champ de texte (voir configurerPourIOS() dans app.js pour le
     verrouillage du viewport) : on passe donc #chat-texte à 16px pile en
     mode iOS pour ne jamais déclencher ce zoom. */
  body.mode-ios #chat-texte {
    font-size: 16px;
  }
  body.mode-ios #gestionnaire-taille-normale,
  body.mode-ios #gestionnaire-plein-ecran {
    display: none;
  }
  body.mode-ios #gestionnaire-entete {
    padding: 1rem;
    /* Même couleur opaque exacte que les dock du haut/bas, voir la version
       <700px ci-dessus pour l'explication. */
    background: rgb(30, 30, 33);
    /* Supprimé, même raison que la version <700px ci-dessus. */
    border-bottom: none;
  }
  body.mode-ios #gestionnaire-titre {
    font-size: 1.05rem;
  }
  /* Bouton de retour à droite, dans le même style que #apercu-fermer
     (cercle translucide + croix qui tourne au survol) plutôt que le
     rond rouge "feu" d'origine. */
  body.mode-ios #gestionnaire-feux {
    left: auto;
    right: .9rem;
  }
  body.mode-ios #gestionnaire-fermer {
    width: 2.2rem;
    height: 2.2rem;
    border-radius: 50%;
    border: 1px solid var(--verre-bordure);
    background: rgba(255, 255, 255, .1);
    box-shadow: none;
    transition: background .2s, border-color .2s, transform .25s;
  }
  body.mode-ios #gestionnaire-fermer svg {
    display: block;
    width: 16px;
    height: 16px;
    color: var(--verre-texte);
  }
  body.mode-ios #gestionnaire-fermer:hover {
    background: rgba(255, 255, 255, .2);
    transform: rotate(90deg);
    filter: none;
  }

  /* Même style translucide que #gestionnaire-fermer, mais du côté gauche de
     l'en-tête, avant le titre (symétrique de #gestionnaire-fermer à droite,
     même marge .9rem depuis le bord). */
  body.mode-ios #gestionnaire-partager {
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 50%;
    left: .9rem;
    transform: translateY(-50%);
    width: 2.2rem;
    height: 2.2rem;
    border-radius: 50%;
    border: 1px solid var(--verre-bordure);
    background: rgba(255, 255, 255, .1);
    color: var(--verre-texte);
    cursor: pointer;
    transition: background .2s, border-color .2s, transform .2s ease;
  }
  body.mode-ios #gestionnaire-partager svg {
    display: block;
    width: 16px;
    height: 16px;
  }
  body.mode-ios #gestionnaire-partager:hover {
    background: rgba(255, 255, 255, .2);
    transform: translateY(-50%) scale(1.08);
  }

  body.mode-ios #gestionnaire-barre-laterale {
    display: contents;
  }

  body.mode-ios #gestionnaire-tags-groupe {
    display: flex;
    position: absolute;
    /* -1px : chevauche légèrement l'en-tête pour éliminer un liseré de
       1px causé par l'arrondi des sous-pixels entre les deux blocs. La
       hauteur compense d'1px pour que le bord bas reste exactement à
       2.4rem (sinon un liseré identique apparaît juste en dessous, sur
       le fond translucide de #gestionnaire-principal). */
    top: -1px;
    left: 0;
    right: 0;
    z-index: 2;
    height: calc(2.4rem + 1px);
    align-items: center;
    justify-content: center;
    gap: .5rem;
    padding: 0 .8rem;
    /* Opaque, même raison que la version <700px ci-dessus. */
    background: rgb(30, 30, 33);
    border-bottom: 1px solid var(--verre-bordure);
  }
  body.mode-ios #gestionnaire-tags-groupe .gestionnaire-section-titre,
  body.mode-ios #gestionnaire-tags-groupe .gestionnaire-label {
    display: none;
  }
  body.mode-ios #gestionnaire-tags-groupe .gestionnaire-tag {
    padding: 0;
    border-radius: 50%;
  }

  body.mode-ios #gestionnaire-filtres-groupe {
    display: flex;
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 2;
    height: 4.5rem;
    align-items: stretch;
    /* Espace latéral pour rapprocher les 4 boutons entre eux et dégager les
       coins gauche/droite, très arrondis sur les iPhone récents. */
    padding: 0 1.4rem;
    justify-content: space-around;
    /* Opaque, même raison que la version <700px ci-dessus. */
    background: rgb(30, 30, 33);
    border-top: 1px solid var(--verre-bordure);
  }
  body.mode-ios #gestionnaire-filtres-groupe .gestionnaire-section-titre {
    display: none;
  }
  body.mode-ios #gestionnaire-filtres-groupe .gestionnaire-filtre {
    flex: 1;
    flex-direction: column;
    justify-content: center;
    gap: .2rem;
    border-radius: 0;
    padding: .3rem 0;
  }
  body.mode-ios #gestionnaire-filtres-groupe .gestionnaire-filtre.actif {
    background: transparent;
  }
  body.mode-ios #gestionnaire-filtres-groupe .gestionnaire-filtre svg {
    width: 22px;
    height: 22px;
  }
  body.mode-ios #gestionnaire-filtres-groupe .gestionnaire-label {
    font-size: .6rem;
    color: var(--verre-sourdine);
  }
  body.mode-ios #gestionnaire-filtres-groupe .gestionnaire-filtre.actif .gestionnaire-label {
    color: rgb(126, 224, 201);
  }

  body.mode-ios #gestionnaire-principal {
    padding: calc(2.4rem + .8rem) .8rem calc(4.5rem + .6rem);
  }

  /* Même limitation à 8 tuiles de squelette qu'en vue réduite : couvre aussi
     les cas iOS qui ne passent pas par @media (max-width: 700px) (iPad en
     largeur, etc). Desktop reste à 10. */
  body.mode-ios #gestionnaire-chargement .fichier-squelette:nth-child(n+9) {
    display: none;
  }

  /* Même léger réglage vertical de l'extension qu'en vue réduite : couvre
     aussi les cas iOS qui ne passent pas par @media (max-width: 700px)
     (iPad en largeur, etc). Desktop reste inchangé. */
  body.mode-ios .fichier-icone span {
    transform: translateY(2px);
  }
