/* ==========================================================================
   Archiverse Search - bibliothèque Outils

   Ce fichier n'ajoute que ce qui n'existe pas déjà dans style.css, qu'il
   charge après lui. Aucune couleur, aucune police, aucun rayon n'y est
   redéfini : tout passe par les variables de la charte. Les composants
   communs (boutons, cartes, panneaux, étiquettes, champs) sont réutilisés
   tels quels.
   ========================================================================== */

/* ---------- 1. En-tête du portail ---------------------------------------- */

/* Les regles .hub* ont rejoint la charte, tools/assets/css/style.css.

   Elles decrivaient l'en-tete de section — le fil, le titre, l'accroche —
   et ne vivaient que dans cette feuille, chargee par les seules pages
   Outils. La section Ressources porte le meme en-tete et ne chargeait pas
   cette feuille : son titre retombait sur le « h1 { font-size: 8vh } » de
   css/style2.css, soit cent un pixels au lieu de quarante et un, et son fil
   n'avait plus ni taille ni couleur propres.

   Un en-tete partage par trois pages appartient a la charte, pas a l'une
   des trois. */

/* ---------- 2. Grille des outils ----------------------------------------- */

.outils {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding: 0 var(--gut) 4rem;
}

.outilgrille {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
}

.outil {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: 1.2rem;
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
    background-color var(--theme-dur) var(--theme-ease);
}

.outil:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.outil:focus-within {
  border-color: var(--accent);
}

.outil__tete {
  display: flex;
  gap: .9rem;
  align-items: flex-start;
}

.outil__id {
  min-width: 0;
  flex: 1 1 auto;
}

.outil__nom {
  font-size: 1.12rem;
}

/* Toute la carte est cliquable, sans emprisonner les boutons d'administration. */
.outil__nom a::after {
  content: "";
  position: absolute;
  inset: 0;
}

.outil__soustitre {
  font-size: .82rem;
  color: var(--text-3);
  margin-top: .15rem;
}

.outil__accroche {
  margin-top: .8rem;
  color: var(--text-2);
  font-size: .9rem;
  line-height: 1.5;
}

.outil__usages {
  margin-top: .9rem;
  display: grid;
  gap: .35rem;
}

.outil__usage {
  display: flex;
  gap: .5rem;
  font-size: .84rem;
  color: var(--text-2);
}

.outil__puce {
  flex: 0 0 auto;
  width: 1.05rem;
  height: 1.05rem;
  margin-top: .18rem;
  border-radius: var(--r-pill);
  display: grid;
  place-items: center;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: .62rem;
  font-weight: 700;
}

.outil__pied {
  margin-top: auto;
  padding-top: 1rem;
  display: flex;
  align-items: center;
  gap: .6rem;
  flex-wrap: wrap;
}

.outil__dossier {
  font-family: var(--font-mono);
  font-size: .72rem;
  color: var(--text-3);
  background: var(--surface-2);
  border: 1px solid var(--line);
  padding: .18rem .5rem;
  border-radius: 6px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

.outil__ouvrir {
  margin-left: auto;
  position: relative;
  z-index: 1;
}

/* Bloc de maintenance, visible des seuls administrateurs. */
.outil__actions {
  display: flex;
  gap: .4rem;
  flex-wrap: wrap;
  margin-left: auto;
}

/* Un outil en chantier n'est pas ouvrable : la carte le dit sans ambiguïté. */
/* ---------- états d'une fiche -------------------------------------------

   Trois états, dont deux à distinguer d'un coup d'œil. Ils portaient le même
   bord en pointillés et la même étiquette grise : il fallait lire pour savoir
   lequel on regardait, ce qui est exactement ce qu'une signalétique doit
   éviter. Mais ces fiches restent minoritaires dans la grille, et un état ne
   doit pas crier plus fort que le nom de l'outil qu'il qualifie.

   Le partage se fait donc en trois degrés, du plus discret au plus visible :

     • la pastille ronde, six pixels, en tête d'étiquette. C'est elle qu'on
       repère en balayant la page, avant d'avoir lu le mot ;
     • l'étiquette elle-même, teintée de la même couleur, en fond pâle ;
     • le bord de la carte, qui reprend la teinte sans changer d'épaisseur.

   Les deux teintes se lisent sans se confondre : l'ambre de l'attente pour
   « en chantier », le rouge éteint du hors-service pour « indisponible ».
   L'une annonce, l'autre retire — et le pointillé, réservé au chantier, dit
   à lui seul que la fiche est là mais pas encore finie. */
.outil--chantier {
  border-style: dashed;
  border-color: var(--warn-line);
  background: var(--surface-2);
}

.outil--indisponible {
  border-color: var(--danger-line);
  background: var(--surface-2);
}

/* Les deux états réservés se tiennent en retrait : fond légèrement enfoncé,
   contenu atténué. Ni l'un ni l'autre n'est un outil qu'on peut prendre et
   utiliser, et la grille doit le dire avant qu'on ait lu quoi que ce soit.

   Ce retrait partagé ne les confond plus, parce qu'il n'est plus seul à
   parler : la teinte s'en charge — l'ambre de l'attente, le rouge du
   hors-service — et le pointillé, réservé au chantier, distingue ce qui se
   construit de ce qui a été retiré. */
.outil--chantier .outil__tete,
.outil--chantier .outil__accroche,
.outil--chantier .outil__usages,
.outil--indisponible .outil__tete,
.outil--indisponible .outil__accroche,
.outil--indisponible .outil__usages {
  opacity: .72;
}

.outil__statut {
  display: inline-flex;
  align-items: center;
  gap: .38rem;
  font-weight: 600;
}

.outil__pastille {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

.outil__statut--chantier {
  background: var(--warn-soft);
  border-color: var(--warn-line);
  color: var(--warn);
}

.outil__statut--indisponible {
  background: var(--danger-soft);
  border-color: var(--danger-line);
  color: var(--danger);
}

/* L état vu par un visiteur : tout gris, cadenas fermé.

   Les deux teintes servent à celui qui administre — elles séparent ce qui
   se construit de ce qui a été retiré. Un visiteur ne fait pas cette
   distinction : de son côté il n y a qu une porte fermée, et la peindre en
   ambre revenait à donner une couleur d alerte à une information qui n en
   est pas une. Le gris la range à sa place, en marge de la grille.

   Le contour de la carte suit, sans quoi un liseré ambre serait resté à
   signaler une couleur qui n est plus nulle part ailleurs sur la fiche. */
.outil__statut--verrou {
  background: var(--surface-3);
  border-color: var(--line-strong);
  color: var(--text-2);
}

.outil--verrouille {
  border-color: var(--line-strong);
}

.outil__cadenas {
  flex: none;
  margin-right: -.04rem;
}

.outil__admin {
  position: relative;
  z-index: 1;
  margin-top: .9rem;
  padding-top: .9rem;
  border-top: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
}

/* ---------- 3. Page d'un outil ------------------------------------------- */

.outilhead {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.outilhead__inner {
  position: relative;
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding: 3rem var(--gut) 1.6rem;
  display: flex;
  gap: 1.2rem;
  align-items: flex-end;
  flex-wrap: wrap;
}

.outilhead__id {
  display: flex;
  gap: 1.1rem;
  align-items: center;
  min-width: 0;
}

.outilhead__txt {
  min-width: 0;
}

.outilhead__kicker {
  font-family: var(--font-display);
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: .25rem;
}

.outilhead__nom {
  font-size: clamp(1.5rem, 3.6vw, 2.2rem);
}

.outilhead__lead {
  color: var(--text-2);
  font-size: .95rem;
  margin-top: .3rem;
  max-width: 60ch;
}

.atelier {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding: 2rem var(--gut) 4rem;
  display: grid;
  gap: 1.6rem;
}

/* ---------- 4. Calculateur d'échelle ------------------------------------- */

.calc {
  /* Une seule marge latérale pour toute la calculatrice. L'historique, l'écran
     et le clavier s'alignaient auparavant sur trois valeurs différentes — 1,1rem
     fixe pour le premier, deux plafonnées distinctes pour les autres — et leurs
     bords gauches tombaient à 17,6, 12,8 et 11,2 pixels. Trois lignes de fuite
     au lieu d'une, dont l'écart changeait avec la largeur : discret, mais c'est
     exactement ce qui fait qu'une mise en page a l'air de flotter. */
  --marge-h: clamp(.8rem, calc(1.6vw + 4.8px), 1.1rem);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-card);
  background: var(--surface);
  overflow: hidden;
}

.calc__echelle {
  display: flex;
  align-items: flex-end;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 1.1rem 1.2rem;
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
}

.calc__mode {
  margin-left: auto;
}

/* Saisie « 1 : N », composée pour se lire comme la notation d'échelle. */
.ratio {
  display: flex;
  align-items: center;
  gap: .45rem;
}

.ratio__un {
  font-family: var(--font-mono);
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--text-2);
}

.ratio__champ {
  width: 7.5rem;
  font-family: var(--font-mono);
  font-weight: 600;
}

.calc__corps {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  gap: 1rem;
  align-items: end;
  padding: 1.4rem 1.2rem;
}

.cote {
  display: grid;
  gap: .45rem;
  min-width: 0;
}

.cote__lab {
  font-family: var(--font-display);
  font-size: .74rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-3);
}

.cote__saisie {
  display: flex;
  gap: .45rem;
}

.cote__valeur {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: 1.35rem;
  font-weight: 600;
  letter-spacing: -.02em;
  padding-block: .55rem;
}

.cote__unite {
  flex: 0 0 auto;
  width: 5.2rem;
}

.cote--plan .cote__lab {
  color: var(--accent);
}

.cote--plan .cote__valeur {
  border-color: var(--accent);
}

.calc__sens {
  display: grid;
  place-items: center;
  gap: .3rem;
  padding-bottom: .55rem;
  color: var(--text-3);
}

.calc__sens svg {
  display: block;
}

.calc__facteur {
  font-family: var(--font-mono);
  font-size: .7rem;
  white-space: nowrap;
  background: var(--surface-2);
  border: 1px solid var(--line);
  padding: .1rem .4rem;
  border-radius: 5px;
}

/* Phrase de contrôle : la garantie que l'utilisateur a bien compris. */
.calc__phrase {
  padding: 1rem 1.2rem;
  border-top: 1px solid var(--line);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: .95rem;
  line-height: 1.5;
}

.calc__phrase b {
  font-family: var(--font-mono);
  font-weight: 700;
}

.calc__phrase--vide {
  background: var(--surface-2);
  color: var(--text-3);
}

/* ---------- 5. Blocs secondaires ----------------------------------------- */

.bloc {
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--surface);
  padding: 1.2rem;
}

.bloc__tete {
  display: flex;
  align-items: baseline;
  gap: .7rem;
  margin-bottom: .9rem;
  flex-wrap: wrap;
}

.bloc__titre {
  font-size: 1.05rem;
}

.bloc__hint {
  font-size: .8rem;
  color: var(--text-3);
}

/* repères de l'échelle courante */
.reperes {
  display: grid;
  gap: .5rem;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}

.repere {
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  background: var(--surface-2);
  padding: .7rem .8rem;
}

.repere__de {
  font-size: .78rem;
  color: var(--text-3);
}

.repere__vers {
  font-family: var(--font-mono);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text);
  margin-top: .15rem;
}

/* tableau des échelles */
.tableau {
  width: 100%;
  border-collapse: collapse;
  font-size: .88rem;
}

.tableau th {
  text-align: left;
  font-family: var(--font-display);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-3);
  padding: .45rem .6rem;
  border-bottom: 2px solid var(--line-strong);
}

.tableau th:last-child,
.tableau td:last-child {
  text-align: right;
}

.tableau td {
  padding: .5rem .6rem;
  border-bottom: 1px solid var(--line);
}

.tableau tbody tr:last-child td {
  border-bottom: 0;
}

.tableau tr.is-courante td {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}

.tableau .num {
  font-family: var(--font-mono);
}

.tableau__enveloppe {
  overflow-x: auto;
}

/* changement d'échelle pour impression */
.reproduction {
  display: grid;
  gap: .8rem;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto;
  align-items: end;
}

.reproduction__res {
  font-family: var(--font-mono);
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--accent);
  white-space: nowrap;
  padding-bottom: .4rem;
}

.reproduction__fleche {
  padding-bottom: .8rem;
  color: var(--text-3);
}

/* ---------- 6. Téléphone -------------------------------------------------- */

@media (max-width: 760px) {
  .calc__corps {
    grid-template-columns: 1fr;
    gap: .9rem;
  }

  /* La flèche pivote : la lecture devient verticale, réel puis plan. */
  .calc__sens {
    grid-row: auto;
    padding: 0;
    flex-direction: row;
  }

  .calc__sens svg {
    transform: rotate(90deg);
  }

  .calc__echelle {
    gap: .8rem;
  }

  .calc__mode {
    margin-left: 0;
    width: 100%;
  }

  .calc__mode .roleswitch {
    width: 100%;
  }

  .calc__mode .roleswitch__opt {
    flex: 1 1 0;
    justify-content: center;
  }

  .ratio__champ {
    width: 6rem;
  }

  .reproduction {
    grid-template-columns: 1fr;
  }

  .reproduction__fleche {
    display: none;
  }

  .outilgrille {
    grid-template-columns: 1fr;
  }

  .outil__ouvrir {
    margin-left: 0;
    width: 100%;
  }

  .outil__ouvrir .btn {
    width: 100%;
  }

  .outilhead__inner {
    padding: 3rem var(--gut) 1.3rem;
  }

  .atelier {
    padding-top: 1.4rem;
  }

  .hub {
    padding-top: 1.4rem;
  }
}

@media (max-width: 460px) {
  .cote__valeur {
    font-size: 1.15rem;
  }

  .reperes {
    grid-template-columns: 1fr;
  }
}

/* ---------- 7. Feuille et barre d'échelle -------------------------------- */

.papier__reglages {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  align-items: flex-end;
  margin-bottom: 1.1rem;
}

.papier {
  display: grid;
  grid-template-columns: minmax(0, 240px) minmax(0, 1fr);
  gap: 1.4rem;
  align-items: start;
}

.papier__vue {
  margin: 0;
  display: grid;
  gap: .5rem;
  justify-items: center;
}

/* Le viewBox du SVG est en millimètres de papier : la feuille garde donc ses
   proportions exactes, et la barre d'échelle y est tracée à sa vraie taille
   relative. */
.feuille__svg {
  width: 100%;
  height: auto;
  max-height: 300px;
  filter: drop-shadow(0 6px 16px rgb(0 0 0 / .12));
}

.papier__legende {
  font-family: var(--font-mono);
  font-size: .74rem;
  color: var(--text-3);
  text-align: center;
}

.papier__infos {
  display: grid;
  gap: 1.1rem;
  align-content: start;
}

.barre {
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  background: var(--surface-2);
  padding: .9rem 1rem;
}

.barre__lab {
  font-family: var(--font-display);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: .6rem;
}

.barre__svg {
  width: 100%;
  max-width: 320px;
  height: auto;
  display: block;
}

.barre__note {
  font-size: .82rem;
  color: var(--text-2);
  margin-top: .6rem;
}

@media (max-width: 760px) {
  .papier {
    grid-template-columns: 1fr;
    gap: 1.1rem;
  }

  .feuille__svg {
    max-height: 240px;
  }

  .papier__reglages .field {
    flex: 1 1 100%;
  }

  .papier__reglages .roleswitch {
    width: 100%;
  }

  .papier__reglages .roleswitch__opt {
    flex: 1 1 0;
    justify-content: center;
  }
}

/* Choix de représentation et export de la barre d'échelle. */
.barre__styles {
  margin-bottom: .8rem;
}

.barre__actions {
  display: flex;
  gap: .5rem;
  flex-wrap: wrap;
  margin-top: .9rem;
}

@media (max-width: 760px) {
  .barre__actions .btn {
    flex: 1 1 auto;
  }
}

/* ---------- 8. Vérificateur loi de Blondel ------------------------------- */

.champ-nb {
  font-family: var(--font-mono);
  font-weight: 600;
  width: 100%;
}

.calc__echelle .field {
  flex: 0 1 11rem;
}

/* La destination porte des intitulés bien plus longs que « Hauteur totale » :
   sans cette largeur propre, la liste déroulante tronque son propre libellé. */
.calc__echelle .field:has(> #destination) {
  flex: 0 1 23rem;
  min-width: 14rem;
}

/* Un champ calculé se distingue d'un champ à remplir. */
.input--calcule {
  background: var(--surface-2);
  color: var(--text-2);
  cursor: default;
}

.blondel {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: 1.2rem;
  padding: 1.4rem 1.2rem;
}

/* La formule est l'élément décisif : elle porte la couleur du verdict. */
.formule {
  border-radius: var(--r-card);
  padding: 1.1rem 1.2rem;
  border: 1px solid var(--line);
  background: var(--surface-2);
  align-content: center;
  display: grid;
  gap: .5rem;
}

.formule--ok {
  border-color: var(--ok);
  background: var(--ok-soft);
}

.formule--ko {
  border-color: var(--danger);
  background: color-mix(in srgb, var(--danger) 12%, transparent);
}

.formule--vide {
  border-style: dashed;
}

.formule__vide {
  font-size: .88rem;
  color: var(--text-3);
}

.formule__titre {
  font-family: var(--font-display);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-3);
}

.formule__calcul {
  display: flex;
  align-items: baseline;
  gap: .45rem;
  flex-wrap: wrap;
  font-family: var(--font-mono);
  font-size: 1.05rem;
  color: var(--text-2);
}

.formule__op {
  opacity: .6;
}

.formule__res {
  font-size: 1.7rem;
  font-weight: 700;
  letter-spacing: -.03em;
  color: var(--text);
}

.formule--ok .formule__res {
  color: var(--ok);
}

.formule--ko .formule__res {
  color: var(--danger);
}

.formule__verdict {
  display: flex;
  align-items: center;
  gap: .6rem;
  flex-wrap: wrap;
}

.formule__badge {
  font-family: var(--font-display);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: .22rem .6rem;
  border-radius: var(--r-pill);
  background: var(--ok);
  color: var(--on-ok);
}

.formule--ko .formule__badge {
  background: var(--danger);
  color: #fff;
}

.formule__regle {
  font-family: var(--font-mono);
  font-size: .74rem;
  color: var(--text-3);
}

/* Chaque grandeur porte son propre état : c'est elle qui rougit, pas tout. */
.mesures {
  display: grid;
  gap: .6rem;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

.mesure {
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  background: var(--surface);
  padding: .8rem .9rem;
}

.mesure__titre {
  font-size: .78rem;
  color: var(--text-3);
}

.mesure__sym {
  font-family: var(--font-mono);
  font-weight: 700;
  color: var(--accent);
  background: var(--accent-soft);
  padding: 0 .28rem;
  border-radius: 4px;
}

.mesure__valeur {
  font-family: var(--font-mono);
  font-size: 1.45rem;
  font-weight: 700;
  letter-spacing: -.03em;
  margin-top: .15rem;
}

.mesure__unite {
  font-size: .9rem;
  font-weight: 500;
  opacity: .7;
}

.mesure__critere {
  font-size: .74rem;
  color: var(--text-3);
  margin-top: .3rem;
}

.calc__phrase--ok {
  background: var(--ok-soft);
  color: var(--ok);
}

.calc__phrase--ko {
  background: color-mix(in srgb, var(--danger) 12%, transparent);
  color: var(--danger);
}

.escalier {
  display: grid;
  place-items: center;
}

.escalier__svg {
  width: 100%;
  max-width: 640px;
  height: auto;
}

/* Bloc de conformité réglementaire. Il porte le vert et le rouge, parce qu'un
   seuil de loi se respecte ou ne se respecte pas ; les cartes de mesure, elles,
   restent neutres. */
.regle {
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  background: var(--surface-2);
  padding: 1rem 1.1rem;
}

.regle--ok {
  border-color: var(--ok);
  background: var(--ok-soft);
}

.regle--ko {
  border-color: var(--danger);
  background: color-mix(in srgb, var(--danger) 12%, transparent);
}

.regle--libre {
  border-style: dashed;
}

.regle__verdict {
  font-family: var(--font-display);
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  margin-bottom: .7rem;
}

.regle--ok .regle__verdict {
  color: var(--ok-hi);
}

.regle--ko .regle__verdict {
  color: var(--danger);
}

.regle--libre .regle__verdict {
  color: var(--text-3);
}

.regle__lignes {
  display: grid;
  gap: .4rem;
  margin-bottom: .9rem;
}

.regle__ligne {
  display: grid;
  align-items: baseline;
  gap: .3rem .8rem;
  grid-template-columns: minmax(8rem, auto) auto 1fr auto;
  padding: .45rem .6rem;
  border-radius: 7px;
  background: var(--surface);
  border: 1px solid var(--line);
}

.regle__nom {
  font-size: .84rem;
  color: var(--text-2);
}

.regle__val {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: .95rem;
}

.regle__exig {
  font-size: .8rem;
  color: var(--text-3);
}

.regle__etat {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: .1rem .45rem;
  border-radius: var(--r-pill);
  white-space: nowrap;
}

.regle__ligne--ok .regle__etat {
  background: var(--ok);
  color: var(--on-ok);
}

.regle__ligne--ko .regle__etat {
  background: var(--danger);
  color: #fff;
}

.regle__ligne--ok .regle__val {
  color: var(--ok-hi);
}

.regle__ligne--ko .regle__val {
  color: var(--danger);
}

/* La sortie proposée quand ça ne passe pas : plus utile qu'un constat d'échec. */
.regle__issue {
  font-size: .86rem;
  line-height: 1.55;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: .55rem .7rem;
  margin-bottom: .9rem;
}

.regle__quoi {
  font-size: .82rem;
  color: var(--text-2);
  line-height: 1.6;
}

.regle__titre {
  font-family: var(--font-display);
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-top: .9rem;
  margin-bottom: .35rem;
}

/* Les textes applicables : le périmètre en évidence, la référence dessous. */
.regle__textes {
  list-style: none;
  display: grid;
  gap: .5rem;
  margin-bottom: .2rem;
}

.regle__textes li {
  /* Bloc, et non grille : le lien reste alors un vrai élément en ligne, qui
     épouse son texte et garde son picto collé au dernier mot quand la
     référence passe à la ligne. */
  display: block;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: .45rem .6rem;
}

.regle__textes b {
  display: block;
  font-size: .82rem;
  font-weight: 600;
  color: var(--text);
  margin-bottom: .1rem;
}

.regle__textes span,
.regle__lien {
  font-family: var(--font-mono);
  font-size: .74rem;
  color: var(--text-3);
}

/* La référence est cliquable : elle mène au texte officiel. Le picto d'ouverture
   externe prévient qu'on quitte le site. */
.regle__lien {
  color: var(--accent);
  text-decoration: none;
}

.regle__lien:hover,
.regle__lien:focus-visible {
  text-decoration: underline;
}

.regle__lien svg {
  vertical-align: -1px;
  opacity: .7;
}

/* Dernier mot et picto soudés : le picto ne finit jamais seul sur sa ligne. */
.regle__fin {
  white-space: nowrap;
}

.regle__liste {
  list-style: none;
  display: grid;
  gap: .25rem;
}

.regle__liste li {
  font-size: .82rem;
  color: var(--text-2);
  line-height: 1.5;
}

.regle__liste li::before {
  content: '— ';
  color: var(--text-3);
}

@media (max-width: 640px) {
  .regle__ligne {
    grid-template-columns: 1fr auto;
  }

  .regle__exig {
    grid-column: 1 / -1;
  }

  /* Sans cela la pastille, seule sur sa ligne de grille, s'étire sur toute la
     colonne au lieu d'épouser son texte. */
  .regle__etat {
    justify-self: start;
  }
}

@media (max-width: 860px) {
  .blondel {
    grid-template-columns: 1fr;
    gap: 1rem;
  }
}

@media (max-width: 760px) {
  .calc__echelle .field {
    flex: 1 1 100%;
  }

  .mesures {
    grid-template-columns: 1fr;
  }

  .formule__res {
    font-size: 1.5rem;
  }
}

/* ---------- 9. Convertisseur de fichiers --------------------------------- */

.depot {
  padding: 1.2rem;
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
  transition: background var(--dur) var(--ease),
    border-color var(--theme-dur) var(--theme-ease);
}

.depot.is-survol {
  background: var(--accent-soft);
}

.depot__vide {
  display: grid;
  justify-items: center;
  gap: .35rem;
  padding: 1.8rem 1rem;
  text-align: center;
}

.depot__ico {
  color: var(--text-3);
}

.depot__titre {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.02rem;
}

.depot__lead {
  font-size: .86rem;
  color: var(--text-3);
  margin-bottom: .5rem;
}

.fichiers {
  display: grid;
  gap: .4rem;
}

.fichier {
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .55rem .7rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  /* Enfant de grille : sans cette remise à zéro, la ligne refuse de passer
     sous sa largeur min-content et un nom de fichier long la fait déborder. */
  min-width: 0;
}

.fichier__ext {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-size: .68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  background: var(--accent-soft);
  color: var(--accent);
  border: 1px solid var(--accent-line);
  padding: .16rem .45rem;
  border-radius: 5px;
  min-width: 3rem;
  text-align: center;
}

.fichier__nom {
  flex: 1 1 auto;
  min-width: 0;
  font-size: .88rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.fichier__poids {
  flex: 0 0 auto;
  font-size: .76rem;
  color: var(--text-3);
}

.fichier__x {
  flex: 0 0 auto;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text-3);
  width: 24px;
  height: 24px;
  border-radius: var(--r-pill);
  display: grid;
  place-items: center;
  cursor: pointer;
}

.fichier__x:hover {
  color: var(--danger);
  border-color: currentColor;
}

.reglages {
  padding: 1.2rem;
}

.reglages__tete {
  display: flex;
  align-items: center;
  gap: .8rem;
  margin-bottom: .8rem;
}

.reglages__lab {
  font-family: var(--font-display);
  font-size: .74rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-right: auto;
}

.reglages__note {
  font-size: .82rem;
  color: var(--text-3);
  margin-top: .8rem;
}

.reglages__pied {
  margin-top: 1.2rem;
  display: flex;
}

/* Choix du format de sortie : le format prime, le détail explique. */
.sorties {
  display: grid;
  gap: .5rem;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

.sortie {
  display: grid;
  gap: .15rem;
  text-align: left;
  cursor: pointer;
  padding: .7rem .85rem;
  border-radius: var(--r-control);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}

.sortie:hover {
  border-color: var(--accent);
}

.sortie.is-actif {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.sortie__lab {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .95rem;
}

.sortie.is-actif .sortie__lab {
  color: var(--accent);
}

.sortie__det {
  font-size: .76rem;
  color: var(--text-3);
  line-height: 1.35;
}

.options {
  display: grid;
  gap: .9rem;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  margin-top: 1.2rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--line);
}

.curseur {
  width: 100%;
  accent-color: var(--accent);
}

.couleur {
  height: 2.4rem;
  padding: .2rem;
  cursor: pointer;
}

/* Ce qui n'a pas pu être converti. Dit par son nom, jamais passé sous
   silence : une page absente du dossier de téléchargement sans explication
   coûte plus cher qu'un message. */
.rapport {
  margin-top: 1rem;
  padding: .8rem 1rem;
  border: 1px dashed var(--line);
  border-radius: var(--r-control);
  background: var(--surface-2);
}

.rapport__titre {
  font-family: var(--font-display);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--danger);
  margin-bottom: .35rem;
}

.rapport__liste {
  list-style: none;
  display: grid;
  gap: .25rem;
}

.rapport__liste li {
  font-size: .82rem;
  color: var(--text-2);
  line-height: 1.45;
}

.rapport__liste li::before {
  content: '— ';
  color: var(--text-3);
}

/* Une impasse n'est pas une erreur : c'est une question à laquelle on répond.
   D'où le ton neutre plutôt que le rouge, et la consigne mise en avant. */
.ajouter {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  width: 100%;
  margin-top: .5rem;
  padding: .5rem;
  background: none;
  border: 1px dashed var(--line);
  border-radius: var(--r-control);
  color: var(--text-3);
  font-size: .82rem;
  font-family: inherit;
  cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
    background-color var(--theme-dur) var(--theme-ease);
}

.ajouter:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.impasses {
  display: grid;
  gap: .5rem;
  margin-top: .5rem;
}

.impasse {
  border: 1px dashed var(--line);
  border-radius: var(--r-control);
  background: var(--surface);
  padding: .7rem .8rem;
}

.impasse__tete {
  display: flex;
  align-items: center;
  gap: .7rem;
  min-width: 0;
}

.impasse__ext {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-size: .68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  background: var(--surface-2);
  color: var(--text-3);
  border: 1px solid var(--line);
  padding: .16rem .45rem;
  border-radius: 5px;
  min-width: 3rem;
  text-align: center;
}

.impasse__nom {
  flex: 1 1 auto;
  min-width: 0;
  font-size: .88rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.impasse__quoi {
  font-size: .82rem;
  color: var(--text-3);
  margin-top: .45rem;
  line-height: 1.5;
}

.impasse__faire {
  font-size: .84rem;
  color: var(--text-2);
  margin-top: .35rem;
  line-height: 1.5;
}

.impasse__faire b {
  font-family: var(--font-display);
  font-size: .68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--accent);
  display: block;
  margin-bottom: .1rem;
}

/* Réglages repliés. La ligne de résumé porte l'information ; on n'ouvre que
   pour changer quelque chose. */
.repli {
  margin-top: 1rem;
  border-top: 1px solid var(--line);
}

.repli__bouton {
  display: flex;
  align-items: center;
  gap: .5rem;
  width: 100%;
  padding: .8rem 0 .2rem;
  background: none;
  border: 0;
  cursor: pointer;
  text-align: left;
  color: var(--text-2);
}

.repli__bouton:hover {
  color: var(--text);
}

.repli__fleche {
  flex: 0 0 auto;
  color: var(--text-3);
  transition: transform var(--dur) var(--ease),
    color var(--theme-dur) var(--theme-ease);
}

.repli__bouton[aria-expanded="true"] .repli__fleche {
  transform: rotate(90deg);
}

.repli__titre {
  flex: 0 0 auto;
  font-family: var(--font-display);
  font-size: .74rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-3);
}

.repli__resume {
  flex: 1 1 auto;
  min-width: 0;
  font-size: .82rem;
  color: var(--text-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.repli .options {
  margin-top: .9rem;
  padding-top: .9rem;
}

.reglages__pied {
  display: flex;
  align-items: center;
  gap: .9rem;
  flex-wrap: wrap;
  margin-top: 1.1rem;
}

.reglages__resume {
  font-size: .84rem;
  color: var(--text-3);
}

/* Repères sur les formats. Un tableau par famille, avec une pastille d'état
   plutôt qu'une colonne de plus. */
.familles {
  display: grid;
  gap: 1.4rem;
}

/* Enfants de grille : sans cette remise à zéro, la largeur minimale du tableau
   qu'ils contiennent les empêche de rétrécir, et c'est la page entière qui
   déborde au lieu du seul tableau. */
.familles>* {
  min-width: 0;
}

.familles__intro {
  font-size: .8rem;
  color: var(--text-3);
  margin-bottom: 1.1rem;
  line-height: 1.9;
}

.familles__pied {
  font-size: .84rem;
  color: var(--text-2);
  line-height: 1.65;
  margin-top: 1.4rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}

.famille__titre {
  font-family: var(--font-display);
  font-size: .95rem;
  font-weight: 700;
  margin-bottom: .5rem;
}

.famille__note {
  font-family: var(--font-sans);
  font-size: .78rem;
  font-weight: 400;
  color: var(--text-3);
}

/* Un tableau large doit défiler dans sa propre boîte, jamais pousser la page. */
.grilleformats {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-control);
}

/* Colonnes de largeur fixe et identique d'un tableau à l'autre : sans cela
   chaque tableau dimensionne ses colonnes sur son propre contenu, et les cinq
   familles ne s'alignent plus verticalement. */
.grilleformats table {
  width: 100%;
  border-collapse: collapse;
  min-width: 34rem;
  table-layout: fixed;
}

.grilleformats col.c-format {
  width: 22%;
}

.grilleformats col.c-role {
  width: 39%;
}

.grilleformats col.c-atout {
  width: 39%;
}

.grilleformats th,
.grilleformats td {
  text-align: left;
  padding: .5rem .7rem;
  font-size: .82rem;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}

.grilleformats thead th {
  font-family: var(--font-display);
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-3);
  background: var(--surface-2);
  white-space: nowrap;
}

.grilleformats tbody tr:last-child th,
.grilleformats tbody tr:last-child td {
  border-bottom: 0;
}

.grilleformats tbody th {
  font-family: var(--font-mono);
  font-weight: 700;
  color: var(--text);
}

.grilleformats td {
  color: var(--text-2);
}

.grilleformats td:last-child {
  color: var(--text-3);
}

.puce {
  display: inline-block;
  width: .5rem;
  height: .5rem;
  border-radius: 50%;
  margin-right: .45rem;
  vertical-align: baseline;
  flex: 0 0 auto;
}

.puce--oui {
  background: var(--accent);
}

.puce--peut {
  background: var(--accent);
  opacity: .4;
}

.puce--non {
  background: none;
  border: 1px solid var(--text-3);
}

@media (max-width: 760px) {
  .sorties {
    grid-template-columns: 1fr 1fr;
  }

  .options {
    grid-template-columns: 1fr;
  }

  .reglages__pied {
    flex-direction: column;
    align-items: stretch;
  }

  .reglages__pied .btn {
    width: 100%;
  }

  .reglages__resume {
    text-align: center;
  }
}

/* ---------- 10. Calculatrice ---------------------------------------------- */

/* Ordre de ce bloc : d'abord les classes de base, ensuite seulement les
   requêtes média. Une requête média n'ajoute aucune spécificité — une règle
   qu'elle contient perd donc contre une classe de même poids déclarée plus
   bas. Le défaut s'est produit deux fois ici avant d'être pris au sérieux. */

.atelier--calculatrice {
  max-width: 72rem;
}

/* ---- l'écran ---------------------------------------------------------------
   La barre en haut, puis l'aperçu, puis le calcul en bas à droite contre la
   touche d'effacement. En pleine page c'est l'écran qui prend la hauteur
   disponible, jamais le clavier : agrandir la fenêtre révèle de l'écran, il ne
   distend pas les touches. L'historique vient occuper cet espace, sur la même
   surface — il n'est pas un panneau posé dessus, mais la suite de l'écran.
   ---------------------------------------------------------------------------- */

.calcul {
  padding: .8rem 1.1rem 1.1rem;
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

/* Hauteur imposée à la barre. La touche « Fonctions » n'existe pas au-delà de
   900 px — les deux claviers y tiennent côte à côte — et sans cette hauteur, la
   barre perdait douze pixels en passant le seuil : DEG remontait, le bloc de
   calcul se raccourcissait et l'historique s'allongeait d'autant. Un mouvement
   vertical pour un geste horizontal, encore. */
.calcul__barre {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin-bottom: .5rem;
  min-height: clamp(2rem, 4.4vh, 2.4rem);
}

.calcul__barre .iconbtn {
  margin-left: auto;
}

/* L'unité d'angle reste lisible en permanence : c'est elle qui décide si
   sin 30 vaut 0,5 ou −0,988. Un clic bascule vers l'autre. */
.calcul__unite {
  font-family: var(--font-mono);
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .08em;
  background: var(--accent-soft);
  color: var(--accent);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-pill);
  padding: .22rem .7rem;
  cursor: pointer;
}

.calcul__unite:hover {
  filter: brightness(.97);
}

/* L'aperçu, au-dessus du calcul et aligné sur lui. Sa place est réservée même
   vide : sans cela, la première opération tapée ferait sauter tout le clavier. */
.calcul__apercu {
  min-height: 1.6em;
  text-align: right;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: clamp(1.3rem, 4.5vw, 1.9rem);
  line-height: 1.35;
  letter-spacing: -.02em;
  color: var(--accent);
  overflow-x: auto;
  white-space: nowrap;
}

.calcul__res--erreur {
  color: var(--text-3);
}

.calcul__bas {
  display: flex;
  align-items: center;
  gap: .7rem;
}

/* Le champ et son miroir partagent exactement les mêmes métriques : c'est ce
   qui fait tomber les deux textes l'un sur l'autre, au pixel près. Toute
   propriété qui déplace un caractère se déclare donc ici, pour les deux. */
.calcul__champ,
.calcul__miroir {
  text-align: right;
  padding: .15rem 0;
  font-family: var(--font-mono);
  font-size: clamp(1.05rem, 3.2vw, 1.45rem);
  letter-spacing: -.01em;
  line-height: 1.35;
  white-space: pre;
  overflow-x: hidden;
}

/* Ce qu'on tape se colle à droite, contre la touche d'effacement : en paysage,
   le pouce va de l'un à l'autre sans traverser l'écran. */
.calcul__zone {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
}

/* Le miroir porte la couleur, le champ porte le curseur. Le premier est en
   dessous et ne reçoit aucun clic ; le second est au-dessus, son texte rendu
   transparent pour ne pas doubler celui du miroir. */
.calcul__miroir {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  color: var(--text-2);
}

.calcul__champ {
  position: relative;
  z-index: 1;
  width: 100%;
  display: block;
  background: transparent;
  border: 0;
  color: transparent;
  /* Le curseur clignotant montre où la prochaine touche écrira. inputmode
     « none » garde ce curseur sans faire surgir le clavier du téléphone, qui
     ferait double emploi avec le pavé de l'outil. */
  caret-color: var(--accent);
}

/* Les signes qui se remplacent les uns les autres portent la couleur d'accent :
   la teinte dit qu'appuyer sur un autre opérateur échangera celui-ci, au lieu
   de s'ajouter à sa suite. Un moins qui n'est qu'un signe reste au ton du
   calcul — lui ne s'échange pas, il appartient au nombre qui suit. */
.calcul__miroir b {
  font-weight: inherit;
  color: var(--accent);
}

.calcul__champ::placeholder {
  color: var(--text-3);
  font-size: .86em;
}

.calcul__champ:focus {
  outline: none;
}

/* La touche d'effacement du cadre de saisie n'a ni fond ni cadre : elle se pose
   sur l'écran de la calculatrice comme un signe, non comme un bouton. Sa zone
   cliquable reste entière — c'est le dessin qui disparaît, pas la cible — et le
   survol met le signe en rouge, qui est ce qu'il fait. */
.calcul__eff {
  flex: 0 0 auto;
  background: none;
  color: var(--text-2);
  border: 0;
  border-radius: var(--r-control);
  padding: .5rem .8rem;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: color var(--dur) var(--ease),
    background-color var(--theme-dur) var(--theme-ease),
    border-color var(--theme-dur) var(--theme-ease);
}

.calcul__eff:hover {
  color: var(--danger);
}

.calcul__eff:active {
  transform: translateY(1px);
}

.calcul__err {
  font-size: .82rem;
  color: var(--danger);
  margin-top: .3rem;
  min-height: 1.2em;
  text-align: right;
}

/* ---- claviers, classes de base ------------------------------------------------ */

/* Les deux pavés se remplacent l'un l'autre sous 900 px, et se rangent côte à
   côte au-delà : dans les deux cas ils doivent faire la même hauteur, sinon
   l'écran au-dessus saute à chaque bascule. La boîte d'une touche est donc
   fixée ici une fois — marge verticale et hauteur de ligne — et les variantes
   ne changent que le corps du texte, qui n'a pas à être le même.

   Cette boîte suit la hauteur de la fenêtre, et sans marche d'escalier. Chaque
   mesure est une plafonnée : une valeur de repos, celle du confort, et en
   dessous une pente exprimée en pourcentage de l'écran. Le clavier ne dépasse
   donc jamais sa taille naturelle, et quand la place manque il se réduit peu à
   peu, autour de la moitié de la hauteur disponible.

   Auparavant tout tenait à des seuils : à un pixel de hauteur près, le clavier
   passait de 321 à 183 pixels d'un seul coup, et l'écran au-dessus sautait avec
   lui. C'est ce que ces trois clamp remplacent. */
.clavier {
  --touche-p: clamp(.3rem, calc(3.65vh - 9.35px), .85rem);
  --touche-l: clamp(1.2rem, 3.4vh, 1.45rem);
  --touche-gap: clamp(.3rem, .95vh, .5rem);
  display: grid;
  gap: var(--touche-gap);
  padding: clamp(.35rem, 1.75vh, .9rem) 1.1rem clamp(.5rem, 2.1vh, 1.1rem);
}

.clavier__pave {
  display: grid;
  gap: var(--touche-gap);
  grid-template-columns: repeat(4, 1fr);
}

.clavier__avance {
  display: grid;
  gap: var(--touche-gap);
  grid-template-columns: repeat(3, 1fr);
}

.touche {
  appearance: none;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text);
  border-radius: var(--r-control);
  font-family: var(--font-mono);
  font-size: clamp(.95rem, 2.2vh, 1.15rem);
  font-weight: 600;
  padding: var(--touche-p) .3rem;
  cursor: pointer;
  /* Bloc et non grille : « x » et son exposant doivent rester sur la même
     ligne, alors qu'une grille en ferait deux éléments empilés. */
  display: block;
  text-align: center;
  line-height: var(--touche-l);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), transform .06s var(--ease),
    color var(--theme-dur) var(--theme-ease);
}

.touche:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.touche:active {
  transform: translateY(1px);
}

/* Hauteur de ligne nulle pour l'exposant : sans cela son petit chiffre, qui
   déborde vers le haut, grandit la boîte de ligne — et les rangées portant un
   exposant deviennent plus hautes que les autres. Le clavier des fonctions
   dépassait ainsi celui du pavé de douze pixels. */
.touche sup {
  font-size: .68em;
  line-height: 0;
}

.touche svg {
  vertical-align: -.28em;
}

.touche--fn {
  font-size: clamp(.8rem, 1.8vh, .95rem);
  background: var(--surface-2);
  color: var(--text-2);
}

.touche--edit {
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 1rem;
}

.touche--op {
  background: var(--accent-soft);
  color: var(--accent);
}

.touche--util {
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 1rem;
}

.touche--libre {
  color: var(--text-3);
  cursor: default;
}

.touche--libre:hover {
  border-color: var(--line);
  background: var(--surface-2);
}

/* Le « 0 » large en bas : la disposition que l'œil connaît des calculatrices
   de poche. Le reste des touches se range tout seul autour. */
.touche--zero {
  grid-column: span 2;
}

.touche--egal {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
  font-size: 1.25rem;
}

.touche--egal:hover {
  background: var(--accent);
  border-color: var(--accent);
  filter: brightness(1.08);
}

/* ---- trois états de clavier ----------------------------------------------------
   Ils ne diffèrent pas par la taille des touches mais par ce qui est là :

     compact      — le pavé seul, quatre colonnes. L'effacement est dans le
                    cadre du résultat, à portée du pouce.
     intermédiaire — le pavé plus la colonne d'outils à droite : effacer,
                    touche libre, historique, aide, C.
     étendu       — les deux claviers côte à côte, colonne d'outils comprise.

   Dans les deux premiers, un seul clavier tient à l'écran : celui des
   fonctions prend la place du pavé au lieu de s'ajouter sous lui.
   ---------------------------------------------------------------------------- */
/* compact et intermédiaire : un seul clavier à la fois.

   Les bornes se rejoignent à deux centièmes de pixel près, et ce n'est pas de
   la coquetterie. Avec un écran à 150 % — le réglage courant sous Windows — la
   largeur de la fenêtre tombe sur des valeurs fractionnaires : à 899,33 px, ni
   « max-width: 899px » ni « min-width: 900px » ne s'appliquaient. Aucune des
   deux dispositions n'était donc active, les deux claviers s'empilaient l'un
   sous l'autre, et la calculatrice faisait 741 px de haut au lieu de 323. */
@media (max-width: 899.98px) {
  .clavier {
    grid-template-columns: 1fr;
    overflow: hidden;
  }

  .clavier__avance {
    display: none;
  }

  .clavier--avance .clavier__avance {
    display: grid;
  }

  .clavier--avance .clavier__pave {
    display: none;
  }
}

/* compact */
@media (max-width: 639.98px) {
  .touche--util {
    display: none;
  }
}

/* intermédiaire : la colonne d'outils apparaît, l'effacement la rejoint */
@media (min-width: 640px) and (max-width: 899.98px) {
  .clavier__pave {
    grid-template-columns: repeat(5, 1fr);
  }

  .calcul__eff {
    display: none;
  }
}

/* étendu */
@media (min-width: 900px) {
  .clavier {
    grid-template-columns: 1fr 1.35fr;
    align-items: stretch;
    gap: 1.1rem;
  }

  .clavier__pave {
    grid-template-columns: repeat(5, 1fr);
    align-content: stretch;
  }

  .clavier__avance {
    align-content: stretch;
  }

  .clavier__bascule {
    display: none;
  }

  .calcul__eff {
    display: none;
  }
}

/* ---- les mouvements du clavier -------------------------------------------------
   Deux natures, deux techniques, et c'est la distinction qui compte.

   La bascule entre les deux pavés ne concerne que le pavé qui entre : rien
   d'autre ne bouge. Une animation suffit, portée par une classe que le script
   pose au départ et retire à l'arrivée — sans quoi elle se rejouerait toute
   seule au prochain affichage du clavier, et viendrait glisser par le côté au
   milieu d'un autre mouvement.

   La descente et la remontée, elles, déplacent tout le reste : l'historique
   prend la hauteur libérée, le calcul en cours descend entre les deux. Une
   animation ne saurait pas faire cela — elle ne déplace que son propre
   élément, en laissant la mise en page où elle était. C'est donc la hauteur du
   clavier qui se referme, en transition : le navigateur recalcule la colonne à
   chaque image, et tout suit.
   ---------------------------------------------------------------------------- */

/* La hauteur exacte est posée par le script, qui seul peut la mesurer. */
.calc--plein .clavier {
  overflow: hidden;
  transition: height 300ms var(--ease), padding 300ms var(--ease), visibility 0s;
}

/* Le clavier replié ne doit plus attraper le curseur ni le tabulateur — mais
   seulement une fois arrivé en bas, d'où le retard sur la visibilité. */
.calc--plein.a-clavier-bas .clavier {
  /* Le rembourrage se referme avec la hauteur : en « border-box », une hauteur
     nulle ne descend pas en dessous du rembourrage, et il restait un talon de
     clavier de vingt-six pixels au bas de l'écran. */
  padding-top: 0;
  padding-bottom: 0;
  visibility: hidden;
  transition: height 300ms var(--ease), padding 300ms var(--ease), visibility 0s 300ms;
}

/* Une fois le mouvement fini, le clavier sort tout à fait de la mise en page.
   Une hauteur nulle ne fait que rogner les touches : leurs boîtes restent, et
   la section redevient défilable sur du vide, ce qui décale tout l'écran au
   premier coup de molette. La classe n'est posée qu'à l'arrivée, sinon il n'y
   aurait rien à animer. */
.calc--plein .clavier--replie {
  display: none;
}

/* Le temps d'une mesure, aucune transition ne doit s'amorcer. */
.sans-transition {
  transition: none !important;
}

/* La bascule ne concerne que le pavé qui entre, et seulement là où les deux se
   remplacent : au-delà de 900 px ils sont côte à côte et rien ne bouge. */
@media (max-width: 899.98px) {
  .clavier--bascule.clavier--avance .clavier__avance {
    animation: entre-gauche var(--dur) var(--ease);
  }

  .clavier--bascule:not(.clavier--avance) .clavier__pave {
    animation: entre-droite var(--dur) var(--ease);
  }
}

@keyframes entre-gauche {
  from {
    transform: translateX(-8%);
    opacity: 0;
  }

  to {
    transform: none;
    opacity: 1;
  }
}

@keyframes entre-droite {
  from {
    transform: translateX(8%);
    opacity: 0;
  }

  to {
    transform: none;
    opacity: 1;
  }
}

/* ---- pleine page ---------------------------------------------------------------
   La calculatrice occupe toute la page, et rien de plus : on ne quitte pas
   l'onglet. L'API du navigateur ferait basculer l'écran entier, escamoter la
   barre d'adresse et les onglets ; c'est trop pour une calculatrice.

   La mise en page s'inverse par rapport à la page normale. En haut, l'écran :
   l'historique d'abord, puis le calcul en cours, séparés d'un trait. En bas,
   juste au-dessus des touches, les deux réglages qui servent pendant le
   calcul — l'unité d'angle et la bascule de clavier. Le bouton de sortie, lui,
   monte seul dans le coin supérieur droit, là où l'œil le cherche.
   ------------------------------------------------------------------------------ */

.calc--plein {
  /* Au-dessus de la barre de navigation du site, posée à 110 : c'est elle
     qui restait visible par-dessus le plein écran. */
  position: fixed;
  inset: 0;
  z-index: 200;
  border-radius: 0;
  border: 0;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  overflow: hidden;
  animation: plein-entre 200ms var(--ease);
}

/* L'écran prend la place libre, le clavier garde sa taille naturelle :
   agrandir la fenêtre révèle de l'écran, cela ne distend pas les touches. */
/* C'est l'historique qui prend la place libre, pas le bloc de saisie : ils ne
   peuvent pas grandir tous les deux sans pousser le clavier hors de l'écran. */
.calc--plein .calcul {
  flex: 0 0 auto;
  order: 2;
}

.calc--plein .clavier {
  flex: 0 0 auto;
  order: 3;
}

/* Ni l'aperçu ni la saisie ne suivent la largeur. Ils l'ont fait, et cela se
   voyait : en élargissant la fenêtre, leur corps grandissait, le bloc de calcul
   gagnait en hauteur, l'historique en perdait autant, et la barre DEG/RAD
   descendait avec. Un mouvement vertical déclenché par un geste horizontal —
   discret, mais faux. En pleine page, c'est la hauteur seule qui commande. */
.calc--plein .calcul__champ,
.calc--plein .calcul__miroir {
  font-size: clamp(1rem, 3.4vh, 1.8rem);
}

html.a-plein-ecran,
body.a-plein-ecran {
  overflow: hidden;
}

/* La barre descend sous le calcul, contre le clavier. */
.calc--plein .calcul__barre {
  order: 4;
  margin: .5rem 0 0;
}

.calc--plein .calcul__apercu {
  order: 1;
}

.calc--plein .calcul__bas {
  order: 2;
}

.calc--plein .calcul__err {
  order: 3;
  margin-top: .2rem;
}

/* Le bouton de sortie quitte la barre et monte dans le coin, la bascule de
   thème juste à sa gauche : en pleine page, la barre du site est cachée
   derrière la calculatrice, et c'est là qu'elle vivait. */
.calcul__theme {
  display: none;
}

.calc--plein #btn-plein,
.calc--plein .calcul__theme {
  position: absolute;
  z-index: 3;
  margin-left: 0;
}

.calc--plein .calcul__theme {
  display: grid;
}

/* Leur écart aux bords suit la hauteur de la fenêtre — voir la section des
   plafonnées, plus bas. */

/* Les volets n'existent qu'en pleine page : ailleurs, les mêmes touches mènent
   aux blocs de la page, déjà sous les yeux. */
.volet {
  display: none;
}

.volet__tete {
  display: flex;
  align-items: center;
  gap: .7rem;
  margin-bottom: .7rem;
}

.volet__titre {
  font-family: var(--font-display);
  font-size: .74rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-right: auto;
}

.volet__retour {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 2.2rem;
  height: 2.2rem;
  cursor: pointer;
  background: var(--surface-2);
  color: var(--text-2);
  border: 1px solid var(--line);
  border-radius: var(--r-control);
}

.volet__retour:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* L'historique est là en permanence : il occupe ce que le clavier laisse.
   Même surface que l'écran, aucun cadre — c'en est la suite, pas un panneau
   posé dessus. Seul un trait le sépare du calcul en cours. */
.calc--plein #volet-histo {
  display: flex;
  flex-direction: column;
  order: 1;
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  background: var(--surface-2);
  border: 0;
  border-radius: 0;
  border-bottom: 1px solid var(--line-strong);
  /* La place de la barre de défilement est réservée en permanence. Sans cela,
     elle apparaissait dès le quatrième calcul, prenait quinze pixels et tirait
     toutes les lignes vers la gauche : l'historique se désalignait de l'écran
     et du clavier, puis se réalignait quand on effaçait une ligne. Un décalage
     intermittent se remarque bien plus qu'un décalage constant. */
  scrollbar-gutter: stable;
  scrollbar-width: thin;
  scrollbar-color: var(--line-strong) transparent;
}

/* Sa largeur exacte n'est pas la même partout : rien du tout quand le système
   dessine la barre par-dessus le contenu, une dizaine de pixels quand il lui
   réserve une gouttière — et « scrollbar-width » l'emporte sur les règles
   webkit, qui sont donc sans effet ici. Le script mesure le volet lui-même et
   publie la valeur dans --gouttiere. Par défaut, zéro : c'est le cas où rien
   n'est à retrancher. */
/* Une bande réservée en haut du volet. Elle a deux emplois : laisser passer le
   bouton de sortie, à droite, et porter sur téléphone les trois touches que le
   clavier compact n'a pas — l'aide, le clavier haut ou bas, la touche libre.
   Elle reste collée en haut quand la liste défile, sans quoi les premières
   lignes passeraient sous le bouton. */
.calc--plein #volet-histo .volet__outils {
  display: flex;
  align-items: center;
  gap: .4rem;
  flex: 0 0 auto;
  position: sticky;
  z-index: 2;
  background: var(--surface-2);
}

/* Au-delà du téléphone, la colonne d'outils du clavier existe : les mêmes
   touches y sont déjà, et les répéter ici n'apporterait rien. La bande, elle,
   reste — c'est elle qui dégage le bouton de sortie. */
.calc--plein #volet-histo .volet__outil {
  display: none;
}

@media (max-width: 639.98px) {
  .calc--plein #volet-histo .volet__outil {
    display: grid;
  }
}

.volet__outils {
  display: none;
}

.volet__outil {
  place-items: center;
  cursor: pointer;
  width: 1.95rem;
  height: 1.95rem;
  background: none;
  color: var(--text-3);
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  font-family: var(--font-mono);
  font-size: 1rem;
  line-height: 1;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
    background-color var(--theme-dur) var(--theme-ease);
}

.volet__outil:hover {
  color: var(--accent);
  border-color: var(--accent-line);
}

.volet__outil--libre {
  cursor: default;
  opacity: .55;
}

.volet__outil--libre:hover {
  color: var(--text-3);
  border-color: var(--line);
}

/* Une liste courte se pose contre le trait plutôt que de flotter en haut. */
.calc--plein #histo-volet {
  margin-top: auto;
}

/* Clavier abaissé : l'historique gagne toute la place libérée. Il n'a pas
   d'animation à lui — c'est la hauteur du clavier qui commande, et il la suit
   image par image parce qu'il est le seul élément élastique de la colonne. */
.calc--plein .calcul__remonter {
  display: none;
}

.calc--plein.a-clavier-bas .calcul__remonter {
  display: grid;
}

.calcul__remonter {
  display: none;
  place-items: center;
  margin-left: auto;
  width: 2.1rem;
  height: 2.1rem;
  cursor: pointer;
  background: var(--accent-soft);
  color: var(--accent);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-control);
}

.calcul__remonter:hover {
  filter: brightness(.97);
}

/* Aide : un menu à part entière, qui couvre la calculatrice. En fixed et non
   en absolute : la section peut défiler, un panneau en absolute partirait
   avec elle au lieu de rester devant. */
.calc--plein.a-aide #volet-aide {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 4;
  background: var(--surface);
  overflow: auto;
  padding: 1rem clamp(1.1rem, 4vw, 2.4rem) 2rem;
  animation: aide-entre 190ms var(--ease);
}

.calc--plein.a-aide-sort #volet-aide {
  animation: aide-sort 170ms var(--ease) forwards;
}

.calc--plein.a-aide #volet-aide .volet__tete {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface);
  padding: .6rem 0 .8rem;
  margin-bottom: 0;
}

/* Une colonne, ou deux quand la largeur le permet : au-delà, les lignes
   deviennent trop longues pour être lues d'un trait. */
.calc--plein #volet-aide .aide {
  grid-template-columns: 1fr;
  gap: 1.4rem;
}

@media (min-width: 720px) {
  .calc--plein #volet-aide .aide {
    grid-template-columns: 1fr 1fr;
  }
}

/* ---- animations ------------------------------------------------------------------
   Toutes sont des animations d'entrée, jouées une fois : elles ne dépendent
   d'aucun état antérieur et ne peuvent donc pas rester coincées à mi-chemin,
   contrairement aux transitions entre deux états que ce fichier a connues.
   ------------------------------------------------------------------------------ */

@keyframes plein-entre {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

@keyframes aide-entre {
  from {
    opacity: 0;
    transform: translateY(10px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes aide-sort {
  from {
    opacity: 1;
    transform: none;
  }

  to {
    opacity: 0;
    transform: translateY(8px);
  }
}

/* L'aperçu tressaille brièvement à chaque valeur nouvelle : le regard, posé
   sur les touches, est ainsi averti que le résultat a changé. */
.calcul__apercu--maj {
  animation: apercu-maj 200ms var(--ease);
}

@keyframes apercu-maj {
  from {
    opacity: .35;
    transform: translateY(5px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

/* Une touche enfoncée s'éclaire et s'enfonce, le temps du contact. */
.touche:active {
  transform: translateY(1px) scale(.97);
}

/* Personne ne devrait subir un mouvement qu'il n'a pas demandé. */
@media (prefers-reduced-motion: reduce) {

  .calc--plein,
  .calc--plein.a-aide #volet-aide,
  .clavier--bascule.clavier--avance .clavier__avance,
  .clavier--bascule:not(.clavier--avance) .clavier__pave,
  .calcul__apercu--maj {
    animation: none;
  }

  .touche {
    transition: none;
  }

  /* Le clavier prend sa hauteur d'un coup. La visibilité n'attend plus la fin
     d'une transition qui n'a pas lieu, sans quoi il resterait cliquable. */
  .calc--plein .clavier {
    transition: none;
  }

  .calc--plein.a-clavier-bas .clavier {
    transition: none;
  }
}

/* Historique : une pile de calculs, chacun réutilisable d'un clic. */
.histo__vide {
  font-size: .86rem;
  color: var(--text-3);
}

.histo__liste {
  list-style: none;
  display: grid;
  gap: .3rem;
}

/* Une ligne d'historique se lit d'un trait mais se manipule en trois endroits :
   le calcul, son résultat, et le retrait. Trois boutons collés dans un même
   cadre plutôt qu'un seul bouton et un menu — ce qu'on veut reprendre est déjà
   sous les yeux, il suffit de le viser. */
.histo__item {
  display: flex;
  align-items: stretch;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  overflow: hidden;
}

.histo__item:hover {
  border-color: var(--accent);
}

.histo__part {
  text-align: left;
  cursor: pointer;
  min-width: 0;
  background: var(--surface);
  border: 0;
  padding: .5rem .7rem;
  font-family: var(--font-mono);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
    border-color var(--theme-dur) var(--theme-ease);
}

.histo__part:hover {
  background: var(--accent-soft);
  color: var(--accent);
}

.histo__part--expr {
  flex: 1 1 auto;
  font-size: .82rem;
  color: var(--text-3);
}

.histo__part--val {
  flex: 0 0 auto;
  font-size: .95rem;
  font-weight: 700;
  color: var(--text);
  text-align: right;
}

.histo__sup {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  cursor: pointer;
  width: 2rem;
  background: var(--surface);
  border: 0;
  color: var(--text-3);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
    border-color var(--theme-dur) var(--theme-ease);
}

.histo__sup:hover {
  background: var(--surface-2);
  color: var(--danger);
}

/* Un calcul abandonné — effacé par « C » sans avoir été validé. Il garde sa
   place dans la liste parce qu'on abandonne rarement pour de bon : c'est
   souvent une faute de frappe au milieu d'un long calcul, et le reprendre
   d'un clic vaut mieux que le retaper. Le cadre en pointillé et le tiret à la
   place du résultat disent qu'il n'a jamais abouti. */
.histo__item--abandonne {
  border-style: dashed;
}

.histo__item--abandonne .histo__part--expr {
  color: var(--text-3);
}

.histo__abandon {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  background: var(--surface);
  padding: .5rem .7rem;
  font-family: var(--font-mono);
  color: var(--text-3);
}

/* Aide : des colonnes courtes plutôt qu'un bloc de texte. */
.aide {
  display: grid;
  gap: 1.1rem;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}

.aide__titre {
  font-family: var(--font-display);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: .45rem;
}

.aide__liste {
  list-style: none;
  display: grid;
  gap: .35rem;
}

.aide__liste li {
  font-size: .84rem;
  color: var(--text-2);
  line-height: 1.5;
}

.aide__liste b {
  font-family: var(--font-mono);
  font-weight: 700;
  color: var(--text);
}

/* ---- ce qui suit la hauteur de la fenêtre --------------------------------------
   Tout ce qui devait se resserrer sur un écran court le fait ici, par des
   plafonnées plutôt que par des seuils. Une plafonnée dit trois choses à la
   fois : la valeur de repos, la pente en pourcentage de l'écran, et le plancher
   sous lequel on ne descend pas. Le résultat varie pixel par pixel avec la
   fenêtre, au lieu de sauter à un endroit donné.

   Les seuils avaient deux défauts, et l'un n'était pas prévisible depuis le
   fichier : le clavier passait de 321 à 183 pixels à un pixel de hauteur près,
   et les boutons des coins changeaient d'écart au même instant — d'où une
   impression de mouvement désordonné en redimensionnant la fenêtre.
   ---------------------------------------------------------------------------- */

/* Les coins de la pleine page. Les deux boutons se suivent : le second se place
   par rapport au premier, ils ne peuvent donc pas se séparer. */
.calc--plein {
  --coin-t: clamp(.4rem, 1.15vh, .8rem);
  --coin-r: .9rem;
  /* constant : rien ne justifie que les coins bougent en largeur */
}

.calc--plein #btn-plein {
  top: var(--coin-t);
  right: var(--coin-r);
}

.calc--plein .calcul__theme {
  top: var(--coin-t);
  right: calc(var(--coin-r) + 2.5rem);
}

/* La gouttière est retranchée de la marge droite : les lignes de l'historique
   retombent alors exactement sur le bord de l'écran et du clavier. */
.calc--plein #volet-histo {
  --marge-d: calc(var(--marge-h) - var(--gouttiere, 0px));
  padding: var(--coin-t) var(--marge-d) .8rem var(--marge-h);
}

.calc--plein #volet-histo .volet__outils {
  top: calc(var(--coin-t) * -1);
  min-height: clamp(2rem, 4.4vh, 2.2rem);
  margin: calc(var(--coin-t) * -1) calc(var(--marge-d) * -1) .35rem calc(var(--marge-h) * -1);
  padding: var(--coin-t) calc(var(--coin-r) + 5rem) .2rem var(--marge-h);
}

/* L'écran de la calculatrice. */
.calc--plein .calcul {
  padding-top: clamp(.3rem, 1.5vh, .8rem);
  padding-bottom: clamp(.35rem, 1.4vh, .8rem);
}

.calc--plein .calcul__apercu {
  font-size: clamp(1.05rem, 3.5vh, 1.9rem);
  min-height: 1.3em;
}

.calc--plein .calcul__barre {
  margin-top: clamp(.3rem, .8vh, .5rem);
}

/* Les lignes d'historique : à quarante-trois pixels utiles en paysage sur
   téléphone, une ligne de quarante et un ne tenait jamais tout à fait, et la
   dernière restait rognée en permanence. */
.calc--plein .histo__liste {
  gap: clamp(.22rem, .5vh, .3rem);
}

.calc--plein .histo__part {
  padding: clamp(.28rem, .75vh, .5rem) .7rem;
}

.calc--plein .histo__part--expr {
  font-size: clamp(.76rem, 1.55vh, .82rem);
}

.calc--plein .histo__part--val {
  font-size: clamp(.86rem, 1.85vh, .95rem);
}

.calc--plein .histo__sup {
  width: clamp(1.7rem, 3.6vh, 2rem);
}

/* Les marges latérales suivent la largeur, sans marche : au seuil, la pastille
   DEG se décalait de cinq pixels d'un coup. La même valeur partout. */
.calcul {
  padding-inline: var(--marge-h);
}

.clavier {
  padding-inline: var(--marge-h);
}

/* ==========================================================================
   Palettes de couleurs

   La disposition est celle d'origine : un bandeau generateur en couleur, la
   palette en grand dessous, les onglets d'harmonie et les cadenas au pied,
   puis le catalogue. Ce qui change, c'est d'ou viennent les valeurs — plus
   aucune mesure ni couleur en dur, tout passe par les variables de la charte.

   Le bandeau garde son fond d'accent : c'est lui qui fait comprendre en une
   seconde ou est l'outil et ou est le catalogue. Les composants qui vivent
   dessus — boutons, onglets, cadenas — sont donc declines en clair, puisque
   les boutons de la charte sont faits pour un fond de surface.
   ========================================================================== */

.atelier--palettes {
  gap: 1.4rem;
}

/* ---- le bandeau generateur -----------------------------------------------

   Sur surface, comme les panneaux des quatre autres outils : aucun d'eux n'a
   d'aplat colore, et un bandeau d'accent faisait de Palettes une piece
   rapportee. L'accent reste, mais la ou il est chez les autres — le bouton
   principal, l'onglet choisi, le cadenas ferme.

   Les boutons, la liste deroulante et les icones sont maintenant ceux de la
   charte : plus rien a redecrire ici. */

.genhero {
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-card);
  padding: clamp(1.1rem, 2.6vw, 1.6rem);
}

.genhero__tete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .8rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}

.genhero__quoi {
  min-width: 0;
}

.genhero__titre {
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 700;
}

.genhero__sous {
  font-size: .82rem;
  color: var(--text-3);
  margin-top: .2rem;
}

/* Pas « .touche » : ce nom appartient déjà aux touches du clavier de la
   calculatrice, qui sont en display:block. Le rappel de raccourci en
   héritait et occupait une ligne entière à lui seul. */
.rappel-touche {
  display: inline;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: .74rem;
  background: var(--surface-2);
  border: 1px solid var(--line);
  padding: .08rem .35rem;
  border-radius: 4px;
}

.genhero__actions {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
}

.ambiance {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
}

.ambiance__cle {
  font-size: .82rem;
  font-weight: 560;
  color: var(--text-2);
}

.ambiance__sel {
  width: auto;
  padding-block: .45rem;
}

/* ---- la palette, en grand -------------------------------------------------

   Cinq parts egales qui s'ecartent au survol : c'est le geste de l'original,
   et il sert — la part survolee montre son code sans qu'on ait a viser. */
.vive {
  display: flex;
  height: clamp(7rem, 18vh, 8.75rem);
  border-radius: var(--r-control);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  list-style: none;
  margin: 0;
  padding: 0;
}

.vivepart {
  flex: 1;
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  transition: flex .3s var(--ease);
}

.vive:hover .vivepart:hover {
  flex: 1.5;
}

.vivepart__btn {
  appearance: none;
  border: 0;
  background: none;
  cursor: pointer;
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: .75rem;
  color: inherit;
}

.vivepart__hex {
  font-family: var(--font-mono);
  font-size: .72rem;
  letter-spacing: .05em;
  font-weight: 700;
  color: #fff;
  background: rgb(0 0 0 / .34);
  padding: .2rem .45rem;
  border-radius: 5px;
  backdrop-filter: blur(4px);
  opacity: 0;
  transform: translateY(4px);
  transition: opacity .2s var(--ease), transform .2s var(--ease);
  pointer-events: none;
}

.vive:hover .vivepart__hex,
.vivepart__btn:focus-visible .vivepart__hex {
  opacity: 1;
  transform: none;
}

/* La coche de copie, sur la part meme : le toast en bas d'ecran dit la meme
   chose, mais trop loin pour qu'on sache laquelle a ete prise. */
.vivepart::after {
  content: 'Copié';
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgb(0 0 0 / .42);
  color: #fff;
  font-size: .8rem;
  font-weight: 700;
  opacity: 0;
  pointer-events: none;
  transition: opacity .15s var(--ease);
}

.vivepart.is-copiee::after {
  opacity: 1;
}

/* ---- le pied du bandeau --------------------------------------------------- */

/* Les onglets a gauche, les trois actions a droite, et rien entre les deux :
   ce sont deux familles de commandes, la separation le dit. */
.genhero__pied {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
  margin-top: .9rem;
}

.genhero__pied .roleswitch {
  margin-right: auto;
}

.modes {
  display: flex;
  gap: 2px;
  padding: 3px;
  background: rgb(0 0 0 / .18);
  border-radius: var(--r-pill);
  flex-wrap: wrap;
  max-width: 100%;
}

.modes__opt {
  appearance: none;
  border: 0;
  background: none;
  cursor: pointer;
  font-family: inherit;
  font-size: .76rem;
  font-weight: 620;
  color: rgb(255 255 255 / .64);
  padding: .34rem .8rem;
  border-radius: var(--r-pill);
  white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.modes__opt:hover {
  color: #fff;
}

.modes__opt[aria-pressed="true"] {
  background: rgb(255 255 255 / .22);
  color: #fff;
}

/* Un cadenas par couleur, pose sous elle et sur son rythme.

   Groupes a droite de la barre de commandes, ils tombaient n'importe ou :
   le premier se retrouvait sous la quatrieme couleur, et les trois boutons
   d'action qui suivaient formaient avec eux une file de huit carres
   identiques dont rien ne disait qu'ils faisaient deux choses differentes.

   Sur la meme grille que la palette, chacun designe sa couleur sans qu'on
   ait a le deviner. Ils restent visibles : reserves au survol ils etaient
   introuvables, et la fonction la plus utile de l'outil passait inapercue. */
.verrous {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  justify-items: center;
  margin-top: .5rem;
}

.verrou {
  appearance: none;
  cursor: pointer;
  width: 1.9rem;
  height: 1.9rem;
  border-radius: var(--r-control);
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text-3);
  display: grid;
  place-items: center;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
    border-color var(--dur) var(--ease);
}

.verrou:hover {
  color: var(--text);
  border-color: var(--line-strong);
}

/* Ferme, il prend l'accent : c'est le seul etat de la page qui merite
   d'etre vu de loin. */
.verrou[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

.icoclair {
  appearance: none;
  cursor: pointer;
  width: 2rem;
  height: 2rem;
  border-radius: var(--r-control);
  border: 1px solid rgb(255 255 255 / .22);
  background: rgb(255 255 255 / .10);
  color: rgb(255 255 255 / .78);
  display: grid;
  place-items: center;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.icoclair:hover {
  background: rgb(255 255 255 / .2);
  color: #fff;
}

@media (max-width: 760px) {
  .genhero__actions {
    width: 100%;
  }

  .ambiance {
    flex: 1 1 100%;
    justify-content: space-between;
  }
}

/* ---- le catalogue --------------------------------------------------------- */

.cat__tete {
  margin-top: .4rem;
}

/* La barre de recherche suit le defilement, comme celle de Logiciels.

   Elle se cale a zero et non a --topbar-h : sur les pages d'outils la barre
   du site est en flux, elle s'en va avec le haut de page et ne laisse aucune
   hauteur a compenser. La caler dessous ouvrirait un vide de soixante-quatre
   pixels sous lequel on verrait passer les cartes.

   Les marges negatives lui rendent la largeur de l'atelier : sans elles, le
   fond s'arreterait au texte et les cartes passeraient dans la gouttiere. */
.cat__barre {
  position: sticky;
  top: 0;
  z-index: 30;
  margin-inline: calc(-1 * var(--gut));
  padding: .5rem var(--gut);
  background: color-mix(in srgb, var(--bg) 93%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

.cat__label {
  font-family: var(--font-display);
  font-size: .72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--text-3);
}

.pilules {
  display: flex;
  gap: .35rem;
  flex-wrap: wrap;
}

.pilule {
  appearance: none;
  cursor: pointer;
  padding: .28rem .75rem;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-2);
  font-family: inherit;
  font-size: .76rem;
  font-weight: 600;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
    background var(--dur) var(--ease);
}

.pilule:hover {
  color: var(--text);
  border-color: var(--line-strong);
}

.pilule[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

/* Les dominantes se choisissent sur la couleur elle-meme : un mot ne dit pas
   « turquoise » aussi vite qu'un rond turquoise. */
.points {
  display: flex;
  gap: .4rem;
  flex-wrap: wrap;
  align-items: center;
}

.points .point {
  appearance: none;
  cursor: pointer;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  border: 2px solid transparent;
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / .14);
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.points .point:hover {
  transform: scale(1.16);
}

.points .point[aria-pressed="true"] {
  border-color: var(--text);
  transform: scale(1.16);
}

.points .point--tous {
  background: var(--surface);
  color: var(--text-3);
  display: grid;
  place-items: center;
  font-size: .64rem;
  font-weight: 700;
  width: auto;
  padding: .28rem .7rem;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
}

.points .point--tous[aria-pressed="true"] {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
}

/* ---- la grille de cartes -------------------------------------------------- */

.palgrille {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
  gap: .9rem;
}

.palcarte {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  overflow: hidden;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
    border-color var(--dur) var(--ease);
}

.palcarte:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
  border-color: var(--line-strong);
}

.palcarte__bandes {
  display: flex;
  height: 6.25rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.palbande {
  flex: 1;
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  transition: flex .25s var(--ease);
}

.palcarte:hover .palbande:hover {
  flex: 1.5;
}

.palbande__btn {
  appearance: none;
  border: 0;
  background: none;
  cursor: pointer;
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: .4rem;
}

.palbande__hex {
  font-family: var(--font-mono);
  font-size: .6rem;
  font-weight: 700;
  letter-spacing: .04em;
  color: #fff;
  background: rgb(0 0 0 / .34);
  padding: .1rem .3rem;
  border-radius: 4px;
  backdrop-filter: blur(4px);
  opacity: 0;
  transform: translateY(3px);
  transition: opacity .18s var(--ease), transform .18s var(--ease);
  pointer-events: none;
}

.palcarte:hover .palbande__hex {
  opacity: 1;
  transform: none;
}

.palbande::after {
  content: 'Copié';
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgb(0 0 0 / .42);
  color: #fff;
  font-size: .68rem;
  font-weight: 700;
  opacity: 0;
  pointer-events: none;
  transition: opacity .15s var(--ease);
}

.palbande.is-copiee::after {
  opacity: 1;
}

.palcarte__pied {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .6rem;
  padding: .7rem .85rem;
}

.palcarte__nom {
  font-family: var(--font-display);
  font-size: .92rem;
  font-weight: 700;
}

.palcarte__reg {
  font-size: .72rem;
  color: var(--text-3);
  margin-top: .05rem;
}

.palcarte__actions {
  display: flex;
  gap: .3rem;
  flex: none;
}

.icocarte {
  appearance: none;
  cursor: pointer;
  width: 1.8rem;
  height: 1.8rem;
  border-radius: var(--r-control);
  border: 1px solid var(--line);
  background: none;
  color: var(--text-3);
  display: grid;
  place-items: center;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.icocarte:hover {
  color: var(--text);
  border-color: var(--line-strong);
}

/* ---- le depot d'image, dans la fenetre ------------------------------------ */

.depot {
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-control);
  background: var(--surface-2);
  color: var(--text-2);
  padding: 2rem 1.2rem;
  text-align: center;
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.depot:hover,
.depot.is-survole {
  background: var(--accent-soft);
  border-color: var(--accent-line);
  color: var(--accent);
}

.depot__titre {
  font-weight: 600;
  margin-top: .5rem;
}

.depot__hint {
  font-size: .8rem;
  color: var(--text-3);
  margin-top: .2rem;
}

.depot.is-survole .depot__hint {
  color: inherit;
}

.extrait {
  display: flex;
  gap: .9rem;
  align-items: flex-start;
  flex-wrap: wrap;
}

.extrait__vue {
  width: 10rem;
  height: 7.5rem;
  object-fit: cover;
  border-radius: var(--r-control);
  border: 1px solid var(--line);
  flex: none;
}

.extrait__corps {
  flex: 1 1 14rem;
  min-width: 0;
}

.extrait__gamme {
  display: flex;
  height: 4rem;
  border-radius: var(--r-control);
  overflow: hidden;
  list-style: none;
  margin: 0 0 .7rem;
  padding: 0;
}

.extrait__gamme li {
  flex: 1;
}

/* ==========================================================================
   Seconde barre : ce qui lui est propre dans SEARCH

   Son apparence est dans css/barre-mode.css, chargee par l'en-tete du site
   sur toutes les pages qui la portent — Ressources, ENSALL, les Stages, la
   Bibliotheque de Bazar. Elle vivait ici, ou seules les pages de SEARCH la
   voyaient ; il ne reste ici que les deux decisions valables dans cette
   section-ci.

   « overflow-x: hidden » sur <body> en fait une boite de defilement, ce qui
   annule position:sticky pour tout ce qu'il contient. « clip » coupe le
   debordement horizontal sans creer de boite : sticky redevient possible. Le
   repli « hidden » sert aux navigateurs qui ignorent « clip ».

   Mais rendre sticky possible le rendrait aussi effectif pour la barre du
   site, qui porte .is-sticky et se mettrait a suivre le defilement — ce qu'on
   ne veut pas ici. On la repasse donc en flux : dans SEARCH une seule barre
   accompagne la lecture, celle du mode, et elle se cale tout en haut de
   l'ecran. Ailleurs sur le site les deux barres restent et s'empilent, d'ou
   --barre-mode-top remis a zero pour cette section seulement.
   ========================================================================== */
body {
  overflow-x: hidden;
  overflow-x: clip;
}

nav.main-menu.is-sticky {
  position: relative;
}

:root {
  --barre-mode-top: 0px;
}