/* =====================================================================
   Signal360 - le tableau de bord personnalisable (document docs/36)

   Trois parties, dans cet ordre :
     1. le canevas, la salutation, l'état vide ;
     2. la grille, le cadre d'un widget, ses gestes, le glisser-déposer ;
     3. l'intérieur des widgets, puis le catalogue en fenêtre.

   La feuille a un second usager : la **maquette du site public**
   (`index.php`, bloc « .appli-ecran ») rejoue le canevas et ses widgets
   avec ce balisage-ci, et charge cette feuille pour l'habiller. Une règle
   « .wid-* » retouchée ici se recette donc des deux côtés - l'écran de
   l'abonné, et la page d'accueil. Les règles « .accueil-* » de l'ancien
   gabarit, que la maquette était seule à employer encore, sont parties
   avec sa remise au niveau (26 août 2026, document 45).
   ===================================================================== */

/* =====================================================================
   1. Le canevas
   =====================================================================
   Le tableau de bord n'est **pas** une « .bo-page ».

   Une « .bo-page » est une carte blanche : c'est le bon cadre pour un
   écran qui a un sujet - un formulaire, un tableau. Un canevas de widgets
   en est le contraire : ce sont les widgets qui sont des cartes, et une
   carte blanche posée sur une carte blanche ne se voit pas. Le canevas est
   donc transparent, et laisse paraître le gris de « .page-bord » derrière
   les cartes qu'on y pose - c'est ce gris qui dessine les gouttières.
   ===================================================================== */

.bord-tete{
  display:flex;align-items:flex-start;justify-content:space-between;
  gap:18px;flex-wrap:wrap;
}
.bord-tete-texte{min-width:0}
.bord-canevas h1{margin:0;font-size:25px;color:var(--nuit)}
.bord-parution{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  margin:8px 0 0;font-size:13.5px;color:var(--texte-doux);
}
.bord-tete-gestes{display:flex;flex-wrap:wrap;gap:10px}

/* L'avis d'un geste qui, lui, ne se voit pas dans la page : le relevé est
   parti dans une boîte aux lettres, l'écran n'en montrera rien. */
.bord-avis{margin:18px 0 0}

/* ------------------------------------------------------------------
   L'état vide (décision W2)

   Il n'annonce pas une absence, il propose deux gestes. C'est la seule
   chose qui sépare « votre tableau de bord est à composer » de « cette
   page ne marche pas » - et l'abonné qui arrive au lendemain de la
   livraison ne dispose de rien d'autre pour en juger.
   ------------------------------------------------------------------ */
.bord-neuf{
  margin-top:22px;padding:44px 30px;text-align:center;
  background:var(--surface);border:1px solid var(--bord);
  border-radius:var(--r-l);box-shadow:var(--ombre-douce);
}
.bord-neuf-icone{
  display:grid;place-items:center;width:52px;height:52px;margin:0 auto 16px;
  background:var(--rose-clair);border-radius:var(--r-m);
}
.bord-neuf-icone .ico{width:24px;height:24px;color:var(--rose)}
.bord-neuf h2{margin:0;font-size:20px;color:var(--nuit)}
.bord-neuf p{
  max-width:52ch;margin:10px auto 0;
  font-size:14.5px;line-height:1.6;color:var(--texte-doux);
}
.bord-neuf strong{color:var(--nuit)}
.bord-neuf-gestes{
  display:flex;justify-content:center;flex-wrap:wrap;gap:12px;margin-top:24px;
}
.bord-neuf-gestes form{margin:0}

.bord-ajouter{margin:16px 0 0}

/* =====================================================================
   2. La grille et le cadre d'un widget
   =====================================================================
   **Un widget est un carré.** La grille est faite de cellules carrées :
   Normal en occupe 4 × 4, et Étendu - le seul rectangle - vaut deux
   Normal côte à côte, 8 × 4.

   Le point délicat est de rendre la cellule carrée à toute largeur
   d'écran. Une colonne en « 1fr » ne connaît pas sa propre taille, et
   une hauteur de rangée en pixels ne suivrait qu'à une seule largeur.
   La cellule est donc mesurée en **unité de conteneur** : « 100cqi » est
   la largeur du canevas, dont on retire les gouttières avant de diviser
   par le nombre de colonnes. La hauteur de rangée vaut alors exactement
   la largeur de colonne, et un span de N cellules est carré parce que
   les N-1 gouttières comptent des deux côtés.

   Le repli - « grid-auto-rows: 104px », déclaré avant - sert le
   navigateur qui ignore les unités de conteneur : les cartes y sont
   presque carrées au lieu de l'être tout à fait, ce qui vaut mieux
   qu'une grille effondrée.
   ===================================================================== */
/* Le canevas s'arrête à 1 080 px, comme « .bo-page » : au-delà, les douze
   colonnes s'élargissent et les cartes avec elles, sans que rien ne
   remplisse la place gagnée. Une largeur de lecture vaut mieux qu'une
   largeur d'écran. */
.bord-canevas{container-type:inline-size;max-width:1080px}

.bord-grille{
  --col:12;
  --gout:12px;
  display:grid;
  grid-template-columns:repeat(var(--col),minmax(0,1fr));
  grid-auto-rows:70px;
  grid-auto-rows:calc((100cqi - (var(--col) - 1) * var(--gout)) / var(--col));
  grid-auto-flow:row dense;
  gap:var(--gout);
  margin-top:20px;
}

/* Il a existé un « wid-compact » de 2 × 2 : retiré (décision W18, révisée
   le 26 août 2026), la carte ne s'y lisait plus. Normal est le plancher. */
.wid-normal {grid-column:span 4;grid-row:span 4}
.wid-etendu {grid-column:span 8;grid-row:span 4}

/* ------------------------------------------------------------------
   L'échelle : le nombre de colonnes suit la largeur du canevas

   **C'est le nombre de colonnes qui règle la taille des cartes**, les
   spans ne changeant jamais : Normal reste 4 × 4, Étendu 8 × 4. Douze
   colonnes rendent chaque widget une fois et demie plus petit que huit,
   exactement.

   Mais douze colonnes ne tiennent pas partout. Une cellule vaut la
   largeur du canevas divisée par leur nombre : sur un canevas de 900 px
   - une fenêtre de 1 200 px, dont le panneau de navigation prend 304 -,
   douze colonnes donnent une cellule de 64 px, où plus rien ne tient.
   Le nombre de colonnes est donc choisi pour que la **cellule reste
   entre 76 et 96 px**, soit un Normal de 340 à 420.

   **Le seuil porte sur le canevas, non sur la fenêtre**, et c'est ce que
   les requêtes de conteneur permettent : le panneau de navigation occupe
   304 px tant qu'il est à gauche et disparaît en dessous de 900 px, si
   bien qu'une même fenêtre de 900 px offre tantôt 596 px de canevas,
   tantôt 872. Un seuil exprimé en largeur de fenêtre se tromperait des
   deux côtés de ce basculement.

   Les media queries qui suivent sont le **repli** : elles servent le
   navigateur qui ignore les requêtes de conteneur - lequel ignore aussi
   « cqi », et n'a donc déjà pas de cellules carrées. Elles supposent le
   panneau présent, ce qui est vrai la plupart du temps.
   ------------------------------------------------------------------ */
@media (max-width:1354px){ .bord-grille{--col:10} }
@media (max-width:1150px){ .bord-grille{--col:8}  }
@media (max-width:980px) { .bord-grille{--col:6}  .wid-etendu{grid-column:span 6} }
@media (max-width:620px) { .bord-grille{--col:4}  .wid-etendu{grid-column:span 4} }
@media (max-width:400px) { .bord-grille{--col:2}
                           .wid-normal,.wid-etendu{grid-column:span 2;grid-row:span 2} }

/* La mesure juste, là où elle est disponible. **Étendu est ramené à la
   largeur de la grille à chaque palier** : un span plus large qu'elle ne
   se replie pas de lui-même, il crée des colonnes implicites et déborde
   de la page. */
@container (max-width:1050px){ .bord-grille{--col:10} .wid-etendu{grid-column:span 8} }
@container (max-width:870px) { .bord-grille{--col:8}  .wid-etendu{grid-column:span 8} }
@container (max-width:700px) { .bord-grille{--col:6}  .wid-etendu{grid-column:span 6} }
@container (max-width:530px) { .bord-grille{--col:4}  .wid-etendu{grid-column:span 4} }
@container (max-width:360px) { .bord-grille{--col:2}
                               .wid-normal,.wid-etendu{grid-column:span 2;grid-row:span 2} }

/* ------------------------------------------------------------------
   La carte

   Elle est de taille fixe : c'est ce que « carré » veut dire. Son corps
   défile donc quand il déborde - une tuile n'a pas d'autre issue -, mais
   les plafonds de lignes sont réglés pour que le cas ordinaire tienne
   sans défilement. Un widget dont il faut faire rouler la molette pour
   lire la deuxième ligne n'est plus un résumé.
   ------------------------------------------------------------------ */
.wid{
  position:relative;display:flex;flex-direction:column;min-width:0;overflow:hidden;
  background:var(--surface);border:1px solid var(--bord);
  border-radius:var(--r-m);box-shadow:var(--ombre-douce);
}
.wid:hover{border-color:#DFE3EB}

/* ---------------- La tête ---------------- */
/* La tête passe à la ligne plutôt que de sacrifier le titre. Sans
   « flex-wrap », le marqueur - qui ne se comprime pas - réduisait le titre
   à zéro sur les cartes les plus étroites : la carte n'avait plus de nom. */
/* Les calages suivent l'échelle : à cartes une fois et demie plus
   petites, un padding de seize pixels prendrait le quart de la largeur
   d'un Compact. */
.wid-tete{
  display:flex;align-items:center;flex-wrap:wrap;gap:5px 8px;flex:none;
  padding:11px 13px 0;
}
.wid-icone{position:relative;display:grid;place-items:center;flex:none;width:22px;height:22px;
  background:var(--rose-clair);border-radius:var(--r-s)}
.wid-icone .ico{width:12px;height:12px;color:var(--rose)}
.wid-titre{
  flex:1 1 58%;min-width:0;margin:0;
  font-size:13px;font-weight:700;line-height:1.25;color:var(--nuit);
  /* Deux lignes au plus : dans un carré de deux cellules, un titre de
     quatre mots ne tient pas sur une ligne, et le couper à l'ellipse
     laisserait « Ce qui me... » là où la place existe juste en dessous. */
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;
}
.wid-coiffe{flex:none}

/* ------------------------------------------------------------------
   La poignée et les gestes, hors du flux

   Ils sont **posés en absolu** : en flux, des boutons invisibles gardent
   leur largeur - « opacity: 0 » n'enlève rien à la place occupée - et il
   ne resterait au titre que trois caractères et une ellipse.

   La poignée recouvre le **carré du pictogramme** au survol : même place,
   même forme, à treize pixels du bord. Serrée dans la gouttière, elle
   collait au rebord de la carte ; et un décalage de la tête pour lui
   faire de la place aurait indenté tous les titres en permanence, pour
   un bouton qui ne paraît qu'au survol.

   La poignée n'existe que si le script est là : sans lui, on déplace par
   les boutons de formulaire, et une poignée qui ne saisirait rien serait
   pire qu'une poignée absente. C'est un <button>, non un carré décoratif :
   les flèches du clavier déplacent la carte (décision W9).
   ------------------------------------------------------------------ */
.wid-poignee{display:none}
[data-bord-js] .wid-poignee{
  position:absolute;inset:0;z-index:2;
  display:grid;place-content:center;gap:3px;
  padding:0;border-radius:var(--r-s);
  background:var(--rose-clair);border:0;cursor:grab;opacity:0;transition:opacity .12s;
  /* Au doigt, presser la poignée saisit la carte : sans cela, le
     navigateur prend le geste pour un défilement et lâche la saisie. */
  touch-action:none;
}
[data-bord-js] .wid-poignee span{width:10px;height:2px;border-radius:1px;background:var(--rose)}
[data-bord-js] .wid:hover .wid-poignee,
[data-bord-js] .wid:focus-within .wid-poignee{opacity:1}
[data-bord-js] .wid-poignee:focus-visible{opacity:1;outline:2px solid var(--rose);outline-offset:2px}
[data-bord-js] .wid-poignee:active{cursor:grabbing}

.wid-gestes{
  position:absolute;top:9px;right:11px;z-index:2;
  display:flex;align-items:center;gap:3px;
  border-radius:var(--r-s);
  /* Le halo de fond découpe les boutons dans la carte : ils recouvrent le
     marqueur au survol plutôt que de lui disputer la ligne en permanence. */
  background:var(--surface);box-shadow:0 0 0 5px var(--surface);
  opacity:0;pointer-events:none;transition:opacity .12s;
}
.wid:hover .wid-gestes,.wid:focus-within .wid-gestes{opacity:1;pointer-events:auto}
.wid-geste{display:flex;margin:0}
.wid-geste button,.wid-menu-bouton{
  display:grid;place-items:center;width:23px;height:23px;padding:0;
  color:var(--texte-doux);background:none;border:1px solid transparent;
  border-radius:var(--r-s);cursor:pointer;
}
.wid-geste button:hover,.wid-menu-bouton:hover{
  color:var(--rose);background:var(--rose-clair);border-color:var(--rose-pale);
}
.wid-geste .ico,.wid-menu-bouton .ico{width:14px;height:14px}

/* Les deux vocabulaires ne cohabitent jamais : le script pose
   « data-bord-js » sur la grille, ce qui remplace les quatre boutons de
   formulaire par le seul bouton de menu. Sans script, l'inverse. */
.wid-menu-bouton{display:none}
[data-bord-js] .wid-menu-bouton{display:grid}
[data-bord-js] .wid-geste{display:none}
.wid-menu-bouton[aria-expanded="true"]{
  color:var(--rose);background:var(--rose-clair);border-color:var(--rose-pale);
}
.wid:has(.wid-menu-bouton[aria-expanded="true"]) .wid-gestes{opacity:1;pointer-events:auto}

/* ---------------- Le menu de réglage ----------------
   Il vit dans la couche flottante quand il est ouvert (règle 2 du
   document 13) : la carte est rognée par « overflow: hidden » - il le
   faut, un carré ne laisse rien dépasser -, et le menu y serait donc
   coupé net. */
.wid-menu{
  position:absolute;min-width:216px;padding:7px;
  animation:signal-apparition .12s ease-out;
  background:var(--surface);border:1px solid var(--bord);
  border-radius:var(--r-m);box-shadow:var(--ombre);
}
.wid-menu[hidden]{display:none}
.wid-menu-titre{
  margin:3px 8px 6px;font-size:10.5px;font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;color:var(--texte-doux);
}
.wid-menu-choix,.wid-menu-retrait{margin:0}
.wid-menu-choix button,.wid-menu-retrait button{
  display:flex;align-items:center;gap:9px;width:100%;padding:8px 9px;
  font:inherit;font-size:13.5px;text-align:left;color:var(--texte);
  background:none;border:0;border-radius:var(--r-s);cursor:pointer;
}
.wid-menu-choix button small{
  margin-left:auto;font-size:11.5px;font-weight:500;color:var(--texte-doux);
  font-variant-numeric:tabular-nums;
}
.wid-menu-choix button:hover,.wid-menu-retrait button:hover{background:var(--bord-clair)}
.wid-menu-choix button.actif{color:var(--rose);font-weight:700;background:var(--rose-clair)}
.wid-menu-choix button.actif small{color:var(--rose)}
.wid-menu-retrait{margin-top:5px;padding-top:5px;border-top:1px solid var(--bord-clair)}
.wid-menu-retrait button{color:var(--rouge,#B3261E)}
.wid-menu-retrait .ico{width:14px;height:14px}

/* La pastille de forme : un carré petit, un carré grand, un rectangle
   large, dans un cadre commun. Un réglage de mise en page se reconnaît
   mieux qu'il ne se lit - et ici la pastille dit exactement ce que la
   grille fera. */
.wid-menu-forme{
  position:relative;display:inline-block;flex:none;width:18px;height:18px;
  background:var(--bord-clair);border-radius:3px;
}
.wid-menu-forme::before{
  content:"";position:absolute;left:50%;top:50%;
  transform:translate(-50%,-50%);
  background:var(--rose);border-radius:2px;
}
.wid-forme-normal::before {width:12px;height:12px}
.wid-forme-etendu::before {width:16px;height:8px}

/* ---------------- Le corps et le pied ----------------
   « wid-centre » pose au milieu du carré ce qui tient en trois lignes -
   la recherche, l'aide, le bouton d'envoi -, où le haut de la carte
   laisserait un vide qui se remarque. « wid-emplir » fait l'inverse :
   son contenu prend toute la hauteur, tuiles et portes comprises. */
/* ------------------------------------------------------------------
   Un widget ne défile pas

   C'est une règle, non un réglage (décision W15). Une carte de taille
   fixe dont le contenu déborde se coupe au milieu d'une ligne : on y lit
   « Appel d'offres pour les prestations de transport maritime des
   matériaux de », et rien ne dit qu'il y a une suite. Le défilement ne
   corrigeait pas cela, il le cachait - une barre de sept pixels dans une
   carte de cent quatre-vingts n'appelle personne.

   Le contenu est donc **plafonné à ce qui tient**, et ce qui ne tient pas
   est compté : « + 14 autres ». Le nombre informe, le lien y mène.
   ------------------------------------------------------------------ */
.wid-corps{
  flex:1;min-height:0;padding:10px 13px 13px;
  overflow:hidden;
}
.wid-corps.wid-centre{display:flex;flex-direction:column;justify-content:center;overflow:hidden}
.wid-corps.wid-emplir{display:flex;flex-direction:column;overflow:hidden}
.wid-corps.wid-emplir>*{flex:1;min-height:0}

.wid-pied{
  flex:none;padding:8px 13px;border-top:1px solid var(--bord-clair);
  background:var(--bord-clair);
}
.wid-lien{
  display:inline-flex;align-items:center;gap:5px;
  font-size:12px;font-weight:600;color:var(--rose);text-decoration:none;
}
.wid-lien:hover{color:var(--rose-sombre)}
.wid-lien .ico{width:13px;height:13px}

/* ------------------------------------------------------------------
   Le glisser-déposer

   Trois états, et trois seulement : la carte saisie suit le doigt, la
   place qu'elle laisse est marquée en pointillé, et rien d'autre ne
   bouge. Une grille qui réanimerait toutes ses cartes à chaque
   déplacement rendrait le rangement illisible.
   ------------------------------------------------------------------ */
/* La carte volée se déplace en « transform » - les deux variables sont
   écrites par le script à chaque mouvement - et non en left/top : le
   compositeur porte le vol seul, sans remettre la page en forme. La
   légère inclinaison et le gain d'échelle disent « saisie » sans mot. */
.wid-vole{
  position:fixed;z-index:400;margin:0;pointer-events:none;
  box-shadow:0 18px 44px rgba(16,26,46,.22);
  border-color:var(--rose-pale);
  transform:translate(var(--vole-x,0px),var(--vole-y,0px)) rotate(.6deg) scale(1.02);
  will-change:transform;
  opacity:.97;
  animation:wid-saisir .14s ease-out;
}
/* La prise en main : la carte se soulève sous le doigt au lieu de
   changer d'état d'un coup. */
@keyframes wid-saisir{
  from{transform:translate(var(--vole-x,0px),var(--vole-y,0px)) rotate(0deg) scale(1);
       box-shadow:var(--ombre-douce)}
}
.wid-fantome{
  border:1.5px dashed var(--rose-pale);border-radius:var(--r-m);
  background:var(--rose-voile);box-shadow:none;
}
.bord-grille.range{cursor:grabbing;user-select:none}
/* Pendant un rangement, la grille se tait : ni poignée ni menu ne
   s'allument sous la carte volée qui passe. */
.bord-grille.range .wid:hover .wid-poignee,
.bord-grille.range .wid:hover .wid-gestes{opacity:0;pointer-events:none}

/* =====================================================================
   3. L'intérieur des widgets
   ===================================================================== */

.wid-vide{margin:0;font-size:13px;line-height:1.55;color:var(--texte-doux)}
.wid-note{margin:6px 0 0;font-size:12.5px;line-height:1.5;color:var(--texte-doux)}
.wid-alerte{
  margin:8px 0 0;font-size:12px;font-weight:600;line-height:1.4;color:var(--rose);
}
.wid-nom{margin:0;font-size:13.5px;font-weight:600;line-height:1.4;color:var(--nuit)}
.wid-detail{margin:2px 0 0;font-size:12.5px;line-height:1.45;color:var(--texte-doux)}
.wid-bouton{margin:12px 0 0}
.wid-bouton .bouton{width:100%;justify-content:center}

/* Les tuiles perdent leur marge haute - dans une carte, c'est le corps du
   widget qui donne la respiration - et prennent toute la hauteur du carré.
   Quatre tuiles en deux rangées de deux, et non en une file : une file de
   quatre laisserait les trois quarts de la hauteur vides. */
/* Le double sélecteur n'est pas une coquetterie : « composants.css » est
   chargée **après** cette feuille par « enTeteBord », si bien que « .tuiles »
   l'emporterait sur « .wid-tuiles » à spécificité égale. C'est le piège de
   l'ordre de cascade déjà rencontré sur la fiche d'entreprise - on ne compte
   pas sur le rang des <link>, on qualifie la règle. */
.tuiles.wid-tuiles{margin-top:0;height:100%;border-radius:var(--r-s)}
.tuiles.wid-tuiles-4{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:1fr}
.wid-tuiles .tuile{align-content:center;padding:12px 14px}
.wid-tuiles .tuile strong{font-size:26px}
.wid-tuiles .tuile-intitule{font-size:12px;font-weight:600;color:var(--texte)}
.wid-tuiles .tuile-detail{font-size:11.5px}

/* ---------------- Une liste de lignes ---------------- */
/* Les lignes d'un extrait ont toutes la même hauteur, et c'est ce qui
   rend le plafond calculable : le nom tient sur une ligne, le détail sur
   une autre, et l'ellipse prend le relais. Un nom d'annonce qui se
   déroulerait sur trois lignes ferait tomber la cinquième ligne hors de
   la carte, et le plafond serait faux. */
.wid-liste{list-style:none;margin:0;padding:0}
/* « position: relative » : chaque ligne est le cadre du lien qui
   s'étire sur elle (voir « .wid-ligne-lien » plus bas). */
.wid-liste li{
  position:relative;display:flex;align-items:flex-start;gap:9px;
  padding:4px 0;border-top:1px solid var(--bord-clair);
}
/* Les interlignes d'une liste sont serrés d'un cran par rapport au reste
   de la carte : c'est un extrait qu'on parcourt, pas un texte qu'on lit.
   Quarante-quatre pixels par ligne, cinq lignes et leur compte : deux
   cent cinquante pixels dans un corps qui en offre deux cent quatre-vingt,
   ce qui laisse la marge qu'une donnée plus longue réclamera. */
.wid-liste .wid-nom{font-size:13px;line-height:1.3}
.wid-liste .wid-detail{margin-top:1px;font-size:11.5px;line-height:1.35}
.wid-liste li:first-child{padding-top:2px;border-top:0}
.wid-liste .wid-nom,.wid-liste .wid-detail{
  display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden;
}

/* ------------------------------------------------------------------
   Pourquoi la liste d'un Étendu reste sur une colonne

   Deux colonnes doubleraient le nombre d'annonces à hauteur égale, et
   c'eût été une bonne raison de choisir l'Étendu. Mais l'Étendu se
   replie - à six colonnes, à quatre, à deux - et son contenu ne suit
   pas : le serveur a déjà rendu ses lignes quand la feuille décide de sa
   largeur. Chaque palier demandait alors sa propre hauteur, calculée à
   la main, et un palier oublié coupait la liste. Trois cas de bord pour
   un gain de quatre lignes.

   L'Étendu garde donc le même nombre d'annonces que le Normal - il est
   plus large, pas plus haut - et ce qu'il apporte est la **lisibilité** :
   un objet de marché de quatre-vingts caractères y tient sans ellipse,
   là où le Normal le coupe. C'est le défaut qu'on cherchait à corriger.
   ------------------------------------------------------------------ */

/* Ce qui ne tient pas est compté, et le compte est un lien. */
.wid-reste{border-top:1px solid var(--bord-clair)}
.wid-reste a{
  display:inline-flex;align-items:center;gap:5px;padding:4px 0 0;
  font-size:11.5px;font-weight:600;color:var(--texte-doux);text-decoration:none;
}
.wid-reste .ico{width:11px;height:11px}
.wid-reste a:hover{color:var(--rose)}
.wid-ligne-texte{flex:1;min-width:0}
.wid-puce{
  display:grid;place-items:center;flex:none;width:24px;height:24px;
  background:var(--rose-clair);border-radius:var(--r-s);
}
.wid-puce .ico{width:13px;height:13px;color:var(--rose)}
/* La famille ouvre la ligne du détail, elle n'a plus de ligne à elle :
   « APPEL D'OFFRES · Avis d'appel public à la concurrence ». Le point
   médian est posé par la feuille, pour ne pas traîner quand le détail
   est vide. */
.wid-famille{
  font-size:10px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--rose);
}

/* ------------------------------------------------------------------
   La ligne entière est cliquable

   Le nom porte un vrai lien - il s'ouvre au clic du milieu, se copie,
   s'annonce au lecteur d'écran -, et son « ::after » s'étire sur la
   ligne : c'est toute la ligne qu'on vise, pas un mot. Les gestes de
   ligne - mise de côté, lien d'entreprise - ont été retirés (26 août
   2026) : ils disputaient le clic à la ligne, pour un rangement que
   plus rien n'affichait.
   ------------------------------------------------------------------ */
.wid-ligne-lien{color:inherit;text-decoration:none}
.wid-ligne-lien::after{content:"";position:absolute;inset:0}
.wid-liste li:hover .wid-ligne-lien{color:var(--rose)}
.wid-ligne-lien:focus-visible{outline:2px solid var(--rose);outline-offset:2px}

/* Le rythme : la dernière ligne peut être un compte, comme dans les
   listes. Elle s'aligne sur elles. */
.wid-rythme .wid-reste{margin-top:2px;padding-top:6px}

/* Les mots-clés sont des pastilles, non une phrase à virgules : ils sont
   entrés un à un, et se relisent un à un. */
.wid-mots{display:flex;flex-wrap:wrap;gap:5px;margin:0}
.wid-mot{
  padding:3px 9px;font-size:12px;color:var(--texte);
  background:var(--bord-clair);border:1px solid var(--bord);border-radius:999px;
}

/* ---------------- Le rythme d'envoi ----------------
   La semaine en pastilles : ce qui est retenu est en plein, le reste
   en creux. */
/* Les pastilles tiennent sur une seule ligne : la semaine se lit d'un
   bloc ou ne se lit pas. D'où la gouttière serrée et la largeur minimale
   calée sur « Di », la plus étroite. */
.wid-jours{display:flex;flex-wrap:nowrap;gap:3px;margin:0}
.wid-jour{
  display:grid;place-items:center;flex:1 1 0;min-width:0;padding:5px 2px;
  font-size:11px;font-weight:700;letter-spacing:0;
  color:var(--texte-doux);background:var(--bord-clair);
  border:1px solid transparent;border-radius:var(--r-s);
}
.wid-jour.retenu{
  color:var(--rose);background:var(--rose-clair);border-color:var(--rose-pale);
}
.wid-jours+.wid-note{margin-top:11px}

.wid-rythme{list-style:none;margin:14px 0 0;padding:0;display:grid;gap:8px}
.wid-rythme li{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px;
  font-size:13px;color:var(--texte-doux);
}
.wid-rythme strong{font-size:13px;color:var(--nuit)}

/* ---------------- L'envoi à la demande ----------------
   Les deux dates qui situent l'envoi - la dernière parution détenue, le
   dernier relevé reçu -, dans la grammaire du rythme : l'étiquette en
   plein, la valeur en doux. Le geste, lui, se dit en phrases au-dessus. */
.wid-faits{list-style:none;margin:12px 0;padding:0;display:grid;gap:7px}
.wid-faits li{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px;
  font-size:12.5px;color:var(--texte-doux);
}
.wid-faits strong{flex:none;font-size:12.5px;color:var(--nuit)}
.wid-faits span{flex:1;min-width:0}

/* ---------------- Les portes ---------------- */
/* Deux colonnes dans un Normal, trois dans un Étendu : la grille des
   portes suit le carré plutôt que de compter ses pixels. */
.wid-portes{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  grid-auto-rows:1fr;gap:10px;
}
.wid-etendu .wid-portes{grid-template-columns:repeat(3,minmax(0,1fr))}
/* Le contenu se centre dans la porte. Les rangées s'étirent pour remplir
   le carré : tassé en haut, le texte laissait sous lui les deux tiers de
   la porte vides ; réparti, il éloignait le pictogramme de son intitulé. */
.wid-porte{
  display:grid;gap:2px;align-content:center;padding:11px 12px;
  text-decoration:none;
  border:1px solid var(--bord);border-radius:var(--r-s);
}
.wid-porte:hover{border-color:var(--rose-pale);background:var(--rose-clair)}
.wid-porte-icone .ico{width:16px;height:16px;color:var(--rose)}
.wid-porte-nom{margin-top:4px;font-size:13px;font-weight:600;color:var(--nuit)}
.wid-porte-aide{font-size:11.5px;line-height:1.4;color:var(--texte-doux)}

/* ---------------- La recherche rapide ---------------- */
/* Le formulaire respire entre les deux notes qui l'encadrent : ce que la
   recherche couvre au-dessus, ce qu'on peut lui donner au-dessous. */
.wid-cherche{margin:12px 0 4px}
.wid-cherche .champ-etiquette{margin-bottom:0}
/* Le champ prend toute la place, le bouton n'est qu'un carré à la loupe
   au bout de la ligne - il s'étire à la hauteur du champ plutôt que de
   porter son propre calage, pour que les deux fassent un seul bloc. */
.wid-cherche-ligne{display:flex;align-items:stretch;gap:8px;margin-top:6px}
.wid-cherche-ligne .bouton{flex:none;width:42px;padding:0;justify-content:center}
.wid-cherche-ligne .bouton .ico{margin:0}
/* Le registre de composants enveloppe le champ effaçable dans
   « .champ-saisie » : c'est elle l'enfant de la ligne, et donc elle qui
   s'étire - l'input la remplit (« width: 100% » de composants.css). La
   règle sur l'input reste pour le rendu sans script, où il est l'enfant
   direct. */
.wid-cherche-ligne .champ-saisie{flex:1 1 auto;min-width:0}
.wid-cherche input[type="search"]{
  flex:1 1 auto;min-width:0;padding:10px 12px;
  font:inherit;font-size:14px;color:var(--nuit);
  background:var(--surface);border:1px solid var(--bord);
  border-radius:var(--r-s);outline:0;
}
.wid-cherche input[type="search"]:focus{border-color:var(--rose);box-shadow:var(--anneau)}

/* =====================================================================
   4. Le catalogue, en fenêtre
   =====================================================================
   Un formulaire, non une liste que le script assemblerait : sans
   JavaScript, on coche, on choisit une taille, on enregistre. Le script
   n'y ajoute que le compteur et l'ordre repris du glisser-déposer.
   ===================================================================== */
.cat-chapo{margin:0 0 10px;font-size:13.5px;line-height:1.6;color:var(--texte-doux)}
.cat-compte{
  margin:0 0 16px;padding-bottom:12px;border-bottom:1px solid var(--bord-clair);
  font-size:13px;color:var(--texte-doux);
}
.cat-compte strong{font-size:15px;color:var(--nuit)}

/* Deux cartes de front : une carte n'a que trois lignes à dire, et sur
   les 760 px de la fenêtre, une colonne unique l'étirait en bandeau et
   doublait la hauteur à faire défiler. Les intertitres de groupe sont
   partis avec (26 août 2026) : sept cartes n'ont pas besoin de quatre
   rubriques. */
.cat-liste{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
@media (max-width:620px){ .cat-liste{grid-template-columns:1fr} }

/* ------------------------------------------------------------------
   L'état se lit à la lumière, non à la couleur de fond

   Poser un fond rose sur chaque carte affichée peignait la fenêtre en
   rose dès que tout l'était - et quand tout est marqué, plus rien ne
   l'est. C'est donc le **masqué** qui s'éteint : fond gris, pictogramme
   et nom en doux. L'affiché reste net, sur blanc, l'interrupteur dit
   déjà son état.
   ------------------------------------------------------------------ */
/* La carte se resserre pour tenir à deux de front : pictogramme de 26,
   corps de 12, calages d'un cran plus courts. L'interrupteur monte dans
   le coin, en face du nom - c'est la même ligne de lecture. */
.cat-ligne{
  display:grid;grid-template-columns:26px minmax(0,1fr) auto;
  gap:6px 10px;align-items:start;padding:11px 12px;
  background:var(--surface);border:1px solid var(--bord);border-radius:var(--r-m);
  transition:background .12s,border-color .12s;
}
.cat-ligne.pose{border-color:var(--rose-pale)}
.cat-ligne:not(.pose){background:var(--bord-clair)}
.cat-icone{
  display:grid;place-items:center;width:26px;height:26px;
  background:var(--rose-clair);border-radius:var(--r-s);
}
.cat-icone .ico{width:13px;height:13px;color:var(--rose)}
.cat-ligne:not(.pose) .cat-icone{background:var(--surface)}
.cat-ligne:not(.pose) .cat-icone .ico{color:var(--texte-doux)}
/* « display: contents » dissout l'enveloppe du texte dans la grille de la
   carte : le nom reste sur la ligne du pictogramme et de l'interrupteur,
   mais la description et les tailles courent sur **toute la largeur** -
   dans la colonne du milieu, elles s'empilaient sur quatre lignes en
   laissant un blanc sous l'interrupteur. */
.cat-texte{display:contents}
.cat-nom{grid-column:2;font-size:13.5px;font-weight:700;line-height:1.35;
  color:var(--nuit);cursor:pointer;padding-top:3px}
.cat-ligne:not(.pose) .cat-nom{color:var(--texte-doux)}
.cat-aide{grid-column:1/-1;margin:0;font-size:12px;line-height:1.45;color:var(--texte-doux)}
.cat-bascule{grid-column:3;grid-row:1;padding-top:3px}
.cat-bascule .interrupteur-texte{font-size:11.5px}

/* ------------------------------------------------------------------
   Le choix de la taille

   Trois boutons radio, non une liste déroulante : sous une fenêtre
   modale, la couche flottante du sélecteur sur mesure est inerte
   (document 29, décision C-D3), et trois valeurs ne méritent pas qu'on
   les cache derrière un déroulé.

   Il s'efface tant que le widget n'est pas posé : régler la largeur de ce
   qu'on n'affiche pas n'a pas de sens, et le proposer laisserait croire
   que le réglage suffit à poser la carte.
   ------------------------------------------------------------------ */
.cat-tailles{grid-column:1/-1;display:flex;flex-wrap:wrap;gap:5px;margin-top:2px}
.cat-ligne:not(.pose) .cat-tailles{opacity:.42;pointer-events:none}
.cat-taille{display:inline-flex;margin:0;cursor:pointer}
.cat-taille input{position:absolute;opacity:0;width:0;height:0}
.cat-taille>span{
  display:inline-flex;align-items:center;gap:6px;padding:3px 9px 3px 4px;
  font-size:11.5px;font-weight:600;color:var(--texte-doux);
  background:var(--surface);border:1px solid var(--bord);border-radius:999px;
}
.cat-taille>span small{
  font-size:11px;font-weight:500;opacity:.75;font-variant-numeric:tabular-nums;
}
.cat-taille:hover>span{border-color:var(--texte-doux)}
.cat-taille input:checked+span{
  color:var(--rose);background:var(--rose-clair);border-color:var(--rose);
}
.cat-taille input:focus-visible+span{outline:2px solid var(--rose);outline-offset:2px}

/* La taille unique se dit, elle ne se choisit pas : un radio solitaire se
   lirait comme une case qu'on n'aurait pas cochée. Même dessin que les
   segments, en inerte. */
.cat-taille-fixe{
  display:inline-flex;align-items:center;gap:6px;padding:3px 9px 3px 4px;
  font-size:11.5px;font-weight:600;color:var(--texte-doux);
  background:var(--bord-clair);border:1px solid transparent;border-radius:999px;
}
.cat-taille-fixe small{
  font-size:11px;font-weight:500;opacity:.75;font-variant-numeric:tabular-nums;
}

/* =====================================================================
   5. La fenêtre d'envoi du relevé (document 30)
   =====================================================================
   Elle est posée par le widget « Envoyer un relevé » plutôt que par
   l'écran lui-même (décision W12).

   Les règles « .accueil-* » de l'ancien gabarit, qui fermaient cette
   feuille pour la seule maquette du site public, sont parties le 26 août
   2026 (document 45) : la maquette rejoue désormais le canevas, et ses
   cartes s'habillent des règles « .wid-* » ci-dessus.
   ===================================================================== */

.envoi-chapo{
  margin:0 0 18px;font-size:14px;line-height:1.6;color:var(--texte-doux);
}
.envoi-chapo strong{color:var(--nuit)}
/* Le champ natif porte sa mise : cet écran ne charge pas app.css (voir
   l'appel à « enTeteBord »), et le <select> y arrivait nu. La forme est
   celle de la fenêtre de capture, qui a le même champ pour la même
   raison - sous une modale, le sélecteur sur mesure est inerte. */
.envoi-periode{
  width:100%;margin-top:7px;padding:10px 12px;
  font:inherit;font-size:14.5px;color:var(--nuit);
  background:var(--surface);border:1px solid var(--bord);
  border-radius:var(--r-s);outline:0;
}
.envoi-periode:focus{border-color:var(--rose);box-shadow:var(--anneau)}
.envoi-titre{margin-top:20px}

/* Une case par personne, séparées d'un filet : la liste se compte du
   regard, ce qui est tout ce qu'on lui demande avant de valider. */
.envoi-gens{margin-top:4px}
.envoi-gens .coche{width:100%;padding:9px 0;border-bottom:1px solid var(--bord-clair)}
.envoi-gens .coche:last-child{border-bottom:0}
.envoi-gens .coche>span{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 10px}
.envoi-adresse{font-size:13px;color:var(--texte-doux)}
/* La mention se lit sans arrêter la lecture : c'est un avertissement, pas
   un refus - la personne reste joignable, et c'est celui qui envoie qui
   décide (décision D30-3). */
.envoi-muet{
  padding:1px 8px;border-radius:999px;
  background:var(--bord-clair);color:var(--texte-doux);
  font-size:11.5px;font-weight:600;
}
/* La coupe des longues périodes, dite avant l'envoi et non découverte dans
   le message. Elle ne s'habille pas en avertissement : c'est une note. */
.envoi-note{
  margin:9px 0 0;font-size:12.5px;line-height:1.5;color:var(--texte-doux);
}
