/* =========================================================================
   Sorties Québec - feuille de style
   Palette : vitalité sarcelle-vert · fonds clairs teintés menthe
   Typographie : Inter (corps) + Inter Tight (titres)
   ========================================================================= */

:root{
  /* Fonds & neutres */
  --bg:        #FBFDF9;
  --bg-2:      #EFF7F0;
  --surface:   #FFFFFF;
  --ink:       #15302B;
  --ink-2:     #2F4A44;
  --muted:     #587068;
  --line:      #DDE8DF;
  --line-2:    #E9F1EA;

  /* Sombre (héro, pied de page) - bleu profond (demande utilisateur
     2026-07-30 : les sections sombres se lisaient "vert foncé", elles
     passent au bleu ; la famille accent sarcelle-vert ci-dessous ne change
     pas). --on-dark-muted et les cinq teintes -bright ont été recalculées
     et restent toutes >= 4.5:1 sur ce nouveau fond (voir le rapport de
     tâche pour la table de contraste complète). */
  --dark:      #123A63;
  --dark-2:    #1A4C80;
  --on-dark:   #EFF7F2;
  --on-dark-muted:#A3C4BA;

  /* Sarcelle-vert (accent) */
  --accent:        #16A87A;
  --accent-bright: #3DC492;
  --accent-strong: #0C7A58;
  --accent-hover:  #0A6B4E;
  --accent-ink:    #0B6E52;
  --accent-soft:   #DCF5EA;
  --accent-line:   #B5E3CF;

  /* États */
  --focus:     #0B6E52;

  /* Hues par type de sortie (palette v3) - solo déplacé vers cyan-bleu pour
     éviter la collision avec le nouvel accent sarcelle-vert ; les quatre
     autres conservent leur teinte (déjà distinctes de l'accent). */
  --c-solo:                #2C99E8;
  --c-solo-ink:             #0C64A0;
  --c-solo-soft:            #DFF0FB;
  --c-entre-amis:           #F5A623;
  --c-entre-amis-ink:       #8F5E00;
  --c-entre-amis-soft:      #FDF0DA;
  --c-couple:               #E84393;
  --c-couple-ink:           #B21E67;
  --c-couple-soft:          #FBE3EF;
  --c-premier-rendez-vous:      #E8552F;
  --c-premier-rendez-vous-ink:  #B23A15;
  --c-premier-rendez-vous-soft: #FBE9E1;
  --c-famille:              #7C4DFF;
  --c-famille-ink:          #5F3DC4;
  --c-famille-soft:         #ECE6FB;

  /* Variantes "bright" - éclaircies pour rester >= 4.5:1 sur le fond sombre
     (--dark, désormais #123A63 - recontrôlées lors du passage vert -> bleu
     du 2026-07-30, toutes encore >= 4.5:1 sans retouche, voir le rapport de
     tâche pour le détail des cinq calculs). Utilisées pour le texte du
     compteur dans la carte de sortie mise en vedette (feature card) et pour
     le dégradé du titre de l'accueil ; les vives --c-<id> ci-dessus restent
     utilisées pour les icônes décoratives (seuil 3:1). */
  --c-solo-bright:                #5AB6EE;
  --c-entre-amis-bright:          #F5A623;
  --c-couple-bright:              #FF7FB8;
  --c-premier-rendez-vous-bright: #FF8F63;
  --c-famille-bright:             #B49CFF;

  /* Formes */
  --r-xs: 6px;
  --r-sm: 9px;
  --r:    13px;
  --r-lg: 20px;
  --r-pill: 999px;

  /* Ombres (chaudes, discrètes) */
  --sh-1: 0 1px 2px rgba(27,26,22,.05);
  --sh-2: 0 2px 4px rgba(27,26,22,.05), 0 14px 30px -18px rgba(27,26,22,.20);
  --sh-3: 0 30px 60px -30px rgba(18,58,99,.45);

  /* Rythme */
  --container: 1200px;
  --gutter: clamp(1.15rem, 4vw, 2.5rem);

  --t: 180ms cubic-bezier(.2,.6,.25,1);

  /* Hauteur de l'en-tête (nav 68px + bordure 1px) - utilisée par la mise en page en coquille d'application */
  --header-h: 69px;

  /* Largeur réelle de la barre de défilement du navigateur - mesurée par un
     petit script en tête de <body> (voir chaque page HTML) et appliquée à
     l'en-tête pour qu'il corresponde exactement à la largeur de .page-scroll
     (qui, elle, perd cette largeur au profit de sa propre barre). Valeur de
     repli 0px si le script n'a pas encore tourné. */
  --sbw: 0px;
}

/* ---------- Polices auto-hébergées ----------
   Inter et Inter Tight sont des fontes variables (axe wght 100-900) - un
   seul fichier .woff2 par famille couvre déjà tous les graisses utilisées
   sur le site (400/500/600/700 pour Inter, 500/600/700 pour Inter Tight),
   donc "font-weight: 400 700" ci-dessous (plage, pas une valeur unique).
   font-display:optional : le navigateur attend un très court instant
   invisible puis, si la fonte n'est pas prête, bascule sur le repli et n'y
   revient jamais pendant cette visite - donc jamais de changement visible
   de police en cours de lecture (pas de "flash" de texte qui grossit/
   rétrécit). Les deux fichiers critiques (Inter 400 + Inter Tight 600,
   utilisés dès le premier rendu) sont préchargés dans le <head> de chaque
   page.
   Les faces "*-repli" ci-dessous appliquent les mêmes métriques verticales
   qu'Inter/Inter Tight (ascenseur/descendeur/hauteur de ligne) à la police
   système de repli (via ascent-override/descent-override/size-adjust), pour
   que le texte occupe exactement la même hauteur de ligne qu'il soit rendu
   avec la police système (avant chargement, ou si font-display:optional a
   tranché en sa faveur) ou avec Inter une fois chargée - donc aucun
   réagencement visible de la mise en page dans un cas comme dans l'autre.
   Valeurs calculées à partir des tables OS/2 réelles des fichiers ci-dessous
   (capHeight 1490/2048, ascent 1984/2048, descent 494/2048, unitsPerEm 2048)
   comparées aux métriques publiées d'Arial (capHeight 1467/2048) - même
   résultat pour les deux familles, qui partagent les mêmes métriques
   verticales OS/2. */
@font-face{
  font-family:"Inter";
  font-style:normal;
  font-weight:400 700;
  font-display:optional;
  src:url("../vendor/fonts/inter-latin.woff2") format("woff2");
}
@font-face{
  font-family:"Inter Tight";
  font-style:normal;
  font-weight:400 700;
  font-display:optional;
  src:url("../vendor/fonts/inter-tight-latin.woff2") format("woff2");
}
@font-face{
  font-family:"Inter Repli";
  src:local("Arial"),local("Helvetica"),local("Segoe UI");
  ascent-override:95.38%;
  descent-override:23.75%;
  line-gap-override:0%;
  size-adjust:101.57%;
}
@font-face{
  font-family:"Inter Tight Repli";
  src:local("Arial"),local("Helvetica"),local("Segoe UI");
  ascent-override:95.38%;
  descent-override:23.75%;
  line-gap-override:0%;
  size-adjust:101.57%;
}

/* ---------- Reset léger ---------- */
*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth; }
/* Le site ne tient PAS compte de prefers-reduced-motion. Décision du
   propriétaire, prise en connaissance de cause le 2026-08-01, pour deux
   raisons : la règle globale qui vivait ici coupait toute animation et toute
   transition du site - y compris l'indicateur de chargement, qui se figeait et
   se lisait comme une panne - et le réglage se retrouve activé sur des
   machines dont la personne ignore l'avoir.

   Ce que cela coûte, écrit ici pour que personne ne le redécouvre : le critère
   2.2.2 de la WCAG (niveau A) demande un moyen d'arrêter une animation qui
   démarre seule et dure plus de cinq secondes. Le cadre tournant des lieux
   commandités entre dans ce cas et n'a plus ce moyen. Ne pas réintroduire la
   règle sans en reparler - ce n'est pas un oubli. */
body{
  margin:0;
  font-family:"Inter","Inter Repli",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  font-size:16.5px;
  line-height:1.62;
  color:var(--ink);
  background:var(--bg);
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  font-feature-settings:"cv05" 1,"ss01" 1;
}
img,svg{ display:block; max-width:100%; }
a{ color:inherit; text-decoration:none; }
button{ font:inherit; color:inherit; cursor:pointer; background:none; border:none; }
input,select,textarea{ font:inherit; color:inherit; }
/* Titres allégés (2026-07-31, demande utilisateur) : 600 partout donnait des
   titres très appuyés. Valeur explicite plutôt que le mot-clé "lighter" :
   celui-ci est relatif au parent (400 ici), donc il demanderait 100 - un poids
   que ni Inter ni Inter Tight ne contiennent (les deux fontes variables sont
   déclarées sur 400-700, voir @font-face plus haut), le navigateur le
   ramènerait à 400 sans le dire. 500 ici, et 400 sur les grands titres
   d'affichage seulement (voir .section-head/.page-hero/.quiz-q plus bas) : à
   1,1rem, 400 ne se distinguerait plus du texte courant. */
h1,h2,h3,h4{ font-family:"Inter Tight","Inter Tight Repli","Inter","Inter Repli",sans-serif; font-weight:500; line-height:1.12; letter-spacing:-.018em; margin:0; color:var(--ink); }
p{ margin:0; }
ul{ margin:0; padding:0; list-style:none; }

/* ---------- Icônes ---------- */
.ic{ width:1.25em; height:1.25em; stroke:currentColor; fill:none; stroke-width:1.75; stroke-linecap:round; stroke-linejoin:round; flex:none; }

/* ---------- Utilitaires ---------- */
.container{ width:100%; max-width:var(--container); margin-inline:auto; padding-inline:var(--gutter); }

/* Le rythme vertical entre sections vient uniquement du padding-bottom -
   seule la première section après le bandeau héro garde un padding-top,
   pour ne jamais doubler l'espacement entre deux sections empilées. */
.section{ padding-top:0; padding-bottom:clamp(3.4rem,7vw,6rem); }
/* Une section qui suit un bloc à fond lavis retrouve son padding-top : la
   règle "pas de padding-top" ci-dessus évite de doubler l'espacement entre
   deux sections sur fond identique, mais ici la rupture de couleur rend la
   section suivante collée à la bande du dessus (2026-07-31). */
.page-hero + .section,
.section-wash + .section,
main > .section:first-child{ padding-top:clamp(3.4rem,7vw,6rem); }
section[id],#quiz-results,#quiz-card{ scroll-margin-top:84px; }
.section-head{ max-width:44rem; margin-bottom:clamp(1.8rem,4vw,3rem); }

/* ---------- Fonds dégradés discrets ----------
   Réécrits en CSS pur le 2026-07-31 : c'étaient trois JPEG de dégradés flous
   (bleu-violet, cyan, blush) recouverts d'un voile blanc à 92% pour rester
   lisibles - trois requêtes réseau et 85 ko pour un résultat presque invisible
   et, surtout, dans des teintes qui n'existent nulle part ailleurs sur le
   site. Ce sont maintenant des dégradés construits sur les jetons de la
   palette : rien à télécharger, net à toutes les résolutions, et les couleurs
   sont celles du reste du site. Plus de voile ::before non plus - les
   couleurs sont choisies ici, donc le contraste est garanti par construction
   plutôt que rattrapé après coup (mesures dans les commentaires ci-dessous,
   toujours contre --muted #587068, le ton de texte le plus pâle du site).
   Trois emplacements : les catégories de l'accueil, le sélecteur d'intérêts
   de par-interet.html, les étapes du speed dating. Jamais derrière une grille
   de fiches de lieu (voir la note dans par-interet.html). */
.section-wash{ position:relative; isolation:isolate; }
.section-wash > .container{ position:relative; z-index:1; }

/* Accueil - vert de marque monté du coin inférieur gauche, bleu marine du
   coin inférieur droit : les deux couleurs identitaires du site, concentrées
   sous l'index des types de sortie et quasi éteintes au niveau du bloc de
   titre. Mesuré sur le rendu réel (capture de la section sans son contenu,
   pixel le plus sombre de chaque zone, contre --muted #587068) : 5,11:1 dans
   le bloc de titre, 4,57:1 dans l'index, 4,43:1 dans la marge basse où aucun
   texte ne repose. Les rangées de l'index n'ont pas de fond opaque, leur
   texte est donc bien posé sur ce dégradé - d'où des opacités volontairement
   basses. */
.wash-blue{
  background:
    radial-gradient(115% 85% at 8% 118%, rgba(22,168,122,.11) 0%, rgba(22,168,122,0) 58%),
    radial-gradient(95% 80% at 92% 112%, rgba(18,58,99,.07) 0%, rgba(18,58,99,0) 60%),
    linear-gradient(180deg, #FBFDFB 0%, var(--bg-2) 100%);
}

/* Par intérêt - bloc court et large : un seul foyer vert d'eau en haut à
   droite suffit, il pousse le regard vers les puces sans les concurrencer.
   Seules des puces (fond opaque) reposent dessus, l'opacité peut donc monter
   plus haut qu'ailleurs sans mettre de texte en difficulté. */
.wash-cyan{
  background:
    radial-gradient(90% 130% at 100% 0%, rgba(22,168,122,.18) 0%, rgba(22,168,122,0) 62%),
    linear-gradient(180deg, var(--bg-2) 0%, #FBFDFB 100%);
}

/* Speed dating - même construction, teintée vers le rose de la sortie "en
   couple" (--c-couple), le seul endroit du site où cette teinte a du sens.
   Du texte --muted court jusqu'en bas de cette section (les étapes, le bloc
   "aucun événement"), d'où des opacités encore plus basses qu'ailleurs :
   point le plus chargé mesuré à 4,55:1 sur le rendu réel. */
.wash-blush{
  background:
    radial-gradient(80% 120% at 15% 0%, rgba(232,67,147,.08) 0%, rgba(232,67,147,0) 55%),
    radial-gradient(90% 110% at 95% 100%, rgba(22,168,122,.07) 0%, rgba(22,168,122,0) 58%),
    linear-gradient(180deg, #FBFDFB 0%, var(--bg-2) 100%);
}
/* .interet-picker (par-interet.html) n'est pas une <section> pleine largeur
   mais un bloc à l'intérieur de .container - il porte lui-même .section-wash
   et a donc besoin de son propre espacement interne pour que le lavis ne
   colle pas directement aux puces/au h2. */
.interet-picker{ padding:1.4rem 1.4rem 1.6rem; border-radius:var(--r); margin-bottom:1.6rem; }
.interet-picker .interet-grid{ margin-bottom:0; position:relative; z-index:1; }
.interet-picker h2{ position:relative; z-index:1; }
/* Grands titres d'affichage : 400, le plus léger que contiennent les fontes
   variables du site. Plus de margin-top : elle ne servait qu'à espacer le
   titre de l'eyebrow au-dessus, retiré des 5 pages le 2026-07-31. */
.section-head h1,.section-head h2{ font-size:clamp(1.7rem,3.6vw,2.5rem); font-weight:400; }
.section-head p{ margin-top:.9rem; color:var(--muted); font-size:1.05rem; }
.skip-link{ position:absolute; left:-999px; top:.5rem; z-index:200; background:var(--dark); color:var(--on-dark); padding:.6rem 1rem; border-radius:var(--r-sm); }
.skip-link:focus{ left:.75rem; }

:where(a,button,input,select,[tabindex]):focus-visible{ outline:2.5px solid var(--focus); outline-offset:2px; border-radius:var(--r-xs); }
/* A11Y fix (2026-07-30, WCAG 2.2 SC 1.4.11): --focus (#0B6E52) measures only
   1.86:1 on the --dark navy (#123A63) used by these three full-bleed dark
   surfaces (site footer, page-hero bands, promo band) - below the 3:1 floor
   for a focus indicator. --accent-bright measures 5.25:1 on --dark, so these
   three dark-surface contexts override the outline colour; every other
   surface (cards, chips, form controls) stays on the light background where
   --focus already passes and is left untouched. */
.site-footer :focus-visible,
.page-hero :focus-visible,
.promo-band :focus-visible{ outline-color:var(--accent-bright); }

/* ---------- Boutons ---------- */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:.55rem;
  padding:.82rem 1.35rem; border-radius:var(--r-sm);
  font-weight:600; font-size:.96rem; letter-spacing:-.005em;
  border:1px solid transparent; transition:transform var(--t),background var(--t),border-color var(--t),color var(--t),box-shadow var(--t);
  white-space:nowrap;
}
.btn .ic{ width:1.15em; height:1.15em; }
.btn-primary{ background:var(--accent-strong); color:#fff; box-shadow:var(--sh-1); }
.btn-primary:hover{ background:var(--accent-hover); transform:translateY(-1px); }
.btn-forest{ background:var(--dark); color:var(--on-dark); }
.btn-forest:hover{ background:var(--dark-2); transform:translateY(-1px); }
.btn-ghost{ background:transparent; color:var(--ink); border-color:var(--line); }
.btn-ghost:hover{ border-color:var(--ink); background:var(--surface); }
.btn-ghost-light{ background:transparent; color:var(--on-dark); border-color:rgba(239,247,242,.34); }
.btn-ghost-light:hover{ border-color:var(--on-dark); background:rgba(255,255,255,.06); }
.btn-sm{ padding:.55rem .9rem; font-size:.86rem; }
.btn[disabled]{ opacity:.4; cursor:not-allowed; transform:none; }

/* ---------- Structure de page (coquille d'application) ----------
   Le défilement se fait dans .page-scroll, pas sur <body>, pour que la
   barre de défilement du viewport ne passe jamais sous l'en-tête. */
html,body{ height:100%; }
body{ display:flex; flex-direction:column; overflow:hidden; }
.page-scroll{
  flex:1; min-height:0;
  overflow-y:auto; overflow-x:clip;
  scroll-behavior:smooth;
  scrollbar-gutter:stable;
}

/* ---------- Barres de défilement discrètes (survol/défilement actif) ----------
   Les régions à défilement interne du site (page complète, résultats de
   l'explorateur, ses filtres, options et résultats du questionnaire)
   réservent déjà leur gouttière (scrollbar-gutter:stable, déclaré sur chaque
   région ci-dessous/plus bas - rien n'est double-réservé, .page-scroll--shell
   annule sa propre réservation quand la vraie barre vit sur une région
   interne, voir plus haut) : le pouce ne devient visible qu'au survol ou
   pendant un défilement actif (classe .is-scrolling, voir wireScrollbarReveal
   dans app.js), sinon la piste reste totalement transparente. Défilement
   clavier/tactile inchangé - c'est un habillage purement visuel. Couleur de
   pouce volontairement translucide plutôt qu'un ton plein unique : certaines
   de ces régions (.page-scroll en particulier) défilent aussi bien sur des
   bandeaux clairs que sur le héro/pied de page sombres - la transparence
   s'adapte visuellement aux deux plutôt que de figer un ton qui ne
   conviendrait qu'à l'un des deux. */
.page-scroll,
.venues,
.explorer-aside,
.quiz-q,
#quiz-venues{
  scrollbar-width:thin;
  scrollbar-color:transparent transparent;
}
.page-scroll:hover, .page-scroll.is-scrolling,
.venues:hover, .venues.is-scrolling,
.explorer-aside:hover, .explorer-aside.is-scrolling,
.quiz-q:hover, .quiz-q.is-scrolling,
#quiz-venues:hover, #quiz-venues.is-scrolling{
  scrollbar-color:rgba(90,110,105,.6) transparent;
}
.page-scroll::-webkit-scrollbar,
.venues::-webkit-scrollbar,
.explorer-aside::-webkit-scrollbar,
.quiz-q::-webkit-scrollbar,
#quiz-venues::-webkit-scrollbar{
  width:8px; height:8px;
}
.page-scroll::-webkit-scrollbar-track,
.venues::-webkit-scrollbar-track,
.explorer-aside::-webkit-scrollbar-track,
.quiz-q::-webkit-scrollbar-track,
#quiz-venues::-webkit-scrollbar-track{
  background:transparent;
}
.page-scroll::-webkit-scrollbar-thumb,
.venues::-webkit-scrollbar-thumb,
.explorer-aside::-webkit-scrollbar-thumb,
.quiz-q::-webkit-scrollbar-thumb,
#quiz-venues::-webkit-scrollbar-thumb{
  background:transparent; border-radius:var(--r-pill);
}
.page-scroll:hover::-webkit-scrollbar-thumb, .page-scroll.is-scrolling::-webkit-scrollbar-thumb,
.venues:hover::-webkit-scrollbar-thumb, .venues.is-scrolling::-webkit-scrollbar-thumb,
.explorer-aside:hover::-webkit-scrollbar-thumb, .explorer-aside.is-scrolling::-webkit-scrollbar-thumb,
.quiz-q:hover::-webkit-scrollbar-thumb, .quiz-q.is-scrolling::-webkit-scrollbar-thumb,
#quiz-venues:hover::-webkit-scrollbar-thumb, #quiz-venues.is-scrolling::-webkit-scrollbar-thumb{
  background:rgba(90,110,105,.6);
}

/* ---------- Coquille stricte "une page" - questionnaire (Étape 3d, remplace
   la version 3c ; explorateur exclu ci-dessous via :not(.explorer-page) - il
   a son propre seuil à 1024px, voir plus bas, depuis l'ajout du panneau de
   filtres plein écran mobile). En dessous de 768px, .page-scroll--shell se
   comporte comme .page-scroll normal (défilement de page classique). À
   768px et plus, plus rien ne défile ici : la page occupe exactement
   100dvh et seule la région désignée (options du questionnaire) défile en
   interne. */
@media (min-width:768px){
  body:not(.explorer-page) .page-scroll--shell{
    overflow:hidden;
    display:flex; flex-direction:column;
    /* Plus de vraie barre de défilement ici (elle est maintenant sur la
       région interne désignée) - annule la réservation --sbw/stable, sinon
       elle laisse un espace fantôme à droite qui empêche le contenu de
       vraiment toucher le bord (demande utilisateur 2026-07-30). */
    scrollbar-gutter:auto;
  }
  body:not(.explorer-page) .page-scroll--shell > main{
    display:flex; flex-direction:column;
    flex:1; min-height:0;
    /* Tâche 16 (ajustement) : .page-scroll--shell n'a plus de barre de
       défilement propre (scrollbar-gutter:auto ci-dessus), alors que les 3
       autres pages défilent dans .page-scroll (scrollbar-gutter:stable, qui
       réserve --sbw). Comme le héro et les coquilles internes de
       l'explorateur/questionnaire utilisent maintenant le même .container
       plafonné/centré que les 3 autres pages, on reproduit ici la même
       réservation - sinon leur centrage se ferait sur une largeur plus
       grande et leur bord gauche ne tomberait plus au même endroit. */
    padding-right:var(--sbw);
  }
}
/* Explorateur : mêmes règles de coquille "une page" que ci-dessus, mais à
   partir de 1024px seulement - entre 768 et 1023px, la page défile
   normalement et les filtres vivent dans le panneau plein écran mobile
   (voir plus bas, section Explorateur) plutôt que dans une colonne latérale
   fixe à côté des résultats. */
@media (min-width:1024px){
  .explorer-page .page-scroll--shell{
    overflow:hidden;
    display:flex; flex-direction:column;
    scrollbar-gutter:auto;
  }
  .explorer-page .page-scroll--shell > main{
    display:flex; flex-direction:column;
    flex:1; min-height:0;
    padding-right:var(--sbw);
  }
}

/* ---------- En-tête / navigation ---------- */
.site-header{
  position:relative; z-index:100; flex:none;
  background:rgba(239,247,240,.82); backdrop-filter:saturate(1.4) blur(12px);
  border-bottom:1px solid var(--line);
}
/* Compense la largeur de la barre de défilement de .page-scroll (voir --sbw
   ci-dessus) en réduisant la largeur du bloc conteneur de l'en-tête (via
   padding, pas overflow:hidden - ça couperait le panneau de menu mobile
   position:fixed, que les navigateurs rognent même si la spec dit le
   contraire). Le .container centré (margin-inline:auto) se recentre alors
   sur la même largeur effective que dans .page-scroll.
   S'applique aux 5 pages, sans exception (2026-07-31) : l'explorateur et le
   questionnaire annulaient cette réservation, alors que leur <main> la
   reproduit quand même (voir .page-scroll--shell > main plus haut) - la
   navigation s'y décalait donc de la largeur d'une barre de défilement par
   rapport aux autres pages. */
.site-header{ padding-right:var(--sbw); }
/* Tâche 16 : le bandeau de navigation est désormais pleine largeur sur les
   5 pages (gutter uniquement, pas de plafond) - même bord gauche que le
   bandeau héro et la marque, sur toutes les pages. Remplace la règle
   propre aux coquilles d'application (explorer/questionnaire), devenue
   redondante puisque la règle s'applique maintenant partout. */
.site-header .container{ max-width:none; margin-inline:0; }
.nav{ display:flex; align-items:center; gap:1.4rem; height:68px; }
.brand{ display:inline-flex; align-items:center; gap:.6rem; font-family:"Inter Tight","Inter Tight Repli",sans-serif; font-weight:600; font-size:1.16rem; letter-spacing:-.02em; }
.brand .fleur{ width:26px; height:26px; color:var(--accent); }
.brand .q{ color:var(--accent-ink); font-weight:600; }
.nav-spacer{ flex:1; }
.nav-links{ display:flex; align-items:center; gap:.35rem; }
.nav-links a{ padding:.5rem .8rem; border-radius:var(--r-sm); font-size:.93rem; font-weight:500; color:var(--ink-2); transition:background var(--t),color var(--t); }
.nav-links a:hover{ background:var(--bg-2); color:var(--ink); }
.nav-links a[aria-current="page"]{ background:var(--bg-2); color:var(--accent-ink); }
.footer-col a[aria-current="page"]{ color:#fff; }
.nav-toggle{ display:none; width:42px; height:42px; align-items:center; justify-content:center; border:none; border-radius:var(--r-sm); }

/* Tâche 18 : ajout d'un 6e lien ("Par intérêt") - entre 861px (seuil du menu
   mobile ci-dessous) et ~1180px, les liens commençaient à serrer le bord du
   bouton hamburger, voire à passer à la ligne de façon abrupte. On resserre
   l'espacement/le padding des liens dans cette plage plutôt que de baisser le
   seuil du menu mobile (qui reste à 860px), et on autorise un retour à la
   ligne propre en tout dernier recours si une résolution encore plus étroite
   s'en trouvait affichée.

   2026-08-01 : la pastille de région a quitté l'en-tête (elle vit maintenant
   dans le sélecteur de géographie, voir .geo-choix plus bas), mais cette règle
   reste nécessaire - vérifié à 861px, les six liens seuls repassent sur deux
   lignes sans elle, et jusqu'à ~960px. La borne haute est laissée à 1180px :
   la largeur exacte où le débordement cesse dépend du rendu des polices, et
   resserrer l'espacement un peu trop longtemps ne coûte rien. */
.nav-links{ flex-wrap:wrap; row-gap:.25rem; }
@media (min-width:861px) and (max-width:1180px){
  .nav-links{ gap:.1rem; }
  .nav-links a{ padding:.5rem .55rem; font-size:.88rem; }
  /* .nav impose height:68px plus haut dans ce fichier (utile quand tout
     tient sur une ligne) - si les 5 liens finissent tout de même sur deux
     lignes à une largeur donnée dans cette plage, height:auto laisse
     l'en-tête grandir pour les deux lignes plutôt que de les centrer dans
     une boîte de hauteur fixe (ce qui les ferait légèrement déborder en haut
     et en bas de l'en-tête). */
  .nav{ height:auto; min-height:68px; padding-block:.35rem; }
}

@media (max-width:860px){
  .nav-links{ display:none; }
  .nav-toggle{ display:inline-flex; }
  .nav-links.open{
    /* position:fixed (plutôt que absolute) : le panneau reste entier même si
       .site-header a overflow-y:hidden (réservation de la gouttière de la
       barre de défilement) - fixed échappe au clip d'un ancêtre. */
    display:flex; position:fixed; left:var(--gutter); right:var(--gutter); top:var(--header-h);
    flex-direction:column; align-items:stretch; gap:.15rem;
    background:var(--surface); border:1px solid var(--line); border-radius:var(--r); padding:.5rem; box-shadow:var(--sh-2);
  }
  .nav-links.open a{ padding:.75rem .9rem; }
}

/* ---------- Héro (bandeau CTA de l'accueil) ----------
   L'accueil partage désormais le même bandeau compact .page-hero que les
   autres pages (Tâche 13, harmonisation) - .hero-cta reste son propre bloc
   car les boutons de l'accueil vivent sous la lede plutôt qu'à côté d'elle. */
.hero-cta{ display:flex; flex-wrap:wrap; gap:.8rem; margin-top:1.6rem; }

@media (max-width:520px){
  .hero-cta{ flex-direction:column; align-items:stretch; }
  .hero-cta .btn{ width:100%; }
}

/* ---------- En-tête de page compact (photo) ---------- */
.page-hero{ position:relative; background:var(--dark); color:var(--on-dark); overflow:hidden; }
/* Tâche 16 (ajustement) : les 5 pages utilisent maintenant .container sur ce
   bloc, donc le texte du héro est toujours plafonné/centré à --container
   (1200px) et aligné avec les titres de section - sur l'explorateur et le
   questionnaire, le reste de la coquille (filtres/résultats, quiz) adopte
   maintenant le même plafond (voir .explorer-shell / .quiz-shell plus bas),
   seule la nav reste pleine largeur sur ces deux pages. padding-inline
   reste déclaré ici en repli (même valeur --gutter que .container) au cas
   où .container serait retiré d'une bande héro. */
.page-hero-inner{ position:relative; z-index:1; padding-block:clamp(2.6rem,6vw,4rem); padding-inline:var(--gutter); }
.page-hero-content{ max-width:44rem; text-align:left; }
.page-hero h1{ color:#fff; font-size:clamp(1.9rem,4.2vw,2.7rem); font-weight:400; max-width:34ch; }
/* Titre de l'accueil : le segment mis en emphase a brièvement essayé une
   couleur pleine puis un dégradé texte (demandes utilisateur du 2026-07-30) ;
   décision finale : aucune mise en emphase de couleur, même blanc que le
   reste du h1 - font-style:normal reste nécessaire (l'élément <em> est
   italique par défaut, ce qui n'est pas voulu ici). */
.page-hero h1 em{ font-style:normal; color:#fff; }
.page-hero p{ margin-top:.85rem; font-size:1.02rem; color:var(--on-dark); max-width:44rem; line-height:1.55; }

.page-hero--index.has-photo{
  background:
    linear-gradient(115deg, rgba(18,58,99,.92) 0%, rgba(18,58,99,.78) 45%, rgba(44,153,232,.5) 100%),
    url("../images/hero-quebec-skyline.jpg") center/cover no-repeat var(--dark);
}
@media (max-width:720px){
  .page-hero--index.has-photo{ background-image:
    linear-gradient(115deg, rgba(18,58,99,.92) 0%, rgba(18,58,99,.78) 45%, rgba(44,153,232,.5) 100%),
    url("../images/hero-quebec-skyline-960.jpg"); }
}
/* Évènements : réutilise la photo du Château Frontenac, déjà dans le dépôt
   (elle ne servait que d'arrière-plan au bloc "Proposer un lieu"). Queue de
   teinte verte comme la page Par intérêt. */
.page-hero--evenements.has-photo{
  background:
    linear-gradient(115deg, rgba(18,58,99,.92) 0%, rgba(18,58,99,.78) 45%, rgba(22,168,122,.5) 100%),
    url("../images/chateau-frontenac.jpg") center/cover no-repeat var(--dark);
}
.page-hero--apropos.has-photo{
  background:
    linear-gradient(115deg, rgba(18,58,99,.92) 0%, rgba(18,58,99,.78) 45%, rgba(245,166,35,.5) 100%),
    url("../images/amis-terrasse.jpg") center/cover no-repeat var(--dark);
}
.page-hero--speeddating.has-photo{
  background:
    linear-gradient(115deg, rgba(18,58,99,.92) 0%, rgba(18,58,99,.78) 45%, rgba(214,51,108,.5) 100%),
    url("../images/sortie-groupe.jpg") center/cover no-repeat var(--dark);
}
/* M1 fix (2026-07-30) : seule page de contenu dont le héro n'avait pas de
   photo - réutilise images/quebec-ville.jpg (jusqu'ici inutilisée depuis le
   retrait de l'ancien héro de l'explorateur). Queue de teinte sarcelle-vert
   (--accent, rgb(22,168,122)) plutôt qu'une des quatre teintes déjà prises
   par une autre page de contenu (orange à propos, rose speed-dating, bleu
   accueil) - Par intérêt n'est rattaché à aucun type de sortie en particulier. */
.page-hero--interet.has-photo{
  background:
    linear-gradient(115deg, rgba(18,58,99,.92) 0%, rgba(18,58,99,.78) 45%, rgba(22,168,122,.5) 100%),
    url("../images/quebec-ville.jpg") center/cover no-repeat var(--dark);
}

/* ---------- Index « types de sortie » ----------
   Remplace la grille de 5 cartes (2026-07-31, demande utilisateur) : à cinq
   colonnes dans 1200px, chaque carte tombait sous les 220px, les titres
   passaient sur deux lignes ("Premier rendez-vous") et les descriptions sur
   trois, avec des hauteurs toutes différentes. En rangées pleine largeur,
   chaque type tient sur une ligne de titre + une ligne de description, les
   nombres s'alignent à droite et l'ensemble se lit comme le sommaire d'un
   guide. Même destination, même donnée, aucun changement côté explorateur. */
.cat-list{ list-style:none; margin:0; padding:0; border-top:1px solid var(--line); }
.cat-row{
  display:grid; grid-template-columns:auto 1fr auto; align-items:center;
  gap:0 1.1rem; padding:1.15rem .75rem;
  border-bottom:1px solid var(--line);
  transition:background var(--t),padding-left var(--t);
}
/* Le fond ne fait que se teinter et la rangée avance légèrement : pas
   d'ombre ni de soulèvement, qui redonneraient l'aspect "carte" que cette
   disposition cherche justement à quitter. */
.cat-row:hover{ background:var(--bg-2); padding-left:1.1rem; }
.cat-row .ic-wrap{ width:40px; height:40px; display:grid; place-items:center; color:var(--accent-strong); }
.cat-row .ic-wrap .ic{ width:22px; height:22px; stroke-width:2.1; }
.cat-row-body{ display:flex; flex-direction:column; gap:.15rem; min-width:0; }
.cat-row h3{ font-size:1.12rem; }
.cat-row-desc{ font-size:.9rem; color:var(--muted); line-height:1.5; }
/* Chevron d'appel : seul repère à droite depuis le retrait du nombre de
   lieux. Teinté à la couleur du type de sortie (voir le bloc "Hues" plus
   bas) pour que chaque rangée garde son identité. */
.cat-row-go{ display:inline-flex; align-items:center; color:var(--accent-ink); }
.cat-row-go .ic{ width:18px; height:18px; transition:transform var(--t); }
.cat-row:hover .cat-row-go .ic{ transform:translateX(3px); }
@media (max-width:560px){
  /* Le chevron ne prend que 18px, les trois colonnes tiennent toujours -
     seuls les marges internes se resserrent. */
  .cat-row{ gap:0 .85rem; padding-inline:.25rem; }
}

/* ---------- Hues par type de sortie (palette v2) ----------
   Un bloc par sortie : cartes de catégorie, puces de filtre, options du
   questionnaire (contexte). Toute la logique de couleur reste en CSS -
   le JS ne fait qu'ajouter data-sortie="<id>" sur les éléments rendus.
   Tuiles d'icône (.ic-wrap/.opt-ic) sans fond depuis le 2026-07-30 (voir plus
   haut) : leur teinte "sélectionnée/catégorie" vient donc uniquement de la
   couleur du glyphe. Les cinq variantes -ink sont utilisées uniformément
   ici (et pas seulement pour entre-amis) - calculé >= 3:1 (repli non-texte)
   sur --surface (blanc) ET --bg-2 pour les cinq teintes : solo 6.27:1/5.74:1,
   entre-amis 5.57:1/5.10:1 (déjà en place), couple 6.41:1/5.87:1,
   premier-rendez-vous 5.99:1/5.48:1, famille 7.12:1/6.52:1 - les teintes
   brutes (--c-<id>) échouaient pour au moins une des deux surfaces (ex.
   solo brut : 3.08:1 sur blanc mais seulement 2.82:1 sur --bg-2, sous le
   seuil), donc -ink partout plutôt qu'un traitement au cas par cas. */
.cat-row[data-sortie="solo"] .ic-wrap{ color:var(--c-solo-ink); }
.cat-row[data-sortie="solo"]:hover{ border-bottom-color:var(--c-solo); }
.cat-row[data-sortie="solo"] .cat-row-go{ color:var(--c-solo-ink); }
.chip[data-sortie="solo"][aria-pressed="true"]{ background:var(--c-solo-soft); border-color:var(--c-solo); color:var(--c-solo-ink); }
.chip[data-sortie="solo"][aria-pressed="true"] .ic{ color:var(--c-solo-ink); }
.opt[data-sortie="solo"][aria-pressed="true"]{ border-color:var(--c-solo); background:var(--c-solo-soft); box-shadow:inset 0 0 0 1px var(--c-solo); }
.opt[data-sortie="solo"][aria-pressed="true"] .opt-ic{ color:var(--c-solo-ink); }
.opt[data-sortie="solo"][aria-pressed="true"] .opt-check{ background:var(--c-solo); border-color:var(--c-solo); }

.cat-row[data-sortie="entre-amis"] .ic-wrap{ color:var(--c-entre-amis-ink); }
/* SECURITY/A11Y: --c-entre-amis (#F5A623) on the white .cat-row surface only
   measures 2.03:1, below the 3:1 non-text floor (WCAG 2.2). Border uses the
   darker -ink token instead (5.57:1 on white) - tiles/icons keep the bright
   amber hue untouched. */
.cat-row[data-sortie="entre-amis"]:hover{ border-bottom-color:var(--c-entre-amis-ink); }
.cat-row[data-sortie="entre-amis"] .cat-row-go{ color:var(--c-entre-amis-ink); }
.chip[data-sortie="entre-amis"][aria-pressed="true"]{ background:var(--c-entre-amis-soft); border-color:var(--c-entre-amis); color:var(--c-entre-amis-ink); }
.chip[data-sortie="entre-amis"][aria-pressed="true"] .ic{ color:var(--c-entre-amis-ink); }
.opt[data-sortie="entre-amis"][aria-pressed="true"]{ border-color:var(--c-entre-amis); background:var(--c-entre-amis-soft); box-shadow:inset 0 0 0 1px var(--c-entre-amis); }
.opt[data-sortie="entre-amis"][aria-pressed="true"] .opt-ic{ color:var(--c-entre-amis-ink); }
.opt[data-sortie="entre-amis"][aria-pressed="true"] .opt-check{ background:var(--c-entre-amis); border-color:var(--c-entre-amis); }

.cat-row[data-sortie="couple"] .ic-wrap{ color:var(--c-couple-ink); }
.cat-row[data-sortie="couple"]:hover{ border-bottom-color:var(--c-couple); }
.cat-row[data-sortie="couple"] .cat-row-go{ color:var(--c-couple-ink); }
.chip[data-sortie="couple"][aria-pressed="true"]{ background:var(--c-couple-soft); border-color:var(--c-couple); color:var(--c-couple-ink); }
.chip[data-sortie="couple"][aria-pressed="true"] .ic{ color:var(--c-couple-ink); }
.opt[data-sortie="couple"][aria-pressed="true"]{ border-color:var(--c-couple); background:var(--c-couple-soft); box-shadow:inset 0 0 0 1px var(--c-couple); }
.opt[data-sortie="couple"][aria-pressed="true"] .opt-ic{ color:var(--c-couple-ink); }
.opt[data-sortie="couple"][aria-pressed="true"] .opt-check{ background:var(--c-couple); border-color:var(--c-couple); }

.cat-row[data-sortie="premier-rendez-vous"] .ic-wrap{ color:var(--c-premier-rendez-vous-ink); }
.cat-row[data-sortie="premier-rendez-vous"]:hover{ border-bottom-color:var(--c-premier-rendez-vous); }
.cat-row[data-sortie="premier-rendez-vous"] .cat-row-go{ color:var(--c-premier-rendez-vous-ink); }
.chip[data-sortie="premier-rendez-vous"][aria-pressed="true"]{ background:var(--c-premier-rendez-vous-soft); border-color:var(--c-premier-rendez-vous); color:var(--c-premier-rendez-vous-ink); }
.chip[data-sortie="premier-rendez-vous"][aria-pressed="true"] .ic{ color:var(--c-premier-rendez-vous-ink); }
.opt[data-sortie="premier-rendez-vous"][aria-pressed="true"]{ border-color:var(--c-premier-rendez-vous); background:var(--c-premier-rendez-vous-soft); box-shadow:inset 0 0 0 1px var(--c-premier-rendez-vous); }
.opt[data-sortie="premier-rendez-vous"][aria-pressed="true"] .opt-ic{ color:var(--c-premier-rendez-vous-ink); }
.opt[data-sortie="premier-rendez-vous"][aria-pressed="true"] .opt-check{ background:var(--c-premier-rendez-vous); border-color:var(--c-premier-rendez-vous); }

.cat-row[data-sortie="famille"] .ic-wrap{ color:var(--c-famille-ink); }
.cat-row[data-sortie="famille"]:hover{ border-bottom-color:var(--c-famille); }
.cat-row[data-sortie="famille"] .cat-row-go{ color:var(--c-famille-ink); }
.chip[data-sortie="famille"][aria-pressed="true"]{ background:var(--c-famille-soft); border-color:var(--c-famille); color:var(--c-famille-ink); }
.chip[data-sortie="famille"][aria-pressed="true"] .ic{ color:var(--c-famille-ink); }
.opt[data-sortie="famille"][aria-pressed="true"]{ border-color:var(--c-famille); background:var(--c-famille-soft); box-shadow:inset 0 0 0 1px var(--c-famille); }
.opt[data-sortie="famille"][aria-pressed="true"] .opt-ic{ color:var(--c-famille-ink); }
.opt[data-sortie="famille"][aria-pressed="true"] .opt-check{ background:var(--c-famille); border-color:var(--c-famille); }

/* ---------- Questionnaire ----------
   Tâche 14 : plus de mini-carte flottante avec ascenseur interne - l'assistant
   occupe toute la largeur de la coquille d'application (comme l'explorateur).
   La barre de progression, l'entête de question et la navigation
   précédent/suivant vivent directement dans .quiz-shell ; .quiz-card (ciblé
   par le JS) n'est plus qu'un conteneur flex sans habillage de carte.
   Tâche (retrait du héro) : le bandeau héro de cette page a été supprimé -
   .quiz-shell part maintenant du haut de la coquille d'application, ce qui
   rend à la grille d'options tout l'espace vertical que le bandeau occupait.
   Le seuil de l'ascenseur interne plus bas dans ce fichier a été abaissé en
   conséquence. */
.quiz{ background:var(--bg-2); border-top:1px solid var(--line); border-bottom:1px solid var(--line); }
/* Tâche 16 (ajustement) : plafonné/centré comme .container (1200px) - la nav
   reste seule pleine largeur sur cette page, le contenu du questionnaire
   partage désormais la même largeur que les 3 autres pages. */
.quiz-shell{ width:100%; max-width:var(--container); margin-inline:auto; padding-inline:var(--gutter); }
.quiz-card{ width:100%; padding-block:clamp(1.1rem,2.6vw,1.7rem) 0; }
.quiz-progress{ display:flex; align-items:center; gap:1rem; margin-bottom:clamp(1.2rem,3vw,1.9rem); }
.quiz-progress .track{ flex:1; height:6px; border-radius:var(--r-pill); background:var(--line-2); overflow:hidden; }
.quiz-progress .fill{ height:100%; width:0; background:var(--accent); border-radius:inherit; transition:width var(--t); }
.quiz-progress .step-lbl{ font-size:.8rem; font-weight:600; color:var(--muted); letter-spacing:.02em; white-space:nowrap; }
.quiz-q{ animation:fade .28s ease; }
@keyframes fade{ from{ opacity:0; transform:translateY(6px); } to{ opacity:1; transform:none; } }
.quiz-q .q-kicker{ font-size:.78rem; font-weight:600; letter-spacing:.14em; text-transform:uppercase; color:var(--accent-ink); }
.quiz-q h3{ font-size:clamp(1.4rem,3.4vw,2.1rem); font-weight:400; margin-top:.5rem; max-width:34ch; }
.quiz-q .q-hint{ margin-top:.45rem; color:var(--muted); font-size:.93rem; max-width:60ch; }
.q-multi-badge{
  display:inline-flex; align-items:center; gap:.4rem; margin-top:.55rem;
  font-size:.76rem; font-weight:600; color:var(--accent-ink);
  background:var(--accent-soft); border:1px solid var(--accent-line);
  padding:.26rem .65rem; border-radius:var(--r-pill);
}
.q-multi-badge .ic{ width:14px; height:14px; }

/* Étiquette « en cours ». Trois critères (réservation, accessibilité,
   alimentation) reposent sur des données encore très incomplètes : presque
   aucun lieu n'est tagué pour l'accessibilité et l'alimentation, et la plupart
   sont « réservation à vérifier ». Filtrer là-dessus donne donc peu ou pas de
   résultats, ce qui se lit à tort comme « il n'y a rien ». L'étiquette le dit
   franchement plutôt que de laisser croire à une recherche complète. Les
   filtres restent utilisables : quelqu'un qui a un besoin d'accessibilité doit
   pouvoir chercher, même sur des données partielles.
   Couleurs : #8F5E00 sur #FDF0DA = 4,96:1, au-dessus du seuil AA de 4,5:1. */
.wip-badge{
  display:inline-flex; align-items:center; flex:none;
  font-size:.68rem; font-weight:700; letter-spacing:.04em; text-transform:none;
  color:var(--c-entre-amis-ink); background:var(--c-entre-amis-soft);
  border:1px solid #EFD9A8; padding:.12rem .45rem; border-radius:var(--r-pill);
}
/* Dans le questionnaire, l'étiquette est seule sur sa ligne sous le titre. */
.quiz-q .wip-badge{ margin-top:.55rem; font-size:.76rem; padding:.26rem .65rem; }
/* Grille d'options du questionnaire (Tâche "UI batch 2", item 6) : colonnes
   explicites par palier plutôt qu'auto-fit/minmax - l'ancienne règle
   (auto-fit, minmax(240px,1fr)) produisait 4 colonnes sur les viewports
   larges (>= ~1050px de contenu), ce qui rendait chaque option trop étroite.
   Plafonné à 3 colonnes max, toujours responsive en-dessous : 1 (mobile),
   2 (tablette), 3 (bureau). */
.opt-grid{
  display:grid; gap:.7rem; margin-top:clamp(1rem,2.4vw,1.5rem);
  grid-template-columns:1fr;
}
@media (min-width:640px){
  .opt-grid{ grid-template-columns:repeat(2,1fr); }
}
@media (min-width:900px){
  .opt-grid{ grid-template-columns:repeat(3,1fr); }
}
.opt{
  display:flex; align-items:center; gap:1rem; text-align:left; width:100%;
  min-height:72px; padding:1.05rem 1.2rem; border:1px solid var(--line); border-radius:var(--r);
  background:var(--surface); transition:border-color var(--t),background var(--t),box-shadow var(--t),transform var(--t);
}
.opt:hover{ border-color:var(--accent-line); background:var(--bg-2); transform:translateY(-1px); }
.opt .opt-ic{ width:46px; height:46px; display:grid; place-items:center; color:var(--accent-strong); flex:none; }
.opt .opt-ic .ic{ width:22px; height:22px; stroke-width:2.1; }
.opt .opt-txt{ display:flex; flex-direction:column; gap:.15rem; }
.opt .opt-txt b{ font-weight:600; font-size:1.02rem; }
.opt .opt-txt small{ color:var(--muted); font-size:.84rem; line-height:1.4; }
.opt .opt-check{ margin-left:auto; width:24px; height:24px; border-radius:50%; border:1.75px solid var(--line); display:grid; place-items:center; color:#fff; flex:none; transition:background var(--t),border-color var(--t); }
.opt .opt-check .ic{ width:15px; height:15px; opacity:0; }
.opt[aria-pressed="true"]{ border-color:var(--dark); background:var(--surface); box-shadow:inset 0 0 0 1px var(--dark); }
.opt[aria-pressed="true"] .opt-ic{ color:var(--dark); }
.opt[aria-pressed="true"] .opt-check{ background:var(--dark); border-color:var(--dark); }
.opt[aria-pressed="true"] .opt-check .ic{ opacity:1; }
.quiz-nav{
  display:flex; align-items:center; justify-content:space-between; gap:.8rem;
  margin-top:clamp(1rem,2.2vw,1.6rem); padding-top:1rem; border-top:1px solid var(--line);
}
.quiz-nav .link-btn{ font-size:.9rem; font-weight:600; color:var(--muted); display:inline-flex; align-items:center; gap:.4rem; padding:.5rem .6rem; border-radius:var(--r-pill); }
.quiz-nav .link-btn:hover{ color:var(--ink); }
/* Suivant désactivé : ne compte pas seulement sur l'opacité (peu visible sur
   un bouton déjà saturé) - un fond neutre rend l'état bloqué évident au
   premier coup d'oeil, tout en gardant un contraste texte/fond lisible. */
.quiz-nav .btn-primary[disabled]{ background:var(--line-2); color:var(--muted); box-shadow:none; opacity:1; }
/* Précédent désactivé (étape 1) : le bouton reste toujours rendu - il ne
   disparaît plus (fini le hack visibility:hidden sur [hidden]) - pour que
   Suivant reste ancré à droite dès la première question. Même logique que
   Suivant ci-dessus : un fond neutre distinct plutôt qu'une simple baisse
   d'opacité, qui garde le texte lisible (AA) tout en signalant clairement
   l'état bloqué. */
.quiz-nav .link-btn[disabled]{ color:var(--muted); background:var(--line-2); cursor:not-allowed; }
.quiz-nav .link-btn[disabled]:hover{ color:var(--muted); }

/* Coquille stricte "une page" - questionnaire (Étape 3d, >= 768px) : la page
   n'excède jamais 100dvh. La grille d'options ne défile PAS dans les
   viewports normaux (Tâche 14 : elle doit se refluer/wrap, pas scroller) ;
   seule une fenêtre vraiment basse active un ascenseur interne pour garder
   la progression et la navigation précédent/suivant toujours visibles. */
@media (min-width:768px){
  /* Sélecteur "main .section.quiz" (et non ".section.quiz") à dessein : depuis
     le retrait du bandeau héro, .section.quiz est devenu le premier enfant de
     <main>, ce qui le fait aussi correspondre à la règle générale plus haut
     (main > .section:first-child, spécificité 0,2,1) qui impose le grand
     padding-top "après héro". Cette règle doit gagner ce bras de fer de
     spécificité (0,2,1 à égalité, mais déclarée après = elle l'emporte) pour
     que le rythme serré de la coquille d'application s'applique bien ici. */
  main .section.quiz{ flex:1; min-height:0; display:flex; flex-direction:column; padding-block:1rem 1.25rem; }
  .quiz-shell{
    flex:1; min-height:0; display:flex; flex-direction:column;
  }
  .quiz-card{ display:flex; flex-direction:column; flex:1; min-height:0; max-height:100%; }
  .quiz-q{ display:flex; flex-direction:column; flex:1; min-height:0; }
  .opt-grid{ flex:1; min-height:0; align-content:start; padding-right:.3rem; }

  .quiz-results{ flex:1; min-height:0; display:flex; flex-direction:column; }
  .quiz-results .rz-head{ flex:none; }
  .quiz-results .view-toggle{ flex:none; }
  .quiz-results #quiz-venues{ flex:1; min-height:0; overflow-y:auto; overflow-x:hidden; scrollbar-gutter:stable; padding-bottom:.5rem; }
  .quiz-results .venue-map{ flex:1; min-height:0; height:auto; }
}
/* Retrait du héro (retune) : sans le bandeau, 1024x768 (le repli à 820px
   servait surtout ce gabarit) tient désormais nativement. Le seuil est
   abaissé à 700px de haut - il ne couvre plus qu'un petit portable en mode
   paysage ou une fenêtre de bureau réellement basse ; l'ascenseur interne
   devient donc un vrai filet de sécurité plutôt qu'un cas courant. */
@media (min-width:768px) and (max-height:700px){
  /* Sous ce seuil, l'entête de question (titre + indice) peut a elle seule
     remplir tout l'espace flex alloué à .quiz-q et écraser la grille
     d'options à 0px de haut. On fait donc défiler .quiz-q en entier (titre +
     options ensemble) plutôt que la seule grille, pour garantir que les
     options restent toujours atteignables - seules la barre de progression
     et la navigation précédent/suivant restent fixes en haut/bas. */
  .quiz-q{ overflow-y:auto; overflow-x:hidden; scrollbar-gutter:stable; padding-right:.3rem; }
  .opt-grid{ flex:none; }
}

/* Résultats du questionnaire */
.quiz-results .rz-head{ display:flex; flex-wrap:wrap; align-items:end; justify-content:space-between; gap:1rem; margin-bottom:1.6rem; }
.quiz-results .rz-head h3{ font-size:clamp(1.4rem,3vw,1.9rem); }
.quiz-results .rz-head p{ color:var(--muted); margin-top:.35rem; }
.match-tags{ display:flex; flex-wrap:wrap; gap:.4rem; margin-top:.9rem; }
.match-tag{ font-size:.76rem; font-weight:600; color:var(--dark); background:var(--accent-soft); border:1px solid var(--accent-line); padding:.28rem .6rem; border-radius:var(--r-pill); }

/* ---------- Explorateur ---------- */
/* Bloc "avant filtres" compacté (UI batch 3, item 4c) : recherche, select de
   quartier et boutons Inspire-moi/Réinitialiser passent tous à 44px (au lieu
   de 48px, même gabarit que la rangée d'adresse) et le gap resserre de
   .7rem à .5rem - avec le retrait de l'ancien bouton "Près de moi" en pleine
   largeur et de la ligne d'attribution (items 2a/4a), l'ensemble du bloc
   perd environ un tiers de sa hauteur par rapport à avant. */
.search-row{ display:flex; gap:.5rem; flex-wrap:wrap; align-items:stretch; }
.search-box{ position:relative; flex:1; min-width:220px; }
.search-box .ic{ position:absolute; left:.95rem; top:50%; transform:translateY(-50%); width:19px; height:19px; color:var(--muted); }
.search-box input{
  width:100%; height:44px; padding:0 1rem 0 2.7rem; background:var(--surface);
  border:1px solid var(--line); border-radius:var(--r-sm); font-size:.98rem;
}
/* A11Y : le gris-vert #7C948C utilisé auparavant ne mesurait que 3.25:1 sur
   --surface (blanc), sous le seuil AA de 4.5:1 qui s'applique aussi au texte
   d'invite. --muted (déjà le ton "texte secondaire" du site) passe à 5.34:1
   tout en restant visuellement plus léger que le texte saisi. */
.search-box input::placeholder{ color:var(--muted); }
/* Message "au moins 2 caractères" - prend toute la largeur de .search-row pour
   se placer sous le champ plutôt qu'à côté des boutons. [hidden] explicite :
   la règle display de .search-hint l'emporterait sinon sur celle du navigateur. */
.search-hint{ flex:1 1 100%; margin:.1rem 0 0; font-size:.82rem; color:var(--ink-2); }
.search-hint[hidden]{ display:none; }
/* Groupes de filtres repliables (<details>/<summary>) - remplace l'ancienne
   pile de <div> toujours dépliée : l'aside prenait trop de hauteur et
   obligeait à défiler pour voir "Budget"/"Accessibilité"/"Alimentation" même
   à 1080p. Chaque <summary> affiche le nom du groupe + un badge de compte
   (masqué à 0) pour que l'état replié reste informatif ; le triangle natif
   est masqué au profit du petit chevron en ::after ci-dessous, cohérent avec
   .select-wrap::after plus haut. */
.filter-groups{ display:flex; flex-direction:column; }
.fgroup{ border-bottom:1px solid var(--line); padding-block:.55rem; }
.fgroup:first-of-type{ padding-top:0; }
.fgroup:last-of-type{ border-bottom:none; padding-bottom:0; }
.fg-summary{
  display:flex; align-items:center; gap:.5rem; cursor:pointer; list-style:none;
  padding-block:.2rem;
}
.fg-summary::-webkit-details-marker{ display:none; }
.fg-summary .fg-label{ font-size:.72rem; font-weight:700; letter-spacing:.12em; text-transform:uppercase; color:var(--muted); }
.fg-summary::after{
  content:""; margin-left:auto; width:7px; height:7px; flex:none;
  border-right:1.5px solid var(--muted); border-bottom:1.5px solid var(--muted);
  transform:rotate(45deg); transition:transform var(--t);
}
.fgroup[open] > .fg-summary::after{ transform:rotate(-135deg); }
.fg-count{
  display:inline-flex; align-items:center; justify-content:center;
  min-width:18px; height:18px; padding:0 .35rem; border-radius:var(--r-pill);
  background:var(--dark); color:#fff; font-size:.68rem; font-weight:700;
  letter-spacing:normal; text-transform:none;
}
.chips{ display:flex; flex-wrap:wrap; gap:.35rem; margin-top:.6rem; }
.chip{
  display:inline-flex; align-items:center; gap:.35rem; padding:.42rem .7rem;
  border:1px solid var(--line); border-radius:var(--r-pill); background:var(--surface);
  font-size:.82rem; font-weight:500; color:var(--ink-2);
  transition:border-color var(--t),background var(--t),color var(--t);
}
.chip .ic{ width:15px; height:15px; color:var(--muted); }
.chip:hover{ border-color:var(--accent-line); }
.chip[aria-pressed="true"]{ background:var(--dark); border-color:var(--dark); color:#fff; }
.chip[aria-pressed="true"] .ic{ color:var(--accent-bright); }

/* ---------- Rangée de puces sur une seule ligne (2026-08-01) ----------
   Les vingt et quelques catégories occupaient quatre ou cinq rangées et
   poussaient tout le bas de la colonne de filtres hors de l'écran. Elles
   tiennent maintenant sur une ligne qui défile à l'horizontale.

   Ce que le défilement horizontal doit à qui n'utilise pas de souris :
   - les puces retenues repassent en tête (js/filtres.js), donc un filtre actif
     reste visible sans avoir à chercher ;
   - une puce qui prend le focus est ramenée dans la vue, et scroll-padding
     laisse assez de marge pour que son anneau de focus ne soit pas coupé par
     le bord du cadre ;
   - le bouton « Tout afficher » rend la rangée à sa forme dépliée, ce qui rend
     la suite atteignable sans défilement du tout.

   scrollbar-width:thin plutôt que none : la barre est un repère visuel de plus
   que la rangée continue, et elle sert de prise à la souris. */
.chips-ligne{
  flex-wrap:nowrap; overflow-x:auto; overflow-y:hidden;
  scrollbar-width:thin; scroll-padding-inline:4px; padding-block:4px;
  /* overscroll-behavior-x:contain : un balayage arrivé au bout de la rangée ne
     doit pas emporter la page ni déclencher le geste « page précédente ». */
  overscroll-behavior-x:contain;
}
.chips-ligne > .chip{ flex:none; }
.chips-ligne.is-deplie{ flex-wrap:wrap; overflow-x:visible; }
.chips-plus{
  margin-top:.45rem; padding:.2rem .1rem;
  font-size:.8rem; font-weight:600; color:var(--accent-ink);
  text-decoration:underline; text-underline-offset:3px;
}
.chips-plus:hover{ color:var(--ink); }
/* Groupe "Distance" (item 3, UI batch 2) - déplacé en haut de l'aside et
   toujours visible : ce n'est plus un <details>/<summary> comme les autres
   groupes de .filter-groups ci-dessus (voir explorer.html), c'est le point
   de départ le plus souvent utilisé en premier, donc il ne doit jamais
   nécessiter un clic pour être découvert. .aside-distance-head reprend le
   même habillage visuel que .fg-summary (étiquette + badge de compte) sans
   le curseur pointeur ni le chevron, qui n'ont plus de sens sans repli.
   .distance-panel n'ajoute que la disposition propre à ses commandes
   (bouton géolocalisation, recherche d'adresse, puces de rayon, statut,
   bouton d'effacement) - inchangée. */
.aside-distance{ border-bottom:1px solid var(--line); padding-bottom:.8rem; }
.aside-distance-head{ display:flex; align-items:center; gap:.5rem; }
.distance-panel{ display:flex; flex-direction:column; gap:.5rem; margin-top:.5rem; }
.distance-address-row{ display:flex; gap:.5rem; align-items:stretch; }
.distance-address-box{ flex:1; min-width:0; }
.distance-address-box input{
  width:100%; height:44px; padding:0 .9rem 0 2.6rem; background:var(--surface);
  border:1px solid var(--line); border-radius:var(--r-sm); font-size:.9rem;
}
/* Bouton géolocalisation compact (UI batch 3) : bouton-icône carré, dans la
   même rangée que le champ d'adresse plutôt qu'au-dessus en pleine largeur -
   remplace aussi l'ancien bouton de recherche d'adresse séparé (même
   gabarit 44x44). */
.distance-geolocate-btn{ width:44px; height:44px; padding:0; flex:none; justify-content:center; }
.distance-geolocate-btn[aria-busy="true"]{ opacity:.7; cursor:wait; }
.distance-geolocate-btn.is-busy .ic{ animation:sq-spin 1s linear infinite; }
@keyframes sq-spin{ to{ transform:rotate(360deg); } }
/* Note "à vol d'oiseau" : discrète mais jamais masquée quand un point de
   départ est actif - c'est ce qui empêche de lire les kilomètres comme une
   distance de trajet. [hidden] explicite, sinon la règle display l'emporte. */
.distance-hint{ font-size:.78rem; color:var(--muted); line-height:1.45; }
.distance-hint[hidden]{ display:none; }
.distance-status{ font-size:.82rem; color:var(--ink-2); min-height:1.2em; }
.distance-status.is-error{ color:#B3261E; }
#btn-distance-clear{ align-self:flex-start; }

.select-wrap{ position:relative; }
.select-wrap select{
  appearance:none; height:44px; padding:0 2.2rem 0 .9rem; border:1px solid var(--line);
  border-radius:var(--r-sm); background:var(--surface); font-size:.85rem; font-weight:500;
}
.search-row .btn{ height:44px; padding-block:0; }
.select-wrap::after{ content:""; position:absolute; right:.85rem; top:50%; width:8px; height:8px; border-right:1.75px solid var(--muted); border-bottom:1.75px solid var(--muted); transform:translateY(-70%) rotate(45deg); pointer-events:none; }

/* "Tous les quartiers" (item 5, UI batch 2) : toujours pleine largeur de la
   colonne de filtres - l'aside n'a que 320px de large sur bureau, où le
   select flottait à sa largeur de contenu à côté de la recherche plutôt que
   de s'aligner avec elle. Hauteur inchangée (48px, comme le champ de
   recherche). Scopé à .explorer-aside : ce composant ne vit nulle part
   ailleurs sur le site. */
.explorer-aside .select-wrap{ flex:1 1 100%; }
.explorer-aside .select-wrap select{ width:100%; }
/* Groupes de régions du sélecteur de géographie. Le menu déroulant natif ne
   se style pas de façon fiable au-delà de ça d'un navigateur à l'autre : on
   aligne seulement la couleur et la graisse sur les tokens du site, pour que
   l'étiquette de région se distingue de ses quartiers. */
.explorer-aside .select-wrap optgroup{ font-weight:700; color:var(--dark); }
.explorer-aside .select-wrap option{ font-weight:500; color:var(--dark); }

@media (max-width:640px){
  .search-box{ flex:1 1 100%; min-width:0; }
  #btn-inspire{ flex:1; }
  #btn-reset{ flex:none; }
}

/* ---------- Coquille stricte "une page" - explorateur (Étape 3d, remplace
   la version 3c ; seuil relevé à 1024px avec l'ajout du panneau de filtres
   plein écran mobile - voir plus bas) ----------
   En dessous de 1024px : flux normal empilé, page classique qui défile ; les
   filtres ne sont plus dans le flux mais dans un panneau plein écran ouvert
   par #filters-trigger (voir la section "Filtres mobiles" plus bas). À
   1024px et plus : la page n'excède jamais 100dvh - l'en-tête et les filtres
   (aside toujours visible) restent visibles, seule la zone des résultats
   défile en interne - comportement desktop inchangé. */
/* Retrait du héro (retune) : l'explorateur reste le seul endroit du site
   plafonné à 1400px plutôt que --container (1200px) - questionnaire et pages
   de contenu gardent 1200px. Valeur locale à cette page (pas de nouvelle
   variable globale) puisque rien d'autre n'en a besoin. */
.explorer-shell{ display:block; width:100%; max-width:1400px; margin-inline:auto; padding-inline:var(--gutter); }
.explorer-aside{ display:flex; flex-direction:column; gap:1rem; }
/* A11Y (item 4, UI batch 2 - re-report) : l'aside n'a pas de padding-inline
   et applique overflow-x:hidden (nécessaire pour neutraliser le débordement
   sous-pixel fantôme documenté plus bas) - l'anneau de focus par défaut
   (outline 2.5px + outline-offset 2px, donc ~4.5px hors de la boîte de
   bordure) des éléments collés aux bords gauche/droite (recherche, select,
   boutons, puces) se faisait donc tronquer horizontalement par ce même
   conteneur. Le correctif précédent (padding-block:8px plus bas) ne
   couvrait que l'axe vertical. Plutôt que d'ajouter du padding-inline (qui
   aurait décalé toute la colonne de filtres), l'anneau devient "en creux"
   ici : décalage négatif égal à son épaisseur, donc entièrement contenu
   DANS la boîte de bordure de l'élément - jamais rogné, sur aucun axe.
   Vérifié sur #search à 1440px et dans le panneau de filtres mobile. */
.explorer-aside :where(a,button,input,select,[tabindex]):focus-visible{
  outline-offset:-2.5px;
}
@media (min-width:1024px){
  /* Sélecteur "main .section.explorer-section" (et non ".explorer-section")
     à dessein - même bras de fer de spécificité qu'expliqué plus haut pour
     .quiz : depuis le retrait du bandeau héro, cette section est devenue le
     premier enfant de <main> et doit explicitement regagner la priorité sur
     la règle générique "main > .section:first-child" (padding-top ~héro). */
  main .section.explorer-section{ flex:1; min-height:0; display:flex; flex-direction:column; padding-block:1rem 1.25rem; }
  .explorer-shell{
    flex:1; min-height:0;
    /* Colonne élargie de 270px -> 320px (~+18%, demande utilisateur
       2026-07-30) : avec le repliage des groupes de filtres, l'objectif
       combiné est "plus large + plus compact" pour que les puces tiennent
       mieux par rangée et qu'il y ait sensiblement moins à faire défiler. */
    display:grid; grid-template-columns:320px 1fr; gap:1.8rem; align-items:stretch;
  }
  .explorer-aside{
    height:100%; max-height:none;
    overflow-y:auto;
    /* overflow-x:hidden explicite (et non laissé à sa valeur implicite) :
       dès qu'un axe passe à auto/scroll, la spec force l'autre axe "visible"
       à devenir "auto" lui aussi - combiné à scrollbar-gutter:stable, un
       arrondi sous-pixel d'~1px suffisait à faire apparaître une barre
       horizontale fantôme (aucun contenu ne dépasse réellement : vérifié
       élément par élément). Rien ici n'a jamais eu besoin de défiler à
       l'horizontale, donc ceci est le vrai correctif, pas juste un masque. */
    overflow-x:hidden;
    scrollbar-gutter:stable;
    /* Padding-top porté à 8px (au lieu de 1px) : le premier élément focusable
       (la recherche) affichait un anneau de focus rogné par ce conteneur
       défilant - 8px contient largement l'anneau (2.5px d'épaisseur + 2px de
       décalage, avec une marge de sécurité pour l'arrondi sous-pixel) sans
       décaler visiblement la coquille. */
    padding-block:8px .5rem;
    /* Respiration à droite : le contenu de la colonne était collé au couloir
       de barre de défilement (scrollbar-gutter:stable ne réserve que la place
       de la barre, pas d'espace visuel). Seul padding-right ici - ajouter du
       padding-left décalerait toute la colonne par rapport au reste de la
       page, alors que le bord gauche est déjà aligné sur la gouttière. */
    padding-right:.75rem;
  }
  .explorer-results{ height:100%; min-height:0; display:flex; flex-direction:column; }
  .explorer-results .view-toggle{ flex:none; }
  .explorer-results .results-head{ flex:none; }
  /* Filet en haut de la zone de résultats (demande utilisateur 2026-07-31) :
     les fiches défilent sous le compte de résultats sans rien pour marquer où
     la zone défilante commence - elles semblaient disparaître dans la page.
     Sur le conteneur défilant lui-même, donc le trait reste fixe pendant que
     le contenu passe dessous. */
  .explorer-results .venues{
    flex:1; min-height:0; overflow-y:auto; overflow-x:hidden; scrollbar-gutter:stable;
    border-top:1px solid var(--line);
    padding-top:1rem; padding-bottom:.5rem;
  }
  .explorer-results .venue-map{ flex:1; min-height:0; height:auto; }
}

/* ---------- Filtres mobiles (< 1024px) ----------
   Sous 1024px, .explorer-aside n'est plus une colonne toujours visible : elle
   est cachée par défaut et ne s'affiche qu'en panneau plein écran quand on
   ouvre #filters-trigger (js/app.js bascule alors sa classe .is-open ainsi
   que role="dialog" aria-modal="true", gère le focus/piège de tabulation/
   Échap, et verrouille le défilement de fond via .page-scroll.scroll-locked -
   voir wireFiltersSheet()). À 1024px et plus, rien de tout ceci ne s'affiche :
   l'aside redevient la colonne latérale normale gérée par le bloc ci-dessus. */
.filters-trigger{
  display:flex; align-items:center; gap:.6rem; width:100%;
  margin-bottom:1.1rem; padding:.85rem 1.05rem;
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r-sm);
  font-size:.95rem; font-weight:600; color:var(--ink);
  box-shadow:var(--sh-1);
  position:sticky; top:0; z-index:20;
}
.filters-trigger .ic{ width:19px; height:19px; color:var(--accent-strong); }
.filters-badge{
  margin-left:auto; display:inline-flex; align-items:center; justify-content:center;
  min-width:22px; height:22px; padding:0 .4rem; border-radius:var(--r-pill);
  background:var(--dark); color:#fff; font-size:.76rem; font-weight:700;
}
.filters-sheet-head{ display:none; }
@media (max-width:1023px){
  .explorer-aside{ display:none; }
  .explorer-aside.is-open{
    display:flex;
    position:fixed; inset:0; z-index:200;
    background:var(--surface);
    padding:1.1rem var(--gutter) 1.5rem;
    overflow-y:auto;
    overflow-x:hidden;
    scrollbar-gutter:stable;
  }
  .filters-sheet-head{
    display:flex; align-items:center; justify-content:space-between;
    margin-bottom:1.1rem; padding-bottom:.9rem; border-bottom:1px solid var(--line);
  }
  .filters-sheet-head h2{ font-size:1.15rem; }
  .filters-close{
    display:inline-flex; align-items:center; justify-content:center;
    width:40px; height:40px; border-radius:50%; background:var(--bg-2); color:var(--ink); flex:none;
  }
  .filters-close .ic{ width:18px; height:18px; }
  .filters-close:hover{ background:var(--line-2); }
}
@media (min-width:1024px){
  .filters-trigger{ display:none; }
}
/* Empêche .page-scroll de défiler en fond pendant que le panneau de filtres
   plein écran est ouvert (celui-ci a son propre défilement interne). */
.page-scroll.scroll-locked{ overflow:hidden; }

/* ---------- Rangée d'en-tête des résultats ----------
   Bascule Liste/Carte et compte de résultats sur la même ligne : le compte
   occupait une rangée entière pour une demi-phrase, dans une zone où chaque
   pixel vertical est pris sur les fiches. Il passe à droite, aligné sur la
   bascule, et repasse dessous seulement quand la largeur ne suffit plus. */
.results-head{
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between;
  gap:.6rem .8rem; margin-bottom:1.2rem;
}
.results-head .view-toggle{ margin-bottom:0; }
.results-head .count{ font-size:.92rem; color:var(--muted); }
.results-head .count b{ color:var(--ink); font-weight:600; }

/* ---------- Sélecteur de géographie sur les pages de contenu (2026-08-01) ----------
   Les quatre pages qui n'ont pas la colonne de filtres portent ici la commande
   unique de géographie, à l'endroit qu'occupait la ligne de portée. La phrase
   qui répétait le choix a disparu : un <select> refermé affiche déjà son
   option, donc la garder revenait à écrire deux fois la même chose.

   Mêmes ingrédients que le reste du site (taille de la ligne de compte,
   couleur --muted, pilule au rayon --r-pill) : c'est une commande de contexte,
   pas une bannière. Aucune couleur nouvelle.

   Bordure, fond et rayon sont posés sur le <select> lui-même et non sur le
   <label> qui l'enveloppe : la boîte interactive et la pilule visible sont
   ainsi le même rectangle, donc l'anneau de focus natif l'épouse exactement. */
.geographie-page{
  display:flex; flex-wrap:wrap; align-items:center; gap:.45rem .8rem;
  font-size:.85rem; color:var(--muted); margin:0 0 1.2rem;
}
.geo-ligne{ display:inline-flex; align-items:center; gap:.35rem; margin:0; max-width:100%; }
.geo-ligne .ic{ width:14px; height:14px; color:var(--accent-ink); flex:none; }
.geo-choix{ display:inline-flex; align-items:center; gap:.35rem; cursor:pointer; position:relative; min-width:0; }
.geo-prefixe{ color:var(--muted); }
.geo-choix select{
  appearance:none; -webkit-appearance:none; -moz-appearance:none;
  font:inherit; font-size:.82rem; font-weight:600; color:var(--ink-2);
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-pill);
  padding:.3rem 1.75rem .3rem .7rem; margin:0; cursor:pointer;
  /* Un <select> natif se dimensionne sur son option la PLUS LONGUE, pas sur
     celle qui est choisie : avec les 17 régions, « Toute la région et
     limitrophes - Gaspésie-Îles-de-la-Madeleine » imposerait sa largeur en
     permanence. field-sizing:content le fait suivre l'option choisie. Là où la
     propriété n'existe pas encore, la pilule garde la largeur de la plus
     longue entrée : plus lâche, jamais tronquée. La troncature ne reste qu'en
     dernier recours, sur écran très étroit. */
  field-sizing:content;
  max-width:100%; text-overflow:ellipsis; white-space:nowrap; overflow:hidden;
}
/* Chevron maison, même motif que .select-wrap::after ailleurs sur le site -
   le rendu natif est retiré ci-dessus pour que la pilule soit entièrement à
   nous. Ancré à droite du <select> et non du <label>, qui contient aussi son
   étiquette visible. */
.geo-choix::after{
  content:""; position:absolute; right:.75rem; top:50%;
  width:7px; height:7px; pointer-events:none;
  border-right:1.5px solid var(--muted); border-bottom:1.5px solid var(--muted);
  transform:translateY(-65%) rotate(45deg);
}
.geo-choix:hover select{ border-color:var(--accent-line); }
/* La règle générique :where(...,select,...):focus-visible impose
   border-radius:var(--r-xs) à l'anneau : sans ce rappel, l'anneau serait
   presque carré autour d'une pilule ronde. */
.geo-choix select:focus-visible{ border-radius:var(--r-pill); }

/* ---------- Grille de lieux ---------- */
.venues{ display:grid; grid-template-columns:repeat(auto-fill,minmax(min(300px,100%),1fr)); gap:1.15rem; }
.venue{
  /* Marge intérieure en variable : le bandeau « Commandité » doit la
     compenser en marge négative pour aller d'un bord à l'autre de la carte,
     et deux valeurs qui doivent rester identiques ne se recopient pas. */
  --venue-pad:1.35rem;
  /* Largeur de bordure en variable : le rayon intérieur d'une boîte bordée
     vaut rayon extérieur moins largeur de bordure. Le bandeau « Commandité »
     doit donc connaître cette largeur pour que ses coins épousent le bord
     intérieur - sinon la rondeur de la carte réapparaît derrière lui. */
  --venue-bordure:1px;
  position:relative; display:flex; flex-direction:column; gap:.85rem;
  background:var(--surface); border:var(--venue-bordure) solid var(--line); border-radius:var(--r);
  padding:var(--venue-pad);
}
/* Pas d'effet au survol sur les cartes. Décision du propriétaire : le
   soulèvement, l'ombre et le changement de bordure agitaient la grille au
   moindre passage de souris, pour une information que le curseur donne déjà.
   Sur un écran tactile l'effet ne veut rien dire du tout, et il restait collé
   après un appui. */
/* Icône à droite (2026-07-31) : le texte de la carte n'a plus qu'une seule
   marge gauche - titre, quartier et description alignés au même bord. Le bloc
   de texte prend min-width:0 pour que les noms longs se coupent proprement au
   lieu de pousser l'icône hors de la carte. */
.venue-top{ display:flex; align-items:flex-start; justify-content:space-between; gap:.8rem; }
.venue .v-head-text{ min-width:0; }
.venue .v-ic{ width:40px; height:40px; display:grid; place-items:center; color:var(--accent-strong); flex:none; }
.venue .v-ic .ic{ width:21px; height:21px; stroke-width:2.1; }
.venue h3{ font-size:1.09rem; letter-spacing:-.02em; }
.venue .v-meta{ display:flex; flex-wrap:wrap; align-items:center; gap:.3rem .7rem; margin-top:.25rem; font-size:.82rem; color:var(--muted); }
.venue .v-meta span{ display:inline-flex; align-items:center; gap:.32rem; }
.venue .v-meta .ic{ width:14px; height:14px; }
/* Provenance d'une région limitrophe : « Lévis - Chaudière-Appalaches ».
   Même couleur que le reste de .v-meta - c'est une précision, pas une
   alerte. Voir venueCard() dans js/rendu.js. */
.venue .v-region{ color:var(--muted); }
.venue .v-quartier--avec-region{ flex-basis:100%; }
.venue .v-price{ font-weight:600; color:var(--accent-ink); letter-spacing:.03em; }
.venue .v-desc{ font-size:.9rem; color:var(--ink-2); line-height:1.55; }
.venue .v-foot{ margin-top:auto; display:flex; flex-direction:column; gap:.75rem; }
.tag-row{ display:flex; flex-wrap:wrap; gap:.35rem; }
.tag{ font-size:.74rem; font-weight:500; color:var(--ink-2); background:var(--bg-2); border:1px solid var(--line-2); padding:.24rem .55rem; border-radius:var(--r-xs); }
.tag.soft{ color:var(--dark); background:var(--surface); border-color:var(--line); }
/* Pilules de réservation : trois états, trois traitements. Le contraste des
   trois est calculé sur leur propre fond, pas sur --surface (mesures : ambre
   #6B4A00 sur #FDF3D9 = 7,3:1 ; vert --accent-ink sur --accent-soft = 5,1:1 ;
   --ink-2 sur --bg-2 = 8,9:1). La couleur n'est jamais le seul signal : le
   libellé dit toujours l'état en toutes lettres. */
/* ---------- Carte commanditée ----------
   Une commandite doit se voir sans discussion possible : cadre multicolore
   tout autour de la carte + bandeau « Commandité » en travers du haut. C'est
   une divulgation, pas une décoration - le cadre attire l'œil, le bandeau dit
   en toutes lettres de quoi il s'agit. La couleur n'est jamais le seul signal.

   ANIMATION - coût et repli
   L'angle du dégradé conique est une propriété personnalisée enregistrée
   (@property, donc interpolable) lue par un seul background-image, sur un
   pseudo-élément masqué qui ne laisse voir que le liseré de 2px. Conséquences
   voulues : aucune propriété de mise en page n'est animée (pas de reflow), le
   contenu de la carte n'est jamais repeint, et l'invalidation se limite au
   pseudo-élément. Le liseré est posé en inset:0 par-dessus la bordure de 1px
   déjà présente : la boîte de la carte ne change pas d'un pixel, donc aucun
   décalage de mise en page quand une carte devient commanditée.

   Le site ne tient pas compte de prefers-reduced-motion (voir la note en tête
   du fichier), donc cette rotation tourne pour tout le monde. Anciennement :
   animations ; on fige explicitement l'angle ici pour que le cadre reste
   multicolore et lisible au lieu de dépendre d'un effet de bord. Un dégradé
   qui tourne en continu est exactement le genre de mouvement qui déclenche
   des malaises, le cadre lui n'a aucune raison de disparaître. */
@property --commandite-angle{ syntax:"<angle>"; inherits:false; initial-value:0deg; }

/* Teintes : les six jetons de la palette v3 déjà utilisés ailleurs (cinq
   contextes de sortie + accent). Aucune couleur nouvelle, et le cadre reste
   de la même famille que le reste du site. La dernière butée reprend la
   première pour que la boucle n'ait pas de couture visible.

   Les six teintes sont les variantes vives (-bright). Une version antérieure
   utilisait les variantes foncées pour tenir 3:1 sur le fond de page, et
   c'était une exigence mal appliquée : le seuil de la WCAG 1.4.11 vise ce qui
   PORTE de l'information ou ce qui est interactif. Ici l'information est
   portée par le bandeau écrit « COMMANDITÉ », sur fond plein à 10,6:1. Le
   cadre est décoratif et redondant, donc il n'est pas soumis à ce seuil - et
   un cadre terne racontait mal ce qu'il devait annoncer.

   Ce qui reste vrai : si un jour le cadre devenait le SEUL signal de
   commandite, sans bandeau, ce raisonnement tomberait et les teintes devraient
   repasser aux variantes foncées. */
@keyframes commandite-rotation{ to{ --commandite-angle:360deg; } }
/* La bordure de base passe en transparent : le liseré coloré la remplace
   exactement au même endroit, sans doubler le trait. */
.venue.is-sponsor{
  --venue-bordure:4px;
  border-color:transparent;
  /* Deux couches de fond plutôt qu'un pseudo-élément masqué : la couleur de
     carte est peinte jusqu'au padding-box, le dégradé jusqu'au border-box, et
     seule la bande de bordure laisse voir le second. Le navigateur calcule
     lui-même les deux rayons concentriques, ce que mask-composite ne pouvait
     pas faire - inner et outer y partageaient un seul rayon, d'où les coins
     qui laissaient passer la rondeur de la carte.
     box-sizing:border-box est global, donc passer de 1px a 4px ne change pas
     la taille exterieure de la carte : aucun decalage dans la grille. */
  background:
    linear-gradient(var(--surface), var(--surface)) padding-box,
    conic-gradient(from var(--commandite-angle),
      var(--c-solo-bright) 0deg, var(--c-famille-bright) 60deg, var(--c-couple-bright) 120deg,
      var(--c-premier-rendez-vous-bright) 180deg, var(--c-entre-amis-bright) 240deg,
      var(--accent-bright) 300deg, var(--c-solo-bright) 360deg) border-box;
  animation:commandite-rotation 12s linear infinite;
}

/* Halo. Une copie floutée du même dégradé, posée derrière la carte et animée
   par le même angle, donc les deux tournent ensemble sans se désynchroniser.
   z-index:-1 la fait peindre derrière le fond de la carte : .venue ne crée pas
   de contexte d'empilement (position:relative seul n'en crée pas), donc la
   couche passe sous le fond opaque de la carte et ne déborde qu'autour.
   inset négatif plutôt qu'une box-shadow : une ombre ne prend qu'une couleur,
   alors qu'ici le halo doit rester multicolore.
   Le flou ne s'applique qu'aux lieux commandités, jamais aux 159 cartes. */
.venue.is-sponsor::after{
  content:""; position:absolute; inset:-5px; z-index:-1; pointer-events:none;
  border-radius:calc(var(--r) + 5px);
  background:conic-gradient(from var(--commandite-angle),
    var(--c-solo-bright) 0deg, var(--c-famille-bright) 60deg, var(--c-couple-bright) 120deg,
    var(--c-premier-rendez-vous-bright) 180deg, var(--c-entre-amis-bright) 240deg,
    var(--accent-bright) 300deg, var(--c-solo-bright) 360deg);
  filter:blur(9px); opacity:.55;
  animation:commandite-rotation 12s linear infinite;
}

/* Bandeau du haut. Fond plein (--dark) et non le dégradé : sur un dégradé qui
   tourne, le contraste du texte changerait à chaque image et rien ne garantit
   4,5:1 à tous les angles. Ici il est constant et mesuré - --on-dark #EFF7F2
   sur --dark #123A63 = 10,6:1. Le mot est écrit en minuscules dans le DOM et
   mis en capitales par la CSS : certains lecteurs d'écran épellent un mot
   écrit tout en majuscules. */
.commandite-bandeau{
  display:flex; align-items:center; justify-content:center; gap:.4rem;
  margin:calc(var(--venue-pad) * -1) calc(var(--venue-pad) * -1) 0;
  padding:.42rem .8rem;
  background:var(--dark); color:var(--on-dark);
  font-size:.7rem; font-weight:700; letter-spacing:.14em; text-transform:uppercase;
  border-radius:calc(var(--r) - var(--venue-bordure)) calc(var(--r) - var(--venue-bordure)) 0 0;
}
.commandite-bandeau .ic{ width:12px; height:12px; }


/* ---------- Sélection de texte ----------
   Cliquer deux fois sur un bouton, ou glisser un peu la souris en cliquant,
   surlignait son libellé en bleu. Sur une interface faite de puces de filtre
   et d'onglets, ça arrive sans arrêt et ça n'a aucun sens : personne ne copie
   le mot « Réinitialiser ».

   La règle est donc posée sur les COMMANDES, jamais globalement. Le contenu
   reste sélectionnable, et c'est délibéré : on copie un nom de lieu pour le
   chercher ailleurs, une adresse pour un itinéraire, une description pour
   l'envoyer à quelqu'un. Un site où l'on ne peut rien copier est pire que le
   problème qu'on corrige. */
.btn, .chip, .nav-links a, .brand, .fg-summary, .opt, .check, .geo-choix,
/* Bouton de fermeture : coin haut-droit, discret au repos, franc au survol et
   au focus. La carte prend position:relative pour l'ancrer. */
.offre-place{ position:relative; }
.offre-place-fermer{
  position:absolute; top:.5rem; right:.5rem;
  display:inline-flex; align-items:center; justify-content:center;
  width:30px; height:30px; padding:0;
  border:1px solid transparent; border-radius:var(--r-pill);
  background:transparent; color:var(--muted); cursor:pointer;
}
.offre-place-fermer:hover{ background:var(--bg-2); color:var(--ink); border-color:var(--line); }
.offre-place-fermer .ic{ width:15px; height:15px; }

.view-tabs, .commandite-bandeau, .offre-place-lien, .pill, .tag,
.quiz-nav, .radius-chip, .filters-head, .fg-count, .step-lbl{
  -webkit-user-select:none; user-select:none;
}
/* Les champs de saisie gardent la sélection : on y corrige ce qu'on a tapé. */
input, textarea, select{ -webkit-user-select:auto; user-select:auto; }

/* ---------- Carte d'offre (place commanditée libre) ----------
   Elle ne porte JAMAIS le mot « Commandité » : ce mot dit que quelqu'un a
   payé, et le coller sur une place invendue serait une fausse affirmation qui
   dévaluerait l'étiquette partout ailleurs. Elle ne porte pas non plus le
   cadre multicolore, réservé aux vraies commandites.

   Traitement volontairement différent d'une carte de lieu : fond teinté au
   lieu de la surface blanche, trait discontinu, pas d'icône de catégorie, pas
   de puces. On doit voir en un coup d'œil que ce n'est pas un lieu.
   Contrastes mesurés sur --bg-2 #EFF7F0 : --accent-ink #0B6E52 = 5,7:1,
   --ink-2 #2F4A44 = 8,8:1. Le trait discontinu, lui, est décoratif : ce qui
   distingue la carte, c'est ce qui est écrit dessus. */
.offre-place{
  display:flex; flex-direction:column; gap:.5rem; justify-content:center;
  background:var(--bg-2); border:1.5px dashed var(--accent-line);
  border-radius:var(--r); padding:1.35rem;
}
.offre-place-titre{
  display:inline-flex; align-items:center; gap:.4rem;
  font-size:.72rem; font-weight:700; letter-spacing:.12em; text-transform:uppercase;
  color:var(--accent-ink);
}
.offre-place-titre .ic{ width:14px; height:14px; }
.offre-place h3{ font-size:1.05rem; letter-spacing:-.02em; }
.offre-place p{ font-size:.89rem; color:var(--ink-2); line-height:1.55; }
.offre-place .offre-place-lien{
  align-self:flex-start; display:inline-flex; align-items:center; gap:.35rem;
  margin-top:.2rem; font-size:.85rem; font-weight:600; color:var(--accent-ink);
}
.offre-place .offre-place-lien .ic{ width:14px; height:14px; }
.offre-place .offre-place-lien:hover{ text-decoration:underline; text-underline-offset:2px; }
.tag-resa{ font-weight:600; }
.tag-resa--requise{ color:#6B4A00; background:#FDF3D9; border-color:#F0DFB0; }
.tag-resa--non-requise{ color:var(--accent-ink); background:var(--accent-soft); border-color:var(--accent-line); }
.tag-resa--inconnu{ color:var(--ink-2); background:var(--bg-2); border-color:var(--line-2); font-weight:500; }
/* Correspondance de filtre (rendu uniquement, voir venueCard() dans app.js -
   aucune logique de filtrage touchée) : la teinte de catégorie/ambiance
   active met en évidence les puces déjà affichées sur chaque carte, en
   réutilisant les jetons de couleur --c-<id> déjà calibrés >= 3:1 (non-texte)
   sur fond clair ailleurs dans ce fichier (chips, cartes de catégorie,
   options du questionnaire) - entre-amis utilise volontairement la variante
   -ink plus foncée pour la même raison de contraste que ces autres usages. */
.tag.tag-match{ border-color:var(--accent-strong); background:var(--accent-soft); color:var(--accent-ink); }
.badge-row{ display:flex; flex-wrap:wrap; gap:.35rem; align-items:center; }
.badge{ display:inline-flex; align-items:center; gap:.33rem; font-size:.73rem; font-weight:600; color:var(--dark); }
.badge .ic{ width:13px; height:13px; color:var(--accent); }
.badge.badge-match{
  padding:.2rem .55rem .2rem .35rem; border-radius:var(--r-pill);
  border:1.5px solid var(--line); background:var(--bg-2);
}
.badge.badge-match[data-sortie="solo"]{ border-color:var(--c-solo-ink); }
.badge.badge-match[data-sortie="entre-amis"]{ border-color:var(--c-entre-amis-ink); }
.badge.badge-match[data-sortie="couple"]{ border-color:var(--c-couple-ink); }
.badge.badge-match[data-sortie="premier-rendez-vous"]{ border-color:var(--c-premier-rendez-vous-ink); }
.badge.badge-match[data-sortie="famille"]{ border-color:var(--c-famille-ink); }
.v-link{ display:inline-flex; align-items:center; gap:.35rem; font-size:.83rem; font-weight:600; color:var(--accent-ink); flex:none; white-space:nowrap; }
.v-link .ic{ width:14px; height:14px; }
.v-link:hover{ text-decoration:underline; text-underline-offset:2px; }
/* Rangée de liens en une seule ligne (demande utilisateur 2026-07-30) :
   "Visiter le site" est maintenant seul ici (UI batch 3 a déplacé "Source"
   dans la description et "Signaler" en bas de carte, voir plus bas) donc son
   libellé complet est revenu - une seule carte, plus besoin de l'abréger. */
/* flex-wrap:wrap depuis l'ajout du lien Google Maps (2026-07-31) : deux liens
   ne tiennent pas toujours sur une ligne dans une colonne de grille étroite,
   et les tronquer cacherait une action. */
.v-links{ display:flex; align-items:center; gap:.5rem .9rem; flex-wrap:wrap; padding-top:.15rem; min-width:0; }
/* "Visiter le site" et "Signaler" sur la même ligne (demande utilisateur
   2026-07-31) : ils occupaient deux rangées de .v-foot, ce qui donnait
   beaucoup de vide en bas de carte pour deux liens courts. min-width:0 sur les
   deux enfants pour que la troncature de .v-links continue de fonctionner
   quand le nom du lien est long. */
.v-actions{ display:flex; align-items:center; justify-content:space-between; gap:.9rem; }
/* "Source" en ligne, à la fin de la description (UI batch 3) : discret et
   rattaché au texte plutôt qu'affiché comme une action à côté de "Visiter le
   site" - lit comme une note de bas de phrase, pas comme un bouton. */
.v-source-inline{ font-size:.78rem; font-weight:500; color:var(--muted); white-space:nowrap; }
.v-source-inline:hover{ text-decoration:underline; text-underline-offset:2px; }
/* "Signaler" reste discret et poussé à droite de la rangée d'actions.
   margin-left:auto (plutôt que de compter sur space-between) : sans lien de
   site, .v-report-row est seul dans .v-actions et doit quand même rester
   collé à droite. */
.v-report-row{ display:flex; justify-content:flex-end; margin-left:auto; flex:none; }
.v-report{ font-size:.78rem; font-weight:500; color:var(--muted); }
.v-report:hover{ text-decoration:underline; text-underline-offset:2px; }
.dot-sep{ width:4px; height:4px; border-radius:50%; background:var(--line); flex:none; }
/* Surlignage des correspondances de recherche (voir highlightSearch() dans
   js/app.js). A11Y : le fond seul ne suffit pas comme signal (daltonisme,
   contraste réduit), d'où le poids de police plus fort en renfort. --ink sur
   --accent-soft mesure ~12.6:1, bien au-dessus du niveau AA, et le <mark>
   reste sémantique donc annoncé par les lecteurs d'écran qui le supportent. */
mark.search-hit{
  background:var(--accent-soft); color:var(--ink); font-weight:600;
  border-radius:3px; padding:0 .1em;
}

.empty{ text-align:center; padding:3rem 1rem; color:var(--muted); border:1px dashed var(--line); border-radius:var(--r); background:var(--bg-2); }
.empty b{ color:var(--ink); display:block; font-family:"Inter Tight","Inter Tight Repli",sans-serif; font-size:1.1rem; margin-bottom:.3rem; }
.empty .empty-suggest{ margin-top:.6rem; font-size:.9rem; }
.empty .empty-suggest a{ color:var(--accent-ink); font-weight:600; }
.empty .empty-suggest a:hover{ text-decoration:underline; text-underline-offset:2px; }

/* ---------- Bascule Liste/Carte (Tâche 17) ----------
   Onglets ARIA (role="tablist"/"tab") plutôt que des puces - un seul des
   deux panneaux (#venues ou .venue-map) est visible à la fois, la bascule
   ne change jamais la logique de filtrage elle-même (voir js/app.js,
   createResultsMapController()). Le contraste texte non sélectionné
   (--muted sur --bg-2) a été vérifié >= 4.5:1. */
.view-toggle{ display:inline-flex; gap:.25rem; padding:.25rem; margin-bottom:1.2rem; background:var(--bg-2); border:1px solid var(--line); border-radius:var(--r-pill); align-self:flex-start; }
.view-tab{ padding:.45rem 1.15rem; border-radius:var(--r-pill); font-size:.88rem; font-weight:600; color:var(--muted); transition:background var(--t),color var(--t); }
.view-tab:hover{ color:var(--ink); }
.view-tab[aria-selected="true"]{ background:var(--surface); color:var(--ink); box-shadow:var(--sh-1); }

/* Carte des résultats - conteneur Leaflet. Une hauteur fixe raisonnable sert
   de repli pour les gabarits qui ne défilent pas en interne (< 1024px sur
   l'explorateur, questionnaire sous 768px) ; les coquilles "une page" plus
   larges reprennent flex:1 (voir les blocs @media plus haut) pour occuper
   tout l'espace disponible dans la même région de défilement que la liste. */
.venue-map{ height:520px; border:1px solid var(--line); border-radius:var(--r); overflow:hidden; background:var(--bg-2); }
.venue-map .leaflet-container{ width:100%; height:100%; font-family:inherit; background:var(--bg-2); }
@media (max-width:640px){ .venue-map{ height:min(70vh,420px); } }

/* Marqueurs divIcon colorés par teinte principale de sortie (voir
   sortieHue() dans js/app.js, qui lit directement les jetons --c-<id>
   ci-dessus pour ne jamais dupliquer les couleurs). */
.venue-marker-dot{
  display:block; width:16px; height:16px; border-radius:50%;
  border:2px solid #fff; box-shadow:0 1px 3px rgba(21,48,43,.45);
}
.venue-marker-origin-dot{
  width:18px; height:18px; background:var(--accent-strong);
  box-shadow:0 0 0 4px rgba(12,122,88,.25), 0 1px 3px rgba(21,48,43,.45);
}
.venue-popup h4{ font-size:.95rem; font-family:"Inter Tight","Inter Tight Repli",sans-serif; margin-bottom:.2rem; }
.venue-popup-quartier{ font-size:.82rem; color:var(--muted); margin-bottom:.15rem; }
.venue-popup-prix{ color:var(--accent-ink); font-weight:600; letter-spacing:.03em; }
.venue-popup-approx{ font-size:.76rem; color:var(--muted); font-style:italic; margin-bottom:.4rem; }
/* Description courte (tronquée par shortenDescription() dans js/app.js) :
   l'infobulle n'a que ~230px de large, la largeur maximale par défaut de
   Leaflet, donc le texte doit rester serré pour ne pas devenir une colonne. */
.venue-popup-desc{ font-size:.82rem; line-height:1.45; color:var(--ink-2); margin:.35rem 0 .5rem; }
.venue-popup-links{ font-size:.82rem; }
.venue-popup-links a{ color:var(--accent-ink); font-weight:600; }
.venue-popup-links a:hover{ text-decoration:underline; text-underline-offset:2px; }

/* ---------- Bascule de style de carte (item 7, 2026-07-30) ----------
   Contrôle Leaflet personnalisé (voir addTileStyleControl() dans js/app.js),
   posé directement sur la carte - même habillage "pilule à deux états" que
   .view-toggle/.view-tab plus haut (bascule Liste/Carte) pour rester
   cohérent visuellement. Partagé par l'explorateur et le questionnaire, qui
   utilisent tous deux createResultsMapController(). */
.map-style-toggle{
  display:flex; gap:.2rem; margin:10px; padding:.2rem;
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-pill); box-shadow:var(--sh-1);
}
.map-style-btn{
  padding:.4rem .8rem; border-radius:var(--r-pill);
  font-size:.78rem; font-weight:600; color:var(--muted);
  transition:background var(--t),color var(--t);
}
.map-style-btn:hover{ color:var(--ink); }
.map-style-btn[aria-pressed="true"]{ background:var(--bg-2); color:var(--ink); }

/* Le style "Simple" ne passe plus par un filtre CSS (grayscale/brightness sur
   .leaflet-tile-pane, retiré le 2026-07-31) : délaver les tuiles OSM laissait
   tout le détail en place. C'est maintenant un vrai fond de carte minimaliste
   (CARTO Positron) chargé à la place - voir TILE_SOURCES dans js/app.js. */

/* ---------- Attribution de la carte (item 1, UI batch 2) ----------
   OSM impose de garder l'attribution visible et accessible, mais rien
   n'oblige à occuper en permanence un coin de la carte - le contrôle Leaflet
   natif (attributionControl) est désactivé (voir js/app.js, ensureMap()) au
   profit de celui-ci, replié par défaut : un petit bouton rond "©" qui
   déplie le texte complet au clic (persiste jusqu'au prochain clic, via
   .is-open) ou dès que le focus clavier entre dans le contrôle
   (:focus-within, sans JS) - donc toujours atteignable au clavier sans
   jamais avoir à cliquer. Fond opaque (pas de transparence sur les tuiles) :
   le contraste du glyphe "©" doit rester lisible quelle que soit la tuile
   affichée dessous, pas seulement sur une tuile claire - blanc sur --dark
   mesure 11.6:1 (déjà vérifié ailleurs sur le site), largement au-dessus du
   seuil AA. */
.map-attrib{ position:relative; }
.map-attrib-btn{
  display:flex; align-items:center; justify-content:center;
  width:26px; height:26px; border-radius:50%;
  background:var(--dark); color:#fff; font-size:.8rem; font-weight:700;
  line-height:1; box-shadow:var(--sh-1);
}
.map-attrib-btn:hover{ background:var(--dark-2); }
.map-attrib :focus-visible{ outline-color:var(--accent-bright); }
.map-attrib-text{
  display:none;
  position:absolute; right:0; bottom:calc(100% + .4rem);
  background:var(--surface); color:var(--ink-2); font-size:.72rem; line-height:1.4;
  padding:.4rem .65rem; border-radius:var(--r-sm); border:1px solid var(--line);
  white-space:nowrap; box-shadow:var(--sh-1);
}
.map-attrib-text a{ color:var(--accent-ink); font-weight:600; }
.map-attrib-text a:hover{ text-decoration:underline; text-underline-offset:2px; }
.map-attrib.is-open .map-attrib-text,
.map-attrib:focus-within .map-attrib-text{ display:block; }

/* ---------- État vide - événements ---------- */
.event-empty{ text-align:center; padding:clamp(2.4rem,6vw,3.6rem) 1.5rem; background:var(--surface); border:1px solid var(--line); border-radius:var(--r); }
.event-empty h2{ font-size:clamp(1.25rem,2.6vw,1.5rem); }
.event-empty p{ margin:.7rem auto 1.5rem; max-width:38rem; color:var(--muted); line-height:1.55; }

/* Carte « Inspire-moi » en vedette */
.spotlight{ border:1px solid var(--accent-line); background:linear-gradient(180deg,var(--surface),var(--bg-2)); box-shadow:var(--sh-2); }
.spotlight::before{ background:var(--accent); }
.spotlight .sl-kicker{ font-size:.72rem; font-weight:700; letter-spacing:.14em; text-transform:uppercase; color:var(--accent-ink); display:inline-flex; align-items:center; gap:.45rem; }

/* ---------- À propos ---------- */
/* background-color (pas le raccourci background) : évite d'écraser
   background-image/-size/-position posés par .section-wash quand les deux
   classes cohabitent sur le même élément (voir speed-dating.html). */
.about{ background-color:var(--bg-2); border-top:1px solid var(--line); }
.about-grid{ display:grid; grid-template-columns:1.1fr .9fr; gap:clamp(1.6rem,5vw,4rem); align-items:start; }
@media (max-width:820px){ .about-grid{ grid-template-columns:1fr; } }
.about h1,.about h2{ font-size:clamp(1.7rem,3.6vw,2.4rem); }
.about .lead{ margin-top:1rem; font-size:1.08rem; color:var(--ink-2); line-height:1.65; }
.about .lead + .lead{ margin-top:1rem; color:var(--muted); font-size:1rem; }
.steps{ display:flex; flex-direction:column; gap:1.1rem; }
.step{ display:flex; gap:1rem; }
.step .n{ width:34px; height:34px; flex:none; border-radius:50%; display:grid; place-items:center; background:var(--dark); color:var(--accent-bright); font-family:"Inter Tight","Inter Tight Repli",sans-serif; font-weight:700; font-size:.95rem; }
/* M3 fix (2026-07-30) : ces titres d'étape étaient des <h4> directement sous
   le <h1> de la page (aucun <h2>/<h3> entre les deux sur à propos et
   speed-dating) - passés à <h2> en HTML (siblings du <h2> du bandeau promo
   plus bas sur la même page), sélecteur renommé en conséquence ; taille/
   police inchangées. */
.step h2{ font-size:1.02rem; font-family:"Inter Tight","Inter Tight Repli",sans-serif; }
.step p{ font-size:.92rem; color:var(--muted); margin-top:.2rem; line-height:1.5; }
.propose{ margin-top:1.6rem; padding:1.35rem; background:var(--surface); border:1px solid var(--line); border-radius:var(--r); }
.propose h2{ font-family:"Inter Tight","Inter Tight Repli",sans-serif; font-size:1.05rem; }
.propose p{ font-size:.9rem; color:var(--muted); margin:.4rem 0 1rem; }
.propose.has-photo{
  position:relative; overflow:hidden; border-color:transparent; color:var(--on-dark);
  background:
    linear-gradient(rgba(18,58,99,.88), rgba(18,58,99,.88)),
    url("../images/chateau-frontenac.jpg") center/cover no-repeat var(--dark);
}
.propose.has-photo h2{ color:#fff; }
.propose.has-photo p{ color:var(--on-dark-muted); }

/* ---------- Page « Commanditer » ----------
   Page commerciale, mais elle garde la sobriété du reste du site : pas de
   dégradés criards ni de gros prix barrés. Ce qu'on vend ici, c'est la
   crédibilité du guide - une page qui crie la contredirait. */
.offre-liste{ list-style:none; margin:0 0 clamp(2.5rem,5vw,4rem); padding:0; display:grid; gap:1.5rem; }
@media (min-width:760px){ .offre-liste{ grid-template-columns:1fr 1fr; gap:1.8rem 2.5rem; } }
.offre-item h3{ font-size:1.08rem; margin-bottom:.4rem; }
.offre-item p{ color:var(--ink-2); line-height:1.6; font-size:.95rem; max-width:52ch; }

.offre-tarifs{ padding-top:clamp(2rem,4vw,3rem); border-top:1px solid var(--line); }
.offre-tarifs h2{ font-size:1.5rem; }
.offre-note{
  margin:.5rem 0 1.5rem; font-size:.84rem; color:var(--warn-ink);
  background:var(--warn-soft); border:1px solid #F0DFB0;
  border-radius:var(--r-sm); padding:.6rem .8rem; max-width:60ch;
}
.offre-grille{ display:grid; gap:1rem; grid-template-columns:repeat(auto-fit,minmax(230px,1fr)); }
.offre-carte{
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r);
  padding:1.4rem; display:flex; flex-direction:column; gap:.4rem;
}
.offre-carte--vedette{ border-color:var(--accent-line); background:var(--accent-soft); }
.offre-duree{ font-size:.78rem; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:var(--muted); }
.offre-prix{ font-family:"Inter Tight","Inter Tight Repli",sans-serif; font-size:1.9rem; font-weight:500; }
.offre-carte p{ font-size:.88rem; color:var(--ink-2); line-height:1.5; }

.offre-contact, .offre-honnete{ padding-top:clamp(2rem,4vw,3rem); margin-top:clamp(2rem,4vw,3rem); border-top:1px solid var(--line); }
.offre-contact h2, .offre-honnete h2{ font-size:1.35rem; margin-bottom:.6rem; }
.offre-contact p, .offre-honnete p{ color:var(--ink-2); line-height:1.65; max-width:58ch; margin-bottom:1.2rem; }

/* =========================================================================
   SOUMISSIONS DU PUBLIC
   -------------------------------------------------------------------------
   Trois blocs qui partagent le même vocabulaire visuel : « Ce qui s'organise »
   sur l'accueil, la page Participer, et le formulaire de signalement déplié
   sous une fiche de lieu. Aucune couleur nouvelle - tout vient des jetons de
   la palette v3 déjà définis en tête de fichier.
   ========================================================================= */

/* ---------- Ce qui s'organise (accueil) ---------- */
.organise-sous-titre{
  font-family:"Inter Tight","Inter Tight Repli",sans-serif;
  font-size:.78rem; font-weight:700; letter-spacing:.12em; text-transform:uppercase;
  color:var(--muted); margin-bottom:.9rem;
}
#organise-bloc-groupes{ margin-top:clamp(1.8rem,3.5vw,2.6rem); }
.organise-liste{
  display:grid; gap:1rem;
  grid-template-columns:repeat(auto-fill,minmax(min(100%,17rem),1fr));
}
.organise-carte{
  display:flex; flex-direction:column; gap:.4rem;
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r);
  padding:1.15rem; box-shadow:var(--sh-1);
  transition:border-color var(--t),box-shadow var(--t);
}
.organise-carte:hover{ border-color:var(--accent-line); box-shadow:var(--sh-2); }
.organise-cat{
  align-self:flex-start; font-size:.68rem; font-weight:700;
  letter-spacing:.09em; text-transform:uppercase; color:var(--accent-ink);
  background:var(--accent-soft); border:1px solid var(--accent-line);
  border-radius:var(--r-pill); padding:.14rem .55rem;
}
.organise-carte h3{ font-size:1.05rem; }
.organise-quand{ font-size:.86rem; font-weight:600; color:var(--ink-2); }
.organise-lieu{ font-size:.84rem; color:var(--muted); }
/* Trois lignes puis coupure : les descriptions vont de deux mots à quinze
   lignes selon qui écrit, et une grille de cartes de hauteurs très
   différentes se lit mal. La carte complète reste accessible par le lien. */
.organise-desc{
  font-size:.9rem; color:var(--ink-2); line-height:1.55;
  display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:3; overflow:hidden;
}
.organise-pied{
  display:flex; align-items:baseline; justify-content:space-between;
  gap:.5rem .9rem; flex-wrap:wrap; margin-top:auto; padding-top:.5rem;
}
.organise-contact{ font-size:.78rem; color:var(--muted); }
.organise-lien{ font-size:.82rem; font-weight:600; color:var(--accent-ink); }
.organise-lien:hover{ text-decoration:underline; text-underline-offset:2px; }
.organise-appel{ display:flex; flex-wrap:wrap; gap:.8rem; margin-top:clamp(1.6rem,3vw,2.2rem); }
@media (max-width:560px){
  .organise-appel{ flex-direction:column; align-items:stretch; }
  .organise-appel .btn{ width:100%; }
}

/* ---------- Page Participer ---------- */
.participer{ max-width:44rem; }
.participer-avis{
  font-size:.9rem; color:var(--warn-ink,#8F5E00); line-height:1.55;
  background:#FDF0DA; border:1px solid #EFD9A8; border-radius:var(--r-sm);
  padding:.85rem 1rem; margin-bottom:1.8rem;
}
.participer-avis a{ color:inherit; font-weight:600; text-decoration:underline; text-underline-offset:2px; }

.participer-choix{ border:0; padding:0; margin:0 0 1.8rem; display:grid; gap:.7rem; }
.participer-choix legend{
  font-family:"Inter Tight","Inter Tight Repli",sans-serif;
  font-size:1.15rem; font-weight:500; letter-spacing:-.01em;
  padding:0; margin-bottom:.4rem;
}
/* Toute la tuile est cliquable, et le bouton radio reste un vrai bouton radio :
   les flèches naviguent dans le groupe et l'anneau de focus reste visible. */
.participer-option{
  display:flex; align-items:flex-start; gap:.75rem; cursor:pointer;
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r);
  padding:.9rem 1rem; transition:border-color var(--t),background var(--t);
}
.participer-option:hover{ border-color:var(--accent-line); background:var(--bg-2); }
.participer-option input{ width:18px; height:18px; margin:.15rem 0 0; accent-color:var(--accent-strong); flex:none; }
.participer-option:has(input:checked){ border-color:var(--accent-strong); background:var(--accent-soft); }
.participer-option:has(input:focus-visible){ outline:2.5px solid var(--focus); outline-offset:2px; }
/* font-weight explicite : .participer-option EST un <label>, donc la règle
   .participer-form label plus bas lui donne 600, qui se transmettrait à ce
   texte d'explication et le ferait lire comme un titre. */
.participer-option span{ display:block; font-size:.86rem; font-weight:400; color:var(--muted); line-height:1.5; }
.participer-option b{ display:block; font-size:.98rem; font-weight:600; color:var(--ink); margin-bottom:.15rem; }

.participer-form .field{ display:flex; flex-direction:column; gap:.35rem; margin-bottom:1.2rem; }
/* Portée limitée aux champs : sans le .field, cette règle attraperait aussi
   les tuiles de choix de type, qui sont elles-mêmes des <label>. */
.participer-form .field label{ font-size:.88rem; font-weight:600; color:var(--ink-2); }
.participer-form .field label .hint{ font-weight:400; }
.participer-form input[type=text],
.participer-form input[type=email],
.participer-form input[type=url],
.participer-form input[type=datetime-local],
.participer-form select,
.participer-form textarea{
  width:100%; padding:.65rem .9rem; font:inherit; font-size:.95rem;
  border:1px solid var(--line); border-radius:var(--r-sm);
  background:var(--surface); color:var(--ink);
}
.participer-form textarea{ min-height:8rem; resize:vertical; line-height:1.55; }
/* Un champ en erreur ne se signale pas seulement par la couleur : le message
   de la zone live nomme ce qui manque, et le focus y est déplacé. La bordure
   n'est qu'un rappel visuel de plus. */
.participer-form [aria-invalid=true]{ border-color:#B3261E; box-shadow:0 0 0 1px #B3261E; }
.participer-form .hint{ font-size:.8rem; color:var(--muted); line-height:1.45; }
.participer-deux{ display:grid; gap:0 1rem; grid-template-columns:repeat(auto-fit,minmax(min(100%,12rem),1fr)); }
.participer-defi{ margin-bottom:1.2rem; min-height:65px; }
.participer-actions{ display:flex; flex-wrap:wrap; gap:.7rem; }
.participer-reponse{ margin-top:1rem; font-size:.92rem; font-weight:500; }
.participer-reponse.is-ok{ color:var(--accent-ink); }
.participer-reponse.is-err{ color:#B3261E; }
.participer-note{ font-size:.82rem; color:var(--muted); line-height:1.6; margin-top:1.2rem; max-width:58ch; }
.participer-note a{ color:var(--accent-ink); text-decoration:underline; text-underline-offset:2px; }
@media (max-width:560px){
  .participer-actions .btn{ width:100%; }
}

/* ---------- Signalement déplié sous une fiche de lieu ---------- */
/* .v-report est maintenant un <button> et non plus un <a> : il faut donc
   annuler l'habillage natif du bouton pour qu'il reste le petit lien discret
   qu'il était. Voir js/signalement.js pour le pourquoi du changement. */
button.v-report{
  border:0; background:none; padding:0; font:inherit; font-size:.78rem;
  font-weight:500; color:var(--muted); cursor:pointer;
}
button.v-report:hover{ color:var(--accent-ink); text-decoration:underline; text-underline-offset:2px; }
.signalement-hote:empty{ display:none; }
/* min-width:0 : l'hôte est posé à la fin de la carte, qui est une colonne
   flex. Sans ça, le contenu du formulaire imposerait sa largeur intrinsèque
   au lieu de passer à la ligne, et déborderait de la carte. */
.signalement-hote{ min-width:0; }
.signalement-form,
.signalement-hote > .signalement-reponse{
  margin-top:.9rem; padding-top:.9rem; border-top:1px solid var(--line-2);
}
.signalement-form{ min-width:0; }
.signalement-sous, .signalement-aide{ overflow-wrap:anywhere; }
.signalement-titre{ font-family:"Inter Tight","Inter Tight Repli",sans-serif; font-size:1rem; font-weight:600; }
.signalement-sous{ font-size:.82rem; color:var(--muted); line-height:1.5; margin:.3rem 0 .9rem; }
.signalement-motifs{ border:0; padding:0; margin:0 0 .9rem; display:grid; gap:.35rem; }
.signalement-motifs legend{ font-size:.82rem; font-weight:600; color:var(--ink-2); padding:0; margin-bottom:.35rem; }
.signalement-option{ display:flex; align-items:flex-start; gap:.55rem; cursor:pointer; padding:.3rem .1rem; }
.signalement-option input{ width:16px; height:16px; margin:.15rem 0 0; accent-color:var(--accent-strong); flex:none; }
.signalement-option b{ display:block; font-size:.86rem; font-weight:600; color:var(--ink); }
/* font-weight explicite, comme sur .participer-option : .signalement-option est
   un <label>, donc la règle des libellés de champ plus bas lui donnerait 600 et
   cette explication se lirait comme un titre. */
.signalement-aide{ display:block; font-size:.78rem; font-weight:400; color:var(--muted); line-height:1.45; }
.signalement-form .field{ display:flex; flex-direction:column; gap:.3rem; margin-bottom:.9rem; }
.signalement-form .field label{ font-size:.82rem; font-weight:600; color:var(--ink-2); }
.signalement-form textarea{
  width:100%; padding:.55rem .75rem; font:inherit; font-size:.88rem; line-height:1.5;
  border:1px solid var(--line); border-radius:var(--r-sm);
  background:var(--surface); color:var(--ink); resize:vertical;
}
.signalement-form .hint{ font-size:.75rem; color:var(--muted); }
.signalement-defi{ margin-bottom:.9rem; }
.signalement-actions{ display:flex; flex-wrap:wrap; gap:.5rem; }
.signalement-reponse{ margin-top:.7rem; font-size:.85rem; font-weight:500; }
.signalement-reponse.is-ok{ color:var(--accent-ink); }
.signalement-reponse.is-err{ color:#B3261E; }

/* ---------- Infolettre ----------
   Deux colonnes à partir de 900px : à gauche ce que contient l'infolettre, à
   droite le formulaire dans une carte --surface. Même idiome que .teaser-grid
   plus haut (colonne de texte souple + colonne de largeur bornée), pour que le
   bloc se lise comme une section du site et non comme un encart rapporté. En
   dessous, les deux colonnes s'empilent : le texte explique, la carte agit. */
.infolettre{
  margin-top:clamp(2.5rem,5vw,4rem); padding:clamp(1.6rem,3.5vw,2.6rem);
  background:var(--bg-2); border:1px solid var(--line); border-radius:var(--r-lg);
  display:grid; gap:clamp(1.4rem,3vw,2.4rem);
}
@media (min-width:900px){
  .infolettre{ grid-template-columns:minmax(0,1fr) minmax(0,440px); align-items:start; }
  .infolettre-erreur{ min-height:1.5rem; }
}
.infolettre h2{ font-size:clamp(1.35rem,3vw,1.85rem); }
.infolettre-lede{ margin-top:.9rem; color:var(--ink-2); font-size:1.02rem; line-height:1.6; max-width:52ch; }
.infolettre-liste{ margin-top:1.2rem; display:flex; flex-direction:column; gap:.6rem; }
.infolettre-liste li{ display:flex; gap:.6rem; align-items:flex-start; color:var(--ink-2); font-size:.95rem; line-height:1.55; max-width:52ch; }
.infolettre-liste .ic{ width:18px; height:18px; flex:none; margin-top:.15rem; color:var(--accent-ink); }
.infolettre-cadence{ margin-top:1.2rem; font-size:.88rem; color:var(--muted); line-height:1.6; max-width:52ch; }

.infolettre-panneau{
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r);
  padding:clamp(1.2rem,2.5vw,1.6rem);
}
.infolettre-etats{ display:grid; }
.infolettre-etats > .infolettre-etat{ grid-area:1 / 1; }
/* visibility:hidden plutôt que display:none : l'état caché garde sa place,
   donc la carte conserve la hauteur du plus grand des deux et rien ne saute
   quand la confirmation remplace le formulaire. visibility retire aussi le
   contenu de l'ordre de tabulation et de l'arbre d'accessibilité, donc l'état
   caché reste hors de portée du clavier et des lecteurs d'écran. */
.infolettre-etat.is-cache{ visibility:hidden; }

.infolettre-form{ display:flex; flex-direction:column; }
.infolettre-label{ font-size:.9rem; font-weight:600; color:var(--ink); margin-bottom:.45rem; }
.infolettre-champ{
  width:100%; height:44px; padding:0 .95rem; font:inherit; font-size:.95rem;
  border:1px solid var(--line); border-radius:var(--r-sm); background:var(--surface); color:var(--ink);
}
.infolettre-champ::placeholder{ color:var(--muted); }
.infolettre-champ[aria-invalid=true]{ border-color:#B3261E; }
/* La place du message d'erreur est réservée en permanence : il n'a donc rien
   à pousser vers le bas quand il apparaît. Deux lignes en colonne étroite, où
   le message le plus long tient sur deux lignes ; une seule au-delà de 900px,
   où la colonne de 440px les fait toutes tenir sur une ligne (voir la règle
   dans le bloc @media plus bas). Les messages sont écrits court pour rester
   dans cette réserve - la plus longue réponse de refus du serveur fait 38
   caractères, et js/infolettre.js n'en affiche aucune au-delà de 60. */
.infolettre-erreur{ min-height:3rem; margin-top:.35rem; font-size:.85rem; line-height:1.5rem; font-weight:500; color:#B3261E; }
.infolettre-bouton{ margin-top:.6rem; width:100%; height:44px; }
/* aria-disabled et non l'attribut disabled : un bouton désactivé pendant
   l'envoi sortirait de l'ordre de tabulation et ferait perdre le focus à
   quelqu'un qui navigue au clavier. Le double envoi est bloqué en JavaScript. */
.infolettre-bouton[aria-disabled=true]{ opacity:.55; cursor:progress; }
.infolettre-bouton[aria-disabled=true]:hover{ background:var(--accent-strong); transform:none; }
.infolettre-double{ margin-top:1rem; display:flex; gap:.55rem; align-items:flex-start; font-size:.85rem; color:var(--ink-2); line-height:1.55; }
.infolettre-double .ic{ width:16px; height:16px; flex:none; margin-top:.2rem; color:var(--accent); }

.infolettre-succes{ display:flex; flex-direction:column; align-items:flex-start; }
.infolettre-succes p{ font-size:.9rem; color:var(--ink-2); line-height:1.6; }
.infolettre-succes p + p{ margin-top:.7rem; }
.infolettre-succes p.infolettre-succes-titre{
  display:flex; gap:.55rem; align-items:center;
  font-size:1.02rem; font-weight:600; color:var(--accent-ink);
}
.infolettre-succes-titre .ic{ width:20px; height:20px; flex:none; }
.infolettre-succes .btn{ margin-top:1.1rem; }

.infolettre-note{ margin-top:1rem; font-size:.8rem; color:var(--muted); line-height:1.55; }
.infolettre-note a{ color:var(--accent-ink); font-weight:600; }
.infolettre-note a:hover{ text-decoration:underline; text-underline-offset:2px; }

/* ---------- Évènements (rendez-vous annuels) ----------
   Une section par saison, chaque saison une liste. Pas de grille de cartes :
   un rendez-vous se lit surtout par son "quand", donc la période reste
   collée au titre plutôt que reléguée en bas d'une carte. */
.ev-saison + .ev-saison{ margin-top:clamp(2rem,4vw,3rem); }
.ev-saison > h2{
  font-size:1.35rem; padding-bottom:.6rem;
  border-bottom:1px solid var(--line);
}
.ev-list{ list-style:none; margin:0; padding:0; display:grid; gap:0; }
.ev-item + .ev-item{ border-top:1px solid var(--line); }
.ev{ padding:1.25rem .25rem; }
/* La période passe sous le titre dès que la ligne devient serrée (wrap), au
   lieu d'écraser le nom de l'évènement. */
.ev-head{ display:flex; align-items:baseline; justify-content:space-between; gap:.5rem 1rem; flex-wrap:wrap; }
.ev-head h3{ font-size:1.12rem; }
.ev-periode{
  display:inline-flex; align-items:center; gap:.35rem; flex:none;
  font-size:.82rem; font-weight:600; color:var(--accent-ink);
}
.ev-periode .ic{ width:15px; height:15px; }
.ev-lieu{
  display:inline-flex; align-items:center; gap:.35rem;
  margin-top:.3rem; font-size:.85rem; color:var(--muted);
}
.ev-lieu .ic{ width:15px; height:15px; flex:none; }
.ev-desc{ margin-top:.55rem; color:var(--ink-2); line-height:1.6; max-width:60ch; }
.ev-links{ margin-top:.7rem; }
.ev-link{ display:inline-flex; align-items:center; gap:.35rem; font-size:.85rem; font-weight:600; color:var(--accent-ink); }
.ev-link .ic{ width:14px; height:14px; }
.ev-link:hover{ text-decoration:underline; text-underline-offset:2px; }
/* Rappel de vérifier les dates : volontairement en bas et discret, mais
   jamais retiré - c'est la contrepartie honnête d'une page sans dates. */
.evenements-note{
  margin-top:clamp(2rem,4vw,3rem); padding-top:1rem;
  border-top:1px solid var(--line);
  font-size:.88rem; color:var(--muted); max-width:60ch;
}
.evenements-note a{ color:var(--accent-ink); font-weight:600; }
.evenements-note a:hover{ text-decoration:underline; text-underline-offset:2px; }

/* ---------- Aperçu "À propos" de l'accueil ----------
   Collage photo à droite du texte (2026-07-31) : cette section n'était que du
   texte sur fond clair entre deux blocs eux aussi clairs, elle se fondait dans
   la page. Le collage est un PNG à fond transparent converti en WebP (44 ko
   contre 406) ; il vit dans le flux, pas en fond CSS, pour rester un vrai
   contenu décrit par son alt. */
.teaser-grid{ display:grid; gap:clamp(1.8rem,4vw,3.2rem); align-items:center; }
.teaser-collage{
  /* Le fichier fait 512px : ne jamais l'agrandir au-delà, il piquerait. */
  width:100%; max-width:440px; height:auto; justify-self:center;
}
@media (min-width:900px){
  /* minmax(0,...) sur les deux colonnes : sans lui, le texte long de la
     colonne de gauche impose une largeur minimale et déborde la grille. */
  .teaser-grid{ grid-template-columns:minmax(0,1fr) minmax(0,440px); }
  .teaser-collage{ justify-self:end; }
}

/* ---------- Bandeau promo (entreprises) ----------
   Cette section garde un padding-top - la règle générale du rythme vertical
   (section{padding-top:0}, l'espacement venant du padding-bottom de la
   section précédente) part du principe que deux sections empilées partagent
   le même fond ; ici .promo-band est un bloc sombre à coins arrondis sur le
   fond clair de la page, il a donc besoin de sa propre respiration en haut
   pour ne pas coller à la section au-dessus. Même valeur que le padding-top
   "post-héro" ailleurs sur le site, pour rester dans le même rythme. */
.promo-band-wrap{ padding-top:clamp(3.4rem,7vw,6rem); }
.promo-band{
  text-align:center; background:var(--dark); color:var(--on-dark);
  border-radius:var(--r); padding:clamp(2.2rem,5.5vw,3.4rem) 1.5rem;
}
.promo-band h2{ color:#fff; font-size:clamp(1.35rem,3vw,1.85rem); max-width:32ch; margin-inline:auto; }
.promo-band p{ color:var(--on-dark-muted); margin:.9rem auto 1.6rem; max-width:40rem; line-height:1.6; }
.note{ margin-top:1.4rem; font-size:.83rem; color:var(--muted); display:flex; gap:.55rem; align-items:flex-start; }
.note .ic{ width:16px; height:16px; color:var(--accent); margin-top:.15rem; flex:none; }

/* ---------- Par intérêt (Tâche 18) ----------
   Grille de puces d'intérêt (réutilise .chips/.chip, déjà stylées et
   accessibles ailleurs - voir plus haut dans ce fichier) suivie du panneau
   qui affiche le mini-guide puis les lieux (réutilise .venues/.venue/.empty,
   également déjà définis pour l'explorateur - Tâche 18 ne fait qu'y ajouter
   les quelques classes propres à l'habillage du panneau lui-même). */
.interet-grid{ margin-bottom:1.6rem; }
.interet-panel{ min-height:2rem; }
.interet-placeholder{ color:var(--muted); font-size:.95rem; padding:.5rem 0 1.5rem; max-width:48rem; line-height:1.55; }
.interet-guide{
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r);
  padding:1.5rem; margin-bottom:1.6rem;
}
.interet-guide h2{ font-size:1.2rem; letter-spacing:-.01em; }
.interet-guide p{ margin-top:.6rem; color:var(--ink-2); line-height:1.6; max-width:56rem; }
.interet-guide .btn{ margin-top:1.1rem; }

/* ---------- Pied de page ----------
   Tâche 16 (refonte) : bandeau supérieur avec une fine bordure --accent en
   haut du pied de page ; colonne « Participer » (courriels mailto) à la
   place de l'ancienne colonne « La région » ; bande de mise en vedette avec
   les 5 types de sortie en liens colorés par teinte, entre le bandeau
   supérieur et la barre du bas. */
.site-footer{ background:var(--dark); color:var(--on-dark); border-top:2px solid var(--accent); }
.footer-top{ display:grid; grid-template-columns:1.4fr 1fr 1fr; gap:2rem; padding-block:clamp(2.6rem,5vw,3.6rem); }
@media (max-width:720px){ .footer-top{ grid-template-columns:1fr; gap:1.6rem; } }
.footer-brand .brand{ color:#fff; }
.footer-brand .brand .fleur{ color:var(--accent-bright); }
.footer-brand .brand .q{ color:var(--accent-bright); }
.footer-brand p{ margin-top:.9rem; color:var(--on-dark-muted); font-size:.92rem; max-width:24rem; line-height:1.6; }
/* M3 fix (2026-07-30) : ces titres de colonne étaient des <h5> alors qu'aucun
   <h3>/<h4> n'existe entre le dernier <h2> visible de la page et le pied de
   page (saut H2 -> H5 sur index/à propos/speed-dating/par intérêt) - passés
   à <h3> en HTML, sélecteur renommé ici en conséquence ; taille/couleur
   inchangées. */
.footer-col h3{ font-family:"Inter Tight","Inter Tight Repli",sans-serif; font-size:.8rem; letter-spacing:.12em; text-transform:uppercase; color:var(--accent-bright); font-weight:600; margin-bottom:.9rem; }
.footer-col a,.footer-col span{ display:block; color:var(--on-dark-muted); font-size:.9rem; padding:.2rem 0; transition:color var(--t); }
.footer-col a:hover{ color:#fff; }

/* Bande de mise en vedette - les 5 types de sortie, chacun dans sa teinte
   (variantes -bright, déjà calculées pour rester >= 4.5:1 sur --dark). */
.footer-highlight{
  border-top:1px solid rgba(239,247,242,.14); padding-block:1.1rem;
  display:flex; flex-wrap:wrap; align-items:center; gap:.6rem 1.6rem;
}
.fh-label{ font-size:.7rem; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:var(--on-dark-muted); }
.fh-links{ display:flex; flex-wrap:wrap; gap:.3rem 1.2rem; }
.fh-links a{ font-size:.87rem; font-weight:600; padding-bottom:2px; border-bottom:1px solid transparent; transition:border-color var(--t); }
.fh-links a:hover,.fh-links a:focus-visible{ border-color:currentColor; }
.fh-links a[data-sortie="solo"]{ color:var(--c-solo-bright); }
.fh-links a[data-sortie="entre-amis"]{ color:var(--c-entre-amis-bright); }
.fh-links a[data-sortie="couple"]{ color:var(--c-couple-bright); }
.fh-links a[data-sortie="premier-rendez-vous"]{ color:var(--c-premier-rendez-vous-bright); }
.fh-links a[data-sortie="famille"]{ color:var(--c-famille-bright); }

.footer-bar{ border-top:1px solid rgba(239,247,242,.14); padding-block:1.3rem; display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:.7rem; font-size:.85rem; color:var(--on-dark-muted); }
.footer-bar .made{ color:#fff; font-weight:600; border-bottom:1px solid var(--accent-bright); padding-bottom:1px; }
.footer-bar .made:hover{ color:var(--accent-bright); }

/* Liens vers les pages légales (confidentialité, conditions), placés dans la
   barre du bas plutôt que dans une colonne : ce ne sont pas des destinations
   de découverte, la grille à 3 colonnes de .footer-top n'a pas à en tenir
   compte. */
.footer-legal{ display:flex; flex-wrap:wrap; gap:.4rem 1.1rem; }
.footer-legal a{ color:var(--on-dark-muted); }
.footer-legal a:hover{ color:#fff; }
.footer-legal a[aria-current="page"]{ color:#fff; }

/* ---------- Pages légales (confidentialité / conditions) ----------
   Même fond que .about (--bg-2) pour rester cohérent avec les autres pages
   de contenu ; pas de grille puisque ce sont de longs textes en une seule
   colonne, plafonnés en largeur pour rester lisibles (~68-72 caractères). */
.legal{ background-color:var(--bg-2); border-top:1px solid var(--line); }
.legal-content{ max-width:44rem; margin-inline:auto; }
.legal-content h2{ margin-top:2.6rem; font-size:clamp(1.2rem,2.6vw,1.5rem); }
.legal-content section:first-child h2{ margin-top:0; }
.legal-content h3{ margin-top:1.5rem; font-size:1.05rem; }
.legal-content p{ margin-top:.9rem; color:var(--ink-2); font-size:1rem; line-height:1.65; }
.legal-content ul{ margin-top:.9rem; padding-left:1.2rem; list-style:disc; display:flex; flex-direction:column; gap:.5rem; }
.legal-content li{ color:var(--ink-2); font-size:1rem; line-height:1.6; }
.legal-content a{ color:var(--accent-ink); font-weight:600; }
.legal-content a:hover{ text-decoration:underline; text-underline-offset:2px; }
.legal-updated{ margin-top:1.1rem; font-size:.85rem; color:var(--muted); }

/* ---------- Divers ---------- */
[hidden]{ display:none !important; }
.sr-only{ position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0; }
