/* ==========================================================================
   INFACT — feuille de style extraite du design system (voir DESIGN.md).
   Écrite pour remplacer directement la constante CSS de build_site.py /
   comparaison.py : mêmes sélecteurs de classes, nouvelles valeurs.
   Zéro dépendance CDN — les polices sont chargées depuis ./polices/.
   ========================================================================== */

/* Le bloc ci-dessous est régénéré par telecharger_polices.py à chaque
   exécution (voir ce script). Ne pas éditer les règles @font-face à la
   main : elles seraient écrasées au prochain lancement du script. */
/* AUTO-GENERATED FONT-FACE START — produit par telecharger_polices.py, ne pas éditer à la main */
@font-face{font-family:'Syne';font-style:normal;font-weight:700 800;font-display:swap;src:url('polices/syne.woff2') format('woff2')}
@font-face{font-family:'DM Sans';font-style:normal;font-weight:400 600;font-display:swap;src:url('polices/dm-sans.woff2') format('woff2')}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:400 700;font-display:swap;src:url('polices/jetbrains-mono.woff2') format('woff2')}
/* AUTO-GENERATED FONT-FACE END */

:root{
  /* ==========================================================================
     PEAU « NEUMORPHISM » — portée le 16/09/2026 depuis la maquette
     "Infact Neumorphism". Principe : UNE seule couleur de surface. Le relief
     ne vient plus d'une bordure ni d'un aplat blanc, mais de deux ombres —
     une claire en haut à gauche, une sombre en bas à droite. Une carte
     "sortante" porte les ombres à l'extérieur, un champ "rentrant" les porte
     à l'intérieur (inset). Conséquence directe : le fond de page n'est plus
     un dégradé blanc→crème, c'est un aplat beige unique, sinon les ombres
     ne raccordent pas.
     Les noms de variables sont INCHANGÉS : build_site.py et comparaison.py
     n'ont rien à savoir de ce changement.
     ========================================================================== */
  --bg-haut:#e8e4de;
  --bg-milieu:#e8e4de;
  --bg-bas:#e8e4de;
  --bg:#e8e4de;           /* surface en relief = exactement la couleur du fond */
  --bg-doux:#e4e0d9;      /* surface en creux : un cran plus sombre */
  --bg-puce:#e4e0d9;      /* chips / badges neutres : en creux eux aussi */

  /* Contrastes : TOUTES les valeurs ci-dessous sont mesurées contre #e4e0d9,
     la plus sombre des deux surfaces. Ce qui passe sur le creux passe donc
     aussi sur le relief. La maquette proposait #666/#777/#bbb et des accents
     clairs (#5a8a5e, #8a7a3e, #a05a4a) qui tombaient entre 1,52 et 4,09:1 —
     sous le minimum WCAG AA de 4,5. Chaque accent a été assombri à teinte
     constante jusqu'à repasser le seuil. Vérifiable : python audit_a11y.py */
  --fg:#333333;           /* 9,60:1 — texte principal, titres Syne */
  --gris:#555555;         /* 5,67:1 — texte secondaire */
  --gris-clair:#636363;   /* 4,57:1 — labels mono discrets (était #bbb côté maquette) */

  /* En neumorphisme il n'y a pas de bordure décorative : --bord devient une
     teinte de raccord quasi invisible. --bord-fort reste, lui, une VRAIE
     bordure : elle matérialise le contour des éléments interactifs (champ de
     recherche, tag cliquable) à 3,13:1, au-dessus du 3:1 exigé par WCAG 1.4.11
     pour les composants d'interface. C'est le garde-fou classique du
     neumorphisme, dont le défaut connu est justement de noyer les contours. */
  --bord:#dcd8d1;
  --bord-fort:#857f76;
  --bord-section:#d8d4cd; /* séparateur de section pleine largeur */

  --acc:#333333;          /* accent = encre, pas de bleu */
  --acc-clair:#e0dcd5;    /* fond hover : le beige enfoncé */

  /* Couleurs sémantiques de fraîcheur — LE signal visuel du produit.
     Teintes de la maquette, assombries pour AA (voir plus haut). */
  --vert:#476c4a;         --vert-clair:#e3e7e0;
  --ambre:#6f6232;        --ambre-clair:#eae5d7;
  --rouge:#c21f1f;        --rouge-clair:#ece0dd;
  --rouge-vif:#c81111;    /* trait de la croix "offre retirée" */

  --info:#1d4ed8;         /* salaire publié : 5,09:1 sur le creux */

  /* Rayons élargis : le neumorphisme a besoin d'angles francs mais doux pour
     que les deux ombres se lisent. Valeurs de la maquette (10 → 24 px). */
  --rayon:14px;
  --rayon-petit:10px;
  --rayon-grand:22px;
  --largeur:800px;        /* pages d'offre ; voir note en fin de fichier */

  /* Les ombres, en variables : un seul endroit pour régler la profondeur de
     tout le site. Modifier --om-sombre / --om-claire suffit à durcir ou
     adoucir la peau entière. */
  --om-sombre:rgba(0,0,0,.10);
  --om-claire:rgba(255,255,255,.70);
  --relief:6px 6px 14px var(--om-sombre),-6px -6px 14px var(--om-claire);
  --relief-fort:12px 12px 28px var(--om-sombre),-12px -12px 28px var(--om-claire);
  --relief-doux:3px 3px 7px rgba(0,0,0,.07),-3px -3px 7px rgba(255,255,255,.60);
  --creux:inset 4px 4px 8px rgba(0,0,0,.07),inset -4px -4px 8px rgba(255,255,255,.60);
  --creux-fort:inset 5px 5px 10px rgba(0,0,0,.08),inset -5px -5px 10px rgba(255,255,255,.60);
  --creux-doux:inset 2px 2px 5px rgba(0,0,0,.07),inset -2px -2px 5px rgba(255,255,255,.50);

  --font-affichage:'Syne',system-ui,sans-serif;      /* logo, titres de page, gros numéros */
  --font-corps:'DM Sans',system-ui,sans-serif;        /* texte courant, boutons, cartes */
  --font-mono:'JetBrains Mono',ui-monospace,"Cascadia Mono","Consolas",monospace; /* labels, meta, "// TITRE", chiffres */
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;color:var(--fg);
  background:linear-gradient(180deg,var(--bg-haut) 0%,var(--bg-milieu) 40%,var(--bg-bas) 100%);
  font:400 17px/1.65 var(--font-corps);
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
a{color:var(--fg);text-decoration:none}
a:hover{color:var(--gris)}
/* Liens de texte du contenu : soulignes. Meme encre que le texte (pas de
   bleu), donc sans soulignement rien ne les distinguait d'une phrase —
   constat du 11/09 sur les renvois d'une page d'offre. :where() garde la
   specificite basse : chaque composant (.fil-ariane, .renvois, .pagination...)
   declare plus bas reprend la main sans !important. */
:where(main) a:not([class]){text-decoration:underline;text-decoration-thickness:1px;
  text-underline-offset:3px;text-decoration-color:var(--gris-clair)}
:where(main) a:not([class]):hover{color:var(--fg);text-decoration-color:var(--fg);
  text-decoration-thickness:2px}
::selection{background:rgba(0,0,0,.08)}

.wrap{max-width:var(--largeur);margin:0 auto;padding:0 24px}
header{border-bottom:1px solid var(--bord-section);padding:20px 0;margin-bottom:44px;
  /* PAS transparent : l'en-tete est colle en haut, et le flou seul ne suffit
     pas a en faire une surface. Constate a la capture le 03/09 sur une liste
     defilee - le titre d'une carte restait lisible a travers le logo. Un fond
     a 85 % rend le bandeau propre AVEC le flou, et lisible sans lui (navigateur
     ancien ou flou desactive), la ou "transparent" laissait le texte de la page
     traverser le logo et la navigation. */
  background:rgba(255,255,255,.85);position:sticky;top:0;z-index:5;
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.logo{font:800 20px/1 var(--font-affichage);letter-spacing:-.02em;color:var(--fg)}
.logo:hover{color:var(--fg);opacity:.7}

/* Une seule échelle typographique, appliquée partout. h1/h2 portent la
   voix de marque (Syne) ; le corps reste en DM Sans pour la lisibilité en
   masse (des centaines d'offres listées). */
h1{font:800 34px/1.18 var(--font-affichage);letter-spacing:-.02em;margin:0 0 12px;color:var(--fg)}
h2{font:700 12.5px/1.3 var(--font-mono);letter-spacing:.02em;text-transform:none;
  color:var(--gris-clair);margin:52px 0 16px}
h2::before{content:"// ";color:var(--gris-clair)}
.sub{color:var(--gris);margin:0 0 30px;font:400 17px/1.6 var(--font-corps);max-width:40em}

/* ── Listes d'offres : grille de cartes ──────────────────────────────── */
.offres{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));
  gap:10px 16px;margin:0 0 8px}
.offre{border:1px solid var(--bord);border-radius:var(--rayon);
  background:var(--bg);padding:16px 18px;transition:border-color .12s,box-shadow .12s;min-width:0}
.offre:hover{border-color:var(--bord-fort);box-shadow:0 2px 12px rgba(0,0,0,.05)}
.offre .t{display:block;font:600 16px/1.25 var(--font-corps);color:var(--fg);
  letter-spacing:-.008em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.offre:hover .t{color:var(--fg);text-decoration:underline;text-underline-offset:2px}
.meta{color:var(--gris)}
.offre .meta{font:400 14px/1.4 var(--font-corps);margin-top:5px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}

/* ── Technologies citées (non cliquables — information, pas filtre) ──── */
.stack{margin:24px 0}
.stack h2{margin:0 0 10px}
.techno{display:inline-block;border:1px solid var(--bord);border-radius:var(--rayon-petit);
  padding:5px 11px;margin:0 7px 7px 0;font:400 13.5px/1.3 var(--font-corps);color:var(--fg);
  background:var(--bg-doux)}
.techno-mini{display:inline-block;border:1px solid var(--bord);border-radius:5px;
  padding:2px 8px;margin:0 5px 5px 0;font:400 11.5px/1.3 var(--font-mono);color:var(--gris);
  background:var(--bg-doux)}
.offre-stack{margin-top:6px}

/* ── Rémunération, quand l'employeur la publie ───────────────────────────
   Présente sur 3,5 % des offres seulement. Elle doit se remarquer sans
   crier : les 96,5 % d'offres sans salaire ne doivent pas donner
   l'impression d'un site à moitié vide. D'où l'encre du texte principal
   plutôt qu'une pastille colorée — c'est un fait, pas une alerte — et la
   police mono, qui aligne les chiffres d'une carte à l'autre.
   `.offre .meta` coupe à l'ellipse : le salaire est en fin de ligne, donc
   `flex-shrink:0` sur la ligne meta le protège du rognage. */
.paie{font-family:var(--font-mono);font-weight:600;color:var(--fg);
  white-space:nowrap}
/* Sur une carte, le salaire prend sa PROPRE ligne. Mesure a 1440 px : la
   colonne d'une grille d'offres fait 330 px, et "entreprise · ville · date"
   la remplit deja - ajouter le salaire au bout le faisait rogner par
   l'ellipse de `.offre .meta`. Une ligne dediee le rend lisible, et le met
   au niveau d'importance qu'il merite : c'est le premier critere de tri
   d'un candidat. */
.offre-paie{margin-top:5px}

/* ── Bouton « afficher plus » sous les résultats de recherche ───────────
   Mesuré le 02/09 : 9 des 16 recherches les plus courantes dépassaient les
   100 résultats affichés, sans aucun moyen d'atteindre les suivants.
   Le bouton occupe toute la largeur de la grille pour ne pas être pris
   pour une carte d'offre. */
.voir-plus{grid-column:1/-1;margin-top:14px;padding:13px 20px;width:100%;
  border:1px solid var(--bord-fort);border-radius:var(--rayon-petit);
  background:var(--bg-doux);color:var(--fg);cursor:pointer;
  font:500 15px/1.3 var(--font-corps)}
.voir-plus:hover{border-color:var(--acc);background:var(--acc-clair)}
.col-stack{margin:2px 0 13px}

/* ── Tags / chips de filtre — mêmes chips que la barre de recherche ──── */
.tags{margin:0 0 8px;display:flex;flex-wrap:wrap;gap:8px}
.tag,.chip{border:1px solid var(--bord);border-radius:var(--rayon-petit);padding:6px 12px;
  font:400 12.5px/1 var(--font-mono);color:var(--gris);background:var(--bg-puce);
  line-height:1;transition:color .12s,border-color .12s,background .12s;display:inline-block}
.tag:hover,.chip:hover{border-color:var(--bord-fort);color:var(--fg);background:#eee;
  text-decoration:none}
.chips{display:flex;gap:8px;flex-wrap:wrap}
/* Un tag qui est un LIEN doit se lire cliquable : encre pleine, bordure
   marquee, fond blanc. Le tag d'information (span) reste gris sur gris. */
a.tag{color:var(--fg);border-color:var(--bord-fort);background:var(--bg)}
a.tag:hover{border-color:var(--fg);background:var(--acc-clair);color:var(--fg)}

/* ── Bloc missions : la raison d'être du site ─────────────────────────  */
.missions{white-space:pre-wrap;background:var(--bg-doux);border:1px solid var(--bord);
  border-left:3px solid var(--fg);padding:20px 24px;margin:28px 0;
  border-radius:0 var(--rayon) var(--rayon) 0;font:400 16px/1.6 var(--font-corps)}
.missions h2{margin:0 0 12px;color:var(--fg)}
.missions h2::before{color:var(--fg)}

/* ── Encart d'argument (page À propos) : l'accroche en gras, puis la preuve ─ */
.argument{background:var(--bg-doux);border:1px solid var(--bord);
  border-left:3px solid var(--fg);padding:18px 24px;margin:14px 0 22px;
  border-radius:0 var(--rayon) var(--rayon) 0}
.argument p{margin:0;color:var(--fg);font:400 16px/1.6 var(--font-corps)}
.argument .argument-titre{margin:0 0 6px;font:700 22px/1.25 var(--font-affichage)}
/* Second argument de l'encart (recence + pertinence) : pas de style inline,
   la CSP du site l'interdit et la recette bloque le deploiement. */
.argument .argument-suite{margin-top:10px}
/* Deuxieme ligne d'accroche de l'accueil : meme voix que .accroche,
   collee dessous pour que les deux arguments se lisent ensemble. */
.accroche-suite{color:var(--fg);font:700 18px/1.6 var(--font-corps);
  max-width:36em;margin:-16px 0 26px}

.cta{display:inline-block;background:var(--fg);color:#fff;padding:12px 22px;
  border-radius:var(--rayon-petit);font:500 15px/1 var(--font-corps);margin:4px 0 32px;
  box-shadow:0 1px 2px rgba(0,0,0,.16)}
.cta:hover{text-decoration:none;background:#333;color:#fff}

/* ── Boutons secondaires : renvois de bas de page d'offre et pagination ──
   Meme gabarit que .voir-plus (bordure, fond clair) : un seul langage pour
   « aller ailleurs sur le site », distinct du bouton plein .cta qui sort
   vers l'employeur. La regle .renvois n'existait que dans le CSS de repli de
   build_site.py : sur le vrai site, les deux liens etaient colles (11/09). */
.renvois{display:flex;flex-wrap:wrap;gap:10px;margin:32px 0 0;padding-top:22px;
  border-top:1px solid var(--bord-section)}
.renvois a,.pagination a{display:inline-flex;align-items:center;gap:8px;
  padding:11px 18px;border:1px solid var(--bord-fort);border-radius:var(--rayon-petit);
  background:var(--bg);color:var(--fg);font:500 15px/1.3 var(--font-corps);
  text-decoration:none;transition:border-color .12s,background .12s}
.renvois a::after{content:"\2192";content:"\2192" / "";color:var(--gris)}
.renvois a:hover,.pagination a:hover{border-color:var(--fg);background:var(--acc-clair);
  color:var(--fg)}
.renvois a:hover::after{color:var(--fg)}
@media (max-width:640px){
  .renvois{flex-direction:column}
  .renvois a{justify-content:space-between}
}

.desc{white-space:pre-wrap;margin:8px 0 24px;color:#3d3d3d;font:400 15.5px/1.7 var(--font-corps)}
.desc summary{cursor:pointer;color:var(--fg);font-weight:600;white-space:normal;
  margin-bottom:14px;font-size:16px;list-style:none}
.desc summary::-webkit-details-marker{display:none}
.desc summary::before{content:"\25B8  ";color:var(--gris-clair)}
.desc[open] summary::before{content:"\25BE  "}
.note-troncature{color:var(--gris);font:400 14px/1.5 var(--font-mono);margin-top:14px;
  padding-top:14px;border-top:1px solid var(--bord-section)}

footer{border-top:1px solid var(--bord-section);margin-top:72px;padding:26px 0 40px;
  color:var(--gris-clair);font:400 14px/1.6 var(--font-corps)}
footer .footer-nav{display:block;margin-top:10px}
footer .footer-nav a{color:var(--gris-clair)}
footer .footer-nav a:hover{color:var(--fg)}

.pagination{display:flex;justify-content:space-between;gap:16px;margin:28px 0 8px;
  padding-top:20px;border-top:1px solid var(--bord-section);font-weight:600}
.pagination .compte{color:var(--gris-clair);font:400 14px/1 var(--font-mono)}

.meta-entreprise{color:var(--gris);margin:4px 0;font:400 15px/1.5 var(--font-corps)}

/* ── Comparaison (comparaison.py) ─────────────────────────────────────  */
.comparaison{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(290px,1fr));
  margin:30px 0;align-items:start}
.colonne{border:1px solid var(--bord);border-radius:var(--rayon);padding:20px 21px;
  background:var(--bg);box-shadow:0 1px 2px rgba(0,0,0,.03);transition:box-shadow .15s}
.colonne:hover{box-shadow:0 4px 16px rgba(0,0,0,.06)}
.colonne .employeur{font:700 17px/1.2 var(--font-affichage);letter-spacing:-.01em;margin-bottom:3px}
.colonne .poste{display:block;font:400 15px/1.4 var(--font-corps);margin-bottom:8px}
.colonne .meta{color:var(--gris-clair);font:400 12.5px/1.3 var(--font-mono);margin-bottom:15px;
  padding-bottom:15px;border-bottom:1px solid var(--bord)}
.colonne .extrait{white-space:pre-wrap;font:400 14.5px/1.62 var(--font-corps);color:#333}
.note{color:var(--gris);font:400 14px/1.5 var(--font-mono);border-top:1px solid var(--bord-section);
  padding-top:20px;margin-top:36px;max-width:44em}
.comparer{display:block;background:var(--bg-doux);border:1px solid var(--bord-fort);
  border-radius:var(--rayon);padding:14px 20px;margin:26px 0;font:600 15px/1.3 var(--font-corps);
  color:var(--fg)}
.comparer:hover{text-decoration:none;border-color:var(--fg)}

/* ── Accueil : démontrer avant de lister ──────────────────────────────  */
.hero{padding:24px 0 0}
.hero h1{max-width:17em;font-size:38px}
.accroche{color:var(--gris);font:400 18px/1.6 var(--font-corps);max-width:36em;margin:16px 0 26px}
.chiffres{display:flex;flex-wrap:wrap;gap:12px 0;font:400 13.5px/1 var(--font-mono);color:var(--gris);
  border-top:1px solid var(--bord-section);border-bottom:1px solid var(--bord-section);padding:16px 0}
.chiffres span{padding:0 22px;border-right:1px solid var(--bord-section)}
.chiffres span:first-child{padding-left:0}
.chiffres span:last-child{border-right:0}
/* La date ne tenait pas sur la ligne des trois chiffres (a 1440 px) : elle
   retombait seule dessous, decalee de 22 px, avec un separateur orphelin
   au bout de "villes". Elle prend donc volontairement sa propre ligne. */
.chiffres span:nth-last-child(2){border-right:0}
.chiffres span:last-child{flex-basis:100%;padding-left:0}
.chiffres b{color:var(--fg);font:700 16px/1 var(--font-mono)}

.demo{border:1px solid var(--bord-fort);border-top:3px solid var(--fg);border-radius:12px;
  padding:24px 26px;margin:34px 0;background:var(--bg-doux)}
.demo-eyebrow{font:700 11px/1 var(--font-mono);letter-spacing:.04em;text-transform:uppercase;
  color:var(--fg);margin-bottom:8px}
.demo-titre{font:700 16px/1.3 var(--font-corps);letter-spacing:-.01em}
.demo .comparaison{margin:18px 0 14px;grid-template-columns:repeat(auto-fit,minmax(250px,1fr))}
.demo .colonne{padding:16px 18px}
.demo .extrait{font-size:14px}
.demo-lien{font:600 15px/1.3 var(--font-corps)}

/* ==========================================================================
   COMPOSANTS NOUVEAUX — apportés par la maquette, pas encore générés par
   build_site.py. Classes prêtes à l'emploi pour une intégration future
   (voir DESIGN.md, section "structure HTML minimale" pour chacun).
   ========================================================================== */

/* Bandeau défilant du haut — flux continu façon terminal boursier.
   Nécessite un site qui connaît les dernières offres publiées EN TEMPS
   RÉEL au moment du build ; voir DESIGN.md "ce que la maquette montre et
   que le site n'a pas" avant de le brancher. */
@keyframes infact-defile{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.bandeau{border-bottom:1px solid var(--bord-section);overflow:hidden;height:32px;
  display:flex;align-items:center;background:var(--bg-doux)}
.bandeau-piste{display:flex;gap:40px;white-space:nowrap;padding:0 20px;
  animation:infact-defile 40s linear infinite}
.bandeau-item{font:500 11px/1 var(--font-mono)}
.bandeau-item.frais{color:var(--vert)}
.bandeau-item.tiede{color:var(--ambre)}
.bandeau-item.vieux{color:var(--gris-clair)}
.bandeau-item.retiree{color:var(--gris-clair);text-decoration:line-through}

/* Rubrique — le label "// TITRE" utilisé pour toutes les sections. h2 le
   fait déjà automatiquement (::before). Cette classe sert quand le label
   est seul, hors d'un h2 (ex. au-dessus de la barre de recherche). */
.rubrique{display:block;font:400 12px/1.5 var(--font-mono);color:var(--gris-clair)}
.rubrique b{color:var(--gris)}

/* Barre de recherche — le "produit" avant tout marketing. */
.barre-recherche{background:var(--bg);border:1px solid var(--bord);border-radius:12px;
  padding:22px;box-shadow:0 2px 12px rgba(0,0,0,.04);display:flex;flex-direction:column;gap:16px}
.barre-recherche .champ{display:flex;align-items:center;gap:12px;font:400 17px/1 var(--font-corps);
  color:var(--gris-clair)}
.barre-recherche .champ input{border:0;outline:0;background:transparent;flex:1;
  font:400 17px/1 var(--font-corps);color:var(--fg)}
.barre-recherche .separateur{height:1px;background:var(--bord)}

/* Score — pastille colorée par tranche de fraîcheur/qualité, format
   IDENTIQUE au score affiché dans les cartes d'offres de la maquette. */
.score{width:44px;height:44px;border-radius:10px;display:flex;align-items:center;
  justify-content:center;font:700 17px/1 var(--font-mono);flex-shrink:0}
.score.score-haut{background:var(--vert-clair);color:var(--vert)}
.score.score-moyen{background:var(--ambre-clair);color:var(--ambre)}
.score.score-bas{background:var(--bg-puce);color:var(--gris-clair)}

/* Offre au format "carte pleine" de la maquette (variante enrichie de
   .offre) : pastille de score + méta inline + bouton d'action. */
.offre-carte{padding:20px;background:var(--bg);border:1px solid var(--bord);border-radius:var(--rayon);
  display:flex;gap:16px;align-items:flex-start}
.offre-carte .corps{flex:1;display:flex;flex-direction:column;gap:6px;min-width:0}
.offre-carte .entete{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.offre-carte .entete .titre{font:600 16px/1.25 var(--font-corps);color:var(--fg)}
.offre-carte .entete .age{font:400 11px/1 var(--font-mono)}
.offre-carte .entete .age.frais{color:var(--vert)}
.offre-carte .entete .age.tiede{color:var(--ambre)}
.offre-carte .badge-contrat{padding:3px 8px;background:var(--bg-puce);border-radius:4px;
  font:400 11px/1 var(--font-mono);color:var(--gris)}
.offre-carte .resume{font:400 14px/1.4 var(--font-corps);color:var(--gris)}
/* flex-wrap : la ligne porte employeur, ville ET salaire depuis le 03/09.
   Sans repli, "OuiHelp - Saint-Nazaire - salaire non communique" elargissait
   la page de 42 px a 320 px. Mesure faite : c'etait la mention de salaire,
   pas les logos ajoutes le meme jour. */
.offre-carte .infos{display:flex;flex-wrap:wrap;gap:4px 12px;align-items:center;
  font:400 13px/1.4 var(--font-corps)}
.offre-carte .infos .entreprise{font-weight:500;color:#555}
.offre-carte .infos .lieu{color:var(--gris)}
.offre-carte .infos .salaire{font-weight:500;color:var(--fg)}
.offre-carte .infos .sep{color:var(--bord-fort)}
.offre-carte .postuler{padding:8px 16px;background:var(--fg);color:#fff;border-radius:var(--rayon-petit);
  font:500 12px/1 var(--font-corps);flex-shrink:0;align-self:center}

/* Section chiffres "ce qu'on a retiré" — grille de 3 statistiques. À ne
   brancher que si ces compteurs existent réellement côté build (voir
   DESIGN.md). */
.stats-retrait{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;
  background:var(--bord-section);border-radius:12px;overflow:hidden}
.stats-retrait .stat{background:var(--bg);padding:26px;display:flex;flex-direction:column;gap:8px}
.stats-retrait .stat .valeur{font:700 34px/1 var(--font-mono);color:var(--rouge)}
.stats-retrait .stat .libelle{font:400 12px/1.4 var(--font-corps);color:var(--gris)}

@media (max-width:640px){
  body{font-size:16px}
  h1{font-size:26px}
  header{position:static}
  .wrap{padding:0 18px}
  .offres{grid-template-columns:1fr}
  .offre .t,.offre .meta{white-space:normal}
  .chiffres span{padding:0 16px 0 0;border-right:0}
  .demo{padding:18px}
  .stats-retrait{grid-template-columns:1fr}
}

/* ---------------------------------------------------------------------------
   Detail du score — la contrepartie de la pastille chiffree.
   Replie par defaut : le visiteur qui veut juste postuler n'en a pas besoin,
   celui qui doute doit pouvoir verifier. C'est ce qui separe un score
   explicable d'un algorithme opaque.
   --------------------------------------------------------------------------- */
.score-detail{margin:22px 0;border:1px solid var(--bord);border-radius:var(--rayon);
  background:#fff;padding:0}
.score-detail summary{cursor:pointer;padding:13px 16px;font:500 14px/1.4 var(--font-mono);
  color:var(--gris);list-style:none}
.score-detail summary::-webkit-details-marker{display:none}
.score-detail summary::before{content:"▸ ";color:var(--gris-clair)}
.score-detail[open] summary::before{content:"▾ "}
.score-detail summary:hover{color:var(--fg)}
.sc-liste{list-style:none;margin:0;padding:0 16px 4px}
.sc-liste li{display:flex;justify-content:space-between;gap:16px;
  padding:7px 0;border-top:1px solid var(--bord);font-size:14.5px}
.sc-lib{color:var(--fg)}
.sc-val{font:500 13.5px/1.5 var(--font-mono);color:var(--fg);white-space:nowrap}
.sc-val.sc-na{color:var(--gris-clair);font-weight:400}
.sc-note{margin:4px 16px 16px;font:400 13.5px/1.6 var(--font-corps);color:var(--gris)}

/* ---------------------------------------------------------------------------
   « D'où viennent les offres ? » — bloc de transparence sous la recherche.
   Sobre volontairement : des noms en typo mono, pas des logos. Aligner huit
   logos de marques tierces donnerait l'impression d'un réseau de partenaires
   qui n'existe pas (voir NOMS_SOURCES dans build_site.py).
   --------------------------------------------------------------------------- */
.sources{margin:38px 0 8px;padding-top:26px;border-top:1px solid var(--bord-section)}
.sources h2{margin:0 0 10px}
.src-intro{margin:0 0 18px;font:400 15.5px/1.6 var(--font-corps);color:var(--gris);
  max-width:44em}
.src-liste{list-style:none;margin:0;padding:0;display:grid;
  grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:8px 16px}
.src-liste li{display:flex;justify-content:space-between;align-items:baseline;
  gap:10px;padding:9px 12px;border:1px solid var(--bord);border-radius:var(--rayon-petit);
  background:var(--bg)}
.src-nom{font:500 14.5px/1.3 var(--font-corps);color:var(--fg)}
.src-n{font:400 12.5px/1.3 var(--font-mono);color:var(--gris);white-space:nowrap}
.src-note{margin:16px 0 0;font:400 13px/1.6 var(--font-corps);color:var(--gris);
  max-width:48em}

/* --- Liste de cartes enrichies -------------------------------------------
   La grille .offres (colonnes de 320 px minimum) convient aux cartes simples,
   pas a .offre-carte : la pastille de score, le corps et le bouton Postuler
   sur une meme ligne demandent la largeur entiere. Les cartes enrichies
   s'empilent donc, comme dans la maquette. */
.offres-cartes{display:flex;flex-direction:column;gap:12px}
.offres-cartes .offre-carte{transition:border-color .12s,box-shadow .12s}
.offres-cartes .offre-carte:hover{border-color:var(--bord-fort);
  box-shadow:0 2px 12px rgba(0,0,0,.05)}
.offre-carte .entete .titre{text-decoration:none}
.offre-carte:hover .entete .titre{text-decoration:underline;text-underline-offset:2px}
.offre-carte .postuler:hover{background:#333;text-decoration:none}
.offre-carte .techno-mini{margin-right:6px}

/* --- Navigation d'en-tete ------------------------------------------------- */
header .wrap{display:flex;align-items:center;justify-content:space-between;gap:16px}
.entete-nav{display:flex;gap:18px;font:400 13px/1 var(--font-mono);color:var(--gris)}
.entete-nav a{color:var(--gris);white-space:nowrap}
.entete-nav a:hover{color:var(--fg)}

/* --- Bandeau : respecter ceux qui ne supportent pas le mouvement ---------- */
@media (prefers-reduced-motion: reduce){
  .bandeau-piste{animation:none}
}

@media (max-width:640px){
  /* A 390 px, "Comment on trie" se coupait apres "on" et venait mordre sur le
     logo : logo + deux liens + les ecarts font exactement la largeur de
     l'ecran. On resserre plutot que de masquer - le lien explique le tri, et
     c'est la premiere question d'un visiteur qui decouvre un agregateur. */
  .entete-nav{font-size:11px;gap:12px}
  /* Sur telephone, le bouton passe sous le corps de la carte plutot que de
     comprimer le titre a deux mots par ligne. */
  .offre-carte{flex-wrap:wrap}
  .offre-carte .postuler{align-self:flex-start;margin-left:60px}
  /* Le bandeau defilant est decoratif et coute une bande de hauteur sur un
     ecran ou elle compte : il disparait. */
  .bandeau{display:none}
}

/* En dessous de 360 px - iPhone SE, petits Android - le logo et les deux liens
   ne tiennent plus sur une ligne : mesure a 320 px, la page debordait de 20 px
   sur les SEPT types de page. Plutot que de masquer un lien, la navigation
   passe sous le logo. */
@media (max-width:359px){
  header .wrap{flex-wrap:wrap;row-gap:6px}
  /* La nav s'enroule au lieu de deborder. Mesure du 23/09 : « Candidatures »
     renomme en « Mes candidatures » faisait deborder la page de 8 px a 320 px
     sur les cinq types de page. Resserrer les ecarts aurait tenu a 8 px pres —
     donc jusqu'au prochain libelle rallonge. L'enroulement, lui, tient quel
     que soit le texte des liens. */
  .entete-nav{width:100%;flex-wrap:wrap;row-gap:6px}
}

/* Legende du score, repetee au-dessus de chaque liste de cartes. Discrete par
   construction : elle doit repondre a la question sans se mettre devant les
   offres, et disparaitre du regard des la deuxieme page lue. */
/* Filet : un titre ne doit jamais elargir la page. Syne est une graisse
   d'affichage tres large - a 320 px, un seul mot de dix caracteres depasse la
   colonne, et le h1 d'une page d'offre est l'intitule ECRIT PAR L'EMPLOYEUR :
   on ne controle ni sa longueur ni ses mots. Mesure du 03/09 : h1 demandait
   316 px pour 284 disponibles. La cesure n'intervient qu'en dernier recours,
   quand le mot ne tient pas sur une ligne entiere. */
h1,h2,.offre-carte .titre,.offre .t{overflow-wrap:break-word}

.legende-score{margin:-6px 0 16px;font:400 13px/1.5 var(--font-corps);
  color:var(--gris)}
.legende-score b{font-weight:600;color:var(--fg)}
.legende-score a{color:var(--gris);text-decoration:underline;
  text-underline-offset:2px}
.legende-score a:hover{color:var(--fg)}

/* L'apercu chiffre d'une page de listing (apercu_liste dans build_site.py).
   Pose juste sous le sous-titre, avant les tags de navigation : c'est le seul
   texte de la page qu'on ne lit nulle part ailleurs sur le site, il merite
   d'etre lisible, pas d'etre une note de bas de page. D'ou le corps a 15px
   (contre 13 pour la legende du score, qui n'est qu'une legende) et le filet
   a gauche, qui le detache du sous-titre sans ajouter de cadre. */
.apercu-liste{margin:-18px 0 24px;padding:0 0 0 14px;max-width:44em;
  border-left:2px solid var(--bord);
  font:400 15px/1.7 var(--font-corps);color:var(--gris)}

/* Un salaire absent s'annonce, mais ne se met pas en avant : meme place que le
   montant, poids et couleur d'une note. Sans cette nuance, "Salaire non
   communique" aurait la meme force visuelle qu'une vraie fourchette. */
.paie-absente,.salaire-absent{font-weight:400;color:var(--gris-clair);
  font-style:normal}
.offre-carte .infos .salaire-absent{font-weight:400;color:var(--gris-clair)}

/* --- Logos ---------------------------------------------------------------
   Taille fixe et object-fit : les fichiers viennent de 160 sites differents,
   en carre comme en rectangle, en 32 px comme en 512. Sans contrainte, une
   seule icone mal proportionnee decale toute une rangee. */
.logo-src,.logo-tag{width:18px;height:18px;object-fit:contain;border-radius:4px;
  flex-shrink:0;vertical-align:-4px}
.logo-tag{margin-right:7px}
.logo-src{margin-right:9px}
/* Pastille a l'initiale quand aucun logo n'a ete trouve : une case vide se
   remarque plus qu'une lettre, et un logo generique serait un faux. */
.logo-src-lettre,.logo-tag-lettre{display:inline-flex;align-items:center;
  justify-content:center;background:var(--bg-puce);color:var(--gris-clair);
  font:600 10px/1 var(--font-mono);border:1px solid var(--bord)}
/* La ligne porte desormais un logo, un nom et un compte. Sans min-width:0 le
   nom refuse de se comprimer et pousse le compte hors de la colonne : mesure
   du 03/09, la page debordait de 22 px a 640 px - soit un zoom a 200 %, que
   WCAG 1.4.10 interdit de faire deborder. */
.src-liste li{display:flex;align-items:center;gap:0;min-width:0}
/* Le nom s'affiche en entier (demande du 21/09 : "Welcome to the Jungle"
   finissait en points de suspension). Colonnes plus larges, et retour a la
   ligne autorise plutot que la coupe - min-width:0 reste, donc un nom long
   passe sur deux lignes au lieu de faire deborder la page. */
.src-liste{grid-template-columns:repeat(auto-fill,minmax(min(300px,100%),1fr))}
.src-liste .src-nom{flex:1;min-width:0;overflow-wrap:anywhere;padding-right:8px}
/* Toute la bulle est le lien vers les offres de la source. */
.src-liste li{padding:0}
.src-liste li a{display:flex;align-items:center;flex:1;min-width:0;
  padding:9px 12px;color:inherit;text-decoration:none}
.src-liste li a:hover .src-nom{text-decoration:underline;text-underline-offset:2px}
.tag-logo{display:inline-flex;align-items:center}

/* Mention de fin de rangee : "+ 2 727 employeurs avec une seule offre".
   Ce n'est pas un lien, donc elle ne doit pas en avoir l'air. */
.tag-muet{color:var(--gris);border-style:dashed;cursor:default}

/* Lien d'evitement — « Aller au contenu ».
   Mesure du 05/09 (audit_a11y_profond.py) : sur CHAQUE page du site, un
   visiteur au clavier traversait 3 arrets (logo, « Comment on trie ? »,
   « Entreprises ») avant d'atteindre le contenu, sans aucun moyen de les
   sauter. WCAG 2.4.1 (niveau A) l'interdit des qu'un bloc se repete d'une
   page a l'autre — c'est le cas de l'en-tete.
   Le lien est HORS ECRAN, pas `display:none` : un element masque de cette
   facon-la ne recoit jamais le focus, donc n'existe pas au clavier non plus.
   Il revient a l'ecran des qu'il est focalise. */
.lien-evitement{position:absolute;top:0;left:-9999px;z-index:200;
  background:var(--fg);color:#fff;padding:12px 18px;
  border-radius:0 0 var(--rayon-petit) 0;text-decoration:none;
  font:600 15px/1 var(--font-corps)}
.lien-evitement:focus{left:0}

/* <main> porte tabindex="-1" pour que le saut deplace REELLEMENT le focus et
   pas seulement le defilement (Safari et les anciens WebKit ne focalisent pas
   une cible d'ancre non focalisable). La bague de focus est retiree sur ce
   seul element : une bague de 800 px de large autour de toute la page n'aide
   personne, et le repere reste le deplacement du contenu. */
main[tabindex="-1"]:focus{outline:none}

/* Bague de focus clavier commune a tout ce qui se clique. :focus-visible et
   non :focus : invisible au clic souris, toujours la au clavier. */
a:focus-visible,button:focus-visible,summary:focus-visible{outline:2px solid var(--fg);
  outline-offset:2px}

/* Fil d'Ariane. Le separateur est en CSS et non dans le texte : un ">" ecrit
   dans le HTML serait lu a voix haute par un lecteur d'ecran entre chaque
   etape. Il defile horizontalement plutot que de passer a la ligne - sur un
   telephone, un fil sur trois lignes mange l'ecran avant le contenu. */
.fil-ariane{display:flex;flex-wrap:nowrap;overflow-x:auto;gap:0;
  margin:0 0 18px;padding:0 0 2px;font-size:14px;color:var(--gris-clair);
  scrollbar-width:none}
.fil-ariane::-webkit-scrollbar{display:none}
.fil-ariane>*{white-space:nowrap;flex:0 0 auto}
.fil-ariane>*+*::before{content:">";content:">" / "";margin:0 9px;font-weight:600;color:var(--gris)}
.fil-ariane a{color:var(--gris);text-decoration:none;border-bottom:1px solid transparent}
.fil-ariane a:hover{border-bottom-color:var(--gris-clair)}
.fil-ariane [aria-current]{color:var(--gris-clair);
  max-width:min(46ch,60vw);overflow:hidden;text-overflow:ellipsis}

/* Page d'offre - arbitrage Karim du 11/09. L'intitule en 34 px Syne ecrasait
   la page (trois lignes sur un intitule long), et la ligne employeur / ville /
   date / salaire, en gris, se lisait moins que lui alors que c'est elle que le
   candidat parcourt. Le titre descend, la ligne passe a l'encre, et un salaire
   PUBLIE prend une couleur indicative : bleu, parce que le vert, l'ambre et le
   rouge portent deja la fraicheur des offres.
   Separateur du fil d'Ariane : deux declarations "content", la syntaxe
   '/ ""' (le lecteur d'ecran ne lit pas le chevron) invalidant la ligne sur un
   navigateur ancien, qui garde alors la premiere. */
.entete-offre h1{font-size:26px;line-height:1.22}
.entete-offre .sub{color:var(--fg);font-weight:500}
.entete-offre .paie{color:var(--info);font-weight:700}
.entete-offre .paie-absente{color:var(--gris);font-weight:400}
@media (max-width:640px){.entete-offre h1{font-size:21px}}

/* ==========================================================================
   PEAU « NEUMORPHISM » — conversion des composants (16/09/2026)
   Portée depuis la maquette "Infact Neumorphism".

   Ce bloc est volontairement EN FIN DE FICHIER et ne fait que surcharger des
   règles déclarées plus haut, à sélecteur identique. Pour revenir au design
   précédent, il suffit de supprimer ce bloc et de restaurer le :root.
   Deux filets pour ça : la copie infact.css.bak-2026-09-16-2100 posée à côté
   (sur disque seulement — les .bak sont ignorés par git), et le commit
   précédent dans l'historique, qui lui fait foi. Aucun sélecteur nouveau
   n'est inventé : build_site.py produit déjà tout ce qui est stylé ici.

   Règle de conversion appliquée partout :
     surface qui AVANCE (carte, bouton, bandeau)  -> ombres externes, bordure retirée
     surface qui RENTRE  (champ, chip, pastille)  -> ombres internes (inset)
     bouton pressé / état actif                   -> passe de l'externe à l'interne
   ========================================================================== */

/* ── Ossature de page ─────────────────────────────────────────────────── */
/* Le fond redevient un aplat : les trois arrêts du dégradé valent désormais
   la même valeur, mais on le déclare explicitement pour que ce soit lisible. */
body{background:var(--bg-haut)}

/* En-tête collant : plus de bordure basse ni de voile blanc — une simple
   ombre portée vers le bas suffit à décoller le bandeau du contenu qui
   défile dessous. Le fond reste OPAQUE (et non translucide) pour la même
   raison qu'avant : un titre de carte ne doit pas traverser le logo. */
header{border-bottom:0;background:var(--bg-haut);
  box-shadow:0 6px 14px -8px var(--om-sombre)}

/* Le logo devient une plaque en relief, comme dans la maquette. */
.logo{display:inline-block;padding:10px 18px;border-radius:var(--rayon);
  background:var(--bg);box-shadow:var(--relief)}
.logo:hover{opacity:1;box-shadow:var(--creux-doux)}

/* Les liens de l'en-tete sont des plaques, comme le logo. Sans cela le logo
   etait la SEULE surface en relief du bandeau et « Comment on trie ? »,
   « Entreprises », « Candidatures » flottaient en texte nu a cote : la barre
   n'avait qu'une moitie de son langage. Relief DOUX et pas --relief : le logo
   doit rester l'element dominant de l'en-tete. */
/* Au-dessus de 640 px SEULEMENT. Mesure du 23/09 : avec le rembourrage de la
   plaque, la barre debordait de 66 px a 320 px et la nav passait a la ligne a
   390 px. Le commentaire du bloc mobile disait deja que logo + liens + ecarts
   font EXACTEMENT la largeur de l'ecran : il n'y a pas de place pour une
   plaque. Sur telephone les liens restent du texte nu, et c'est tres bien. */
@media (min-width:641px){
  .entete-nav{align-items:center}
  .entete-nav a{display:inline-block;padding:8px 14px;border-radius:var(--rayon-petit);
    background:var(--bg);box-shadow:var(--relief-doux);
    transition:box-shadow .12s,color .12s}
  .entete-nav a:hover{color:var(--fg);box-shadow:var(--creux-doux)}
  .entete-nav a:focus-visible{outline:2px solid var(--fg);outline-offset:2px}
}

/* ── Cartes ───────────────────────────────────────────────────────────── */
.offre,.offre-carte,.colonne,.score-detail,.src-liste li,.demo{
  border:0;background:var(--bg);box-shadow:var(--relief-doux)}
.offre,.offre-carte{border-radius:var(--rayon)}
.demo{border-top:3px solid var(--fg);border-radius:var(--rayon-grand)}
.colonne{border-radius:var(--rayon)}

/* Au survol, une carte s'enfonce au lieu de se cercler : c'est le seul
   retour visuel disponible quand il n'y a plus de bordure à colorer. */
.offre:hover,.offres-cartes .offre-carte:hover,.colonne:hover{
  border-color:transparent;box-shadow:var(--creux-doux)}

/* ── Chips, tags, technos : toujours en creux ─────────────────────────── */
.techno,.techno-mini,.tag,.chip{border:0;background:var(--bg-puce);
  box-shadow:var(--creux-doux)}
.tag:hover,.chip:hover{background:var(--bg-puce);box-shadow:var(--relief-doux)}
/* a.tag est un tag CLIQUABLE : il garde une vraie bordure (3,13:1), sans quoi
   rien ne le distingue d'une étiquette décorative une fois les ombres posées. */
a.tag{border:1px solid var(--bord-fort);background:var(--bg);box-shadow:var(--relief-doux)}
a.tag:hover{border-color:var(--fg);background:var(--bg);box-shadow:var(--creux-doux)}

/* ── Boutons secondaires ──────────────────────────────────────────────── */
.voir-plus,.renvois a,.pagination a,.comparer{
  border:0;background:var(--bg);box-shadow:var(--relief-doux)}
.voir-plus:hover,.renvois a:hover,.pagination a:hover,.comparer:hover{
  border-color:transparent;background:var(--bg);box-shadow:var(--creux)}

/* ── Boutons primaires ────────────────────────────────────────────────── */
/* Ceux-là NE passent PAS en beige : ce sont les deux seules actions fortes du
   site (postuler, appel à l'action). Un aplat d'encre à 9,6:1 reste l'élément
   le plus contrasté de la page — c'est exactement ce qu'on veut d'un bouton
   primaire, et le neumorphisme ne doit pas l'aplatir. */
.cta,.offre-carte .postuler{background:var(--fg);color:#fff;border-radius:var(--rayon-petit);
  box-shadow:5px 5px 12px var(--om-sombre),-3px -3px 8px var(--om-claire)}
.cta:hover,.offre-carte .postuler:hover{background:#222;
  box-shadow:inset 3px 3px 7px rgba(0,0,0,.30)}

/* ── Champ de recherche : la pièce la plus typée de la maquette ───────── */
.barre-recherche{background:var(--bg);border:0;border-radius:var(--rayon);
  box-shadow:var(--creux-fort)}
.barre-recherche .separateur{background:var(--bord)}

/* ── Panneaux de contenu (missions, argument) ─────────────────────────── */
.missions,.argument{background:var(--bg-doux);border:0;border-left:3px solid var(--fg);
  border-radius:0 var(--rayon) var(--rayon) 0;box-shadow:var(--creux)}

/* ── Bandeau défilant ─────────────────────────────────────────────────── */
.bandeau{border-bottom:0;background:var(--acc-clair);
  box-shadow:inset 0 -1px 2px rgba(0,0,0,.06)}

/* ── Pastilles de score ───────────────────────────────────────────────── */
.score{box-shadow:var(--creux-doux)}
.score.score-bas{background:var(--bg-puce)}

/* ── Bloc « ce que le site retire » ───────────────────────────────────── */
/* L'ancienne astuce du fond de grille visible dans un gap de 1 px ne marche
   plus : sur fond beige, deux beiges séparés par un trait ne se voient pas.
   Le conteneur passe en relief, chaque chiffre en creux, avec un vrai écart. */
.stats-retrait{background:var(--bg);border-radius:var(--rayon-grand);gap:14px;
  padding:14px;box-shadow:var(--relief)}
.stats-retrait .stat{background:var(--bg-doux);border-radius:var(--rayon);
  box-shadow:var(--creux)}

/* ── Divers ───────────────────────────────────────────────────────────── */
.logo-src-lettre,.logo-tag-lettre{border:0;background:var(--bg-puce);
  box-shadow:var(--creux-doux)}
footer{border-top:0;background:var(--bg);border-radius:var(--rayon-grand);
  box-shadow:var(--relief-doux);padding:28px 40px;margin-top:64px}

/* ── Garde-fous ───────────────────────────────────────────────────────── */
/* 1. Contraste forcé (Windows "contraste élevé") : les ombres ne sont pas
      rendues du tout. Sans ce repli, toutes les surfaces deviennent des
      rectangles sans contour. On rétablit des bordures franches. */
@media (forced-colors:active){
  .offre,.offre-carte,.colonne,.score-detail,.src-liste li,.demo,
  .techno,.tag,.chip,.voir-plus,.renvois a,.pagination a,.comparer,
  .barre-recherche,.stats-retrait .stat,footer{border:1px solid;box-shadow:none}
}
/* 2. Le bandeau défilant s'arrête si l'utilisateur a demandé moins
      d'animations — règle déjà posée plus haut pour .bandeau-piste, rappelée
      ici parce que la peau ajoute des transitions d'ombre. */
@media (prefers-reduced-motion:reduce){
  .offre,.offre-carte,.colonne,.voir-plus,.cta{transition:none}
}

/* Largeur de page — TRANCHÉ le 19/09 : par type de page.
   Les pages d'offre gardent 800 px (longueur de ligne lisible). Les
   pages-listes (accueil, listes métier/ville, entreprises) portent
   class="large" sur <html>, posée par page(large=True) dans build_site.py,
   et composent leurs grilles sur 1200 px. */
html.large{--largeur:1200px}

/* ── Panneaux de la page d'accueil ────────────────────────────────────────
   La maquette ne pose pas ses sections à plat : chaque grand bloc est une
   plaque qui avance. Sans ça, la peau se voit sur les petits éléments mais
   la page reste plate. On n'ajoute AUCUNE classe : .hero et .sources sont
   déjà produits par build_site.py. */
.hero{background:var(--bg);border-radius:var(--rayon-grand);
  padding:36px 34px 30px;box-shadow:var(--relief-fort);margin-top:8px}
.sources{background:var(--bg);border-radius:var(--rayon-grand);border-top:0;
  padding:30px 34px;box-shadow:var(--relief);margin:34px 0 8px}
.sources h2{margin-top:0}

/* VÉRIFIÉ au DOM le 16/09 : #bloc-recherche est le FRÈRE de .hero, pas son
   enfant. Il garde donc sa propre plaque (déclarée dans recherche.py) et la
   page d'accueil se lit comme deux plaques empilées — l'accroche, puis la
   recherche. Une règle .hero #bloc-recherche a été écrite puis retirée : elle
   ne s'appliquait à rien. Les réunir en une seule plaque demanderait de
   changer le HTML dans build_site.py, ce qui sort d'un travail de peau. */

/* Les chiffres passent en cartes creusées, comme dans la maquette, au lieu
   d'une ligne de texte séparée par des filets. */
.chiffres{border-top:0;border-bottom:0;padding:0;gap:12px;margin-top:26px}
.chiffres span{padding:14px 20px;border-right:0;background:var(--bg-doux);
  border-radius:var(--rayon);box-shadow:var(--creux);display:flex;
  flex-direction:column;gap:6px;color:var(--gris)}
.chiffres span:first-child{padding-left:20px}
/* La règle d'origine envoyait la date seule sur sa propre ligne : elle
   existait parce qu'un séparateur orphelin restait au bout de "villes"
   (constat à 1440 px). Il n'y a plus de séparateur — la date peut reprendre
   sa place dans la rangée. */
.chiffres span:last-child{flex-basis:auto;padding-left:20px}
.chiffres b{font:700 22px/1 var(--font-affichage);color:var(--fg)}


/* ==========================================================================
   RACCORDS D'INTÉGRATION — 23/09/2026
   Ajouté après confrontation du CSS au HTML RÉELLEMENT produit par
   build_site.py (page-accueil-REELLE-sans-css.html + CLASSES-CONTRAT.md).

   Aucune classe renommée, aucune classe inventée, aucun nom de variable
   existant modifié, HTML inchangé. Ce bloc ne fait que deux choses :

   1. STYLER CE QUI NE L'ÉTAIT PAS. Cinq classes du contrat n'avaient aucune
      règle dans le fichier — dont deux très visibles :
        .recherche-champ  le CSS stylait `.barre-recherche .champ`, un
                          sélecteur que build_site.py ne produit PAS. Le champ
                          de recherche de l'accueil sortait donc en input nu.
        .cand             7 498 occurrences (une par page d'offre) : bouton de
                          suivi de candidature, rendu sans aucun style.
        .filtres-menus    rangée de <select> : widgets natifs sur une page
        .filtres-options  neumorphique.
        .tri
      Les identifiants voisins (#bloc-recherche, #filtres, #compteur,
      #resultats) sont traités ici aussi : ils étaient supposés stylés par
      recherche.py, ce qui rendait l'accueil dépendant d'un autre fichier.

   2. POSER LA COUCHE DE VERRE validée sur la maquette, sous @supports : un
      navigateur sans backdrop-filter garde la peau neumorphique opaque telle
      qu'elle est déclarée plus haut. Un fond translucide non flouté serait
      illisible — d'où le garde-fou plutôt qu'une déclaration sèche.
   ========================================================================== */

/* ── Garde-fou n°1, avant toute règle de display ──────────────────────────
   #bloc-recherche est livré avec l'attribut `hidden` et c'est recherche.js
   qui le retire une fois l'index chargé. Toute règle de mise en page qui
   porte un `display` écraserait cet attribut et ferait apparaître la barre
   de recherche pendant le chargement, vide et non fonctionnelle. */
[hidden]{display:none!important}

/* ── Nouvelles variables (les existantes sont inchangées) ─────────────── */
:root{
  --verre:rgba(255,255,255,.20);        /* plaque : translucidité de surface */
  --verre-doux:rgba(255,255,255,.10);   /* surface en creux */
  --verre-dense:rgba(255,255,255,.85);  /* en-tête collant : lisibilité d'abord.
     85 % et pas 72 % : test_rendu_design.py exige >= 80 % d'opacité sur l'en-tête
     collant (garde-fou du constat du 03/09). 72 % faisait echouer le controle
     bloquant et interdisait tout deploiement. */
  --verre-flou:blur(32px) saturate(125%);
  --verre-flou-doux:blur(20px) saturate(115%);
  /* Arête claire : c'est elle qui donne l'épaisseur du verre. Volontairement
     basse (.40 / .16) — au-dessus, la page se met à briller. */
  --verre-arete:inset 1px 1px 0 rgba(255,255,255,.40),
                inset -1px -1px 0 rgba(255,255,255,.16);
  --verre-arete-creux:inset 0 0 0 1px rgba(255,255,255,.26);
}

/* ==========================================================================
   1. BLOC DE RECHERCHE DE L'ACCUEIL
   ========================================================================== */

/* La plaque qui porte champ + chips + filtres. Même gabarit que .hero et
   .sources : la page d'accueil se lit comme une pile de plaques. */
#bloc-recherche{background:var(--bg);border-radius:var(--rayon-grand);
  padding:28px 34px;box-shadow:var(--relief);margin:22px 0 10px}

/* Le champ lui-même : creux profond, c'est la pièce la plus typée. */
.recherche-champ{display:flex;align-items:center;gap:12px;
  background:var(--bg-doux);border-radius:var(--rayon);padding:16px 20px;
  box-shadow:var(--creux-fort)}
.recherche-champ svg{width:20px;height:20px;flex-shrink:0;color:var(--gris-clair)}
.recherche-champ input{flex:1;min-width:0;border:0;outline:0;background:transparent;
  font:400 16px/1.25 var(--font-corps);color:var(--fg);
  /* Le rayon ne se voit jamais (fond transparent, pas de bordure) : il sert
     uniquement a arrondir la bague de focus ci-dessous, qu'un outline calque
     sur le rayon de l'element. Sans lui, la bague est un rectangle a angles
     droits pose dans une pilule arrondie — on dirait un defaut. */
  border-radius:var(--rayon-petit);
  -webkit-appearance:none;appearance:none}
.recherche-champ input::placeholder{color:var(--gris-clair);opacity:1}
/* La bague de focus est portée par l'INPUT, en retrait (`outline-offset:-2px`),
   et non par la pilule parente. Mesure du 23/09 : `audit_a11y_profond.py`
   capture le rectangle de l'element focalise et compare pixel a pixel ; une
   bague posee sur `.recherche-champ:focus-within` tombe HORS de ce rectangle,
   donc « 0 pixel change sur 47 520 » et echec bloquant WCAG 2.4.7. L'outil a
   raison sur le fond : l'indicateur doit etre sur l'element qui a le focus.
   Le retrait est obligatoire — un outline se dessine vers l'EXTERIEUR, donc a
   offset positif il sort du rectangle mesure et le defaut revient. */
.recherche-champ input:focus-visible{outline:2px solid var(--fg);outline-offset:-2px}
.recherche-champ input::-webkit-search-decoration,
.recherche-champ input::-webkit-search-cancel-button{-webkit-appearance:none}

.chips{margin-top:16px}

/* ── Menus de filtre ──────────────────────────────────────────────────────
   `appearance:none` retire le widget natif ; le chevron est une image de
   fond en data-URI, donc aucune balise ajoutée au HTML. background-color et
   background-image sont déclarés séparément : la forme courte `background`
   remettrait background-image à none. */
#filtres{margin-top:18px;display:flex;flex-direction:column;gap:12px}
.filtres-menus{display:flex;flex-wrap:wrap;gap:10px}
.filtres-menus select,.tri select{
  -webkit-appearance:none;appearance:none;border:0;cursor:pointer;
  background-color:var(--bg);
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23555555' stroke-width='2.2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 12px center;
  background-size:13px 13px;
  border-radius:var(--rayon-petit);padding:11px 34px 11px 16px;
  font:400 13.5px/1.2 var(--font-corps);color:var(--gris);
  box-shadow:var(--relief-doux);max-width:100%}
.filtres-menus select:hover,.tri select:hover{color:var(--fg);box-shadow:var(--creux-doux)}
/* Les <option> sont dessinées par le système : sur fond beige translucide
   elles deviendraient illisibles. On force une paire opaque. */
.filtres-menus select option,.tri select option{background:#fff;color:var(--fg)}

/* ── Ligne d'options : case à cocher + tri ───────────────────────────── */
.filtres-options{display:flex;flex-wrap:wrap;align-items:center;gap:10px 16px}
.filtres-options label{display:inline-flex;align-items:center;gap:9px;
  background:var(--bg-doux);border-radius:var(--rayon-petit);padding:10px 16px;
  box-shadow:var(--creux-doux);cursor:pointer;
  font:400 13.5px/1.2 var(--font-corps);color:var(--gris)}
.filtres-options label:hover{color:var(--fg)}
.filtres-options input[type=checkbox]{-webkit-appearance:none;appearance:none;
  width:17px;height:17px;flex-shrink:0;margin:0;cursor:pointer;
  border:0;border-radius:5px;background-color:var(--bg);box-shadow:var(--creux-doux)}
.filtres-options input[type=checkbox]:checked{
  background-color:var(--fg);box-shadow:none;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:center;background-size:11px 11px}
.filtres-options input[type=checkbox]:focus-visible{outline:2px solid var(--fg);
  outline-offset:2px}
/* `.tri` est un <label> qui enveloppe son <select> : il hérite du label
   ci-dessus, on ne règle donc que l'écart interne. */
.tri{gap:10px;padding:6px 8px 6px 16px}
.tri select{padding:7px 32px 7px 12px;box-shadow:var(--creux-doux)}

/* ── Compteur de résultats et conteneur ──────────────────────────────── */
#compteur{margin:18px 0 10px;font:400 13px/1.5 var(--font-mono);color:var(--gris-clair)}
#compteur:empty{margin:0}
#resultats:empty{margin:0}

/* ==========================================================================
   2. .cand — SUIVI DE CANDIDATURE (page d'offre, 7 498 occurrences)
   Le script candidatures.js bascule l'état ; on style via l'ATTRIBUT
   aria-pressed, pas via une classe ajoutée — rien à inventer côté contrat.
   Déclaré pour <button> ET <a> : les deux gabarits existent selon la page.
   ========================================================================== */
.cand{display:inline-flex;align-items:center;gap:8px;padding:11px 18px;
  border:0;border-radius:var(--rayon-petit);background:var(--bg);color:var(--fg);
  box-shadow:var(--relief-doux);cursor:pointer;text-decoration:none;
  font:500 14.5px/1.3 var(--font-corps);transition:box-shadow .12s,background .12s}
.cand:hover{color:var(--fg);box-shadow:var(--creux-doux);text-decoration:none}
/* État « candidature suivie » : vert de la palette de fraîcheur, enfoncé.
   Le bouton pressé passe de l'externe à l'interne — règle de conversion du
   bloc neumorphique ci-dessus. */
.cand[aria-pressed="true"]{background:var(--vert-clair);color:var(--vert);
  box-shadow:var(--creux-doux)}
.cand[aria-pressed="true"]:hover{background:var(--vert-clair);color:var(--vert)}
.cand:disabled,.cand[disabled],.cand[aria-disabled="true"]{
  opacity:.55;cursor:default;box-shadow:var(--creux-doux)}
.cand:focus-visible{outline:2px solid var(--fg);outline-offset:2px}

/* ==========================================================================
   3. COUCHE DE VERRE
   ========================================================================== */

/* Les halos : ils sont posés comme couches de background sur <body>, et non
   dans un élément dédié — le HTML est figé. `fixed` les ancre au viewport,
   comme dans la maquette. Teintes tirées de la palette (--vert, --ambre,
   --rouge) mais désaturées : au-delà de ~.10 d'opacité, le verre au-dessus
   prend une couleur franche et la page se met à briller. */
body{
  background-color:var(--bg-haut);
  background-image:
    radial-gradient(620px 620px at 4% -6%,  rgba(122,138,120,.10), transparent 72%),
    radial-gradient(680px 680px at 104% 18%,rgba(150,140,112,.09), transparent 72%),
    radial-gradient(580px 580px at -8% 44%, rgba(160,128,116,.08), transparent 72%),
    radial-gradient(660px 660px at 92% 68%, rgba(126,140,124,.08), transparent 72%),
    radial-gradient(700px 700px at 28% 108%,rgba(206,198,182,.16), transparent 72%);
  background-attachment:fixed;background-repeat:no-repeat}

/* Tout ce qui suit est conditionnel : sans backdrop-filter, un fond blanc à
   20 % ne floute rien et le texte passe à travers. Le repli est la peau
   neumorphique opaque déclarée plus haut, qui reste parfaitement valide. */
@supports ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){

  /* Grandes plaques */
  .hero,.sources,#bloc-recherche,.stats-retrait{
    background-color:var(--verre);
    -webkit-backdrop-filter:var(--verre-flou);backdrop-filter:var(--verre-flou)}
  .hero{box-shadow:var(--relief-fort),var(--verre-arete)}
  .sources,#bloc-recherche,.stats-retrait{box-shadow:var(--relief),var(--verre-arete)}
  footer{background-color:var(--verre-doux);
    -webkit-backdrop-filter:var(--verre-flou-doux);backdrop-filter:var(--verre-flou-doux);
    box-shadow:var(--relief-doux),var(--verre-arete-creux)}

  /* En-tête collant : le plus dense du fichier. Le constat du 03/09 tient
     toujours — un titre de carte ne doit pas traverser le logo — donc 85 %
     de blanc, pas 20 %. Le flou n'est ici qu'un complément. */
  header{background-color:var(--verre-dense);
    -webkit-backdrop-filter:var(--verre-flou-doux);backdrop-filter:var(--verre-flou-doux);
    box-shadow:0 6px 14px -8px var(--om-sombre),inset 0 -1px 0 rgba(255,255,255,.35)}

  /* Bandeau défilant */
  .bandeau{background-color:rgba(255,255,255,.22);
    -webkit-backdrop-filter:blur(14px) saturate(140%);backdrop-filter:blur(14px) saturate(140%);
    box-shadow:inset 0 -1px 0 rgba(255,255,255,.28),0 1px 3px rgba(0,0,0,.05)}

  /* Plaque du logo */
  .logo{background-color:rgba(255,255,255,.22);
    -webkit-backdrop-filter:blur(28px) saturate(125%);backdrop-filter:blur(28px) saturate(125%);
    box-shadow:var(--relief),var(--verre-arete)}

  /* Plaques de la navigation : meme verre, arete plus discrete que le logo.
     Sous 641 px il n'y a pas de plaque a habiller (cf. bloc ci-dessus). */
  @media (min-width:641px){
    /* TEINTE BEIGE, pas blanche. Constat du 23/09 sur capture : des plaques a
       rgba(255,255,255,.18) posees sur un en-tete deja blanc a 85 % ne se
       voyaient pas — du blanc sur du blanc, le verre n'a rien a refracter. On
       reprend la teinte de la page (#e8e4de) : c'est elle qui cree l'ecart
       avec l'en-tete. Et --relief plutot que --relief-doux, comme le logo :
       c'est l'ombre qui fait le bouton, la doux ne portait pas. */
    .entete-nav a{background-color:rgba(232,228,222,.72);
      -webkit-backdrop-filter:var(--verre-flou-doux);backdrop-filter:var(--verre-flou-doux);
      box-shadow:var(--relief),var(--verre-arete)}
    .entete-nav a:hover{background-color:rgba(232,228,222,.85);
      box-shadow:var(--creux-doux),var(--verre-arete-creux)}
  }

  /* Cartes et boutons secondaires : en relief, donc arête claire visible. */
  .offre,.offre-carte,.colonne,.score-detail,.src-liste li,.demo,
  .voir-plus,.renvois a,.pagination a,.comparer,.cand{
    background-color:rgba(255,255,255,.15);
    -webkit-backdrop-filter:blur(24px) saturate(120%);backdrop-filter:blur(24px) saturate(120%);
    box-shadow:var(--relief-doux),inset 1px 1px 0 rgba(255,255,255,.35)}

  /* Surfaces en creux : verre plus léger, contour interne au lieu de l'arête
     — un creux ne peut pas avoir de bord éclairé en haut à gauche. */
  .chiffres span,.recherche-champ,.techno,.techno-mini,.tag,.chip,.score,
  .missions,.argument,.stats-retrait .stat,.filtres-options label,
  .logo-src-lettre,.logo-tag-lettre{
    background-color:var(--verre-doux);
    -webkit-backdrop-filter:var(--verre-flou-doux);backdrop-filter:var(--verre-flou-doux)}
  .chiffres span,.stats-retrait .stat{box-shadow:var(--creux),var(--verre-arete-creux)}
  .recherche-champ{box-shadow:var(--creux-fort),var(--verre-arete-creux)}
  .recherche-champ:focus-within{box-shadow:var(--creux-fort),var(--verre-arete-creux)}
  .techno,.techno-mini,.tag,.chip,.score,.filtres-options label,
  .logo-src-lettre,.logo-tag-lettre{box-shadow:var(--creux-doux),var(--verre-arete-creux)}
  .missions,.argument{box-shadow:var(--creux),var(--verre-arete-creux)}

  /* Menus */
  .filtres-menus select,.tri select{background-color:rgba(255,255,255,.15);
    -webkit-backdrop-filter:blur(20px) saturate(118%);backdrop-filter:blur(20px) saturate(118%)}

  /* Les surfaces au survol restent des surfaces : sans redéclarer le fond,
     le hover repassait sur `var(--bg)` opaque et la carte clignotait. */
  .offre:hover,.offres-cartes .offre-carte:hover,.colonne:hover,
  .voir-plus:hover,.renvois a:hover,.pagination a:hover,.comparer:hover,
  .cand:hover{background-color:rgba(255,255,255,.22);
    box-shadow:var(--creux-doux),var(--verre-arete-creux)}
  .tag:hover,.chip:hover{background-color:rgba(255,255,255,.22);
    box-shadow:var(--relief-doux),inset 1px 1px 0 rgba(255,255,255,.35)}
  a.tag{background-color:rgba(255,255,255,.20);
    -webkit-backdrop-filter:blur(22px) saturate(120%);backdrop-filter:blur(22px) saturate(120%)}
  a.tag:hover{background-color:rgba(255,255,255,.28)}

  /* Les boutons primaires ne passent PAS en verre : ce sont les deux seules
     actions fortes du site, et un aplat d'encre à 9,6:1 est précisément ce
     qu'on attend d'un bouton primaire. Rappelé ici pour que les sélecteurs
     groupés ci-dessus ne les emportent pas. */
  .cta,.offre-carte .postuler{background-color:var(--fg);
    -webkit-backdrop-filter:none;backdrop-filter:none}
}

/* ── Garde-fou n°2 : transparence réduite ─────────────────────────────────
   Réglage système (macOS « Réduire la transparence », Windows équivalent).
   On rend toutes les surfaces opaques et on coupe le flou — la peau
   neumorphique seule reste lisible et complète. */
@media (prefers-reduced-transparency:reduce){
  body{background-image:none}
  header,.bandeau,.logo,.hero,.sources,#bloc-recherche,.stats-retrait,footer,
  .offre,.offre-carte,.colonne,.score-detail,.src-liste li,.demo,
  .voir-plus,.renvois a,.pagination a,.comparer,.cand,
  .filtres-menus select,.tri select,a.tag{
    -webkit-backdrop-filter:none;backdrop-filter:none;background-color:var(--bg)}
  .chiffres span,.recherche-champ,.techno,.techno-mini,.tag,.chip,.score,
  .missions,.argument,.stats-retrait .stat,.filtres-options label,
  .logo-src-lettre,.logo-tag-lettre{
    -webkit-backdrop-filter:none;backdrop-filter:none;background-color:var(--bg-doux)}
}

/* ── Garde-fou n°3 : contraste forcé ─────────────────────────────────────
   Extension de la règle déjà posée plus haut aux éléments ajoutés ici. En
   contraste forcé, ni les ombres ni les backdrop-filter ne sont rendus : sans
   bordure franche, tout devient un rectangle sans contour. */
@media (forced-colors:active){
  #bloc-recherche,.recherche-champ,.filtres-menus select,.tri select,
  .filtres-options label,.filtres-options input[type=checkbox],.cand,
  .hero,.sources,.chiffres span{border:1px solid;box-shadow:none;
    -webkit-backdrop-filter:none;backdrop-filter:none}
  body{background-image:none}
}

/* ── Garde-fou n°4 : mouvement réduit ───────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  .cand,.filtres-menus select,.tri select{transition:none}
}

/* ── Téléphone ────────────────────────────────────────────────────────── */
@media (max-width:640px){
  /* background-attachment:fixed sur un fond multi-couches coûte un repaint à
     chaque défilement sur iOS. Les halos redeviennent solidaires de la page. */
  body{background-attachment:scroll}
  #bloc-recherche{padding:20px 18px}
  .hero{padding:26px 20px 22px}
  .sources{padding:24px 20px}
  footer{padding:24px 20px;border-radius:var(--rayon)}
  .filtres-menus select,.tri select{flex:1 1 100%}
  .filtres-options{gap:10px}
  .filtres-options label,.tri{width:100%}
  .tri select{flex:1}
}

/* Surlignage des mots cherches. Un fond colore seul ne suffit pas : un
   visiteur daltonien doit voir la difference, d'ou le gras. */
#resultats mark { background: rgba(255, 214, 102, .38); color: inherit;
                  font-weight: 650; border-radius: 3px; padding: 0 1px; }

/* Recherche : le champ est l'action principale de la page, il doit se voir
   en premier. Karim, le 11/09 : "fouilli" - cinq menus, une case et un tri
   poses a la suite sur deux lignes de largeurs inegales. Desormais : un
   panneau, le champ, les raccourcis, puis les quatre menus en grille de
   largeurs egales, et le teletravail + le tri sur une ligne a part.
   Les id et data-filtre ne changent pas : le JS et recette_exhaustive.py
   les ciblent. Pas de "display" sur #bloc-recherche : il casserait `hidden`,
   qui cache le formulaire aux visiteurs sans JavaScript. */
/* Peau neumorphism (16/09) : le panneau avance, il n'a plus ni fond blanc
   ni bordure. La DISPOSITION posee le 11/09 est inchangee. */
#bloc-recherche{margin:6px 0 30px;padding:18px;background:var(--bg);
  border:0;border-radius:var(--rayon-grand);box-shadow:var(--relief)}
/* La LOUPE et la pilule appartiennent a design/infact.css (23/09).
   Ce bloc portait un second modele, incompatible : `.recherche-champ` en
   `position:relative` avec la loupe en absolu a `left:16px`, et `#q` faisant
   office de pilule visible (bordure + creux + `padding-left:50px`). Or
   infact.css fait de `.recherche-champ` une boite FLEX avec `padding:16px 20px`
   ou la loupe est un enfant normal. Resultat a l'ecran : la loupe se posait a
   16 px du bord de la boite, donc AVANT le bord de la pilule dessinee par #q,
   et pendait a gauche du champ.
   On garde ici la seule chose qui n'est pas dans infact.css : la taille de
   texte du champ, plus grande que le corps parce que c'est l'action
   principale de la page. Le reste (fond, creux, rayon, bague de focus portee
   par :focus-within) vient du fichier de design. */
#q{font:inherit;font-size:19px;color:var(--fg)}
#filtres{margin-top:14px}
.filtres-menus{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}
#filtres select{width:100%;min-width:0;box-sizing:border-box;font:inherit;font-size:14.5px;
  padding:9px 10px;border:1px solid var(--bord-fort);border-radius:var(--rayon);
  background:var(--bg);color:var(--fg);box-shadow:var(--creux-doux)}
.filtres-options{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:10px 16px;margin-top:12px;padding-top:12px;border-top:1px solid var(--bord)}
#filtres label{font-size:14.5px;color:var(--gris);display:flex;align-items:center;gap:8px}
#filtres .tri select{width:auto}
#compteur{margin:14px 0 8px;font-size:14.5px;color:var(--gris)}
@media (max-width:640px){
  #bloc-recherche{padding:12px}
  #q{font-size:17px}
  .filtres-menus{grid-template-columns:repeat(2,minmax(0,1fr))}
}
/* Les chips reprennent .chip de infact.css ; il ne manque que ce qu'un
   <button> impose : sa police ne s'herite pas, et son etat "pose" doit se
   voir autrement que par la couleur seule (WCAG 1.4.1). */
#chips{margin-top:12px}
button.chip{cursor:pointer;-webkit-appearance:none;appearance:none;font-family:var(--font-mono)}
button.chip[aria-pressed="true"]{background:var(--fg);border-color:var(--fg);color:#fff}
/* L'etat pose ne tient pas a la seule couleur (WCAG 1.4.1) : le fond
   s'inverse ET le libelle passe en gras. Un pictogramme en ::before a
   ete essaye puis retire : cette constante CSS est une chaine Python
   ordinaire, ou l'echappement CSS d'une coche est relu comme une
   sequence OCTALE - le site affichait "13 paris" au lieu de la coche.
   Vu a la capture d'ecran, invisible pour tous les tests HTML. */
button.chip[aria-pressed="true"]{font-weight:700}
button.chip:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
.techno-liste{margin-top:8px}

/* Suivi de candidatures : meme grammaire visuelle que le reste. */
/* Peau neumorphism (16/09) : ce bouton etait le dernier aplat blanc de la
   page d'offre - il ressortait comme une piece rapportee sur le beige. */
button.cand{cursor:pointer;-webkit-appearance:none;appearance:none;font:inherit;
  font-size:15px;padding:11px 16px;margin:10px 0 0;border:0;
  border-radius:var(--rayon);background:var(--bg);color:var(--fg);
  box-shadow:var(--relief-doux)}
/* Sans cette ligne, un `display` pose sur button.cand ecrase l'attribut
   `hidden` et le bouton reste VISIBLE quand JavaScript est coupe - un bouton
   qui ne fait rien. Constate par test_candidatures.py, invisible autrement :
   toutes les autres verifications tournent avec JavaScript actif. */
button.cand[hidden]{display:none}
button.cand:hover{box-shadow:var(--creux-doux)}
button.cand:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
/* L'etat "coche" ne tient pas a la seule couleur (WCAG 1.4.1) : le fond
   s'inverse ET le libelle passe en gras. Aucun pictogramme en ::before -
   voir la mesaventure de la coche octale dans recherche.py. */
button.cand[aria-pressed="true"]{background:var(--fg);border-color:var(--fg);
  color:#fff;font-weight:700}
.cand-rappel{margin:8px 0 0;font-size:14.5px;color:var(--gris)}
/* Marqueur pose par le JS sur les cartes des listes : on doit voir en
   parcourant une liste ce a quoi on a deja postule. */
.cand-marque{font-weight:700;font-size:13.5px;color:var(--gris);margin-left:6px}
.cand-ligne{border:0;border-radius:var(--rayon);
  padding:13px 15px;margin:0 0 10px;background:var(--bg);box-shadow:var(--relief-doux)}
.cand-ligne h3{margin:0 0 4px;font-size:16.5px}
.cand-ligne .meta{font-size:14px;color:var(--gris)}
.cand-ligne .bas{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-top:10px}
.cand-ligne select{font:inherit;font-size:14.5px;padding:6px 9px;
  border:1px solid var(--bord-fort);border-radius:var(--rayon);
  background:var(--bg);color:var(--fg);box-shadow:var(--creux-doux)}
.cand-ligne .retirer{font:inherit;font-size:14px;background:none;border:none;
  color:var(--gris);text-decoration:underline;cursor:pointer;padding:6px}
.cand-ligne .retirer:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
.cand-relance{font-size:14px;color:var(--fg);font-weight:700}
.cand-outils{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-top:18px}
.cand-outils button,.cand-import{font:inherit;font-size:14.5px;padding:8px 12px;
  border:0;border-radius:var(--rayon);background:var(--bg);
  color:var(--fg);cursor:pointer;box-shadow:var(--relief-doux)}
.cand-import input{display:none}
/* Le troisieme lien d'en-tete ("Candidatures") ne tient pas a cote du logo :
   infact.css le dit noir sur blanc, a 390 px le logo et DEUX liens font deja
   exactement la largeur de l'ecran. On etend donc a 640 px ce que le design
   faisait deja sous 360 px - la navigation passe sous le logo, sur sa propre
   ligne. Elle reste sur UNE ligne, ce que mesure test_rendu_design.py, et
   aucun lien n'est masque : masquer celui-ci sur telephone reviendrait a
   retirer la fonctionnalite a la moitie des visiteurs. */
@media (max-width:640px){
  header .wrap{flex-wrap:wrap;row-gap:6px}
  .entete-nav{width:100%;gap:10px}
}
