/* Feuille de style du portail.
 *
 * Dans un fichier et non en ligne dans le gabarit, pour que la CSP puisse
 * refuser `unsafe-inline` : le portail n'expédie aucun script, et son style
 * vient d'une seule origine.
 *
 * Palette et polices reprises telles quelles de `web/site/src/styles/global.css`,
 * qui reste la source de vérité du design. Huit variables dupliquées ne
 * justifient pas encore un paquet partagé avec sa chaîne de construction ;
 * `web/packages/tokens` attendra un troisième consommateur.
 *
 * Thème sombre assumé, sans variante claire : le site entier l'est déjà, et
 * une page de nuit posée sur une photo de crépuscule n'a pas de version diurne
 * qui tienne debout.
 */

/* Polices auto-hébergées. Pas de CDN Google : il expose l'adresse IP des
 * visiteurs à un tiers, ce que la vitrine évite déjà (web/CLAUDE.md). */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url('/static/fonts/inter-var.woff2') format('woff2');
}

@font-face {
  font-family: 'Rajdhani';
  font-style: normal;
  font-display: swap;
  font-weight: 600;
  src: url('/static/fonts/rajdhani-600.woff2') format('woff2');
}

@font-face {
  font-family: 'Rajdhani';
  font-style: normal;
  font-display: swap;
  font-weight: 700;
  src: url('/static/fonts/rajdhani-700.woff2') format('woff2');
}

:root {
  --night: #0b1220;
  --surface: #121c2c;
  --surface-2: #1a2638;
  --line: #263449;
  --ink: #dce3f0;
  --muted: #9aa9c2;
  --brand: #1f6ac2;
  --brand-deep: #175aa8;
  --accent: #5a9df0;
  --flag-red: #e11d38;

  /* Couleurs d'état, volontairement distinctes de l'accent : elles disent une
     situation, pas une interaction. Confondre les deux ferait passer un pilote
     blessé pour un lien à cliquer. */
  --ok: #4fb286;
  --warn: #e0a33e;
  --ok-bord: color-mix(in srgb, var(--ok) 40%, var(--line));
  --warn-bord: color-mix(in srgb, var(--warn) 40%, var(--line));
  --flag-red-bord: color-mix(in srgb, var(--flag-red) 40%, var(--line));

  --display: 'Rajdhani', ui-sans-serif, system-ui, sans-serif;
  --sans: 'Inter', ui-sans-serif, system-ui, -apple-system, sans-serif;

  color-scheme: dark;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--night);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

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

/* --- Ossature de la page d'accueil ---------------------------------------- */

.page {
  position: relative;
  isolation: isolate;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Le <picture> ne doit rien peser dans la mise en page : son enfant est
   positionné en absolu, mais l'élément lui-même resterait un item flex vide
   qui décalerait la bande du haut de quelques pixels. */
.page > picture {
  display: contents;
}

.fond {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Le F-16 est au centre droit du cadre. Ce décalage le garde visible quand
     la fenêtre se resserre, alors qu'un centrage le couperait. */
  object-position: 62% 48%;
}

/* Deux voiles superposés. Le premier assombrit toute l'image d'un cran pour
   que le texte clair tienne où qu'il tombe ; le second creuse le bord gauche
   jusqu'au noir plein, là où se pose la colonne de texte. */
.voile-global {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(11, 18, 32, 0.42);
}

.voile-lateral {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    100deg,
    var(--night) 0%,
    rgba(11, 18, 32, 0.94) 26%,
    rgba(11, 18, 32, 0.62) 48%,
    rgba(11, 18, 32, 0.12) 72%,
    rgba(11, 18, 32, 0) 88%
  );
}

.bande {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.5rem clamp(1.25rem, 5vw, 4.5rem);
}

.contenu {
  flex: 1;
  display: flex;
  align-items: center;
  padding: 1rem clamp(1.25rem, 5vw, 4.5rem) 2.5rem;
}

/* 46rem, et non la largeur de lecture confortable : c'est la rangée de trois
   accès qui commande cette mesure. Plus étroite, le troisième passait à la
   ligne et s'y étirait tout seul. Le paragraphe, lui, garde sa propre largeur
   maximale plus bas. */
.colonne {
  width: 100%;
  max-width: 46rem;
  display: flex;
  flex-direction: column;
  gap: 1.75rem;
}

/* --- Signature ------------------------------------------------------------ */

.signature {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.9375rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
}

/* Le liseré tricolore du logo de l'escadron, réduit à trois traits. Seul
   ornement de la page, et il vient de l'identité existante plutôt que d'un
   vocabulaire graphique inventé pour l'occasion. */
.cocarde {
  display: flex;
  width: 1.375rem;
  height: 0.875rem;
}

.cocarde span {
  flex: 1;
}

.cocarde span:nth-child(1) {
  background: var(--brand);
}

.cocarde span:nth-child(2) {
  background: var(--ink);
}

.cocarde span:nth-child(3) {
  background: var(--flag-red);
}

.retour {
  font-size: 0.8125rem;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.2s;
}

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

/* --- Titre ---------------------------------------------------------------- */

.surtitre {
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.8125rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0;
}

h1 {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(3rem, 9vw, 6.25rem);
  line-height: 0.92;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  text-wrap: balance;
  margin: 0.5rem 0 0;
}

.accroche {
  max-width: 34rem;
  margin: 0;
  font-size: clamp(1rem, 1.6vw, 1.1875rem);
  color: var(--ink);
}

.accroche em {
  font-style: normal;
  color: var(--accent);
}

/* --- Les trois accès ------------------------------------------------------ */

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.875rem;
}

.action {
  flex: 1 1 12rem;
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  padding: 0.9375rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  background: rgba(18, 28, 44, 0.72);
  backdrop-filter: blur(6px);
  text-decoration: none;
  color: var(--ink);
  transition:
    border-color 0.2s,
    background 0.2s,
    transform 0.2s;
}

a.action:hover {
  border-color: var(--accent);
  background: rgba(26, 38, 56, 0.85);
}

.action .libelle {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.0625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.action .detail {
  font-size: 0.8125rem;
  line-height: 1.4;
  color: var(--muted);
}

/* L'action principale est la seule pleine. Deux boutons pleins côte à côte ne
   disent plus lequel est le geste attendu. */
.action--principale {
  flex-basis: 13rem;
  border-color: var(--brand);
  background: var(--brand);
}

a.action--principale:hover {
  border-color: var(--accent);
  background: var(--brand-deep);
}

.action--principale .libelle {
  color: #fff;
}

.action--principale .detail {
  color: rgba(255, 255, 255, 0.82);
}

/* Un accès annoncé mais pas encore construit. Rendu en <div> et non en <a> :
   un lien mort se découvre en cliquant, une pastille se lit avant. */
.action--bientot {
  opacity: 0.72;
}

.bientot {
  font-family: var(--sans);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--night);
  background: var(--muted);
  border-radius: 999px;
  padding: 0.0625rem 0.4375rem;
}

@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  a.action:hover {
    transform: translateY(-2px);
  }
}

/* --- Mention et pied ------------------------------------------------------ */

.mention {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  margin: 0;
  font-size: 0.8125rem;
  color: var(--muted);
}

/* Souligné, et pas seulement coloré : dans une ligne déjà grise et petite, la
   couleur seule ne dit pas assez qu'on peut cliquer, et c'est précisément la
   personne non membre qui doit le remarquer. */
.mention a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 0.15em;
  transition: color 0.2s;
}

.mention a:hover {
  color: var(--ink);
}

.puce {
  width: 0.4375rem;
  height: 0.4375rem;
  flex: none;
  border-radius: 50%;
  background: var(--accent);
}

.pied {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem 1.25rem;
  padding: 0 clamp(1.25rem, 5vw, 4.5rem) 1.75rem;
  font-size: 0.75rem;
  color: var(--muted);
}

.pied a {
  color: var(--muted);
  text-decoration: none;
  transition: color 0.2s;
}

.pied a:hover {
  color: var(--accent);
}

/* --- Petits écrans -------------------------------------------------------- */

/* Sous 48rem la colonne occupe toute la largeur : un dégradé latéral n'a plus
   rien à protéger, il devient vertical et remonte depuis le bas. */
/* Sur un téléphone, superposer le texte à la photo ne marche pas : le contenu
   occupe presque tout l'écran, donc le voile qui le rend lisible recouvre
   aussi l'appareil, et il ne reste qu'une brume. Deux cadrages n'y changeaient
   rien, le problème était le voile et non l'image.

   L'image devient donc une bande en haut, et le texte se pose en dessous sur
   du noir plein. On y perd l'effet d'immersion, on y gagne une photo qu'on
   voit vraiment. */
@media (max-width: 48rem) {
  .fond,
  .voile-global,
  .voile-lateral {
    height: 52svh;
  }

  .page .fond {
    /* Le cadrage portrait déborde légèrement en hauteur ; on garde le bas,
       où se trouve l'appareil, et on coupe le ciel. Réservé à la landing :
       elle a une source portrait dédiée, ce que les pages de contenu n'ont
       pas. */
    object-position: 50% 62%;
  }

  .voile-global {
    /* Plus léger qu'en grand écran : plus rien ne s'écrit par-dessus, sauf la
       signature du haut, qui a le ciel derrière elle. */
    background: rgba(11, 18, 32, 0.22);
  }

  /* Le dégradé ne protège plus du texte, il raccorde la bande au fond de la
     page. Il finit donc en noir plein exactement là où l'image s'arrête. */
  .voile-lateral {
    background: linear-gradient(
      to top,
      var(--night) 0%,
      rgba(11, 18, 32, 0.8) 22%,
      rgba(11, 18, 32, 0.25) 62%,
      rgba(11, 18, 32, 0) 100%
    );
  }

  .contenu {
    align-items: flex-start;
    /* Le contenu commence sous la bande. La signature, elle, reste dessus. */
    padding-top: calc(52svh - 4.5rem);
  }

  .action {
    flex-basis: 100%;
  }
}

/* --- Entrée --------------------------------------------------------------- */

/* Une seule séquence, au chargement, dans l'ordre de lecture. Rien au
   défilement : la page tient sur un écran. */
@media (prefers-reduced-motion: no-preference) {
  .anime {
    animation: monte 0.75s cubic-bezier(0.22, 1, 0.36, 1) both;
  }

  .anime:nth-child(1) {
    animation-delay: 0.05s;
  }

  .anime:nth-child(2) {
    animation-delay: 0.14s;
  }

  .anime:nth-child(3) {
    animation-delay: 0.23s;
  }

  .anime:nth-child(4) {
    animation-delay: 0.32s;
  }

  .fond {
    animation: rapproche 1.6s cubic-bezier(0.22, 1, 0.36, 1) both;
  }
}

@keyframes monte {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes rapproche {
  from {
    opacity: 0;
    transform: scale(1.04);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* --- Pages en carte ------------------------------------------------------- */

/* Le compte et les refus : une colonne étroite centrée, sans photo. Elles
   n'ont pas à impressionner, elles ont à être lisibles. */
.carte-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}

.carte {
  width: 100%;
  max-width: 34rem;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 0.75rem;
  padding: 2rem;
}

.carte h1 {
  font-size: 1.35rem;
  line-height: 1.3;
  letter-spacing: 0.08em;
  margin: 0;
}

.carte p {
  margin: 0;
  color: var(--muted);
}

.carte dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.5rem 1.5rem;
  margin: 0;
}

.carte dt {
  color: var(--muted);
  font-size: 0.875rem;
}

.carte dd {
  margin: 0;
}

.carte form {
  margin: 0;
}

.bouton {
  align-self: flex-start;
  font: inherit;
  display: inline-block;
  border: 1px solid rgba(90, 157, 240, 0.65);
  background: rgba(90, 157, 240, 0.06);
  color: var(--ink);
  border-radius: 0.375rem;
  padding: 0.65rem 1rem;
  cursor: pointer;
  text-decoration: none;
  transition:
    border-color 0.2s,
    background 0.2s,
    color 0.2s;
}

.bouton:hover {
  border-color: var(--accent);
  background: rgba(90, 157, 240, 0.12);
  color: var(--accent);
}

/* === Tableau de bord ======================================================
 *
 * Une coque en 16:9 : rail d'identité à gauche, champ de modules à droite.
 * En paysage la hauteur est la ressource rare, et un bandeau horizontal aurait
 * coûté un dixième de l'écran pour trois informations.
 *
 * Sous 60rem le rail devient une bande compacte au-dessus des modules :
 * empilé tel quel, il aurait imposé un écran entier de défilement avant
 * d'atteindre le contenu.
 */

.bord {
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  background: var(--night);
}

.barre {
  flex: none;
  display: flex;
  align-items: center;
  gap: 1.25rem;
  padding: 0 clamp(1rem, 3vw, 2rem);
  height: 3.75rem;
  border-bottom: 1px solid var(--line);
}

.barre .qui {
  margin-left: auto;
  color: var(--muted);
  font-size: 0.875rem;
}

.corps {
  flex: 1;
  display: grid;
  grid-template-columns: 21rem 1fr;
  min-height: 0;
}

/* --- Rail d'identité --- */

.rail {
  border-right: 1px solid var(--line);
  padding: 1.9rem 1.75rem;
  display: flex;
  flex-direction: column;
  gap: 1.6rem;
  background: linear-gradient(180deg, var(--surface) 0%, var(--night) 70%);
}

.etiquette {
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.75rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}

.indicatif {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(2.25rem, 5vw, 3.5rem);
  line-height: 0.95;
  margin: 0.35rem 0 0.7rem;
  overflow-wrap: anywhere;
}

.montant {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(1.75rem, 4vw, 2.6rem);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  display: block;
  margin-top: 0.35rem;
}

/* `abbr` et non une infobulle maison : elle est native, atteignable au
 * clavier, et la CSP du portail interdit le JavaScript qu'il faudrait pour en
 * fabriquer une. */
/* La pièce, à la place de l'abréviation « CC ».
 *
 * Dimensionnée en `em` et non en pixels : elle suit la taille du nombre
 * qu'elle accompagne, du solde en gros caractères du rail jusqu'aux lignes de
 * tableau. Les attributs `width` et `height` du gabarit restent là pour
 * réserver la place avant le chargement — sans eux, chaque ligne d'un tableau
 * de prix sursaute quand l'image arrive.
 *
 * `vertical-align` plutôt qu'un alignement de boîte flex : la pièce vit au
 * milieu d'un texte, et la caler sur la ligne de base la ferait flotter trop
 * haut. */
.devise {
  width: 1.15em;
  height: 1.15em;
  margin-left: 0.32em;
  vertical-align: -0.2em;
}

.rail-bas {
  margin-top: auto;
  display: grid;
  gap: 0.7rem;
}

.fait {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
  margin: 0;
  font-size: 0.875rem;
  color: var(--muted);
}

/* --- Pastilles d'état ---
 * Les couleurs d'état sont distinctes de l'accent : elles disent une
 * situation, pas une interaction. */

.pastille {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.1rem 0.7rem 0.1rem 0.5rem;
  color: var(--muted);
  white-space: nowrap;
}

.pastille::before {
  content: "";
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

.pastille--active { color: var(--ok); border-color: var(--ok-bord); }
.pastille--pending_link,
.pastille--injured,
.pastille--captured { color: var(--warn); border-color: var(--warn-bord); }
.pastille--dead { color: var(--flag-red); border-color: var(--flag-red-bord); }

/* --- Champ de modules ---
 * `grid-auto-rows: 1fr` : avec un seul module, il occupe toute la hauteur au
 * lieu de laisser un écran aux trois quarts vide. Un module s'étire, il ne se
 * duplique pas pour meubler. */

.modules {
  padding: 1.9rem clamp(1rem, 3vw, 2rem);
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
  grid-auto-rows: minmax(min-content, 1fr);
  gap: 1.1rem;
  align-content: start;
  min-height: 0;
}

.module {
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  padding: 1.25rem 1.35rem;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* Chaque module déclare sa largeur. C'est ce qui empêche la grille de
 * fabriquer une ligne orpheline — défaut déjà rencontré deux fois sur ce
 * projet, au palmarès puis sur les boutons de la landing. */
.module--large { grid-column: span 2; }
.module--pleine { grid-column: 1 / -1; }

.module h2 {
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.85rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 0.9rem;
}

.module p { margin: 0; }
.module p + p { margin-top: 0.6rem; }

.module .aide {
  color: var(--muted);
  font-size: 0.85rem;
}

/* --- Historique du registre --- */

.lignes {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.ligne {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.9rem;
  align-items: baseline;
  font-size: 0.925rem;
}

.ligne + .ligne {
  border-top: 1px solid var(--line);
  padding-top: 0.6rem;
}

.ligne .quand {
  display: block;
  color: var(--muted);
  font-size: 0.8rem;
}

.ligne .valeur {
  font-family: var(--display);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  font-size: 1.05rem;
  white-space: nowrap;
}

.valeur--plus { color: var(--ok); }
.valeur--moins { color: var(--muted); }

/* --- Création du pilote --- */

.seul {
  flex: 1;
  display: grid;
  place-items: center;
  padding: 2rem clamp(1rem, 3vw, 2rem);
}

.carte-creation {
  width: min(34rem, 100%);
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface);
  padding: clamp(1.5rem, 5vw, 2.75rem);
}

.carte-creation h1 {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(1.9rem, 5vw, 2.4rem);
  line-height: 1.1;
  margin: 0 0 0.6rem;
}

.carte-creation > p { margin: 0; color: var(--muted); }

.formulaire { margin-top: 1.5rem; }

.champ {
  display: block;
  width: 100%;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0.7rem 0.9rem;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1rem;
  margin: 0.4rem 0 1.1rem;
}

.champ:focus-visible { border-color: var(--accent); }

.erreur {
  color: var(--flag-red);
  font-size: 0.875rem;
  margin: -0.7rem 0 1.1rem;
}

.code {
  display: block;
  font-family: ui-monospace, 'SF Mono', Menlo, monospace;
  font-size: 1.2rem;
  letter-spacing: 0.08em;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0.7rem 0.9rem;
  margin: 0.8rem 0;
  color: var(--ink);
  overflow-x: auto;
}

.bouton {
  display: inline-block;
  font-family: var(--display);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 0.9rem;
  background: var(--brand);
  color: #fff;
  border: 1px solid var(--brand);
  border-radius: 8px;
  padding: 0.55rem 1.3rem;
  cursor: pointer;
}

.bouton--calme {
  background: transparent;
  color: var(--muted);
  border-color: var(--line);
}

@media (hover: hover) {
  .bouton:hover { background: var(--brand-deep); }
  .bouton--calme:hover { color: var(--ink); border-color: var(--muted); background: transparent; }
}

/* --- Sous 60rem : le rail devient une bande --- */

@media (max-width: 60rem) {
  .corps { grid-template-columns: 1fr; }

  .rail {
    border-right: 0;
    border-bottom: 1px solid var(--line);
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: 0.75rem 1.25rem;
    padding: 1.25rem clamp(1rem, 3vw, 2rem);
  }

  .rail-tete { min-width: 0; }
  .indicatif { font-size: 2rem; margin: 0.2rem 0 0.5rem; }
  .rail-solde { text-align: right; }
  .montant { font-size: 1.6rem; }

  /* Les faits du compte passent sous les deux colonnes : ils ne servent pas à
     décider d'un vol, donc ils cèdent la ligne à l'indicatif et au solde. */
  .rail-bas {
    grid-column: 1 / -1;
    margin-top: 0.5rem;
    grid-auto-flow: column;
    justify-content: start;
    align-items: center;
    gap: 1rem;
    overflow-x: auto;
  }

  .fait { gap: 0.5rem; }
  .module--large, .module--pleine { grid-column: 1 / -1; }
}

/* === Administration =======================================================
 *
 * Sobre à dessein : c'est un poste de travail, pas une vitrine. Ce qui compte
 * est de lire vingt lignes d'un coup d'œil et de repérer celle qui cloche.
 */

.admin {
  flex: 1;
  padding: 2rem clamp(1rem, 3vw, 2.5rem) 4rem;
  display: flex;
  flex-direction: column;
  gap: 3rem;
  min-width: 0;
}

.admin h2 {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 1rem;
  display: flex;
  align-items: center;
  gap: 0.7rem;
}

.compte {
  font-size: 0.8rem;
  letter-spacing: 0;
  color: var(--night);
  background: var(--muted);
  border-radius: 999px;
  padding: 0 0.5rem;
}

/* Le tableau déborde dans son propre conteneur : sur un portable, une colonne
 * de trop ferait sinon défiler la page entière de côté. */
.tableau {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: 12px;
}

.admin table {
  border-collapse: collapse;
  width: 100%;
  min-width: 44rem;
  font-size: 0.9rem;
}

.admin th,
.admin td {
  text-align: left;
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}

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

.admin th {
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--surface);
}

/* Les chiffres s'alignent sur leurs unités, sinon comparer deux soldes d'un
 * coup d'œil demande de les lire. */
.admin td.nombre,
.admin th.nombre {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-family: var(--display);
  font-weight: 700;
}

.discret {
  color: var(--muted);
  font-size: 0.8rem;
  display: block;
}

/* Visible par les lecteurs d'écran seulement : une colonne d'actions sans
 * en-tête laisse le lecteur annoncer une cellule sans dire de quoi il s'agit. */
.lecteur-seul {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.actions-ligne {
  display: flex;
  gap: 0.4rem;
}

.mini {
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0.25rem 0.6rem;
  cursor: pointer;
  white-space: nowrap;
}

@media (hover: hover) {
  .mini:hover { color: var(--ink); border-color: var(--muted); }
}

.admin .aide {
  color: var(--muted);
  font-size: 0.82rem;
  margin: 0.8rem 0 0;
  max-width: 46rem;
}

/* --- Formulaires du catalogue --------------------------------------------- */

/* Une ligne quand la largeur le permet, une colonne sinon. Les libellés
 * restent au-dessus de leur champ dans les deux cas : à côté, ils se
 * désalignent dès qu'un texte passe à la ligne. */
.ligne-formulaire {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
}

.ligne-formulaire label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  flex: 1 1 12rem;
  min-width: 0;
}

.ligne-formulaire .champ {
  margin: 0;
}

.ligne-prix {
  display: flex;
  gap: 0.4rem;
  align-items: center;
}

/* Assez large pour sept chiffres, pas plus : un champ pleine largeur suggère
 * qu'on y écrit une phrase. */
.champ--court {
  width: 7.5rem;
  margin: 0;
  padding: 0.3rem 0.5rem;
  font-family: var(--display);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

select.champ {
  appearance: none;
  /* Sans cette flèche dessinée à la main, un `select` dépouillé de son style
   * natif ne se distingue plus d'un champ de saisie. */
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 1.1rem) 55%, calc(100% - 0.75rem) 55%;
  background-size: 0.35rem 0.35rem, 0.35rem 0.35rem;
  background-repeat: no-repeat;
  padding-right: 2rem;
}

.admin .erreur {
  margin: 0 0 1rem;
}

/* --- Prose des règles ------------------------------------------------------ */

/* Une largeur de lecture, pas la largeur de l'écran : au-delà d'une
 * soixantaine de caractères, l'œil perd la ligne suivante en revenant à
 * gauche. Les tableaux de prix, eux, gardent toute la place. */
.prose {
  max-width: 38rem;
}

.prose h2 {
  color: var(--ink);
  font-size: 1.15rem;
  letter-spacing: 0.1em;
}

.prose p {
  margin: 0 0 1rem;
  /* Le corps du texte, pas une annotation. En `--muted` il se lisait comme une
   * mention secondaire, ce qui le faisait paraître plus petit qu'il n'était :
   * la couleur pèse ici davantage que la taille. `--muted` reste pour les
   * notes, en bas des tableaux. */
  color: var(--ink);
}

.prose p:last-child {
  margin-bottom: 0;
}

/* --- Édition des règles ---------------------------------------------------- */

.edition {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  align-items: flex-start;
  max-width: 46rem;
  margin-bottom: 0.75rem;
}

.edition label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  width: 100%;
}

.edition .champ {
  margin: 0;
}

.zone {
  font-family: var(--sans);
  line-height: 1.6;
  resize: vertical;
  /* Le texte s'écrit, il ne se code pas : une police proportionnelle rend la
   * relecture plus fidèle à ce que verra le pilote. */
}

/* --- Hero d'une page de contenu ------------------------------------------- */

/* Même ossature que la landing, avec ses deux voiles : l'un assombrit toute
 * l'image d'un cran, l'autre creuse le bord gauche là où tombe le texte. Ce
 * réglage a été calé une fois pour que du texte clair tienne sur une photo, et
 * le refaire ici le ferait diverger.
 *
 * La différence tient à la hauteur. La landing n'a rien sous elle et prend
 * tout l'écran ; ici le texte suit, et le hero s'arrête avant le bas pour que
 * la suite se devine sans avoir à faire défiler à l'aveugle. */
.hero {
  position: relative;
  isolation: isolate;
  min-height: clamp(20rem, 68svh, 38rem);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.hero > picture {
  display: contents;
}

/* Son propre cadrage. `.fond` en porte un, calé sur la photo de la landing où
 * l'appareil est au centre droit ; l'hériter ici marcherait par chance, et un
 * réglage de la landing déplacerait cette page sans qu'on le voie.
 *
 * Le reste des règles de `.fond` — position, `object-fit`, la bande de 52svh
 * en petit écran — est partagé volontairement : c'est la mécanique « image en
 * fond puis texte dessous », la même pour les deux pages. */
.hero .fond {
  object-position: 50% 46%;
}

/* Le raccord vers la page. La landing n'en a pas besoin : elle occupe tout
 * l'écran, donc son image n'a pas de bas. Ici elle s'arrête, et sans ce
 * dégradé la photo finit sur une arête nette qui la fait ressembler à une
 * capture collée. */
.hero::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  z-index: -1;
  height: 35%;
  background: linear-gradient(180deg, rgba(11, 18, 32, 0) 0%, var(--night) 100%);
  pointer-events: none;
}

/* Plus petit que le titre de la landing : celle-ci annonce le serveur, une
 * page de contenu annonce seulement son sujet. Les faire de la même taille
 * mettrait les deux au même rang. */
.titre-hero {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(2.5rem, 7vw, 4.5rem);
  line-height: 0.95;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  text-wrap: balance;
  margin: 0.5rem 0 0;
}

/* --- Page de lecture publique --------------------------------------------- */

/* Alignée sur le hero, pas centrée. Le titre est calé sur le bord gauche ; un
 * texte centré en dessous donne deux axes sur une même page, et l'œil ne sait
 * plus où commence une ligne. Même retrait que `.bande` et `.contenu`.
 *
 * Elle n'emprunte pas la mise en page de l'administration : elle se lit, elle
 * ne s'opère pas. */
.lecture {
  flex: 1;
  width: 100%;
  padding: 3rem clamp(1.25rem, 5vw, 4.5rem) 5rem;
  display: flex;
  flex-direction: column;
  gap: 2.75rem;
  min-width: 0;
  /* 17 px, et seulement ici. Le `body` sert aussi des tableaux et des
   * étiquettes, où 16 va bien ; une page qu'on lit d'un bout à l'autre demande
   * un cran de plus. */
  font-size: 1.0625rem;
}

.lecture h2 {
  font-family: var(--display);
  font-weight: 700;
  /* Assez gros pour accrocher l'œil au défilement. En 1,05 rem, six chapitres
   * se lisaient comme six étiquettes d'interface. */
  font-size: 1.3rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin: 0 0 1rem;
  display: flex;
  align-items: center;
  gap: 0.7rem;
}

/* En `ch` et non en `rem` : la vraie contrainte est le nombre de signes par
 * ligne, pas une largeur absolue. En `rem`, agrandir le corps allonge la ligne
 * en caractères et la rend pénible sans qu'on comprenne pourquoi. */
.lecture .prose {
  max-width: 66ch;
}

/* Deux colonnes, une désignation et un montant : au-delà, le montant part si
 * loin du nom qu'il faut suivre la ligne du doigt. */
.lecture .tableau {
  overflow-x: auto;
  max-width: 52rem;
  border: 1px solid var(--line);
  border-radius: 12px;
}

.lecture table {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.95rem;
}

.lecture th,
.lecture td {
  text-align: left;
  padding: 0.7rem 1rem;
  border-bottom: 1px solid var(--line);
}

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

.lecture th {
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--surface);
}

.lecture td.nombre,
.lecture th.nombre {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-family: var(--display);
  font-weight: 700;
}

.lecture .aide {
  color: var(--muted);
  font-size: 0.85rem;
  margin: 0.9rem 0 0;
  max-width: 66ch;
}

/* --- Prose des règles ------------------------------------------------------ */

/* Une largeur de lecture, pas la largeur de l'écran : au-delà d'une
 * soixantaine de caractères, l'œil perd la ligne suivante en revenant à
 * gauche. Les tableaux de prix, eux, gardent toute la place. */
.prose {
  max-width: 38rem;
}

.prose h2 {
  color: var(--ink);
  font-size: 1.15rem;
  letter-spacing: 0.1em;
}

.prose p {
  margin: 0 0 1rem;
  /* Le corps du texte, pas une annotation. En `--muted` il se lisait comme une
   * mention secondaire, ce qui le faisait paraître plus petit qu'il n'était :
   * la couleur pèse ici davantage que la taille. `--muted` reste pour les
   * notes, en bas des tableaux. */
  color: var(--ink);
}

.prose p:last-child {
  margin-bottom: 0;
}

/* --- Édition des règles ---------------------------------------------------- */

.edition {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  align-items: flex-start;
  max-width: 46rem;
  margin-bottom: 0.75rem;
}

.edition label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  width: 100%;
}

.edition .champ {
  margin: 0;
}

.zone {
  font-family: var(--sans);
  line-height: 1.6;
  resize: vertical;
  /* Le texte s'écrit, il ne se code pas : une police proportionnelle rend la
   * relecture plus fidèle à ce que verra le pilote. */
}

/* --- Hero d'une page de contenu ------------------------------------------- */

/* Même ossature que la landing, avec ses deux voiles : l'un assombrit toute
 * l'image d'un cran, l'autre creuse le bord gauche là où tombe le texte. Ce
 * réglage a été calé une fois pour que du texte clair tienne sur une photo, et
 * le refaire ici le ferait diverger.
 *
 * La différence tient à la hauteur. La landing n'a rien sous elle et prend
 * tout l'écran ; ici le texte suit, et le hero s'arrête avant le bas pour que
 * la suite se devine sans avoir à faire défiler à l'aveugle. */
.hero {
  position: relative;
  isolation: isolate;
  min-height: clamp(20rem, 68svh, 38rem);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.hero > picture {
  display: contents;
}

/* Son propre cadrage. `.fond` en porte un, calé sur la photo de la landing où
 * l'appareil est au centre droit ; l'hériter ici marcherait par chance, et un
 * réglage de la landing déplacerait cette page sans qu'on le voie.
 *
 * Le reste des règles de `.fond` — position, `object-fit`, la bande de 52svh
 * en petit écran — est partagé volontairement : c'est la mécanique « image en
 * fond puis texte dessous », la même pour les deux pages. */
.hero .fond {
  object-position: 50% 46%;
}

/* Le raccord vers la page. La landing n'en a pas besoin : elle occupe tout
 * l'écran, donc son image n'a pas de bas. Ici elle s'arrête, et sans ce
 * dégradé la photo finit sur une arête nette qui la fait ressembler à une
 * capture collée. */
.hero::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  z-index: -1;
  height: 35%;
  background: linear-gradient(180deg, rgba(11, 18, 32, 0) 0%, var(--night) 100%);
  pointer-events: none;
}

/* Plus petit que le titre de la landing : celle-ci annonce le serveur, une
 * page de contenu annonce seulement son sujet. Les faire de la même taille
 * mettrait les deux au même rang. */
.titre-hero {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(2.5rem, 7vw, 4.5rem);
  line-height: 0.95;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  text-wrap: balance;
  margin: 0.5rem 0 0;
}

/* Un prix pas encore arrêté. En gris et en romain, pour qu'il ne se lise pas
 * comme un montant : c'est une absence, pas une valeur. */
.a-fixer {
  color: var(--muted);
  font-family: var(--sans);
  font-weight: 400;
  font-size: 0.85rem;
}

/* --- Navigation de la barre ------------------------------------------------ */

/* Les liens entre écrans. Discrets à dessein : ils servent une fois par
 * visite, alors que le contenu de la page se lit en permanence. */
.liens {
  display: flex;
  gap: 1.1rem;
  font-size: 0.8125rem;
}

.liens a {
  color: var(--muted);
  text-decoration: none;
  transition: color 0.2s;
  white-space: nowrap;
}

.liens a:hover {
  color: var(--accent);
}

/* ===========================================================================
 * Page d'état — /status
 *
 * Une page de supervision se scanne, elle ne se lit pas. La hiérarchie est
 * donc inversée par rapport aux pages de prose : le verdict occupe le haut de
 * l'écran en gros, et le détail ne vient qu'après, en lignes régulières où
 * l'œil descend d'une pastille à l'autre.
 *
 * Les couleurs d'état sont celles du tableau de bord (`--ok`, `--warn`,
 * `--flag-red`) et restent distinctes de l'accent : elles disent une
 * situation, pas une interaction.
 * ======================================================================== */

.etat {
  flex: 1;
  padding: clamp(1.75rem, 5vw, 3.5rem) clamp(1.25rem, 5vw, 4.5rem)
    clamp(3rem, 8vw, 5rem);
  max-width: 56rem;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
}

/* --- Le verdict ---
 * La seule chose que la plupart des visiteurs liront. La barre de couleur est
 * à gauche et non un fond teinté : un aplat rouge sur toute la largeur rend le
 * texte moins lisible au moment précis où il compte. */

.verdict {
  border-left: 3px solid var(--line);
  padding-left: clamp(1rem, 3vw, 1.5rem);
}

.verdict .etiquette {
  margin: 0 0 0.5rem;
}

.verdict h1 {
  margin: 0;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(1.75rem, 5vw, 2.6rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-wrap: balance;
}

.verdict .commentaire {
  margin: 0.6rem 0 0;
  color: var(--muted);
  font-size: 0.9375rem;
}

.verdict--ok { border-left-color: var(--ok); }
.verdict--ok h1 { color: var(--ok); }
.verdict--degrade { border-left-color: var(--warn); }
.verdict--degrade h1 { color: var(--warn); }
.verdict--rompu { border-left-color: var(--flag-red); }
.verdict--rompu h1 { color: var(--flag-red); }
.verdict--inconnu { border-left-color: var(--line); }

/* --- Groupes de sondes --- */

.etat .groupe h2,
.bande-temps h2 {
  margin: 0 0 0.9rem;
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

.sondes {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 0.6rem;
  background: var(--surface);
  overflow: hidden;
}

/* Trois colonnes : le nom pousse, la mesure et la pastille gardent leur place.
 * `auto` sur la mesure plutôt qu'une largeur fixe — « il y a 3 min » et
 * « 0,4 ms » n'ont pas la même longueur, et les aligner de force couperait
 * l'un des deux. */
.sonde {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 0.5rem 1rem;
  padding: 0.85rem 1.1rem;
}

.sonde + .sonde {
  border-top: 1px solid var(--line);
}

.sonde .nom {
  color: var(--ink);
  font-size: 0.9375rem;
}

.sonde .mesure {
  color: var(--muted);
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* Le détail passe sous les trois colonnes : le mettre dans la première le
 * ferait pousser le nom vers le haut et casserait l'alignement des pastilles,
 * qui est ce qui rend la liste scannable. */
.sonde .pourquoi {
  grid-column: 1 / -1;
  margin: 0.15rem 0 0;
  color: var(--muted);
  font-size: 0.8125rem;
  line-height: 1.45;
}

.pastille--ok { color: var(--ok); border-color: var(--ok-bord); }
.pastille--degrade { color: var(--warn); border-color: var(--warn-bord); }
.pastille--rompu { color: var(--flag-red); border-color: var(--flag-red-bord); }
.pastille--inconnu { color: var(--muted); }

/* --- Bande d'historique ---
 * Sans JavaScript : la CSP du portail interdit les scripts, donc pas de
 * bibliothèque de graphes. Des cases et un `title`, ce qui suffit — et ce qui
 * reste lisible au clavier et sans souris.
 *
 * `flex` avec des cases qui s'étirent : le nombre de cases change avec la
 * fenêtre de temps demandée, et une largeur fixe laisserait un trou à droite
 * ou déborderait. */

.cases {
  display: flex;
  gap: 2px;
  height: 2.75rem;
}

.case {
  flex: 1;
  border-radius: 2px;
  background: var(--line);
  min-width: 3px;
}

.case--ok { background: var(--ok); }
.case--degrade { background: var(--warn); }
.case--rompu { background: var(--flag-red); }
/* Une case sans mesure garde la couleur neutre : c'est un trou dans la série,
 * pas un incident. La distinction est celle qui empêche de lire une coupure de
 * supervision comme une panne de service. */
.case--inconnu { background: var(--line); }

.reperes {
  display: flex;
  justify-content: space-between;
  margin: 0.5rem 0 0;
  color: var(--muted);
  font-size: 0.75rem;
}

.etat .aide {
  margin: 0;
  color: var(--muted);
  font-size: 0.8125rem;
}

.etat .aide a {
  color: var(--accent);
  text-decoration: none;
}

.etat .aide a:hover {
  text-decoration: underline;
}

@media (max-width: 30rem) {
  /* La mesure passe sous le nom : à trois colonnes sur un écran étroit,
   * « il y a 12 min » se coupait en trois lignes et déformait toute la liste. */
  .sonde {
    grid-template-columns: 1fr auto;
  }

  .sonde .mesure {
    grid-column: 1;
    grid-row: 2;
    text-align: left;
  }

  .sonde .pastille {
    grid-row: 1 / span 2;
  }
}

/* ===========================================================================
 * Hangar et boutique
 *
 * Deux pages, une seule mise en page : posséder et dépenser sont deux gestes
 * différents, mais ils se lisent de la même façon — un titre, une phrase qui
 * situe l'enjeu, puis des tableaux par catégorie.
 *
 * Le solde vit dans la barre, à droite, sur les deux pages. C'est le seul
 * chiffre qui décide d'un achat, et le chercher ailleurs ferait acheter à
 * l'aveugle.
 * ======================================================================== */

.atelier {
  flex: 1;
  padding: clamp(1.75rem, 5vw, 3rem) clamp(1.25rem, 5vw, 4.5rem) clamp(3rem, 8vw, 5rem);
  max-width: 60rem;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 2.25rem;
}

.atelier .entete h1 {
  margin: 0;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(1.75rem, 5vw, 2.4rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
}

/* La phrase sous le titre porte la règle du jeu, pas une décoration : le
 * hangar survit au pilote, l'emport non. Elle est mesurée pour rester lisible
 * — au-delà de 62 caractères l'œil perd sa ligne. */
.atelier .chapeau {
  margin: 0.6rem 0 0;
  max-width: 62ch;
  color: var(--muted);
  font-size: 0.9375rem;
  line-height: 1.6;
}

.atelier h2 {
  margin: 0 0 0.9rem;
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: 0.01em;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
}

.atelier table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9375rem;
}

.atelier th,
.atelier td {
  text-align: left;
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}

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

.atelier th {
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

.atelier td.nombre,
.atelier th.nombre {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.atelier .tableau {
  border: 1px solid var(--line);
  border-radius: 0.6rem;
  background: var(--surface);
  overflow-x: auto;
}

.atelier .aide {
  margin: 0;
  max-width: 62ch;
  color: var(--muted);
  font-size: 0.8125rem;
  line-height: 1.6;
}

.atelier .aide a {
  color: var(--accent);
  text-decoration: none;
}

.atelier .aide a:hover {
  text-decoration: underline;
}

/* Un tiret gris et non un zéro : « 0 » se lit comme une quantité mesurée,
 * alors qu'ici il n'y a simplement rien à dire. */
.rien {
  color: var(--muted);
  opacity: 0.5;
}

.en-vol {
  color: var(--warn);
  font-weight: 600;
}

/* --- Acheter --- */

.atelier td.achat {
  text-align: right;
  width: 1%;
  white-space: nowrap;
}

.atelier td.achat form {
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
  align-items: center;
}

.atelier .quantite {
  width: 4.5rem;
  padding: 0.4rem 0.5rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Lisible par un lecteur d'écran, invisible à l'œil. Chaque champ de quantité
 * a besoin d'une étiquette, mais vingt fois « Quantité » à l'écran serait du
 * bruit dans une colonne qui n'a de place que pour un chiffre. */
.invisible {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --- État vide --- */

.atelier .vide {
  border: 1px solid var(--line);
  border-radius: 0.6rem;
  background: var(--surface);
  padding: clamp(1.5rem, 4vw, 2.25rem);
}

.atelier .vide h2 {
  margin-bottom: 0.5rem;
}

.atelier .vide p {
  margin: 0 0 1rem;
  max-width: 52ch;
  color: var(--muted);
  font-size: 0.9375rem;
  line-height: 1.6;
}

.atelier .vide p:last-child {
  margin-bottom: 0;
}

.atelier .vide .bouton {
  display: inline-block;
}

@media (max-width: 40rem) {
  /* Le formulaire passe sous la ligne : à quatre colonnes sur un téléphone,
   * le champ de quantité et le bouton se chevauchaient. */
  .atelier td.achat form {
    justify-content: flex-start;
  }

  .atelier th,
  .atelier td {
    padding: 0.6rem 0.65rem;
  }
}

/* Le module « Hangar » finit par deux liens, collés à la dernière ligne sans
 * cette respiration — et soulignés par défaut, ce qui les faisait ressembler à
 * du texte d'erreur plutôt qu'à une navigation. */
.module .lignes + .aide {
  margin-top: 0.9rem;
}

.module .aide a {
  color: var(--accent);
  text-decoration: none;
}

.module .aide a:hover {
  text-decoration: underline;
}

/* --- Facettes de la boutique ---
 * Des liens, pas un menu : la CSP interdit le JavaScript, et un menu
 * déroulant demanderait un bouton d'envoi de plus pour changer de vue. */

.facettes {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.facette {
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.35rem 0.9rem;
  transition: color 0.2s, border-color 0.2s;
  white-space: nowrap;
}

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

.facette--active {
  color: var(--night);
  background: var(--accent);
  border-color: var(--accent);
}

/* --- Hors budget ---
 * Marqué, jamais caché : savoir qu'un F-15E existe fait partie de la
 * projection, même quand on ne peut pas encore se l'offrir. L'opacité seule
 * suffit — teinter en rouge ferait passer une ambition pour une erreur. */

.hors-budget td {
  opacity: 0.45;
}

.hors-budget .quantite {
  border-style: dashed;
}

/* --- Pied de formulaire --- */

.valider {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  align-items: flex-start;
  padding-top: 0.5rem;
}

/* Le formulaire du panier enveloppe plusieurs sections ; sans cet écart elles
 * se collent, alors qu'elles sont espacées quand elles sont filles directes
 * du conteneur en `gap`. */
.atelier form > section + section {
  margin-top: 2.25rem;
}

.atelier form > section:first-child {
  margin-top: 0;
}

/* --- Correspondance DCS, en administration ---
 * Un article porte de zéro à dix noms internes DCS. Des jetons plutôt qu'une
 * liste à puces : la colonne est étroite et ces noms sont longs. */

.admin td.dcs {
  min-width: 18rem;
}

.jeton-dcs {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  margin: 0 0.3rem 0.3rem 0;
  padding: 0.12rem 0.3rem 0.12rem 0.45rem;
  border: 1px solid var(--line);
  border-radius: 0.3rem;
  background: var(--surface-2);
}

.jeton-dcs code {
  font-size: 0.75rem;
  color: var(--muted);
  white-space: nowrap;
}

.retirer {
  border: 0;
  background: none;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1;
  padding: 0 0.15rem;
  cursor: pointer;
}

.retirer:hover {
  color: var(--flag-red);
}

/* Un nom DCS fait couramment trente caractères — `weapons.missiles.AIM_120C`.
 * Le champ de prix, lui, en accueille cinq : réutiliser sa largeur tronquait
 * l'exemple avant même qu'on ait tapé quoi que ce soit. */
.champ--dcs {
  width: 15rem;
  font-size: 0.8125rem;
}

/* --- Journal du relais, en administration ---
 * La route affichée en détail se repère dans le tableau d'ensemble sans
 * relire le titre plus bas. */

.journal-route {
  color: var(--ink);
}

.journal-route[aria-current="page"] {
  color: var(--accent);
  font-weight: 700;
}
