/* style-05-responsive.css — Barre du haut responsive, mobile (volets en plein écran), focus clavier, boîtes colorées des groupes de filtres. Chargé après style-04 (ordre 01 → 07 : voir style-01-recherche.css). */
/* ── TOPBAR RESPONSIVE ──
   Les constantes soustraites à 100vw ci-dessous sont calées pour que le bord
   gauche de la recherche reste toujours à distance du titre/label à sa gauche.
   Vérifié empiriquement (Playwright, pas seulement visuellement) à chaque
   palier : logo+titre ≈389px jusqu'à 720px (où le titre se masque, voir
   shared.css), logo+label ≈143px en dessous. Revérifier ces marges si le
   titre, le label, le logo ou leurs tailles changent. */
@media (max-width: 1280px) {
  .topbar-count { display: none; }
  /* Recherche alignée à droite, par-dessus l'espace de Déconnexion/Recueils
     (qui se masquent alors eux-mêmes au scroll au même palier, cf. règle plus
     bas) — étendu de 1000px à 1280px pour corriger un chevauchement avec le
     label "CATALOGUE" mesuré entre 1240 et 1100px avec l'ancien calcul
     (centré, clamp) encore actif dans cette tranche. Marge resserrée à 440
     (400 à l'origine, 460 dans une précédente passe) : Joseph l'a mesurée
     trop généreuse en dessous de 940px environ. */
  #topbar-search {
    left: auto;
    right: 1.5rem;
    transform: none;
    width: min(480px, calc(100vw - 440px));
  }
}
@media (max-width: 720px) {
  /* Le titre ("Partithèque / Guides et Scouts d'Europe") passe en display:none
     à ce même palier (shared.css) : c'est maintenant LUI qui libère la place,
     plus besoin de masquer le label pour ça — seul le label ("Catalogue")
     reste à gauche de la recherche, nettement plus court que l'ancien titre.
     Marge resserrée à 200 (278 à l'origine, 220 dans une précédente passe) :
     mesurée trop généreuse par Joseph en dessous de 700px environ — la
     recherche peut encore se rapprocher du label sans risquer de le
     chevaucher. Aligné sur 720px (au lieu de 680px) pour coïncider avec le
     passage en colonne unique (.results-area, plus bas dans ce fichier).
     Plus de palier séparé à 640px ni à 400px (tous deux supprimés) : cette
     règle s'applique directement jusqu'aux plus petites largeurs, min-width
     préservant une recherche utilisable sur les téléphones les plus étroits. */
  #topbar-search { right: 1rem; width: min(480px, calc(100vw - 200px)); min-width: 110px; }
}


/* ── RESPONSIVE MOBILE : colonnes détail et filtres en overlay plein écran ──
   En dessous de 720px, ni la fiche détaillée ni la colonne de recherche
   avancée ne réduisent plus la liste — elles se superposent en overlay
   plein écran (position fixed). Détail glisse depuis le bas, filtres
   glissent depuis la gauche.
   Au-dessus de 720px : comportement side-by-side d'origine conservé. */
/* Voile (créé dynamiquement) — invisible par défaut et hors mobile. Doit
   précéder le bloc @media ci-dessous (même sélecteur .overlay-scrim, mêmes
   spécificité) : sinon cette règle de base, plus tardive dans le fichier,
   écrase le display:block du mobile et le voile ne s'affiche jamais.
   z-index 301 : au-dessus de la topbar (300) — l'assombrit avec le reste de
   la page plutôt que de la laisser en bleu vif, visuellement incohérente
   au-dessus d'un fond par ailleurs dimmé. Toujours sous .filters-panel/
   .detail-col (500). */
.overlay-scrim {
  position: fixed;
  inset: 0;
  background: var(--scrim);
  z-index: 301;
  opacity: 0;
  pointer-events: none;
  display: none;
  transition: opacity 0.3s ease;
}

@media (max-width: 720px) {
  /* En mobile, le layout ne se divise plus en deux colonnes */
  .results-area {
    position: relative; /* contexte pour le positionnement du overlay */
  }
  .results-list-col {
    width: 100%;
  }
  /* La colonne détail devient un overlay plein écran */
  .detail-col {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100% !important;   /* écrase width:0 et width:480px */
    height: 100dvh;           /* dvh : tient compte de la barre d'URL mobile */
    background: var(--white);        /* même fond blanc qu'en desktop */
    z-index: 500;
    border-left: none;
    transform: translateY(100%);  /* masqué : glisse depuis le bas */
    transition: transform 0.3s ease;
    /* PAS de overflow-y:auto ici : .detail-scroll (interne) est le SEUL
       défileur, comme en desktop. En avoir un second ici causait un double
       défilement imbriqué sur mobile. */
  }
  .detail-col.open {
    transform: translateY(0);
  }
  /* L'outer gère déjà tout seul l'overlay mobile (position, transform, fond) —
     neutralise l'inner (ajouté pour le correctif desktop), sans quoi sa
     propre largeur fixe (480px) s'ajouterait à celle de l'outer. */
  .detail-col-inner {
    width: 100%;
    height: 100%;
    background: transparent;
    border-left: none;
  }
  /* Poignée visuelle en haut de la fiche (comme Hodari, .yk-sheet-handle) :
     signale que la fiche peut se refermer par glissement vers le bas.
     Purement décorative — le geste lui-même (attachDetailGestures, app.js)
     écoute déjà tout .detail-header, pas seulement cette poignée. Couleur
     blanche translucide (et non var(--border), gris neutre utilisé par
     Hodari) : le fond de .detail-header est navy ici, pas blanc — même
     teinte que les bordures des boutons de l'en-tête juste en dessous. */
  .detail-header-handle {
    display: block;
    width: 40px; height: 4px;
    background: var(--white-30);
    border-radius: 3px;
    margin: 0 auto 0.6rem;
  }
  /* La colonne de recherche avancée devient elle aussi un overlay plein écran :
     une colonne fixe de 300px n'a pas sa place sur un petit écran. Même logique
     que .detail-col ci-dessus, glissée depuis la gauche cette fois.
     Largeur calc(100% - 48px), PAS 100% : laisse 48px visibles à droite
     (résultats assombris par le voile) — la topbar (z-index 300, au-dessus du
     voile à 250) reste visible dans cette bande. */
  .filters-panel {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: calc(100% - 48px) !important;   /* écrase width:0 et width:300px */
    height: 100dvh;
    background: var(--white);
    z-index: 500;
    border-right: none;
    transform: translateX(-100%);
    transition: transform 0.3s ease;
    overflow: hidden;         /* la grille interne gère le défilement, l'en-tête reste figé */
    margin-left: 0;    /* sinon le -28px de la règle desktop .open fuit ici, décalant l'overlay hors champ */
  }
  .filters-panel.open {
    transform: translateX(0);
    margin-left: 0;
  }
  /* L'outer gère déjà tout seul l'overlay mobile (position, transform,
     fond) — neutralise l'inner (ajouté pour le correctif desktop ci-dessus),
     sans quoi sa propre largeur fixe (300px) et son propre transform
     s'ajouteraient à ceux de l'outer au lieu de les laisser faire. */
  .filters-panel-inner {
    width: 100%;
    height: 100%;
    background: transparent;
    border-right: none;
    transform: none;
    transition: none;
  }
  .filters-panel.open .filters-grid { padding-bottom: 6rem; }
  /* Le rail de réouverture n'a pas sa place sur mobile : le bouton
     « Recherche avancée » de la barre de recherche suffit. */
  .filters-rail { display: none !important; }
  /* Bouton fermer plus grand et plus visible sur mobile */
  .detail-close {
    width: 36px;
    height: 36px;
    font-size: 1rem;
  }
  /* Pagination compacte sur mobile */
  .pagination { gap: 0.2rem; }
  .page-btn { min-width: 28px; height: 28px; font-size: var(--fs-sm); }

  /* Quand un overlay plein écran (fiche ou recherche avancée) est ouvert :
     - le scroll de la page de fond est verrouillé (plus de défilement derrière) ;
     - le pull-to-refresh est neutralisé (overscroll-behavior) ;
     - le bouton « retour en haut » est masqué PROGRESSIVEMENT (opacity, pas
       display:none — display:none empêcherait toute transition/fondu piloté
       en JS pendant le geste de fermeture). */
  .detail-col,
  .filters-panel { overscroll-behavior: contain; }
  html.overlay-open,
  body.overlay-open { overflow: hidden; overscroll-behavior: none; }
  /* Le verrou de scroll (app.js, syncOverlayLock) fige <body> en position:fixed
     avec un top négatif compensant le scroll courant — ça déplace TOUT le
     contenu de body avec lui, y compris la topbar (position:sticky, shared.css),
     qui suit alors ce décalage et se retrouve hors écran si la page était
     scrollée au moment de l'ouverture. Fixée explicitement au viewport pendant
     le verrou, indépendamment du décalage appliqué à body.
     Carte d'installation (shared.css, position:relative normalement) : même
     principe, empilée AU-DESSUS de la topbar (ordre HTML) — mais seulement
     sur sa portion ENCORE VISIBLE à l'instant du verrouillage
     (--install-card-visible, posée par app.js = hauteur moins défilement déjà
     effectué, 0px si on avait déjà défilé au-delà). Ouvrir un volet ne doit
     jamais faire réapparaître la carte si elle était déjà masquée par le
     défilement — elle doit rester masquée en tout ou partie, exactement
     comme avant l'ouverture (signalé par Joseph). --install-card-h (hauteur
     totale) sert uniquement à décaler le haut de la carte hors écran d'autant
     que nécessaire pour ne laisser dépasser que sa portion basse. Les deux
     restent sous le voile (z-index 301) : dimées avec le reste de la page
     plutôt que de disparaître — demandé par Joseph après qu'une première
     tentative avec des styles inline (plus prioritaires que ces classes) soit
     entrée en conflit avec la règle topbar ci-dessous et casse l'affichage ;
     puis un repli en display:none (perdait le dimmage en place), puis une
     version qui révélait toujours la carte en entier (celle-ci), qu'on
     remplace ici par la bonne portion. */
  body.overlay-open .install-card {
    position: fixed;
    top: calc(var(--install-card-visible, 0px) - var(--install-card-h, 0px));
    left: 0;
    right: 0;
    z-index: 300;   /* sous le voile (301) : dimée avec la topbar, pas au-dessus */
  }
  body.overlay-open .topbar {
    position: fixed;
    top: var(--install-card-visible, 0px);
    left: 0;
    right: 0;
  }
  /* --install-card-h (hauteur TOTALE, pas --install-card-visible) : la carte
     occupe toujours sa pleine hauteur dans le flux normal, qu'elle soit
     visible à l'écran à cet instant ou déjà défilée hors champ — retirer ce
     flux (position:fixed ci-dessus) libère systématiquement cette hauteur,
     qu'il faut compenser intégralement pour que le contenu suivant ne
     remonte pas. Utiliser --install-card-visible ici (comme pour topbar/
     install-card juste au-dessus) sous-compensait dès qu'on avait défilé,
     d'où la remontée du contenu signalée par Joseph. */
  body.overlay-open { padding-top: calc(60px + var(--install-card-h, 0px)); }   /* 60px : NE PAS SUPPRIMER — voir DECISIONS.md §3 et §4 */
  body.overlay-open #back-to-top { opacity: 0; pointer-events: none; }

  /* Voile sombre + ombre : quand un overlay est ouvert (et surtout quand on le
     glisse pour le fermer), le contenu recouvert derrière est assombri, ce qui
     matérialise le geste. Le voile est SOUS les overlays (z-index 500) mais
     AU-DESSUS du contenu de page (z-index auto) — et surtout SOUS la topbar
     (z-index 300 > 250) : elle reste visible dans la bande de 48px laissée
     par .filters-panel ci-dessus. Voir la règle de base .overlay-scrim
     (z-index 250) plus bas dans ce fichier.
     Ombres DIRECTIONNELLES et uniquement quand le panneau est visible :
       · recherche avancée → ombre à droite (jamais à gauche quand masquée) ;
       · fiche détaillée   → ombre en haut  (jamais en bas quand masquée, ni sur
         les côtés entre deux fiches lors du swipe carrousel). */
  .filters-panel.open,
  .filters-panel.swiping { box-shadow: 6px 0 24px var(--black-30); }
  .detail-col.open       { box-shadow: 0 -6px 24px var(--black-30); }
  /* Pendant le carrousel (swipe entre fiches), AUCUNE ombre : ni sur la fiche
     réelle en cours de navigation, ni sur les calques voisins — sinon le flou
     de l'ombre déborde latéralement entre deux fiches. Aux extrémités (un seul
     résultat, ou déjà à la première/dernière fiche), un remplissage blanc
     (.at-edge, voir plus bas) couvre l'espace vide plutôt que de laisser
     apparaître les résultats derrière. */
  .detail-col.navigating,
  .detail-ghost { box-shadow: none !important; }
  /* Extrémités du carrousel (aucune fiche voisine de ce côté) : un fond blanc
     comble l'écart pendant l'étirement élastique, plutôt que de laisser
     apparaître les résultats derrière. Spécificité (0,3,0) > la règle
     box-shadow:none!important ci-dessus (0,2,0) : l'emporte malgré !important. */
  .detail-col.navigating.at-edge {
    box-shadow: 100vw 0 0 0 var(--white), -100vw 0 0 0 var(--white) !important;
  }
  .overlay-scrim { display: block; }
  /* pointer-events:auto : sans ça, le voile est purement visuel et les clics
     traversent jusqu'à la page de résultats en dessous — un élément (filtre,
     recherche…) resterait cliquable malgré l'assombrissement, notamment dans
     la bande grisée à droite du volet filtres. */
  body.overlay-open .overlay-scrim { opacity: 1; pointer-events: auto; }
}

/* ── FOCUS-VISIBLE : accessibilité clavier ── */
.chip:focus-visible,
.toggle-btn:focus-visible,
.btn-adv:focus-visible,
.btn-primary:focus-visible,
.btn-ghost:focus-visible,
.btn-reset-filters:focus-visible,
.btn-detail:focus-visible,
.file-btn:focus-visible,
.page-btn:focus-visible,
.harm-expand-btn:focus-visible,
.accordion-toggle:focus-visible,
.filters-close-btn:focus-visible,
.sort-select:focus-visible,
.per-page-select:focus-visible,
.dropdown-filter-trigger:focus-visible {
  outline: 2.5px solid var(--accent);
  outline-offset: 2px;
}

/* ── GROUPES DE FILTRES — boîtes colorées dans le panneau avancé ──
   Remplacent les styles inline dans catalogue.html.
   Chaque variante colore la bordure, le fond et le titre selon le groupe. */
.filter-group-box {
  grid-column: 1 / -1;
  min-width: 0;
  border-radius: 8px;
  padding: 0.75rem 1rem 0.5rem;
}
.filter-group-box-title {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-bottom: 0.6rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
/* Bouton discret OU/ET par section (recherche avancée) — currentColor pour
   suivre automatiquement la couleur sémantique de chaque section (héritée de
   .filter-group-box-title ci-dessus), sans règle par variante à dupliquer.
   Discret par défaut (opacité réduite) ; pleine opacité en mode ET (le mode
   OU est le défaut silencieux, ET est le changement notable à signaler). */
.filter-mode-toggle {
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: none;
  padding: 0.1em 0.55em;
  border-radius: var(--radius-pill);
  border: 1px solid currentColor;
  background: transparent;
  color: currentColor;
  opacity: 0.55;
  cursor: pointer;
  flex-shrink: 0;
  transition: opacity 0.15s, background 0.15s;
}
.filter-mode-toggle:hover { opacity: 1; background: var(--black-06); }
.filter-mode-toggle.and-mode { opacity: 1; }
.filter-group-box-inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.6rem;
  min-width: 0;
}
/* Variantes sémantiques */
.filter-group-box--voix    { border: 1.5px solid var(--c-voix-border);    background: var(--c-voix-bg); }
.filter-group-box--voix    .filter-group-box-title { color: var(--c-voix); }
.filter-group-box--langue  { border: 1.5px solid var(--c-langue-border);  background: var(--c-langue-bg); }
.filter-group-box--langue  .filter-group-box-title { color: var(--c-langue); }
.filter-group-box--etiq    { border: 1.5px solid var(--c-etiq-border);    background: var(--c-etiq-bg); }
.filter-group-box--etiq    .filter-group-box-title { color: var(--c-etiq); }
.filter-group-box--themes  { border: 1.5px solid var(--c-themes-border);  background: var(--c-themes-bg); }
.filter-group-box--themes  .filter-group-box-title { color: var(--c-themes); }
.filter-group-box--dispo   { border: 1.5px solid var(--c-dispo-border);   background: var(--c-dispo-bg); }
.filter-group-box--dispo   .filter-group-box-title { color: var(--c-dispo); }
.filter-group-box--recueil { border: 1.5px solid var(--c-recueil-border); background: var(--c-recueil-bg); }
.filter-group-box--recueil .filter-group-box-title { color: var(--c-recueil); }
.filter-group-box--audio   { border: 1.5px solid var(--c-audio-border);   background: var(--c-audio-bg); }
.filter-group-box--audio   .filter-group-box-title { color: var(--c-audio); }

/* Sous-grille des boîtes Étiquettes / Thèmes / Disponibilité / Recueils —
   une seule colonne (empilées) : la boîte vit désormais dans une colonne étroite. */
.filter-group-box-row2 {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.9rem;
  min-width: 0;
}
