/* SOIKO — la plateforme.
 *
 * Müller-Brockmann pour de bon : une grille qui se voit — une colonne de
 * menus, une colonne de travail —, une échelle typographique franche, et des
 * couleurs qui DÉSIGNENT au lieu de décorer.
 *
 *   --accent  la marque : titres, repères, boutons, éléments actifs
 *   --alerte  ce qui ne va pas, et RIEN d'autre : une erreur, un refus
 *   --gris    ce qui se tait : libellés, valeurs absentes
 *   --succes  la coche d'une réussite, et nulle part ailleurs
 *
 * Le rouge servait aux deux premiers ; un écran où tout crie ne hiérarchise
 * plus rien. Changer la marque tient en une ligne, ci-dessous.
 */

:root {
  color-scheme: dark;
  /* Ambiance « Fumée · jaune signal », choisie le 2026-09-12. Le fond quitte
     le noir absolu : les filets s'y détachent, et les yeux tiennent une
     heure. Le noir pur reste splendide sur une affiche ; un écran de travail
     n'est pas une affiche. */
  --noir: #17181a;
  --encre: #f2f3f4;
  --gris: #9aa0a6;
  --accent: #f2c200;
  --accent-encre: #17181a;
  --alerte: #e2001a;
  --succes: #2fbf5b;
  /* Le rouge d'une NOTE sous un champ : l'alerte éclaircie, lisible en petit sur le fond sombre. */
  --alerte-texte: #ff6b6b;
  /* Le champ est CLAIR sur le fond sombre : c'est le procédé de l'affiche —
     le blanc désigne l'endroit où l'on écrit, au lieu d'un creux cerné d'un
     trait qu'il faut chercher. Mesuré : la case se détache du fond à 14,7
     contre 1, là où le champ sombre n'atteignait que 1,1. */
  --champ: #ece9e3;
  --champ-actif: #ffffff;
  --champ-encre: #15161a;
  --champ-bord: #ece9e3;
  --survol: #1e2023;
  --trait: #34373b;
  --bord: #74787e;
  --estompe: #7b776f;
  --eteint: #55585d;
  --sur-alerte: #ffffff;
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font: 15px/22px 'Helvetica Neue', Helvetica, Arial, sans-serif;
  color: var(--encre);
  background: var(--noir);
  -webkit-text-size-adjust: 100%;
}

body {
  min-height: 100vh;
}

/* ── La grille : un sixième pour les menus, le reste pour le travail ────── */

.cadre {
  display: grid;
  grid-template-columns: minmax(180px, 1fr) 5fr;
  gap: 0;
  min-height: 100vh;
  max-width: 1440px;
  margin: 0 auto;
}

/* La bande des menus est FIGÉE : on descend dans un tableau de deux cents
   lignes sans perdre de vue où l'on est ni comment en sortir. Elle défile
   pour elle-même si elle devient plus haute que l'écran.
   #menus et non « nav » : les rangées d'onglets sont aussi des <nav>, et
   elles devenaient sur téléphone un panneau fixe posé sur la page. */
#menus {
  position: sticky;
  top: 0;
  align-self: start;
  max-height: 100vh;
  overflow-y: auto;
  border-right: 1px solid var(--trait);
  padding: 0 24px 48px;
}

/* Avant d'entrer, il n'y a ni menus ni parc : la page redevient une seule
   colonne, centrée dans l'écran. Sans cela, le formulaire tombait dans la
   colonne étroite de la grille — celle des menus, devenue vide. */
.cadre.seul {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: calc(100vh - 16px);
  padding: 48px 24px;
}

.cadre.seul .travail {
  width: 100%;
  max-width: 420px;
  padding: 0;
}

.cadre.seul h2:first-child {
  margin-top: 0;
}

.marque-seule {
  margin-bottom: 32px;
}

/* Deux classes portent le même h1 ; celle-ci doit l'emporter, d'où le
   sélecteur plus précis. Avant, « .marque h1 », écrit plus bas, gagnait par
   simple ordre d'apparition — et le titre de la page d'entrée restait petit. */
.marque.marque-seule h1 {
  font-size: 30px;
  line-height: 32px;
}

.travail {
  padding: 0 32px 64px;
  min-width: 0;
}

/* ── Le bandeau et le titre, comme une affiche ──────────────────────────── */

.bandeau {
  height: 8px;
  background: var(--accent);
}

/* ── La console d'un routeur ──────────────────────────────────────────────
   Le menu du routeur remplace celui de la plateforme : son titre dit dans
   quelle machine on se trouve, et « Quitter » ramène au parc. */
.menu-titre {
  padding: 10px 0 6px;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}

.menu-retour {
  margin-top: 16px;
  color: var(--gris);
}

/* Le routeur ouvert, EN RETRAIT sous « Routeurs » : le décalage et le filet
   disent l'appartenance — ce menu-là gouverne une machine, pas le parc.
   Décision de l'utilisateur, le 2026-09-18. */
.sous-menu {
  margin: 2px 0 8px 4px;
  padding-left: 14px;
  border-left: 1px solid var(--trait);
}

.sous-menu .menu-titre {
  padding-top: 4px;
}

/* La tête de flèche PLEINE, au bout du bouton : elle dit qu'un routeur est
   déplié là-dessous, et que le bouton le repliera. */
.menu button.deplie::after {
  content: '';
  margin-left: auto;
  width: 0;
  height: 0;
  flex: none;
  border-top: 6px solid currentColor;
  border-right: 5px solid transparent;
  border-left: 5px solid transparent;
}

/* Les onglets du hotspot : la rangée de Mikhmon, au trait de SOIKO. */
.onglets {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--trait);
}

.onglets button {
  min-width: 0;
  height: auto;
  padding: 9px 14px;
  background: transparent;
  color: var(--gris);
  border: 0;
  border-bottom: 3px solid transparent;
  font-size: 12px;
  letter-spacing: 0.04em;
  cursor: pointer;
}

.onglets button:hover {
  color: var(--encre);
  background: var(--survol);
}

.onglets button[aria-current='true'] {
  color: var(--encre);
  border-bottom-color: var(--accent);
}

/* Deux gestes sur un même lot — l'imprimer, le confier — se séparent d'un
   filet : collés, on lisait « Exporter en CSV » comme le titre du suivant. */
#form-confier {
  margin-top: 40px;
  padding-top: 16px;
  border-top: 1px solid var(--trait);
}

/* La caméra du scan : la largeur d'un champ long, jamais plus haute que l'écran. */
.camera {
  display: block;
  width: 100%;
  max-width: 34ch;
  max-height: 50vh;
  margin: 8px 0 16px;
  background: var(--noir);
  border: 1px solid var(--trait);
  object-fit: cover;
}

/* Les trois chiffres du tableau de bord : ce qu'on lit d'un coup d'œil. */
.cartes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 2px;
  margin-bottom: 32px;
}

.carte {
  padding: 20px;
  background: var(--survol);
}

.chiffre {
  margin: 4px 0 0;
  font-size: 30px;
  line-height: 1;
  font-weight: 700;
}

.fiche {
  display: grid;
  grid-template-columns: minmax(140px, 220px) 1fr;
  gap: 1px;
  margin: 0 0 32px;
  background: var(--trait);
  border: 1px solid var(--trait);
}

.fiche dt,
.fiche dd {
  margin: 0;
  padding: 10px 16px;
  background: var(--noir);
}

.fiche dt {
  color: var(--gris);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Une case à cocher : le libellé va À CÔTÉ, pas au-dessus — c'est une
   phrase qu'on lit, pas un champ qu'on remplit. */
.case {
  display: flex;
  align-items: center;
  gap: 10px;
  width: auto;
  margin-bottom: 16px;
  color: var(--encre);
}

/* La case à cocher se DESSINE : la règle générale des champs pose
   « appearance: none », qui efface aussi le crochet du navigateur — on
   cochait sans que rien ne change à l'écran. Le crochet est donc à nous. */
.case input[type='checkbox'] {
  flex: none;
  width: 18px;
  height: 18px;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 1px solid var(--champ-bord);
  background: var(--champ);
  cursor: pointer;
}

.case input[type='checkbox']:checked {
  border-color: var(--accent);
  background: var(--accent) center / 13px 13px no-repeat
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2317181a' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5 5L20 6.5'/%3E%3C/svg%3E");
}

.case input[type='checkbox']:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.case input[type='checkbox']:disabled {
  border-color: var(--trait);
  background: var(--trait);
  cursor: not-allowed;
}

/* Le banc d'essai se signale lui-même : deux plateformes identiques sur deux
   ports, c'est une erreur qui attend son heure. Jamais allumé en production. */
.banc {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 30;
  margin: 0;
  padding: 5px 14px;
  background: var(--alerte);
  color: var(--encre);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
}

.marque {
  padding-top: 24px;
  margin-bottom: 48px;
}

.marque h1 {
  font-size: 22px;
  line-height: 24px;
  font-weight: 700;
  letter-spacing: -0.02em;
  text-transform: uppercase;
}

.k {
  font-size: 10px;
  line-height: 14px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 8px;
}

/* ── Les menus ──────────────────────────────────────────────────────────── */

.menu {
  list-style: none;
}

.menu li {
  margin-bottom: 4px;
}

.menu button {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  height: auto;
  padding: 9px 0;
  border: 0;
  background: none;
  color: var(--encre);
  font-size: 11px;
  line-height: 16px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: left;
  cursor: pointer;
}

.menu button::before {
  content: '';
  width: 8px;
  height: 8px;
  flex: none;
  background: none;
  border: 1px solid var(--bord);
}

.menu button:hover {
  background: none;
  color: var(--accent);
}

.menu button[aria-current='true'] {
  color: var(--accent);
}

.menu button[aria-current='true']::before {
  background: var(--accent);
  border-color: var(--accent);
}

.menu button:disabled,
.menu button:disabled:hover {
  color: var(--eteint);
  background: none;
  cursor: default;
}

.menu button:disabled::before {
  border-color: var(--trait);
}

/* Le bouton qui fait surgir les menus, et sa barre : invisibles tant que
   l'écran est large — là, la bande est déjà dépliée à gauche. */
.bouton-menu,
.barre-mobile,
.voile {
  display: none;
}

/* ── Titres de section ──────────────────────────────────────────────────── */

h2 {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 11px;
  line-height: 16px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border-top: 1px solid var(--encre);
  padding-top: 10px;
  margin: 36px 0 18px;
}

h2:first-child {
  margin-top: 24px;
}

h2::before {
  content: '';
  width: 8px;
  height: 8px;
  background: var(--accent);
  flex: none;
}

/* ── Formulaires ────────────────────────────────────────────────────────── */

/* La largeur d'un champ appartient au GROUPE : dans un même formulaire, tous
   les champs s'alignent sur la saisie la plus longue. Des bords qui dansent
   privent l'œil de son repère vertical. Un groupe dont TOUTES les saisies sont
   courtes — un code seul — prend une largeur courte : la différence se voit
   alors entre deux groupes, jamais à l'intérieur d'un seul. */
form {
  max-width: 560px;
  --largeur-champ: 22ch;
}

form.groupe-code {
  --largeur-champ: 12ch;
}

form.groupe-court {
  --largeur-champ: 16ch;
}

form.groupe-long {
  --largeur-champ: 34ch;
}

/* Les canaux d'alerte : des saisies LONGUES par nature — un jeton de Meta
   passe les deux cents caractères, une liste de destinataires s'allonge, un
   nom d'hôte se lit en entier. Le champ prend toute la place qu'on lui donne,
   et le formulaire s'étend au-delà des 560 px ordinaires. */
form.groupe-canal {
  max-width: 900px;
  --largeur-champ: 100%;
}

form.groupe-canal .champ-secret {
  max-width: 100%;
}

/* Un long formulaire sur un écran large : deux colonnes, pour ne pas faire
   défiler ce qui tient sous les yeux. Les notes, les messages et le bouton
   traversent la grille — ils parlent du formulaire entier. */
@media (min-width: 900px) {
  form.deux-colonnes {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 32px;
    align-items: end;
    max-width: 760px;
    --largeur-champ: 100%;
  }

  form.deux-colonnes > .hint,
  form.deux-colonnes > .msg,
  form.deux-colonnes > button,
  form.deux-colonnes > .large,
  form.deux-colonnes > .case,
  form.deux-colonnes > .rangee,
  form.deux-colonnes > fieldset {
    grid-column: 1 / -1;
  }

  form.groupe-canal.deux-colonnes {
    max-width: 900px;
  }

  form.deux-colonnes > .hint {
    margin-top: 0;
    margin-bottom: 18px;
  }

  form.deux-colonnes > button {
    justify-self: start;
  }
}

/* Chercher, c'est un geste : le champ et son bouton vont ensemble. */
.rangee {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 16px;
}

.rangee label {
  margin-bottom: 0;
}

/* Un titre et son geste : le bouton va au bout de la ligne, pas sous elle. */
.rangee.entre {
  justify-content: space-between;
  align-items: baseline;
}

.rangee.entre button {
  margin-top: 0;
}

.rangee button {
  min-width: 130px;
}

label {
  display: block;
  font-size: 10px;
  line-height: 14px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gris);
  margin-bottom: 18px;
}

/* La largeur d'un champ ANNONCE ce qu'on y attend : six chiffres n'occupent
   pas la place d'un courriel. Un champ trop large fait douter de la saisie
   demandée. Les largeurs sont en « ch », l'unité du caractère : elles suivent
   donc la fonte, quelle que soit la taille d'écran. */
input {
  display: block;
  width: 100%;
  max-width: var(--largeur-champ, 22ch);
  height: 30px;
  margin-top: 5px;
  padding: 0 9px;
  border: 1px solid var(--champ-bord);
  border-radius: 0;
  background: var(--champ);
  color: var(--champ-encre);
  font: 400 14px/28px Menlo, Consolas, 'Courier New', monospace;
  letter-spacing: 0.02em;
  /* Le curseur clignotant n'est PAS fixé ici : ainsi il suit l'encre du champ.
     Fixé, il restait sombre là où un navigateur repeint la page de lui-même
     — mode sombre forcé, fort contraste —, et l'on obtenait un curseur noir
     sur un texte blanc. */
  outline: 0;
  -webkit-appearance: none;
  appearance: none;
}

/* La note sous un champ : ce qui ne va pas, ou que c'est bon. En casse
   normale — le libellé qui la contient est en capitales. */
.note-champ {
  display: block;
  max-width: 44ch;
  margin-top: 6px;
  font-size: 12px;
  line-height: 16px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: none;
  color: var(--alerte-texte);
}

.note-champ.ok {
  color: var(--succes);
}

input[aria-invalid='true'] {
  border-color: var(--alerte);
  box-shadow: inset 0 0 0 1px var(--alerte);
}

/* Le champ de mot de passe et son œil. L'œil est DANS la case, à droite :
   il appartient au champ, pas au formulaire. */
.champ-secret {
  position: relative;
  display: block;
  max-width: var(--largeur-champ, 22ch);
}

.champ-secret input {
  max-width: none;
  padding-right: 38px;
}

.champ-secret button.oeil {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 34px;
  min-width: 0;
  max-width: none;
  height: 30px;
  padding: 0;
  border: 0;
  background: transparent center / 18px 18px no-repeat
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2315161a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 12s4-7 11-7 11 7 11 7-4 7-11 7S1 12 1 12z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E");
  opacity: 0.55;
  cursor: pointer;
}

.champ-secret button.oeil.ouvert {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2315161a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 12s4-7 11-7 11 7 11 7-4 7-11 7S1 12 1 12z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3Cpath d='M3 3l18 18'/%3E%3C/svg%3E");
  opacity: 0.9;
}

.champ-secret button.oeil:hover,
.champ-secret button.oeil:focus-visible {
  background-color: transparent;
  opacity: 1;
}

/* Un code se tape chiffre à chiffre : lettres espacées et centrées. Ce n'est
   plus une largeur — c'est une façon d'écrire. */
input.code {
  letter-spacing: 0.16em;
  text-align: center;
}

select {
  display: block;
  width: 100%;
  max-width: var(--largeur-champ, 22ch);
  height: 30px;
  margin-top: 5px;
  padding: 0 9px;
  border: 1px solid var(--champ-bord);
  border-radius: 0;
  background: var(--champ);
  color: var(--champ-encre);
  font: 400 14px/28px 'Helvetica Neue', Helvetica, Arial, sans-serif;
  outline: 0;
}

select:focus {
  border-color: var(--accent);
  background: var(--champ-actif);
}

input::selection {
  background: var(--accent);
  color: var(--accent-encre);
}

input::placeholder {
  color: var(--estompe);
  letter-spacing: 0.04em;
}

input:focus {
  border-color: var(--accent);
  background: var(--champ-actif);
}

button {
  display: inline-block;
  width: auto;
  min-width: 160px;
  height: 30px;
  padding: 0 20px;
  border: 1px solid var(--accent);
  border-radius: 0;
  background: var(--accent);
  color: var(--accent-encre);
  cursor: pointer;
  font-family: inherit;
  font-size: 11px;
  line-height: 28px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

button:hover {
  background: var(--noir);
  color: var(--accent);
}

button:disabled,
button:disabled:hover {
  border-color: var(--trait);
  background: var(--trait);
  color: var(--gris);
  cursor: default;
}

/* Un bloc qui se déplie pour AGIR — créer un profil, générer des tickets,
   ajouter un revendeur — se présente comme un bouton : un triangle gris de
   11 px ne se voit pas sur le fond sombre, et l'écran semblait sans geste.
   Replié, « + » ; déplié, « − », et le formulaire vient dessous. */
details.action > summary {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-width: 160px;
  height: 30px;
  margin-bottom: 18px;
  padding: 0 20px;
  border: 1px solid var(--accent);
  color: var(--accent);
  font-size: 11px;
  line-height: 28px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  list-style: none;
  cursor: pointer;
  user-select: none;
}

details.action > summary::-webkit-details-marker {
  display: none;
}

details.action > summary::before {
  content: '+';
  font-size: 16px;
  line-height: 1;
}

details.action[open] > summary::before {
  content: '−';
}

details.action > summary:hover,
details.action > summary:focus-visible {
  background: var(--accent);
  color: var(--accent-encre);
  outline: 0;
}

/* Ce qui détruit : le rouge de l'alerte, et rien d'autre ne le porte. */
button.danger {
  border-color: var(--alerte);
  background: var(--alerte);
  color: var(--sur-alerte);
}

button.danger:hover {
  background: var(--noir);
  color: var(--alerte-texte);
}

.zone-danger {
  margin-top: 40px;
  padding-top: 8px;
  border-top: 1px solid var(--alerte);
}

button.secondaire {
  border-color: var(--bord);
  background: none;
  color: var(--encre);
  margin-top: 24px;
}

button.secondaire:hover {
  border-color: var(--encre);
  background: none;
}

button.secondaire.danger {
  border-color: var(--alerte);
  color: var(--alerte-texte);
}

/* Un bouton qui se lit comme un lien : dans un tableau, un pavé écraserait
   la ligne. */
button.lien {
  width: auto;
  min-width: 0;
  max-width: none;
  height: auto;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  font-size: 11px;
  letter-spacing: 0.06em;
  line-height: 22px;
}

button.lien:hover {
  background: none;
  color: var(--encre);
}

/* ── Messages ───────────────────────────────────────────────────────────── */

.msg {
  max-width: 520px;
  margin: 0 0 24px;
  padding: 12px 16px;
  background: var(--alerte);
  color: var(--sur-alerte);
  font-weight: 700;
}

/* La confirmation : le cadre du message, sans le rouge de l'alerte — la barre
   de la marque à gauche, la coche verte à droite. */
.msg.ok {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: transparent;
  color: var(--encre);
  border-left: 4px solid var(--accent);
  font-weight: 700;
}

.msg.ok[hidden] {
  display: none;
}

.msg.ok::after {
  content: '';
  flex: none;
  width: 20px;
  height: 20px;
  background: center / contain no-repeat
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232fbf5b' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5 5L20 6.5'/%3E%3C/svg%3E");
}

.hint {
  margin-top: 12px;
  max-width: 640px;
  font-size: 13px;
  line-height: 20px;
  color: var(--gris);
}

.state {
  font-size: 24px;
  line-height: 30px;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.mono {
  font-family: Menlo, Consolas, 'Courier New', monospace;
  letter-spacing: 0.08em;
}

/* ── Listes et tableaux ─────────────────────────────────────────────────── */

dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 8px 32px;
  align-items: baseline;
  margin: 24px 0;
}

dt {
  font-size: 10px;
  line-height: 22px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gris);
}

dd {
  font-variant-numeric: tabular-nums;
}

/* Un tableau doit pouvoir défiler seul : sur un téléphone, il déborde. */
.tableau {
  overflow-x: auto;
}

table {
  width: 100%;
  border-collapse: collapse;
}

th {
  text-align: left;
  padding: 0 20px 6px 0;
  border-bottom: 1px solid var(--accent);
  font-size: 10px;
  line-height: 14px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gris);
  white-space: nowrap;
}

/* Une colonne retirée l'est en-tête ET cellules : sans cette règle, la
   cellule d'un tableau garde son « display: table-cell » malgré « hidden ». */
th[hidden],
td[hidden] {
  display: none;
}

td {
  padding: 12px 24px 12px 0;
  border-bottom: 1px solid var(--trait);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

tbody tr:hover td {
  background: var(--survol);
}

/* Le ticket vendu est LE livrable : on le recopie sur un carton ou on le
   dicte. Il se lit donc à un mètre, sur le fond clair des saisies. */
.ticket {
  display: inline-block;
  margin: 8px 0 24px;
  padding: 16px 24px;
  background: var(--champ);
  color: var(--champ-encre);
  font-family: Menlo, Consolas, 'Courier New', monospace;
  font-size: 30px;
  line-height: 36px;
  font-weight: 700;
  letter-spacing: 0.12em;
}

.ticket-mdp {
  font-size: 16px;
  line-height: 32px;
  letter-spacing: 0.12em;
}

/* Un état se lit d'un coup d'œil : plein quand tout va, creux sinon. */
.chip {
  display: inline-block;
  padding: 2px 10px;
  font-size: 11px;
  line-height: 20px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.chip.oui {
  background: var(--accent);
  color: var(--accent-encre);
}

.chip.non {
  border: 1px solid var(--bord);
  color: var(--gris);
}

a {
  color: var(--accent);
}

footer {
  margin-top: 64px;
  border-top: 2px solid var(--trait);
  padding-top: 12px;
  font-size: 11px;
  line-height: 16px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gris);
}

[hidden] {
  display: none !important;
}

/* ── Sur un téléphone : les menus se replient ───────────────────────────── */

@media (max-width: 768px) {
  .cadre {
    display: block;
  }

  /* Sur téléphone, la bande sort DE LA GAUCHE par-dessus la page, et le
     reste s'estompe derrière. Elle ne pousse rien : ce qu'on lisait reste
     où on l'avait laissé. */
  #menus {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 20;
    width: min(78vw, 300px);
    max-height: none;
    border-right: 1px solid var(--trait);
    border-bottom: 0;
    background: var(--noir);
    padding: 8px 24px 32px;
    overflow-y: auto;
    transition: transform 160ms ease-out;
  }

  /* Fermée, elle attend juste à côté de l'écran. */
  #menus.repliee {
    transform: translateX(-100%);
  }

  /* Le bouton, lui, reste visible en haut à gauche de la page. */
  /* La barre tient contre le bandeau, et fait 0,8 cm de haut. */
  .barre-mobile {
    position: sticky;
    top: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    gap: 10px;
    height: 30px;
    padding: 0 16px;
    background: var(--noir);
    border-bottom: 1px solid var(--trait);
  }

  .barre-mobile .k {
    margin: 0;
  }

  .voile:not([hidden]) {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 15;
    background: rgba(0, 0, 0, 0.6);
  }

  .travail {
    padding: 0 0 48px;
  }

  main,
  #marque-seule {
    padding: 0 16px;
  }

  .marque {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding-top: 12px;
    margin-bottom: 16px;
  }

  .travail {
    padding-top: 0;
  }

  .bouton-menu,
  .barre-mobile {
    display: block;
  }

  .barre-mobile {
    display: flex;
  }

  .bouton-menu {
    width: auto;
    max-width: none;
    min-width: 0;
    height: 22px;
    margin: 0;
    padding: 0 10px;
    line-height: 20px;
    font-size: 10px;
    letter-spacing: 0.08em;
  }

  /* La bande entière coulisse : les listes, elles, restent visibles —
     sinon rien ne surgirait. */
  .menu.replie {
    display: block;
  }

  .menu {
    padding-bottom: 8px;
  }

  button {
    width: 100%;
    min-width: 0;
  }

  .bouton-menu {
    width: auto;
  }

  /* Les onglets restent une RANGÉE : empilés, trois boutons pleine largeur
     mangeaient un tiers d'écran avant la première ligne utile. */
  .onglets button {
    width: auto;
  }
}

/* ── Le réseau du parc : la carte ───────────────────────────────────────────
 *
 * Les couleurs des liaisons DÉSIGNENT, comme le reste : orange 2,4 GHz, bleu
 * 5 GHz, vert Internet — décision de l'utilisateur, le 2026-09-18. Elles ne
 * servent à rien d'autre sur l'écran.
 */

.barre-carte {
  align-items: center;
  margin-bottom: 12px;
}

.barre-carte .case {
  margin-bottom: 0;
}

.barre-carte .bascule {
  flex-wrap: nowrap;
  margin-bottom: 0;
  border-bottom: 0;
}

.barre-carte .bascule button {
  min-width: 0;
  margin: 0;
}

.gestes-reseau button {
  margin-top: 0;
  min-width: 0;
}

.plan-reseau {
  position: relative;
  height: clamp(360px, 62vh, 680px);
  overflow: hidden;
  background: var(--survol);
  border: 1px solid var(--trait);
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

.plan-reseau:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.plan-reseau.en-pose {
  cursor: crosshair;
  outline: 2px solid var(--accent);
}

.plan-reseau .tuiles img {
  position: absolute;
  left: 0;
  top: 0;
  width: 256px;
  height: 256px;
  max-width: none;
  pointer-events: none;
}

.plan-reseau svg.dessus {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.plan-reseau .touchable {
  pointer-events: all;
  cursor: pointer;
}

.plan-reseau .poignee {
  pointer-events: all;
  cursor: grab;
  fill: rgba(255, 255, 255, 0.01);
  stroke: #ffffff;
  stroke-width: 1.4;
  stroke-dasharray: 2 3;
}

.plan-reseau .poignee:hover {
  fill: rgba(242, 194, 0, 0.3);
  stroke: var(--accent);
}

.plan-reseau .a-orienter {
  opacity: 0.6;
}

.plan-reseau .nom-site {
  font: 700 11px/1 'Helvetica Neue', Helvetica, Arial, sans-serif;
  fill: #ffffff;
  stroke: #101114;
  stroke-width: 3px;
  stroke-linejoin: round;
  paint-order: stroke;
  text-anchor: middle;
}

.plan-reseau .repere {
  fill: var(--accent);
  stroke: #101114;
  stroke-width: 2;
}

.plan-reseau .zoom {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.plan-reseau .zoom button {
  width: 32px;
  min-width: 0;
  height: 32px;
  margin: 0;
  padding: 0;
  border-color: var(--bord);
  background: var(--noir);
  color: var(--encre);
  font-size: 17px;
  line-height: 30px;
  letter-spacing: 0;
}

.plan-reseau .zoom button:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.plan-reseau .attribution {
  position: absolute;
  right: 0;
  bottom: 0;
  z-index: 2;
  margin: 0;
  padding: 1px 6px;
  background: rgba(255, 255, 255, 0.78);
  color: #222222;
  font-size: 10px;
  line-height: 14px;
}

.plan-reseau .pose {
  position: absolute;
  top: 10px;
  left: 50%;
  z-index: 2;
  margin: 0;
  padding: 6px 12px;
  transform: translateX(-50%);
  background: var(--accent);
  color: var(--accent-encre);
  font-size: 12px;
  font-weight: 700;
  pointer-events: none;
}

/* La fiche : une petite feuille de papier posée sur la carte. */
.feuille {
  position: absolute;
  z-index: 3;
  width: 240px;
  max-width: calc(100% - 16px);
  /* Jamais plus haute que la carte : sur un téléphone, elle défile en elle-même. */
  max-height: calc(100% - 16px);
  overflow-y: auto;
  padding: 12px 14px 10px;
  background: #f5f2ea;
  color: #1b1c1f;
  border-top: 4px solid var(--accent);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.5);
  cursor: auto;
  user-select: text;
  -webkit-user-select: text;
}

.feuille h3 {
  margin: 0 22px 8px 0;
  font-size: 14px;
  line-height: 18px;
}

.feuille .photo {
  display: block;
  width: 100%;
  max-height: 120px;
  margin-bottom: 10px;
  object-fit: contain;
  background: #ffffff;
}

.feuille dl {
  gap: 2px 12px;
  margin: 0 0 6px;
}

.feuille dt {
  color: #6b6f75;
  font-size: 9px;
  line-height: 18px;
}

.feuille dd {
  font-size: 12px;
  line-height: 18px;
  overflow-wrap: anywhere;
}

.feuille button.fermer {
  position: absolute;
  top: 4px;
  right: 6px;
  width: auto;
  min-width: 0;
  height: auto;
  margin: 0;
  padding: 0 4px;
  border: 0;
  background: none;
  color: #44474c;
  font-size: 18px;
  line-height: 22px;
}

.feuille button.lien {
  color: #1b1c1f;
  text-decoration: underline;
}

.legende {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 20px;
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
  color: var(--gris);
  font-size: 12px;
}

.legende .trait,
.signal::before {
  display: inline-block;
  vertical-align: middle;
}

.legende .trait {
  width: 26px;
  margin-right: 8px;
  border-top: 3px solid;
}

.trait.t24 {
  border-color: #ff8a00;
}

.trait.t5 {
  border-color: #1e88ff;
}

.trait.tnet {
  border-color: #2fbf5b;
}

.trait.suppose {
  border-top-style: dashed;
}

.signal::before {
  content: '';
  width: 9px;
  height: 9px;
  margin-right: 8px;
}

.signal.s24::before {
  background: #ff8a00;
}

.signal.s5::before {
  background: #1e88ff;
}

.gestes {
  display: inline-flex;
  gap: 16px;
}

/* Les formulaires du réseau s'ouvrent sous la carte, séparés d'un filet. */
.panneau {
  margin-top: 32px;
  padding-top: 4px;
  border-top: 1px solid var(--trait);
}

.panneau h2 {
  grid-column: 1 / -1;
}

.panneau fieldset {
  margin: 0 0 18px;
  padding: 0;
  border: 0;
}

.panneau legend {
  margin-bottom: 10px;
  color: var(--gris);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* La galerie : on touche l'antenne qui ressemble à la sienne. */
.vignettes {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 8px;
}

.vignettes.grandes {
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  margin-top: 24px;
}

.vignette {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  width: auto;
  min-width: 0;
  height: auto;
  margin: 0;
  padding: 6px;
  border: 1px solid var(--trait);
  background: var(--survol);
  color: var(--encre);
  font-size: 11px;
  font-weight: 400;
  line-height: 14px;
  letter-spacing: 0;
  text-transform: none;
  text-align: center;
}

button.vignette:hover {
  border-color: var(--encre);
  background: var(--survol);
  color: var(--encre);
}

.vignette[aria-pressed='true'] {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

.vignette img,
.vignette .sans-photo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 72px;
  object-fit: contain;
  background: #ffffff;
  color: var(--estompe);
  font-size: 22px;
}

.vignettes.grandes .vignette img {
  height: 130px;
}

.vignette figcaption {
  font-size: 12px;
}

.vignette button.lien {
  align-self: center;
}

.apercu-photo {
  display: block;
  max-width: 240px;
  max-height: 180px;
  margin: 0 0 12px;
  background: #ffffff;
  border: 1px solid var(--trait);
}

@media (max-width: 768px) {
  .plan-reseau {
    height: 62vh;
  }

  .gestes-reseau button,
  .barre-carte .bascule button {
    width: auto;
  }

  .feuille .photo {
    max-height: 80px;
  }
}
