
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
  --fond: #12100e;
  --carte: #1b1815;
  --carte2: #221f1b;
  --bord: #2e2a25;
  --or: #d9a441;
  --or-pale: #e8bb6a;
  --vert: #6fa87c;
  --rouge: #c4705f;
  --bleu: #5f8fc4;
  --texte: #e8e0d4;
  --texte-doux: #a09080;
  /* v30 : remonté de #6a5e52 (3,0:1 sur --fond, sous le seuil AA de 4,5) à
     #8a7a6a (4,6:1). Cette couleur porte des prix, des dates, des noms de
     plateforme et le montant de la commission : elle doit être lisible sur un
     téléphone en plein jour. Revenir en arrière = cette seule ligne. */
  --texte-tres-doux: #8a7a6a;
  --rayon: 12px;
  --rayon-sm: 8px;
}
/* `overscroll-behavior-x` et non `overscroll-behavior` : sur l'axe vertical,
   `none` supprime le tirer-pour-rafraichir natif du telephone. Il est le seul
   moyen de rafraichir depuis que l'entete ne porte plus de bouton « Actualiser »
   (18/09/2026), et il est gratuit — on ne s'en prive pas pour supprimer un rebond.
   L'axe horizontal reste bride : rien ici ne se navigue au glissement lateral. */
html, body { height: 100%; background: var(--fond); color: var(--texte); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; font-size: 16px; line-height: 1.5; overscroll-behavior-x: none; }
a { color: var(--or); text-decoration: none; }
button { cursor: pointer; border: none; font-family: inherit; font-size: inherit; }
input, textarea, select { font-family: inherit; font-size: inherit; color: var(--texte); background: var(--carte2); border: 1px solid var(--bord); border-radius: var(--rayon-sm); padding: 12px; width: 100%; outline: none; }
input:focus, textarea:focus, select:focus { border-color: var(--or); }
textarea { resize: vertical; min-height: 80px; }
select option { background: var(--carte2); }
h1 { font-size: 1.4rem; font-weight: 700; }
h2 { font-size: 1.1rem; font-weight: 600; }

/* ── Bandeau erreur ── */
#bandeau-erreur {
  background: #8b1a1a; color: white;
  padding: 12px 16px;
  font-size: 0.85rem; line-height: 1.4;
  display: none; flex-direction: column; gap: 6px;
}
#bandeau-erreur .erreur-msg-texte { flex: 1; word-break: break-word; }
#bandeau-erreur button {
  background: rgba(255,255,255,0.2); border: 1px solid rgba(255,255,255,0.4);
  color: white; border-radius: 4px; padding: 4px 12px;
  font-size: 0.8rem; align-self: flex-start; margin-top: 4px;
}

/* ── LES ANNONCES, UN SEUL ENDROIT ─────────────────────────────────────────
   Laurent, 25/09/2026 : erreur, analyse, toast et annulations s'affichaient
   les uns en haut, les autres en bas, et il a demande « tout mettre au meme
   endroit, a savoir au milieu ». #zone-annonces est le seul conteneur fixe :
   centre en hauteur et en largeur, ses enfants (`.annonce`) s'empilent dedans
   au lieu de se superposer. Il ne pousse plus rien (le decalage --bandeau-h du
   ticket 1433 n'existe plus : une annonce centree ne recouvre ni la barre du
   haut, ni la navigation du bas, ni le bouton « ← » de la camera).

   Le conteneur laisse passer les appuis (`pointer-events: none`) ; une annonce
   qui porte un bouton le reprend (`.annonce button, .annonce a`), pour que
   « Fermer » et « Annuler » restent atteignables et que le reste de l'ecran
   ne le soit pas moins. Une annonce qui s'efface (toast, annulations) n'est
   dans le flux que tant qu'elle est `.visible`. */
#zone-annonces {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
  z-index: 9999; width: calc(100% - 32px); max-width: 480px;
  display: flex; flex-direction: column; align-items: stretch; gap: 8px;
  pointer-events: none;
}
.annonce {
  position: static; transform: none; opacity: 1; margin: 0;
  width: 100%; max-width: none; white-space: normal;
  border-radius: var(--rayon); box-shadow: 0 4px 24px rgba(0,0,0,0.6);
  text-align: center; justify-content: center;
}
.annonce button, .annonce a { pointer-events: auto; }
.toast.annonce:not(.visible), .undo-revu-bar.annonce:not(.visible),
.undo-enlever-bar.annonce:not(.visible) { display: none; }
#bandeau-erreur.annonce { text-align: left; }

/* ── Pages ── */
.page { display: none; min-height: 100vh; }
.page.active { display: block; }
/* La marge sous le dernier bloc de l'accueil : la hauteur de la barre d'action
   basse (68 px : 10 + 48 + 10) plus les 16 px de la gouttiere des cotes
   (DESIGN.md), plus la zone sure des telephones a barre basse. Elle est sur la
   page et non sur le dernier bloc, qui change selon le compte. Cette valeur et
   la hauteur de `.barre-action-basse` se lisent ensemble : reduire l'une sans
   l'autre laisse les compteurs sous la barre, et un chiffre couvert par un
   bouton ne se lit pas du tout. */
#p-accueil.page { padding-bottom: calc(84px + env(safe-area-inset-bottom)); }
#p-accueil .compteurs { padding-bottom: 0; }

/* ── En-tête ── */
.entete { padding: 24px 16px 8px; display: flex; align-items: center; gap: 12px; }
.entete h1 { flex: 1; }
.entete-actions { display: flex; gap: 8px; }
.btn-icone { background: var(--carte2); border: 1px solid var(--bord); border-radius: var(--rayon-sm); padding: 8px; color: var(--texte-doux); display: flex; align-items: center; justify-content: center; }
.btn-icone svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* ── Compteurs ── */
.compteurs { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; padding: 0 16px 16px; }
.compteur { background: var(--carte); border-radius: var(--rayon); padding: 14px 10px; text-align: center; border: 1px solid var(--bord); }
.compteur-valeur { font-size: 1.6rem; font-weight: 700; color: var(--texte-doux); font-family: ui-monospace, 'Courier New', monospace; font-variant-numeric: tabular-nums; line-height: 1; }
.compteur-label { font-size: 0.7rem; color: var(--texte-doux); margin-top: 4px; }

/* ── Boutons modes accueil ── */
.btns-modes { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 0 16px 24px; }
.btn-mode {
  background: var(--or); color: #12100e;
  font-size: 0.9rem; font-weight: 700;
  padding: 15px 12px; border-radius: var(--rayon);
  text-align: center; transition: background 0.15s;
  display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 10px;
  line-height: 1.3;
}
.btn-mode:active { background: var(--or-pale); }
.btn-mode-scene {
  background: var(--carte2); color: var(--texte);
  border: 1px solid var(--bord);
}
.btn-mode-scene:active { background: var(--carte); }
.btn-mode-icone { font-size: 1.8rem; }

/* ── La barre d'action basse ───────────────────────────────────────────────
   « Photographier » est la seule action principale de l'accueil, et elle se
   touche d'une main pendant que l'autre tient l'objet : elle est donc en bas
   de l'ecran, pas en bas de la page. `fixed` et non un simple deplacement dans
   le flux — sur un compte a 115 objets, le bas de la page est a plusieurs
   ecrans du pouce.
   La barre porte son propre fond opaque : la liste passe DESSOUS en defilant,
   et un bouton translucide sur des vignettes ne se lit plus. L'ombre est celle
   de la barre de fusion, deja au catalogue (DESIGN.md, « Rayons et ombres ») :
   c'est le meme cas, un element qui flotte au-dessus du contenu.
   z-index 40, sous la barre de fusion (50) : quand on selectionne des objets a
   fusionner, la barre de fusion se pose juste au-dessus de celle-ci. */
.barre-action-basse {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
  background: var(--fond);
  border-top: 1px solid var(--bord);
  box-shadow: 0 -4px 20px rgba(0,0,0,0.5);
}
/* 48 px de haut : au-dela des 40 px du minimum tactile, parce que c'est
   l'action que tout le monde fait tous les jours. La taille de texte revient
   dans l'echelle de DESIGN.md (0,95 rem, « bouton principal ») : le 1,1 rem
   d'avant tenait a la bande pleine hauteur qu'occupait le bouton en haut. */
.barre-action-basse .btn-photographier {
  width: 100%; min-height: 48px; font-size: 0.95rem; padding: 12px;
}

/* ── Section lots ── */
.section-titre { padding: 10px 16px 6px; font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--texte-doux); }
.lots-liste { display: flex; flex-direction: column; }

/* ── Carte lot — v28 : lignes avec filet ── */
.lot-carte { display: flex; align-items: center; gap: 10px; padding: 10px 16px; cursor: pointer; user-select: none; -webkit-user-select: none; position: relative; }
.lot-carte:not(:last-child)::after { content: ''; position: absolute; bottom: 0; left: 78px; right: 0; height: 1px; background: var(--bord); }
.lot-carte.selectionnee { background: #221d12; }
.lot-carte.sortie { opacity: 0.45; }
.lot-vignette { width: 62px; height: 62px; min-width: 62px; border-radius: 9px; overflow: hidden; background: var(--carte2); flex-shrink: 0; }
.lot-vignette img { width: 62px; height: 62px; object-fit: cover; display: block; }
.lot-vignette-vide { width: 62px; height: 62px; display: flex; align-items: center; justify-content: center; color: var(--texte-tres-doux); }
.lot-corps { flex: 1; min-width: 0; }
.lot-titre { font-size: 0.9rem; font-weight: 600; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; line-height: 1.3; }
.lot-sous { display: flex; align-items: center; gap: 3px; margin-top: 3px; flex-wrap: wrap; font-size: 0.72rem; color: var(--texte-doux); line-height: 1.4; }
.etat-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.lot-sous-plat { color: var(--texte-tres-doux); }
.lot-sous-plat.en-ligne { color: var(--vert); }
.lot-sous-age { color: var(--texte-tres-doux); }
.sep-median { color: var(--texte-tres-doux); flex-shrink: 0; }
.lot-prix-col { flex-shrink: 0; text-align: right; padding-left: 8px; }
.lot-prix-tabular { font-size: 0.88rem; font-weight: 600; color: var(--texte-doux); font-family: ui-monospace, 'Courier New', monospace; font-variant-numeric: tabular-nums; white-space: nowrap; }
.lot-prix-vide { font-size: 0.88rem; color: var(--texte-tres-doux); }
/* Kept for reference in fiche, validation cards */
.etiquette { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 999px; font-size: 0.7rem; font-weight: 700; }
.etiquette-vendre { background: #1e3a1a; color: var(--vert); }
.etiquette-donner { background: #1a2e3a; color: var(--bleu); }
.etiquette-jeter { background: #3a1a1a; color: var(--rouge); }
.etiquette-garder { background: #2e2a1a; color: var(--or); }
.lot-vendu-badge { font-size: 0.65rem; padding: 1px 6px; border-radius: 3px; background: #1a3a1a; color: var(--vert); font-weight: 700; }

/* ── Actions de carte : le bouton « Publier » de la section « prêts » ──
   v28 avait masqué cette classe en croyant y trouver les deux boutons carrés
   des lignes de liste. Elle ne porte que « Publier », et le masquer avait
   supprimé le seul raccourci pour publier un objet depuis l'accueil. ── */
.lot-carte-actions { display: flex; justify-content: flex-end; padding: 0 12px 10px; }

/* ── Fenêtre saisonnière (fiche), ticket rang 20, chantier regles-finales-2026-09-26 ──
   Encart en liseré, le motif deja employe pour l'arbitrage et la suggestion de
   remise : fond teinte, liseré --or a gauche. `a_confirmer` prend le meme or que
   .suggestion-remise, ce n'est pas une alerte mais une relecture a faire. */
.zone-saison { font-size: 0.78rem; color: var(--or-pale); background: #1e1a0e;
  border-left: 3px solid var(--or); border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0;
  padding: 8px 12px; margin: 0 16px 14px; }
.zone-saison-fenetre { font-weight: 600; }
.zone-saison-provenance { color: var(--texte-tres-doux); font-size: 0.72rem; margin-top: 2px; }
.zone-saison-confirmer { display: inline-block; margin-top: 4px; color: var(--or); font-weight: 700; }

/* ── Zone détail prix vendu (fiche) ── */
.zone-vendu-detail { display: none; flex-direction: column; gap: 2px; padding: 0 16px 12px; font-size: 0.82rem; }
.zone-vendu-detail .prix-realise-val { color: var(--vert); font-weight: 700; }
.zone-vendu-detail .commission-val { color: var(--texte-tres-doux); }

/* ── Commission dans compteur accueil ── */
.cpt-commission { font-size: 0.62rem; color: var(--texte-tres-doux); margin-top: 2px; line-height: 1.3; }

/* ── Spinner ── */
.spinner { display: inline-block; width: 18px; height: 18px; border: 2px solid var(--bord); border-top-color: var(--or); border-radius: 50%; animation: spin 0.7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ── Boutons ── */
.btn { display: block; width: 100%; padding: 15px; border-radius: var(--rayon); font-size: 0.95rem; font-weight: 700; text-align: center; transition: opacity 0.15s; }
.btn:active { opacity: 0.8; }
.btn-or { background: var(--or); color: #12100e; }
.btn-secondaire { background: var(--carte2); border: 1px solid var(--bord); color: var(--texte); }
.btn-danger { background: var(--rouge); color: white; }
.btn-vert { background: var(--vert); color: white; }
.btn-sm { padding: 10px 16px; font-size: 0.85rem; border-radius: var(--rayon-sm); width: auto; display: inline-flex; align-items: center; gap: 6px; }
.padding-16 { padding: 16px; }

/* ── Session analyse en cours ── */
.session-analyse { background: var(--carte); border-radius: var(--rayon); border: 1px solid var(--bord); padding: 16px; margin: 0 16px 8px; display: flex; align-items: center; gap: 12px; }
.session-analyse-info { flex: 1; }
.session-analyse-titre { font-size: 0.9rem; font-weight: 600; }
.session-analyse-sous { font-size: 0.75rem; color: var(--texte-doux); margin-top: 2px; }

/* ── Page Capture — plein écran caméra ── */
#p-capture.active {
  position: fixed; inset: 0;
  min-height: unset; padding: 0;
  background: #000; overflow: hidden;
  display: flex; flex-direction: column;
  z-index: 50;
}

#camera-video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; z-index: 0;
}

#camera-ui {
  position: relative; z-index: 10;
  display: flex; flex-direction: column;
  height: 100%; min-height: 100%;
}

#camera-top {
  background: linear-gradient(rgba(0,0,0,0.65) 0%, transparent 100%);
  padding: 16px 16px 32px;
  display: flex; align-items: center; gap: 12px;
  flex-shrink: 0;
}

.camera-btn-retour {
  background: rgba(0,0,0,0.4); border: 1px solid rgba(255,255,255,0.2);
  border-radius: 50%; width: 40px; height: 40px;
  display: flex; align-items: center; justify-content: center;
  color: white; font-size: 1.2rem; flex-shrink: 0;
}

#camera-titre { flex: 1; color: white; font-size: 1rem; font-weight: 700; }
#camera-compteur { color: rgba(255,255,255,0.7); font-size: 0.8rem; flex-shrink: 0; }

/* Retour d'Axelle (27/09/2026) : la phrase qui dit que plusieurs objets sur
   une même photo sont acceptés. Visible tant qu'aucune photo n'est prise
   (public/app.js, majVignettes), sur le même fond dégradé que #camera-top
   pour rester lisible sur n'importe quel arrière-plan de caméra. */
#camera-astuce {
  margin: -20px 16px 0; padding: 0 0 16px;
  background: linear-gradient(rgba(0,0,0,0.5) 0%, transparent 100%);
  color: rgba(255,255,255,0.85); font-size: 0.8rem; line-height: 1.3;
}

#camera-mid { flex: 1; }

#camera-vignettes {
  display: flex; gap: 8px;
  padding: 16px 16px 8px;
  overflow-x: auto; scrollbar-width: none;
  flex-shrink: 0;
}
#camera-vignettes::-webkit-scrollbar { display: none; }

.cam-vignette {
  position: relative; flex-shrink: 0;
  width: 64px; height: 64px;
  border-radius: 8px; overflow: hidden;
  border: 2px solid rgba(255,255,255,0.3);
  background: #222;
}
.cam-vignette img { width: 100%; height: 100%; object-fit: cover; }
/* LA CIBLE FAIT 40 px, LA PASTILLE EN GARDE 20 (ticket rang 36).
   Ce bouton est le seul geste qui retire une photo ratee avant l'analyse, et il
   se touche d'une main pendant que l'autre tient l'objet : a 20 x 20 px, la
   moitie du minimum de DESIGN.md, le rater touche la vignette d'a cote, ou rien.
   Ce qui grossit est ce que le doigt atteint, pas ce que l'oeil voit — le bouton
   couvre le quart haut-droit de la vignette de 64 px, sans fond ni bordure, et
   le dessin reste a sa place d'avant grace au rond qu'il contient, 20 px a 2 px
   du coin. La vignette elle-meme ne porte aucun clic (public/app.js,
   majVignettes) : ce bouton transparent ne vole donc rien a personne. */
.cam-vignette-suppr {
  position: absolute; top: 0; right: 0;
  background: none; border: none; padding: 0;
  width: 40px; height: 40px;
  display: flex; align-items: flex-start; justify-content: flex-end;
}
.cam-vignette-suppr-rond {
  width: 20px; height: 20px; margin: 2px 2px 0 0;
  background: rgba(0,0,0,0.75); border-radius: 50%;
  color: white; font-size: 11px;
  display: flex; align-items: center; justify-content: center;
}

#camera-bottom {
  background: linear-gradient(transparent 0%, rgba(0,0,0,0.75) 100%);
  padding: 16px 24px calc(16px + env(safe-area-inset-bottom));
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-shrink: 0; min-height: 100px;
}

#btn-shutter {
  width: 72px; height: 72px; border-radius: 50%;
  background: rgba(255,255,255,0.9);
  border: 4px solid rgba(255,255,255,0.4);
  box-shadow: 0 0 0 2px rgba(255,255,255,0.6);
  flex-shrink: 0; transition: transform 0.1s, background 0.1s;
}
#btn-shutter:active { transform: scale(0.88); background: white; }
#btn-shutter:disabled { opacity: 0.4; }

#btn-analyser-cam {
  background: var(--or); color: #12100e;
  border: none; border-radius: var(--rayon-sm);
  padding: 12px 16px; font-weight: 700; font-size: 0.85rem;
  white-space: nowrap; flex-shrink: 0;
}
#btn-analyser-cam:disabled { opacity: 0.5; }

#camera-fallback {
  flex: 1; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 16px; padding: 32px; text-align: center;
}
#camera-fallback p { color: rgba(255,255,255,0.7); font-size: 0.9rem; line-height: 1.5; }
.btn-fallback {
  background: var(--carte2); border: 1px solid var(--bord);
  border-radius: var(--rayon); padding: 16px 24px;
  font-size: 0.95rem; font-weight: 700; color: var(--texte);
  width: 100%; max-width: 320px; text-align: center;
}

/* ── Fiche lot ── */
.fiche-photos { display: flex; gap: 8px; overflow-x: auto; padding: 16px; scrollbar-width: none; }
.fiche-photos::-webkit-scrollbar { display: none; }

/* ── Photos de la fiche : ce qui deborde se voit ───────────────────────────
   Ticket rang 36. La rangee defile en largeur depuis toujours, et rien ne le
   disait : sur la capture du Run du 26/09/2026 a 23h15 (390 x 844, cinq
   photos), la troisieme colonne etait coupee net au bord droit — ses boutons se
   lisaient « Ecarter cet… » et « Mettre en co… » — et les deux dernieres
   entierement hors champ. Meme remede que la rangee d'onglets (ticket rang 34),
   meme decision mesuree, et pour la meme raison : un bord franc se lit comme
   une fin de rangee.
   `right: 0` et non `16px` comme pour les onglets : la gouttiere de 16 px est
   ici le `padding` du conteneur qui defile, et une photo la traverse en
   defilant. Le bord franc est donc au bord de l'ecran, pas a 16 px de la.
   `pointer-events: none` : le degrade recouvre a moitie une photo et son bouton
   « Ecarter », et il n'est pas une commande — on ne l'appuie pas, on fait
   glisser la rangee.
   Ni `display` ni `visibility` ici : ces deux blocs se montrent et se cachent
   par l'attribut `hidden`, dont la regle du navigateur (`display: none`) ne
   tiendrait pas face a un `display` ecrit ici. */
.photos-rangee-wrapper { position: relative; }
.photos-deborde {
  position: absolute; top: 0; bottom: 0; width: 28px;
  pointer-events: none; z-index: 2;
}
.photos-deborde--droite { right: 0; background: linear-gradient(to right, rgba(18,16,14,0), var(--fond)); }
.photos-deborde--gauche { left: 0; background: linear-gradient(to left, rgba(18,16,14,0), var(--fond)); }
.fiche-photo { flex-shrink: 0; width: 140px; height: 140px; border-radius: var(--rayon-sm); overflow: hidden; background: var(--carte2); cursor: zoom-in; }
.fiche-photo:active { opacity: 0.8; }
.fiche-photo img { width: 100%; height: 100%; object-fit: cover; }
/* Ticket 40 : une photo redressee le DIT, sous elle, et se defait. La mention
   est discrete (texte tertiaire, 0.7rem) parce qu'elle n'est pas une alerte ;
   le bouton, lui, garde les 40 px de toute cible tactile — on l'atteint d'une
   main, l'autre tenant l'objet. */
.fiche-photo-bloc { flex-shrink: 0; width: 140px; }
.photo-redressee { display: flex; align-items: center; justify-content: space-between; gap: 4px; margin-top: 4px; font-size: 0.7rem; color: var(--texte-tres-doux); line-height: 1.3; }
.btn-annuler-rotation { flex-shrink: 0; min-height: 40px; padding: 0 12px; border-radius: var(--rayon-sm); background: var(--carte2); border: 1px solid var(--bord); color: var(--texte-doux); font-size: 0.7rem; font-weight: 600; }
.btn-annuler-rotation:active { opacity: 0.8; }
/* Retour de Lucile, 9 sept. : ecarter une photo ratee avant publication. Le
   bouton fait toute la largeur du bloc photo (140 px) et 40 px de haut, comme
   toute cible tactile — on s'en sert une main tenant l'objet. */
.btn-ecarter-photo { display: block; width: 100%; min-height: 40px; margin-top: 4px; padding: 0 8px; border-radius: var(--rayon-sm); background: var(--carte2); border: 1px solid var(--bord); color: var(--texte-doux); font-size: 0.7rem; font-weight: 600; }
.btn-ecarter-photo:active { opacity: 0.8; }
/* La photo de couverture : celle qui part en premier, donc la vignette de la
   liste de resultats sur les trois plateformes. En or, la couleur d'accent :
   ce n'est ni une erreur ni un succes, c'est l'element actif du groupe. Le
   liseré est sur la vignette elle-meme parce que la question posee est
   « laquelle », et qu'un badge sans ancrage oblige a compter les photos. */
.fiche-photo-bloc.est-couverture .fiche-photo { outline: 2px solid var(--or); outline-offset: -2px; }
.photo-couverture-badge { margin-top: 4px; padding: 4px 8px; border-radius: var(--rayon-sm); background: var(--or); color: var(--fond); font-size: 0.7rem; font-weight: 700; line-height: 1.3; text-align: center; }
/* Meme gabarit que « Ecarter cette photo » : 140 px de large, 40 px de haut,
   atteignable d'une main. Les deux boutons se suivent sous la meme vignette. */
.btn-couverture { display: block; width: 100%; min-height: 40px; margin-top: 4px; padding: 0 8px; border-radius: var(--rayon-sm); background: var(--carte2); border: 1px solid var(--bord); color: var(--texte-doux); font-size: 0.7rem; font-weight: 600; }
.btn-couverture:active { opacity: 0.8; }
/* La photo ecartee ici que l'annonce publiee montre encore. Le motif de
   l'encart en lisere, en or : ce n'est pas une panne de la machine — rien n'a
   echoue — c'est un geste qui reste a faire chez la plateforme, et il ne doit
   pas se chercher. Rien ne s'y clique : le lien de l'annonce est juste
   au-dessous, dans les liens de plateformes. */
.fiche-photo-en-ligne { margin: 0 16px 16px; padding: 12px; border-left: 3px solid var(--or); border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0; background: #1e1a0e; color: var(--texte); font-size: 0.8rem; line-height: 1.4; }
.fiche-photo-en-ligne-ligne { font-weight: 600; }
.fiche-photo-en-ligne-suite { margin-top: 4px; color: var(--texte-doux); }
/* Ticket 149 : les liens de plateformes, sortis de la liste. Un par plateforme
   reellement en ligne. 40 px de haut, comme toute cible tactile. */
.fiche-liens-plateformes { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 16px 16px; }
.fiche-lien-plateforme { display: inline-flex; align-items: center; min-height: 40px; padding: 8px 16px; border-radius: var(--rayon-sm); background: var(--carte2); border: 1px solid var(--bord); color: var(--vert); font-size: 0.8rem; font-weight: 600; text-decoration: none; }
.fiche-lien-plateforme:active { opacity: 0.8; }
/* OÙ EN EST CET OBJET, une ligne par plateforme. Le motif de l'encart en
   liseré : attirer l'œil sans crier, la couleur portant l'état. Ce n'est pas
   une cible tactile — rien ne s'y clique, le lien de l'annonce est juste
   au-dessus — mais la ligne garde 40 px de haut : elle se lit à bout de bras,
   une main tenant l'objet. Le gris est l'état par défaut, et c'est voulu :
   « pas encore en ligne » n'est ni un succès ni une panne à ses yeux. */
.fiche-etats-plateformes { display: flex; flex-direction: column; gap: 4px; padding: 0 16px 16px; }
.fiche-etats-titre { font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--texte-doux); margin-bottom: 4px; }
.fiche-etat-plateforme { display: flex; align-items: center; min-height: 40px; padding: 8px 12px; background: var(--carte); border: 1px solid var(--bord); border-left: 3px solid var(--texte-tres-doux); border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0; font-size: 0.8rem; color: var(--texte); }
.fiche-etat-plateforme--en_ligne { border-left-color: var(--vert); }
/* « déposée » se peint comme « en ligne », en vert : le dépôt est un fait
   atteint, et le ranger avec les annonces arrêtées serait une seconde erreur.
   C'est le mot qui change, pas le jugement (docs/etat-de-diffusion.md), et la
   même règle tient déjà pour le badge de la liste (.lot-sous-plat.en-ligne). */
.fiche-etat-plateforme--deposee { border-left-color: var(--vert); }
/* Arrêtées : ni vert ni rouge. Une pause n'est pas une panne, c'est un geste
   voulu ; le gris clair les distingue de ce qui n'est jamais parti, qui garde
   le --texte-tres-doux par défaut. Même couleur que .lot-sous-plat.arretee. */
.fiche-etat-plateforme--en_pause { border-left-color: var(--texte-doux); }
.fiche-etat-plateforme--retiree { border-left-color: var(--texte-doux); }
.fiche-etat-plateforme--en_cours { border-left-color: var(--or); }
.fiche-etat-plateforme--bloque { border-left-color: var(--rouge); }
.decision-segment { display: grid; grid-template-columns: repeat(5, 1fr); gap: 4px; padding: 0 16px 16px; }
.seg-btn { padding: 10px 4px; border-radius: var(--rayon-sm); font-size: 0.75rem; font-weight: 700; text-align: center; transition: all 0.15s; border: 2px solid transparent; color: var(--texte-doux); background: var(--carte2); }
.seg-btn.active-vendre { border-color: var(--vert); color: var(--vert); background: #162016; }
.seg-btn.active-donner { border-color: var(--bleu); color: var(--bleu); background: #0f1e2e; }
.seg-btn.active-jeter { border-color: var(--rouge); color: var(--rouge); background: #2e100e; }
.seg-btn.active-garder { border-color: var(--or); color: var(--or); background: #1e1a0a; }
.champ-fiche { padding: 0 16px 14px; }
.champ-fiche label { display: block; font-size: 0.75rem; color: var(--texte-doux); margin-bottom: 5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; }
.rangee-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; padding: 0 16px 14px; }
.rangee-2 .champ-fiche { padding: 0; }
.rendement-affiche { background: var(--carte2); border-radius: var(--rayon-sm); padding: 10px 12px; margin: 0 16px 14px; font-size: 0.85rem; color: var(--texte-doux); }
.rendement-affiche strong { color: var(--texte); }
.info-arbitrage { background: #2e1a0a; border-left: 3px solid var(--or); border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0; padding: 10px 12px; margin: 0 16px 14px; font-size: 0.8rem; color: var(--or-pale); }

/* ── Ticket 113 : ce que le modele a ecarte du commentaire vocal ──
   « rendre a Cesar » : un feedback pris en compte en silence, c'est bien ;
   un feedback ECARTE en silence fait croire a la personne qu'elle a ete
   entendue alors que non. Meme famille visuelle que .info-arbitrage — un
   avertissement qui explique, pas une erreur. */
.avertissement-ignore { background: #2e1a0a; border-left: 3px solid var(--or); border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0; padding: 8px 12px; margin-top: 8px; font-size: 0.8rem; color: var(--or-pale); }

/* ── Conseil arbitrage (consultatif) ── */
.zone-conseil { background: var(--carte2); border: 1px solid var(--bord); border-radius: var(--rayon-sm); padding: 10px 12px; margin: 0 16px 14px; }
.conseil-texte { font-size: 0.8rem; color: var(--texte-doux); }
.btn-basculer-don { margin-top: 8px; padding: 7px 14px; background: #0f1e2e; border: 1px solid var(--bleu); color: var(--bleu); border-radius: var(--rayon-sm); font-size: 0.8rem; font-weight: 600; }

/* ── Ticket 141 : la décision qui interdit la publication ──
   Fond « garder-or » et liseré or : c'est une décision tenue, pas une erreur,
   donc ni le rouge de l'échec ni le vert de la vente. Le bouton, lui, porte le
   vert de « vendre » : c'est là qu'il mène. 44 px comme « C'est donné ». */
.zone-decision-tenue { background: #1e1a0a; border-left: 3px solid var(--or); border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0; padding: 12px; }
.decision-tenue-texte { font-size: 0.85rem; color: var(--texte-doux); margin-bottom: 12px; }
.btn-vendre-finalement { background: #162016; border: 2px solid var(--vert); color: var(--vert); border-radius: var(--rayon-sm); padding: 12px 16px; min-height: 44px; font-size: 0.9rem; font-weight: 700; cursor: pointer; width: 100%; }

/* ── Statut LBC ── */
.zone-lbc-status { background: #141e14; border-left: 3px solid var(--vert); border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0; padding: 10px 12px; margin: 0 16px 10px; }
.lbc-status-header { font-size: 0.8rem; font-weight: 700; color: var(--vert); margin-bottom: 3px; }
.lbc-status-nom { font-size: 0.78rem; color: var(--texte-doux); font-family: monospace; }
.lbc-status-date { font-size: 0.72rem; color: var(--texte-tres-doux); margin-top: 2px; }

/* ── Plateformes chips ── */
.plateformes-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
.plat-chip { padding: 7px 14px; border-radius: 999px; font-size: 0.8rem; font-weight: 600; border: 2px solid var(--bord); color: var(--texte-doux); background: var(--carte2); transition: all 0.15s; }
.plat-chip.actif { border-color: var(--or); color: var(--or); background: #1e1a0a; }

.qcm-section { padding: 0 16px 16px; }
.qcm-titre { font-size: 0.8rem; font-weight: 700; color: var(--texte-doux); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px; }
.qcm-question { margin-bottom: 14px; }
.qcm-q { font-size: 0.9rem; margin-bottom: 8px; }
.qcm-options { display: flex; flex-direction: column; gap: 6px; }
.qcm-opt { background: var(--carte2); border: 2px solid var(--bord); border-radius: var(--rayon-sm); padding: 10px 14px; font-size: 0.85rem; text-align: left; color: var(--texte); transition: all 0.15s; }
.qcm-opt.selected { border-color: var(--or); color: var(--or); background: #1e1a0a; }
/* Le champ qu'ouvre « Autre » (ticket rang 1, 28/09/2026). Il reprend .q-champ,
   le champ de reponse des questions du deposant, pour que la meme chose se
   ressemble d'un ecran a l'autre ; seule la phrase qui va dessous est a lui. */
.qcm-libre-aide { font-size: 0.75rem; color: var(--texte-tres-doux); margin-top: 4px; }

/* ── Questions bloquantes (ticket du 9 septembre 2026) ───────────────────────
   Le parcours qui remplace le bouton « Publier » tant qu'une question attend.
   Une question par écran, un bouton par réponse : 56 px de haut, bien au-dessus
   des 40 px du minimum, parce qu'on y répond d'une main en tenant l'objet. Les
   vignettes sont dans les boutons — c'est l'humain qui désigne la photo, on ne
   la devine pas depuis un motif. Aucune couleur hors palette. */
.q-progres { font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--texte-doux); font-family: ui-monospace, 'Courier New', monospace; font-variant-numeric: tabular-nums; }
.q-texte { font-size: 1.1rem; font-weight: 600; line-height: 1.4; margin: 8px 0 4px; }
.q-aide { font-size: 0.8rem; color: var(--texte-doux); font-style: italic; margin-bottom: 4px; }
.q-choix { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; }
.q-opt { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 56px; background: var(--carte2); border: 1px solid var(--bord); border-radius: var(--rayon); padding: 12px 14px; font-size: 0.95rem; font-weight: 700; color: var(--texte); text-align: left; }
.q-opt:active { background: var(--carte); border-color: var(--or); }
.q-opt-vignette { width: 56px; height: 56px; min-width: 56px; border-radius: var(--rayon-sm); object-fit: cover; background: var(--carte); }
.q-opt-sous { display: block; font-size: 0.75rem; font-weight: 400; color: var(--texte-doux); margin-top: 2px; }
/* ── Ticket 20 : la question montre ses photos ───────────────────────────────
   Le titre de l'objet au-dessus des vignettes (on arbitre entre un titre et
   des photos : il faut voir les deux), le rang de la photo sur la vignette, et
   la case a cocher. Le rang est en chiffres tabulaires comme tout nombre
   comparable (DESIGN.md, « rang de photo ») : c'est le meme comptage que le
   motif du controle photo, a partir de zero. */
.q-objet-titre { padding: 16px 16px 0; font-size: 0.9rem; font-weight: 700; color: var(--texte); }
.q-photo { position: relative; }
.q-photo-num {
  position: absolute; left: 4px; bottom: 4px;
  padding: 2px 6px; border-radius: var(--rayon-sm);
  background: rgba(0,0,0,0.65); color: var(--texte);
  font-size: 0.7rem; font-weight: 700;
  font-family: ui-monospace, 'Courier New', monospace; font-variant-numeric: tabular-nums;
}
.q-photo-motif { margin-top: 4px; font-size: 0.7rem; color: var(--texte-tres-doux); line-height: 1.3; }

/* Mettre en avant la vignette signalée par le contrôle photo : liseré rouge discret. */
.q-photo-fautive .q-photo { outline: 2px solid var(--rouge); outline-offset: -2px; }

/* La bande de vignettes vide dit pourquoi elle l'est : texte tertiaire, comme
   tout état vide, et non une alerte — ce n'est pas une panne, c'est qu'il n'y a
   rien à revoir. Elle occupe la largeur de la bande (`.fiche-photos` est une
   ligne en flex) au lieu de se tasser à gauche. */
.q-photos-vide { flex: 1; font-size: 0.8rem; color: var(--texte-tres-doux); line-height: 1.4; }

/* La case fait partie de la cible tactile du bouton entier (56 px de haut) :
   on coche une photo d'une main, l'autre tenant l'objet. */
.q-case {
  flex-shrink: 0; width: 24px; height: 24px; border-radius: 6px;
  border: 2px solid var(--bord); background: var(--carte);
  display: flex; align-items: center; justify-content: center;
  font-size: 0.8rem; font-weight: 700; color: var(--fond);
}
.q-opt-coche--oui { border-color: var(--or); background: #1e1a0a; }
.q-opt-coche--oui .q-case { background: var(--or); border-color: var(--or); }
/* « Coche au moins une photo » : le bouton existe, il dit ce qui manque. Le
   griser sans le dire ferait chercher. */
.q-valider { margin-top: 16px; }
.q-valider:disabled { opacity: 0.55; }
/* Deja dans la gouttiere de 16 px de la page : le padding de
   .fiche-liens-plateformes ferait un decalage de 32 px. */
.q-liens { padding: 0; margin-top: 12px; }
.q-libre { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; }
.q-fin { display: flex; flex-direction: column; gap: 12px; }
.q-fin-titre { font-size: 1.1rem; font-weight: 600; }
.q-fin-sous { font-size: 0.8rem; color: var(--texte-doux); }
/* Le bouton qui remplace « Publier » sur la fiche. Il n'est ni grisé ni caché
   ailleurs : il est REMPLACÉ, pour que la marche à suivre soit évidente. Fond
   de carte et liseré or — c'est un chemin, pas une erreur, et pas encore
   l'action finale, qui garde l'aplat or. */
.btn-questions-fiche { background: #1e1a0a; border: 1px solid var(--or); color: var(--or); border-radius: var(--rayon); padding: 15px; font-size: 0.95rem; font-weight: 700; width: 100%; min-height: 40px; }
.btn-questions-fiche:active { background: var(--carte2); }
/* ── UNE MODALE QUI DEMANDE QUOI FAIRE D'UN OBJET ────────────────────────────
   Cette peinture etait celle de l'ecran « Terminer un objet » (ticket 129), et
   elle portait son nom : `.terminer-intro`, `.terminer-choix`, `.terminer-btn`.
   Cet ecran a ete retire le 27 septembre 2026 ; les classes restent parce que la
   modale « Enlever » (ticket 134) les partageait deja, et elles portent
   desormais le nom de ce qu'elles sont, `.modale-*`. Cibles a 48 px : on decide
   du sort d'un objet d'une main, l'autre tenant l'objet.
   `.terminer-btn` est parti avec son ecran ; `.enlever-btn` gardait un nom a
   part pour que `querySelectorAll` ne decoche pas deux modales a la fois, et le
   garde : c'est maintenant le seul nom de cette famille. */
.zone-sortie-bloc { padding: 0 16px; margin-bottom: 16px; }
.modale-intro { font-size: 0.85rem; color: var(--texte-doux); margin-bottom: 12px; }
.modale-choix { display: grid; gap: 8px; }
.enlever-btn { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%; min-height: 48px; padding: 12px; text-align: left; background: var(--carte2); border: 2px solid var(--bord); border-radius: var(--rayon-sm); color: var(--texte); font-size: 0.9rem; font-weight: 700; }
.enlever-btn span { font-size: 0.75rem; font-weight: 400; color: var(--texte-tres-doux); }
.enlever-btn.selected { border-color: var(--or); color: var(--or); background: #1e1a0a; }
.modale-note { font-size: 0.75rem; color: var(--texte-tres-doux); margin-top: 6px; }
/* L'encart en lisere : attirer l'oeil sans crier. Les annonces encore en ligne
   sont le seul point de cette modale qui puisse couter de l'argent, elles ne
   peuvent pas etre en gris discret. */
.modale-avert { font-size: 0.85rem; color: var(--or-pale); background: #1e1a0e; border-left: 3px solid var(--or); border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0; padding: 10px 12px; }
/* La sortie deja posee, seule chose qui reste dans cette zone : ce qu'il est
   advenu de l'objet, et la porte de retour si on s'est trompe. En gris doux,
   pas en alerte — un objet donne n'est pas un incident. */
.sortie-faite { display: flex; flex-direction: column; gap: 8px; }
.sortie-faite-texte { font-size: 0.8rem; color: var(--texte-doux); }
.issue-badge { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 999px; font-size: 0.75rem; font-weight: 700; margin: 0 16px 14px; }
.issue-vendu { background: #1a3a1a; color: var(--vert); }
.issue-donne { background: #0f1e2e; color: var(--bleu); }
.issue-jete { background: #3a1a1a; color: var(--rouge); }
/* `.issue-retire` manquait depuis le ticket 129 : majBadgeIssue posait la
   classe, la feuille ne la connaissait pas, et « Retiré » sortait sans fond,
   seule pastille des quatre a ne pas se lire comme une pastille. Fond garder-or
   du DESIGN.md. */
.issue-retire { background: #1e1a0a; color: var(--or); }
.divider { border: none; border-top: 1px solid var(--bord); margin: 8px 0; }
.fusionner-bar { position: fixed; bottom: 72px; left: 16px; right: 16px; background: var(--or); color: #12100e; border-radius: var(--rayon); padding: 14px 16px; display: flex; align-items: center; justify-content: space-between; font-weight: 700; z-index: 50; box-shadow: 0 -4px 20px rgba(0,0,0,0.5); }
.fusionner-bar button { background: #12100e; color: var(--or); border: none; border-radius: var(--rayon-sm); padding: 8px 16px; font-weight: 700; font-size: 0.85rem; }
.vide-etat { padding: 40px 16px; text-align: center; color: var(--texte-tres-doux); font-size: 0.9rem; }

/* ── v4 : lotir ── */
.etiquette-lotir { background: #2a1a3a; color: #b87fe8; }
.seg-btn.active-lotir { border-color: #b87fe8; color: #b87fe8; background: #1a0e2e; }

/* ── LE BANDEAU D'ANALYSE ────────────────────────────────────────────────────
   Il vit dans #zone-annonces avec les autres annonces (voir plus haut). Sa
   fenetre de vie est decidee par etatBandeauAnalyses (public/affichage.js). */
#bandeau-analyses {
  background: rgba(18,16,14,0.97);
  border: 1px solid var(--bord);
  padding: 8px 14px;
  display: none; align-items: center; gap: 10px;
}
.bandeau-analyses-vign { width: 32px; height: 32px; border-radius: 5px; object-fit: cover; flex-shrink: 0; }
.bandeau-analyses-txt { flex: 1; font-size: 0.78rem; color: var(--texte-doux); }

/* ── v4 : À valider ── */
.aval-carte { background: var(--carte); border-radius: var(--rayon); border: 1px solid var(--or); padding: 14px 16px; display: flex; align-items: center; gap: 12px; cursor: pointer; margin-bottom: 0; }
.aval-nb { font-size: 1.2rem; font-weight: 700; color: var(--or); flex-shrink: 0; }
.aval-info { flex: 1; }
.aval-titre { font-size: 0.9rem; font-weight: 600; }
.aval-sous { font-size: 0.75rem; color: var(--texte-doux); margin-top: 2px; }

/* ── v4 : pistes ── */
.piste-carte { background: var(--carte); border-radius: var(--rayon); border: 1px solid var(--bord); padding: 12px; border-left: 3px solid var(--bord); }
.piste-carte.interet-fort { border-left-color: var(--or); }
.piste-carte.interet-moyen { border-left-color: var(--bleu); }
.piste-carte.interet-faible { border-left-color: var(--texte-tres-doux); }
.piste-libelle { font-size: 0.9rem; font-weight: 600; margin-bottom: 4px; }
.piste-justif { font-size: 0.78rem; color: var(--texte-doux); margin-bottom: 8px; }
.piste-actions { display: flex; gap: 8px; align-items: center; }
.btn-piste-photo { background: var(--or); color: #12100e; border: none; border-radius: var(--rayon-sm); padding: 6px 12px; font-size: 0.8rem; font-weight: 700; cursor: pointer; }
.btn-piste-suppr { background: none; border: 1px solid var(--bord); color: var(--texte-tres-doux); border-radius: var(--rayon-sm); padding: 6px 10px; font-size: 0.75rem; cursor: pointer; }

/* ── v4 : réserve (lotir) ── */
.reserve-carte { background: #1a0e2e; border: 1px solid #3a2a5a; border-radius: var(--rayon); padding: 14px 16px; }
.reserve-famille { font-size: 0.9rem; font-weight: 700; color: #b87fe8; margin-bottom: 4px; }
.reserve-nb { font-size: 0.78rem; color: var(--texte-doux); }
.btn-constituer-lot { background: #b87fe8; color: #12100e; border: none; border-radius: var(--rayon-sm); padding: 8px 14px; font-size: 0.8rem; font-weight: 700; margin-top: 10px; cursor: pointer; width: 100%; }

/* ── v4 : plateformes suggestion ── */
.plat-suggestion-msg { font-size: 0.72rem; color: var(--texte-tres-doux); font-style: italic; margin-top: 4px; }

/* ── Ticket 126 : pourquoi cet objet n'est pas sur les trois plateformes ──
   Encart en lisere, le motif deja employe pour l'arbitrage et le statut LBC.
   Gris pour une exclusion motivee (c'est un fait range), or pour une absence
   sans raison ecrite (c'est une anomalie, elle doit accrocher l'oeil). */
.exclusion-ligne { font-size: 0.75rem; color: var(--texte-doux); background: var(--carte2);
  border-left: 3px solid var(--bord); border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0;
  padding: 8px 12px; margin-top: 8px; }
.exclusion-par { color: var(--texte-tres-doux); font-style: italic; }
.exclusion-manque { font-size: 0.75rem; color: var(--or-pale); background: #1e1a0e;
  border-left: 3px solid var(--or); border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0;
  padding: 8px 12px; margin-top: 8px; }

/* ── Ticket 144 : le label « main propre uniquement » ──
   Une case a cocher pleine largeur, pas une case de formulaire : la fiche
   s'utilise au telephone, une main tenant l'objet, et 44 px de hauteur utile
   sont le minimum pour ne pas la rater. Inactive elle est neutre (--carte2),
   active elle prend l'or, comme toute selection de ce produit. */
.label-remise { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 44px;
  text-align: left; background: var(--carte2); border: 1px solid var(--bord);
  border-radius: var(--rayon-sm); padding: 12px; color: var(--texte); cursor: pointer; }
.label-remise:active { opacity: 0.8; }
.label-remise.actif { border-color: var(--or); background: #1e1a0a; }
.label-remise-case { font-size: 1.1rem; line-height: 1; color: var(--texte-tres-doux); }
.label-remise.actif .label-remise-case { color: var(--or); }
.label-remise-texte { display: block; }
.label-remise-titre { display: block; font-size: 0.85rem; font-weight: 600; }
.label-remise.actif .label-remise-titre { color: var(--or-pale); }
.label-remise-sous { display: block; font-size: 0.75rem; color: var(--texte-tres-doux); margin-top: 2px; }
/* La proposition, ticket 144 : elle PROPOSE, elle ne coche rien. Encart en
   lisere or, le motif deja employe pour l'arbitrage. */
.suggestion-remise { font-size: 0.75rem; color: var(--or-pale); background: #1e1a0e;
  border-left: 3px solid var(--or); border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0;
  padding: 8px 12px; margin-top: 8px; }
.suggestion-remise .btn-suggestion-remise { display: inline-flex; align-items: center; min-height: 40px;
  margin-top: 8px; background: var(--carte2); border: 1px solid var(--bord);
  border-radius: var(--rayon-sm); padding: 8px 14px; font-size: 0.8rem; font-weight: 600;
  color: var(--texte); cursor: pointer; }

/* ── v4 : commentaire photo ── */
.btn-reecrire { display: inline-block; margin-top: 6px; background: var(--carte2); border: 1px solid var(--bord); border-radius: var(--rayon-sm); padding: 8px 14px; font-size: 0.8rem; font-weight: 600; color: var(--texte-doux); cursor: pointer; }
.btn-reecrire:disabled { opacity: 0.5; }

/* ── v4 : overlay méthode ── */

/* ── Réglages ── */
.texte-info { font-size: 0.85rem; color: var(--texte-doux); line-height: 1.5; margin-bottom: 20px; }

/* ── Connexion ── */
.connexion-page { min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 32px 24px; }
.connexion-logo { font-size: 3rem; margin-bottom: 8px; }
.connexion-titre { font-size: 1.6rem; font-weight: 700; margin-bottom: 6px; }
.connexion-sous { color: var(--texte-doux); margin-bottom: 32px; font-size: 0.9rem; }
.connexion-form { width: 100%; max-width: 360px; }
.connexion-input { font-size: 1.1rem; text-align: center; letter-spacing: 0.1em; margin-bottom: 16px; }
.erreur-msg { color: var(--rouge); font-size: 0.85rem; text-align: center; margin-top: 12px; min-height: 20px; }

/* ── Toast ── */
.toast { background: var(--carte2); border: 1px solid var(--bord); padding: 12px 20px; font-size: 0.85rem; pointer-events: none; }
.toast.visible { opacity: 1; }

/* ── Modale ── */
.overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.7); z-index: 150; display: flex; align-items: flex-end; justify-content: center; padding: 0; }
.overlay.hidden { display: none; }
.modale { background: var(--carte); border-radius: var(--rayon) var(--rayon) 0 0; padding: 24px; width: 100%; max-width: 480px; }
.modale h2 { margin-bottom: 16px; }
.modale-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 16px; }

/* ── Validation session ── */
.validation-header { padding: 20px 16px 12px; }
.validation-header h2 { font-size: 1.1rem; }
.validation-sous { font-size: 0.8rem; color: var(--texte-doux); margin-top: 2px; }

/* ── v5 : pastilles statut publication ── */
.pastille { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 4px; font-size: 0.65rem; font-weight: 700; text-decoration: none; }
.pastille-grise { background: #2a2825; border: 1px solid var(--bord); color: var(--texte-tres-doux); }
.pastille-orange { background: #2e1e0a; border: 1px solid #8a5a20; color: #e8902a; }
.pastille-verte { background: #1a3a1a; border: 1px solid #3a6a3a; color: var(--vert); }
.pastille-rouge { background: #2e1010; border: 1px solid #6a2020; color: var(--rouge); cursor: help; }

/* ── v5 : section Prêts avec bouton Publier ── */
.section-prets-actions { display: flex; align-items: center; gap: 8px; padding: 0 16px 10px; }
.btn-tout-publier { background: var(--or); color: #12100e; border: none; border-radius: var(--rayon-sm); padding: 8px 16px; font-size: 0.8rem; font-weight: 700; cursor: pointer; }
.btn-publier-lot { background: var(--or); color: #12100e; border: none; border-radius: var(--rayon-sm); padding: 5px 10px; font-size: 0.7rem; font-weight: 700; cursor: pointer; flex-shrink: 0; }
/* .lot-carte-actions masqué v28 — voir règle principale */

/* ── v5 : état file sur accueil ── */
.file-statut { background: var(--carte); border: 1px solid var(--bord); border-radius: var(--rayon-sm); padding: 10px 14px; margin: 0 16px 10px; font-size: 0.78rem; color: var(--texte-doux); display: flex; align-items: center; gap: 8px; }
.file-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--texte-tres-doux); flex-shrink: 0; }
.file-dot.actif { background: var(--orange, #e8902a); animation: pulse 1.5s infinite; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }

/* ── v5 : auto-save indicator ── */
.autosave-ok { position: fixed; bottom: 90px; left: 50%; transform: translateX(-50%); background: var(--vert); color: white; border-radius: 999px; padding: 4px 12px; font-size: 0.75rem; opacity: 0; transition: opacity 0.3s; pointer-events: none; z-index: 180; }
.autosave-ok.visible { opacity: 1; }
.autosave-err { background: var(--carte2); border: 1px solid var(--rouge); border-radius: var(--rayon-sm); padding: 8px 14px; margin: 0 16px 14px; font-size: 0.78rem; color: var(--rouge); display: none; }

/* ── UNE ANNONCE PUBLIEE SE LIT, PUIS S'EDITE (ticket 2752) ──
   Morgane, 24/09/2026 a 22h12 : « J'ai pas de bouton "valider" quand je fais
   une modif ». Le bandeau dit pourquoi les champs sont fermes, la barre du bas
   porte le bouton qui termine. Les deux sont a 44 px au moins : l'application
   s'utilise au telephone, une main tenant l'objet.
   Le bandeau est en haut de la zone de texte (il explique un champ ferme, il
   doit etre a cote de lui) ; le bouton est en bas, comme toutes les actions
   principales. */
.annonce-publiee { display: none; flex-direction: column; gap: 10px; margin: 0 16px 14px; padding: 12px 14px; background: var(--carte2); border: 1px solid var(--bord); border-left: 3px solid var(--or); border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0; }
.annonce-publiee-texte { font-size: 0.8rem; line-height: 1.45; color: var(--texte); }
.annonce-publiee .btn { min-height: 44px; }
/* Un champ ferme se voit ferme : sinon on tape dedans, rien ne s'ecrit, et on
   croit l'application cassee. */
.champ-lecture { background: var(--carte2) !important; color: var(--texte-doux) !important; cursor: default; }
.maj-annonce { display: none; flex-direction: column; gap: 8px; margin: 0 16px 14px; }
.maj-annonce .btn { min-height: 48px; }
.btn-maj-annonce { font-weight: 700; }
/* UN ECHEC DE MISE A JOUR SE VOIT SANS QU'ON LE CHERCHE : deuxieme contrainte
   d'interface du projet. Le rouge n'est pas decoratif, il est la seule chose qui
   distingue « c'est parti » de « ce n'est pas parti ». */
.maj-annonce-suivi { display: none; flex-direction: column; gap: 4px; margin: 0 16px 14px; }
.maj-ligne { min-height: 40px; display: flex; align-items: center; padding: 8px 12px; background: var(--carte); border: 1px solid var(--bord); border-left: 3px solid var(--texte-tres-doux); border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0; font-size: 0.8rem; color: var(--texte); }
.maj-ligne--a_jour { border-left-color: var(--vert); }
.maj-ligne--en_attente { border-left-color: var(--or); }
/* « envoyé, pas encore relu en ligne » : le même or que « en cours », et pas une
   cinquième couleur. Ce n'est pas le vert de « à jour », qui promettrait une page
   que personne n'a regardée, ni le rouge d'un échec : c'est une attente, celle
   d'une relecture. La phrase la distingue de « en cours », pas la teinte.
   Ticket rang 4 du 27/09/2026. */
.maj-ligne--envoye { border-left-color: var(--or); }
.maj-ligne--manuelle { border-left-color: var(--texte-doux); }
.maj-ligne--echec { border-left-color: var(--rouge); color: var(--rouge); }

/* ── LE TUNNEL D'APRES-ANALYSE (ticket 3614, tour 2 sur 3) ───────────────────
   Le fil d'etapes se pose en tete de la fiche, sous le bandeau : il dit le nom
   du temps en cours et son rang, et porte le retour en arriere. Le retour est un
   bouton de 44 px de haut, pas un chevron de texte — c'est une cible de doigt
   sur un telephone tenu d'une main (DESIGN.md, « Zones tactiles »). Le compte
   « n sur N » est ecrit par majFilEtapes() a partir de positionEtape, jamais
   ici : une etiquette de CSS ne saurait pas qu'un objet sans question n'a que
   deux temps. */
.fil-etapes { display: flex; align-items: center; gap: 10px; padding: 8px 16px 12px; }
.fil-etapes-retour { background: var(--carte2); color: var(--texte-doux); border: 1px solid var(--bord); border-radius: var(--rayon-sm); min-height: 44px; padding: 8px 14px; font-size: 0.82rem; font-weight: 600; cursor: pointer; flex-shrink: 0; }
.fil-etapes-retour:active { opacity: 0.8; }
.fil-etapes-nom { flex: 1; font-size: 0.95rem; font-weight: 700; }
.fil-etapes-position { font-size: 0.78rem; color: var(--texte-doux); flex-shrink: 0; }

/* Les actions d'un temps sont en bas de ce que ce temps porte, jamais au milieu
   (DESIGN.md, contrainte 1 : le pouce ne va pas en haut). Meme boite que le bloc
   d'actions de la fiche, dont les boutons de publication viennent. */
.etape-actions { padding: 16px; display: flex; flex-direction: column; gap: 10px; }
/* Meme boite que « Valider et mettre en vente » : c'est le meme geste — avancer
   — a un temps different, et deux hauteurs differentes se rateraient du pouce.
   Sur le fond de la page, parce qu'il n'engage rien : l'or est reserve a la mise
   en vente, et deux boutons dores sur un ecran sont deux portes pour une piece. */
.btn-etape-suivante { background: var(--fond); color: var(--or); border: 1px solid var(--or); border-radius: var(--rayon); padding: 15px; font-size: 0.95rem; font-weight: 700; width: 100%; min-height: 44px; cursor: pointer; }
.btn-etape-suivante:active { opacity: 0.8; }

/* ── v5 : bouton Publier dans la fiche ── */
.btn-publier-fiche { background: var(--or); color: #12100e; border: none; border-radius: var(--rayon); padding: 15px; font-size: 0.95rem; font-weight: 700; width: 100%; cursor: pointer; }

/* « Ne pas mettre en vente finalement » : la même boîte que le bouton doré
   au-dessus — mêmes rayon, padding, graisse et pleine largeur, donc la même
   hauteur sous le pouce — sur le noir du fond plutôt que sur un aplat d'or.
   Le noir demandé est celui de la page (--fond), pas une couleur de plus : la
   bordure est ce qui garde le bouton trouvable une fois la couleur enlevée.
   Il reste à 40 px au moins par son padding de 15, comme tous les boutons
   pleine largeur de cette fiche. */
.btn-ne-pas-vendre { background: var(--fond); color: var(--texte-doux); border: 1px solid var(--bord); border-radius: var(--rayon); padding: 15px; font-size: 0.95rem; font-weight: 700; width: 100%; min-height: 40px; cursor: pointer; }
.btn-ne-pas-vendre:active { opacity: 0.8; }

/* ── v6 : lot non revu — liseré discret ── */
.lot-carte.non-revu { border-left: 3px solid var(--or); }


/* ── v6 : bouton Valider (marquer revu) ── */
.btn-valider-revu { background: var(--carte2); border: 1px solid var(--or); color: var(--or); border-radius: var(--rayon-sm); padding: 8px 16px; font-size: 0.82rem; font-weight: 600; cursor: pointer; width: 100%; }
/* ── ticket 128 : « C'est donné ». Couleurs du don (fond teinté + --bleu),
   44 px de haut : c'est une action principale, faite au téléphone. ── */
.btn-cest-donne { background: #0f1e2e; border: 2px solid var(--bleu); color: var(--bleu); border-radius: var(--rayon-sm); padding: 12px 16px; min-height: 44px; font-size: 0.9rem; font-weight: 700; cursor: pointer; width: 100%; }
/* ── v6 : bouton Tout valider ── */
.btn-tout-valider { background: var(--carte2); border: 1px solid var(--or); color: var(--or); border-radius: 999px; padding: 5px 12px; font-size: 0.75rem; font-weight: 600; cursor: pointer; flex-shrink: 0; }
/* ── v6 : barre annulation tout-valider ── */
.undo-revu-bar { background: var(--carte2); border: 1px solid var(--bord); padding: 8px 16px; font-size: 0.8rem; color: var(--texte-doux); pointer-events: none; }
.undo-revu-bar.visible { opacity: 1; pointer-events: auto; }
.undo-revu-bar a { color: var(--or); cursor: pointer; text-decoration: underline; margin-left: 6px; }

/* ── v6 : pastille a_verifier ── */
.pastille-jaune { background: #2e2000; border: 1px solid #7a5800; color: #d4a000; }

/* ── v8 : liens annonces ── */
.lien-annonce { display: flex; align-items: center; gap: 8px; padding: 10px 14px; background: var(--carte2); border: 1px solid var(--bord); border-radius: var(--rayon-sm); text-decoration: none; color: var(--texte); font-size: 0.85rem; font-weight: 600; }
.lien-annonce:hover { border-color: var(--or); }
.lien-annonce-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--vert); flex-shrink: 0; }
.lien-annonce-nom { flex: 1; }
/* L'etat d'une annonce et l'histoire de ses retraits : du texte tertiaire, au
   meme rang que les prix et les dates (DESIGN.md). Ces lignes existaient sans
   regle et prenaient donc la taille du corps, ce qui les mettait au meme poids
   que les liens qu'elles commentent. La couleur d'un geste en cours ou en
   echec est posee en ligne par app.js : elle porte l'etat, pas la hierarchie. */
.annonce-etat { font-size: 0.8rem; color: var(--texte-tres-doux); }

/* Le titre qui situe les gestes finis dans le passe (histoireAnnonces). Plus
   petit et plus discret que les lignes qu'il coiffe : il ne dit rien de l'objet,
   il dit seulement a quel temps lire ce qui suit. */
.annonce-histoire-titre {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--texte-tres-doux);
  opacity: 0.75;
  margin: 8px 0 2px;
}

/* ── v8 : page micro ── */
#p-micro.active { background: #0a0908; }
.micro-page { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; padding: 32px 24px; gap: 24px; text-align: center; }
.micro-titre { font-size: 1.2rem; font-weight: 700; }
.micro-sous { font-size: 0.9rem; color: var(--texte-doux); max-width: 320px; }
.micro-btn { width: 96px; height: 96px; border-radius: 50%; background: var(--rouge); border: none; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background 0.15s, transform 0.1s, box-shadow 0.05s linear; }
.micro-btn:active { transform: scale(0.95); }
.micro-btn.enregistrement { background: #8b1a1a; }
/* TICKET 113 : le halo tourne avec le niveau sonore reel, pose en JS a chaque
   frame (voir demarrerEcouteVisuelle dans app.js et haloMicro dans
   affichage.js) — « une animation qui tourne toute seule » ne dit rien de ce
   que le micro capte. `.niveau-indispo` est le seul cas qui garde le pulse
   generique : Web Audio a echoue a s'ouvrir (navigateur trop vieux, contexte
   refuse), et un halo immobile vaudrait moins qu'un signal generique. */
.micro-btn.enregistrement.niveau-indispo { box-shadow: 0 0 0 8px rgba(196,112,95,0.25); animation: pulse 1s infinite; }
.micro-btn svg { width: 40px; height: 40px; fill: white; stroke: none; }
.micro-etat { font-size: 0.85rem; color: var(--texte-doux); min-height: 1.5em; }
.micro-fallback { width: 100%; max-width: 360px; }
.micro-actions { display: flex; flex-direction: column; gap: 10px; width: 100%; max-width: 360px; }

/* ── v12 : bouton sortie-ailleurs ── */
.sortie-ailleurs { background: #1a1200; border: 1.5px solid #6b5000; color: #c8a000; }
.sortie-ailleurs:hover { background: #241900; }
/* ── v26 : bouton vendu en direct ── */
.sortie-direct { background: #0d1f0d; border: 1.5px solid var(--vert); color: var(--vert); }
.sortie-direct:hover { background: #122012; }

/* ── v12 : badge retiré ── */
.issue-retire { background: #1a1a1a; border-color: #555; color: #aaa; }

/* ── v12 : section À confirmer ── */
.confirmer-carte { background: #1a1200; border: 1.5px solid #6b5000; border-radius: var(--rayon); padding: 14px 16px; margin: 4px 16px 8px; }
.confirmer-titre { font-size: 0.9rem; font-weight: 600; margin-bottom: 6px; }
.confirmer-lien { font-size: 0.78rem; color: var(--or); text-decoration: none; display: block; margin-bottom: 10px; }
.confirmer-lien:hover { text-decoration: underline; }
.confirmer-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.confirmer-btn { padding: 6px 12px; border-radius: 999px; font-size: 0.78rem; font-weight: 600; border: 1.5px solid; cursor: pointer; background: none; }
.confirmer-vendu { border-color: var(--vert); color: var(--vert); }
.confirmer-retire { border-color: #6b5000; color: #c8a000; }
.confirmer-expire { border-color: var(--bord); color: var(--texte-doux); }

/* ── v8 : page post-analyse ── */
.postanalyse-page { display: flex; flex-direction: column; gap: 12px; padding: 16px; }
.postanalyse-lot { background: var(--carte); border: 1px solid var(--bord); border-radius: var(--rayon); padding: 14px; margin-bottom: 4px; }
.postanalyse-lot-titre { font-size: 0.9rem; font-weight: 600; }
.postanalyse-lot-actions { display: flex; gap: 8px; margin-top: 10px; }

/* ── v14 : confirmer inline dans carte ── */
.confirmer-inline { border-top: 1px solid var(--bord); padding: 6px 12px 8px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.confirmer-inline-label { font-size: 0.72rem; color: var(--texte-doux); }
.confirmer-btn-sm { background: none; border: 1px solid var(--bord); color: var(--texte-doux); font-size: 0.68rem; padding: 2px 7px; border-radius: 4px; cursor: pointer; }
.confirmer-btn-sm:hover { border-color: var(--or); color: var(--or); }


/* ── v16 : commission visible ── */
.sv-commission-mention { font-size: 0.78rem; color: var(--texte-doux); line-height: 1.5; text-align: left; margin: 8px 0 4px; }
.lot-prix-bloc { display: inline-flex; flex-direction: column; gap: 0; }
.preview-net-prix { font-size: 0.75rem; color: var(--texte-doux); margin-top: 4px; min-height: 1.2em; }

/* ── LE NET N'EST PAS SUR QUAND LA PAGE AFFICHE UN AUTRE PRIX (ticket rang 7,
   22 septembre 2026) ── Cinq objets ce jour-la portaient un prix de page
   different de celui de leur fiche, et l'ecran promettait le net de la fiche
   sans reserve : 38,00 € sur un LEGO que la page vendait 30 €, soit 28,50 €.
   L'or du bandeau de brouillon plutot que le rouge des echecs : ce n'est pas
   une panne, c'est un arbitrage qui n'a pas ete rendu, et le montant reste
   lisible. Le soulignement pointille dit le doute sans deplacer le chiffre. */
.lot-prix-incertain { color: var(--or); text-decoration: underline dotted var(--or); text-underline-offset: 3px; }
.lot-prix-ecart { display: block; font-size: 0.72rem; color: var(--or); white-space: nowrap; }
.ecart-prix-lbc { margin-top: 6px; background: #1e1a0e; border-left: 3px solid var(--or); border-radius: var(--rayon-sm); padding: 7px 9px; font-size: 0.78rem; line-height: 1.45; color: var(--texte); }

/* ── v20 : archiver lot ── */
.btn-archiver { font-size: 0.72rem; color: var(--texte-tres-doux); background: none; border: 1px solid var(--bord); border-radius: var(--rayon-sm); padding: 3px 10px; cursor: pointer; }
.btn-archiver:active { opacity: 0.6; }

/* LE BOUTON « Archiver » APPARTIENT A L'OBJET DU DESSUS, ET ÇA DOIT SE VOIR.
   Le filet de separation des lignes d'objet est un `::after` au bas de
   `.lot-carte` : pose apres la ligne, le bouton se retrouvait sous le filet,
   donc visuellement rattache a l'objet SUIVANT — Laurent, le 12 septembre
   2026 : « on a l'impression qu'il archive l'objet du dessous ». L'enveloppe
   reunit la ligne et son bouton, eteint le filet de la ligne et le reprend a
   son bas, sous le bouton. Meme gouttiere (16 px) et meme depart de filet
   (78 px, aligne sous le texte et non sous la vignette) : l'ensemble se lit
   comme un seul bloc a 400 px comme a 1200. */
.ligne-terminee { position: relative; }
.ligne-terminee > .lot-carte:not(:last-child)::after { content: none; }
.ligne-terminee > .lot-carte { padding-bottom: 4px; }
.ligne-terminee-actions { display: flex; justify-content: flex-end; padding: 0 16px 8px; }
.ligne-terminee:not(:last-child)::after { content: ''; position: absolute; bottom: 0; left: 78px; right: 0; height: 1px; background: var(--bord); }
.section-archive-toggle:hover { opacity: 0.8; }

/* ── v21 : bandeau urgences ── */
.urgence-bandeau { display: flex; align-items: flex-start; gap: 10px; background: #7b1a1a; color: #fff; padding: 12px 16px; margin: 0 0 2px; border-left: 4px solid #e53e3e; }
.urgence-icone { font-size: 1.1rem; flex-shrink: 0; margin-top: 1px; }
.urgence-texte { flex: 1; font-size: 0.9rem; font-weight: 600; line-height: 1.4; }
.urgence-lien { font-size: 0.78rem; color: #fbd38d; white-space: nowrap; text-decoration: underline; flex-shrink: 0; margin-top: 2px; }

/* ── v22 : vue opérateur ── */
.lien-operateur { font-size: 0.78rem; color: var(--texte-tres-doux); text-decoration: none; }
.lien-operateur:hover { color: var(--or); }

/* ── v24 : pastilles navigation par état ── */
.pastilles-etat-bar { display: flex; gap: 6px; padding: 0 16px 10px; flex-wrap: wrap; }
.pastille-etat { padding: 4px 12px; border-radius: 999px; font-size: 0.75rem; font-weight: 600; background: var(--carte2); border: 1px solid var(--bord); color: var(--texte-doux); cursor: pointer; transition: all 0.15s; font-family: inherit; }
.pastille-etat:not(.inactive):not(.actif):hover { border-color: var(--or); color: var(--or); }
.pastille-etat.actif { background: var(--or); color: #12100e; border-color: var(--or); }
.pastille-etat.inactive { color: var(--texte-tres-doux); cursor: default; }

/* Interrupteur par canal (ticket rang 122, 29/09/2026), carte des reglages
   « Comment Debarras te previent ». Meme principe que .badge-initial : la
   cible tactile (40 px) est plus grande que le dessin (24 px), et c'est le
   bouton qui la porte, pas la piste visible. */
.toggle-canal { width: 56px; height: 40px; display: inline-flex; align-items: center; justify-content: center; background: none; border: none; padding: 0; cursor: pointer; flex-shrink: 0; font-family: inherit; }
.toggle-canal-piste { position: relative; width: 44px; height: 24px; border-radius: 999px; background: var(--carte2); border: 1px solid var(--bord); transition: background-color 0.15s, border-color 0.15s; }
.toggle-canal-actif .toggle-canal-piste { background: var(--or); border-color: var(--or); }
.toggle-canal-bouton { position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: var(--texte); transition: transform 0.15s; }
.toggle-canal-actif .toggle-canal-bouton { transform: translateX(20px); background: #12100e; }

/* ── v28 : entête accueil ── */
.entete-accueil { padding: 14px 16px 8px; display: flex; align-items: center; gap: 8px; }
/* min-width:0 force le flex-item a se laisser retrecir sous sa largeur de
   contenu : sans ca, overflow/text-overflow n'a aucun effet dans une ligne
   flex et le h1 pousse la rangee entiere au lieu de tronquer. */
.entete-nom { font-size: 1.05rem; font-weight: 700; flex: 1; min-width: 0; line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 40 px et non 32 : c'est la seule cible du bandeau depuis le 18/09/2026, elle
   ouvre le menu du compte, et le seuil tactile du projet est de 40 px. Le disque
   colore, lui, reste a 32 px (::before) — la cible grandit, pas le dessin. */
.badge-initial { width: 40px; height: 40px; border-radius: 50%; background: none; border: none; color: var(--texte-doux); font-size: 0.8rem; font-weight: 700; display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0; font-family: inherit; position: relative; padding: 0; }
/* z-index negatif, sinon le pseudo-element positionne se peint PAR-DESSUS
   l'initiale et le badge parait vide. Le bouton n'a pas de fond a lui, il n'y a
   donc rien derriere quoi disparaitre. */
.badge-initial::before { content: ''; position: absolute; z-index: -1; width: 32px; height: 32px; border-radius: 50%; background: var(--carte2); border: 1px solid var(--bord); }
.badge-initial:active::before, .badge-initial[aria-expanded="true"]::before { border-color: var(--or); }
.badge-initial[aria-expanded="true"] { color: var(--or); }

/* LE MENU DU COMPTE. Il s'ancre sous l'initiale, a droite, et il ne contient que
   ce qui est rare ou irreversible. Chaque ligne fait 44 px de haut : on la vise
   au pouce, une main tenant l'objet. */
.menu-compte { position: relative; flex-shrink: 0; }
.menu-compte-panneau {
  position: absolute; top: 44px; right: 0; z-index: 150;
  min-width: 190px; padding: 6px;
  background: var(--carte2); border: 1px solid var(--bord);
  border-radius: var(--rayon); box-shadow: 0 8px 24px rgba(0,0,0,0.55);
  display: flex; flex-direction: column;
}
.menu-compte-panneau[hidden] { display: none; }
.menu-compte-item {
  min-height: 44px; padding: 0 14px; text-align: left;
  background: none; border: none; border-radius: var(--rayon-sm);
  color: var(--texte); font-size: 0.9rem; font-family: inherit;
  display: flex; align-items: center; cursor: pointer;
}
.menu-compte-item:hover, .menu-compte-item:focus-visible { background: var(--carte); color: var(--or); outline: none; }
/* La sortie est separee par un filet : c'est la seule ligne du menu dont on ne
   revient pas d'un clic, et elle ne doit pas se prendre pour une autre. */
.menu-compte-item--sortie { border-top: 1px solid var(--bord); border-radius: 0 0 var(--rayon-sm) var(--rayon-sm); margin-top: 4px; }

/* ── v28 : alerte action ── */
#zone-alerte:not(:empty) { padding: 0 16px 10px; }
.alerte-action { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-left: 3px solid var(--or); background: #1e1a0e; border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0; cursor: pointer; }
.alerte-action:active { background: #282010; }
/* Une ligne d'action sans adresse ou aller : elle informe, elle n'ouvre rien.
   Le serveur retire l'adresse de celles qu'il envoie a un deposant, nos comptes
   de plateforme ne s'ouvrant pas chez lui (lib/gestes-deposant.mjs). La main du
   curseur promettait un ailleurs qui n'existe pas ; la fleche, elle, est retiree
   par app.js, une fleche vide se lisant encore comme un lien. */
.alerte-action--info { cursor: default; }
.alerte-action--info:active { background: #1e1a0e; }
.alerte-action-texte { flex: 1; min-width: 0; }
.alerte-action-titre { font-size: 0.85rem; font-weight: 600; color: var(--or); }
.alerte-action-detail { font-size: 0.75rem; color: var(--texte-doux); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.alerte-action-fleche { color: var(--or); font-size: 1rem; flex-shrink: 0; }

/* ── v28 : onglets dossier ── */
.onglets-wrapper { padding: 0 16px 0; }
.onglets-rangee { display: flex; align-items: flex-end; }
.onglets-rangee2 { margin-top: -2px; position: relative; z-index: 2; }
.onglets-rangee1 { position: relative; z-index: 1; }
.onglet { padding: 7px 10px; border-radius: 11px 11px 0 0; border: 1px solid var(--bord); border-bottom: none; background: var(--carte2); color: var(--texte-tres-doux); font-size: 0.72rem; font-weight: 600; cursor: pointer; font-family: inherit; margin-left: -10px; position: relative; white-space: nowrap; }
.onglet:first-child { margin-left: 0; }
.onglet:not(.actif):not(.inactif):hover { border-color: var(--or); color: var(--texte-doux); }
.onglet.actif { background: var(--carte); color: var(--texte); padding-top: 10px; padding-bottom: 10px; box-shadow: 0 -3px 12px rgba(0,0,0,0.55); z-index: 5; border-color: var(--bord); }
.onglet.inactif { color: var(--texte-tres-doux); cursor: default; opacity: 0.6; }
.onglet-n { font-size: 0.65rem; margin-left: 3px; }
.onglet.actif .onglet-n { color: var(--or); }
.dossier-contenu { background: var(--carte); border: 1px solid var(--bord); border-radius: 0 0 var(--rayon) var(--rayon); margin: 0 16px 16px; position: relative; z-index: 1; min-height: 48px; overflow: hidden; padding-bottom: 4px; }
.dossier-contenu .section-titre { padding-top: 6px; }

/* ── Visionneuse de photos ──────────────────────────────────────────────────
   Fond opaque et non transparent : on regarde une photo pour juger un objet,
   le reste de l'écran ne doit pas la parasiter. */
.visionneuse {
  position: fixed; inset: 0; z-index: 200;
  background: #000;
  display: flex; align-items: center; justify-content: center;
  touch-action: none; overflow: hidden;
}
.visionneuse[hidden] { display: none; }
#vis-image {
  max-width: 100%; max-height: 100%;
  transform-origin: center center;
  will-change: transform;
  user-select: none; -webkit-user-drag: none;
}
.vis-fermer {
  position: absolute; top: 10px; right: 10px; z-index: 2;
  width: 44px; height: 44px; border-radius: 50%;
  background: rgba(0,0,0,0.55); border: none; color: #fff;
  font-size: 1.1rem; cursor: pointer; font-family: inherit;
}
.vis-rang {
  position: absolute; top: 18px; left: 50%; transform: translateX(-50%); z-index: 2;
  color: rgba(255,255,255,0.75); font-size: 0.8rem;
  font-variant-numeric: tabular-nums; pointer-events: none;
}
.vis-fleche {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 48px; height: 64px; border: none; background: rgba(0,0,0,0.35);
  color: #fff; font-size: 2rem; line-height: 1; cursor: pointer; font-family: inherit;
}
.vis-prec { left: 0; border-radius: 0 8px 8px 0; }
.vis-suiv { right: 0; border-radius: 8px 0 0 8px; }
.vis-fleche[hidden] { display: none; }
/* Ticket 149 : la vignette n'ouvre plus la visionneuse depuis la liste — toute
   la carte ouvre la fiche, et c'est dans la fiche que la photo s'agrandit.
   Le curseur suit : « pointer », pas « zoom-in ». */
.lot-vignette { cursor: pointer; }

/* ── v30 : cibles tactiles ────────────────────────────────────────────────────
   L'application s'utilise au téléphone, une main tenant l'objet photographié.
   Quatre boutons descendaient sous le seuil de 40 px fixé par DESIGN.md et se
   rataient au pouce. On garde leur apparence (fond, bordure, taille de texte),
   on ne change que la hauteur utile. */
.confirmer-btn-sm,
.btn-archiver,
.btn-piste-suppr,
.btn-tout-valider {
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* ── v30 : état vide qui dit quoi faire ───────────────────────────────────────
   Un état vide qui se contente de constater le vide laisse l'utilisateur
   devant un écran mort. La deuxième ligne dit l'action suivante. */
.vide-etat-action {
  display: block;
  margin-top: 6px;
  font-size: 0.8rem;
  color: var(--texte-doux);
}

/* Une photo en attente d'analyse : meme carte que les autres, mais on voit
   qu'elle respire encore. Pas d'animation agressive : un battement lent sur
   la vignette suffit a dire « ca travaille » sans attirer l'oeil en boucle. */
.lot-carte.carte-attente { cursor: default; }
.lot-carte.carte-attente .lot-titre { color: var(--texte-doux); font-weight: 500; }
.lot-carte.carte-attente .lot-vignette img { animation: attente-respire 2.4s ease-in-out infinite; }
@keyframes attente-respire { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
@media (prefers-reduced-motion: reduce) {
  .lot-carte.carte-attente .lot-vignette img { animation: none; opacity: 0.75; }
}

/* LES FILTRES DOIVENT ETRE AU-DESSUS DE LA LIGNE DE FLOTTAISON.
   Mesure du 4 septembre 2026 sur un ecran de telephone (390x844) : la rangee
   de pastilles commencait a y=815 pour 27 pixels de haut. Elle depassait de
   vingt-neuf pixels, et la barre d'un vrai navigateur en mange davantage.
   Lucile n'a pas rate les categories : elles n'etaient pas a l'ecran.
   Le bloc des compteurs occupait 179 pixels a lui seul. Sur petit ecran il
   passe sur une seule ligne : on garde les quatre chiffres, on rend cent
   pixels a ce qui suit. */
@media (max-width: 480px) {
  /* IL Y A TROIS COMPTEURS, PLUS QUATRE.
     Cette regle disait `repeat(4, 1fr) !important`, ecrit le 4 septembre 2026
     pour tenir quatre chiffres sur une ligne de telephone. Le compteur CO2 a
     ete retire le lendemain et la regle est restee : les deux premiers
     compteurs faisaient 86 pixels et s'arretaient a 186 sur une ligne de 375,
     la moitie droite vide. Remarque de Lucile, 5 septembre.
     Le !important a aussi neutralise trois regles que j'avais posees ensuite
     sur l'identifiant : aucune specificite ne le bat. Un !important est une
     promesse que rien ne changera jamais ; celle-ci a tenu une journee. */
  .compteurs {
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
    padding: 8px 10px;
  }
  .compteurs .compteur:nth-child(3) { grid-column: 1 / -1; }
  .compteur-valeur { font-size: 1.05rem; line-height: 1.15; }
  .compteur-label  { font-size: 0.62rem; line-height: 1.1; }
  .cpt-commission  { font-size: 0.58rem; }
}

/* Et une fois qu'on l'a vue, la rangee reste : elle colle en haut quand on
   fait defiler la liste. Sans ca, choisir un filtre oblige a remonter. */
.onglets-wrapper {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--fond);
}

/* ── ALERTES ───────────────────────────────────────────────────────────────
   Une alerte est un evenement : elle attire l'oeil parce qu'elle vient
   d'arriver. Passe vingt-quatre heures sans que personne n'agisse, ce n'est
   plus un evenement mais un retard : --ancienne la ramene au calme, sans la
   faire disparaitre. La croix est toujours la, en haut a droite. */
.alertes-liste { padding: 0 16px 8px; display: flex; flex-direction: column; gap: 8px; }
.alerte-carte {
  position: relative;
  background: #2e1010;
  border: 1px solid #6a2020;
  border-radius: var(--rayon-sm);
  padding: 10px 34px 10px 12px;
  font-size: 0.8rem;
}
.alerte-carte--pause { background: #1a1a2e; border-color: #3a3a6a; }
.alerte-carte--ancienne { background: transparent; border-color: var(--bord); }
.alerte-titre { font-weight: 700; color: var(--rouge); }
.alerte-carte--pause .alerte-titre { color: #7a7ae8; }
.alerte-carte--ancienne .alerte-titre { color: var(--texte); font-weight: 600; }
.alerte-motif { color: var(--texte-doux); margin-top: 3px; }
/* Ticket 147 : ce que l'échec change pour l'objet. C'est la ligne qui manquait,
   donc elle se lit plus fort que le motif — texte principal, pas texte doux. */
.alerte-consequence { color: var(--texte); font-size: 0.8rem; margin-top: 4px; }
/* Ticket 20 : une carte qui dit « les photos ne correspondent pas » montre les
   photos. Elles restent petites et sur une ligne qui defile : la carte est une
   ligne de liste, pas la fiche. */
.alerte-vignettes { display: flex; gap: 6px; margin-top: 8px; overflow-x: auto; scrollbar-width: none; }
.alerte-vignettes::-webkit-scrollbar { display: none; }
.alerte-vignette {
  flex-shrink: 0; width: 56px; height: 56px; border-radius: var(--rayon-sm);
  object-fit: cover; background: var(--carte2); cursor: pointer;
}
.alerte-vignette:active { opacity: 0.8; }
.alerte-pied { color: var(--texte-tres-doux); font-size: 0.7rem; margin-top: 3px; }
.alerte-detail { margin-top: 6px; }
.alerte-detail summary { color: var(--texte-tres-doux); font-size: 0.7rem; cursor: pointer; }
.alerte-detail pre {
  white-space: pre-wrap; word-break: break-word;
  color: var(--texte-tres-doux); font-size: 0.68rem; margin: 4px 0 0;
}
.alerte-actions { margin-top: 8px; display: flex; gap: 8px; }
.alerte-btn {
  background: none; border: 1px solid var(--bord); border-radius: var(--rayon-sm);
  color: var(--texte-tres-doux); padding: 5px 11px; font-size: 0.75rem; cursor: pointer;
  /* Regle des 40 px : ces deux boutons faisaient 26 px de haut, sous le seuil
     que DESIGN.md impose a toute cible tactile. Apparence inchangee. */
  min-height: 40px; display: inline-flex; align-items: center; justify-content: center;
}
.alerte-btn--primaire { background: #1a1a4a; border-color: #6a2020; color: var(--rouge); }

/* ── Ticket 136 : la decision et la panne ne se peignent pas pareil ────────
   Deux des trois cartes rouges de la capture du 8 septembre etaient le
   garde-fou photo en train de faire son travail. Rouge sang a cote d'un
   plantage de script, elles passaient pour des pannes et appelaient un clic
   sur « Relancer ». Elles prennent l'orange d'alerte deja au catalogue
   (#e8902a, fond teinte alerte #1e1a0e) : visible, mais pas alarmant. */
.alerte-carte--decision { background: #1e1a0e; border-color: #7a5a20; }
.alerte-carte--decision .alerte-titre { color: #e8902a; }
.alerte-carte--decision .alerte-btn--primaire { background: none; border-color: #7a5a20; color: #e8902a; }
.urgence-bandeau--decision { background: #2e1a0a; border-left-color: #e8902a; }

/* ── LES DEUX BANDEAUX DE REPONSE A UN ACHETEUR SONT PARTIS D'ICI ──────
   Vingt-deux regles peignaient les cartes de brouillon du bandeau
   d'accueil — le champ modifiable, la question citee, les deux boutons, et le
   refus du controle de ton ecrit sous le texte. Les deux cartes sont devenues
   des cartes d’operateur le 29 septembre 2026 (ticket rang 1, chantier
   laurent-2026-09-29) : leur rendu a quitte public/app.js, ces regles-la
   n'avaient plus rien a peindre. L'ecran qui les porte est celui de l'admin,
   page « Autres comptes », avec ses classes `ac-*`. */

/* ── Le mot a dire a l'acheteur pendant l'absence du deposant ───────────────
   Ticket 2705. Fond d'alerte teinte (#1e1a0e) et liseré or, pour la raison
   ecrite dans DESIGN.md : cinq tons d'alarme sur un ecran et plus aucun ne se
   remarque. Ce qui le distingue se lit dans sa phrase, qui nomme l'acheteur et
   la periode. `.urgence-bandeau--proposition` partageait cette peinture et
   vivait ici : elle est partie avec sa carte le 29/09/2026 (voir plus haut). */
.urgence-bandeau--absence { background: #1e1a0e; color: var(--texte); border-left-color: var(--or); }
.urgence-bandeau--absence .urgence-lien { color: var(--or-pale); }

/* ── Une question posee a l'operateur, qui n'a pas d'objet ──────────────────
   La quatrieme famille de bandeaux (lib/decisions-en-attente.mjs). Elle
   n'annonce pas une panne : fond d'arbitrage #2e1a0a et liseré orange #e8902a,
   les memes que .urgence-bandeau--decision et .alerte-carte--decision, qui
   marquent deja dans ce depot « on te demande de trancher ». Le rouge des
   echecs de publication reste a ce qui a echoue.
   Les trois boutons font 40 px de haut : l'application s'utilise au telephone,
   une main tenant l'objet. Ils passent a la ligne plutot que de retrecir. */
.urgence-bandeau--question { background: #2e1a0a; color: var(--texte); border-left-color: #e8902a; font-weight: 700; }
/* Une decision du Rat deja executee (lib/decisions-du-rat.mjs) : un CONSTAT, pas
   une question. Elle ne porte aucun bouton d'issue, et sa couleur le dit — le
   vert sourd de ce qui est fait, jamais l'orange de « on te demande de
   trancher » ni le rouge de ce qui a echoue. Elle n'est pas discrete pour
   autant : c'est de l'argent, et un accueil qui chuchote une vente conclue
   serait la meme faute que celui qui chuchote un echec de publication. */
.urgence-bandeau--fait { background: #14291a; color: var(--texte); border-left-color: #3f9a5c; font-weight: 700; }
.decision-phrase { margin: 6px 0 0; font-size: 0.85rem; font-weight: 400; line-height: 1.45; }
.decision-mesure { margin: 4px 0 0; font-size: 0.75rem; font-weight: 400; color: var(--texte-doux); }
.decision-issues { display: flex; align-items: center; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.decision-issue {
  min-height: 40px; padding: 0 16px;
  background: var(--carte2); color: var(--texte);
  border: 1px solid #7a5a20; border-radius: 8px;
  font-size: 0.9rem; font-weight: 700; cursor: pointer;
}
.decision-issue:active { background: var(--carte); }
.decision-issue:disabled { opacity: 0.55; cursor: default; }

/* ── LES ACHETEURS QU'ON NE SAIT PAS RATTACHER (ticket rang 3, 25 sept. 2026)
   Septieme famille. Meme fond d'arbitrage que la question
   (#2e1a0a, liseré #e8902a) : on demande de trancher, pas de
   constater une panne. Elle en reprend aussi la composition — une ligne par
   fil, phrase puis mesure — parce que quatre familles de cartes qui posent une
   question avec quatre mises en page differentes se relisent quatre fois.
   LE MENU EST LA CIBLE PRINCIPALE, ET IL FAIT 40 px comme tout le reste : il se
   touche au pouce, d'une main, l'autre tenant l'objet dont on cherche le nom.
   Il prend toute la largeur disponible (`flex: 1 1 100%`) parce qu'un titre
   d'objet tronque a 90 px ne se distingue pas du suivant ; le bouton et le lien
   passent alors sous lui, dans l'ordre de lecture. */
.rattacher-ligne { margin-top: 12px; padding-top: 12px; border-top: 1px solid rgba(232, 224, 212, 0.12); }
.rattacher-ligne:first-of-type { margin-top: 8px; border-top: 0; padding-top: 0; }
.rattacher-actions { display: flex; align-items: center; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.rattacher-choix {
  flex: 1 1 100%; min-height: 40px; max-width: 100%; padding: 0 12px;
  background: var(--carte2); color: var(--texte);
  border: 1px solid var(--bord); border-radius: 8px;
  font-size: 0.9rem; font-weight: 400;
}
.rattacher-bouton {
  min-height: 40px; padding: 0 16px;
  background: var(--carte2); color: var(--texte);
  border: 1px solid #7a5a20; border-radius: 8px;
  font-size: 0.9rem; font-weight: 700; cursor: pointer;
}
.rattacher-bouton:active { background: var(--carte); }
.rattacher-bouton:disabled { opacity: 0.55; cursor: default; }
/* LE DERNIER MOT DE L'ACHETEUR. Meme boite que celle qu'avait le texte a
   envoyer du bandeau de brouillon, dont c’etait le pendant en lecture : la, un
   texte que NOUS allions envoyer ; ici, une phrase que l’acheteur a ecrite.
   Elle a gardé sa classe a elle parce qu’un texte a envoyer se modifie avant
   de partir et que celui-ci ne se modifie jamais — la confusion des deux est
   ce que le test 3062.10 tenait, du temps ou ce bandeau etait ici. */
.rattacher-dernier-mot {
  margin: 8px 0 0; padding: 8px 12px;
  background: var(--carte); border-radius: 8px;
  font-size: 0.85rem; font-weight: 400; line-height: 1.45; color: var(--texte);
}
/* Un refus reste ecrit sous la ligne, jamais dans un toast : « ce fil n'attend
   plus de choix d'objet » est une information, et elle doit pouvoir etre relue. */
.rattacher-refus {
  margin: 8px 0 0; padding: 8px 12px;
  background: #2e100e; border-left: 3px solid var(--rouge);
  border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0;
  font-size: 0.8rem; font-weight: 600; line-height: 1.45; color: var(--texte);
}

/* ── LES FILS QUI ATTENDENT UNE REPONSE (ticket 2211, 22 sept. 2026) ────────
   Sixieme famille de bandeaux. Les cinq autres portent un GESTE a faire ;
   celle-ci porte un ETAT : 123 fils attendent, 106 au-dela du plafond de sept
   jours, et rien ne partira seul dessus. Meme fond d'arbitrage que la question
   (#2e1a0a, liseré #e8902a) : on demande de trancher, pas de constater une
   panne — le rouge reste a ce qui a echoue.
   LA LIGNE ENTIERE EST LA CIBLE, et elle fait 40 px de haut : l'application
   s'utilise au telephone, une main tenant l'objet (DESIGN.md). C'est un bouton
   qui REPLIE, pas une croix qui ferme — ce bandeau-la ne doit pas pouvoir se
   taire, c'est tout son objet.
   Chaque fil est une carte de la liste, avec son lien « Ouvrir le fil » en bas,
   lui aussi a 40 px. La mention de redite passe en rouge : c'est le seul
   endroit de cet ecran ou un geste est explicitement DECONSEILLE. */
.urgence-bandeau--attente { background: #2e1a0a; color: var(--texte); border-left-color: #e8902a; }
.attente-titre {
  display: flex; align-items: center; gap: 8px; width: 100%;
  min-height: 40px; padding: 0; margin: 0;
  background: none; border: 0; text-align: left;
  color: var(--texte); font-size: 0.95rem; font-weight: 700; cursor: pointer;
}
.attente-chevron { margin-left: auto; font-size: 0.8rem; color: var(--texte-doux); }
.attente-note { margin: 4px 0 0; font-size: 0.75rem; font-weight: 400; color: var(--texte-doux); }
.attente-note code { font-size: 0.72rem; }
.attente-liste { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.attente-fil {
  padding: 10px 12px; background: var(--carte); border-radius: 8px;
  font-weight: 400; line-height: 1.45;
}
.attente-fil-tete { display: flex; align-items: baseline; gap: 8px; }
.attente-qui { font-size: 0.9rem; font-weight: 700; }
.attente-age { margin-left: auto; font-size: 0.8rem; color: var(--texte-doux); white-space: nowrap; }
.attente-objet { margin-top: 2px; font-size: 0.85rem; color: var(--texte); }
.attente-objet em { color: var(--texte-doux); font-style: normal; }
.attente-redite { margin-top: 6px; font-size: 0.8rem; color: var(--rouge); font-weight: 700; }
.attente-detail { margin-top: 6px; font-size: 0.75rem; color: var(--texte-doux); }
.attente-lien {
  display: inline-flex; align-items: center; min-height: 40px;
  margin-top: 2px; font-size: 0.85rem; color: var(--or-pale);
}

/* LE REGIME D'ENVOI, EN HAUT DE L'ECRAN DES MESSAGES (ticket du 10 sept. 2026).
   Trois etats, trois apparences, parce qu'ils ne demandent pas la meme chose :
   - `--ouvert` : une ligne discrete en --texte-doux, un point vert. Le systeme
     repond, on n'interrompt personne pour le dire ;
   - `--attention` : silence de moins de 24 h, liseré --or, fond d'alerte. C'est
     probablement un reglage qu'on a pose exprès ;
   - `--anomalie` : silence de plus de 24 h, ou dont on ne sait pas dater le
     debut. Liseré --rouge : personne ne revient reouvrir un interrupteur qu'il
     a oublie, et trois jours de silence total sont une panne, pas un reglage.
   Le rouge est celui des echecs de publication, et c'est voulu : la regle du
   projet est que le succes n'est jamais l'etat par defaut. */
.regime-bandeau {
  margin: 10px 16px 0; padding: 10px 12px;
  border-left: 3px solid var(--bord); border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0;
  background: var(--carte); font-size: 0.85rem; line-height: 1.45; color: var(--texte);
}
.regime-bandeau--ouvert { background: none; border-left-color: var(--vert); color: var(--texte-doux); font-size: 0.8rem; padding: 6px 12px; }
.regime-bandeau--attention { background: #1e1a0e; border-left-color: var(--or); }
.regime-bandeau--anomalie { background: #201512; border-left-color: var(--rouge); }
.regime-bandeau-faire { margin-top: 6px; font-size: 0.8rem; color: var(--texte-doux); }
.regime-bandeau-depuis { margin-top: 4px; font-size: 0.75rem; color: var(--texte-tres-doux); }
/* Un bouton qui parle au serveur le montre : inactif, et son libelle dit ce
   qui se passe (« Relance en cours… »). La classe ne sert qu'a l'apparence,
   l'etat vrai est `disabled`. */
.btn-occupe { opacity: 0.55; cursor: default; }
.alerte-carte--ancienne .alerte-btn--primaire { background: none; border-color: var(--bord); color: var(--texte-doux); }
/* LA CROIX EST UNE CIBLE TACTILE, DONC 40 PX (DESIGN.md : « tout bouton
   tactile porte au minimum 40 px de hauteur utile »). Elle en faisait 30, ce
   qui passait tant qu'elle n'etait que sur les cartes d'echec ; le 11 septembre
   2026 elle est posee sur les trois familles de bandeaux de l'accueil, y
   compris sur une ligne d'une seule ligne de haut, au pouce et l'objet dans
   l'autre main. Le signe, lui, ne grossit pas : seule la zone cliquable. */
.alerte-fermer, .urgence-fermer {
  position: absolute; top: 2px; right: 2px;
  background: none; border: 0; color: var(--texte-tres-doux);
  font-size: 1.15rem; line-height: 1; cursor: pointer;
  width: 40px; height: 40px; border-radius: 4px;
}
.alerte-fermer:hover, .urgence-fermer:hover { color: var(--texte); background: rgba(255,255,255,0.07); }
.urgence-bandeau { position: relative; padding-right: 44px; }
/* La ligne d'action porte sa croix elle aussi, et `position: absolute` se cale
   sur le premier ancetre positionne : sans cette regle, la croix serait allee
   se poser dans le coin de la page. */
.alerte-action { position: relative; padding-right: 44px; }

/* ── Zone « jamais en ligne » ──────────────────────────────────────────────
   Ce bloc n'avait AUCUNE regle : il s'affichait en texte de paragraphe,
   pleine largeur, en haut de l'accueil, et mangeait la moitie d'un ecran de
   telephone. Il passait inapercu parce qu'il n'etait rendu qu'une fois et
   disparaissait au premier rafraichissement. */
.zone-jamais-en-ligne { padding: 0 16px; margin: 2px 0 10px; }
.zone-jamais-en-ligne:empty { display: none; }
.zjel-titre {
  font-size: 0.84rem; font-weight: 700; color: var(--texte);
  display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
}
.zjel-montant { color: var(--or); }
.zjel-sous { font-size: 0.72rem; color: var(--texte-doux); margin: 3px 0 4px; }
.zjel-ligne {
  display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
  padding: 8px 0; border-bottom: 1px solid var(--bord);
  font-size: 0.78rem; cursor: pointer; min-height: 34px;
}
.zjel-ligne:last-child { border-bottom: none; }
.zjel-nom { flex: 1; min-width: 0; color: var(--texte); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.zjel-prix { color: var(--texte-doux); white-space: nowrap; }
.zjel-motif { color: var(--texte-tres-doux); font-size: 0.7rem; flex-shrink: 0; max-width: 45%; text-align: right; }
.zjel-bloques {
  margin-top: 8px; border: 1px solid var(--bord);
  border-radius: var(--rayon-sm); padding: 2px 10px;
}
.zjel-resume {
  font-size: 0.75rem; color: var(--texte-doux); cursor: pointer;
  list-style: none; padding: 9px 0; min-height: 34px;
}
.zjel-resume::-webkit-details-marker { display: none; }
.zjel-resume::before { content: '▸\00a0'; color: var(--texte-tres-doux); }
.zjel-bloques[open] .zjel-resume::before { content: '▾\00a0'; }
.btn-tout-publier { margin-top: 10px; width: 100%; min-height: 44px; }

/* ── Cibles tactiles ───────────────────────────────────────────────────────
   Les onglets faisaient 7 px de marge et 0,72 rem de texte. Le minimum
   recommande pour une cible tactile est de 44 a 48 px de haut. */
.onglet { padding: 11px 14px; font-size: 0.8rem; min-height: 42px; }
.onglet.actif { padding-top: 13px; padding-bottom: 13px; }
.onglet-n { font-size: 0.72rem; margin-left: 5px; }

/* ── Onglets : ils se chevauchaient ────────────────────────────────────────
   `margin-left: -10px` faisait passer chaque onglet PAR-DESSUS le precedent,
   et seul l'onglet actif portait un z-index. Le dernier de la rangee se
   retrouvait donc au premier plan et se lisait comme selectionne : sur la
   capture du 4 septembre a 21h36, « Terminée » paraissait actif alors que la
   liste affichait « EN COURS (115) » — en realite aucun onglet n'etait
   choisi, le filtre par defaut etant « tous ».
   Chaque onglet perdait aussi dix pixels de zone cliquable, manges par son
   voisin, sur 7 px de marge interieure. */
.onglet { margin-left: 4px; }
.onglet:first-child { margin-left: 0; }
.onglet.actif {
  border-top: 2px solid var(--or);
  padding-top: 11px;
}
/* Un onglet vide n'est pas cliquable : il doit le montrer, sans disparaitre. */
.onglet.inactif { opacity: 0.45; }
/* La rangee vide de la v28 ne doit pas manger de hauteur. */
.onglets-rangee:empty { display: none; }

/* ── Onglets : quatre, tous cliquables ─────────────────────────────────────
   Avec quatre onglets, la rangee peut deborder sur un telephone etroit.
   Elle defile, sans barre visible, et l'onglet choisi est ramene dans le
   champ par afficherOngletsDossiers. */
.onglets-rangee {
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.onglets-rangee::-webkit-scrollbar { display: none; }
.onglet { flex: 0 0 auto; }

/* ── Onglets : ce qui deborde se voit ──────────────────────────────────────
   Un degrade par cote, cale sur la gouttiere de 16 px, qui fond les onglets
   dans le fond de page au lieu de les trancher net. `pointer-events: none` :
   il ne vole pas le clic de l'onglet qu'il recouvre a moitie, et il n'est pas
   une commande — on ne l'appuie pas, on fait glisser la rangee.
   z-index 6, soit juste au-dessus de l'onglet actif (5) : sans ca, l'onglet
   actif traverserait le degrade et serait le seul a rester coupe net.
   Ni `display` ni `visibility` ici : ces deux blocs se montrent et se cachent
   par l'attribut `hidden`, dont la regle du navigateur (`display: none`) ne
   tiendrait pas face a un `display` ecrit ici. */
.onglets-wrapper { position: relative; }
.onglets-deborde {
  position: absolute; top: 0; bottom: 0; width: 28px;
  pointer-events: none; z-index: 6;
}
.onglets-deborde--droite { right: 16px; background: linear-gradient(to right, rgba(18,16,14,0), var(--fond)); }
.onglets-deborde--gauche { left: 16px; background: linear-gradient(to left, rgba(18,16,14,0), var(--fond)); }
/* Un onglet vide reste cliquable : il s'efface un peu, il ne se ferme pas. */
.onglet.vide { opacity: 0.55; }
.onglet.vide.actif { opacity: 1; }
.dossier-vide {
  padding: 26px 16px;
  text-align: center;
  color: var(--texte-doux);
  font-size: 0.85rem;
}

/* ── Compteurs : trois au lieu de quatre ───────────────────────────────────
   Le compteur CO2 est retire. La grille a deux colonnes laissait donc une
   case vide a droite du troisieme. « Encaissés » porte deja une seconde
   ligne (la commission) : il prend toute la largeur, ce qui lui va. */
.compteurs .compteur:nth-child(3) { grid-column: 1 / -1; }

/* ── Compteurs : trois, et centres ─────────────────────────────────────────
   Mesure du 5 septembre 2026 sur un ecran de 390 points : les deux premiers
   compteurs faisaient 86 pixels et s'arretaient a 186 sur une ligne de 375.
   La moitie droite etait vide. La grille prevoyait encore quatre colonnes,
   comme du temps ou le CO2 en occupait une : le retrait d'hier soir a laisse
   la regle telle quelle.
   L'identifiant l'emporte sur la classe, donc cette regle vaut aussi dans la
   requete de media qui reglait la version a quatre. */
#zone-compteurs.compteurs { grid-template-columns: repeat(2, 1fr); }
#zone-compteurs.compteurs .compteur { min-width: 0; }
#zone-compteurs.compteurs .compteur:nth-child(3) { grid-column: 1 / -1; }

/* « Se déconnecter » n'est plus dans l'en-tête : il est dans le menu du compte,
   sous l'initiale (.menu-compte-item--sortie, plus haut dans ce fichier). Le
   bouton d'en-tête et ses règles sont partis le 19/09/2026 avec le ticket 1199 ;
   ce qu'ils avaient appris reste vrai et vit maintenant là-bas : une cible qu'on
   ne remarque pas n'est pas une cible, et sortir d'un compte doit rester
   trouvable sans défilement. */
}


/* Ranger un objet bloque. Discret : ce n'est pas une action qu'on cherche,
   c'est une action qu'on trouve quand on en a assez de relire le motif. */
.zjel-ranger {
  background: none;
  border: 1px solid #6a6156;
  color: var(--texte-doux);
  border-radius: 6px;
  padding: 4px 10px;
  min-height: 32px;
  font-size: 0.82rem;
  margin-left: 8px;
  cursor: pointer;
}
.zjel-ranger:hover { border-color: var(--texte-doux); }

/* Un titre d'alerte que le front n'a pas pu resoudre : il se distingue, pour
   qu'on ne le confonde pas avec un vrai nom d'objet. Cause : /api/etat ne
   renvoie que les lots du compte connecte, la file contient ceux de tous. */
.alerte-titre--inconnu { color: var(--texte-tres-doux); font-style: italic; }

/* ── Rachat direct : « tu gagnerais peut-etre plus ailleurs » ──
   Une carte dans le flux, sous le prix : pas d'ombre, pas de rouge, pas
   d'encadre d'erreur. C'est un CONSEIL, pas un avertissement — la carte
   emprunte donc la meme surface et le meme filet que .zone-conseil. Le lien
   porte 40 px de hauteur utile : sur un telephone, une main tenant l'objet,
   un lien plus court se rate. */
.bloc-rachat { background: var(--carte2); border: 1px solid var(--bord); border-radius: var(--rayon-sm); padding: 12px; margin: 0 16px 14px; }
.bloc-rachat-titre { font-size: 0.85rem; font-weight: 600; color: var(--texte); margin-bottom: 4px; }
.bloc-rachat-corps { font-size: 0.8rem; line-height: 1.5; color: var(--texte-doux); margin-top: 4px; }
.bloc-rachat-lien { display: inline-flex; align-items: center; min-height: 40px; font-size: 0.8rem; font-weight: 600; color: var(--or); text-decoration: none; }
.bloc-rachat-lien:active { color: var(--or-pale); }

/* ── Ticket 135 : trois details d'ecran ────────────────────────────────────
   1. Le bandeau d'analyse sur l'ecran de capture. Il etait masque la, c'est-a-
      dire exactement la ou la personne se trouve apres avoir pris sa photo
      (Lucile, retour 1 du 5 septembre 2026). Il y reste, mais EN HAUT : le bas
      appartient au declencheur, et un bandeau par-dessus ferait rater la
      photo. Fond opaque, il se pose sur l'image de la camera.

      19 SEPTEMBRE 2026 (ticket 1433) : il est desormais en haut PARTOUT, et
      cette regle n'a plus de position a corriger — le cas general porte ce que
      le cas particulier apprenait. Ce qui lui reste est le decalage de
      l'ecran de capture, qui ne passe pas par le `padding-top` du body : il
      est sur `#camera-ui`. La classe survit parce que `etatBandeauAnalyses`
      la rend et que le test 61 la tient ; elle dit ou l'on est, elle ne place
      plus rien. */
#bandeau-analyses.sur-capture {
  border-top: none;
}
/* Le ton dit l'etat reel. Un echec ne se chuchote pas (DESIGN.md, contrainte 2). */
#bandeau-analyses.ton-echec { border-color: var(--rouge); }
#bandeau-analyses.ton-echec .bandeau-analyses-txt { color: var(--rouge); }
#bandeau-analyses.ton-termine .bandeau-analyses-txt { color: var(--vert); }

/* 2. Une session en echec ne disparait plus, et elle porte de quoi agir.
      Trois photos de Paul, le 2 septembre 2026, sont devenues introuvables
      pour lui au bout de six heures. */
.lot-carte.carte-attente-arretee .lot-vignette img { animation: none; opacity: 1; }
.lot-carte.carte-attente-echec .lot-titre { color: var(--rouge); }
.lot-carte.carte-attente .lot-vignette { cursor: pointer; }
/* LA CARTE DE RELAIS : L'ANALYSE A ABOUTI, L'OBJET EST AILLEURS.
   Elle prend la place de la carte « Analyse en cours » et reste dix minutes,
   le temps de dire dans quel onglet l'objet est parti. Toute la ligne est une
   cible, comme une ligne d'objet, et elle mene a cet onglet : le titre reprend
   donc la couleur du texte principal, la vignette ne respire plus. */
.lot-carte.carte-attente-relais { cursor: pointer; }
.lot-carte.carte-attente-relais .lot-titre { color: var(--texte); font-weight: 600; }
.lot-carte.carte-attente-relais .lot-vignette { cursor: pointer; }

.btn-reessayer, .btn-relais {
  font-size: 0.75rem; font-weight: 600; color: var(--or);
  background: var(--carte2); border: 1px solid var(--bord);
  border-radius: var(--rayon-sm); padding: 4px 12px; cursor: pointer;
  min-height: 40px; display: inline-flex; align-items: center; justify-content: center;
}
.btn-reessayer:active, .btn-relais:active { color: var(--or-pale); opacity: 0.7; }

/* 3. Une plateforme prevue n'a pas l'apparence d'une annonce en ligne.
      « en ligne sur leboncoin » est vert et cliquable ; « prevu sur Vinted »
      reste en texte tres doux et ne mene nulle part, parce qu'il n'y a nulle
      part ou aller. */
.lot-sous-plat.prevu { color: var(--texte-tres-doux); font-style: italic; }

/* Une annonce ARRETEE n'est ni l'un ni l'autre : elle a existe, donc pas
   l'italique de ce qui est seulement prevu ; elle ne diffuse plus, donc pas le
   vert de « en ligne ». Le texte doux la laisse lisible sans la faire passer
   pour une bonne nouvelle. */
.lot-sous-plat.arretee { color: var(--texte-doux); }

/* ── L'ECRAN DU DEPOSANT : UNE CONVERSATION AVEC DEBARRAS (ticket 146) ───────
   Laurent, le 8 septembre 2026 : « du point de vue de l'utilisateur,
   l'utilisateur est en train de parler a Debarras, pas au client. » Une entree
   n'est donc pas un fil : c'est une question de Debarras attachee a un objet,
   et deux a quatre boutons pour y repondre en trois secondes.

   Zones tactiles : 44 px sur chaque bouton de reponse. L'ecran s'utilise au
   telephone, une main tenant l'objet (DESIGN.md, contrainte 1). */
.q-carte { background: var(--carte); border: 1px solid var(--bord); border-radius: var(--rayon); margin: 8px 16px; padding: 12px 14px; }
.q-entete { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.q-objet { font-size: 0.9rem; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.q-delai { font-size: 0.75rem; color: var(--texte-tres-doux); white-space: nowrap; font-variant-numeric: tabular-nums; }
.q-delai.presse { color: var(--rouge); font-weight: 700; }
.q-texte { font-size: 0.9rem; line-height: 1.5; margin-top: 6px; color: var(--texte); }
.q-boutons { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.q-bouton {
  background: var(--carte2); border: 2px solid var(--bord); border-radius: var(--rayon-sm);
  padding: 12px 14px; min-height: 44px; font-size: 0.9rem; font-weight: 600; text-align: left;
  color: var(--texte); cursor: pointer; width: 100%;
}
.q-bouton:active { border-color: var(--or); color: var(--or); background: #1e1a0a; }
.q-bouton:disabled { opacity: 0.55; cursor: default; }
/* La voix avant le clavier : Laurent l'a demandee en deuxieme choix, le texte
   libre en dernier recours. Les deux ne s'affichent qu'apres un geste. */
.q-autres { display: flex; gap: 8px; margin-top: 10px; }
.q-autre {
  flex: 1; background: none; border: 1px solid var(--bord); border-radius: var(--rayon-sm);
  padding: 10px; min-height: 40px; font-size: 0.8rem; font-weight: 600; color: var(--texte-doux); cursor: pointer;
}
.q-autre:active { color: var(--or); border-color: var(--or); }
.q-autre.enregistrement { color: var(--rouge); border-color: var(--rouge); }
.q-champ {
  width: 100%; margin-top: 10px; padding: 12px; box-sizing: border-box;
  background: var(--carte2); border: 1px solid var(--bord); border-radius: var(--rayon-sm);
  color: var(--texte); font-size: 0.9rem; resize: vertical;
}
.q-champ:focus { border-color: var(--or); outline: none; }
.q-etat { font-size: 0.8rem; color: var(--texte-doux); margin-top: 10px; }

/* ── Ce que la reponse du deposant a ajoute a l'annonce (25 septembre 2026) ──
   Pas une carte : rien a y faire, rien a y cliquer. Un liseret dore le long du
   texte dit « ceci vient de toi et c'est parti dans l'annonce », sans prendre
   la place d'une question a laquelle il faut repondre, juste au-dessus. */
.enrichissements { margin: 8px 16px; padding: 10px 0 0 12px; border-left: 2px solid var(--or); }
.enrichissements-titre { font-size: 0.75rem; color: var(--texte-tres-doux); text-transform: uppercase; letter-spacing: 0.04em; }
.enrichissement { font-size: 0.9rem; line-height: 1.5; color: var(--texte); margin-top: 6px; }

/* ── Doublon présumé au dépôt (ticket 142) ──────────────────────────────────
   Deux photos côte à côte, la question au-dessus, les deux décisions en bas :
   la personne compare avant de trancher, elle ne lit pas un verdict. */
.doublon-phrase {
  background: #1e1a0e; border: 1px solid var(--bord); border-radius: var(--rayon);
  padding: 12px 14px; font-size: 0.9rem; line-height: 1.5; color: var(--texte);
}
/* Le nombre de photos communes : le fait qui a declenche la question, et qui la
   tranche plus vite que la phrase. Tabulaire comme tout nombre comparable. */
.doublon-communes {
  margin-top: 8px; font-size: 0.85rem; color: var(--texte-tres-doux);
  font-family: ui-monospace, 'Courier New', monospace; font-variant-numeric: tabular-nums;
}
.doublon-photos { display: flex; gap: 12px; margin-top: 16px; }
.doublon-photo { flex: 1; margin: 0; min-width: 0; }
.doublon-photo img {
  width: 100%; aspect-ratio: 1; object-fit: cover;
  border-radius: var(--rayon-sm); border: 1px solid var(--bord); background: var(--carte2);
}
.doublon-photo figcaption {
  font-size: 0.75rem; font-weight: 600; color: var(--texte-tres-doux);
  margin-top: 8px; text-align: center;
}
.doublon-actions { display: flex; flex-direction: column; gap: 12px; margin-top: 24px; }
.doublon-actions .btn { min-height: 48px; }

/* ── CE QUI N'A PAS DE PHOTO UTILISABLE (ticket rang 43, 17 sept. 2026) ──────
   Deux objets vivants etaient dans ce cas le 17 septembre et rien ne le disait
   a l'ecran : la carte gardait son bouton « Publier » et l'objet ne bougeait
   jamais. Le rouge des echecs de publication serait faux — rien n'a plante, et
   le deposant peut reparer d'une photo — donc c'est le jaune deja au catalogue,
   celui de « photos a revoir » : une decision a prendre, pas un incident.
   Le bloc de blocage reprend mot pour mot ce que le blocage reglementaire
   portait en style inline avant ce ticket : meme apparence, une classe au lieu
   de six declarations recopiees a chaque carte. */
.pastille-photo-manquante { background: #2e2000; border: 1px solid #7a5800; color: #d4a000; }
.lot-sous-photo-manquante { color: #d4a000; font-weight: 700; }
.lot-carte-blocage { padding: 8px 12px; font-size: 0.75rem; color: var(--texte-doux); font-style: italic; }
.lot-carte-blocage-photo { color: #d4a000; font-style: normal; font-weight: 600; }

/* ── AJOUTER UNE PHOTO A UN OBJET BLOQUE (ticket rang 24) ────────────────────
   Le bouton prend la place que « Publier » n'occupe pas sur ces fiches-la : en
   bas d'ecran, pleine largeur, 48 px de haut. On tient l'objet d'une main et le
   telephone de l'autre, et c'est exactement le geste que la fiche demande — donc
   il est la cible principale, pas un lien discret. Le jaune est celui de
   `.pastille-photo-manquante` juste au-dessus : la meme panne porte la meme
   couleur du haut de la carte jusqu'au bouton qui la repare. */
.btn-ajouter-photo { background: #2e2000; border: 1px solid #7a5800; color: #d4a000; border-radius: var(--rayon); padding: 15px; font-size: 0.95rem; font-weight: 700; width: 100%; min-height: 48px; }
.btn-ajouter-photo:active { background: var(--carte2); }
.btn-ajouter-photo[disabled] { opacity: 0.6; }

/* ── OU EN EST L'EXPEDITION : LA FRISE DE LA FICHE (ticket 2571, point 1) ────
   Carte dans le flux, donc sans ombre : `--carte` + 1px de `--bord`, comme
   toutes les autres (DESIGN.md, « Rayons et ombres »).

   Chaque etape fait 40 px de haut. Ce n'est pas une cible tactile, mais c'est
   la meme regle et pour la meme raison : ca se lit au telephone, une main
   tenant l'objet, et six lignes serrees a 24 px ne se lisent pas debout dans
   un couloir. Les dates sont en chiffres tabulaires comme tout nombre
   comparable du projet. */
.frise-exp { background: var(--carte); border: 1px solid var(--bord); border-radius: var(--rayon); padding: 12px 16px; margin: 12px 0; }
.frise-exp-titre { font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--texte-doux); margin-bottom: 8px; }
.frise-exp-liste { list-style: none; margin: 0; padding: 0; }
.frise-exp-etape { display: flex; align-items: center; gap: 12px; min-height: 40px; font-size: 0.85rem; color: var(--texte-tres-doux); border-bottom: 1px solid var(--bord); }
.frise-exp-etape:last-child { border-bottom: none; }
.frise-exp-puce { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; background: transparent; border: 1px solid var(--texte-tres-doux); }
.frise-exp-etape.est-atteinte { color: var(--texte); }
.frise-exp-etape.est-atteinte .frise-exp-puce { background: var(--vert); border-color: var(--vert); }
.frise-exp-etape.est-courante { font-weight: 700; }
/* L'etape qui vient : la puce est creuse et or, pour qu'on la trouve sans
   compter les lignes atteintes. */
.frise-exp-etape.est-prochaine { color: var(--texte); }
.frise-exp-etape.est-prochaine .frise-exp-puce { border-color: var(--or); border-width: 2px; }
.frise-exp-libelle { flex: 1; }
.frise-exp-date { font-family: ui-monospace, 'Courier New', monospace; font-variant-numeric: tabular-nums; font-size: 0.8rem; color: var(--texte-tres-doux); }
/* ATTEINTE SANS DATE : le mot, jamais un tiret. Un tiret a cette place se lit
   comme une date qui manque par erreur, donc comme un defaut a signaler ; la
   frise ne sait simplement pas quand, et le dit. */
.frise-exp-sans-date { font-size: 0.8rem; font-style: italic; color: var(--texte-tres-doux); }
/* L'ECHEANCE DEPASSEE SE VOIT SANS QU'ON LA CHERCHE : le rouge d'urgence du
   projet (#7b1a1a, liseré #e53e3e), le meme que `.urgence-bandeau`. Une vente
   s'annule pour ca — le skateboard du 26 aout 2026. */
.frise-exp-alerte { display: flex; align-items: flex-start; gap: 10px; background: #7b1a1a; color: #fff; border-left: 4px solid #e53e3e; border-radius: var(--rayon-sm); padding: 12px; margin-bottom: 12px; }
.frise-exp-alerte-icone { font-size: 1.1rem; flex-shrink: 0; line-height: 1.2; }
.frise-exp-alerte-texte { flex: 1; font-size: 0.85rem; font-weight: 700; line-height: 1.4; }
.frise-exp-suite { margin-top: 10px; font-size: 0.85rem; color: var(--texte-doux); }
.frise-exp-suite.est-pressee { color: var(--rouge); font-weight: 700; }

/* ── Ecran de rachat instantane contre vente (ticket rang 121, suite du 2901) :
   le deposant saisit ce que Momox/Gibert lui proposent, cette zone lit la
   comparaison rendue par GET /api/lot/:id/rachat, elle ne calcule rien. */
.rachat-instantane-vente-nette { font-size: 0.85rem; font-weight: 700; color: var(--texte); margin: 10px 16px 4px; }
.rachat-instantane-ligne { font-size: 0.85rem; color: var(--texte-doux); margin: 0 16px 10px; padding: 10px 12px; background: var(--carte2); border-radius: var(--rayon-sm); min-height: 40px; }
.rachat-instantane-panier { font-size: 0.78rem; color: var(--texte-tres-doux); margin-top: 4px; }
.rachat-instantane-sans-code { font-size: 0.8rem; font-style: italic; color: var(--texte-tres-doux); margin: 4px 16px 10px; }

/* ── Écran « Enlever » : trois gestes, un seul appui (ticket 2724) ──────────
   Cibles de 48 px déjà tenues par `.enlever-btn` plus haut ; le geste
   irréversible se distingue par sa bordure, pas par une modale de plus. */
.enlever-btn-definitif { border-color: var(--rouge); color: var(--rouge); }
.enlever-btn-definitif span { color: var(--texte-tres-doux); }
.annonce-encours { color: var(--or); }
.annonce-erreur { color: var(--rouge); font-weight: 700; }
.undo-enlever-bar { background: var(--carte2); border: 1px solid var(--rouge); padding: 12px 16px; min-height: 44px; display: flex; align-items: center; font-size: 0.8rem; color: var(--texte-doux); pointer-events: none; }
.undo-enlever-bar.visible { opacity: 1; pointer-events: auto; }
.undo-enlever-bar a { color: var(--or); cursor: pointer; text-decoration: underline; margin-left: 10px; padding: 8px; min-height: 44px; display: inline-flex; align-items: center; }

/* ── LE RENVOI D'UN ECRAN DE REGLAGE A L'AUTRE (ticket rang 33, 27/09/2026) ──
   Les quatre reglages du deposant sont repartis sur deux ecrans : « Comment on
   te previent » et le seuil de reserve dans Reglages, « publier sans me
   demander », l'adresse, le mode de remise et la pause dans Mon compte — et le
   prix plancher sur la fiche de chaque objet. Le partage est defendable,
   l'absence de renvoi ne l'est pas : qui se demande « est-ce que ca publie tout
   seul ? » ouvre Reglages, n'y lit que des alertes, et s'arrete la.
   Un encart, pas une alerte : `--carte2` et texte secondaire, comme un champ au
   repos. Le lien porte ses 40 px de hauteur utile comme tout ce qui se touche. */
.renvoi-ecran { background: var(--carte2); border: 1px solid var(--bord); border-radius: var(--rayon-sm); padding: 12px; margin-bottom: 16px; font-size: 0.8rem; color: var(--texte-doux); line-height: 1.5; }
.renvoi-ecran strong { color: var(--texte); font-weight: 700; }
.renvoi-ecran-lien { display: inline-flex; align-items: center; min-height: 40px; background: none; border: none; padding: 0; color: var(--or); font-weight: 700; font-size: 0.85rem; }

/* ── « Ton annonce » : l'apercu au-dessus du bouton qui l'envoie (3899) ──
   Une CARTE, pas un formulaire : fond de carte, liseré or sur le bord gauche
   comme les autres encarts qui montrent sans rien demander (.fiche-photo-en-ligne,
   .zone-decision-tenue). Rien ne s'y clique, donc aucune cible tactile ici.
   La vignette fait 88 px : assez pour reconnaitre l'objet d'un coup d'oeil sur
   un telephone, assez peu pour que le texte entier reste visible a cote sans
   que la carte pousse le bouton de validation hors de l'ecran. */
.apercu-annonce { margin: 0 16px 14px; }
.apercu-annonce-entete { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--or-pale); margin-bottom: 6px; }
.apercu-annonce-carte { display: flex; gap: 12px; padding: 12px; background: var(--carte2); border: 1px solid var(--bord); border-left: 3px solid var(--or); border-radius: 0 var(--rayon-sm) var(--rayon-sm) 0; }
.apercu-annonce-photo { flex-shrink: 0; width: 88px; height: 88px; border-radius: var(--rayon-sm); overflow: hidden; background: var(--fond); }
.apercu-annonce-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.apercu-annonce-photo--vide { display: flex; align-items: center; justify-content: center; padding: 6px; text-align: center; font-size: 0.7rem; line-height: 1.2; color: var(--texte-doux); border: 1px dashed var(--bord); }
.apercu-annonce-corps { min-width: 0; flex: 1; }
.apercu-annonce-titre { font-size: 0.9rem; font-weight: 700; color: var(--texte); line-height: 1.3; }
.apercu-annonce-prix { margin-top: 2px; font-size: 0.95rem; font-weight: 700; color: var(--or); }
/* Le texte entier, et il revient a la ligne comme il a ete tape : une annonce
   dont les paragraphes sont ecrases ne se relit pas comme elle se lira. */
.apercu-annonce-texte { margin-top: 6px; font-size: 0.8rem; line-height: 1.45; color: var(--texte-doux); white-space: pre-wrap; overflow-wrap: anywhere; }
.apercu-annonce-autres { margin-top: 6px; font-size: 0.7rem; color: var(--texte-tres-doux); }
/* Ce qui manque n'est ni une erreur rouge ni une decoration : c'est un champ
   vide qui partira vide si personne n'y retourne. */
.apercu-annonce-absent { font-style: italic; color: var(--texte-tres-doux); font-weight: 400; }
.apercu-annonce-manque { margin-top: 6px; font-size: 0.75rem; line-height: 1.4; color: var(--or-pale); }

/* ── DIRE CE QUI NE VA PAS (ticket 2085, 30/09/2026) ────────────────────────
   Le formulaire de retour du deposant, dans les Reglages, juste sous la carte
   des canaux : l'une dit comment Debarras te joint, l'autre comment tu joins
   Debarras. Meme fond et meme bordure que `.renvoi-ecran`, qui est la forme des
   blocs d'explication de cette page — ce n'est pas un reglage a enregistrer, et
   lui donner l'apparence d'un champ de reglage ferait chercher un bouton
   « Enregistrer » qui n'existe pas.
   Le bouton porte 44 px : c'est une action principale, tapee a une main, et
   DESIGN.md borne toute cible a 40 px au minimum. */
.carte-retour { background: var(--carte2); border: 1px solid var(--bord); border-radius: var(--rayon-sm); padding: 14px; margin-bottom: 16px; }
.carte-retour-titre { font-size: 0.75rem; color: var(--texte-doux); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 6px; }
.carte-retour-phrase { margin: 0 0 10px; font-size: 0.8rem; line-height: 1.5; color: var(--texte-doux); }
.carte-retour textarea { width: 100%; box-sizing: border-box; padding: 10px; background: var(--carte); border: 1px solid var(--bord); border-radius: var(--rayon-sm); color: var(--texte); font-size: 0.9rem; resize: vertical; }
.carte-retour .btn { width: 100%; min-height: 44px; margin-top: 10px; }
/* L'echec ne chuchote pas : il porte la couleur de l'alerte, comme partout
   ailleurs. Un retour qui n'est pas arrive et qu'on croit arrive est exactement
   le defaut que ce chemin repare. */
.carte-retour-etat { margin-top: 10px; font-size: 0.8rem; line-height: 1.4; }
.carte-retour-etat[data-etat="ok"] { color: var(--or); font-weight: 700; }
.carte-retour-etat[data-etat="echec"] { color: var(--rouge); font-weight: 700; }
