/*
  La page web : une seule feuille, aucune police distante.

  POURQUOI AUCUNE POLICE TELECHARGEE
  ------------------------------------
  Une police distante est une adresse exterieure de plus, donc une requete qui
  dit a un tiers quand cette page est ouverte. Les piles systeme suffisent, et
  elles s'affichent immediatement -- pas de texte invisible pendant le
  chargement.

  LES DEUX THEMES SONT ECRITS, PAS DEDUITS
  ------------------------------------------
  On declare la palette claire sur `:root`, et on ne redefinit que les jetons
  sous `prefers-color-scheme: dark`. Inverser mecaniquement les couleurs donne
  un contraste faux : le rouge d'un refus doit rester lisible sur les deux
  fonds.
*/

:root {
  color-scheme: light dark;

  --fond: #f6f6f4;
  --carte: #ffffff;
  --trait: #d9d9d2;
  --texte: #1c1d21;
  --pale: #63656e;
  --accent: #2f6f5e;
  --vert: #1f7a4d;
  --rouge: #a3282a;
  --ambre: #8a5a12;
  --ambre-fond: #fdf4e3;
}

@media (prefers-color-scheme: dark) {
  :root {
    --fond: #12141a;
    --carte: #1b1e26;
    --trait: #2a2f3a;
    --texte: #e6e8ee;
    --pale: #9aa2b1;
    --accent: #6ee7a8;
    --vert: #6ee7a8;
    --rouge: #f38a8a;
    --ambre: #f5c86b;
    --ambre-fond: #2a1f14;
  }
}

* { box-sizing: border-box; }

/* ⚠ CETTE REGLE N'EST PAS UNE PRECAUTION, ELLE REPARE UN DEFAUT OBSERVE.
   `hidden` vient de la feuille du NAVIGATEUR, et une regle d'auteur la bat
   toujours : `.conversation { display: flex }` faisait apparaitre une section
   marquee `hidden`. Le formulaire de conversation s'affichait donc avant toute
   connexion, par-dessus rien.

   Trouve le 08/09/2026 en regardant la page, pas en la relisant : aucune
   verification de types ne voit une regle de cascade. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--fond);
  color: var(--texte);
  font: 15px/1.55 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* ------------------------------------------------------ la barre d'etat -- */

.etat {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  background: var(--carte);
  border-bottom: 1px solid var(--trait);
  font-size: 13px;
  flex-wrap: wrap;
  position: sticky;
  top: 0;
  z-index: 2;
}

.pastille {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--pale);
  flex: none;
}
.pastille[data-etat="en-ligne"] { background: var(--vert); }
.pastille[data-etat="occupe"]   { background: var(--ambre); }
.pastille[data-etat="rompu"]    { background: var(--rouge); }

/* Le bouton de reprise : discret, dans la barre d'etat, et jamais la quand
   tout va bien. `margin-top: 0` parce que la regle generale des boutons en pose
   un pour les formulaires -- ici il decalerait la barre. */
.reconnecter {
  margin-top: 0;
  padding: 4px 12px;
  font-size: 12.5px;
  border-radius: 6px;
}

.separateur {
  width: 1px;
  height: 14px;
  background: var(--trait);
}

.pousse { flex: 1; }

.mode, .portees, .moteur { color: var(--pale); }

/* LE MODE « UNE SEULE VIE » NE PASSE PAS INAPERCU. Le brief exige qu'il soit
   visible en permanence ; l'ecrire de la meme couleur que le reste
   reviendrait a le cacher a la vue de tous. */
.mode[data-une-seule-vie="oui"] {
  color: var(--rouge);
  font-weight: 700;
  letter-spacing: .02em;
}

main {
  flex: 1;
  width: 100%;
  max-width: 820px;
  margin: 0 auto;
  padding: 20px 16px 24px;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* ----------------------------------------------------------- l'accueil -- */

.carte {
  background: var(--carte);
  border: 1px solid var(--trait);
  border-radius: 12px;
  padding: 22px;
}

/* ------------------------------------------------------- la marque JaCynth Corp
   ⚠ DEUX TAILLES, DEUX ROLES, ET AUCUNE DES DEUX N'EST DECORATIVE.

   `.marque` ouvre les ecrans d'entree : c'est le seul endroit ou la personne
   attend, donc le seul ou une marque a le temps d'etre regardee.
   `.marque-barre` tient dans la hauteur du texte de la barre d'etat -- une
   image plus haute ferait grandir la barre, qui est `sticky` : tout le fil de
   conversation descendrait de quelques pixels a chaque chargement.

   ⚠ `flex-shrink: 0` SUR LES DEUX. La barre est en `flex-wrap` et la carte
   peut etre etroite sur un telephone ; sans cela le logo s'ecrase en premier,
   puisque c'est le seul element sans texte pour le retenir. */
.marque {
  display: block;
  width: 96px;
  height: auto;
  flex-shrink: 0;
  margin: 0 0 16px;
}

.marque-barre {
  width: 20px;
  height: auto;
  flex-shrink: 0;
  /* Aligne le badge sur la ligne de base du texte plutot que sur sa boite :
     un hexagone centre sur la boite parait toujours trop haut. */
  vertical-align: middle;
}

.carte h1 { font-size: 19px; margin: 0 0 12px; }
.carte p { margin: 0 0 12px; max-width: 62ch; }

label {
  display: block;
  font-size: 13px;
  color: var(--pale);
  margin: 14px 0 5px;
}

textarea, input[type="text"] {
  width: 100%;
  background: var(--fond);
  color: var(--texte);
  border: 1px solid var(--trait);
  border-radius: 8px;
  padding: 9px 11px;
  font: inherit;
  resize: vertical;
}

textarea#appairage-texte {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px;
}

button {
  margin-top: 14px;
  background: var(--accent);
  color: var(--fond);
  border: 0;
  border-radius: 8px;
  padding: 10px 18px;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
button:disabled { opacity: .5; cursor: default; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.erreur {
  color: var(--rouge);
  border-left: 3px solid var(--rouge);
  padding-left: 10px;
  white-space: pre-wrap;
}

/* ------------------------------------------------------ la conversation -- */

.conversation {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

.fil {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-bottom: 8px;
}

.tour {
  border: 1px solid var(--trait);
  border-radius: 12px;
  padding: 12px 15px;
  background: var(--carte);
  /* Le texte du modele arrive en flux : les sauts de ligne comptent, et une
     reponse ne doit jamais deborder horizontalement. */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.tour[data-qui="moi"] {
  background: transparent;
  border-color: transparent;
  border-left: 3px solid var(--accent);
  border-radius: 0;
  color: var(--pale);
  padding-left: 12px;
}

.tour[data-qui="erreur"] {
  border-color: var(--rouge);
  color: var(--rouge);
}

/* Le curseur de frappe : il DIT que le flux est en cours. Sans lui, une
   reponse lente est indistinguable d'une reponse perdue. */
.tour[data-encours="oui"]::after {
  content: "▌";
  color: var(--pale);
  animation: clignote 1s steps(2) infinite;
}
@keyframes clignote { 50% { opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  .tour[data-encours="oui"]::after { animation: none; }
}

.alerte {
  background: var(--ambre-fond);
  border: 1px solid var(--ambre);
  color: var(--ambre);
  border-radius: 10px;
  padding: 10px 14px;
  margin: 10px 0 0;
}

.saisie {
  display: flex;
  gap: 10px;
  align-items: flex-end;
  padding-top: 12px;
  border-top: 1px solid var(--trait);
  margin-top: 12px;
}
.saisie textarea { flex: 1; }
.saisie button { margin-top: 0; }

/* ------------------------------------------------------- qui est connecte -- */

/* L'identite dans la barre. Elle vient de `status`, jamais d'un souvenir de la
   page : apres une coupure la session est NEUVE, et afficher le nom de la
   precedente ferait croire identifie quelqu'un qui ne l'est plus. */
.identite {
  font-weight: 600;
  white-space: nowrap;
}
.identite .role {
  font-weight: 400;
  color: var(--pale);
}

/* L'INDICATEUR DE DEBRIDAGE (section 12.2), et il est VOLONTAIREMENT VOYANT.
   C'est le seul etat ou une action sensible part sans qu'on la confirme ; un
   badge discret laisserait s'installer l'habitude de ne plus le voir. Le rouge
   du theme -- pas une couleur inventee ici -- pour qu'il reste lisible en clair
   comme en sombre, ou `--rouge` est deja redefini. */
.debridage {
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  white-space: nowrap;
  padding: 0.15rem 0.5rem;
  border: 1px solid var(--rouge);
  border-radius: 999px;
  color: var(--rouge);
}

/* Un bouton qui n'a pas le poids d'une action : se deconnecter n'est pas
   l'action principale de la barre, et lui donner l'aspect d'un bouton plein la
   mettrait au meme rang que « Reconnecter », qui repare une panne. */
.lien {
  margin-top: 0;
  background: transparent;
  color: var(--pale);
  padding: 4px 6px;
  font-weight: 400;
  font-size: 12.5px;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.lien:hover { color: var(--texte); }

input[type="password"] {
  width: 100%;
  background: var(--fond);
  color: var(--texte);
  border: 1px solid var(--trait);
  border-radius: 8px;
  padding: 9px 11px;
  font: inherit;
}

.discret {
  color: var(--pale);
  font-size: 13.5px;
}

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

.application {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  /* ⚠ SANS CETTE LIGNE, TOUTE LA PAGE DEBORDE A DROITE. La largeur minimale
     d'un element flex est celle de son CONTENU : une ligne de code sans espace
     ou un chemin long pousse alors la colonne au-dela de la fenetre, et
     l'en-tete comme le champ de saisie partent avec elle. Constate le
     11/09/2026 -- « c'est coupe », et le bouton « Envoyer » sortait de
     l'ecran. */
  min-width: 0;
}

/* ============================================================ le panneau Code

   ⚠ `min-width: 0` SUR CHAQUE COLONNE, POUR LA MEME RAISON QU'AU-DESSUS. */
.code {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  min-width: 0;
  gap: 10px;
}

.code-barre {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  min-width: 0;
}

.code-choix {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--pale);
}

.code-choix select {
  background: var(--fond);
  color: var(--texte);
  border: 1px solid var(--trait);
  border-radius: 6px;
  padding: 5px 8px;
  font: inherit;
  max-width: 46ch;
}

.code-fil {
  font-size: 12px;
  color: var(--pale);
  min-width: 0;
  overflow-wrap: anywhere;
}

.code-corps {
  display: flex;
  gap: 14px;
  flex: 1;
  min-height: 0;
  min-width: 0;
}

.code-liste {
  list-style: none;
  margin: 0;
  padding: 0;
  width: 20rem;
  flex: none;
  min-height: 0;
  overflow-y: auto;
  border: 1px solid var(--trait);
  border-radius: 8px;
}

.code-liste li { border-bottom: 1px solid var(--trait); }
.code-liste li:last-child { border-bottom: none; }

.code-liste button {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  padding: 7px 10px;
  background: none;
  border: none;
  color: var(--texte);
  font: inherit;
  text-align: left;
  cursor: pointer;
  /* Un nom de fichier tres long ne doit pas elargir la colonne. */
  min-width: 0;
  overflow-wrap: anywhere;
}

.code-liste button:hover { background: var(--carte); }
.code-dossier { font-weight: 600; }
.code-dossier::before { content: "▸ "; color: var(--pale); }
.code-taille { color: var(--pale); font-size: 12px; flex: none; }

.code-tronque {
  padding: 7px 10px;
  font-size: 12px;
  color: var(--pale);
}

.code-lecture {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.code-avertissement {
  margin: 0;
  padding: 8px 10px;
  border-radius: 8px;
  background: var(--carte);
  border: 1px solid var(--trait);
  font-size: 13px;
}

.code-vue {
  margin: 0;
  flex: 1;
  min-height: 0;
  /* ⚠ LES DEUX DEBORDEMENTS SONT BORNES ICI, ET NULLE PART AILLEURS. Une ligne
     de code de trois cents caracteres doit faire defiler CE cadre, jamais la
     page : sinon tout le reste -- en-tete, onglets, champ de saisie -- part a
     droite avec elle. */
  overflow: auto;
  padding: 10px 12px;
  background: var(--fond);
  border: 1px solid var(--trait);
  border-radius: 8px;
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: 12.5px;
  line-height: 1.55;
  white-space: pre;
  tab-size: 2;
}

@media (max-width: 760px) {
  /* Sur un telephone, deux colonnes cote a cote donnent deux colonnes
     illisibles. On empile, et la liste cesse d'occuper la moitie de l'ecran. */
  .code-corps { flex-direction: column; }
  .code-liste { width: auto; max-height: 40vh; }
}

.onglets {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--trait);
  margin-bottom: 16px;
}

/* ⚠ L'ONGLET COURANT SE MARQUE PAR `aria-current`, ET LE STYLE LE SUIT.
   Une classe « active » posee en plus serait un second etat a tenir a jour, et
   les deux finiraient par diverger : l'oeil verrait un onglet, un lecteur
   d'ecran en annoncerait un autre. */
.onglet {
  margin-top: 0;
  background: transparent;
  color: var(--pale);
  border-radius: 0;
  border-bottom: 2px solid transparent;
  padding: 9px 14px;
  font-weight: 500;
}
.onglet:hover { color: var(--texte); }
.onglet[aria-current="page"] {
  color: var(--texte);
  border-bottom-color: var(--accent);
  font-weight: 600;
}

/* ---------------------------------------------------------- la vue d'etat -- */

.etat-detail {
  display: flex;
  flex-direction: column;
  gap: 14px;
  overflow-y: auto;
  min-height: 0;
}
.etat-detail h2 { font-size: 15px; margin: 0 0 10px; }

/* Deux colonnes qui s'alignent, et des chiffres qui s'alignent entre eux. */
.paires {
  display: grid;
  grid-template-columns: minmax(9rem, auto) 1fr;
  gap: 6px 16px;
  margin: 0;
  font-size: 13.5px;
}
.paires dt { color: var(--pale); }
.paires dd {
  margin: 0;
  overflow-wrap: anywhere;
  font-variant-numeric: tabular-nums;
}

/* Une valeur qui doit se voir : un refus, une attente d'approbation. */
.paires dd[data-alerte="oui"] { color: var(--ambre); font-weight: 600; }
.paires dd[data-alerte="rouge"] { color: var(--rouge); font-weight: 600; }

.jetons {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.jetons li {
  border: 1px solid var(--trait);
  border-radius: 999px;
  padding: 3px 11px;
  font-size: 12.5px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
/* AUCUN OUTIL N'EST UN FAIT, PAS UN VIDE. Une liste vide se lit comme un
   chargement qui n'a pas fini ; la phrase, elle, se lit comme une reponse. */
.jetons:empty::after {
  content: "aucun outil monté — l’assistante ne peut rien faire d’autre que parler";
  color: var(--ambre);
  font-size: 13px;
}

@media (max-width: 560px) {
  .paires { grid-template-columns: 1fr; gap: 2px 0; }
  .paires dd { margin-bottom: 8px; }
  .etat { font-size: 12px; }
}

/* --------------------------------------------------------------- la voix -- */

/* Une bascule, pas un bouton d'action : elle dit un ETAT, elle ne declenche pas
   un envoi. Lui donner l'aspect plein du bouton « Envoyer » la mettrait au meme
   rang, et l'on cliquerait sur la mauvaise. */
.bascule {
  margin-top: 0;
  background: transparent;
  color: var(--pale);
  border: 1px solid var(--trait);
  padding: 9px 14px;
  font-weight: 500;
  font-size: 13px;
  white-space: nowrap;
}
.bascule:hover { color: var(--texte); }
.bascule[aria-pressed="true"] {
  color: var(--accent);
  border-color: var(--accent);
  font-weight: 600;
}

/* Au telephone, la ligne de saisie deborderait avec trois elements cote a cote.
   La bascule passe alors au-dessus, en pleine largeur : elle reste atteignable
   au pouce, ce qu'un bouton comprime ne serait pas. */
@media (max-width: 560px) {
  .saisie { flex-wrap: wrap; }
  .bascule { order: -1; width: 100%; }
}

/* ------------------------------------------------------- les images jointes */

.jointes {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* La VIGNETTE, et pas seulement le nom du fichier. Une liste de noms ne dit pas
   si l'on a joint la bonne capture d'ecran -- et c'est precisement la question
   qu'on se pose au moment d'envoyer. */
.jointes li {
  display: flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--trait);
  border-radius: 8px;
  padding: 5px 6px 5px 5px;
  font-size: 12.5px;
  color: var(--pale);
  max-width: 260px;
}
.jointes img {
  width: 40px;
  height: 40px;
  object-fit: cover;
  border-radius: 5px;
  flex: none;
}
.jointes .nom {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.jointes button {
  margin-top: 0;
  background: transparent;
  color: var(--pale);
  border: 0;
  padding: 2px 6px;
  font-size: 15px;
  line-height: 1;
  flex: none;
}
.jointes button:hover { color: var(--rouge); }

/* ============================================================ approbation ==
   Une action sensible qui attend un oui ou un non.

   ⚠ ELLE SE DISTINGUE DES AUTRES BULLES A L'OEIL NU, ET C'EST LE POINT. Une
   demande d'approbation qui ressemblerait a une reponse ordinaire se ferait
   approuver machinalement -- et une approbation accordee sans regarder ne
   protege plus de rien. D'ou la couleur d'alerte et le liseré. */
.tour[data-qui="approbation"] {
  border-color: var(--ambre);
  background: var(--ambre-fond);
  border-left: 3px solid var(--ambre);
}
.approbation-titre {
  margin: 0 0 6px;
  font-weight: 600;
  color: var(--ambre);
}
.approbation p { margin: 0 0 8px; }

/* L'action EXACTE, en chasse fixe. Elle doit se lire caractere par caractere :
   c'est un chemin de fichier qu'on approuve, et deux chemins voisins ne
   different parfois que d'une lettre. */
.approbation-action {
  margin: 0 0 10px;
  padding: 8px 10px;
  border: 1px solid var(--trait);
  border-radius: 8px;
  background: var(--carte);
  font-family: ui-monospace, "Cascadia Code", "Consolas", monospace;
  font-size: 13px;
  /* Un argument long ne doit pas faire deborder la page horizontalement. */
  overflow-x: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.approbation-boutons { display: flex; gap: 8px; }
.approbation-boutons button {
  padding: 7px 14px;
  border: 1px solid var(--accent);
  border-radius: 8px;
  background: var(--accent);
  color: var(--carte);
  font: inherit;
  cursor: pointer;
}
.approbation-boutons button[data-role="refus"] {
  background: transparent;
  border-color: var(--rouge);
  color: var(--rouge);
}
.approbation-boutons button:disabled { opacity: 0.45; cursor: default; }

/* Une fois tranchee, la carte cesse d'appeler l'oeil : elle devient une trace,
   pas une demande. Les boutons restent visibles et desarmes -- les retirer
   effacerait ce qui a ete choisi. */
.tour[data-tranchee] {
  background: transparent;
  border-color: var(--trait);
}
.tour[data-tranchee] .approbation-titre { color: var(--pale); }
.tour[data-tranchee="refusee"] .approbation-titre { color: var(--rouge); }

/* ⚠ « ELLE EST EN TRAIN DE… » -- CE QUI MANQUAIT ENTIEREMENT AU FIL.
   Discrete par construction : c'est une trace de ce qui se fait, pas une
   parole. Une lecture et une ecriture ne se ressemblent PAS -- le niveau vient
   du verbe, jamais du nom de l'outil (voir `coeur.py`), et c'est cette
   distinction-la qu'on veut voir d'un coup d'oeil. */
.outil-en-cours {
  margin: 6px 0;
  padding: 5px 12px;
  border-left: 2px solid var(--trait);
  color: var(--pale);
  font-size: 12.5px;
  font-family: "Cascadia Mono", Consolas, ui-monospace, monospace;
}
.outil-en-cours[data-niveau="ecriture"] { border-left-color: var(--ambre); }
.outil-en-cours[data-niveau="sensible"] { border-left-color: var(--rouge); }

/* ================================================ l'application installee -- */

/* ⚠ L'ENCOCHE, ET C'EST CE QUI SEPARE UNE APPLICATION D'UN SITE EN PLEIN
   ECRAN. Installee sur l'ecran d'accueil, la page n'a plus de barre
   d'adresse : elle commence SOUS l'horloge et le capteur. Sans cette marge, la
   barre d'etat passe derriere l'encoche et la pastille de connexion devient
   illisible -- exactement au seul endroit ou elle compte.

   `env()` vaut zero partout ailleurs : la regle est sans effet sur un
   ordinateur, et il n'y a donc rien a conditionner. */
.etat {
  padding-top: calc(10px + env(safe-area-inset-top));
  padding-left: calc(16px + env(safe-area-inset-left));
  padding-right: calc(16px + env(safe-area-inset-right));
}

main {
  padding-bottom: env(safe-area-inset-bottom);
}

/* Le chemin court de l'enrolement. Il porte l'accent parce qu'il est ce qu'on
   veut que la personne fasse ; le chemin long, replie juste en dessous, reste
   en gris. */
.mise-en-avant {
  background: var(--fond);
  border: 1px solid var(--accent);
  border-radius: 10px;
  padding: 14px 16px;
  margin: 0 0 14px;
  line-height: 1.5;
}

/* Le repli : visible, cliquable, et discret tant qu'on n'en a pas besoin. */
.repli {
  border-top: 1px solid var(--trait);
  margin-top: 6px;
  padding-top: 10px;
}
.repli > summary {
  cursor: pointer;
  color: var(--pale);
  font-size: 13.5px;
  padding: 4px 0;
}
.repli > summary:hover { color: var(--texte); }

/* « Le code affiche vient du cache » -- une information sur le CODE, pas sur la
   connexion. Voir le commentaire d'`index.html` : les deux se decorrelent. */
.bandeau-cache {
  background: var(--ambre-fond);
  border-bottom: 1px solid var(--ambre);
  color: var(--ambre);
  margin: 0;
  padding: 9px 16px;
  font-size: 13px;
  text-align: center;
}

/* ------------------------------------------------------- les appareils lies
   Une ligne par appareil : son nom, quand il s'est lie, et de quoi le couper.
   ⚠ `word-break` sur le nom : il vient du client qui se connecte, donc de
   quelqu'un d'autre. Un nom de deux cents signes sans espace ferait deborder
   la carte horizontalement sur un telephone. */
.appareils {
  list-style: none;
  margin: 0 0 12px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.appareils li {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px 0;
  border-bottom: 1px solid var(--trait);
}

.appareils li:last-child { border-bottom: none; }
.appareil-nom { font-weight: 600; word-break: break-word; }
.appareil-ici { color: var(--pale); font-style: italic; }
.appareils button { margin-left: auto; }

/* L'INTERRUPTEUR DU DEBRIDAGE, DANS LA BARRE D'ETAT.

   ⚠ SA PROPRE CLASSE, ET NON `.bascule`. Celle-ci habille les boutons de la
   ligne de saisie, avec leur rembourrage : la reutiliser ici donnerait un
   bouton deux fois trop grand dans une barre de treize pixels. Deux usages
   differents, deux classes -- les melanger est la facon dont un style finit
   par etre retouche pour un ecran et casse pour l'autre.

   ⚠ IL CHANGE D'APPARENCE, PAS SEULEMENT DE LIBELLE. Un mode qui leve les
   approbations doit se voir d'un coup d'oeil depuis l'autre bout de la piece,
   pas se lire. */
.bascule-barre {
  border: 1px solid var(--trait);
  background: var(--fond);
  color: var(--pale);
  border-radius: 999px;
  padding: 3px 12px;
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  flex: none;
  white-space: nowrap;
}

.bascule-barre:hover { color: var(--texte); background: var(--carte); }

.bascule-barre[data-actif="oui"] {
  border-color: #b4541f;
  background: #3a1d0c;
  color: #ffcf9e;
  font-weight: 600;
}

/* LE CHOIX DU MOTEUR, DANS LA BARRE D'ETAT. */
.choix-moteur {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  font-size: 12px;
  color: var(--pale);
  flex: none;
}

.choix-moteur select {
  background: var(--fond);
  color: var(--texte);
  border: 1px solid var(--trait);
  border-radius: 6px;
  padding: 2px 6px;
  font: inherit;
  font-size: 12px;
  max-width: 22ch;
}

/* ========================================================== la vue JARVIS

   ⚠ ELLE SE REPLIE A ZERO QUAND RIEN NE SE PASSE. Une couronne vide occupant le
   tiers de l'ecran entre deux questions ferait descendre la conversation pour
   ne rien dire. On anime la HAUTEUR, pas l'affichage : `display: none` ne
   s'anime pas, et le saut se verrait. */
.jarvis {
  height: 0;
  overflow: hidden;
  transition: height .25s ease;
  flex: none;
}

.jarvis[data-actif="oui"] { height: 190px; }

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

.jarvis-toile { width: 100%; height: 190px; display: block; }

/* Le centre : plein, calme, et il ne clignote pas. Ce qui bouge doit dire
   quelque chose ; un coeur qui pulse en permanence ne dit rien. */
.jarvis-centre {
  fill: var(--carte);
  stroke: var(--accent);
  stroke-width: 1.5;
}

.jarvis-dit {
  fill: var(--pale);
  font-size: 11px;
  font-family: inherit;
}

.jarvis-trait { stroke: var(--trait); stroke-width: 1; }
.jarvis-point { fill: var(--pale); }
.jarvis-nom {
  fill: var(--pale);
  font-size: 10px;
  font-family: inherit;
}

/* ⚠ TROIS COULEURS POUR TROIS SENS, ET L'ATTENTE TRANCHE. Un accord demande
   arrete tout : il doit se distinguer d'un outil qui travaille, sans qu'on ait
   a lire l'etiquette. */
.jarvis-trait[data-genre="reflexion"] { stroke: var(--accent); opacity: .45; }
.jarvis-point[data-genre="reflexion"] { fill: var(--accent); opacity: .7; }

.jarvis-trait[data-genre="outil"] { stroke: var(--accent); }
.jarvis-point[data-genre="outil"] { fill: var(--accent); }
.jarvis-nom[data-genre="outil"] { fill: var(--texte); }

.jarvis-trait[data-genre="attente"] { stroke: var(--ambre); stroke-width: 1.6; }
.jarvis-point[data-genre="attente"] { fill: var(--ambre); }
.jarvis-nom[data-genre="attente"] { fill: var(--ambre); font-weight: 600; }
