/* ═══════════════════════════════════════════════════════════════════════
   LA FEUILLE DU MARCHÉ.

   ⚠ ELLE EST EXTRAITE DE `docs/maquette/index.html`, PAS RÉÉCRITE. Elle porte
   la totalité des corrections de l'audit de style (§34) — des contrastes
   remesurés, un anneau de focus qui était à 1,00:1, une requête de média
   placée après la règle qu'elle devait battre. Réécrire cette feuille depuis
   la maquette « au propre » reviendrait à réintroduire une dizaine de défauts
   qui ont coûté une campagne de mesures à trouver.

   La maquette reste la source : ce qui est corrigé ici doit l'être là-bas.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Jetons ─────────────────────────────────────────────────────────────
   Bleu cobalt et or Vault-Tec. Le bandeau garde le bleu dans les deux
   thèmes — c'est la signature, elle ne s'inverse pas ; seule la zone de
   travail change de fond. Clair = dossier imprimé, sombre = abri de nuit.

   `--ink-3` et `--gold` sont assombris par rapport au premier jet : ils
   portaient une vingtaine de sélecteurs sous le seuil de contraste.        */
:root {
  --ground:#E8EDF5; --surface:#FFFFFF; --raised:#F3F7FC; --plate:#DFE7F2;
  --line:#C6D4E6; --line-soft:#DEE7F2; --line-champ:#6B82A6;
  /* ⚠ --line-champ N'EST PAS --line, et l'écart est le sujet. Un filet
     décoratif sépare ; la bordure d'un champ de saisie DIT OÙ EST LE CHAMP,
     donc WCAG 1.4.11 lui demande 3:1 quand --line n'en donnait que 1,28
     contre l'intérieur du champ. Deux rôles, deux jetons. */
  --ink:#0C233F; --ink-2:#33506F; --ink-3:#52698A;
  --accent:#1B54A0; --accent-2:#123F7C; --on-accent:#FFFFFF;
  --gold:#8A6300; --gold-bg:#F6EBCF; --gold-rule:#C9950E; --on-gold:#0C233F;
  --good:#26663F; --bad:#992F24;
  /* Séries de graphique. Choisies par mode, jamais retournées, et passées au
     validateur (bande de clarté, plancher de chroma, écart CVD, plancher
     vision normale, contraste sur la surface) : l'or d'interface #EEBE45 est
     à L 0,82, hors bande — il éclaire un bouton, il ne peut pas porter une
     marque. La teinte suit l'ENTITÉ : l'offre est bleue et la demande dorée
     dans les deux thèmes. */
  --serie-1:#1B54A0; --serie-2:#B07A00;
  /* Le bandeau inter-sites a son propre fond, nettement plus sombre que celui
     du site : --chrome-2 en était trop proche et les deux barres se lisaient
     comme un seul bloc bleu. C'est l'écart qui fait comprendre qu'on a une
     barre de communauté AU-DESSUS d'un site, et pas deux navigations. */
  --xbar-bg:#0C233F;
  --serie-1-wash:rgba(27,84,160,.10);
  --chrome:#1B54A0; --chrome-2:#17488B; --on-chrome:#FFFFFF; --chrome-3:#C3D6EF;
  --f-display:"Jost","Noto Sans JP","Futura",sans-serif;
  --f-body:"Noto Sans","Noto Sans JP",system-ui,sans-serif;
  --f-mono:"JetBrains Mono",ui-monospace,Menlo,monospace;
  --r:4px; --maxw:1260px;
  --shadow:0 1px 2px rgba(12,35,63,.06), 0 12px 30px -22px rgba(12,35,63,.55);
}
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) {
  --ground:#08182C; --surface:#0E2340; --raised:#143053; --plate:#16355A;
  --line:#1F4370; --line-soft:#173458; --line-champ:#4A7DB8;
  --ink:#E9EFF8; --ink-2:#B4C6DC; --ink-3:#8CA4C0;
  --accent:#EEBE45; --accent-2:#F8D77E; --on-accent:#08182C;
  --gold:#EEBE45; --gold-bg:#25324A; --gold-rule:#EEBE45; --on-gold:#08182C;
  --good:#6FC48F; --bad:#F0847A;
  --serie-1:#4E8FD1; --serie-2:#AD8322;
  --xbar-bg:#04101F;
  --serie-1-wash:rgba(78,143,209,.14);
  --chrome:#0B2340; --chrome-2:#081C34; --on-chrome:#EAF1FA; --chrome-3:#A8C0DA;
  --shadow:0 1px 0 rgba(0,0,0,.35), 0 14px 34px -24px #000;
} }
:root[data-theme="dark"] {
  --ground:#08182C; --surface:#0E2340; --raised:#143053; --plate:#16355A;
  --line:#1F4370; --line-soft:#173458; --line-champ:#4A7DB8;
  --ink:#E9EFF8; --ink-2:#B4C6DC; --ink-3:#8CA4C0;
  --accent:#EEBE45; --accent-2:#F8D77E; --on-accent:#08182C;
  --gold:#EEBE45; --gold-bg:#25324A; --gold-rule:#EEBE45; --on-gold:#08182C;
  --good:#6FC48F; --bad:#F0847A;
  --serie-1:#4E8FD1; --serie-2:#AD8322;
  --xbar-bg:#04101F;
  --serie-1-wash:rgba(78,143,209,.14);
  --chrome:#0B2340; --chrome-2:#081C34; --on-chrome:#EAF1FA; --chrome-3:#A8C0DA;
  --shadow:0 1px 0 rgba(0,0,0,.35), 0 14px 34px -24px #000;
}

* { box-sizing:border-box; }
/* ⚠ LE PIED RESTE EN BAS DE L'ÉCRAN, MÊME SUR UNE PAGE COURTE. Sans cela, une
   page qui tient en trois lignes — l'accueil d'un site neuf, un résultat de
   recherche vide, une erreur — pose son pied au milieu de la fenêtre et laisse
   des centaines de pixels de fond nu en dessous. Ça ne ressemble pas à une
   page courte : ça ressemble à une page cassée.
   `main` en `flex:1` occupe la place restante ; les bandes pleine largeur
   (en-tête, onglets, pied) gardent leur largeur, `align-items` valant
   `stretch` par défaut en colonne. */
body { margin:0; background:var(--ground); color:var(--ink);
  font-family:var(--f-body); font-size:15px; line-height:1.55; -webkit-font-smoothing:antialiased;
  min-height:100vh; display:flex; flex-direction:column; }
body > main { flex:1 0 auto; }
body > footer { flex-shrink:0; }
:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
/* ⚠ DANS L'EN-TÊTE, --accent VAUT --chrome : le trait générique y est de la
   même couleur que le fond sur lequel il tombe, soit 1,00:1 — le logo et
   « Mes annonces » n'avaient donc AUCUN focus visible en thème clair. Le piège
   vient de ce que deux jetons partagent une valeur ; il ne se lit pas dans la
   règle, il ne se voit qu'en mesurant le rendu. */
.bar :focus-visible { outline-color:#EEBE45; }

/* ── Bandeau de maquette — RETIRÉ ─────────────────────────────────────
   `.avis` annonçait « ceci est une maquette » en haut de la page de
   démonstration. Le site n'en est pas une, et une règle sans balise est une
   règle que le prochain lecteur essaie de comprendre. Elle reste dans
   `docs/maquette/index.html`, où elle sert. */

/* ── Chrome ──────────────────────────────────────────────────────────── */
.bar { position:sticky; top:0; z-index:20; background:var(--chrome);
  border-bottom:3px solid #EEBE45; color:var(--on-chrome); overflow:hidden; }
.bar::before { content:""; position:absolute; right:-70px; top:-130px; width:320px; height:320px;
  pointer-events:none; border:26px solid var(--on-chrome); border-radius:50%; opacity:.05; }
.bar-in { position:relative; max-width:var(--maxw); margin:0 auto; padding:13px 20px;
  display:flex; align-items:center; gap:18px; flex-wrap:wrap; }
.logo { display:flex; align-items:center; gap:11px; text-decoration:none; color:inherit; }
.logo svg { width:38px; height:38px; flex:none; color:#EEBE45; }
/* L'enseigne : le heaume marchand rond. Servi en WebP quand le navigateur le
   lit (voir <picture> dans base.html.twig), à hauteur fixe pour ne pas faire
   sauter le bandeau au chargement. */
.logo img { height:40px; width:auto; flex:none; display:block; }
.logo-txt { font-family:var(--f-display); font-size:26px; font-weight:800; letter-spacing:.015em; line-height:.92; }
.logo-txt em { display:block; font-style:italic; font-weight:500; font-size:11.5px;
  /* ⚠ #F1C95F, PAS L'OR DE MARQUE #EEBE45. À 11,5 px sur le bleu du chrome,
     celui-ci donne 4,28:1 pour un seuil de 4,5 — il manque de 0,22, ce qui ne
     se voit pas à l'œil et se mesure très bien. L'or de marque reste partout
     où il porte du GRAND texte ou un simple filet, où 3:1 suffit ; ici seul,
     il est éclairci du minimum qui fait passer le seuil. */
  letter-spacing:.01em; color:#F1C95F; margin-top:2px; }

.search { flex:1 1 210px; position:relative; min-width:180px; }
.search input { width:100%; background:rgba(255,255,255,.12); color:var(--on-chrome);
  border:1px solid rgba(255,255,255,.28); border-radius:var(--r);
  padding:9px 12px 9px 34px; font:inherit; font-size:14px; }
.search input::placeholder { color:#CBDCF2; }
.search input:focus-visible { outline:2px solid #EEBE45; outline-offset:1px; background:rgba(255,255,255,.18); }
.search svg { position:absolute; left:10px; top:50%; transform:translateY(-50%); color:#CBDCF2; }

.me { display:flex; align-items:center; gap:9px; font-size:13px; }
.me-btn { appearance:none; background:none; border:0; padding:0; color:inherit; font:inherit;
  display:flex; align-items:center; gap:9px; cursor:pointer; text-align:left; }
.me-btn:hover .me-nom { text-decoration:underline; }
.me-av { width:32px; height:32px; border-radius:3px; flex:none; background:#EEBE45; color:#0C233F;
  display:grid; place-items:center; font-family:var(--f-display); font-weight:800; font-size:16px; }
.me-nom { font-weight:700; }
.me small { display:block; color:#CBDCF2; font-size:11px; }

.langs { display:flex; border:1px solid rgba(255,255,255,.3); border-radius:var(--r); overflow:hidden; }
.langs button { appearance:none; background:transparent; border:0;
  border-right:1px solid rgba(255,255,255,.2); color:#DCE9F8;
  font-family:var(--f-display); font-size:13px; font-weight:600; letter-spacing:.1em;
  padding:8px 11px; cursor:pointer; transition:background .12s, color .12s; }
.langs button:last-child { border-right:0; }
.langs button:hover { background:rgba(255,255,255,.14); color:#fff; }
.langs button[aria-pressed="true"] { background:#EEBE45; color:#0C233F; }
.langs button:focus-visible { outline:2px solid #EEBE45; outline-offset:-3px; }
.langs button[aria-pressed="true"]:focus-visible { outline-color:#0C233F; }

/* ── Bandeau inter-sites ─────────────────────────────────────────────────
   Adapté de css/xbar.css (Fallout Maps). La carte n'a qu'un thème et pose des
   couleurs en dur ; ici tout passe par les jetons, donc le bandeau suit la
   bascule clair/sombre sans seconde feuille.

   Il est plus SOMBRE que le bandeau du site (--chrome-2 contre --chrome) :
   c'est ce qui le fait lire comme une barre de système posée au-dessus, et non
   comme une seconde navigation du marché. */
.xbar { display:flex; align-items:center; gap:3px; height:34px; padding:0 12px;
  background:var(--xbar-bg); color:var(--chrome-3); border-bottom:1px solid rgba(238,190,69,.28);
  font-family:var(--f-mono); font-size:12.5px; line-height:1; letter-spacing:.04em;
  user-select:none; z-index:1500; }
/* ⚠ LE BANDEAU NE COLLE PAS, et c'est délibéré. Il l'a fait, à top:0, en même
   temps que l'en-tête du marché qui y colle aussi : les deux se superposaient,
   le bandeau passant devant (z-index 1500 contre 20) et masquant la moitié de
   l'enseigne dès qu'on faisait défiler. Un bandeau inter-sites est un panneau
   indicateur, pas une commande dont on a besoin en permanence — le laisser
   partir rend en prime 34 px de hauteur au téléphone. */
.xb-brand { display:flex; align-items:center; gap:8px; margin-right:16px; white-space:nowrap;
  font-family:var(--f-display); font-weight:700; letter-spacing:.1em; color:var(--gold-rule); }
.xbar a { color:var(--chrome-3); text-decoration:none; padding:5px 10px; border-radius:var(--r);
  white-space:nowrap; }
.xbar a:hover { background:rgba(238,190,69,.14); color:#fff; }
/* Le site courant : contraste plein, et `aria-current` le dit aussi. */
.xbar a.actif { background:var(--gold-rule); color:#0C233F; font-weight:700; }
.xbar a:focus-visible { outline:2px solid var(--gold-rule); outline-offset:-2px; }
/* ⚠ UN TRAIT DE FOCUS DORÉ SUR UN FOND DORÉ FAIT 1,00:1 — c'est-à-dire aucun
   focus visible du tout, sur la commande SÉLECTIONNÉE, donc exactement celle
   où l'on se trouve. Le décalage négatif peint le trait à l'intérieur du
   bouton, contre son propre fond. Sur les commandes à fond plein, le trait
   passe donc à l'encre sombre. */
.xbar a.actif:focus-visible { outline-color:#0C233F; }
.xb-sep { opacity:.35; }
.xb-short { display:none; }
.xb-discord { margin-left:auto; display:inline-flex; align-items:center; gap:7px; font-size:12px;
  min-width:0; }
/* ⚠ LE BANDEAU NE POUSSE PLUS LE DOCUMENT. À 320 px il débordait de 12 px sur
   les sept écrans et dans les deux thèmes — un échec de WCAG 1.4.10 causé par
   le seul élément que j'avais ajouté. Il défile maintenant dans son propre
   cadre, ce que le critère autorise explicitement pour une région, alors qu'il
   interdit de le faire subir à la page. */
.xbar { overflow-x:auto; scrollbar-width:none; }
.xbar::-webkit-scrollbar { display:none; }
.xb-discord svg { width:17px; height:13px; flex:none; }
.xb-discord .xb-count b { font-weight:700; }
.xb-count[hidden] { display:none; }
.xb-dot { width:7px; height:7px; border-radius:50%; background:#7fbf5f;
  box-shadow:0 0 5px #7fbf5f; display:inline-block; }

@media (max-width:1080px) {
  /* Mêmes arbitrages que sur la carte : les libellés raccourcissent, la marque
     s'efface. Elle est la seule chose qu'on peut retirer sans rien perdre —
     les liens, eux, sont la raison d'être du bandeau.

     ⚠ 1080 px, PAS 768. Le seuil avait été posé à 768 sans mesurer ce que le
     bandeau demande réellement en version longue : 1072 px. Entre 769 et 1071,
     il passait donc en version longue dans une fenêtre trop étroite pour elle,
     et c'est la PAGE qui défilait — une bande de 300 px de large où le site
     était cassé, entre deux largeurs où il ne l'était pas. Un point de rupture
     se mesure, il ne se choisit pas. */
  .xb-long { display:none; }
  .xb-short { display:inline; }
  .xb-brand { display:none; }
  .xbar { padding:0 8px; gap:1px; }
  .xbar a { padding:5px 7px; }
  .xb-discord .xb-join { display:none; }
}

.langues { display:flex; align-items:center; gap:9px; }
.lang-jeu { display:flex; align-items:center; gap:6px; }
.lang-jeu > span { font-family:var(--f-display); font-size:9.5px; letter-spacing:.14em;
  text-transform:uppercase; font-weight:700; color:#CBDCF2; white-space:nowrap; }
.lang-jeu select { appearance:none; font-family:var(--f-display); font-size:12.5px; font-weight:600;
  background:rgba(255,255,255,.08); color:#fff; border:1px solid rgba(255,255,255,.3);
  border-radius:var(--r); padding:7px 24px 7px 10px; cursor:pointer; max-width:170px;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' fill='none' stroke='%23DCE9F8' stroke-width='1.6'/></svg>");
  background-repeat:no-repeat; background-position:right 8px center; }
.lang-jeu select:hover { background-color:rgba(255,255,255,.16); }
.lang-jeu select:focus-visible { outline:2px solid #EEBE45; outline-offset:1px; }
/* Le navigateur peint la liste déroulante avec SES couleurs, pas celles du
   bandeau : sans cette règle, les options sont blanches sur blanc chez
   certains. */
.lang-jeu select option { background:var(--surface); color:var(--ink); }
.lang-jeu select option:disabled { color:var(--ink-3); }

.tabs { background:var(--chrome-2); }
.tabs-in { max-width:var(--maxw); margin:0 auto; padding:0 20px; display:flex; gap:2px; overflow-x:auto; }
/* ⚠ `a` AUTANT QUE `button`. Dans la maquette, les onglets étaient des
   boutons : une page unique, tout se jouait en JavaScript. Sur le site, ce
   sont des LIENS — ils mènent à des adresses, s'ouvrent dans un onglet, se
   collent dans un salon. Les deux sélecteurs cohabitent pour que la maquette
   reste juste ; l'état courant s'écrit `aria-current="page"` du côté des
   liens, `aria-selected` n'ayant de sens que dans un jeu d'onglets. */
.tabs button, .tabs a { appearance:none; background:none; border:0; border-bottom:3px solid transparent;
  color:#C3D6EF; font-family:var(--f-display); font-size:15px; font-weight:600;
  letter-spacing:.08em; text-transform:uppercase; padding:12px 15px 9px; cursor:pointer;
  white-space:nowrap; text-decoration:none; display:inline-block; }
.tabs button:hover, .tabs a:hover { color:#fff; }
.tabs button[aria-selected="true"],
.tabs a[aria-current="page"] { color:#EEBE45; border-bottom-color:#EEBE45; }
.tabs button:focus-visible, .tabs a:focus-visible { outline:2px solid #EEBE45; outline-offset:-4px; }

/* ── Ossature ────────────────────────────────────────────────────────── */
main { max-width:var(--maxw); margin:0 auto; padding:24px 20px 72px; }
.view[hidden] { display:none; }
.split { display:grid; grid-template-columns:238px minmax(0,1fr); gap:22px; align-items:start; }
@media (max-width:900px) { .split { grid-template-columns:1fr; } }

.eyebrow { font-family:var(--f-display); font-size:11.5px; font-weight:700;
  letter-spacing:.2em; text-transform:uppercase; color:var(--gold); margin:0 0 8px; }
h2.sect { font-family:var(--f-display); font-size:clamp(24px,5vw,33px); font-weight:700;
  margin:0 0 6px; letter-spacing:-.005em; line-height:1.1; text-wrap:balance; overflow-wrap:anywhere; }
.sub { color:var(--ink-2); font-size:13.5px; margin:0 0 22px; max-width:64ch; }

.panel { background:var(--surface); border:1px solid var(--line); border-radius:var(--r); box-shadow:var(--shadow); }
.panel-h { padding:11px 15px; border-bottom:1px solid var(--line); background:var(--raised);
  border-radius:var(--r) var(--r) 0 0; font-family:var(--f-display); font-size:13px; font-weight:700;
  letter-spacing:.12em; text-transform:uppercase; display:flex; justify-content:space-between;
  align-items:center; gap:10px; flex-wrap:wrap; }
.panel-h .note { font-family:var(--f-mono); font-size:10.5px; letter-spacing:0;
  text-transform:none; font-weight:400; color:var(--ink-3); }
.panel-b { padding:15px; }

.fgroup { border-top:1px solid var(--line-soft); padding-top:12px; margin-top:12px; }
.fgroup:first-child { border-top:0; padding-top:0; margin-top:0; }
.fgroup h3 { font-family:var(--f-display); font-size:11px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink-3); margin:0 0 8px; font-weight:700; }
.chips { display:flex; flex-wrap:wrap; gap:5px; }
.chip { appearance:none; font-family:var(--f-body); font-size:12px; cursor:pointer;
  background:var(--ground); color:var(--ink-2); border:1px solid var(--line-champ);
  border-radius:100px; padding:3.5px 11px; }
.chip:hover { border-color:var(--accent); color:var(--ink); }
.chip[aria-pressed="true"] { background:var(--accent); border-color:var(--accent);
  color:var(--on-accent); font-weight:600; }
.fnote { font-size:11.5px; color:var(--ink-3); line-height:1.45; }
.filters { position:sticky; top:78px; }
@media (max-width:900px) { .filters { position:static; } }

/* ── Boutons ─────────────────────────────────────────────────────────── */
.btn { appearance:none; font-family:var(--f-display); font-size:13.5px; font-weight:600;
  letter-spacing:.06em; text-transform:uppercase; cursor:pointer;
  background:var(--accent); color:var(--on-accent); border:1px solid var(--accent);
  border-radius:var(--r); padding:8px 15px; text-decoration:none; display:inline-flex;
  align-items:center; gap:7px; line-height:1.3; }
.btn:hover { background:var(--accent-2); border-color:var(--accent-2); }
.btn.ghost { background:transparent; color:var(--accent); }
.btn.ghost:hover { background:var(--gold-bg); color:var(--ink); border-color:var(--gold-rule); }
.btn.mini { font-size:11.5px; padding:5px 10px; }
.lien { appearance:none; background:none; border:0; padding:0; font:inherit; font-size:11.5px;
  color:var(--accent); cursor:pointer; text-decoration:underline; text-underline-offset:2px; }
.lien:hover { color:var(--accent-2); }
.lien.discret { color:var(--ink-3); }
.lien.discret:hover { color:var(--bad); }

/* ── Liste d'annonces ────────────────────────────────────────────────── */
.list-h { display:flex; justify-content:space-between; align-items:baseline; gap:14px;
  margin-bottom:13px; flex-wrap:wrap; }
.count { font-family:var(--f-display); font-size:20px; font-weight:600; }
.count b { color:var(--accent); font-variant-numeric:tabular-nums; font-weight:800; }
.tris { display:flex; gap:5px; flex-wrap:wrap; }

.cards { display:flex; flex-direction:column; gap:11px; }
.card { display:grid; grid-template-columns:92px minmax(0,1fr) auto; gap:15px;
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r);
  padding:13px; box-shadow:var(--shadow); transition:border-color .14s; }
.card:hover { border-color:var(--gold-rule); }
@media (max-width:640px) {
  .card { grid-template-columns:60px minmax(0,1fr); }
  .card .price-col { grid-column:1 / -1; text-align:left; align-items:flex-start;
    border-top:1px solid var(--line-soft); padding-top:11px; }
}
.thumb { aspect-ratio:1; background:var(--plate); border:1px solid var(--line-soft);
  border-radius:3px; display:grid; place-items:center; color:var(--accent); }
.thumb svg { width:60%; height:60%; }
/* L'illustration de fiche : la copie locale (§11) quand elle existe, sinon la
   silhouette. La case garde la même allure dans les deux cas. */
.illus { aspect-ratio:1; max-width:200px; background:var(--plate);
  border:1px solid var(--line-soft); border-radius:3px; overflow:hidden; }
.illus img { width:100%; height:100%; object-fit:contain; display:block; }

.card-top { display:flex; align-items:baseline; gap:9px; flex-wrap:wrap; }
.card-name { font-family:var(--f-display); font-size:22px; font-weight:700; line-height:1.14;
  letter-spacing:-.005em; margin:0; overflow-wrap:anywhere; }
/* ⚠ LE TITRE EST UN LIEN, ET IL NE DOIT PAS EN AVOIR L'AIR AVANT LE SURVOL.
   Souligné en bleu par défaut, il écrase la hiérarchie de la carte : le nom de
   l'objet doit se lire comme un titre, pas comme une action. Le survol et le
   focus le rendent au lien — et le focus, lui, reste toujours visible. */
.card-name a { color:inherit; text-decoration:none; }
.card-name a:hover { color:var(--accent); text-decoration:underline; text-underline-offset:3px; }
.meta a { color:var(--ink-2); text-decoration:none; border-bottom:1px solid var(--line); }
.meta a:hover { color:var(--accent); border-bottom-color:currentColor; }
.sens { font-family:var(--f-display); font-size:10.5px; font-weight:700; letter-spacing:.12em;
  text-transform:uppercase; padding:2px 8px; border-radius:100px; white-space:nowrap; }
.sens.vend { background:var(--accent); color:var(--on-accent); }
.sens.cherche { background:var(--gold-bg); color:var(--gold); border:1px solid var(--gold-rule); }
/* ⚠ PAS DE `.sens.echange`. Le §41 a supprimé « échange » comme DIRECTION :
   `annonce.sens` ne vaut plus que `vend` ou `cherche`, et le troc est devenu
   une DEVISE. Une règle qui décrit un état que la base refuse est pire
   qu'inutile — elle donne à croire que l'état existe encore. */

.formid { font-family:var(--f-mono); font-size:10.5px; color:var(--ink-3); letter-spacing:.03em; }
.formid b { color:var(--ink-2); font-weight:600; }

.stars { display:flex; flex-wrap:wrap; gap:5px; margin:9px 0 8px; }
.stars:empty { display:none; }
.star { display:inline-flex; align-items:center; gap:6px; font-size:12px;
  background:var(--gold-bg); color:var(--ink); border-radius:100px; padding:3px 10px 3px 8px; }
.star i { font-style:normal; font-family:var(--f-mono); font-size:10px; color:var(--gold); font-weight:600; }

.meta { display:flex; flex-wrap:wrap; gap:4px 13px; font-size:12px; color:var(--ink-3); align-items:center; }
.meta b { color:var(--ink-2); font-weight:600; }
.plat { font-family:var(--f-mono); font-size:10px; letter-spacing:.08em; border:1px solid var(--line);
  border-radius:2px; padding:1px 5px; color:var(--ink-2); }
.rep { color:var(--ink-2); font-weight:600; }

.rdv { display:flex; align-items:center; gap:6px; margin-top:7px; font-size:12px;
  color:var(--ink-2); flex-wrap:wrap; }
.rdv svg { width:13px; height:13px; color:var(--gold); flex:none; }
.rdv a { color:var(--accent); text-decoration:none; border-bottom:1px solid currentColor; font-size:11.5px; }
.rdv a:hover { color:var(--accent-2); }

.actions { display:flex; gap:8px; align-items:center; margin-top:10px; flex-wrap:wrap; }

.price-col { text-align:right; display:flex; flex-direction:column; align-items:flex-end;
  justify-content:space-between; gap:8px; min-width:150px; }
.price { font-family:var(--f-display); font-size:29px; font-weight:800; color:var(--accent);
  line-height:1; font-variant-numeric:tabular-nums; white-space:nowrap; letter-spacing:-.01em; }
.price small { font-family:var(--f-display); font-size:10.5px; font-weight:600; color:var(--ink-3);
  letter-spacing:.14em; text-transform:uppercase; display:block; margin-top:3px; }
.prix-lot { font-size:11.5px; color:var(--ink-3); font-variant-numeric:tabular-nums; }
/* Un écart est une donnée, pas un jugement : pas de vert, pas de rouge. §19. */
.vs-cote { font-size:11.5px; color:var(--ink-3); font-variant-numeric:tabular-nums; line-height:1.4; }
.vs-cote b { color:var(--ink-2); font-weight:700; }
.vs-cote .franc { color:var(--gold); font-weight:700; display:block; }
.troc { font-family:var(--f-display); font-size:20px; font-weight:700; color:var(--ink-2);
  line-height:1.1; text-transform:uppercase; letter-spacing:.06em; }

@keyframes flash { from { background:var(--gold-bg); } to { background:transparent; } }
.swapped { animation:flash .6s ease-out; border-radius:2px; }
@media (prefers-reduced-motion:reduce) { .swapped { animation:none; } }

/* ── Armurerie ───────────────────────────────────────────────────────── */
.arm-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(170px,1fr)); gap:10px; }
.arm-item { appearance:none; text-align:left; font:inherit; cursor:pointer; color:inherit;
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r);
  padding:10px; display:flex; flex-direction:column; gap:8px; transition:border-color .14s; }
.arm-item:hover { border-color:var(--gold-rule); }
.arm-item[aria-pressed="true"] { border-color:var(--accent); box-shadow:inset 0 0 0 1px var(--accent); }
.arm-ic { aspect-ratio:16/10; background:var(--plate); border-radius:3px; display:grid;
  place-items:center; color:var(--accent); }
.arm-ic svg { width:46%; height:70%; }
.arm-nom { font-family:var(--f-display); font-size:16px; font-weight:700; line-height:1.14;
  overflow-wrap:anywhere; }
.arm-sig { font-family:var(--f-mono); font-size:9.5px; color:var(--ink-3); letter-spacing:.04em;
  margin-top:auto; }

.conf { display:grid; grid-template-columns:minmax(0,1fr) 272px; gap:18px; align-items:start; }
@media (max-width:900px) { .conf { grid-template-columns:1fr; } }
.conf-head { display:grid; grid-template-columns:70px minmax(0,1fr) auto; gap:14px;
  align-items:center; margin-bottom:15px; }
/* ⚠ LA GRILLE PERD UNE COLONNE, PAS UN ENFANT. En passant de trois colonnes à
   deux, le bouton retombait seul sur la deuxième rangée, dans la colonne de
   56 px réservée à l'icône : 56 px de large pour un texte qui en demande 76,
   donc des mots peints hors de leur fond bleu. Il prend maintenant toute la
   largeur de la rangée. */
@media (max-width:560px) {
  .conf-head { grid-template-columns:56px minmax(0,1fr); }
  .conf-head > .btn { grid-column:1 / -1; justify-self:start; }
}
.conf-ic { aspect-ratio:1; background:var(--plate); border-radius:3px; display:grid;
  place-items:center; color:var(--accent); }
.conf-ic svg { width:60%; height:60%; }
.conf-nom { font-family:var(--f-display); font-size:clamp(21px,4.5vw,27px); font-weight:800;
  line-height:1.05; letter-spacing:-.01em; overflow-wrap:anywhere; }

.slots { display:grid; gap:7px; }
.slot { display:grid; grid-template-columns:38px minmax(0,1fr); gap:10px; align-items:center;
  border:1px solid var(--line); border-left:3px solid var(--gold-rule); border-radius:var(--r);
  padding:6px 10px; background:var(--ground); }
.slot-n { font-family:var(--f-mono); font-size:11px; color:var(--gold); font-weight:600; }
.slot select { width:100%; background:transparent; border:0; color:var(--ink); font:inherit;
  font-size:13.5px; padding:3px 0; }
.slot select:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.slot.empty { border-left-color:var(--line); }
.slot.empty .slot-n, .slot.empty select { color:var(--ink-3); }

/* Propriétés lues dans les records — la valeur elle-même est une entrée
   du catalogue, donc traduite. C'est l'argument le plus fort du projet,
   et il n'était affiché nulle part. */
.props { margin-top:13px; border:1px solid var(--line); border-radius:var(--r); overflow:hidden; }
.props-h { background:var(--raised); padding:7px 11px; font-family:var(--f-display); font-size:10.5px;
  font-weight:700; letter-spacing:.14em; text-transform:uppercase; color:var(--ink-3);
  border-bottom:1px solid var(--line); }
.props-l { display:grid; grid-template-columns:repeat(auto-fill,minmax(150px,1fr)); }
.prop { padding:7px 11px; border-top:1px solid var(--line-soft); border-right:1px solid var(--line-soft); }
.prop-k { font-size:10.5px; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-3); font-weight:700; }
.prop-v { font-size:14px; font-weight:600; font-variant-numeric:tabular-nums; overflow-wrap:anywhere; }
.prop-v.trad { color:var(--accent); }
.props-n { padding:9px 11px; border-top:1px solid var(--line-soft); font-size:11.5px; color:var(--ink-3); }

.empreinte { display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; margin-top:11px;
  font-size:11.5px; color:var(--ink-3); }
.empreinte code { font-family:var(--f-mono); font-size:11.5px; color:var(--ink-2); }
.empreinte button { font-size:11px; }

.repli { border:1px solid var(--line); border-left:3px solid var(--gold-rule);
  border-radius:var(--r); padding:11px 13px; font-size:12.5px; color:var(--ink-2); background:var(--ground); }
.repli b { color:var(--ink); display:block; margin-bottom:3px; }
.vide { border:1px dashed var(--line); border-radius:var(--r); padding:14px;
  font-size:13px; color:var(--ink-2); text-align:center; }

/* ── Formulaire ──────────────────────────────────────────────────────── */
.form-grid { display:grid; grid-template-columns:minmax(0,1fr) 330px; gap:22px; align-items:start; }
@media (max-width:940px) { .form-grid { grid-template-columns:1fr; } }
.field { margin-bottom:15px; }
.field > label { display:block; font-family:var(--f-display); font-size:11px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-3); font-weight:700; margin-bottom:6px; }
.field input[type=text], .field textarea, .field select { width:100%; background:var(--ground);
  color:var(--ink); font:inherit; font-size:14px; border:1px solid var(--line-champ);
  border-radius:var(--r); padding:9px 11px; }
.field textarea { min-height:70px; resize:vertical; }
.hint { font-size:11.5px; color:var(--ink-3); margin-top:6px; line-height:1.45; }
.hint.warn { color:var(--ink-2); border-left:2px solid var(--gold-rule); padding-left:9px; }
.row2 { display:grid; grid-template-columns:1fr 1fr; gap:13px; }
@media (max-width:480px) { .row2 { grid-template-columns:1fr; } }

.ac { border:1px solid var(--accent); border-top:0; border-radius:0 0 var(--r) var(--r);
  background:var(--surface); overflow:hidden; }
.rech-etat { display:flex; align-items:baseline; gap:10px; flex-wrap:wrap;
  border:1px solid var(--line); border-left:3px solid var(--accent); border-radius:var(--r);
  background:var(--surface); padding:9px 13px; margin-bottom:11px; font-size:13px; }
.ac-vide { padding:11px 13px; font-size:12.5px; color:var(--ink-3); line-height:1.5; }
.ac-vide b { display:block; color:var(--ink); font-size:13.5px; margin-bottom:2px; }
.ac-via { font-family:var(--f-mono); font-size:9.5px; letter-spacing:.06em; color:var(--on-accent);
  background:var(--accent); border-radius:2px; padding:0 4px; margin-right:4px; }
button.ac-row { width:100%; text-align:left; font:inherit; color:inherit; cursor:pointer;
  background:var(--surface); border:0; }
button.ac-row:hover:not(:disabled) { background:var(--gold-bg); }
button.ac-row:disabled { cursor:default; }
button.ac-row:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
.ac-row { display:grid; grid-template-columns:32px minmax(0,1fr) auto; gap:11px; align-items:center;
  padding:8px 11px; border-top:1px solid var(--line-soft); }
.ac-row:first-child { border-top:0; }
.ac-ic { width:30px; height:30px; background:var(--plate); border-radius:3px; display:grid;
  place-items:center; color:var(--accent); }
.ac-ic svg { width:19px; height:19px; }
.ac-n { font-weight:600; font-size:14px; display:block; overflow-wrap:anywhere; }
.ac-alt { font-size:11.5px; color:var(--ink-3); }
.ac-alt em { font-style:normal; color:var(--ink-2); }
.ac-row.hs { background:var(--ground); }
.ac-row.hs .ac-n, .ac-row.hs .formid { color:var(--ink-3); text-decoration:line-through; text-decoration-thickness:1px; }
.ac-row.hs .ac-ic { opacity:.5; }
.hs-tag { font-family:var(--f-display); font-size:10px; font-weight:700; letter-spacing:.1em;
  text-transform:uppercase; color:var(--gold); border:1px solid var(--gold-rule);
  border-radius:100px; padding:0 6px; margin-right:5px; }

.barre { display:flex; gap:12px; align-items:center; flex-wrap:wrap;
  border-top:1px solid var(--line); background:var(--raised); padding:13px 15px;
  border-radius:0 0 var(--r) var(--r); }
.barre .recap { flex:1 1 240px; font-size:12px; color:var(--ink-2); line-height:1.45; }
.barre .recap b { color:var(--ink); }

.preview { position:sticky; top:78px; display:flex; flex-direction:column; gap:12px; }
@media (max-width:940px) { .preview { position:static; } }
.pv-card { border:1px solid var(--line); border-left:3px solid var(--accent); border-radius:var(--r);
  background:var(--ground); padding:10px 12px; }
.pv-lang { font-family:var(--f-mono); font-size:10px; letter-spacing:.1em; color:var(--ink-3);
  margin-bottom:4px; display:flex; justify-content:space-between; }
.pv-nom { font-family:var(--f-display); font-size:19px; font-weight:700; line-height:1.15; overflow-wrap:anywhere; }
.pv-eff { font-size:12px; color:var(--ink-2); margin-top:3px; }
.pv-prix { font-family:var(--f-mono); font-size:12px; color:var(--accent); margin-top:6px; font-weight:600; }

/* ── Vendeur ─────────────────────────────────────────────────────────── */
.seller-head { display:grid; grid-template-columns:72px minmax(0,1fr) auto; gap:16px; align-items:center; }
@media (max-width:700px) { .seller-head { grid-template-columns:56px minmax(0,1fr); } }
.seller-av { aspect-ratio:1; background:var(--accent); color:var(--on-accent); border-radius:3px;
  display:grid; place-items:center; font-family:var(--f-display); font-size:32px; font-weight:800; }
.seller-nom { font-family:var(--f-display); font-size:clamp(23px,5vw,32px); font-weight:800;
  line-height:1.02; letter-spacing:-.01em; overflow-wrap:anywhere; }
/* §16 : vérifié et déclaré ne s'affichent pas pareil. */
.faits { display:flex; flex-wrap:wrap; gap:6px; margin-top:8px; }
.fait { display:inline-flex; align-items:center; gap:6px; font-size:12px; border-radius:100px;
  padding:2.5px 10px; border:1px solid var(--line); background:var(--ground); color:var(--ink-2); }
.fait.verifie { border-color:var(--accent); }
.fait .tag { font-family:var(--f-mono); font-size:9px; letter-spacing:.06em; text-transform:uppercase; }
.fait.verifie .tag { color:var(--accent); }
.fait.declare .tag { color:var(--ink-3); }
.fait code { font-family:var(--f-mono); font-size:12px; color:var(--ink); }

.repbar { height:9px; border-radius:100px; overflow:hidden; display:flex; background:var(--plate); }
.repbar i { display:block; }
.repnums { display:flex; gap:14px; font-size:12.5px; margin-top:8px; color:var(--ink-3);
  font-variant-numeric:tabular-nums; flex-wrap:wrap; }
.dot { display:inline-block; width:7px; height:7px; border-radius:50%; margin-right:5px; vertical-align:1px; }

.avis-list { display:flex; flex-direction:column; }
.avis-item { display:grid; grid-template-columns:auto minmax(0,1fr) auto; gap:12px; padding:12px 0;
  border-top:1px solid var(--line-soft); align-items:start; }
.avis-item:first-child { border-top:0; padding-top:0; }
.avis-mark { font-family:var(--f-mono); font-size:15px; font-weight:600; width:18px; text-align:center; }
.avis-corps { font-size:13.5px; }
.avis-lang { display:inline-block; font-family:var(--f-mono); font-size:9.5px; letter-spacing:.06em;
  text-transform:uppercase; color:var(--ink-3); border:1px solid var(--line); border-radius:2px;
  padding:0 4px; margin-left:6px; vertical-align:1px; }
.avis-qui { font-size:11.5px; color:var(--ink-3); margin-top:2px; display:block; }
.avis-quand { font-size:11px; color:var(--ink-3); white-space:nowrap; font-variant-numeric:tabular-nums; }

/* ── Cote ────────────────────────────────────────────────────────────── */
.cote-top { display:grid; grid-template-columns:minmax(0,1fr) 262px; gap:22px; align-items:start; }
@media (max-width:860px) { .cote-top { grid-template-columns:1fr; } }
.stat { display:flex; flex-direction:column; gap:1px; padding:12px 0; border-top:1px solid var(--line-soft); }
.stat:first-child { border-top:0; padding-top:0; }
.stat-k { font-family:var(--f-display); font-size:10.5px; letter-spacing:.15em; text-transform:uppercase;
  color:var(--ink-3); font-weight:700; }
.stat-v { font-family:var(--f-display); font-size:26px; font-weight:700; line-height:1.1;
  font-variant-numeric:tabular-nums; }
.stat-v.acc { color:var(--accent); }
.stat-n { font-size:11.5px; color:var(--ink-3); }
.chart { width:100%; height:auto; display:block; }
.legend { display:flex; gap:16px; flex-wrap:wrap; font-size:11.5px; color:var(--ink-3); margin-top:10px; }
.legend i { display:inline-block; width:13px; height:3px; vertical-align:3px; margin-right:6px; }
.variante { margin-top:26px; border-top:2px dashed var(--line); padding-top:18px; }
.variante > p { font-family:var(--f-display); font-size:11px; letter-spacing:.15em;
  text-transform:uppercase; color:var(--ink-3); font-weight:700; margin:0 0 10px; }

.garantie { border:1px solid var(--gold-rule); background:var(--gold-bg); border-radius:var(--r);
  padding:12px 14px; font-size:13px; color:var(--ink); }
.garantie b { display:block; font-family:var(--f-display); font-size:12px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--gold); margin-bottom:4px; }

/* ── Boutique ────────────────────────────────────────────────────────────
   Le profil EST une boutique. Elle se personnalise par CHOIX DANS LE
   CATALOGUE — emblème, vitrine, CAMP, rayons — donc sans créer un seul
   texte à traduire ni une seule image à modérer. §25.               */
.btq { border-radius:var(--r); overflow:hidden; border:1px solid var(--line); box-shadow:var(--shadow); }
.btq-h { padding:22px 24px; color:#fff; position:relative; overflow:hidden;
  display:grid; grid-template-columns:auto minmax(0,1fr) auto; gap:20px; align-items:center; }
@media (max-width:700px) { .btq-h { grid-template-columns:auto minmax(0,1fr); padding:16px; } }
.btq-h::before { content:""; position:absolute; right:-50px; top:-90px; width:240px; height:240px;
  border:20px solid #fff; border-radius:50%; opacity:.07; pointer-events:none; }
.btq-embleme { width:74px; height:74px; border-radius:50%; display:grid; place-items:center;
  background:rgba(255,255,255,.14); border:2px solid rgba(255,255,255,.5); flex:none;
  font-family:var(--f-display); font-size:30px; font-weight:800; }
@media (max-width:700px) { .btq-embleme { width:52px; height:52px; font-size:22px; } }
.btq-nom { font-family:var(--f-display); font-size:clamp(24px,5vw,34px); font-weight:800;
  line-height:1.05; overflow-wrap:anywhere; }
.btq-tenu { font-size:12.5px; opacity:.9; margin-top:2px; }
.btq-devise { font-family:var(--f-display); font-style:italic; font-size:14.5px; margin-top:6px;
  opacity:.95; display:flex; align-items:baseline; gap:7px; flex-wrap:wrap; }
.btq-devise .lang { font-family:var(--f-mono); font-style:normal; font-size:9px; letter-spacing:.06em;
  text-transform:uppercase; border:1px solid currentColor; border-radius:2px; padding:0 4px; opacity:.75; }
.btq-etat { display:flex; flex-direction:column; align-items:flex-end; gap:5px; }
.btq-pastille { font-family:var(--f-display); font-size:10.5px; font-weight:700; letter-spacing:.12em;
  text-transform:uppercase; border-radius:100px; padding:3px 11px; background:rgba(255,255,255,.18);
  border:1px solid rgba(255,255,255,.4); white-space:nowrap; }
.btq-pastille.ouverte { background:#fff; color:#0C233F; border-color:#fff; }
.btq-faction { font-size:11.5px; opacity:.85; }
/* ⚠ `.plat` EST DESSINÉ POUR LA SURFACE CLAIRE D'UNE CARTE, pas pour le
   bandeau coloré d'une boutique : `--ink-2` sur un dégradé sombre donnait un
   badge quasi invisible, mesuré au rendu. Le bandeau porte ses propres
   couleurs dans les deux thèmes du site — c'est l'identité de la boutique,
   elle ne s'inverse pas — donc le badge aussi. */
.btq-h .plat { color:#fff; border-color:rgba(255,255,255,.55); }

.btq-nav { display:flex; justify-content:space-between; align-items:center; gap:12px;
  margin-top:14px; flex-wrap:wrap; }
.perso { display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr)); gap:14px;
  border:1px solid var(--gold-rule); border-left:3px solid var(--gold-rule);
  border-radius:var(--r); background:var(--surface); padding:15px; margin-top:14px; }
.perso .field { margin:0; }
.perso-note { grid-column:1/-1; font-size:12px; color:var(--ink-2); border-top:1px solid var(--line-soft);
  padding-top:11px; line-height:1.5; }
.themes { display:flex; gap:6px; flex-wrap:wrap; }
.theme-b { width:30px; height:30px; border-radius:50%; border:2px solid var(--line); cursor:pointer;
  padding:0; }
.theme-b[aria-pressed="true"] { border-color:var(--ink); box-shadow:0 0 0 2px var(--surface), 0 0 0 4px var(--accent); }

.rayon-h { display:flex; align-items:baseline; gap:10px; margin:0 0 10px; }
.rayon-h h3 { font-family:var(--f-display); font-size:20px; font-weight:700; margin:0; letter-spacing:.01em; }
.rayon-h span { font-size:12px; color:var(--ink-3); }

/* ── Messagerie ──────────────────────────────────────────────────────── */
.msg-grid { display:grid; grid-template-columns:280px minmax(0,1fr); gap:18px; align-items:start; }
@media (max-width:860px) { .msg-grid { grid-template-columns:1fr; } }
.fil-item { display:block; width:100%; text-align:left; font:inherit; color:inherit; cursor:pointer;
  background:none; border:0; border-bottom:1px solid var(--line-soft); padding:11px 14px; }
.fil-item:hover { background:var(--raised); }
.fil-item[aria-pressed="true"] { background:var(--gold-bg); box-shadow:inset 3px 0 0 var(--accent); }
.fil-qui { font-weight:700; font-size:14px; }
.fil-obj { font-size:12.5px; color:var(--ink-2); margin-top:1px; overflow-wrap:anywhere; }
.fil-etat { font-size:11.5px; color:var(--ink-3); margin-top:3px; display:flex; gap:6px; align-items:center; flex-wrap:wrap; }

.fil { display:flex; flex-direction:column; gap:10px; margin:14px 0; }
.bulle { max-width:78%; border-radius:var(--r); padding:9px 12px; font-size:13.5px; line-height:1.5; }
.bulle.eux { align-self:flex-start; background:var(--ground); border:1px solid var(--line); }
.bulle.moi { align-self:flex-end; background:var(--accent); color:var(--on-accent); border:1px solid var(--accent); }
.bulle-h { font-size:10.5px; opacity:.75; margin-bottom:3px; display:flex; gap:7px; align-items:baseline; }
.bulle .lang { font-family:var(--f-mono); font-size:9.5px; letter-spacing:.06em; text-transform:uppercase;
  border:1px solid currentColor; border-radius:2px; padding:0 4px; opacity:.8; }

/* Un message STRUCTURÉ : il ne porte pas de phrase, il porte une entrée du
   catalogue. C'est ce qui le rend lisible dans les onze langues. */
.bulle.structure { max-width:100%; align-self:stretch; background:var(--surface);
  border:1px solid var(--gold-rule); border-left:3px solid var(--gold-rule); color:var(--ink); }
.bulle.structure .quoi { font-family:var(--f-display); font-size:11px; letter-spacing:.13em;
  text-transform:uppercase; color:var(--gold); font-weight:700; }
.bulle.structure .lieu { display:flex; align-items:center; gap:8px; font-family:var(--f-display);
  font-size:19px; font-weight:700; margin-top:3px; overflow-wrap:anywhere; }
.bulle.structure .lieu svg { width:16px; height:16px; color:var(--gold); flex:none; }

.rdv-carte { border:1px solid var(--line); border-radius:var(--r); overflow:hidden; background:var(--ground); }
.rdv-h { padding:9px 13px; background:var(--raised); border-bottom:1px solid var(--line);
  display:flex; justify-content:space-between; align-items:center; gap:10px; flex-wrap:wrap;
  font-family:var(--f-display); font-size:11px; letter-spacing:.13em; text-transform:uppercase; font-weight:700; }
.rdv-b { display:grid; grid-template-columns:200px minmax(0,1fr); gap:14px; padding:13px; align-items:center; }
@media (max-width:620px) { .rdv-b { grid-template-columns:1fr; } }
.vignette { aspect-ratio:16/11; background:var(--plate); border:1px solid var(--line-soft);
  border-radius:3px; position:relative; overflow:hidden; }
.vignette svg { width:100%; height:100%; display:block; }
.vignette figcaption { position:absolute; left:0; right:0; bottom:0; font-size:9.5px; text-align:center;
  color:var(--ink-3); background:color-mix(in srgb, var(--ground) 78%, transparent); padding:2px 0; }
.rdv-nom { font-family:var(--f-display); font-size:22px; font-weight:800; line-height:1.1; overflow-wrap:anywhere; }
.rdv-n { font-size:12px; color:var(--ink-3); margin-top:4px; line-height:1.45; }

.ecrire { display:flex; gap:8px; align-items:center; flex-wrap:wrap;
  border-top:1px solid var(--line); padding-top:13px; }
.ecrire input { flex:1 1 180px; background:var(--ground); color:var(--ink); font:inherit; font-size:14px;
  border:1px solid var(--line); border-radius:var(--r); padding:9px 11px; }

/* ── Panel d'administration ──────────────────────────────────────────── */
.acces { display:flex; align-items:baseline; gap:10px; flex-wrap:wrap;
  border:1px solid var(--accent); border-left:3px solid var(--accent); border-radius:var(--r);
  background:var(--surface); padding:10px 14px; margin-bottom:16px; font-size:13px; }
.acces b { font-family:var(--f-display); font-size:11px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--accent); }
.acces span.d { color:var(--ink-3); font-size:12px; }
.adm-nav { display:flex; gap:4px; flex-wrap:wrap; margin-bottom:18px; }
.adm-nav button { appearance:none; font-family:var(--f-display); font-size:13px; font-weight:600;
  letter-spacing:.06em; text-transform:uppercase; cursor:pointer; background:var(--surface);
  color:var(--ink-2); border:1px solid var(--line); border-radius:var(--r); padding:7px 13px; }
.adm-nav button:hover { border-color:var(--accent); color:var(--ink); }
.adm-nav button[aria-pressed="true"] { background:var(--accent); border-color:var(--accent); color:var(--on-accent); }
.adm-sec[hidden] { display:none; }
.tuiles { display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:12px; margin-bottom:18px; }
.tuile { background:var(--surface); border:1px solid var(--line); border-left:3px solid var(--line);
  border-radius:var(--r); padding:13px 15px; box-shadow:var(--shadow); }
.tuile.ok { border-left-color:var(--good); }
.tuile.attention { border-left-color:var(--gold-rule); }
.tuile.err { border-left-color:var(--bad); }
.tuile-k { font-family:var(--f-display); font-size:10.5px; letter-spacing:.15em; text-transform:uppercase;
  color:var(--ink-3); font-weight:700; }
.tuile-v { font-family:var(--f-display); font-size:26px; font-weight:800; line-height:1.1;
  font-variant-numeric:tabular-nums; margin:2px 0; }
.tuile-n { font-size:11.5px; color:var(--ink-3); line-height:1.4; }
table.adm { width:100%; border-collapse:collapse; font-size:13.5px; }
table.adm th { text-align:left; font-family:var(--f-display); font-size:10.5px; letter-spacing:.13em;
  text-transform:uppercase; color:var(--ink-3); font-weight:700; padding:0 10px 8px; }
table.adm td { padding:9px 10px; border-top:1px solid var(--line-soft); vertical-align:top; }
table.adm td.n { text-align:right; font-variant-numeric:tabular-nums; font-weight:600; white-space:nowrap; }
table.adm td.motif { font-family:var(--f-mono); font-size:11.5px; color:var(--ink-3); }
.wiki { display:flex; align-items:baseline; gap:9px; flex-wrap:wrap; margin-top:14px;
  padding-top:12px; border-top:1px solid var(--line-soft); font-size:12.5px; }
.wiki .wiki-n { color:var(--ink-3); font-size:11.5px; }
.wiki.sans { color:var(--ink-3); font-style:italic; }
.marq { font-family:var(--f-display); font-size:9.5px; letter-spacing:.13em; text-transform:uppercase;
  font-weight:700; border:1px solid var(--line); border-radius:100px; padding:2px 7px; color:var(--ink-3); }
.marq.manuel { border-color:var(--good); color:var(--good); }
.marq.auto   { border-color:var(--line); color:var(--ink-3); }
.marq.absent { border-color:var(--line); color:var(--ink-3); }
.marq.mort   { border-color:var(--bad); color:var(--bad); }
/* ── Graphiques ──────────────────────────────────────────────────────── */
/* Un viewBox fixe rétrécit TOUT, texte compris : à 390 px les six graphiques
   tombaient à 0,51 d'échelle, soit 5,1 px de texte effectif — mesuré, pas
   estimé. Une vignette illisible n'est pas une version mobile.

   Le graphique garde donc sa largeur minimale et DÉFILE dans son propre cadre.
   C'est le conteneur qui défile, jamais la page : `overflow-x` est sur `.gfx`,
   et le corps du document reste sans débordement horizontal. */
/* Un enfant de grille ou de flex vaut `min-width:auto` par défaut : il grandit
   pour tenir son contenu au lieu de rétrécir. Le cadre à défilement ne pouvait
   donc pas se contraindre, et c'était la PAGE qui débordait — le contraire de
   ce qu'on cherchait. Un `min-width:0` sur le panneau rend la main au cadre. */
.panel { min-width:0; }
.gfx { position:relative; overflow-x:auto; overflow-y:hidden;
  -webkit-overflow-scrolling:touch; }
.gfx svg { width:100%; min-width:600px; height:auto; display:block; }
/* `overflow:visible` sur le SVG et `overflow-x:auto` sur le parent se
   contredisent : les étiquettes qui débordaient à droite seraient rognées.
   Elles tiennent désormais dans le viewBox — voir la marge droite des rendus. */
@media (max-width:700px) {
  .gfx { border:1px solid var(--line-soft); border-radius:var(--r); }
  .gfx::after { content:""; }
}
/* L'infobulle du survol : un graphique HTML EST interactif, s'en priver
   revient à publier une image.
   ⚠ ELLE S'APPELLE .gbulle, PAS .bulle. Elle a porté ce second nom, et comme
   les messages d'un fil s'appellent aussi des bulles, la règle la plus basse
   gagnait : les onze bulles du fil héritaient de position:absolute et
   opacity:0, et l'écran Messages se rendait avec une hauteur de zéro. Le texte
   était dans le DOM, donc tout harnais qui lisait innerText le trouvait — le
   défaut ne se voyait qu'en mesurant une BOÎTE. Deux composants distincts ne
   partagent pas un nom parce qu'ils se ressemblent. */
.gbulle { position:absolute; pointer-events:none; opacity:0; transition:opacity .1s;
  max-width:min(260px, 88vw);
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r);
  box-shadow:var(--shadow); padding:7px 10px; font-size:12.5px; white-space:nowrap;
  transform:translate(-50%,-115%); z-index:5; }
.gbulle.on { opacity:1; }
.gbulle b { font-family:var(--f-mono); font-size:13px; }
.gbulle i { display:inline-block; width:9px; height:9px; border-radius:2px;
  margin-right:6px; vertical-align:baseline; font-style:normal; }
.gbulle .d { color:var(--ink-3); font-size:11.5px; }
/* La vue tableau : l'identité ne doit jamais tenir à la seule couleur, et
   des chiffres se lisent parfois mieux qu'une courbe. */
.gfx-tab { width:100%; border-collapse:collapse; font-size:13px; margin-top:12px; }
.gfx-tab th { text-align:left; font-family:var(--f-display); font-size:10px;
  letter-spacing:.13em; text-transform:uppercase; color:var(--ink-3);
  font-weight:700; padding:0 9px 7px; }
.gfx-tab td { padding:7px 9px; border-top:1px solid var(--line-soft);
  font-variant-numeric:tabular-nums; }
.gfx-tab td:first-child { font-variant-numeric:normal; }
.gfx-bascule { appearance:none; background:none; border:0; padding:0; margin-top:10px;
  color:var(--accent); font:inherit; font-size:12.5px; cursor:pointer;
  text-decoration:underline; text-underline-offset:3px; }
.stats-2 { display:grid; grid-template-columns:repeat(auto-fit,minmax(320px,1fr)); gap:16px; }
@media (max-width:700px) { .stats-2 { grid-template-columns:1fr; } }

.btq-signaler { appearance:none; background:rgba(255,255,255,.14); border:1px solid rgba(255,255,255,.3);
  border-radius:var(--r); color:#fff; font:inherit; font-size:11.5px; padding:3px 9px;
  cursor:pointer; margin-top:6px; }
.btq-signaler:hover { background:rgba(255,255,255,.26); }

/* La fenêtre d'une statistique se lit AVEC elle, jamais ailleurs. */
.fen { display:inline-block; margin-left:6px; padding:1px 6px; border-radius:100px;
  border:1px solid var(--line); background:var(--raised); color:var(--ink-3);
  font-family:var(--f-body); font-size:10px; font-weight:600; letter-spacing:.02em;
  text-transform:none; vertical-align:middle; }

.uni { margin:-6px 0 12px; padding:7px 10px; border-radius:var(--r);
  background:var(--gold-bg); border-left:3px solid var(--gold-rule);
  color:var(--ink-2); font-size:12.5px; }
.uni b { font-family:var(--f-mono); font-weight:700; color:var(--gold); }

/* ── Recours : bloquer, signaler, quitter ────────────────────────────── */
.recours { display:flex; gap:6px; flex-wrap:wrap; align-items:center;
  padding:8px 15px; border-bottom:1px solid var(--line-soft); background:var(--surface); }
.recours button { appearance:none; background:none; border:1px solid var(--line);
  border-radius:var(--r); color:var(--ink-3); font:inherit; font-size:12px;
  padding:4px 9px; cursor:pointer; }
.recours button:hover { border-color:var(--bad); color:var(--bad); }
.recours .r-note { color:var(--ink-3); font-size:11.5px; margin-left:auto; }
.recours .r-fait { color:var(--good); font-size:12px; font-weight:600; }

.jauge { height:6px; border-radius:100px; background:var(--plate); overflow:hidden; margin-top:5px; }
.jauge i { display:block; height:100%; background:var(--accent); }
.reglage { display:grid; grid-template-columns:minmax(0,1fr) 110px auto; gap:12px; align-items:center;
  padding:11px 0; border-top:1px solid var(--line-soft); }
.reglage:first-child { border-top:0; }
.reglage-n { font-size:11.5px; color:var(--ink-3); margin-top:2px; }
.reglage input { width:100%; background:var(--ground); color:var(--ink); font:inherit; font-size:14px;
  border:1px solid var(--line); border-radius:var(--r); padding:6px 9px; text-align:right;
  font-variant-numeric:tabular-nums; }
.source { font-family:var(--f-mono); font-size:9.5px; letter-spacing:.06em; text-transform:uppercase;
  border:1px solid var(--line); border-radius:2px; padding:1px 5px; color:var(--ink-3); white-space:nowrap; }
.source.base { border-color:var(--accent); color:var(--accent); }

footer { background:var(--chrome-2); color:var(--chrome-3); border-top:3px solid #EEBE45; }
.foot-in { max-width:var(--maxw); margin:0 auto; padding:20px; font-size:12px; display:flex;
  gap:20px; flex-wrap:wrap; justify-content:space-between; align-items:center; }
.foot-in em { font-family:var(--f-display); font-style:italic; font-size:13px; color:#EEBE45; }
/* Les conditions doivent être atteignables depuis N'IMPORTE QUELLE page — un
   texte qu'on ne trouve qu'en le cherchant n'a pas été porté à connaissance.
   Le pied est le seul élément commun aux sept écrans. */
.foot-liens { display:flex; gap:16px; flex-wrap:wrap; }
.foot-liens a { color:var(--chrome-3); text-decoration:underline; text-underline-offset:3px; }
.foot-liens a:hover { color:#EEBE45; }
/* Masqué à l'œil, présent pour l'assistance. Surtout pas display:none, qui le
   retirerait aussi de l'arbre d'accessibilité — donc du sommaire des titres. */
.hors-ecran { position:absolute; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip-path:inset(50%); white-space:nowrap; border:0; }
.evite { position:absolute; left:8px; top:-60px; z-index:3000; background:var(--surface);
  color:var(--ink); border:2px solid var(--accent); border-radius:var(--r);
  padding:10px 16px; font-weight:700; text-decoration:none; transition:top .12s; }
.evite:focus { top:8px; }
.view:focus-visible { outline:2px solid var(--accent); outline-offset:-4px; }
/* ── L'éditeur du commentaire d'annonce ──────────────────────────────────
   Le SEUL texte mis en forme du site. Sept balises, aucun attribut, et
   c'est le serveur qui tranche : FalloutMarket\Security\TexteRiche.
   Ce qui suit est un confort de saisie, pas une barrière. */
.ed { border:1px solid var(--line); border-radius:var(--r); background:var(--surface); }
.ed-barre { display:flex; gap:2px; padding:4px; border-bottom:1px solid var(--line-soft);
  background:var(--raised); border-radius:var(--r) var(--r) 0 0; flex-wrap:wrap; }
/* 32 px : au-dessus du plancher de 24 px de WCAG 2.5.8, et assez large pour
   le pouce sans manger la hauteur du champ sur un téléphone. */
.ed-b { width:32px; height:32px; display:grid; place-items:center; border:1px solid transparent;
  border-radius:3px; background:none; color:var(--ink-2); cursor:pointer; font-size:14px;
  font-family:var(--f-body); line-height:1; padding:0; }
.ed-b:hover { background:var(--plate); color:var(--ink); }
.ed-b:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }
.ed-b[aria-pressed="true"] { background:var(--accent); color:var(--on-accent); border-color:var(--accent-2); }
.ed-b b { font-weight:800; }
.ed-b i { font-style:italic; font-family:var(--f-display); }
.ed-sep { width:1px; background:var(--line-soft); margin:4px 3px; align-self:stretch; }
.ed-zone { min-height:116px; max-height:280px; overflow-y:auto; padding:10px 12px;
  font-size:14px; line-height:1.6; color:var(--ink); font-family:var(--f-body); }
.ed-zone:focus { outline:2px solid var(--accent); outline-offset:-2px; }
.ed-zone p { margin:0 0 .7em; }
.ed-zone p:last-child { margin-bottom:0; }
.ed-zone ul, .ed-zone ol { margin:0 0 .7em; padding-left:1.4em; }
.ed-zone li { margin:.15em 0; }
.ed-zone:empty::before { content:attr(data-vide); color:var(--ink-3); }
.ed-pied { display:flex; justify-content:space-between; gap:12px; flex-wrap:wrap;
  padding:6px 10px; border-top:1px solid var(--line-soft); font-size:11.5px; color:var(--ink-3); }
.ed-reste.pres { color:var(--gold); font-weight:600; }
.ed-reste.trop { color:var(--bad); font-weight:700; }
.field .lab { display:block; }

/* Un modèle se lit comme une ligne d'inventaire, pas comme une carte d'annonce :
   la ressemblance visuelle avec une offre serait mensongère. */
.masque { letter-spacing:.18em; color:var(--ink-3); }
.rdv-jeu { margin-top:8px; padding-top:8px; border-top:1px solid var(--line-soft);
  display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; font-size:12.5px; }
.rdv-jeu code { font-family:var(--f-mono); font-size:13px; background:var(--gold-bg);
  color:var(--on-gold); border:1px solid var(--gold-rule); border-radius:2px; padding:1px 6px; }
.rdv-jeu.attente { color:var(--ink-3); font-style:italic; }

/* La couverture : un cadre 21/9, comme une photo de couverture de profil. */
.couv { border:1px solid var(--line); border-radius:var(--r); overflow:hidden;
  background:var(--plate); margin-bottom:16px; }
.couv iframe { display:block; width:100%; aspect-ratio:21/9; min-height:170px; border:0; }
.couv-pied { display:flex; justify-content:space-between; align-items:center; gap:12px;
  flex-wrap:wrap; padding:7px 12px; font-size:11.5px; color:var(--ink-3);
  border-top:1px solid var(--line); background:var(--surface); }
.couv-pied a { color:var(--accent); }
/* L'étal se lit comme un ticket, pas comme une carte d'annonce. */
.etal-l { display:flex; align-items:baseline; gap:12px; padding:7px 0;
  border-top:1px solid var(--line-soft); }
.etal-l:first-child { border-top:0; }
.etal-nom { flex:1 1 auto; min-width:0; font-weight:600; }
.etal-qte { font-family:var(--f-mono); font-size:12px; color:var(--ink-3); white-space:nowrap; }
.etal-prix { font-family:var(--f-mono); font-variant-numeric:tabular-nums; white-space:nowrap; }
.etal-prix small { font-size:10.5px; color:var(--ink-3); }

.lot-liste { font-size:12px; color:var(--ink-2); margin:3px 0 0; }
.lot-liste b { font-weight:600; }
.lot-l { display:flex; align-items:center; gap:8px; padding:4px 0; flex-wrap:wrap; }
.lot-l select { flex:1 1 160px; min-width:0; }
.mod { display:flex; align-items:center; gap:12px; padding:9px 0;
  border-top:1px solid var(--line-soft); flex-wrap:wrap; }
.mod:first-child { border-top:0; }
.mod-nom { flex:1 1 200px; min-width:0; font-weight:600; }
.mod-nom small { display:block; font-weight:400; font-size:11.5px; color:var(--ink-3); }
.mod-prix { font-family:var(--f-mono); font-variant-numeric:tabular-nums; white-space:nowrap; }
.mod.dort { opacity:.55; }
.mod-dort { font-size:10.5px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--gold); border:1px solid var(--gold-rule); border-radius:2px; padding:1px 5px; white-space:nowrap; }

.tbl-cadre { overflow-x:auto; }
.tbl-cadre:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
.foot-liens a:focus-visible { outline:2px solid #EEBE45; outline-offset:3px; border-radius:2px; }

/* ⚠ L'EN-TÊTE CESSE DE COLLER SUR UNE FENÊTRE BASSE. À 400 % de zoom — le cas
   que WCAG 1.4.10 impose de tenir — la fenêtre utile fait 256 px de haut et
   l'en-tête collant en occupait 266 : le ruban d'onglets se retrouvait à 534 px,
   hors d'atteinte, sans aucun moyen de le découvrir. Un élément collant n'a de
   sens que s'il reste minoritaire dans la hauteur disponible. Vaut aussi pour
   le paysage sur téléphone. */
@media (max-height: 450px) {
  .bar, .filters, .preview { position:static; }
}

/* ── Ce que le site a et que la maquette n'avait pas ──────────────────────
   La maquette est une page unique : elle n'a ni compte, ni pagination, ni
   message d'échec de connexion. Ces règles sont donc les seules écrites ici
   et non extraites — d'où la section à part, pour qu'on sache lesquelles
   n'ont PAS traversé la campagne de mesures du §34.                        */

/* ⚠ CE QUI SUIT NE REDÉFINIT RIEN. La première version de cette section
   redéclarait `footer` et `.evite`, que la maquette porte déjà — et sa règle
   `footer { max-width }` gagnait, ce qui découpait le bandeau du pied en un
   rectangle bleu flottant au milieu de la page. On ne rajoute donc ici que ce
   qui MANQUE, et l'en-tête réutilise `.me`, `.me-nom` et `.foot-in` de la
   maquette plutôt que d'en inventer des jumeaux. */

/* Le compte, dans l'en-tête. `.me` vient de la maquette ; il lui manquait
   seulement de quoi porter un lien, une image et un formulaire de sortie. */
.me a { color:inherit; text-decoration:none; }
.me a:hover .me-nom { text-decoration:underline; }
.me form { margin:0; }
/* Le bouton de sortie est un vrai bouton — la route est en POST — mais il ne
   doit pas peser comme une action principale à côté du pseudo. */
.me form button { appearance:none; background:none; border:0; padding:0; cursor:pointer;
  font:inherit; font-size:11.5px; color:#CBDCF2; text-decoration:underline;
  text-underline-offset:2px; }
.me form button:hover { color:#EEBE45; }
/* L'avatar est rendu en <picture> (WebP + repli). Sa taille d'affichage est
   FIXÉE ici — l'image locale peut faire 128 px de côté, le bandeau la montre à
   32. `object-fit:cover` garde le cadrage carré sans déformer. */
.avatar { width:32px; height:32px; object-fit:cover; display:block;
  border-radius:3px; border:1px solid rgba(255,255,255,.3); flex:none; }
.me picture { flex:none; display:block; font-size:0; }
.entrer { white-space:nowrap; }

/* Un échec de connexion. Un seul message pour trois causes — §43. */
.alerte { background:var(--gold-bg); border:1px solid var(--gold-rule); border-left-width:4px;
  border-radius:var(--r); padding:11px 15px; margin:0 0 20px; color:var(--ink); font-size:13.5px; }

/* Ce que contient un lot, sous le titre de la carte. §42 */
.lot-liste { font-size:12.5px; color:var(--ink-2); margin:6px 0 2px; }
.lot-liste b { color:var(--ink); font-weight:600; }

.pagination { display:flex; align-items:center; justify-content:center; gap:14px;
  margin-top:26px; font-variant-numeric:tabular-nums; color:var(--ink-2); font-size:13px; }

.vide { background:var(--surface); border:1px dashed var(--line-champ); border-radius:var(--r);
  padding:36px 20px; text-align:center; color:var(--ink-2); }
.vide b { display:block; font-family:var(--f-display); font-size:17px; color:var(--ink); margin-bottom:5px; }

/* Le pied garde la règle de la maquette : une bande PLEINE LARGEUR, et un
   `.foot-in` borné à l'intérieur. Le borner lui-même en faisait un rectangle
   bleu flottant, détaché des bords — ce qui se lit comme un défaut de mise en
   page, pas comme un pied. */

/* ── Les cinq thèmes de boutique ──────────────────────────────────────────
   ⚠ DES CLASSES, PAS UN `style=` EN LIGNE. La maquette posait le dégradé dans
   l'attribut : une page unique, aucune donnée venue d'ailleurs. Sur le site,
   la valeur vient de `boutique.theme` — donc d'une colonne, donc un jour d'un
   formulaire. Un dégradé construit par concaténation dans un attribut de
   style est une injection de CSS, et le CSS sait lire des adresses.

   Les couleurs sont celles de la maquette, au point près. Le bandeau garde ses
   teintes dans les deux thèmes du site : c'est l'identité de la boutique, elle
   ne s'inverse pas — seul le texte par-dessus est déjà blanc dans les deux. */
.t-vault      { background:linear-gradient(135deg,#1B54A0,#17488B); }
.t-confrerie  { background:linear-gradient(135deg,#3E4B33,#2C3625); }
.t-enclave    { background:linear-gradient(135deg,#1E2A38,#14202C); }
.t-repondants { background:linear-gradient(135deg,#8A3A1E,#6B2C16); }
.t-pillards   { background:linear-gradient(135deg,#5A2432,#421A25); }

/* Le CAMP en couverture. Le cadre est un CONFORT, pas une condition : tant que
   Fallout Maps n'a pas son `?embed=1` et sa politique `frame-ancestors`, on
   sert un lien — un cadre vide serait pire que pas de cadre. §24, §40 */
.camp { margin-top:14px; border:1px solid var(--line); border-radius:var(--r);
  background:var(--surface); overflow:hidden; }
.camp iframe { display:block; width:100%; height:260px; border:0; }
.camp-pied { padding:10px 14px; font-size:12.5px; color:var(--ink-2);
  display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.camp-pied b { color:var(--ink); font-weight:600; }

/* L'étal du distributeur. ⚠ Il ne produit AUCUNE transaction, n'entre pas dans
   la cote et ne donne lieu à aucun avis — §40. La mise en forme le dit : pas de
   bouton « contacter », pas d'écart au prix de référence. Ce n'est pas une
   annonce, c'est un inventaire. */
.etal { width:100%; border-collapse:collapse; font-size:13.5px; }
.etal th { text-align:left; font-family:var(--f-display); font-size:11px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-3); font-weight:700; padding:0 10px 8px 0;
  border-bottom:1px solid var(--line); }
.etal td { padding:9px 10px 9px 0; border-bottom:1px solid var(--line-soft); }
.etal td.n { text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }
.etal tr:last-child td { border-bottom:0; }
.etal .prix { font-family:var(--f-display); font-size:16px; font-weight:800; color:var(--accent); }

/* Les horaires. Structurés (§25), donc traduits, donc comparables au fuseau du
   visiteur — savoir quand quelqu'un joue vaut mieux que dix messages. */
.dispo { display:flex; gap:6px; flex-wrap:wrap; align-items:center; font-size:13px; }
.jour { font-family:var(--f-mono); font-size:11px; letter-spacing:.04em; text-transform:uppercase;
  border:1px solid var(--line); border-radius:2px; padding:2px 7px; color:var(--ink-2); }
.jour.on { background:var(--accent); border-color:var(--accent); color:var(--on-accent); font-weight:600; }

/* Ce que le visiteur ne voit pas, et pourquoi. §39 : dire qu'un champ est
   réservé vaut mieux que le laisser croire absent — sinon le vendeur passe
   pour n'avoir rien rempli, et l'acheteur pour n'avoir rien à demander. */
.reserve { font-size:12.5px; color:var(--ink-3); font-style:italic; }

/* Les conditions et la doctrine de modération, servies depuis `docs/`.
   ⚠ ELLES SONT AFFICHÉES EN MARKDOWN BRUT, et c'est assumé : deux pages ne
   justifient pas une bibliothèque de rendu de plus. Ce qui n'est pas assumé,
   c'est qu'un `<pre>` sans règle ne se replie PAS — un paragraphe juridique de
   quatre-vingts colonnes déborde alors sur mobile, et le texte le plus
   important du site est le seul qu'on ne peut pas lire sur un téléphone. */
.texte-source { white-space:pre-wrap; overflow-wrap:anywhere; font-family:var(--f-mono);
  font-size:12.5px; line-height:1.7; color:var(--ink-2); background:var(--surface);
  border:1px solid var(--line); border-radius:var(--r); padding:20px;
  max-width:80ch; margin:0; overflow-x:auto; }

/* ── Le formulaire de dépôt ───────────────────────────────────────────────
   ⚠ `label.field > span`, ET PAS SEULEMENT `.field > label`. La maquette
   écrivait `<div class="field"><label>…</label><input></div>` ; le site écrit
   `<label class="field"><span>…</span><input></label>`, qui associe l'étiquette
   au champ SANS avoir à inventer un `id` unique par ligne — et un `for` qui
   pointe à côté est un défaut d'accessibilité qui ne se voit pas à l'œil.
   Les deux formes cohabitent pour que la maquette reste juste.

   ⚠ ET LA LISTE DE TYPES ÉTAIT INCOMPLÈTE : `input[type=text]` seul laissait
   `number` et `search` sans bordure ni fond — donc invisibles sur la moitié du
   formulaire de dépôt, qui ne compte presque que ceux-là. */
label.field > span { display:block; font-family:var(--f-display); font-size:11px;
  letter-spacing:.14em; text-transform:uppercase; color:var(--ink-3); font-weight:700;
  margin-bottom:6px; }
.field input[type=number], .field input[type=search], .field input[type=url] {
  width:100%; background:var(--ground); color:var(--ink); font:inherit; font-size:14px;
  border:1px solid var(--line-champ); border-radius:var(--r); padding:9px 11px; }
.depot textarea { width:100%; background:var(--ground); color:var(--ink); font:inherit;
  font-size:14px; border:1px solid var(--line-champ); border-radius:var(--r);
  padding:9px 11px; min-height:80px; resize:vertical; }
.depot .alerte ul { margin:8px 0 0; padding-left:20px; }
.depot .alerte li { margin:3px 0; }

/* ⚠ UNE GRILLE, ET PAS `.perso`. La première version réutilisait la classe du
   bloc de personnalisation de boutique pour sa disposition — et prenait au
   passage sa bordure dorée, qui dans tout le reste du site veut dire
   « attention, lisez ceci ». Un panneau de saisie ordinaire encadré comme un
   avertissement apprend au lecteur à ignorer les avertissements. Emprunter une
   classe pour sa grille, c'est emprunter son sens. */
.champs { display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); gap:0 14px; }
.champs .field { margin-bottom:13px; }
.champs .note-large { grid-column:1/-1; font-size:12px; color:var(--ink-2);
  border-top:1px solid var(--line-soft); padding-top:11px; margin:2px 0 13px; line-height:1.5; }

/* Un palier de niveau se choisit comme une pastille, pas dans une liste
   déroulante : ils sont quatre, ils tiennent sur une ligne, et le §28 veut
   qu'on VOIE qu'il n'y en a que quatre. */
.chip-radio { position:relative; display:inline-flex; }
.chip-radio input { position:absolute; opacity:0; width:100%; height:100%; margin:0; cursor:pointer; }
.chip-radio span { font-size:12px; background:var(--ground); color:var(--ink-2);
  border:1px solid var(--line-champ); border-radius:100px; padding:3.5px 13px;
  font-variant-numeric:tabular-nums; }
.chip-radio input:checked + span { background:var(--accent); border-color:var(--accent);
  color:var(--on-accent); font-weight:600; }
/* ⚠ L'ANNEAU DE FOCUS SUIT L'ENTRÉE INVISIBLE. Sans cette règle, la case est
   masquée en `opacity:0` et le focus au clavier ne se voit NULLE PART : le
   champ reste atteignable et devient impossible à suivre. */
.chip-radio input:focus-visible + span { outline:2px solid var(--accent); outline-offset:2px; }

/* Un FAIT dans le fil : rendez-vous proposé, accepté, échange déclaré. Il ne
   ressemble pas à un message, et c'est le sujet — ce n'est pas quelqu'un qui
   parle, c'est quelque chose qui s'est passé. Sa phrase est composée à
   l'affichage, libellés d'interface d'un côté, nom de lieu de l'autre : c'est
   ce qui permet à deux joueurs sans langue commune de se comprendre. §24 */
.fil-fait { text-align:center; font-size:12.5px; color:var(--ink-3); margin:14px 0;
  padding:6px 12px; border-top:1px solid var(--line-soft); border-bottom:1px solid var(--line-soft); }
.fil-fait b { color:var(--ink-2); font-weight:600; }

/* ── Les deux recours du §31 — bloquer, signaler ────────────────────────────
   Un repli discret sous l'en-tête du fil et de la fiche : il protège, il ne
   doit pas concurrencer l'action principale (contacter, finaliser). D'où le ton
   effacé, et le fait qu'il soit replié par défaut. */
.recours { border:1px solid var(--line); border-radius:var(--r); background:var(--surface); }
.recours > summary { padding:9px 14px; cursor:pointer; font-size:12.5px; color:var(--ink-2); }
.recours-b { padding:2px 14px 14px; }
.recours-b .fnote { display:inline; margin-left:8px; }

/* Le pseudo en jeu, une fois dévoilé (§39) : ce qu'on cherche au moment de
   l'échange, donc lisible et un peu mis en avant, sans crier. */
.pseudo-jeu { margin-top:14px; padding:10px 14px; border:1px solid var(--line);
  border-radius:var(--r); background:var(--surface); font-size:13.5px; }
.pseudo-jeu span { font-family:var(--f-mono); color:var(--ink); margin-left:6px; }

/* ── L'état d'une tâche d'entretien ────────────────────────────────────────
   Le panel des tâches montre un journal d'exécution : le sort d'un passage
   doit se lire à la COULEUR autant qu'au mot, sans quoi une page de trente
   lignes oblige à tout relire pour trouver l'échec. Les mêmes teintes que
   partout — `--good`, `--bad`, `--gold-rule` — pour qu'un état signifie ici
   ce qu'il signifie ailleurs. */
.badge { display:inline-block; font-family:var(--f-display); font-size:10px; font-weight:700;
         letter-spacing:.11em; text-transform:uppercase; padding:2px 7px; border-radius:2px;
         border:1px solid var(--line); background:var(--raised); color:var(--ink-3);
         vertical-align:middle; }
.badge-faite    { border-color:var(--good); color:var(--good); }
.badge-echouee  { border-color:var(--bad); color:var(--bad); }
.badge-en_cours { border-color:var(--gold-rule); color:var(--gold); }
.badge-demandee { border-color:var(--line-champ); color:var(--ink-2); }

/* Une tâche en retard sur son échéance : c'est le SEUL signal qui révèle que
   la tâche planifiée ne passe plus. Sans le worker, rien ne s'inscrit et rien
   n'échoue — l'historique cesse simplement de grandir, ce qui ressemble à
   « tout va bien ». La ligne doit donc se voir. */
tr.tache-retard td { background:var(--gold-bg); }
tr.tache-retard .fnote.alerte { color:var(--gold); font-weight:600; margin-top:4px; }

/* ── Les langues d'échange d'un membre ─────────────────────────────────────
   Une PUCE, pas une phrase : on la lit d'un coup d'œil dans une liste de vingt
   annonces, et c'est ce coup d'œil qui décide si l'on écrit. Discrète — elle
   accompagne un pseudo, elle ne lui dispute pas la vedette. `lang=` est posé
   sur chaque puce dans le gabarit : la fonte et la prononciation suivent. */
.lg { display:inline-block; font-size:11px; font-weight:600; padding:1px 6px;
      border:1px solid var(--line); border-radius:2px; background:var(--raised);
      color:var(--ink-2); white-space:nowrap; }
.langues-fil { margin-top:6px; display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
/* Sur l'en-tête de boutique, les puces suivent l'enseigne : le bandeau porte
   déjà son thème, elles ne doivent pas lui disputer le contraste. */
.btq-langues { display:flex; gap:6px; flex-wrap:wrap; margin-top:6px; }
.langues-fil .lg { border-color:var(--line-champ); color:var(--ink); }

/* Le choix dans le profil : des cases, pas une liste déroulante — on en coche
   PLUSIEURS, et une liste multiple se manque à la souris comme au doigt. */
.langues-choix { display:flex; flex-wrap:wrap; gap:8px; margin-top:10px; }
.lg-choix { display:inline-flex; align-items:center; gap:6px; padding:5px 10px;
            border:1px solid var(--line); border-radius:var(--r);
            background:var(--surface); cursor:pointer; font-size:13px; }
.lg-choix:hover { border-color:var(--line-champ); }
.lg-choix:focus-within { outline:2px solid var(--line-champ); outline-offset:1px; }
.lg-choix input { margin:0; }

/* ── L'accueil ─────────────────────────────────────────────────────────────
   La seule page que voit quelqu'un qui ne sait pas encore ce qu'est ce site.
   Elle doit tenir debout AVEC ZÉRO ANNONCE — c'est l'état d'un site neuf, et
   celui que voit celui qui vient d'installer. */
.accueil-h { padding:26px 0 22px; border-bottom:1px solid var(--line); margin-bottom:20px; }
.accueil-h h1 { font-family:var(--f-display); font-size:clamp(26px,4.2vw,40px); font-weight:800;
                line-height:1.08; letter-spacing:-.01em; margin:0 0 10px; text-wrap:balance; }
.accueil-h .sub { max-width:62ch; margin:0; font-size:15.5px; line-height:1.6; color:var(--ink-2); }
.accueil-actions { display:flex; flex-wrap:wrap; gap:10px; margin:18px 0 0; }
.accueil-suite { margin-top:16px; }

/* Une tuile de l'accueil sert deux fois : porter un chiffre, ou porter une
   promesse. Sans chiffre, le libellé devient le titre — d'où le poids. */
.tuile-k:only-child, .tuile-k + .tuile-n { font-size:12px; }
.accueil-h + .tuiles .tuile-k { font-size:10.5px; }
