/* ══════════════════════════════════════════════════════════════════════════
   COUCHE DE MARQUE ANCRAGE
   ──────────────────────────────────────────────────────────────────────────
   Ce fichier était deux blocs <style> dans index.html jusqu'au 29/07/2026.
   Il en est sorti pour une seule raison : tant qu'un style en ligne existait
   dans une page servie, la politique de sécurité de contenu devait porter
   `style-src 'unsafe-inline'`, c'est-à-dire autoriser N'IMPORTE quel style
   injecté dans la page. Le contenu n'a pas changé d'une ligne ; il est
   simplement servi comme fichier, donc couvert par `style-src 'self'`.

   Il se charge APRÈS le système de base (_ds/…/styles.css) : c'est cet ordre
   qui lui permet de recouvrir ce qu'il doit recouvrir. Inverser les deux
   `<link>` d'index.html casserait la marque sans rien signaler.
   ══════════════════════════════════════════════════════════════════════ */


  /* ══ IDENTITÉ ANCRAGE ═══════════════════════════════════════════════════
     La couche de marque, posée APRÈS le système de base pour le recouvrir.
     Cinq couleurs seulement — vert 315C4A, sauge 8FAF9D, crème F1F6F2,
     or D9A441, brun 4B362B — toutes les nuances par intensité ou opacité.
     Une seule famille : Instrument Sans, du Regular au Bold, l'aération se
     joue sur l'espacement des lettres. Les jetons de couleur vivent dans
     themes.js ; ici, ce que les jetons ne peuvent pas dire : la typographie
     et la physionomie des composants. */
  :root {
    --font-heading: 'Instrument Sans', system-ui, sans-serif;
    --font-body: 'Instrument Sans', system-ui, sans-serif;
    --font-heading-weight: 600;
  }
  body { font-size: 15px; letter-spacing: 0.005em; }

  /* Les titres portent le vert de la marque ; le texte courant reste brun. */
  h1, h2, h3, h4, h5 { color: var(--color-titre, #315C4A); letter-spacing: -0.015em; }
  h1 { font-size: 38px; } h2 { font-size: 29px; } h3 { font-size: 23px; }
  h6 { letter-spacing: 0.12em; font-weight: 500; }

  /* L'action est OR, texte brun — le vert reste aux liens et à la structure.
     Le système de base peint .btn-primary en accent : on le recouvre. */
  .btn { border-radius: var(--radius-md, 10px); font-weight: 600; letter-spacing: 0.01em; }
  .btn-primary { background: var(--color-accent-2, #D9A441); color: var(--color-brun, #4B362B); }
  .btn-primary:hover { background: color-mix(in srgb, var(--color-accent-2, #D9A441) 86%, var(--color-brun, #4B362B)); }
  .btn-primary:active { background: color-mix(in srgb, var(--color-accent-2, #D9A441) 74%, var(--color-brun, #4B362B)); }
  .btn-ghost { font-weight: 500; }

  /* Champs : plus clairs que la carte qui les porte, cernés de sauge. */
  .input {
    background: color-mix(in srgb, var(--color-surface, #F1F6F2) 45%, white);
    border-color: color-mix(in srgb, var(--color-secondaire) 55%, transparent);
    border-radius: var(--radius-sm, 6px);
  }
  .input:hover { border-color: var(--color-secondaire); }
  .input:focus-visible { border-color: var(--color-accent, #315C4A); }

  /* Tableaux : en-tête en petites capitales sauge-vert, filets légers. */
  .table th {
    font-weight: 500; letter-spacing: 0.12em;
    color: color-mix(in srgb, var(--color-accent) 55%, var(--color-secondaire));
    border-bottom: 1px solid color-mix(in srgb, var(--color-secondaire) 60%, transparent);
  }
  .table td { border-bottom: 1px solid color-mix(in srgb, var(--color-secondaire) 35%, transparent); }
  .table tbody tr:hover { background: color-mix(in srgb, var(--color-secondaire) 14%, transparent); }

  .tag { border-radius: 999px; font-weight: 500; }
  .card { box-shadow: var(--shadow-sm); }
  ::selection { background: color-mix(in srgb, var(--color-accent-2) 35%, transparent); }

  /* ══ HARMONISATION DES ÉCRANS ═══════════════════════════════════════════
     Les écrans posent leurs styles en ligne — trente fichiers, des dizaines
     de panneaux. Plutôt que de les réécrire un à un, cette couche normalise
     par sélecteur d'attribut, avec !important quand il faut battre le style
     en ligne. Trois règles de la maquette :
       · plus aucun filet de 2px — tout trait est un souffle de 1px ;
       · tout panneau porteur (fond crème ou cadre) est arrondi ;
       · les titres de section sont amples et verts.
     Le jour où les écrans seront réécrits proprement, cette couche meurt. */
  main [style*="border: 2px solid"]        { border-width: 1px !important; }
  main [style*="border-top: 2px solid"]    { border-top-width: 1px !important; }
  main [style*="border-bottom: 2px solid"] { border-bottom-width: 1px !important; }
  main [style*="border-left: 2px solid"]   { border-left-width: 1px !important; }
  main [style*="border-right: 2px solid"]  { border-right-width: 1px !important; }

  /* Panneaux : un fond crème ou un cadre sans rayon propre s'arrondit. Les
     éléments qui fixent déjà leur rayon en ligne gardent le leur (le style
     en ligne gagne sur une règle sans !important — c'est voulu). */
  main [style*="background: var(--color-surface)"],
  main [style*="border: 2px solid"],
  main [style*="border: 1px solid var(--color-divider)"],
  main [style*="border: 1px solid var(--color-accent)"] { border-radius: var(--radius-md); }

  /* Pas d'overflow:hidden sur ces panneaux, même pour la beauté des coins :
     les bulles d'aide « ? » se positionnent en absolu depuis l'intérieur et
     seraient découpées. Les barres internes sont déjà en pilule. */

  /* ══ ALIGNEMENT DES RANGÉES DE CHAMPS ═════════════════════════════════
     Le défaut : les formulaires en grille étaient alignés par le BAS
     (align-items: end). Or la hauteur d'une boîte de champ dépend de son
     texte d'aide — présent ou absent, sur une ligne ou deux. Aligner par le
     bas revenait donc à décaler les champs vers le haut de la hauteur de
     leur propre aide : jusqu'à 38 px d'écart entre deux colonnes voisines.

     La règle juste : ce sont l'ÉTIQUETTE et le CHAMP qui doivent se répondre
     d'une colonne à l'autre. On aligne donc par le haut, et l'aide pend
     librement en dessous, de longueur variable — c'est sans conséquence.

     Pour que cela suffise, le bloc d'étiquette doit avoir la même hauteur
     partout : ligne pincée à 18 px, plus 5 px d'écart, soit 23 px. */
  :root { --hauteur-etiquette: 23px; }

  .field { display: flex; flex-direction: column; }
  .field > label {
    line-height: 18px; min-height: 18px; margin-bottom: 5px;
    /* Une étiquette qui passe à la ligne décalerait son propre champ : on
       lui interdit de se couper là où la colonne est assez large, et on la
       laisse déborder proprement plutôt que casser la rangée. */
    text-wrap: nowrap; overflow: visible;
  }

  main [style*="align-items: end"]:has(> .field) { align-items: start !important; }

  /* Un bouton dans une telle rangée n'a pas d'étiquette : il descend d'une
     hauteur d'étiquette pour se poser au niveau des champs, pas au-dessus. */
  main [style*="align-items: end"]:has(> .field) > .btn,
  main [style*="align-items: end"]:has(> .field) > div:not(.field):not(:has(label)) {
    align-self: start; margin-top: var(--hauteur-etiquette);
  }

  /* Titres de section : la maquette les veut amples, verts, aérés. */
  main h4 { font-size: 21px; }
  main h5 { font-size: 19px; }

  /* Les grands boutons d'action respirent comme sur la maquette. */
  .btn-primary { padding: 10px 20px; }



  /* Le site imposait 1 180 px de large, donc restait inutilisable sur
     téléphone — alors que photographier un ticket est précisément un geste
     de téléphone. On lève la contrainte et on réorganise sous 900 px : la
     barre latérale passe au-dessus en bandeau déroulant, les grilles à deux
     ou trois colonnes retombent sur une, et les tableaux larges défilent
     dans leur propre cadre plutôt que d'élargir la page. */
  body { margin: 0; min-width: 320px; }
  input[type="date"], select.input { font-family: var(--font-body); }
  input[type="number"] { font-variant-numeric: tabular-nums; }
  code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
  button { font-family: inherit; }
  aside::-webkit-scrollbar { width: 8px; }
  aside::-webkit-scrollbar-thumb { background: var(--color-neutral-400); }
  table { max-width: 100%; }

  /* Le bouton de bascule du menu n'existe que sur petit écran : sur grand
     écran la barre est toujours là, un bouton pour la montrer n'aurait aucun
     sens. Il est rendu par la coquille dans tous les cas et masqué ici — le
     rendu ne connaît pas la largeur de la fenêtre, la feuille de style si. */
  .nav-bascule { display: none; }

  /* ══ LA PAGE D'ENTRÉE PORTE L'IMAGE DE LA VITRINE ════════════════════════
     Appliqué le 30/08/2026, direction « D — volet inversé », retenue par
     Tristan après mesure de quatre directions. C'est l'exécution de sa
     consigne permanente : « peu importe la landing qu'on choisit, il faudra
     que ce soit tout incorporé, le même style et design à l'intérieur du
     site une fois qu'on clique dessus. » La palette avait été portée le
     29/08 ; ici c'est l'IMAGE.

     Le geste central, et il est contre-intuitif : le volet gauche était du
     texte CLAIR sur un dégradé SOMBRE. La vitrine, elle, est de l'encre
     sombre sur un fond pâle. On ne porte pas l'une dans l'autre en gardant
     le fond sombre — trois directions l'ont tenté, toutes ont dû assombrir
     la photo pour y poser du texte clair, et toutes ont détruit exactement
     ce qui fait cette image : sa pâleur. La photo mesure 12,33:1 sous
     l'encre sur la vitrine. Le fond pâle n'est pas un risque de contraste,
     c'est la solution. D inverse le volet au lieu de voiler l'image.

     Effet de bord voulu : les textes du volet étaient en crème
     SEMI-TRANSPARENTE (`color-mix(..., transparent)`) et échouaient le
     contraste AA en production — 2,61:1 pour la sur-titre, 3,04:1 pour le
     paragraphe, mesurés sur le code servi. En passant à l'encre opaque, D
     fait disparaître ce défaut ; il n'était celui d'aucune direction, il
     était déjà là. */
  .entree-gauche {
    background-image: url(../img/fond-brume.jpg);
    background-size: cover;
    background-position: center 78%;
    background-repeat: no-repeat;
  }
  /* Les blocs passent au-dessus des voiles, qui sont leurs propres fonds. */
  .entree-gauche > * { position: relative; z-index: 1; }

  /* Le voile est PAR BLOC, et il s'éteint à alpha 0 sur son propre bord.
     Un fond plat rendait un rectangle à arêtes franches posé sur le
     cerisier ; une ombre portée ne feutrait que l'extérieur de la boîte,
     jamais son bord. Le dégradé radial n'a d'arête à aucun rayon, par
     construction.

     `padding` + `margin` négatif de même valeur : la boîte PEINTE déborde
     du texte de 26 px pour laisser le dégradé respirer, sans que la mise en
     page bouge d'un pixel. La largeur reste bornée — un bloc en pleine
     largeur rendrait une bande, pas une tache, et le contraste mesuré ne
     vaudrait plus. */
  .entree-voile {
    max-width: 540px;
    padding: 26px;
    margin: -26px;
    background: radial-gradient(ellipse at center,
      rgba(247,248,247,.97) 0%, rgba(247,248,247,.94) 45%,
      rgba(247,248,247,.72) 68%, rgba(247,248,247,.28) 86%,
      rgba(247,248,247,0) 100%);
  }

  /* La bande n'existe qu'en dessous de 900 px — voir le bloc de repli. */
  .entree-bande-photo { display: none; }

  @media (max-width: 900px) {
    /* La coquille : deux colonnes deviennent deux rangées. */
    #app > div { display: block !important; }
    aside {
      position: static !important; width: auto !important; height: auto !important;
      max-height: 42vh; overflow-y: auto;
      border-right: none !important; border-bottom: 1px solid var(--color-divider);
    }
    main { min-width: 0; }

    /* ══ LE MENU SE REPLIE DERRIÈRE UN BOUTON ═══════════════════════════
       Même ramenée à cinq entrées, la barre mangeait le haut de chaque écran
       sur téléphone : on arrivait sur une page et on voyait un sommaire.
       Elle se replie donc derrière un bouton, et l'écran commence à l'écran.
       Choisir une destination referme le menu — sur téléphone, un menu qui
       reste ouvert après le choix cache ce qu'on vient d'aller chercher. */
    .nav-bascule {
      display: flex; align-items: center; gap: 10px; width: 100%;
      padding: 10px 0 2px; border: 0; background: transparent; cursor: pointer;
      font: inherit; font-size: 13px; font-weight: 600; color: var(--color-accent);
      min-height: 40px;
    }
    aside:not(.menu-ouvert) nav,
    aside:not(.menu-ouvert) .pied-barre { display: none !important; }
    aside:not(.menu-ouvert) { max-height: none; }

    /* Toute grille multi-colonnes retombe sur une seule. Les grilles sont
       déclarées en style en ligne par le moteur de rendu, d'où le !important. */
    [style*="grid-template-columns"] { grid-template-columns: 1fr !important; }

    /* ══ SAUF LES CHIFFRES-CLÉS, QUI SE RANGENT EN 2×2 ═══════════════════
       La règle du dessus vaut pour des grilles de CONTENU — des cartes, des
       formulaires, des tuiles — qu'une colonne unique sert bien. Elle servait
       mal la rangée de chiffres : quatre nombres de six caractères occupaient
       quatre pleines rangées, et il fallait faire défiler pour lire un tableau
       de bord censé tenir d'un coup d'œil.

       Cette règle vient APRÈS et la corrige. Les deux sélecteurs pèsent le
       même poids (une classe contre un attribut) : c'est l'ordre qui tranche,
       pas la spécificité — ne pas remonter ce bloc.

       Les filets suivent la nouvelle découpe : verticale entre les deux
       colonnes, horizontale entre les deux rangées. Le style en ligne pose
       `border-right` cellule par cellule pour une grille à quatre colonnes ;
       il faut donc l'annuler avant de le reposer au bon endroit.

       `minmax(0, …)` plutôt que `1fr` : une piste de grille a une largeur
       minimale automatique, et un montant à sept chiffres — que `nowrap`
       empêche de se replier — élargissait sa colonne aux dépens de l'autre,
       jusqu'à pousser la page. Le chiffre rétrécit d'un cran par la même
       occasion : 24 px tient un million sur une demi-largeur de téléphone. */
    .kpi-row { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
    .kpi-row > * { border-right: none !important; }
    /* `:not(:last-child)` pour la rangée à trois chiffres : le troisième est
       seul sur sa ligne, un filet à sa droite longerait le vide. */
    .kpi-row > :nth-child(odd):not(:last-child) { border-right: 1px solid var(--color-divider) !important; }
    .kpi-row > :nth-child(n+3) { border-top: 1px solid var(--color-divider); }
    .kpi-row .kpi-valeur { font-size: 24px !important; }

    /* L'en-tête, la page d'entrée et les blocs en ligne s'empilent. */
    header { flex-wrap: wrap !important; gap: 12px !important; padding: 14px 16px 12px !important; }
    .entree-gauche { padding: 36px 24px 20px !important; }
    /* Sous 900 px le texte occupe presque toute la hauteur du volet : aucun
       voile ne peut à la fois protéger le texte ET laisser voir la photo.
       Mesuré — la première version rendait 32 % de photo visible en 1440 et
       tombait à près de zéro en 375, c'est-à-dire que l'image disparaissait
       exactement là où on prétendait la porter.

       Donc on ne voile plus : on SORT la photo du texte. Une bande pleine
       largeur, pleine intensité, sans aucun voile, posée au-dessus du bloc
       de texte qui repose sur le fond uni. Plus aucun texte ne touche
       l'image, le contraste devient trivial, et le cerisier redevient
       réellement visible au lieu d'être deviné. */
    .entree-gauche { background-image: none !important; }
    /* On annule le débordement du voile — haut, gauche, droite — mais JAMAIS
       la marge du BAS : c'est elle qui porte le rythme vertical entre le
       titre, le paragraphe et la liste. Un `margin: 0` en bloc l'emportait
       aussi, et les trois blocs se collaient. */
    .entree-voile {
      max-width: none !important; padding: 0 !important; background: none !important;
      margin-top: 0 !important; margin-left: 0 !important; margin-right: 0 !important;
    }
    .entree-bande-photo {
      display: block !important;
      height: 32vh; min-height: 210px;
      margin: -36px -24px 26px;
      background-image: url(../img/fond-brume.jpg);
      background-size: cover; background-position: center 78%;
      background-repeat: no-repeat;
    }
    .entree-gauche + div { padding: 0 16px 40px !important; }
    section { padding-left: 16px !important; padding-right: 16px !important; }
    h1 { font-size: 30px !important; }
    h2 { font-size: 21px !important; }

    /* Un tableau large défile chez lui, jamais en poussant la page. */
    table { display: block; overflow-x: auto; white-space: nowrap; }
    table td, table th { white-space: normal; }

    /* Cibles tactiles : rien sous 40 px de haut. */
    .btn, button.btn { min-height: 40px; }
    input.input, select.input, textarea.input { font-size: 16px; }   /* évite le zoom iOS */
  }

  @media print {
    body { min-width: 0; }
    aside, header button, .btn { display: none !important; }
    #app > div { display: block !important; }
  }


/* ══ ACCUEIL SUR DEUX COLONNES ═══════════════════════════════════════════
   Ajouté le 29/07/2026. L'accueil tenait dans une colonne de 860 px et
   laissait un tiers de l'écran vide sur un poste de bureau.

   Le flux principal garde sa largeur de LECTURE — au-delà de quelque 75
   caractères, l'œil perd son retour à la ligne, et étirer le texte sur
   1 900 px aurait dégradé la page en croyant la remplir. Ce qui occupe le
   vide est donc ce qui gagne à être étroit : des indicateurs courts empilés.

   Sous 1 260 px, la colonne passe SOUS le flux. Elle ne disparaît pas : un
   contenu qu'on masque à l'étroit est un contenu qu'il ne fallait pas
   écrire. */
.accueil-colonnes {
  display: grid;
  /* Le flux est plafonné à sa largeur de lecture ; le surplus va au rail,
     lui-même borné — au-delà de 380 px il cesserait d'être une marge
     d'indicateurs pour devenir une seconde colonne de contenu, et la page
     n'aurait plus de centre de gravité. */
  grid-template-columns: minmax(0, 840px) minmax(260px, 360px);
  gap: 28px;
  align-items: start;
}
.accueil-rail {
  display: grid;
  gap: 16px;
  /* Aligné sur « Où vous en êtes » plutôt que sur la salutation : le rail
     répond aux chiffres, il n'a pas à concurrencer le titre de la page. */
  margin-top: 22px;
  /* Le collage ne vaut que si la colonne tient dans l'écran. Avec quatre
     cartes elle atteint 906 px, mesurés dans une fenêtre de 900 : collée,
     son dernier bloc devenait INATTEIGNABLE — on ne peut pas faire défiler
     un élément fixé. `align-self: start` remplace donc `position: sticky` :
     la colonne suit la page, et rien ne se cache.

     Le collage reviendra sans risque le jour où l'on saura que la colonne
     tient — c'est ce que fait la règle ci-dessous, à partir d'une hauteur
     d'écran où quatre cartes passent confortablement. */
  align-self: start;
}

@media (min-height: 1100px) {
  .accueil-rail { position: sticky; top: 22px; }
}

/* Le point de bascule vient d'un calcul, pas d'un chiffre rond : barre
   latérale 236 + marges de section 56 + écart 30 + rail minimal 260 = 582 px
   pris avant le flux. Sous 1 440 px, il ne reste donc plus les 860 px que la
   rangée de chiffres réclame, et ses quatre libellés passaient sur trois
   lignes — mesuré à 1 280 px. On repasse sur une colonne AVANT que le flux
   ne se comprime, pas après. */
/* Les deux colonnes n'apparaissent qu'une fois le plafond atteint : barre
   latérale 236 + plafond 1 300 = 1 536 px, ce qui est exactement la largeur
   d'un moniteur de 1 920 à l'échelle 125 % de Windows. En dessous, la
   colonne passe dessous plutôt que de se comprimer. */
@media (max-width: 1535px) {
  .accueil-colonnes { grid-template-columns: minmax(0, 1fr); }
  .accueil-rail {
    position: static;
    margin-top: 34px;
    /* Replié, le rail occupe la MÊME largeur que le flux au-dessus : le
       plafonner à 860 px le laissait plus étroit que le reste de la page,
       et ses cartes flottaient au lieu de s'aligner sur la colonne. */
    max-width: none;
    /* Empilé sous le flux, il a la place de s'étaler en deux ou trois
       cartes plutôt que de faire une longue file. */
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    /* Des cartes de hauteurs différentes s'accrochent par le HAUT : étirées,
       la plus courte se serait délavée sur toute la hauteur de la plus
       longue. */
    align-items: start;
  }

  /* La ligne des barèmes n'est pas une carte : c'est une note de pied de
     colonne. En grille, elle prenait une cellule et se posait À CÔTÉ d'une
     carte, seule au milieu du vide — c'est ce qu'on voyait sur l'écran de
     Mac. Elle occupe donc toute la largeur, sur sa propre ligne. */
  .accueil-rail > .rail-note {
    grid-column: 1 / -1;
    margin-top: 2px;
  }
}

/* ══ UNE SEULE MISE EN PAGE, QUELLE QUE SOIT LA TAILLE DE L'ÉCRAN ═════════
   Ajouté le 29/07/2026, sur un constat mesuré : rien n'était plafonné. La
   zone de contenu prenait toute la largeur disponible — 1 684 px sur un
   écran de 1 920, 1 044 px sur un écran de 1 280. Deux personnes devant le
   même écran voyaient donc deux mises en page différentes, et une capture
   d'écran ne ressemblait jamais à ce qu'on avait sous les yeux.

   Le contenu est donc plafonné et CENTRÉ. Au-delà de la largeur de plafond,
   plus rien ne bouge : la page est strictement identique d'un poste à
   l'autre, et le surplus devient de la marge.

   1 300 px n'est pas un chiffre rond, c'est une contrainte à deux bouts.
   Par le bas : l'accueil doit y tenir ses deux colonnes — flux 840 + écart
   28 + colonne 360, plus les 56 px de marges de section, soit 1 284.
   Par le haut : le plafond doit être atteint par les écrans réels, or
   Windows applique couramment une échelle de 125 % — un moniteur de 1 920
   n'offre alors que 1 536 px de large, et 236 px partent dans la barre
   latérale. Un plafond plus généreux aurait été raté par cette
   configuration, qui est l'une des plus répandues.

   Le bandeau d'alerte, lui, reste pleine largeur : c'est une bande d'alerte,
   elle doit barrer l'écran. */
main > header,
main > div,
main > section {
  width: 100%;
  max-width: 1300px;
  margin-inline: auto;
}

/* Le conteneur de contenu porte le plafond ; ses enfants doivent alors
   pouvoir occuper toute sa largeur, sans hériter d'un second plafond. */
main > div > section { max-width: none; margin-inline: 0; }

/* La barre de défilement ne doit pas décaler la mise en page. Sans cette
   règle, un écran qui défile perd 15 px de largeur utile et un écran qui ne
   défile pas les garde : deux pages du même site ne s'alignaient donc pas
   entre elles, et une capture ne correspondait jamais tout à fait à ce qu'on
   avait sous les yeux. La gouttière est réservée en permanence. */
html { scrollbar-gutter: stable; }

/* ══ LA TABLE DES OPÉRATIONS ═══════════════════════════════════════════════
   Demande du 01/08/2026, référence visuelle à l'appui : un en-tête qui reste
   visible pendant qu'on descend, et des lignes qui se détachent au survol.

   Ce n'est pas cosmétique sur 744 opérations. Sans en-tête collant, on ne sait
   plus à mi-parcours laquelle des colonnes est la catégorie et laquelle est le
   compte — et sur une table large, on lit la catégorie d'une ligne avec le
   montant de la suivante.

   La mise en forme vit ICI et non dans le rendu : un cadre est une affaire de
   feuille de style, et l'hyperscript n'a pas à porter des pixels. La politique
   de sécurité l'autorise sans réserve — c'est un fichier servi depuis notre
   origine, ni un style en ligne ni une ressource tierce.

   CE QUI N'EST PAS FAIT, ET POURQUOI : la référence envoyée borne aussi la
   hauteur de la table avec un défilement interne. Cela suppose un conteneur
   autour du tableau, donc une modification de structure dans le rendu. Elle a
   été tentée, elle a mal placé la fermeture du bloc — le cadre englobait toute
   la section — et elle a été annulée. À reprendre à tête reposée : le gain est
   réel (les bandeaux et la corbeille deviennent atteignables sans traverser
   six cents lignes), le risque de casser l'écran ne l'est pas moins. */
.table-operations {
  border-collapse: separate;
  border-spacing: 0;
}

/* Le fond est OPAQUE et non translucide : sur une table qui défile, un en-tête
   semi-transparent laisse voir les lignes passer dessous, et les intitulés
   deviennent illisibles au moment précis où l'on en a besoin. */
.table-operations thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--color-bg);
  box-shadow: inset 0 -1px 0 var(--color-divider);
}

.table-operations tbody tr:hover td {
  background: color-mix(in srgb, var(--color-surface) 55%, transparent);
}

/* ══ LE CADRE DE LA TABLE, SANS CONTENEUR ══════════════════════════════════
   Suite du 01/08/2026. La première passe n'avait posé que l'en-tête collant —
   invisible tant qu'on ne défile pas — et Tristan a constaté, à juste titre,
   que rien n'avait changé à l'écran.

   Le cadre arrondi de la référence se pose SUR LA TABLE elle-même : avec
   `border-collapse: separate`, un `<table>` accepte une bordure et un rayon,
   à condition d'arrondir aussi les cellules d'angle — sans quoi les coins de
   l'en-tête débordent du cadre. C'est ce qui permet de s'en tenir à la feuille
   de style : aucun conteneur à insérer dans le rendu, donc aucun risque de
   déplacer la fermeture d'un bloc. */
.table-operations {
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-lg);
  overflow: hidden;
  width: 100%;
}

/* Les angles. Sans ces quatre règles, le fond de l'en-tête forme deux carrés
   qui dépassent du rayon, et le cadre a l'air mal découpé. */
.table-operations thead tr:first-child th:first-child { border-top-left-radius: var(--radius-lg); }
.table-operations thead tr:first-child th:last-child  { border-top-right-radius: var(--radius-lg); }
.table-operations tbody tr:last-child td:first-child  { border-bottom-left-radius: var(--radius-lg); }
.table-operations tbody tr:last-child td:last-child   { border-bottom-right-radius: var(--radius-lg); }

/* L'en-tête se distingue du corps : c'est ce qui donne au tableau sa lisibilité
   sur une largeur de neuf colonnes. Intitulés en petites capitales espacées,
   comme partout ailleurs dans Ancrage. */
.table-operations thead th {
  background: var(--color-surface);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 500;
  color: color-mix(in srgb, var(--color-accent) 62%, var(--color-secondaire));
  padding-top: 12px;
  padding-bottom: 12px;
}

/* Un filet seulement ENTRE les lignes, jamais sous la dernière : un trait qui
   longe le bord du cadre ressemble à une carte mal fermée. */
.table-operations tbody td {
  border-top: 1px solid var(--color-divider);
}
.table-operations tbody tr:first-child td {
  border-top: none;
}

/* Les contrôles dans les cellules respirent un peu moins que sur un
   formulaire : sur quarante lignes, chaque pixel de hauteur est un pixel de
   défilement en plus. */
.table-operations select.input,
.table-operations input.input {
  height: 32px;
  padding-top: 4px;
  padding-bottom: 4px;
  font-size: 12.5px;
}

/* ══ LES CONTRÔLES OCCUPENT LEUR COLONNE ═══════════════════════════════════
   Constat du 01/08/2026 : « Bred · Tristan… » — le nom du compte était coupé,
   et on ne pouvait pas savoir de quel compte il s'agissait sans ouvrir la
   liste. Sur un dossier à plusieurs banques, c'est la colonne la plus utile
   qui devenait la moins lisible.

   Les listes déroulantes prennent donc TOUTE la largeur de leur cellule, au
   lieu de la largeur par défaut que le navigateur leur donne. La colonne, elle,
   est dimensionnée sur son contenu réel : « Bred · Tristan Jet & CO » demande
   190 px, « Virement entre mes comptes » en demande 230.

   `min-width: 0` sur la cellule est ce qui rend la troncature possible quand
   elle est INÉVITABLE : sans lui, une cellule de tableau refuse de rétrécir
   sous la largeur de son contenu et pousse toute la table hors de l'écran.
   Mieux vaut un nom coupé qu'une colonne « Montant » invisible. */
.table-operations td select.input,
.table-operations td input.input {
  width: 100%;
  min-width: 0;
}

.table-operations td {
  min-width: 0;
}

/* Le texte d'une option ne se coupe pas au milieu d'un mot : on préfère
   l'ellipsis, qui laisse deviner qu'il y a une suite. */
.table-operations td select.input {
  text-overflow: ellipsis;
}

/* ══ CHAQUE LIGNE COMMENCE SUR UNE SEULE LIGNE ═════════════════════════════
   Constat du 01/08/2026, à côté du décalage de colonnes : une opération dont
   le libellé tient sur trois lignes étirait la rangée, et toutes les autres
   cellules — la date, le tiers, le montant — se centraient dans cette hauteur.
   Résultat, six informations de la MÊME opération à six hauteurs différentes :
   l'œil ne peut plus lire une ligne de gauche à droite, il la reconstruit.

   `vertical-align: top` fait commencer chaque cellule en haut de sa rangée.
   Le montant, le tiers et la date retombent alors sur la première ligne du
   libellé, et ce qui les complète (« ↺ en recette », « 3 op. ») s'écrit dessous
   au lieu de flotter au milieu.

   La liste déroulante, elle, est un BOÎTIER et non une ligne de texte : son
   intitulé est centré dans 36 px de haut, quand celui des cellules voisines
   l'est dans une ligne de 20. Aligner les cellules par le HAUT ne suffit donc
   pas — on obtiendrait un alignement juste au pixel près et faux à l'œil, le
   boîtier restant 8 px plus bas que ses voisines.

   Ces 8 px, mesurés et non estimés, se répartissent des deux côtés : le texte
   descend de 5, le boîtier remonte de 3. Tout mettre sur le boîtier l'aurait
   collé au filet de la rangée, où il n'a plus de quoi respirer ; tout mettre
   sur le texte allongerait chaque rangée d'autant, et il y en a sept cents.

   `:has()` évite d'avoir à marquer ces cellules dans le rendu — la mise en
   forme reste entièrement dans la feuille de style. */
.table-operations tbody td {
  vertical-align: top;
  padding-top: calc(var(--space-2) + 5px);
}
.table-operations tbody td:has(select.input) {
  padding-top: calc(var(--space-2) - 3px);
}

/* La croix de suppression est un bouton : son propre remplissage la posait
   7 px sous la première ligne de la rangée qu'elle supprime. Elle remonte,
   sans rien perdre de sa surface cliquable — c'est la CELLULE qui bouge, pas
   le bouton. */
.table-operations tbody td:last-child {
  padding-top: calc(var(--space-2) - 2px);
}

/* ══ LES POSTES DE CHARGE, TOUS DE LA MÊME TAILLE ══════════════════════════
   Signalement du 01/08/2026 : « les cases n'ont pas toutes la même taille »
   sur la page Immobilier.

   La cause n'est pas un défaut de mise en page mais une différence de
   CONTENU : un poste saisi au mois porte douze champs, un poste régulier
   n'en porte qu'un. Dans une grille, la ligne prend alors la hauteur du plus
   grand, et les voisins flottent au milieu d'un vide.

   Deux règles suffisent, et elles ne touchent à aucune structure :
     · `align-items: start` — chaque case commence en haut de sa ligne, au
       lieu d'être centrée dans la hauteur du plus grand de ses voisins ;
     · un encadré léger et une hauteur minimale — les cases se lisent alors
       comme des cases, et une ligne de trois reste une ligne de trois même
       quand l'une d'elles s'est dépliée sur douze mois.

   CE QUI N'EST PAS RÉGLÉ : la saisie mois par mois reste organisée par
   POSTE (douze champs pour l'électricité), alors qu'on saisit dans la vie
   par MOIS (tous les postes de juin, facture en main). L'inverser demande de
   repenser l'écran, pas de le restyler.

   ── SUITE DU 02/08/2026 : LA GRILLE A ÉTÉ REMPLACÉE ─────────────────────
   « Repense toute cette page, les cases ne sont pas bien égalisées et très
   petites. » Les deux règles ci-dessus traitaient le symptôme. La cause
   était la STRUCTURE : trois colonnes recevaient quatre informations par
   poste plus deux à trois lignes d'aide, donc un champ de montant à cent
   pixels et une liste de périodicité rétrécie à 11,5 px pour tenir.

   Seize postes de même forme sont une LISTE. Les règles de grille sont donc
   remplacées par celles d'une liste à quatre colonnes alignées. */
.grille-postes { align-items: start; }

/* ══ LA LISTE DES POSTES DE CHARGE ════════════════════════════════════════
   Une seule déclaration de colonnes, partagée par l'en-tête, chaque ligne et
   le pied de total : c'est ce qui garantit qu'ils restent alignés. Trois
   grilles indépendantes dériveraient au premier ajustement — et un total
   désaligné de sa colonne se lit comme une erreur de calcul.

   `minmax(0, …)` sur la première colonne : sans le zéro, un libellé long
   pousse la grille au lieu de se replier, et les montants perdent leur
   alignement vertical, qui est tout l'intérêt de la liste.

   ⚠ `display: grid` est déclaré ICI et non en style en ligne, et ce n'est
   pas une préférence : un style en ligne bat une règle de feuille, donc la
   requête média plus bas ne pouvait PAS masquer l'en-tête tant que le JS
   posait `display: grid` sur l'élément. Mesuré à 467 px — l'en-tête restait
   affiché par-dessus une liste repliée. Toute propriété qu'une requête média
   doit pouvoir reprendre appartient à la feuille de style. */
.postes-entete,
.poste-ligne,
.poste-total {
  display: grid;
  gap: 4px 14px;
  grid-template-columns: minmax(0, 1fr) 132px 148px 108px;
}

.poste-ligne { align-items: center; }

/* La ligne d'aide passe SOUS les quatre colonnes, alignée sur le libellé.
   Elle ne concurrence plus la saisie, et sa longueur variable ne déforme
   plus rien puisqu'elle n'a plus de voisin latéral — c'était la cause réelle
   de l'inégalité des cases. */
.poste-ligne > .poste-aide { grid-column: 1 / -1; }

/* Une ligne vide ne porte pas d'aide : sans cette règle elle occuperait
   quand même sa hauteur, et le rythme de la liste se briserait. */
.poste-ligne > .poste-aide:empty { display: none; }

.poste-ligne:hover { background: color-mix(in srgb, var(--color-surface) 55%, transparent); }

/* Les champs occupent leur colonne, au lieu de la largeur que le navigateur
   leur donne. C'est ce qui rend le montant confortable et la périodicité
   lisible sans rétrécir sa police. */
.poste-ligne input.input,
.poste-ligne select.input { width: 100%; min-width: 0; }

/* ── En dessous de 760 px, la ligne se replie ────────────────────────────
   Quatre colonnes ne tiennent pas sur un téléphone. Le libellé prend toute
   la largeur, puis le montant et la périodicité se partagent la ligne
   suivante, et le total annuel se range à droite sous eux. L'ordre de
   lecture est conservé, donc l'ordre de tabulation aussi. */
@media (max-width: 760px) {
  .postes-entete { display: none; }
  .poste-ligne,
  .poste-total {
    grid-template-columns: 1fr 108px;
  }
  .poste-ligne > label,
  .poste-total > *:first-child { grid-column: 1 / -1; }
}

/* ══ LA PAGE IMMOBILIER ════════════════════════════════════════════════════
   Demande du 01/08/2026 : « une refonte de la mise en page, quelque chose de
   premium, intuitif, simple ».

   Le défaut n'était pas le manque d'ornement : c'était l'absence de HIÉRARCHIE.
   Un bien, ses cinq indicateurs, seize postes de charge et deux blocs de
   recettes vivaient tous dans le même encadré de 2 px, au même niveau de
   lecture. L'œil n'avait aucun point d'entrée, et tout se valait.

   Trois plans, et rien d'autre :
     1. LA CARTE DU BIEN — l'objet dont on parle. Ombre douce et filet clair
        plutôt qu'un cadre épais : c'est ce qui la fait exister sans crier.
     2. LES CHIFFRES — ce qu'on vient voir. Posés sur un bandeau crème, comme
        les rangées de chiffres du reste d'Ancrage : la page se relie ainsi au
        reste du site au lieu d'avoir son style propre.
     3. LA SAISIE — ce qu'on fait ensuite. En retrait, dans des cases de
        taille égale.

   Aucune modification de calcul. Les montants qui alimentent la 2044 ne sont
   pas touchés — une refonte visuelle qui déplace un chiffre n'est pas une
   refonte, c'est un défaut. */
.carte-bien {
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-lg);
  background: var(--color-bg);
  box-shadow: var(--shadow-sm);
}

/* Le nom du bien porte la page : il doit se lire avant tout le reste. */
.entete-bien h4 {
  font-size: 20px;
  letter-spacing: -0.01em;
}

/* Les indicateurs dans leur bandeau, à la manière des chiffres-clés du reste
   de l'application. Le filet de séparation disparaît : c'est le fond qui
   groupe, pas un trait. */
.chiffres-bien {
  background: var(--color-surface);
  border-radius: var(--radius-md);
  padding: 16px 18px;
  margin-top: 16px;
}

/* Un filet vertical entre les indicateurs, jamais après le dernier — un trait
   qui longe le bord ressemble à une carte mal découpée. */
.chiffres-bien > *:not(:last-child) {
  border-right: 1px solid var(--color-divider);
  padding-right: 16px;
}

/* Les titres de section respirent, pour que « Charges du bien » et « Recettes »
   se distinguent des seize lignes qui les suivent. */
.carte-bien h5 {
  font-size: 13px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-accent) 70%, var(--color-secondaire));
  margin-top: 4px;
}

/* ── Palette d aller-a (Ctrl+K) ─────────────────────────────────────────
   Tout est ici plutot que dans le rendu : la selection est portee par
   aria-selected, donc une seule source dit ce que le lecteur d ecran
   annonce et ce que l oeil voit. Aucune icone : la hierarchie se fait a la
   taille et a la graisse, comme le veut la regle posee avec le contraste. */
.palette-fond {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: color-mix(in srgb, var(--color-accent) 38%, transparent);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 12vh 16px 16px;
}
.palette-boite {
  width: 100%;
  max-width: 560px;
  background: var(--color-bg);
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-lg);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.22);
  overflow: hidden;
}
.palette-champ {
  width: 100%;
  box-sizing: border-box;
  border: 0;
  border-bottom: 1px solid var(--color-divider);
  background: transparent;
  color: var(--color-text);
  font-family: var(--font-body);
  /* 16px et pas moins : en dessous, Safari sur telephone zoome tout seul a
     la prise de focus, et la palette s ouvre sur une page deplacee. */
  font-size: 16px;
  padding: 14px 18px;
  outline: none;
}
.palette-liste {
  max-height: 46vh;
  overflow-y: auto;
}
.palette-option {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 18px;
  cursor: pointer;
}
.palette-option[aria-selected="true"] {
  background: var(--color-surface);
}
.palette-label {
  font-size: 14px;
}
.palette-section {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 85%, transparent);
  white-space: nowrap;
}
/* Ce qui attend sur la destination. Même code que la barre latérale : or
   quand c’est en retard, sauge sinon. `margin-right: auto` la garde collée
   au nom — sans lui, le `space-between` de la rangée la poserait au milieu,
   entre le nom et la section, où elle n’appartient à ni l’un ni l’autre. */
.palette-signal {
  flex: none;
  align-self: center;
  margin-right: auto;
  min-width: 17px;
  text-align: center;
  padding: 0 5px;
  font-size: 10.5px;
  font-weight: 600;
  line-height: 17px;
  border-radius: 999px;
  font-variant-numeric: tabular-nums;
  color: var(--color-accent);
  background: color-mix(in srgb, var(--color-secondaire) 55%, transparent);
}
.palette-signal.urgent {
  background: var(--color-accent-2);
}
.palette-vide {
  padding: 16px 18px;
  font-size: 13px;
  color: color-mix(in srgb, var(--color-text) 85%, transparent);
}

/* ══ ACCUEIL — LES QUATRE DESTINATIONS ══════════════════════════════════
   En CSS et non en style en ligne : la grille passe de quatre colonnes a
   deux sous 760 px, et une requete de media ne s'ecrit pas dans un
   attribut. Quatre tuiles de 25 % sur un telephone donnent quatre colonnes
   de six caracteres. */
.accueil-destinations {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin-top: 24px;
  max-width: 860px;
}
.accueil-dest {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-start;
  text-align: left;
  padding: 16px 16px 14px;
  cursor: pointer;
  font: inherit;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
}
.accueil-dest-kicker {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 600;
  color: color-mix(in srgb, var(--color-text) 85%, transparent);
}
.accueil-dest-valeur {
  font-family: var(--font-heading);
  font-size: 21px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
}
.accueil-dest-action {
  margin-top: auto;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--color-accent-700, var(--color-accent));
}
/* Une seule tuile en plein sur la page. « Pas des couleurs de partout » :
   l'accentuation designe le geste, elle ne decore pas la rangee. */
.accueil-dest.accent {
  background: var(--color-accent);
  border-color: var(--color-accent);
}
.accueil-dest.accent .accueil-dest-kicker,
.accueil-dest.accent .accueil-dest-valeur {
  color: var(--color-bg);
}
.accueil-dest.accent .accueil-dest-action {
  color: var(--color-accent-2);
}

/* ══ ACCUEIL — LA PROCHAINE CHOSE, EN UNE LIGNE ═════════════════════════ */
.accueil-statut {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  max-width: 860px;
  margin-top: 22px;
  padding: 14px 0;
  border-top: 1px solid var(--color-divider);
  border-bottom: 1px solid var(--color-divider);
}
/* L intitule sur sa propre ligne, en petites capitales : il nomme la nature
   de la phrase sans lui voler son poids. Un label de la meme taille que le
   texte redevient un titre, et la ligne redevient un bloc. */
.accueil-statut-titre {
  display: block;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 600;
  color: color-mix(in srgb, var(--color-text) 85%, transparent);
  margin-bottom: 4px;
}
.accueil-statut-texte {
  flex: 1 1 340px;
  font-size: 14px;
  line-height: 1.55;
}
.accueil-statut-lien {
  flex: none;
  padding: 0;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--color-accent-700, var(--color-accent));
}

@media (max-width: 760px) {
  .accueil-destinations { grid-template-columns: repeat(2, 1fr); }
}

/* ══ ACCUEIL — LE PLAN DU JOUR EN PASTILLES ═════════════════════════════
   Elles se balayent, elles ne se lisent pas. Le `detail` de chaque ligne
   n est plus dessine — il vit sur l ecran de destination, et il reste le
   nom accessible de la pastille. */
.accueil-puces {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.accueil-puce {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 13px;
  cursor: pointer;
  font: inherit;
  font-size: 12.5px;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-divider);
  border-radius: 999px;
}
.accueil-puce-n {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.accueil-puce-titre { text-align: left; }
/* Trois degres, pas dix : une page ou tout est marque n alerte plus.
   `.proche` ne teinte que le filet — ca se prepare ; `.critique` teinte le
   filet ET le texte — on ne le rate pas. Aucun fond plein : la rangee du
   haut porte deja la seule tuile en plein de la page. */
.accueil-puce.proche {
  border-color: var(--color-accent-2-300, var(--color-accent-2));
}
.accueil-puce.critique {
  border-color: var(--color-accent-2);
  color: var(--color-accent-700, var(--color-accent));
  font-weight: 600;
}

/* ══ ACCUEIL — OÙ VOUS EN ÊTES, EN UNE PHRASE ═══════════════════════════ */
.accueil-encart {
  max-width: 860px;
  margin-top: 26px;
  padding: 16px 18px;
  background: var(--color-surface);
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
}
.accueil-encart-phrase {
  margin: 8px 0 0;
  font-size: 13.5px;
  line-height: 1.6;
}
.accueil-encart-source {
  margin: 8px 0 0;
  font-size: 11.5px;
  color: color-mix(in srgb, var(--color-text) 85%, transparent);
}
