/* ============================================================
   marchesdepotiers.fr - site styles
   Palette derived from the logo:
     navy  #1d3a6e   teal  #2e8fa3   green #8cb63c
     coral #e4574c   sun   #f2b32c   paper #f7f5f0
   ============================================================ */

/* Design tokens. Every value used by this stylesheet lives here; a
   raw hex, radius or shadow written anywhere below is a bug.
   Reference: docs/charte-graphique.md (rendered on /admin/charte). */
:root {
  /* --- Brand ---------------------------------------------------- */
  --mdp-navy:  #1d3a6e;
  --mdp-teal:  #2e8fa3;
  --mdp-green: #8cb63c;
  --mdp-coral: #e4574c;
  --mdp-sun:   #f2b32c;
  --mdp-paper: #f7f5f0;
  --mdp-ink:   #26313d;
  --bs-primary: var(--mdp-teal);

  /* --- Derived tints: button hover / active states only ---------- */
  --mdp-teal-700:  #257487;
  --mdp-teal-800:  #1f6273;
  --mdp-green-700: #7aa233;
  --mdp-green-800: #6d9130;
  --mdp-coral-700: #cf4a40;
  --mdp-coral-800: #b93a30;
  --mdp-sun-700:   #e0a41f;
  --mdp-sun-800:   #d99e17;
  --mdp-on-sun:    #443204;   /* the only readable text on sun */

  /* --- Neutrals: four levels, no more --------------------------- */
  --mdp-line:      #e3e0d8;   /* standard block border */
  --mdp-line-soft: #eceae2;   /* inner separators, dashed rules */
  --mdp-muted:     #8a8578;   /* secondary text, meta */
  --mdp-faint:     #b3ad9d;   /* disabled text, placeholders */

  /* --- Surfaces -------------------------------------------------- */
  --mdp-surface:      #fff;
  --mdp-surface-soft: #fdfcfa;   /* second-plane card */
  --mdp-surface-mute: #f4f2ec;   /* image well, hovered row */
  --mdp-tint:         #eef7f8;   /* ultra-light turquoise: nav, footer */
  --mdp-tint-2:       #e6f3f6;   /* teal icon pill */
  --mdp-zebra:        #f7fbfc;   /* --mdp-tint halved: every other row */

  /* --- Typography ------------------------------------------------ */
  /* System stack, declared rather than inherited. No webfont: shared
     hosting, no FOUT, the logo already carries the brand voice. */
  --mdp-font-sans: system-ui, -apple-system, "Segoe UI", Roboto,
                   "Helvetica Neue", Arial, sans-serif;
  --fs-900: clamp(1.4rem, 1.3rem + .6vw, 1.75rem);  /* h1, page name */
  --fs-800: 1.25rem;   /* h2, section card title */
  --fs-700: 1.05rem;   /* h3, sub-section */
  --fs-600: .95rem;    /* h4 h5 h6, field group label */
  --fs-500: 1rem;      /* body */
  --fs-400: .875rem;   /* meta, .small */
  --fs-300: .78rem;    /* micro: chips, hints, dense cells */
  --fs-200: .7rem;     /* eyebrow, badge counters */
  --fw-normal: 400; --fw-medium: 500; --fw-semibold: 600; --fw-bold: 700;
  --lh-tight: 1.2; --lh-snug: 1.35; --lh-base: 1.55;

  /* --- Spacing: named after the Bootstrap steps (--sp-3 = p-3) --- */
  --sp-1: .25rem; --sp-2: .5rem; --sp-2h: .75rem;
  --sp-3: 1rem;   --sp-4: 1.5rem; --sp-5: 3rem;

  /* --- Radii: five values, a sixth one is a bug ------------------ */
  --r-sm:     .4rem;   /* thumbnails, inline images */
  --r-md:     .6rem;   /* inner blocks: tiles, mini-map */
  --r-lg:     .9rem;   /* the container: cards, nav, footer, modal */
  --r-pill:   999px;
  --r-circle: 50%;     /* avatars, nothing else */

  /* --- Shadows: navy-tinted, never black on cream paper ---------- */
  --sh-1: 0 1px 6px rgba(29, 58, 110, .08);    /* rest */
  --sh-2: 0 6px 18px rgba(29, 58, 110, .12);   /* hover */
  --sh-3: 0 4px 14px rgba(29, 58, 110, .18);   /* floating */
  --ring-primary: 0 0 0 2px var(--mdp-teal);         /* selection */
  --ring-pulse:   0 0 0 3px rgba(140, 182, 60, .25); /* "to do" dot */
  --sh-overlay:   0 8px 30px rgba(0, 0, 0, .5);      /* on dark */
}

body {
  background: var(--mdp-paper);
  color: var(--mdp-ink);
  font-family: var(--mdp-font-sans);
  line-height: var(--lh-base);
  /* Sticky footer: the footer's mt-auto pushes it to the bottom
     even on short pages (e.g. map view). */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* --- Headings ---------------------------------------------------
   Four visual levels: h1 page name, h2 section card, h3 sub-section,
   h4-h6 field group label. The tags carry the size, so a page never
   writes <h1 class="h3"> - that was a way of working around the
   native Bootstrap scale, and it made the hierarchy unreadable.
   --fs-900 and --fs-800 reproduce Bootstrap's .h3 and .h5 exactly,
   which is what makes this swap invisible. */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
  color: var(--mdp-navy);
  line-height: var(--lh-tight);
}
h1 { font-size: var(--fs-900); font-weight: var(--fw-bold); }
h2 { font-size: var(--fs-800); font-weight: var(--fw-semibold); }
h3 { font-size: var(--fs-700); font-weight: var(--fw-semibold); }
h4, h5, h6 { font-size: var(--fs-600); font-weight: var(--fw-semibold); }

a { color: var(--mdp-teal); }
a:hover { color: var(--mdp-navy); }

/* --- Bootstrap re-tint ------------------------------------------
   Every button variant used in the site is re-tinted here, through
   the --bs-btn-* custom properties (Bootstrap is vendored and never
   recompiled, so there is no Sass entry point). A variant left at
   its Bootstrap default would drop a stock red or orange into a
   palette that has its own coral and sun. */
.btn-primary {
  --bs-btn-bg: var(--mdp-teal);
  --bs-btn-border-color: var(--mdp-teal);
  --bs-btn-hover-bg: var(--mdp-teal-700);
  --bs-btn-hover-border-color: var(--mdp-teal-700);
  --bs-btn-active-bg: var(--mdp-teal-800);
  --bs-btn-active-border-color: var(--mdp-teal-800);
}
.btn-outline-primary {
  --bs-btn-color: var(--mdp-teal);
  --bs-btn-border-color: var(--mdp-teal);
  --bs-btn-hover-bg: var(--mdp-teal);
  --bs-btn-hover-border-color: var(--mdp-teal);
  --bs-btn-active-bg: var(--mdp-teal);
  --bs-btn-active-border-color: var(--mdp-teal);
}
.btn-success {
  --bs-btn-bg: var(--mdp-green);
  --bs-btn-border-color: var(--mdp-green);
  --bs-btn-hover-bg: var(--mdp-green-700);
  --bs-btn-hover-border-color: var(--mdp-green-700);
  /* Without these the pressed state fell back to Bootstrap's own
     dark green, which is not in the palette. */
  --bs-btn-active-bg: var(--mdp-green-800);
  --bs-btn-active-border-color: var(--mdp-green-800);
}
.btn-outline-success {
  /* Darker than --mdp-green: the raw green does not contrast enough
     as text on the paper background. */
  --bs-btn-color: #5f7d20;
  --bs-btn-border-color: var(--mdp-green);
  --bs-btn-hover-bg: var(--mdp-green);
  --bs-btn-hover-border-color: var(--mdp-green);
  --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: var(--mdp-green-700);
  --bs-btn-active-border-color: var(--mdp-green-700);
}
.btn-danger {
  --bs-btn-bg: var(--mdp-coral);
  --bs-btn-border-color: var(--mdp-coral);
  --bs-btn-hover-bg: var(--mdp-coral-700);
  --bs-btn-hover-border-color: var(--mdp-coral-700);
  --bs-btn-active-bg: var(--mdp-coral-800);
  --bs-btn-active-border-color: var(--mdp-coral-800);
}
.btn-outline-danger {
  --bs-btn-color: #c0392f;
  --bs-btn-border-color: var(--mdp-coral);
  --bs-btn-hover-bg: var(--mdp-coral);
  --bs-btn-hover-border-color: var(--mdp-coral);
  --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: var(--mdp-coral-800);
  --bs-btn-active-border-color: var(--mdp-coral-800);
}
/* Sun needs dark text at every state - white on #f2b32c fails. */
.btn-warning {
  --bs-btn-bg: var(--mdp-sun);
  --bs-btn-border-color: var(--mdp-sun);
  --bs-btn-color: var(--mdp-on-sun);
  --bs-btn-hover-bg: var(--mdp-sun-700);
  --bs-btn-hover-border-color: var(--mdp-sun-700);
  --bs-btn-hover-color: var(--mdp-on-sun);
  --bs-btn-active-bg: var(--mdp-sun-800);
  --bs-btn-active-border-color: var(--mdp-sun-800);
  --bs-btn-active-color: var(--mdp-on-sun);
}
.btn-outline-warning {
  --bs-btn-color: #8a6a10;
  --bs-btn-border-color: var(--mdp-sun);
  --bs-btn-hover-bg: var(--mdp-sun);
  --bs-btn-hover-border-color: var(--mdp-sun);
  --bs-btn-hover-color: var(--mdp-on-sun);
  --bs-btn-active-bg: var(--mdp-sun-800);
  --bs-btn-active-border-color: var(--mdp-sun-800);
  --bs-btn-active-color: var(--mdp-on-sun);
}
/* Neutral buttons: warm grays from the palette, not Bootstrap's
   cool #6c757d which reads blue next to the paper background. */
.btn-outline-secondary {
  --bs-btn-color: #6b6659;
  --bs-btn-border-color: var(--mdp-line);
  --bs-btn-hover-bg: var(--mdp-surface-mute);
  --bs-btn-hover-color: var(--mdp-ink);
  --bs-btn-hover-border-color: #d7d3c8;
  --bs-btn-active-bg: #e9e6dd;
  --bs-btn-active-color: var(--mdp-ink);
  --bs-btn-active-border-color: #d7d3c8;
}

/* Controles de formulaire. Bootstrap les laisse en #0d6efd : cases a
   cocher, interrupteurs et anneaux de focus etaient donc bleus sur
   tout le site — publier une edition, ouvrir les inscriptions, les
   profils du compte. La passe de re-teinte n'avait couvert que les
   boutons et les badges. */
.form-check-input:checked {
  background-color: var(--mdp-teal);
  border-color: var(--mdp-teal);
}
.form-check-input:focus {
  border-color: var(--mdp-teal);
  box-shadow: 0 0 0 .25rem rgba(46, 143, 163, .25);
}
/* Le pouce de l'interrupteur au focus est un SVG bleu encode dans une
   data-URL. :not(:checked) est indispensable — sans lui cette regle
   passerait apres celle de Bootstrap et repeindrait en turquoise le
   pouce d'un interrupteur ACTIF, qui doit rester blanc. */
.form-switch .form-check-input:focus:not(:checked) {
  --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%232e8fa3'/%3e%3c/svg%3e");
}
.form-control:focus,
.form-select:focus {
  border-color: var(--mdp-teal);
  box-shadow: 0 0 0 .25rem rgba(46, 143, 163, .25);
}

.text-primary { color: var(--mdp-teal) !important; }

/* Badges follow the same palette as the buttons: app_status_badge()
   alone emits eight of them, and a stock Bootstrap red next to a
   coral button reads as two different alarms. */
.badge.text-bg-primary   { background-color: var(--mdp-teal) !important; }
.badge.text-bg-success   { background-color: var(--mdp-green) !important; color: #fff !important; }
.badge.text-bg-danger    { background-color: var(--mdp-coral) !important; color: #fff !important; }
.badge.text-bg-warning   { background-color: var(--mdp-sun) !important; color: var(--mdp-on-sun) !important; }
.badge.text-bg-info      { background-color: var(--mdp-tint-2) !important; color: var(--mdp-teal-800) !important; }
.badge.text-bg-secondary { background-color: var(--mdp-surface-mute) !important; color: #6b6659 !important; }
/* Progress badges (profile completion): sun tone, distinct from the
   teal buttons sitting right next to them. */
.badge.text-bg-sun { background-color: var(--mdp-sun); color: var(--mdp-on-sun); }

/* Placeholders: light enough that they can't be mistaken for a
   filled-in value (Bootstrap's default gray reads as real text). */
.form-control::placeholder { color: var(--mdp-faint); opacity: 1; }

/* ================================================================
   PRIMITIVES
   The shared building blocks. Everything below is mobile-first:
   the bare declaration is the phone, media queries only ever add.
   ================================================================ */

/* --- State tones -------------------------------------------------
   Five triplets, carried by a class, read by any component that
   wants to be colourable. A component consumes --tone-bg/fg/line
   and nothing else, so a new coloured thing costs no new palette. */
.tone-ok      { --tone-bg: #eaf3de; --tone-fg: #4c6b18; --tone-line: #d5e6bd; }
.tone-wait    { --tone-bg: #faeeda; --tone-fg: #8a6a10; --tone-line: #f0dcbb; }
.tone-info    { --tone-bg: var(--mdp-tint-2); --tone-fg: var(--mdp-teal-800); --tone-line: #c9e6ea; }
.tone-neutral { --tone-bg: var(--mdp-surface-mute); --tone-fg: #6b6659; --tone-line: var(--mdp-line); }
.tone-bad     { --tone-bg: #fdecea; --tone-fg: #9c2b22; --tone-line: #f5cdc9; }

/* Decorative tones for potter production groups. These are families,
   not states: they must not be mistaken for ok/wait/bad. */
.tone-terre   { --tone-bg: #fdf3dc; --tone-fg: #a2751a; --tone-line: #f2ddaa; }
.tone-tech    { --tone-bg: #e7eefb; --tone-fg: #274690; --tone-line: #c3d3ef; }
.tone-univers { --tone-bg: #eef6e3; --tone-fg: #5f7d20; --tone-line: #cfe2b6; }

.badge.tone-ok, .badge.tone-wait, .badge.tone-info,
.badge.tone-neutral, .badge.tone-bad {
  background: var(--tone-bg);
  color: var(--tone-fg);
  border: 1px solid var(--tone-line);
  font-weight: var(--fw-semibold);
}

/* --- The card ----------------------------------------------------
   One declaration for every panel in the site. The named variants
   below only add what is specific to them (layout, hover, media). */
.form-card, .market-card, .dir-card, .ed-card,
.poster-card, .orga-todo, .media-item, .part-stat {
  background: var(--mdp-surface);
  border: 1px solid var(--mdp-line);
  border-radius: var(--r-lg);
}
.card-hover { transition: transform .12s ease, box-shadow .12s ease; }
.card-hover:hover { transform: translateY(-2px); box-shadow: var(--sh-2); }
.card-flat { box-shadow: none; }

/* --- Page head ---------------------------------------------------
   Title left, consultation actions right. On a phone the actions
   take the full width and sit under the title; from 768px they
   return to the right of it. */
.page-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
}
/* Sous 768px le bloc titre prend toute la largeur : les actions
   passent donc TOUJOURS sous lui, quelle que soit la longueur du
   titre. Sans cette base, le point de bascule dependait de la
   largeur du titre — les actions descendaient sur une fiche potier
   et restaient a droite sur une fiche marche, a la meme taille
   d'ecran. */
.page-head-main { min-width: 0; flex: 1 1 100%; }
@media (min-width: 768px) {
  .page-head-main { flex: 1 1 16rem; }
}
/* Le visuel s'aligne sur le HAUT du titre, jamais sur le milieu du
   bloc : centre, il glissait vers le bas des que le sous-titre gagnait
   une ligne, et deux fiches voisines ne se ressemblaient plus. */
.page-head-main.has-media {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  flex-wrap: wrap;
}
.page-head-media { flex: none; }
.page-head-text { min-width: 0; }
.page-head-sub { color: var(--mdp-muted); font-size: var(--fs-400); margin-top: var(--sp-1); }
/* Un sous-titre qui enumere des FAITS — depuis quand, combien
   d'abonnes — les pose en segments, chacun avec son icone, comme la
   seconde ligne d'une ligne de liste (charte 7.5). Ecrits comme une
   phrase ponctuee de « · », ils se coupaient n'importe ou et les
   separateurs finissaient en bout de ligne. */
.head-facts { display: flex; flex-wrap: wrap; align-items: baseline; gap: .1rem var(--sp-2h); }
.head-facts > span { display: inline-flex; align-items: baseline; gap: var(--sp-1); min-width: 0; }
.head-facts i { color: var(--mdp-faint); flex: none; }
/* L'objet de la page dans son sous-titre : le nom du marche sur une
   candidature, celui d'un dossier sur un examen. Le h1 nomme l'ecran,
   celui-ci nomme ce qu'on y traite — il se detache donc du contexte
   qui l'entoure, sans aller jusqu'a rivaliser avec le titre. */
.page-head-object {
  display: inline-block;
  font-size: var(--fs-700);
  font-weight: var(--fw-semibold);
  color: var(--mdp-navy);
  line-height: var(--lh-tight);
}
/* align-items:center, pas la valeur par defaut : un flex etire ses
   enfants, et un btn-sm etire a la hauteur d'un bouton normal garde
   son texte collé en haut (le padding ne se recentre pas). */
.page-head-acts { display: flex; gap: var(--sp-2); flex-wrap: wrap; align-items: center; }
.page-head-acts > .btn { flex: 1 1 auto; }
@media (min-width: 576px) {
  .page-head-acts > .btn { flex: 0 0 auto; }
}
@media (min-width: 768px) {
  .page-head-acts { justify-content: flex-end; }
}
/* --- En-tete de carte de section ---------------------------------
   Meme grammaire que .page-head, un cran plus bas : le titre h2, sa
   phrase d'explication, et les actions qui portent sur CETTE section.
   Meme regle mobile : sous 768px les actions passent sous le titre. */
.section-head { margin-bottom: var(--sp-3); }
/* Le titre et ses actions partagent une ligne ; la phrase passe
   dessous, pleine largeur. */
.section-head-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
/* Sous 768px le titre prend la ligne : les actions passent dessous,
   meme regle que .page-head. */
.section-head-row > h2 { flex: 1 1 100%; min-width: 0; }
/* Titre portant une pastille d'entite (option 'icon' de section_head).
   flex-wrap indispensable : sans lui le badge d'etat ne peut pas
   passer sous le titre et deborde de la carte sur un telephone. */
.section-head-row > h2.has-ico {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
/* Un badge accole a un titre se lit un cran plus bas que lui : le
   .75em de Bootstrap le calcule sur la taille du titre, ce qui donne
   un badge de 15px dans un h2. Taille fixe, echelle du site. */
.page-head h1 > .badge,
.section-head h2 > .badge { font-size: var(--fs-300); vertical-align: middle; }
@media (min-width: 768px) {
  .section-head-row > h2 { flex: 0 1 auto; }
}
.section-head-sub {
  color: var(--mdp-muted);
  font-size: var(--fs-400);
  margin-top: var(--sp-1);
}
.section-head-acts { display: flex; gap: var(--sp-2); flex-wrap: wrap; align-items: center; }
.section-head-acts > .btn { flex: 1 1 auto; }
@media (min-width: 576px) {
  .section-head-acts > .btn { flex: 0 0 auto; }
}
@media (min-width: 768px) {
  .section-head-acts { justify-content: flex-end; }
}

/* --- Bandeau de titre de section (essai, espace Mon compte) -------
   L'en-tete de carte prend un fond teinte qui court d'un bord a
   l'autre : les marges negatives annulent le p-4 de la carte, le
   rayon reprend le sien moins l'epaisseur du filet. Suppose une carte
   en p-4 dont le section_head est le premier enfant — c'est le cas
   partout dans « Mon compte ». */
.section-band .form-card > .section-head:first-child {
  margin: calc(-1 * var(--sp-4)) calc(-1 * var(--sp-4)) var(--sp-4);
  padding: var(--sp-2h) var(--sp-4);
  background: var(--mdp-tint);
  border-bottom: 1px solid var(--mdp-line);
  border-radius: calc(var(--r-lg) - 1px) calc(var(--r-lg) - 1px) 0 0;
}
/* Sur le bandeau, la pastille d'entite s'inverse : sa teinte
   (--mdp-tint-2, #e6f3f6) se confondait avec le fond (--mdp-tint,
   #eef7f8), huit points d'ecart. Surface blanche cernee du meme filet
   que le bandeau, icone turquoise. Le selecteur reprend celui du
   bandeau, et pas .section-band .ico-badge : dans « Mes profils » les
   pastilles vivent sur carte blanche, ou la teinte fonctionne — et ou
   leur vert dit que le profil est actif. */
.section-band .form-card > .section-head:first-child .ico-badge {
  background: var(--mdp-surface);
  border: 1px solid var(--mdp-line);
  color: var(--mdp-teal);
}

/* Texte saisi par un utilisateur, rendu tel qu'il l'a frappe : ses
   retours a la ligne comptent. Une classe, pas un style en ligne — la
   charte l'interdit (15). */
.prewrap { white-space: pre-line; }

/* Ligne d'une liste NON cliquable — un justificatif attendu, une
   piece a fournir. Meme cadre que .list-row, sans l'ancrage ni le
   survol : rien n'y mene. Ecrite jusqu'ici en `border rounded`, donc
   avec la bordure froide de Bootstrap au lieu de --mdp-line. */
.req-row {
  border: 1px solid var(--mdp-line);
  border-radius: var(--r-md);
}

.eyebrow {
  font-size: var(--fs-200);
  letter-spacing: .1em;
  text-transform: uppercase;
  font-weight: var(--fw-bold);
  color: var(--mdp-muted);
}

/* --- Filter bar --------------------------------------------------
   No pixel widths: each control declares a flex-basis in rem and is
   free to shrink. min-width:0 is what actually lets a select shrink
   below its content width inside a flex row. */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  align-items: flex-end;
}
.filter-field { flex: 1 1 var(--ff-basis, 9rem); min-width: 0; }
.filter-field--wide { --ff-basis: 14rem; }
.filter-field--search { --ff-basis: 100%; }
@media (min-width: 576px) {
  .filter-field--search { --ff-basis: 16rem; flex-grow: 2; }
}
/* Barre compacte : la recherche partage sa ligne avec le bouton de
   repli des le telephone, au lieu de prendre la ligne entiere et de
   le renvoyer dessous. Ne vaut que si ce bouton est reduit a son
   icone — avec un libelle, il ecraserait la recherche a 320px. */
.filter-bar-tight .filter-field--search { --ff-basis: 8rem; }

/* The secondary filters, folded away on a phone behind the toggle.
   The search field stays outside this group: it is the primary
   filter and must never be hidden.
   From 768px the group dissolves (display:contents) so its fields
   join the search on a single flex row - a collapsible wrapper must
   not become a layout row of its own on desktop. */
.filter-group {
  flex-basis: 100%;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  align-items: flex-end;
}
@media (min-width: 768px) {
  .filter-group,
  .filter-group:not(.show) { display: contents; }
}
/* Variante : le groupe reste replie a TOUTES les largeurs. Il ne
   porte pas .filter-group — celle-ci se deplie de force des 768px et
   couvrirait le display:none de Bootstrap. Ici on laisse .collapse
   faire son travail et on ne decrit que la disposition ouverte. */
.filter-fold {
  flex-basis: 100%;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  align-items: center;
}
/* Dans un repli, le libelle est au-dessus de son controle sur les
   ecrans etroits et a cote des 576px. Le basculement se fait au
   palier, pas champ par champ : laisse au flex-wrap, chaque champ
   bascule a SA largeur de libelle — « Etat du dossier » passe
   au-dessus quand « Trier par », plus court, reste a cote, et le
   repli a l'air casse. Une largeur plancher commune reglait le seuil
   mais creusait un blanc derriere le libelle le plus court. */
.filter-fold .filter-field {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--sp-1);
}
.filter-fold .filter-field > label { margin-bottom: 0; }
.filter-fold .filter-field > select,
.filter-fold .filter-field > .input-group { min-width: 0; }
/* Tant que le repli est une rangee a lui, il s'ecrit en DEUX COLONNES
   exactes : la base d'un champ vaut la moitie de la largeur, gouttiere
   deduite. Les deux filtres remplissent la premiere rangee, le tri se
   pose seul sur la seconde — a la meme largeur, donc pile sous celui
   du dessus. Une base fixe voisine (9rem) le laissait 19 px plus
   court : ni large, ni aligne, il avait l'air rate plutot que range.
   Le plancher de 9rem garde la main sous ~355px, ou deux colonnes
   couperaient « Eure-et-Loir (28) » en plein milieu : les champs
   s'empilent alors, et seul le tri reste court. */
.filter-fold .filter-field { --ff-basis: max(9rem, calc(50% - var(--sp-2) / 2)); }
/* Le tri NE GRANDIT PAS : c'est ce qui l'empeche de s'etaler sur la
   rangee entiere quand il y tombe seul. Le reglage le moins important
   du repli etait jusqu'ici le plus large — la hierarchie se joue sur
   le rapport des largeurs, pas sur une taille de police. */
.filter-fold .filter-field--sort { flex-grow: 0; }
@media (min-width: 576px) {
  .filter-fold .filter-field {
    flex-direction: row;
    align-items: center;
    gap: var(--sp-2);
  }
  .filter-fold .filter-field > label { flex: none; }
  /* La LARGEUR reprend la base, elle ne s'y ajoute pas. Sans elle, un
     <select> se dimensionne sur son option la plus longue et la
     remonte au repli : « Association culturelle / de quartier /
     Comité des Fêtes » portait celui de /organisateurs a 990px, et le
     filtre d'entete se retrouvait renvoye sous la barre. Un choix
     long est une info de la liste ouverte, pas une largeur a reserver
     — le champ grandit ensuite avec la place disponible. */
  .filter-fold .filter-field > select,
  .filter-fold .filter-field > .input-group { flex: 1 1 8rem; width: 8rem; }
}
/* Barre compacte : tout est sur une seule rangee de controles, donc
   c'est le centre qui aligne, pas le pied. */
.filter-bar-tight { align-items: center; }
/* Des 768px le groupe ouvert rejoint la recherche sur sa ligne au lieu
   de s'ouvrir en dessous : la place existe, une deuxieme rangee ne
   servirait qu'a repousser la liste. */
@media (min-width: 768px) {
  .filter-fold { flex-basis: auto; }
  /* Le repli n'est plus une rangee : sa largeur suit son contenu, et
     un pourcentage n'aurait plus de reference stable a quoi se
     mesurer. Retour a la base fixe commune, et le tri reprend sa part
     — sur une ligne partagee par cinq controles, aucun ne domine. */
  .filter-fold .filter-field { --ff-basis: 9rem; }
  .filter-fold .filter-field--sort { flex-grow: 1; }
}
/* Le filtre qui reste HORS du repli, sur les ecrans publics :
   « autour de moi » est la porte d'entree d'un visiteur sur telephone,
   range derriere une icone il ne se decouvrirait plus. Il prend sa
   propre ligne sous 576px — la recherche et les deux boutons
   remplissent deja la premiere a 320px — et rejoint la barre ensuite. */
.filter-geo {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--sp-2);
  flex-basis: 100%;
  /* Sans min-width, le plancher automatique d'un element flex est son
     min-content : le bloc restait a 331px dans une barre de 262 et
     debordait a 320px, curseur compris. Le zero rend la compression a
     ses enfants, ce que nowrap suppose. */
  min-width: 0;
}
/* Le curseur de rayon prend ce qui reste, il ne reserve rien. Avec sa
   largeur fixe de 120px et un libelle « Rayon : 30 km » en toutes
   lettres, le bloc actif tenait sur QUATRE lignes a 375px. Ici tout
   ce qui l'entoure est incompressible et court : bouton, valeur,
   croix — le curseur absorbe la difference et la ligne reste une. */
.range-radius { flex: 1 1 3rem; min-width: 0; width: auto; }
@media (min-width: 576px) {
  .filter-geo { flex-basis: auto; }
}
/* Le compteur est un inline-block borde : pose dans la boite de ligne
   du bouton, il la poussait a 32,1px quand ses voisins font 31, et le
   bouton demarrait 0,5px plus haut — mesure sur l'accueil. En flex il
   devient un element a part entiere, aligne sur le centre, et ne
   grandit plus rien. La gouttiere remplace l'espace du HTML, que le
   flex ne rend pas. */
.filter-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
}
.filter-toggle .badge { font-size: var(--fs-200); line-height: 1; }
.sort-ctl { margin-bottom: var(--sp-2); }
/* Curseur de rayon, turquoise comme le bouton d'a cote. accent-color
   ne suffit PAS : Bootstrap dessine le pouce lui-meme, en #0d6efd
   ecrit en dur, avec -webkit-appearance:none — le navigateur n'a donc
   plus de controle natif a teinter. Il faut reprendre les
   pseudo-elements un par un. */
.range-radius { accent-color: var(--mdp-teal); }
.range-radius::-webkit-slider-thumb { background-color: var(--mdp-teal); }
.range-radius::-webkit-slider-thumb:active { background-color: var(--mdp-teal-700); }
.range-radius::-moz-range-thumb { background-color: var(--mdp-teal); }
.range-radius::-moz-range-thumb:active { background-color: var(--mdp-teal-700); }
.range-radius:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 .25rem rgba(46, 143, 163, .25); }
.range-radius:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 .25rem rgba(46, 143, 163, .25); }

/* --- Form action bar ---------------------------------------------
   Sticky on phones: a form several screens tall must not hide its
   own save button. Static again from 576px, where the button is
   reachable without it. */
.form-actions {
  display: flex;
  gap: var(--sp-2);
  align-items: center;
  flex-wrap: wrap;
  margin-top: var(--sp-4);
  position: sticky;
  bottom: 0;
  z-index: 3;
  /* Meme retrait sur les quatre cotes : la barre flotte au-dessus du
     formulaire, un cadre plus mince sur les cotes qu'en haut se voit. */
  padding: var(--sp-2);
  background: var(--mdp-surface);   /* fallback: Safari < 15.4 */
  background: color-mix(in srgb, var(--mdp-surface) 92%, transparent);
  backdrop-filter: blur(4px);
  border-top: 1px solid var(--mdp-line);
  box-shadow: var(--sh-3);
}
@media (min-width: 576px) {
  .form-actions {
    position: static;
    background: none;
    backdrop-filter: none;
    border-top: 0;
    box-shadow: none;
    padding: 0;
  }
}
/* Le bouton d'enregistrement prend toute la largeur de son module, a
   toutes les tailles d'ecran : une seule silhouette d'un formulaire a
   l'autre, quelle que soit la longueur du libelle. Bouton canonique :
   `btn btn-primary w-100`. (L'utilitaire .w-sm-auto, qui lui rendait
   sa largeur naturelle au-dessus de 576px, n'a plus d'emploi.) */

/* Carte d'interrupteur d'etat (publier, ouvrir les inscriptions) :
   libelle a gauche, interrupteur a droite, sur la MEME ligne a toutes
   les largeurs.
   Il passait sous le texte des que la phrase ne tenait plus : le bloc
   de gauche gardait sa largeur de contenu, donc le formulaire etait
   renvoye a la ligne — a 600px il descendait alors meme que le
   libelle tenait encore sur une ligne. C'est au texte de se replier,
   pas a la commande de partir ailleurs : min-width:0 le lui permet,
   nowrap l'y oblige.
   flex-start, et non center : sur deux ou trois lignes, l'interrupteur
   flottait au milieu du paragraphe. Il se cale sur la PREMIERE ligne,
   celle qui porte l'etat (meme principe qu'une icone, cf. 7.6). */
.toggle-card {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: nowrap;
  gap: var(--sp-2);
}
.toggle-card > :first-child { min-width: 0; }
.toggle-card > form { flex: none; }

/* --- Bloc image en tete de module --------------------------------
   Le visuel a gauche, ses boutons a droite (empiles et de meme
   largeur, cf. .btn-even), la ligne de caracteristiques sous les
   boutons. Detache du formulaire qui suit par une simple respiration
   (pas de filet : l'image se detache deja seule). */
.media-inline {
  display: flex;
  align-items: center;   /* boutons + caracteristiques centres sur l'image */
  gap: var(--sp-3);
  flex-wrap: nowrap;     /* les boutons restent a droite, meme sur mobile */
  margin-bottom: var(--sp-4);
}
.media-inline > :first-child { flex: none; }
/* La colonne boutons + caracteristiques retrecit au lieu de passer a
   la ligne : min-width:0 pour qu'elle puisse vraiment descendre sous
   sa largeur de contenu, les libelles s'y enroulent. */
.media-inline > div:last-child { min-width: 0; flex: 1 1 auto; }
/* Meme respiration entre les deux boutons et sous la pile. */
.media-inline .field-hint { margin: var(--sp-2) 0 0; }

/* Repeatable input rows (document + type + delete): they must wrap,
   otherwise the text input is crushed to a few characters.
   Le CADRE dit le groupe, et il n'est pas decoratif : en se repliant
   sur deux rangs a 375px, la ligne devenait haute de 70px alors que
   deux lignes voisines n'etaient separees que de 8px. L'ecart interne
   depassait l'ecart externe, donc le bouton d'une ligne se lisait
   comme celui de la suivante. La proximite seule ne pouvait pas
   trancher : il fallait une frontiere. C'est celle de .req-row, qui
   montre deja ces memes objets en lecture. */
.repeat-line {
  display: flex;
  gap: var(--sp-2);
  flex-wrap: wrap;
  align-items: center;
  border: 1px solid var(--mdp-line);
  border-radius: var(--r-md);
  padding: var(--sp-2);
}
.repeat-line > .form-control { flex: 1 1 12rem; min-width: 0; }

/* --- Groupe de boutons de meme largeur ---------------------------
   Deux boutons qui vont ensemble prennent la meme largeur, celle du
   libelle le plus long : sinon leur bord fait un escalier, et l'ecart
   se lit comme une difference d'importance. En pile, une colonne en
   max-content suffit ; minmax(0, …) la laisse retrecir sur une carte
   etroite, ou les libelles s'enroulent au lieu de deborder. Les
   boutons vivent souvent dans un <form>, la largeur doit donc
   descendre jusqu'a eux. */
.btn-even {
  display: grid;
  grid-template-columns: minmax(0, max-content);
  gap: var(--sp-2);
}
.btn-even .btn { width: 100%; }
/* Modificateur : cote a cote des 576px, empiles en dessous. Des
   colonnes en 1fr dans un conteneur en max-content prennent toutes la
   largeur du plus large des boutons — c'est ce qui les egalise. */
@media (min-width: 576px) {
  .btn-even-row {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    width: max-content;
    max-width: 100%;
  }
}

/* --- Stacked tables ----------------------------------------------
   Under 768px a table becomes a list of bordered cards: the header
   disappears and each cell is prefixed by its data-th. Above, it is
   a plain table again. Every <table> in the site carries this. */
.table-stack thead { display: none; }
/* The zebra tint: the site's turquoise, halved. It is the colour of
   the navbar and the footer, taken down to where it barely registers
   — a stripe, not a state. Being a different family from the beige
   of a hovered row, it never competes with it.
   The border colour goes with it: Bootstrap's default rule is a cool
   grey that had no token behind it. --mdp-line-soft is the site's
   inner separator. */
.table-stack {
  --bs-table-striped-bg:   var(--mdp-zebra);
  --bs-table-border-color: var(--mdp-line-soft);
}
.table-stack,
.table-stack tbody,
.table-stack tr,
.table-stack td { display: block; width: 100%; }
.table-stack tr {
  border: 1px solid var(--mdp-line);
  border-radius: var(--r-md);
  padding: var(--sp-2h);
  margin-bottom: var(--sp-2);
  background: var(--mdp-surface);
}
/* One row in two is tinted, at every width — no class to write, so no
   table can forget it. Two carriers for one tint, which is why the
   rule needs no breakpoint: stacked, the row IS the card and takes
   the colour itself; as a table, the cells take it through
   --bs-table-bg-type, so a contextual row (.table-danger) darkens
   its own tint instead of being covered by ours. Painting the cells
   alone would leave a white rim inside the stacked card, where the
   row's padding is. */
.table-stack > tbody > tr:nth-of-type(even) {
  background: var(--mdp-zebra);
  --bs-table-bg-type: var(--bs-table-striped-bg);
}
.table-stack td { border: 0; padding: var(--sp-1) 0; }
.table-stack td:empty { display: none; }
.table-stack td[data-th]::before {
  content: attr(data-th) " ";
  font-weight: var(--fw-semibold);
  color: var(--mdp-muted);
  font-size: var(--fs-300);
}
.table-stack td.is-actions {
  display: flex;
  gap: var(--sp-2);
  flex-wrap: wrap;
  margin-top: var(--sp-1);
  padding-top: var(--sp-2);
  border-top: 1px solid var(--mdp-line-soft);
  text-align: left !important;
}
.table-stack td.is-actions form { display: inline-block; }
@media (min-width: 768px) {
  .table-stack { display: table; }
  .table-stack thead { display: table-header-group; }
  .table-stack tbody { display: table-row-group; }
  .table-stack tr {
    display: table-row;
    border: 0;
    padding: 0;
    margin: 0;
    background: none;
  }
  .table-stack td {
    display: table-cell;
    width: auto;
    padding: .5rem;
    border-bottom: 1px solid var(--mdp-line-soft);
  }
  .table-stack td[data-th]::before { content: none; }
  .table-stack td.is-actions {
    display: table-cell;
    border-top: 0;
    margin-top: 0;
    padding-top: .5rem;
    text-align: right !important;
  }
}

/* Campaign progress bar: a fixed track that must not collapse when
   the table is dense (it was a style="min-width" on the header). */
.campaign-progress { height: 6px; }
@media (min-width: 768px) {
  .table-stack .col-progress { min-width: 140px; }
}

/* --- Exhibitor grid (market page) --------------------------------
   Auto-filled columns so the row reflows on a phone without a
   breakpoint of its own. */
.exhibitor-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: var(--sp-3);
}
.exhibitor {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--sp-2);
  color: inherit;
}
button.exhibitor { background: none; border: 0; padding: 0; font: inherit; }
.exhibitor-name { font-size: var(--fs-400); line-height: var(--lh-tight); }
.exhibitor-person {
  font-size: var(--fs-300);
  line-height: var(--lh-tight);
  color: var(--mdp-muted);
  margin-top: -.3rem;
}
a.exhibitor:hover .exhibitor-name,
button.exhibitor:hover .exhibitor-name { text-decoration: underline; }

/* --- Styleguide (/admin/charte) ----------------------------------
   Only used by the reference page. Kept here rather than inline so
   the page is styled by the very sheet it documents. */
.sg-swatches { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.sg-swatch { display: flex; align-items: center; gap: var(--sp-2); flex: 0 0 15rem; }
.sg-chip {
  width: 40px; height: 40px; flex: none;
  border-radius: var(--r-md);
  border: 1px solid var(--mdp-line);
}
.sg-type > div {
  display: flex; align-items: baseline; gap: var(--sp-3);
  padding: var(--sp-2) 0;
  border-bottom: 1px solid var(--mdp-line-soft);
}
.sg-type > div:last-child { border-bottom: 0; }
.sg-tag {
  flex: none; width: 4.5rem;
  font-size: var(--fs-200); font-family: monospace;
  color: var(--mdp-muted);
}
/* Demo frame: makes clear where the component starts and stops. */
.sg-demo {
  border: 1px dashed var(--mdp-line);
  border-radius: var(--r-md);
  padding: var(--sp-3);
  background: var(--mdp-surface-soft);
}
.sg-code {
  background: var(--mdp-surface-mute);
  border-radius: var(--r-md);
  padding: var(--sp-2h);
  font-size: var(--fs-300);
  margin-top: var(--sp-2);
  overflow-x: auto;
}
/* Stands in for an <h1> in the page-head demo: the reference page
   must not carry two h1 of its own. */
.sg-h1 {
  font-size: var(--fs-900);
  font-weight: var(--fw-bold);
  color: var(--mdp-navy);
  line-height: var(--lh-tight);
}
.sg-box {
  width: 64px; height: 64px;
  background: var(--mdp-surface);
  border: 1px solid var(--mdp-line);
  margin-bottom: var(--sp-1);
}

/* --- Mini list ---------------------------------------------------
   A short "latest N" list: a label that can wrap, a meta value that
   cannot. Replaces the header-less 3-column tables that used to
   overflow on a phone. */
/* Le zebrage deborde le texte de part et d'autre — une bande qui
   s'arrete pile sur la premiere lettre n'en est pas une. La liste
   reprend cette marge en negatif pour rester alignee sur le reste
   de la carte. */
.mini-list {
  list-style: none;
  padding: 0;
  margin: 0 calc(-1 * var(--sp-2));
  font-size: var(--fs-400);
}
/* Variante dense de la ligne cliquable (charte 7.5) : meme regle,
   sans le cadre — l'ancrage et le survol sont la, seul le skin change. */
.mini-list li {
  position: relative;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-2);
  padding: var(--sp-2);
  border-bottom: 1px solid var(--mdp-line-soft);
  transition: background-color .12s ease;
}
.mini-list li:last-child { border-bottom: 0; }
/* Une ligne sur deux, comme un tableau (charte 7.2) : c'est la meme
   lecture, la meme teinte. Le survol reste le beige de partout — les
   deux couleurs ne sont pas de la meme famille, il se lit donc aussi
   bien sur une ligne teintee que sur une blanche. */
.mini-list li:nth-of-type(even) { background: var(--mdp-zebra); }
@media (hover: hover) {
  .mini-list li:has(a.stretched-link):hover { background: var(--mdp-surface-mute); }
}
.mini-list li:has(a.stretched-link):active { background: var(--mdp-surface-mute); }
.mini-list a.stretched-link { text-decoration: none; }
.mini-list .ml-main { min-width: 0; }
.mini-list .ml-meta { flex: none; color: var(--mdp-muted); font-size: var(--fs-300); white-space: nowrap; }
/* D'ou vient la ligne — le carnet, un compte du site. Une provenance,
   pas un fait : elle se lit sous le nom, au dernier plan. */
.mini-list .ml-origin { font-size: var(--fs-300); color: var(--mdp-muted); }

/* --- Empty state -------------------------------------------------
   Must say why it is empty and offer a way out (see charte 11). */
.empty-state {
  text-align: center;
  color: var(--mdp-muted);
  padding: var(--sp-4) var(--sp-3);
}
.empty-state .es-ico { font-size: 2rem; line-height: 1; opacity: .5; color: var(--mdp-faint); }

/* --- Danger zone -------------------------------------------------
   Action irreversible, en fin de parcours. La carte est celle de tout
   le monde — meme fond, meme filet, meme bandeau : c'est le BOUTON
   qui porte le rouge. Un cadre coral autour d'un bloc qu'on ne fait
   que lire criait avant meme qu'on ait touche a quoi que ce soit. */

/* Orga editions table on phones: tighter cells so the row fits the
   viewport without a horizontal scrollbar. */
.edition-table { font-size: .85rem; }
.edition-table th, .edition-table td { padding-left: .3rem; padding-right: .3rem; }
.edition-table .btn-sm { padding: .1rem .35rem; font-size: .8rem; }
@media (min-width: 576px) {
  .edition-table { font-size: inherit; }
  .edition-table th, .edition-table td { padding-left: .5rem; padding-right: .5rem; }
  .edition-table .btn-sm { padding: .25rem .5rem; font-size: .875rem; }
}

/* Upload progress bar: same size whatever the surrounding form. */
.upload-progress { height: 6px; width: 220px; max-width: 100%; margin-bottom: .6rem; }

/* Ligne de caracteristiques d'un champ : formats, poids et dimensions
   d'un fichier, complexite d'un mot de passe. Elle vient TOUJOURS
   apres la phrase d'explication, jamais a sa place — et se lit un
   cran plus bas qu'elle (plus petite, plus claire). */
.field-hint {
  font-size: var(--fs-300);
  color: var(--mdp-faint);
  font-style: italic;
  margin: var(--sp-1) 0 var(--sp-2);
}
/* Derniere du bloc : sa marge basse s'ajouterait a celle de l'element
   suivant (barre d'action), et le bouton descendrait plus bas ici que
   sur les formulaires sans ligne de caracteristiques. */
.field-hint:last-child { margin-bottom: 0; }

/* --- Deux largeurs nommees ---------------------------------------
   La charte interdit les pixels dans un attribut style (9.1), et ces
   deux-la reviennent : l'ecran qui ne demande qu'un nom, et le champ
   qui ne recoit qu'un nombre. Un champ de saisie aussi large que la
   carte annonce une reponse longue — pour une annee, il ment. */
.screen-narrow { max-width: 35rem; }
.field-short { max-width: 10rem; }

/* Le compteur de caracteres est CENTRE. La portee tranche l'alignement
   d'une ligne de caracteristiques (charte 5.5) : celle-ci qualifie un
   champ qui prend toute la largeur du bloc, donc elle se centre — au
   fer a gauche sous un textarea pleine largeur, elle partait d'un
   cote, exactement comme sous un bouton w-100. */
.field-count { text-align: center; }

/* --- Aide a la saisie d'adresse -----------------------------------
   Les propositions de la Base Adresse Nationale, sous le champ. La
   boite n'existe que pour les ancrer : sans elle, l'absolu se calerait
   sur le premier ancetre positionne, qui peut etre la page entiere.
   Posee par le JS, jamais dans un gabarit. */
.addr-box { position: relative; }
.addr-suggest {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  /* Au-dessus des couches de Leaflet (400) : l'editeur de marche a sa
     carte juste sous le champ, et la liste doit passer devant. */
  z-index: 500;
  margin: var(--sp-1) 0 0;
  padding: 0;
  list-style: none;
  background: var(--mdp-surface);
  border: 1px solid var(--mdp-line);
  border-radius: var(--r-md);
  box-shadow: var(--sh-3);
  max-height: 15rem;
  overflow-y: auto;
}
.addr-suggest li {
  padding: var(--sp-2) var(--sp-2h);
  border-bottom: 1px solid var(--mdp-line-soft);
}
.addr-suggest li:last-child { border-bottom: 0; }
.addr-suggest li[role="option"] { cursor: pointer; }
/* Une seule ligne se distingue, qu'on y soit venu a la souris ou aux
   fleches : c'est la meme designation, elle a la meme couleur. */
.addr-suggest li[aria-selected="true"] { background: var(--mdp-surface-mute); }
@media (hover: hover) {
  .addr-suggest li[role="option"]:hover { background: var(--mdp-surface-mute); }
}
.addr-suggest .as-name { display: block; }
.addr-suggest .as-sub {
  display: block;
  font-size: var(--fs-300);
  color: var(--mdp-muted);
}
/* Ni un choix ni une erreur : la raison pour laquelle il n'y a rien a
   proposer. Elle ne se survole pas et ne se clique pas. */
.addr-suggest .as-note {
  font-size: var(--fs-300);
  color: var(--mdp-muted);
  font-style: italic;
}

/* Name inputs: last name uppercase / first name capitalized while
   typing (the server normalizes the stored value too). */
.input-uppercase { text-transform: uppercase; }
.input-capitalize { text-transform: capitalize; }

/* --- Navbar (boxed: same width as the page content) ------------ */
/* Bottom corners are always square: on home the hero banner is
   glued below, on other pages a thin pattern strip (.nav-strip). */
.site-nav {
  background: #eef7f8;               /* ultra-light turquoise */
  border: 1px solid var(--mdp-line);
  border-bottom: 3px solid var(--mdp-teal);
  border-radius: .9rem .9rem 0 0;
  box-shadow: 0 1px 6px rgba(29, 58, 110, .08);
}

/* Thin slice of the banner pattern that dresses the navbar on
   pages without the hero. */
.nav-strip {
  /* Fixed pattern scale (repeated) so the shapes stay recognizable
     whatever the viewport; slim on mobile, taller from 768px. */
  height: 30px;
  background-size: auto 110px;
  background-repeat: repeat-x;
  background-position: center bottom;
  border: 1px solid var(--mdp-line);
  border-top: 0;
  border-radius: 0 0 .9rem .9rem;
  box-shadow: 0 1px 6px rgba(29, 58, 110, .08);
}
.nav-logo { height: 36px; width: auto; }
.site-nav .nav-link { color: var(--mdp-navy); font-weight: 500; }
.site-nav .nav-link.active { color: var(--mdp-teal); }

/* --- Footer (boxed, mirrors the navbar block: thin banner strip
       with teal line on top, ultra-light turquoise body) ---------- */
.footer-strip {
  height: 30px;
  /* Anchored to the TOP of the pattern (the navbar strip uses the
     bottom) so the two bands don't look identical. */
  background-size: auto 110px;
  background-repeat: repeat-x;
  background-position: center top;
  border: 1px solid var(--mdp-line);
  border-bottom: 3px solid var(--mdp-teal);
  border-radius: .9rem .9rem 0 0;
  box-shadow: 0 1px 6px rgba(29, 58, 110, .08);
}
.site-footer {
  background: #eef7f8;               /* ultra-light turquoise */
  color: var(--mdp-ink);
  border: 1px solid var(--mdp-line);
  border-top: 0;
  border-radius: 0 0 .9rem .9rem;
}
.site-footer a { color: var(--mdp-teal); text-decoration: none; }
.site-footer a:hover { color: var(--mdp-navy); }

/* --- Home hero banner ------------------------------------------- */
.hero-banner {
  background-size: cover;
  background-position: center;
  border: 1px solid var(--mdp-line);
  border-radius: .9rem;
  overflow: hidden;
  box-shadow: 0 1px 6px rgba(29, 58, 110, .08);
}
.hero-veil {
  /* soft white veil so the title stays readable over the pattern */
  background: linear-gradient(rgba(255, 255, 255, .82), rgba(255, 255, 255, .66));
}
.hero-veil h1 {
  color: var(--mdp-navy);
  font-weight: 700;
  text-shadow: 0 1px 0 rgba(255, 255, 255, .8);
}

/* Banner glued right under the navbar (home page): the navbar's
   teal bottom line becomes the junction between the two blocks. */
.hero-attached { margin-top: 0; }
.hero-attached .hero-banner {
  border-top-left-radius: 0;
  border-top-right-radius: 0;
  border-top: 0;
}

/* Filter bar glued under the banner, with the same teal line
   as junction (navbar / banner / filters form one block). */
.hero-glued {
  border-bottom: 3px solid var(--mdp-teal);
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}
.form-card.filters-attached {
  border-top: 0;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}
.hero-sub { color: #3f5570; font-weight: 500; }
@media (min-width: 768px) {
  .hero-veil h1 { font-size: 2rem; }
}

/* --- Market cards ---------------------------------------------- */
/* Surface, border and radius come from the shared card rule. */
.market-card {
  overflow: hidden;
  transition: transform .12s ease, box-shadow .12s ease;
  height: 100%;
  display: flex;
  flex-direction: column;
}
.market-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--sh-2);
}
.market-card a { text-decoration: none; color: inherit; }

/* Poster thumbnails are A4/A3 portrait: show them full-height,
   centered on a soft neutral background. */
.market-card .poster-box {
  background: var(--mdp-tint);       /* same ultra-light turquoise as the navbar */
  height: 200px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding: .6rem 0;
}
.market-card .poster-box img {
  max-height: 100%;
  max-width: 100%;
  object-fit: contain;
}
.market-card .poster-box .poster-placeholder-img {
  width: 72px;
  height: 72px;
  opacity: .45;
}
.market-card .card-city,
.agenda-body .card-city {
  color: var(--mdp-teal);
  font-weight: 600;
  text-transform: uppercase;
  font-size: .8rem;
  letter-spacing: .04em;
}
/* Date line, shared wherever a market date is shown (cards, market
   page, application pages): the coral, always bold. */
.card-date { color: var(--mdp-coral); font-weight: 600; font-size: .9rem; }

/* Feature chips. The colour comes from a tone class; the bare .chip
   defaults to the green "univers" family so an untagged chip still
   renders. Potter production groups use the decorative tones:
   Terres = jaune, Techniques = bleu, Univers = vert. */
.chip {
  display: inline-block;
  font-size: var(--fs-300);
  padding: .15rem .55rem;
  border-radius: var(--r-pill);
  background: var(--tone-bg, #eef4e0);
  color: var(--tone-fg, #5c7a22);
  border: 1px solid var(--tone-line, #d5e3b4);
  margin: 0 var(--sp-1) .3rem 0;   /* breathing room when chips wrap */
}

/* --- Agenda view ---------------------------------------------------- */
.agenda-row {
  display: flex;
  align-items: center;
  gap: .9rem;
  background: #fff;
  border: 1px solid var(--mdp-line);
  border-radius: .7rem;
  padding: .6rem .8rem;
  margin-bottom: .6rem;
  text-decoration: none;
  color: inherit;
  transition: transform .1s ease, box-shadow .1s ease;
}
.agenda-row:hover {
  color: inherit;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(29, 58, 110, .12);
}
.agenda-date {
  flex: 0 0 74px;
  text-align: center;
  background: #eef7f8;
  border: 1px solid #cfe7ea;
  border-radius: .55rem;
  padding: .35rem .2rem;
}
.agenda-date .ad-day {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--mdp-navy);
  line-height: 1.1;
  white-space: nowrap;
}
.agenda-date .ad-month {
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .05em;
  color: var(--mdp-coral);
}
.agenda-date .ad-year {
  font-size: .72rem;
  font-weight: 700;
  color: var(--mdp-navy);
}
.agenda-body { flex: 1 1 auto; min-width: 0; }
.agenda-thumb {
  height: 74px;
  width: auto;
  object-fit: cover;
  border-radius: var(--r-sm);
  border: 1px solid var(--mdp-line);
}
@media (min-width: 576px) {
  .agenda-thumb { height: 96px; }
}

/* --- Pagination --------------------------------------------------- */
.pagination {
  --bs-pagination-color: var(--mdp-teal);
  --bs-pagination-hover-color: var(--mdp-navy);
  --bs-pagination-active-bg: var(--mdp-teal);
  --bs-pagination-active-border-color: var(--mdp-teal);
  --bs-pagination-focus-color: var(--mdp-navy);
}

/* --- List/map switch -------------------------------------------- */
#mapWrap {
  border-radius: var(--r-lg);
  overflow: hidden;
  border: 1px solid var(--mdp-line);
}
/* Taller share of the viewport on a phone, where the map IS the page. */
#map { height: 70vh; min-height: 380px; }

/* Leaflet tiles are square: without clipping they bleed over the
   rounded corners of their frame by a few pixels. */
.mini-map { overflow: hidden; }
.leaflet-container { border-radius: inherit; }
.leaflet-popup-content { margin: 10px 12px; }
.map-pop strong { color: var(--mdp-navy); display: block; }
.map-pop .small { color: var(--mdp-coral); }
.map-pop { text-align: center; min-width: 150px; }
.map-pop .mp-thumb {
  display: block;
  max-height: 140px;
  max-width: 100%;
  margin: 0 auto .35rem;
  border-radius: .35rem;
  box-shadow: 0 2px 8px rgba(29, 58, 110, .25);
}

/* --- Market page ------------------------------------------------- */
.poster-carousel {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  gap: .75rem;
  -webkit-overflow-scrolling: touch;
  padding-bottom: .5rem;
}
.poster-carousel .poster-slide {
  flex: 0 0 auto;
  scroll-snap-align: center;
  max-width: 92%;
}
.poster-carousel img {
  max-height: 70vh;
  max-width: 100%;
  border-radius: .6rem;
  box-shadow: 0 4px 14px rgba(29, 58, 110, .18);
  background: #fff;
}
.market-meta .bi { width: 1.4rem; display: inline-block; }
/* La mini-carte d'une fiche : un point, pas un outil d'exploration.
   Une classe et non l'identifiant #miniMap — deux des quatre pages qui
   en posent une ecrivaient les memes valeurs en style en dur, faute de
   savoir qu'une regle existait. */
.mini-map { height: 260px; border-radius: var(--r-md); border: 1px solid var(--mdp-line); }

/* --- Inline custom SVG icons --------------------------------------- */
.si {
  width: 1em;
  height: 1em;
  vertical-align: -.125em;
  fill: currentColor;
}

/* --- Admin impersonation banner ---------------------------------------- */
.impersonation-bar {
  background: var(--mdp-sun);
  color: #4a3608;
  border-bottom: 2px solid #d99e17;
  position: sticky;
  top: 0;
  z-index: 1040;
}

/* --- Maintenance banner (admins only) ----------------------------------- */
.maintenance-bar {
  background: var(--mdp-coral);
  color: #fff;
  border-bottom: 2px solid #b93a30;
}
.maintenance-bar code { color: #ffe3e0; }

/* --- Navbar avatar --------------------------------------------------- */
.nav-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--mdp-line);
}
.nav-avatar-wrap { position: relative; display: inline-block; }
/* Dans la barre, la photo precede le nom : la seule espace du texte
   les colle. Vise le lien de compte, pas le raccourci mobile, ou la
   photo est seule dans son carre et une marge la decentrerait. */
.site-nav .nav-link .nav-avatar-wrap { margin-right: var(--sp-1); }
.admin-badge {
  position: absolute;
  right: -5px;
  bottom: -4px;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--mdp-navy);
  color: #fff;
  border: 1.5px solid #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .5rem;
  line-height: 1;
}
/* Acces direct au tableau de bord, pose hors du menu sur telephone.
   44px de cote : la cible tactile minimale de la charte (14). */
.nav-dash {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-md);
  color: var(--mdp-navy);
  font-size: 1.6rem;   /* dimensionne l'icone de repli, pas la photo */
  line-height: 1;
  text-decoration: none;
}
.nav-dash:hover,
.nav-dash:focus-visible { background: var(--mdp-tint-2); color: var(--mdp-teal); }

/* --- Onglets ---------------------------------------------------------- */
/* Les DERNIERS onglets du site : ceux de la modale de dossier
   (orga/selection). Legitimes — ils commutent des panneaux en
   LECTURE dans une fenetre, donc pas de bouton d'enregistrement a
   multiplier et pas la place d'une colonne de menu (charte 5.4).
   Chaque onglet garde son filet bas, pour qu'une ligne continue
   coure sous une rangee qui est passee a la ligne.
   (.account-nav partageait ces regles ; elle est morte avec la
   conversion du sixieme ecran de l'espace compte.) */
.dossier-tabs { flex-wrap: wrap; row-gap: .15rem; }
.dossier-tabs.nav-tabs { border-bottom: none; }
.dossier-tabs .nav-link {
  color: var(--mdp-navy);
  white-space: nowrap;
  border-bottom-color: var(--mdp-line);
}
.dossier-tabs .nav-link:hover { color: var(--mdp-teal); }
.dossier-tabs .nav-link.active {
  color: var(--mdp-teal);
  font-weight: 600;
  background-color: transparent;
  /* Dans la modale, la page derriere est blanche, pas papier. */
  border-color: var(--mdp-line) var(--mdp-line) #fff;
}
.dossier-tabs .nav-link { padding: .3rem .6rem; font-size: .9rem; }
@media (min-width: 576px) {
  .dossier-tabs .nav-link { padding: .5rem 1rem; font-size: 1rem; }
}
/* L'image d'un dossier dans cette fenetre : elle tient dans la hauteur
   sans faire defiler la fenetre entiere, et garde ses proportions —
   une photo de production est verticale une fois sur deux. La reserve
   se voit derriere les bandes, elle prend donc la surface mate du
   site plutot qu'un gris ecrit a la main. */
.dossier-img {
  max-height: 56vh;
  object-fit: contain;
  background: var(--mdp-surface-mute);
}
/* Dashboard (/tableau-de-bord) quick-access: big square buttons —
   icon + function, with a small stat sub-line. */
.dash-acts { display: flex; flex-wrap: wrap; gap: var(--sp-2h); }
.dash-act {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; gap: var(--sp-2);
  width: 132px; min-height: 116px; padding: var(--sp-2h) var(--sp-2);
  background: var(--mdp-surface); border: 1px solid var(--mdp-line); border-radius: var(--r-lg);
  color: var(--mdp-navy); text-decoration: none;
  font-size: var(--fs-300); font-weight: var(--fw-medium); line-height: var(--lh-tight);
}
.dash-act:hover { border-color: var(--mdp-teal); color: var(--mdp-teal); background: var(--mdp-tint); }
.dash-act .da-ico { font-size: 1.75rem; line-height: 1; color: var(--mdp-teal); }
.dash-act .da-sub { font-weight: var(--fw-normal); font-size: var(--fs-200); color: var(--mdp-muted); line-height: var(--lh-tight); }
.dash-act:hover .da-sub { color: var(--mdp-muted); }
.avatar-lg {
  width: 96px;
  height: 96px;
  border-radius: var(--r-circle);
  object-fit: cover;
  border: 2px solid var(--mdp-line);
}
/* Meme avatar en petit, dans les lignes de "Mes profils". */
.avatar-sm { width: 48px; height: 48px; }
/* Reserve quand aucune photo n'est deposee : meme gabarit que la
   photo, pour que la carte ne change pas de hauteur. */
.avatar-lg.d-flex { background: var(--mdp-surface-mute); font-size: 2.4rem; }
.logo-square {
  width: 96px;
  height: 96px;
  border-radius: var(--r-md);
  object-fit: cover;
  border: 1px solid var(--mdp-line);
  background: var(--mdp-surface);
}
/* Tailles reduites : en-tete de page (52px) et lignes de la page
   "Mes profils" (48px). Etaient des style="width:…px" inline. */
.logo-square-sm { width: 52px; height: 52px; }
.logo-square-xs { width: 48px; height: 48px; }
/* Un visage se montre en rond. Meme boite que le carre, seul le rayon
   change : la colonne du sommaire ne bouge pas d'un ecran a l'autre. */
.logo-square-round { border-radius: var(--r-circle); }
.role-switch .form-check-input { width: 3em; height: 1.5em; }

/* --- Sommaire / section (.split) ---------------------------------
   Un ecran long coupe en sections. Le serveur rend toujours les DEUX
   faces ; seule la largeur decide de ce qu'on voit. C'est ce qui
   permet un gabarit unique : le sommaire et le detail sont les memes
   morceaux, pas deux mises en page a tenir cohérentes.
   Sur telephone, une face a la fois — celle que l'URL demande. */
.split--summary > .split-pane { display: none; }
.split--section > .split-menu { display: none; }
.split-grp {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-200);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--mdp-muted);
  font-weight: var(--fw-semibold);
  margin: var(--sp-3) 0 var(--sp-2);
}
/* Le badge d'etat d'un groupe ne suit pas la capitalisation du titre :
   « PUBLIÉ » crierait, et ce n'est pas un intertitre mais une valeur. */
.split-grp .badge { text-transform: none; letter-spacing: 0; }
.split-grp:first-child { margin-top: 0; }
.split-list {
  background: var(--mdp-surface);
  border: 1px solid var(--mdp-line);
  border-radius: var(--r-md);
  overflow: hidden;
}
.split-row {
  display: flex;
  align-items: center;
  gap: var(--sp-2h);
  padding: var(--sp-2h) var(--sp-3);
  border-bottom: 1px solid var(--mdp-line-soft);
  color: var(--mdp-navy);
  text-decoration: none;
}
.split-row:last-child { border-bottom: 0; }
.split-row:hover { background: var(--mdp-tint); color: var(--mdp-navy); }
.split-ico {
  width: 2rem; height: 2rem; flex: none;
  border-radius: var(--r-sm);
  background: var(--mdp-tint);
  color: var(--mdp-teal);
  display: flex; align-items: center; justify-content: center;
}
.split-txt { min-width: 0; }
.split-lb { display: block; font-weight: var(--fw-medium); line-height: var(--lh-tight); }
.split-sb { display: block; font-size: var(--fs-300); color: var(--mdp-muted); }
/* Une seconde ligne peut porter un ton — uniquement pour ce qui BLOQUE
   quelque chose sur cet ecran (charte 5.4). Partout ailleurs elle
   reste grise : elle rapporte, elle ne reproche pas. */
.split-sb.tone-ok, .split-sb.tone-wait, .split-sb.tone-bad { color: var(--tone-fg); }
.split-ch { margin-left: auto; flex: none; color: var(--mdp-faint); }
/* Bandeau d'etat : la TEINTE fait le travail. En carte blanche il se
   lisait comme une section de plus ; teinte, il se lit comme un etat.
   Meme silhouette qu'une carte d'interrupteur — texte a gauche,
   commande a droite calee sur la premiere ligne — mais il constate au
   lieu de commander. Tons de .badge (charte 1.5), et seule l'icone
   prend la couleur : le texte reste a pleine lisibilite. */
.state-card {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: nowrap;
  gap: var(--sp-2);
  padding: var(--sp-2h) var(--sp-3);
  border: 1px solid var(--tone-line);
  border-radius: var(--r-md);
  background: var(--tone-bg);
}
.state-card > :first-child { min-width: 0; }
.state-card > .btn { flex: none; }
.state-card .state-ico { color: var(--tone-fg); }
/* Plusieurs commandes dans un bandeau. L'egalisation des largeurs est
   celle de .btn-even (charte 6.3) — deux boutons qui vont ensemble
   prennent la largeur du plus long libelle ; .state-acts ne regle que
   leur PLACE.
   Sur telephone elles passent SOUS le texte, pleine largeur : calees a
   droite dans une carte de 336px, elles ne laissaient que 145px a la
   phrase, qui partait sur six lignes. Des 576px elles reviennent a
   droite, comme l'interrupteur d'une toggle-card (charte 10.4).
   L'action qui FAIT AVANCER est toujours la premiere. */
.state-card--stack { flex-wrap: wrap; }
.state-card--stack .state-acts {
  flex: 1 0 100%;
  grid-template-columns: minmax(0, 1fr);
}
.state-card--stack .state-acts form { margin: 0; }
@media (min-width: 576px) {
  .state-card--stack { flex-wrap: nowrap; }
  .state-card--stack .state-acts {
    flex: none;
    grid-template-columns: minmax(0, max-content);
  }
}
/* Ce qui manque, une ligne par element — puce ORDINAIRE, celle du
   navigateur. C'est la meme liste que « Ce qui vous sera demande » sur
   l'ecran d'entree d'une candidature, qui enumere exactement les memes
   pieces : elles se ressemblent parce qu'elles disent la meme chose.
   Le retrait gauche est reduit : dans un bandeau, les 2 rem de
   Bootstrap decrochaient la liste de la phrase au-dessus. */
.state-list {
  margin: var(--sp-2) 0 0;
  padding-left: var(--sp-4);
  font-size: var(--fs-400);
}
.state-list li { margin-top: var(--sp-1); }

/* En-tete du sommaire : la vignette EST la commande. Un media qui
   porte l'identite n'a pas besoin d'une rangee de boutons — la
   pastille au crayon dit qu'on peut le changer, et le clic ouvre le
   selecteur. Le gabarit .media-inline (visuel + deux boutons pleine
   largeur + ligne de contraintes) est fait pour une carte, pas pour
   une colonne de 15rem : il y tenait, mais il y pesait. */
/* L'en-tete est une CARTE, comme les listes qui suivent. Pose a nu sur
   le fond de page, le logo flottait : rien ne le rattachait au
   sommaire dont il est pourtant le titre. */
.split-head {
  background: var(--mdp-surface);
  border: 1px solid var(--mdp-line);
  border-radius: var(--r-md);
  padding: var(--sp-2h) var(--sp-3);
  margin-bottom: var(--sp-3);
}
.head-media { display: flex; align-items: center; gap: var(--sp-2h); }
.head-logo {
  position: relative;
  display: block;
  flex: none;
  cursor: pointer;
  padding: 0;
  border: 0;
  background: none;
}
.head-logo .logo-square { display: block; }
.head-logo-pen {
  position: absolute;
  right: -.25rem;
  bottom: -.25rem;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: var(--r-circle);
  background: var(--mdp-teal);
  color: #fff;
  border: 2px solid var(--mdp-paper);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-300);
}
.head-txt { min-width: 0; }
.head-txt .head-name { font-weight: var(--fw-medium); line-height: var(--lh-tight); }
/* En-tete de sommaire en LECTURE (subject_head) : le sujet dont
   l'ecran depend — le marche d'une candidature. Il ne se modifie pas
   d'ici, il se visite : toute la carte est le lien. Le nom monte d'un
   cran, comme .page-head-object : c'est l'objet de la page. */
.head-subject { color: var(--mdp-navy); text-decoration: none; }
.head-subject:hover { color: var(--mdp-teal-800); }
.head-subject .head-name {
  font-size: var(--fs-700);
  font-weight: var(--fw-semibold);
  display: block;
}
.head-sub {
  display: block;
  font-size: var(--fs-300);
  color: var(--mdp-muted);
  line-height: var(--lh-snug);
  margin-top: 2px;
}
.head-go { margin-left: auto; flex: none; color: var(--mdp-faint); }
/* La zone de danger breve (danger_action) : le bouton seul, detache.
   La classe reste, c'est le bloc separe de la charte 12 — mais elle
   n'a plus de carte a porter. */
.danger-zone > form { margin: 0; }
.split-back {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  margin-bottom: var(--sp-2h);
  font-size: var(--fs-300);
}
@media (min-width: 768px) {
  /* Les deux faces cote a cote : le menu ne mene plus ailleurs, il
     selectionne. Le lien de retour n'a donc plus d'objet. */
  .split { display: flex; align-items: flex-start; gap: var(--sp-3); }
  .split--summary > .split-pane,
  .split--section > .split-menu { display: block; }
  .split-menu { width: 15rem; flex: none; }
  .split-pane { flex: 1 1 0; min-width: 0; }
  .split-back { display: none; }
  .split-row { padding: var(--sp-2) var(--sp-2h); }
  .split-ch { display: none; }
  .split-row.is-active { background: var(--mdp-tint); color: var(--mdp-teal-800); }
}

/* --- Blocs de profil ("Mes profils") -----------------------------
   Un profil desactive se voit d'un coup d'oeil, sans avoir a lire
   l'interrupteur : c'est l'information principale du bloc. */
.profile-block {
  border: 1px solid var(--mdp-line);
  border-radius: var(--r-md);
  background: var(--mdp-surface);
  padding: var(--sp-3);
  margin-bottom: var(--sp-2);
}
.profile-block .pb-title {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-weight: var(--fw-semibold);
}
/* Le titre et sa phrase se touchaient. */
.profile-block .pb-desc { margin-top: var(--sp-2); }
.profile-block .pb-foot {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-2h);
  padding-top: var(--sp-2);
  border-top: 1px solid var(--mdp-line-soft);
}
/* Le nom du profil se lit comme une etiquette, pas comme un lien de
   texte courant : la couleur et la graisse suffisent a le designer. */
.profile-block a { text-decoration: none; }
/* L'etat se lit sur la seule pastille : verte quand le profil est
   actif, turquoise sinon. Le bloc lui-meme ne change pas — le griser
   le faisait passer pour desactive, donc intouchable, alors que c'est
   precisement la ou l'on clique pour l'activer. */
.ico-badge.tone-ok { background: var(--tone-bg); color: var(--tone-fg); }

/* Past participation (apps_past_chip): washed-out on purpose, so a
   previous edition never reads as the state of the current file. */
.chip-past {
  display: inline-block;
  font-size: var(--fs-200);
  line-height: 1.5;
  padding: 0 .45rem;
  border-radius: var(--r-sm);
  white-space: nowrap;
  vertical-align: .05rem;
  background: var(--tone-bg);
  color: var(--tone-fg);
}

/* Carnet card: what this potter did on the organizer's markets, one
   pill per EDITION (a market may run twice in the same year). */
/* Two columns on a phone, the last figure spanning both: three equal
   columns left "liste d'attente" on its own line, alone and orphaned
   next to a hole. Three columns from 576px, where they fit. */
.part-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-2h); margin-bottom: var(--sp-3); }
.part-stats > :last-child { grid-column: 1 / -1; }
@media (min-width: 576px) {
  .part-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .part-stats > :last-child { grid-column: auto; }
}
/* Border and radius from the shared card rule; a plain stat keeps
   the second-plane surface, a toned one takes its triplet. */
.part-stat { border-radius: var(--r-md);
  padding: var(--sp-2) var(--sp-2h); background: var(--mdp-surface-soft); }
.part-stat .n { font-size: 1.5rem; font-weight: var(--fw-bold); line-height: 1.1; }
.part-stat .k { font-size: var(--fs-300); color: var(--mdp-muted);
  text-transform: uppercase; letter-spacing: .03em; }
.part-stat.is-ok, .part-stat.is-wait { background: var(--tone-bg); border-color: var(--tone-line); }
.part-stat.is-ok .n, .part-stat.is-ok .k,
.part-stat.is-wait .n, .part-stat.is-wait .k { color: var(--tone-fg); }

/* Same figures, chip-sized, for the rows of the carnet list. */
.part-chip { border-radius: var(--r-md); padding: .1rem .5rem; font-size: var(--fs-300);
  font-weight: var(--fw-semibold); white-space: nowrap;
  background: var(--tone-bg, var(--mdp-surface-mute));
  color: var(--tone-fg, #6b6659);
  border: 1px solid var(--tone-line, var(--mdp-line)); }
/* Not a count: what kind of card this is, next to the name. Purple
   on purpose - it is outside the state scale. */
.part-chip.manual { background: #eceaf6; color: #504a75; border-color: #dcd8ee;
  font-weight: var(--fw-medium); vertical-align: .05rem; }

.part-serie { padding: var(--sp-2h) 0; border-top: 1px solid var(--mdp-line); }
.part-serie:first-of-type { border-top: 0; padding-top: 0; }
.part-serie-head { display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap; margin-bottom: .45rem; }
/* The strip WRAPS, it does not scroll (charte 4.4). A horizontal
   scrollbar inside a page that already scrolls vertically is a trap
   on a phone: the editions past the fold are invisible, and the
   gesture that would reveal them is the one that turns the page. */
.part-strip { display: flex; flex-wrap: wrap; gap: .35rem; }
.part-ed { display: inline-flex; flex-direction: column; align-items: center; justify-content: center;
  min-width: 84px; max-width: 100%; padding: .32rem .6rem; border-radius: var(--r-md);
  border: 1px solid transparent;
  font-size: var(--fs-300); line-height: 1.3; text-align: center; text-decoration: none;
  background: var(--tone-bg); color: var(--tone-fg); border-color: var(--tone-line); }
.part-ed .m { font-size: .92rem; }
/* The edition label, whole: it is how the organizer named it. It only
   gives way on a label long enough to break out of its card, and the
   pill's title attribute still carries it entire. */
.part-ed .y { font-weight: var(--fw-bold); font-size: var(--fs-300); white-space: nowrap;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
a.part-ed:hover { filter: brightness(.97); }
/* "Never took part": dashed and washed out, deliberately outside the
   tone scale so it does not read as a state. */
.part-none { background: var(--mdp-surface-soft); color: var(--mdp-faint);
  border: 1px dashed var(--mdp-line-soft); }
.part-legend { display: flex; flex-wrap: wrap; gap: var(--sp-2h); margin-top: var(--sp-3);
  border-top: 1px solid var(--mdp-line); padding-top: var(--sp-2h);
  font-size: var(--fs-300); color: var(--mdp-muted); }
.part-legend span { display: inline-flex; align-items: center; gap: .3rem; }
.part-key { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px;
  border-radius: var(--r-sm); border: 1px solid var(--tone-line, transparent); font-size: var(--fs-200);
  background: var(--tone-bg); color: var(--tone-fg); }
.more-link { background: none; border: 0; padding: .2rem 0; font-size: var(--fs-300);
  color: var(--mdp-teal); font-weight: var(--fw-semibold); cursor: pointer; }
.more-link:hover { text-decoration: underline; }

/* Media browser (admin): a contact sheet of every stored picture. */
.media-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: .9rem;
}
.media-item {
  border: 1px solid var(--mdp-line);
  border-radius: .6rem;
  overflow: hidden;
  background: #fff;
}
.media-item.is-missing { border-color: var(--mdp-coral); }
.media-item img,
.media-none {
  display: block;
  width: 100%;
  height: 120px;
  object-fit: cover;
  background: #f4f2ec;
}
.media-none {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--mdp-coral);
  font-size: 1.4rem;
}
.media-meta { padding: .4rem .5rem; font-size: .72rem; line-height: 1.35; }
.media-meta a { text-decoration: none; }
.media-tech { color: var(--mdp-muted); }

/* L'image d'un potier (identity_badge, lib/applications.php) : UN
   carre arrondi, jamais deux images superposees. La photo de profil
   y montait autrefois en pastille d'angle par-dessus le logo — depuis
   que l'image se derive (logo, a defaut avatar, charte 7.5), les deux
   moities disaient la meme personne. */
.idbadge { display: inline-block; flex: 0 0 auto; line-height: 0; }
.idbadge-main {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: .5rem;
  object-fit: cover;
  background: var(--mdp-surface-mute);
  border: 1px solid var(--mdp-line);
  color: var(--mdp-faint);
}
/* Ni image ni logo — un dossier papier, un compte vide : l'icone
   tient la place, pour que la ligne garde sa hauteur. */
.idbadge-none .si { width: 55%; height: 55%; }
.idbadge-sm .idbadge-main { width: 40px; height: 40px; }
.idbadge-md .idbadge-main { width: 64px; height: 64px; border-radius: .6rem; }
.idbadge-lg .idbadge-main { width: 84px; height: 84px; border-radius: .6rem; }

/* --- Ligne de liste entierement cliquable ------------------------
   Quand l'objet d'une ligne a une destination, c'est TOUTE la ligne
   qui y mene, pas son seul nom : la cible passe de quelques
   caracteres a un bloc, ce qui compte surtout au doigt. Le nom porte
   .stretched-link, la ligne lui sert d'ancrage. Markup :
     <li class="list-row p-3 mb-2"> … <a class="stretched-link" …> … */
.list-row {
  position: relative;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2);
  border: 1px solid var(--mdp-line);
  border-radius: var(--r-md);
  transition: background-color .12s ease;
}
/* Le survol n'existe pas au doigt — et sur iOS il RESTE colle apres le
   toucher, jusqu'au suivant ailleurs. On le reserve donc aux appareils
   a pointeur, et le retour tactile passe par :active, qui lui se
   declenche a l'appui. */
@media (hover: hover) {
  .list-row:hover { background: var(--mdp-surface-mute); }
}
.list-row:active { background: var(--mdp-surface-mute); }
/* La ligne entiere est cliquable : souligner le nom reviendrait a
   souligner un bloc (charte 7.4). Seul le lien etendu perd son trait
   — un lien pose dans une phrase de la ligne garde le sien, rien
   d'autre ne l'y distingue. */
.list-row a.stretched-link { text-decoration: none; }
/* Les commandes de la ligne repassent devant la nappe du lien, sinon
   elle les recouvre et elles deviennent injouables. */
.list-row form,
.list-row .btn { position: relative; z-index: 2; }
/* Une ligne dont la destination est une FENETRE, pas une page : le
   bloc d'identite est un <button>, et c'est lui qui porte
   .stretched-link — toute la ligne ouvre le dossier, comme partout
   ailleurs elle ouvre une page (charte 7.5).
   Il ne prend surtout PAS .btn : la regle ci-dessus le passerait en
   position: relative, et la nappe du lien etendu, qui se cale sur le
   premier ancetre positionne, se replierait sur le bouton lui-meme.
   Les enfants gardent les classes .lr-* : elles ne supposent pas un
   <div>, seulement un enfant de .list-row. */
.list-row .lr-open {
  display: flex;
  align-items: center;
  gap: var(--sp-2h);
  min-width: 0;
  flex: 1 1 12rem;
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  color: inherit;
}
/* Bloc principal : nom, puis la ligne secondaire qui le situe. */
.list-row .lr-main { min-width: 0; flex: 1 1 12rem; }
.list-row .lr-name { font-weight: var(--fw-semibold); color: var(--mdp-navy); }
/* Le visuel d'une ligne s'aligne sur le haut du nom, meme regle que
   l'en-tete de page : centre, il descendait des qu'une ligne de
   contexte s'ajoutait. */
.list-row > .idbadge { align-self: flex-start; }
/* Le second nom : la personne derriere l'atelier. Encre plutot que
   gris, et un demi-cran de graisse — il se lisait comme un detail
   parmi les autres alors qu'il sert a reconnaitre quelqu'un. */
.list-row .lr-person { font-size: var(--fs-400); font-weight: var(--fw-medium); color: var(--mdp-ink); }
/* Ligne secondaire : une suite de FAITS, pas une phrase. Chaque fait
   est un <span> avec son icone ; les separateurs « · » se retrouvaient
   en fin de ligne et la coupure tombait n'importe ou. C'est l'espace
   entre segments qui separe, et le retour a la ligne se fait entre
   deux faits. */
.list-row .lr-sub {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .1rem var(--sp-2h);
  margin-top: .1rem;
  font-size: var(--fs-400);
  color: var(--mdp-muted);
}
/* Un fait plus large que la colonne — une adresse email, un nom de
   domaine — se coupe au lieu de deborder. Sans min-width, un segment
   flex ne descend jamais sous la largeur de son mot le plus long, et
   il sortait de la carte (charte 4.4).
   L'icone se cale sur la ligne de base de la PREMIERE ligne : centree,
   elle descendait au milieu du bloc des que le texte passait a la
   ligne, et ne designait plus rien (charte 7.6). */
.list-row .lr-sub > span { display: inline-flex; align-items: baseline; gap: var(--sp-1);
  min-width: 0; overflow-wrap: anywhere; }
.list-row .lr-sub i { color: var(--mdp-faint); flex: none; }

/* Examination rail (orga/application-view): the three process states
   in order, the outcome (validé / refusé) living in its own zone. */
.exam-rail { display: flex; align-items: flex-start; }
.exam-step { flex: 0 0 auto; width: 5.5rem; text-align: center; }
.exam-line { flex: 1; height: 2px; background: var(--mdp-line); margin-top: .8rem; }
.exam-line.is-done { background: var(--mdp-teal); }
.exam-dot {
  width: 1.7rem;
  height: 1.7rem;
  margin: 0 auto .35rem;
  border-radius: 50%;
  border: 1px solid #d7d3c8;
  background: #fff;
  color: var(--mdp-faint);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .9rem;
}
.exam-dot.is-done { background: #e2f0f3; border-color: #e2f0f3; color: var(--mdp-teal); }
.exam-dot.is-current { background: var(--mdp-teal); border-color: var(--mdp-teal); color: #fff; }
.exam-dot.is-current.is-pay { background: var(--mdp-sun); border-color: var(--mdp-sun); color: #443204; }
.exam-label { font-size: .75rem; line-height: 1.25; }
.exam-here { font-size: .68rem; color: var(--mdp-teal); }
.exam-dot.is-pay + .exam-label + .exam-here { color: #8a6a10; }
.exam-trail { display: flex; flex-wrap: wrap; gap: .3rem; align-items: center; }

/* Shared confirm/alert dialog (site.js): the message keeps the line
   breaks it was written with, and the header carries the site tone. */
.mdp-dialog .modal-content { border: 0; border-radius: .9rem; }
.mdp-dialog .modal-header { border-bottom: 0; padding-bottom: .25rem; }
.mdp-dialog .modal-title { font-size: 1.05rem; }
.mdp-dialog .modal-body { white-space: pre-line; }
.mdp-dialog .modal-footer { border-top: 0; padding-top: .25rem; }

/* Round preview inside the generic crop modal (avatars) */
.crop-round .cropper-view-box,
.crop-round .cropper-face { border-radius: 50%; }

/* --- Public directory cards ------------------------------------------- */
.dir-card {
  height: 100%;
  transition: transform .12s ease, box-shadow .12s ease;
}
.dir-card:hover { transform: translateY(-2px); box-shadow: var(--sh-2); }
.dir-card a { text-decoration: none; color: inherit; }
.dir-logo {
  width: 72px;
  height: 72px;
  border-radius: var(--r-md);
  object-fit: cover;
  border: 1px solid var(--mdp-line);
  background: var(--mdp-surface-mute);
}
/* Taille d'en-tete de fiche publique (etait un style="width:96px"
   inline, duplique sur organizer.php et potter.php). */
.dir-logo-lg { width: 96px; height: 96px; }
/* Vignette des resultats de recherche de l'accueil, ecrite jusqu'ici
   en style="width:44px;height:44px" sur quatre elements. */
.dir-logo-sm { width: 44px; height: 44px; }
.gallery-strip { display: flex; gap: var(--sp-2h); overflow-x: auto; padding-bottom: var(--sp-1); }
.gallery-strip img {
  height: 140px;
  border-radius: var(--r-md);
  border: 1px solid var(--mdp-line);
}

/* --- Forms -------------------------------------------------------- */
/* .form-card takes surface, border and radius from the shared card
   rule; it is the generic panel of the site. */
.required::after { content: " *"; color: var(--mdp-coral); }

/* Poster management grid (organizer) */
.poster-admin { display: flex; flex-wrap: wrap; gap: .75rem; }
.poster-admin .pa-item {
  width: 130px;
  background: #fff;
  border: 1px solid var(--mdp-line);
  border-radius: .6rem;
  padding: .4rem;
  text-align: center;
}
.poster-admin .pa-item img { max-width: 100%; height: 140px; object-fit: contain; }
.poster-admin .pa-main { border-color: var(--mdp-teal); box-shadow: 0 0 0 2px var(--mdp-teal); }

/* --- Lightbox (fullscreen gallery carousel) -------------------------- */
.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(14, 19, 27, .93);
  display: none;
  z-index: 1080;
}
.lightbox.open { display: block; }
.lb-track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  height: 100%;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.lb-track::-webkit-scrollbar { display: none; }
.lb-slide {
  flex: 0 0 100%;
  scroll-snap-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2.5rem 1rem;
}
.lb-slide img {
  max-width: 100%;
  max-height: 100%;
  border-radius: .4rem;
  box-shadow: 0 8px 30px rgba(0, 0, 0, .5);
}
.lb-close {
  position: absolute;
  top: .5rem;
  right: .8rem;
  z-index: 2;
  background: none;
  border: 0;
  color: #fff;
  font-size: 2.2rem;
  line-height: 1;
  opacity: .8;
}
.lb-close:hover { opacity: 1; }
/* Hidden by default: on touch the native swipe does the job. The
   arrows only appear once there is a pointer to click them with. */
.lb-arrow {
  display: none;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  background: rgba(255, 255, 255, .12);
  border: 0;
  color: #fff;
  font-size: 2rem;
  line-height: 1;
  width: 44px;
  height: 60px;
  border-radius: var(--r-sm);
}
.lb-arrow:hover { background: rgba(255, 255, 255, .25); }
.lb-prev { left: .6rem; }
.lb-next { right: .6rem; }
@media (min-width: 768px) {
  .lb-arrow { display: block; }
}
.lb-badge {
  position: absolute;
  right: 1rem;
  bottom: 1rem;
  z-index: 2;
  background: rgba(0, 0, 0, .65);
  color: #fff;
  padding: .15rem .7rem;
  border-radius: 999px;
  font-size: .85rem;
}

/* Gallery thumbnails (market/organizer/potter pages) */
.gallery-thumbs { display: flex; flex-wrap: wrap; gap: .6rem; }
.gallery-thumbs img {
  height: 96px;
  width: 96px;
  object-fit: cover;
  border-radius: .5rem;
  border: 1px solid var(--mdp-line);
  transition: transform .1s ease;
}
.gallery-thumbs a:hover img { transform: scale(1.04); }

/* Poster card on the market page: centered in a full-width card */
.poster-card {
  background: #fff;
  border: 1px solid var(--mdp-line);
  border-radius: .9rem;
  padding: 1rem;
  text-align: center;
}
.poster-card img {
  max-height: 70vh;
  max-width: 100%;
  border-radius: .4rem;
  box-shadow: 0 4px 14px rgba(29, 58, 110, .18);
}

/* --- Share fallback popup (from BijouShop pattern) ----------------- */
.share-pop {
  position: fixed;
  inset: 0;
  background: rgba(20, 28, 40, .55);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 1060;
}
.share-pop.open { display: flex; }
.share-pop .sp-box {
  background: #fff;
  border-radius: .9rem;
  padding: 1.25rem;
  width: min(92vw, 360px);
}

/* --- Size steps ------------------------------------------------------
   The base declarations above are the phone; these only grow things
   as the viewport does. */
@media (min-width: 576px) {
  .nav-logo { height: 44px; }
  #map { height: 65vh; }
  .market-card .poster-box { height: 240px; }
}
@media (min-width: 768px) {
  .nav-strip { height: 64px; background-size: auto 240px; }
  .footer-strip { height: 64px; background-size: auto 240px; }
}

/* ====================================================================
   Organizer "Mes marchés": editions as cards (not a table)
   ==================================================================== */
/* "À traiter": aggregated active items, shown only when non-empty. */
.orga-todo { background: #fff; border: 1px solid var(--mdp-line); border-radius: .9rem; padding: .9rem 1rem; }
.orga-todo-h {
  display: flex; align-items: center; gap: .5rem; margin-bottom: .75rem;
  font-size: .72rem; letter-spacing: .1em; text-transform: uppercase; font-weight: 700; color: var(--mdp-muted);
}
.orga-todo-h .pulse { width: 8px; height: 8px; border-radius: 50%; background: var(--mdp-green);
  box-shadow: 0 0 0 3px rgba(140, 182, 60, .25); }
/* One column on a phone, then two, then the full row of three. */
.orga-tiles { display: grid; grid-template-columns: 1fr; gap: var(--sp-2h); }
@media (min-width: 576px) { .orga-tiles { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 768px) { .orga-tiles { grid-template-columns: repeat(3, 1fr); } }
.orga-tile { display: flex; align-items: center; gap: var(--sp-2h); border: 1px solid var(--mdp-line);
  border-radius: var(--r-md);
  padding: .65rem .8rem; background: var(--mdp-surface-soft); text-decoration: none; color: var(--mdp-ink); }
.orga-tile:hover { border-color: var(--mdp-teal); background: #f4fbfc; }
.orga-tile.static { cursor: default; }
.orga-tile.static:hover { border-color: var(--mdp-line); background: var(--mdp-surface-soft); }
.orga-tile .ti { width: 38px; height: 38px; border-radius: var(--r-md); display: flex; align-items: center;
  justify-content: center; flex: none; font-size: 1.15rem;
  background: var(--tone-bg); color: var(--tone-fg); }
.orga-tile .n { font-size: 1.3rem; font-weight: var(--fw-bold); color: var(--mdp-navy); line-height: 1;
  font-variant-numeric: tabular-nums; }
.orga-tile .t { font-size: var(--fs-300); font-weight: var(--fw-semibold); line-height: 1.15; }

/* Teal icon badge for entity / section headings (markets, dashboard roles…). */
.ico-badge { width: 32px; height: 32px; border-radius: var(--r-md); background: var(--mdp-tint-2); color: var(--mdp-teal);
  display: inline-flex; align-items: center; justify-content: center; flex: none; font-size: 1.05rem; }

/* --- La carte d'une edition : le haut dit ce qu'ELLE EST, le pied
   ce qu'on peut y FAIRE ------------------------------------------
   L'affiche occupait la moitie gauche d'une carte de 320px, soit plus
   que les dates, la ville, les exposants et les trois acces reunis —
   pour une image qu'on depose une fois et qu'on ne relit jamais d'ici.
   Elle descend a une vignette au ratio A (A3/A4 = 1:V2) ; hors format,
   elle reste en `contain` plutot que rognee. */
.ed-card { display: flex; flex-direction: column; overflow: hidden; margin-bottom: var(--sp-2h); }
/* La tete est l'ancrage du .stretched-link : toute la partie haute
   mene a l'editeur, comme une ligne de liste (charte 7.5). Le pied
   est hors de cet ancrage, ses trois acces gardent donc leur lien —
   et les boutons de la tete repassent devant la nappe. */
.ed-head { display: flex; gap: var(--sp-2h); padding: var(--sp-2h); align-items: flex-start;
  flex-wrap: wrap; position: relative; }
.ed-head:hover { background: var(--mdp-surface-mute); }
.ed-head a.stretched-link { color: inherit; text-decoration: none; }
.ed-head .btn { position: relative; z-index: 2; }
.ed-poster, .ed-poster-ph { width: 64px; flex: none; aspect-ratio: 210 / 297; border-radius: var(--r-sm);
  border: 1px solid var(--mdp-line); }
/* La meme affiche, dans la section qui la gere : on la regarde, la
   place ne manque pas. */
.ed-poster.is-lg, .ed-poster-ph.is-lg { width: 7rem; }
.ed-poster { background: var(--mdp-surface-mute); object-fit: contain; }
.ed-poster-ph { display: flex; align-items: center; justify-content: center;
  color: var(--mdp-faint); background: var(--mdp-surface-soft); border-style: dashed; }
.ed-main { flex: 1 1 12rem; min-width: 0; }
.ed-label { font-size: 1rem; font-weight: var(--fw-bold); color: var(--mdp-navy); line-height: 1.15; }
.ed-facts { display: flex; flex-direction: column; gap: .1rem; margin-top: .2rem;
  font-size: var(--fs-300); color: var(--mdp-muted); }
.ed-facts .unset { font-style: italic; color: var(--mdp-faint); }

/* La prochaine edition d'un marche : trois choses de natures
   differentes — un libelle, une date, un etat. En un seul <span>
   elles se coupaient n'importe ou sur un telephone ; en segments,
   le retour a la ligne tombe forcement ENTRE deux d'entre elles
   (charte 7.5). */
.lr-next { display: flex; align-items: baseline; flex-wrap: wrap; gap: .2rem .5rem;
  margin-top: .2rem; font-size: var(--fs-300); color: var(--mdp-muted); }
/* Modifier / Voir la fiche. Sous 576px ils passent SOUS les
   informations (order) et se partagent la largeur a egalite : a droite
   du titre, ils l'ecrasaient et perdaient leurs libelles. */
.ed-tools { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: var(--sp-2);
  flex: 1 1 100%; order: 3; }
@media (min-width: 576px) {
  .ed-tools { display: flex; align-items: flex-start; flex: 0 0 auto; order: 0; }
}

/* Le pied PORTE la grille : un conteneur en flex autour laissait les
   trois boutons a leur largeur de contenu au lieu de la largeur
   disponible. Trois colonnes egales des 576px, empilees en dessous —
   au doigt, la cible fait alors la ligne entiere. */
.ed-access { display: grid; grid-template-columns: 1fr; gap: .35rem;
  padding: var(--sp-2) var(--sp-2h); border-top: 1px solid var(--mdp-line-soft);
  background: var(--mdp-surface-soft); }
@media (min-width: 576px) { .ed-access { grid-template-columns: repeat(3, 1fr); } }
/* Le bouton d'acces lui-meme ne change pas d'apparence : pastille
   d'icone, libelle en demi-gras, badge a droite, teinte d'etat. Seule
   sa largeur est desormais imposee par la grille du pied — d'ou le
   min-width qui autorise le libelle a s'abreger. */
.ed-act { display: flex; align-items: center; gap: .5rem; padding: .4rem .55rem; border-radius: .55rem;
  border: 1px solid var(--mdp-line); background: #fff; text-decoration: none; font-size: .82rem;
  color: var(--mdp-ink); min-width: 0; }
.ed-act .ai { width: 24px; height: 24px; border-radius: .45rem; display: flex; align-items: center;
  justify-content: center; flex: none; background: #e6f3f6; color: var(--mdp-teal); }
.ed-act .lb { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ed-act .st { margin-left: auto; font-size: .72rem; font-weight: 700; padding: .1rem .5rem; border-radius: 1rem;
  white-space: nowrap; background: #e6f3f6; color: #1f6273; }
.ed-act .cnt { margin-left: auto; min-width: 22px; height: 20px; padding: 0 .4rem; border-radius: 1rem;
  background: var(--mdp-teal); color: #fff; font-size: .72rem; font-weight: 800;
  display: flex; align-items: center; justify-content: center; }
.ed-act.on { border-color: #cfe2b6; background: #f6faee; }
.ed-act.on .ai { background: #eef6e3; color: #5f7d20; } .ed-act.on .st { background: #dcecc4; color: #4f6b1c; }
.ed-act.info .ai { background: #e6f3f6; color: #1f6273; } .ed-act.info .st { background: #d6ebef; color: #1f6273; }
.ed-act.warn { border-color: #f2ddab; background: #fffdf6; }
.ed-act.warn .ai { background: #fdf1d6; color: #96690a; } .ed-act.warn .st { background: #fbe6b5; color: #8a5f08; }
.ed-act.done .ai { background: #eef6e3; color: #5f7d20; } .ed-act.done .st { background: #dcecc4; color: #4f6b1c; }
/* Le survol vient APRES les quatre teintes, sans quoi chacune
   reimposait sa bordure : seuls les boutons neutres reagissaient, et
   le meme geste ne disait pas la meme chose d'un bouton a l'autre.
   Le turquoise est la couleur qui dit « cliquable » partout ailleurs
   sur le site — elle vaut sur les quatre fonds. */
.ed-act:hover { border-color: var(--mdp-teal); }

/* .ed-foot et .past-toggle ont disparu avec le repli des editions
   passees : « un partage de la liste est un filtre, jamais un repli »
   (charte 9.2). Les deux liens du pied sont devenus .ed-tools, et le
   repli une liste deroulante « Editions : a venir / passees /
   toutes ». */

/* --- "Report this page" link (foot of a public page) -------------- */
.report-link, .report-link .btn { font-size: .8rem; line-height: 1.4; color: var(--mdp-muted); }
.report-link .btn:hover, .report-link a:hover { color: var(--mdp-coral); }
