/* ============================================================================
   airbnb.css — « Airbnb chez Decarmy », le design system du site
   Écrit le 14/08/2026. Structure et proportions relevées au navigateur sur
   airbnb.fr (viewport 1280) ; palette et vocabulaire de Decarmy.

   ── POURQUOI CE FICHIER EXISTE ─────────────────────────────────────────────
   Le site avait trois chromes concurrents (.dsh injecté par bottom-nav.js,
   le <header class="nav"> inline d'index.html, et le legacy #header recopié
   dans 73 pages), quatre familles de pieds de page et autant de grammaires de
   cartes. Une seule feuille, un seul préfixe : plus rien n'est recopié.

   ── RÈGLE DU PRÉFIXE ───────────────────────────────────────────────────────
   TOUT est préfixé `ab-`. Aucune règle ne touche un sélecteur de balise nu ni
   une classe du site — SAUF le bloc final, clairement signalé, qui neutralise
   les en-têtes maison quand `body.ab-on` est posé.

   ⚠️ PIÈGE MAJEUR, À LIRE AVANT D'AJOUTER UNE CLASSE : le préfixe `ab-` est
   DÉJÀ pris par detail-airbnb.css et par les 4 pages *-detail.html. Sont
   occupés et donc INTERDITS ici : .ab-actions .ab-avatar .ab-badge-icon
   .ab-badge-text .ab-badge-wrap .ab-bottom* .ab-btn .ab-btn-res .ab-desc-*
   .ab-dropdown* .ab-head .ab-highlights .ab-hl* .ab-host-* .ab-hr .ab-icon
   .ab-img .ab-label .ab-location* .ab-rate-line .ab-stars .ab-stat-* .ab-stats
   .ab-sub .ab-sub-2 .ab-title .ab-wrap-dropdown .ab-wrap-logement.
   C'est pour ça que la partie FICHE (§7) est intégralement PORTÉE PAR
   `.ab-fiche` : `.ab-fiche .ab-actions` ne peut pas entrer en collision avec
   le `.ab-actions` de detail-airbnb.css, qui n'a jamais d'ancêtre `.ab-fiche`.
   Ne JAMAIS écrire ici un `.ab-actions` nu.

   ── CE QU'ON NE FAIT PAS ───────────────────────────────────────────────────
   · Aucun @import, aucune police distante. Inter est déjà chargée par les
     pages (poids 400/500/600/700/800 — n'en demander aucun autre).
   · Aucun rouge Airbnb #FF385C, aucun doré #D4A847 : bannis par Elia.
     Le CTA est NOIR, le cœur « enregistré » est noir lui aussi.
   · Aucun mode sombre. lang.js:37 force le clair sur le web, et cet en-tête
     ne s'affiche qu'en desktop web (≥768px, jamais en natif). Introduire un
     [data-theme=dark] ici serait du code mort ambigu.
   ========================================================================= */


/* ══════════════════════════════════════════════════════════════════════════
   §1 — JETONS
   Mesures d'Airbnb, couleurs de Decarmy. Les valeurs de styles.css
   (--color-text #1D1D1F, --color-surface #F5F5F7, --color-border #E8E8ED)
   sont RECOPIÉES et non référencées : index.html ne charge pas styles.css,
   et une variable absente casse en silence.
   ══════════════════════════════════════════════════════════════════════════ */
/* ⚠️ PALETTE GÉNÉRÉE DEPUIS L'APP (27/08) — voir db/theme-deca.css.
   Ce fichier n'avait AUCUN mode sombre : les 92 pages qui le chargent
   restaient blanches pendant que l'app était noire. Les --ab-* ci-dessous
   sont maintenant des alias des jetons DECA, donc les deux thèmes suivent
   l'app sans qu'on recopie une couleur.
   ⚠️ Un @import doit précéder toute règle : ne rien insérer au-dessus. */
@import url('db/theme-deca.css');

:root {
  /* Palette — équivalents Decarmy des #222 / #6A6A6A / #EBEBEB / #DDD / #F7F7F7 */
  --ab-text:      var(--deca-text);   /* Airbnb #222222 */
  --ab-sec:       var(--deca-text-secondary);   /* Airbnb #6A6A6A */
  --ab-tert:      var(--deca-text-tertiary);
  --ab-line:      var(--deca-border);   /* filet fin — Airbnb #EBEBEB */
  --ab-line-fort: #D6D6DE;   /* contour de bouton/pilule — Airbnb #DDDDDD */
  --ab-grey:      var(--deca-surface);   /* aplat de fond — Airbnb #F7F7F7 */
  --ab-grey-fort: #EDEDF2;   /* survol d'un aplat */
  --ab-white:     var(--deca-bg);
  --ab-cta:       var(--deca-primary);   /* le noir Decarmy remplace le rouge Airbnb */
  --ab-cta-h:     #333336;

  /* Rayons — 12 (cartes/menu), 16 (blocs), 32 (pilule de recherche) */
  --ab-r12:   12px;
  --ab-r16:   16px;
  --ab-r32:   32px;
  --ab-rfull: 100px;

  /* Ombres — relevées : pilule 0 3px 12px .10 ; menu 0 10px 38px .16 */
  --ab-sh-pill:  0 3px 12px rgba(0,0,0,.10);
  --ab-sh-pill-h:0 4px 16px rgba(0,0,0,.14);
  --ab-sh-menu:  0 10px 38px rgba(0,0,0,.16);
  --ab-sh-card:  0 2px 10px rgba(0,0,0,.10);

  /* Gabarit */
  --ab-h:       80px;    /* hauteur de la ligne d'en-tête */
  --ab-h-small: 80px;    /* idem repliée : la pilule 46px tient dedans */
  --ab-wrap:    1216px;  /* conteneur d'en-tête et de listes */
  --ab-fiche-w: 1120px;  /* conteneur de fiche (mesure Airbnb) */
  --ab-book-w:  373px;   /* colonne droite collante de la fiche */
  --ab-card-w:  193px;   /* carte de carrousel */
  --ab-gap:     12px;    /* pas 205 − carte 193 = 12 */
  --ab-gut:     32px;    /* gouttière du conteneur (marges 32 à 1280) */

  /* Divers */
  --ab-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --ab-ease: .18s cubic-bezier(.4,0,.2,1);
  /* z-index : au-dessus de .mobile-menu (1200) et de .hero-search-dropdown
     (1000), SOUS .deca-tabbar (2000) et .dcc (4000) — ces deux-là sont
     mobiles/globaux et ne doivent jamais passer dessous. */
  --ab-z: 1500;
}

/* ── Les trois nuances propres à ce fichier ────────────────────────────
   Elles n'existent pas dans DecaTheme.ts (l'app n'en a pas l'usage), donc
   elles ne peuvent pas venir du générateur : on leur écrit ici leur
   version sombre, dérivée des jetons DECA. Tout le reste suit l'app. */
:root[data-theme="dark"] {
  --ab-line-fort: rgba(255,255,255,0.18);
  --ab-grey-fort: var(--deca-border);
  --ab-cta-h:     #E5E5EA;
}
/* ⛔ Pas de @media (prefers-color-scheme) : le site est blanc par décision
   produit (25/07, lang.js:30), et toutes les pages ne chargent pas lang.js —
   une media query s'y appliquerait donc SANS garde-fou. Mesuré le 27/08 sur
   index.html : les libellés des cases passaient en blanc sur fond clair.
   Le sombre ne s'active que sur <html data-theme="dark">. */



/* ══════════════════════════════════════════════════════════════════════════
   §2 — EN-TÊTE
   DOM attendu :
     <header class="ab-header">
       <div class="ab-wrap">
         <a class="ab-brand" …>            (zone « brand »)
         <nav class="ab-tabs">…</nav>      (zone « tabs »)
         <form class="ab-search">…</form>  (zone « search »)
         <div class="ab-right">…</div>     (zone « right »)
       </div>
     </header>
   Le placement passe par grid-area : l'ordre du DOM n'a aucune importance,
   c'est ce qui permet à la pilule de PASSER de la 2ᵉ ligne au centre de la
   1ʳᵉ en état replié sans déplacer un seul nœud.
   Deux classes d'état, posées par JS :
     .ab-header.scrolled → le filet du bas apparaît
     .ab-header.small    → en-tête replié (onglets masqués, pilule dans la ligne)
   ══════════════════════════════════════════════════════════════════════════ */
/* ⚠️ BANDEAU GRIS, BARRE BLANCHE — ET SURTOUT PAS L'INVERSE (18/08).
   C'est la correction la plus visible de la capture d'Elia, et elle est
   déjà écrite noir sur blanc dans `EnteteDeca` :
     « Chez Airbnb, l'en-tête est un bandeau GRIS et la barre de recherche
       est BLANCHE, posée dessus avec une ombre. On avait fait le
       contraire — barre grise sur fond blanc — et c'est ce qui faisait le
       plus "pas pareil" : la barre s'enfonçait dans la page au lieu de
       flotter au-dessus. Le bandeau gris est aussi ce qui SÉPARE l'en-tête
       du contenu ; sans lui le premier titre de section semble collé aux
       onglets. »
   J'avais posé un en-tête blanc avec une barre blanche : l'ombre ne
   portait sur rien et les deux se confondaient. */
.ab-header {
  position: sticky; top: 0; z-index: var(--ab-z);
  /* ⚠️ LE FOND DE LA PAGE, PAS UN GRIS (Elia, 27/08) : « il y a encore en haut
     le header avec une couleur différente […] je veux juste que ce soit noir
     normal. Regarde bien sûr toutes les pages, je ne veux plus voir ça. »
     `--deca-bg` et non `#000` en dur : en sombre c'est le noir demandé, en
     clair c'est le blanc de la page. Un noir en dur ferait une bande noire
     au-dessus d'une page blanche. */
  background: var(--deca-bg);
  /* Le filet n'existe qu'au défilement : en haut de page Airbnb n'en a pas.
     On garde une bordure transparente pour ne pas décaler d'1px au moment
     où .scrolled arrive. */
  border-bottom: 1px solid transparent;
  transition: border-color var(--ab-ease), box-shadow var(--ab-ease);
  /* index.html déclare viewport-fit=cover : en PWA plein écran l'encoche
     mordrait l'en-tête. Personne ne gère la safe-area en haut sur ce site. */
  padding-top: env(safe-area-inset-top, 0px);
  font-family: var(--ab-font);
  color: var(--ab-text);
  -webkit-font-smoothing: antialiased;
}
/* Plus de filet au défilement : c'était la « couleur différente » qui
   revenait dès qu'on descendait de 40 pixels. */
.ab-header.scrolled { border-bottom-color: transparent; }

/* Conteneur — sert aussi hors en-tête (rangées, pied de page, listes). */
.ab-wrap {
  width: 100%;
  max-width: var(--ab-wrap);
  margin: 0 auto;
  padding-left: var(--ab-gut);
  padding-right: var(--ab-gut);
}

/* ⚠️ LA BARRE EST AU-DESSUS DES ONGLETS, PAS EN DESSOUS (18/08).
   C'est l'ordre de l'app (`components/EnteteDeca.tsx` : barre de
   recherche, PUIS la rangée d'onglets) et c'est ce qu'Elia décrit —
   « la barre très clean de recherche, puis en dessous les catégories
   avec leur image 3D ». Airbnb fait l'inverse (onglets puis pilule) ;
   ici c'est l'app qui fait foi, pas Airbnb. */
/* ⚠️ La colonne du milieu est une PISTE EXPLICITE `minmax(0,560px)`, pas
   `auto` (18/08). En `auto`, la piste se dimensionne sur le contenu : la
   barre demandait 560px et n'en obtenait que 250 — la largeur de son
   texte. Mesuré au navigateur. Avec une piste bornée, la barre prend
   100 % de sa colonne et rétrécit proprement sur petit écran. */
.ab-header .ab-wrap {
  display: grid;
  grid-template-columns: 1fr minmax(0, 560px) 1fr;
  grid-template-areas:
    "brand search right"
    "tabs  tabs   tabs";
  align-items: center;
  column-gap: 16px;
}
.ab-header.small .ab-wrap {
  /* Replié : les onglets s'effacent, il ne reste que la ligne du haut. */
  grid-template-areas: "brand search right";
}

.ab-brand {
  grid-area: brand; justify-self: start; align-self: center;
  height: var(--ab-h); display: flex; align-items: center;
  font: 800 21px/1 var(--ab-font); letter-spacing: -.03em;
  color: var(--ab-text); text-decoration: none;
}
.ab-brand img, .ab-brand svg { height: 32px; width: auto; display: block; } /* logo mesuré 102×32 */

/* ── Onglets de domaine (les 5 domaines DECA + « Tout voir ») ──
   Icône 3D 49×49 puis libellé à sa droite, soulignement 2px sous l'onglet
   actif. Les images sont celles du bundle iOS : img/domaines/*.png. */
/* ══ LA RANGÉE D'ONGLETS, RECOPIÉE DE L'APP (18/08) ══════════════════
   Modèle : `components/EnteteDeca.tsx`. Mesures reprises telles quelles —
   rangée `paddingTop:20 paddingBottom:7`, onglet `alignItems:center
   gap:3` avec l'illustration AU-DESSUS du libellé, dessin 42, libellé
   12.5, trait actif 2.5 de haut sur 60 % de l'onglet, filet de clôture.
   Les cinq onglets se PARTAGENT la largeur (`flex:1`), comme dans l'app
   depuis qu'ils sont étalés. */
.ab-tabs {
  grid-area: tabs; justify-self: stretch;
  display: flex; align-items: flex-end; gap: 0;
  position: relative;
  padding: 20px 8px 7px;
  max-width: 100%;
}
.ab-header.small .ab-tabs { display: none; }

/* ⚠️ PLUS DE FILET SOUS LES ONGLETS depuis le bandeau gris (18/08) :
   c'est le bord du bandeau qui sépare l'en-tête du contenu, et deux
   séparations superposées font une rayure. Le filet reviendrait si on
   repassait un jour l'en-tête en blanc. */

.ab-tab {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  flex: 1 1 0; min-width: 0;
  /* ⚠️ 14px EN BAS, PAS 8 (Elia, 27/08 soir : « la ligne, elle est trop près
     du nom, ça fait bizarre, il faut que tu la descendes un peu »). Le trait
     de l'onglet actif est un ::after posé à `bottom: 0` : c'est donc CE
     rembourrage qui écarte le libellé du trait, pas une marge sur le trait.
     Le besoin est apparu en retirant les dessins : sans eux, le libellé
     descend et venait toucher la ligne. */
  padding: 0 6px 14px;
  border: none; background: none; cursor: pointer;
  font: 500 12.5px/1.2 var(--ab-font); letter-spacing: -.01em;
  color: var(--ab-sec); white-space: nowrap;
  text-decoration: none;
  transition: color var(--ab-ease);
}
.ab-tab:hover { color: var(--ab-text); }
.ab-tab.on   { color: var(--ab-text); font-weight: 700; }
.ab-tab:focus-visible { outline: 2px solid var(--ab-text); outline-offset: -4px; border-radius: 8px; }

/* Trait de l'onglet actif : 60 % de sa largeur, centré, posé au FOND de la
   rangée (au-dessus du filet). En pseudo-élément — il marche sans JS. */
.ab-tab.on::after {
  content: ""; position: absolute; left: 20%; right: 20%; bottom: 0;
  height: 2.5px; border-radius: 2px; background: var(--ab-text);
}

/* ⛔ LES DESSINS DES ONGLETS SONT RETIRÉS PARTOUT (Elia, 27/08 soir) :
   « il y a encore les anciennes icônes, et ça ce n'est pas bien — je t'ai dit
   que je ne voulais pas d'icône ». Ils ne l'étaient que sur `guide.html` ;
   ils restaient sur la recherche et sur toutes les pages de liste.
   Les onglets sont donc des libellés seuls, comme dans l'app.
   ⚠️ La règle qui suit (l'illustration en couleur) devient sans effet, mais on
   la GARDE : elle porte la raison du choix d'origine, et c'est elle qu'on
   relira le jour où les dessins reviendront. */
.ab-tab-img { display: none; }

/* ⚠️ L'ILLUSTRATION RESTE EN COULEUR, MÊME INACTIVE. C'est écrit noir sur
   blanc dans `EnteteDeca` : « chez Airbnb les icônes restent en couleur
   sur les onglets inactifs, seul le LIBELLÉ grise. Une rangée d'icônes
   toutes grises donne une barre de filtres administrative ; les mêmes en
   couleur donnent une vitrine. » Le site les grisait (règle du 08/08) —
   c'est justement ce qui ne ressemblait pas à l'app. */
.ab-tab-img {
  width: 42px; height: 42px; object-fit: contain; flex: none;
  transition: transform var(--ab-ease);
}
.ab-tab:hover .ab-tab-img { transform: scale(1.06); }

/* Variante FACULTATIVE : trait qui glisse d'un onglet à l'autre (le mécanisme
   de .nav-ink d'index.html). Poser .ab-tabs.has-ink pour éteindre le trait
   statique, et laisser le JS positionner .ab-ink en transform/width. */
.ab-tabs.has-ink .ab-tab.on::after { display: none; }
.ab-ink {
  position: absolute; left: 0; bottom: 14px;
  height: 2px; width: 24px; border-radius: 2px;
  background: var(--ab-text); opacity: 0;
  transition: transform .28s cubic-bezier(.3,.8,.3,1),
              width .28s cubic-bezier(.3,.8,.3,1), opacity .15s ease;
}
.ab-ink.on { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .ab-ink { transition: opacity .15s ease; } }

/* ── Bloc de droite ── */
.ab-right {
  grid-area: right; justify-self: end;
  height: var(--ab-h);
  display: flex; align-items: center; gap: 8px;
  position: relative;      /* ⚠️ ancre de .ab-menu — ne pas retirer */
}

/* « Devenir hôte » chez Airbnb → « Espace pro » chez Decarmy (pro.html). */
.ab-pro-link {
  display: inline-flex; align-items: center; height: 40px; padding: 0 14px;
  border-radius: var(--ab-rfull);
  font: 600 14px var(--ab-font); color: var(--ab-text);
  text-decoration: none; white-space: nowrap;
  transition: background var(--ab-ease);
}
.ab-pro-link:hover { background: var(--ab-grey); }

/* Rond 40px — avatar, globe/langue, tout bouton d'icône de l'en-tête. */
.ab-round {
  width: 40px; height: 40px; flex: none;
  border: none; border-radius: 50%;
  /* Pastille transparente : sur un en-tête devenu noir, un rond `--ab-grey`
     (#1C1C1E) est exactement la teinte parasite qu'on vient de retirer.
     Le fond ne réapparaît qu'au survol — le bouton reste un bouton. */
  background: transparent; color: var(--ab-text);
  display: grid; place-items: center; cursor: pointer;
  padding: 0; overflow: hidden;
  transition: background var(--ab-ease);
}
.ab-round:hover { background: var(--ab-grey-fort); }
.ab-round svg { width: 20px; height: 20px; }
.ab-round img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ab-round:focus-visible { outline: 2px solid var(--ab-text); outline-offset: 2px; }

/* Burger : même rond, mais bordé (mesure Airbnb : 1px #DDDDDD sur fond blanc). */
.ab-burger { background: var(--ab-white); border: 1px solid var(--ab-line-fort); }
.ab-burger:hover { background: var(--ab-grey); }


/* ══════════════════════════════════════════════════════════════════════════
   §3 — PILULE DE RECHERCHE : OÙ / QUOI / QUAND
   ⚠️ Ce ne sont PAS les segments d'Airbnb (Où/Quand/Qui). Decarmy ne réserve
   pas de nuits : « Quand » veut dire « ouvert maintenant », décision d'Elia
   du 04/08 reprise de app/rechercher.tsx. Ne pas y remettre de dates.
   Déployée : 850×66, radius 32. Repliée (.ab-header.small) : ~380×46.
   ══════════════════════════════════════════════════════════════════════════ */
/* ══ LA BARRE SIMPLE — LE MODÈLE DE L'APP (18/08) ═══════════════════════
   Elia a supprimé le panneau Où/Quoi/Quand de l'app le 18/08 : « elle a
   maintenant deux fonctions […] et du coup on supprime l'ancien truc pour
   la rendre très simple ». Une barre, deux usages : un LIEU (« Paris ») ou
   une CHOSE (« rénovation »). Dessin repris de `EnteteDeca` : h56, rayon
   28, blanc, ombre .1/12/0-3, contenu CENTRÉ — la loupe et le texte
   groupés au MILIEU, pas collés à gauche (« aligné à gauche, l'écran
   paraît vide à droite »).
   Les règles `.ab-search` qui suivent appartiennent à la pilule à trois
   segments, désormais sans appelant : gardées le temps de vérifier que
   plus rien ne l'invoque. */
.ab-bar {
  grid-area: search;
  justify-self: stretch; align-self: center;
  width: 100%;
  height: 56px;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  padding: 0 18px;
  background: var(--ab-white);
  border: none;
  border-radius: 28px;
  box-shadow: 0 3px 12px rgba(0,0,0,.10);
  transition: box-shadow var(--ab-ease), height .22s var(--ab-ease), width .22s var(--ab-ease);
}
.ab-bar:hover, .ab-bar:focus-within { box-shadow: 0 4px 16px rgba(0,0,0,.14); }
.ab-bar-ic { width: 18px; height: 18px; flex: none; color: var(--ab-text); }
/* ⚠️ LE CHAMP NE PREND PAS TOUTE LA LARGEUR AU REPOS, ET C'EST LE POINT.
   Avec `width:100%`, la loupe est plaquée à gauche et le texte centré :
   les deux se retrouvent séparés par 200px de vide. Dans l'app, loupe et
   texte forment UN groupe centré (« la barre a son contenu CENTRÉ, pas
   aligné à gauche »). Le champ se dimensionne donc sur son texte au
   repos, et ne s'étale qu'une fois qu'on écrit dedans. */
.ab-bar-champ {
  flex: 0 1 auto; min-width: 0; width: 29ch; max-width: 100%;
  border: none; background: none; outline: none; padding: 0;
  font: 600 15.5px/1 var(--ab-font);   /* 15,5/600 : la mesure d'EnteteDeca */
  color: var(--ab-text); text-align: center;
}
.ab-bar-champ::placeholder { color: var(--ab-sec); font-weight: 500; }
/* Le champ prend toute la place dès qu'on écrit dedans : le texte saisi
   s'aligne à gauche, seul le PLACEHOLDER est centré (motif de l'app, où la
   barre fermée est un faux bouton centré et le champ ouvert un vrai champ). */
.ab-bar-champ:focus { text-align: left; flex: 1 1 auto; width: 100%; }
.ab-bar-champ::-webkit-search-cancel-button { -webkit-appearance: none; }

/* Repliée : plus courte, plus basse — même logique que l'app. */
.ab-header.small .ab-bar { height: 44px; max-width: 380px; justify-self: center; }
.ab-header.small .ab-bar-champ { font-size: 14px; }

.ab-search {
  grid-area: search;
  justify-self: center; align-self: center;
  width: min(850px, 100%);
  height: 66px;
  margin: 0 auto 20px;
  display: flex; align-items: center;
  background: var(--ab-white);
  border: 1px solid var(--ab-line-fort);
  border-radius: var(--ab-r32);
  box-shadow: var(--ab-sh-pill);
  padding: 0 8px 0 0;
  transition: box-shadow var(--ab-ease), height .22s var(--ab-ease),
              width .22s var(--ab-ease);
}
.ab-search:hover { box-shadow: var(--ab-sh-pill-h); }

/* Un segment = libellé 12/600 puis valeur 14/400 grise. */
.ab-seg {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; justify-content: center; gap: 2px;
  height: 100%; padding: 0 24px;
  border: none; background: none; cursor: pointer; text-align: left;
  border-radius: var(--ab-r32);
  font-family: var(--ab-font);
  transition: background var(--ab-ease);
}
/* Le segment « Où » est le plus large (mesuré 278px sur 850). */
.ab-seg:first-child { flex-grow: 1.5; }
.ab-seg:hover { background: var(--ab-grey); }
.ab-seg.on { background: var(--ab-white); box-shadow: var(--ab-sh-pill); }
.ab-seg:focus-visible { outline: 2px solid var(--ab-text); outline-offset: -2px; }

.ab-seg-label { font: 600 12px/1.2 var(--ab-font); color: var(--ab-text); }
.ab-seg-val {
  font: 400 14px/1.3 var(--ab-font); color: var(--ab-sec);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ab-seg-val.filled { color: var(--ab-text); }   /* valeur choisie ≠ placeholder */
/* Un <input> peut remplacer .ab-seg-val sans rien casser. */
.ab-seg input {
  border: none; background: none; padding: 0; width: 100%;
  font: 400 14px/1.3 var(--ab-font); color: var(--ab-text);
}
.ab-seg input::placeholder { color: var(--ab-sec); }
.ab-seg input:focus { outline: none; }

.ab-seg-sep { width: 1px; height: 32px; flex: none; background: var(--ab-line); }
/* Le filet disparaît au survol des segments qui l'entourent (détail Airbnb). */
.ab-seg:hover + .ab-seg-sep,
.ab-seg-sep:has(+ .ab-seg:hover) { background: transparent; }

/* Rond de recherche — NOIR, jamais le rouge Airbnb. */
.ab-go {
  width: 48px; height: 48px; flex: none; margin-left: 4px;
  border: none; border-radius: 50%;
  background: var(--ab-cta); color: var(--ab-white);
  display: grid; place-items: center; cursor: pointer;
  transition: background var(--ab-ease), transform .12s;
}
.ab-go:hover  { background: var(--ab-cta-h); }
.ab-go:active { transform: scale(.94); }
.ab-go svg { width: 18px; height: 18px; }
.ab-go:focus-visible { outline: 2px solid var(--ab-text); outline-offset: 2px; }

/* ── Variante REPLIÉE ── */
.ab-header.small .ab-search {
  /* ⚠️ `min-width`, pas seulement `width` (18/08). La pilule est un élément
     de grille dont la piste est dimensionnée sur le CONTENU : `width:min(380px,
     100%)` s'y résolvait circulairement et la pilule prenait la largeur de son
     texte — 380px tant que les valeurs étaient longues, 262px dès qu'on les a
     raccourcies. `min-width` force la piste, mesuré 380px dans les deux cas. */
  width: 380px;
  min-width: 380px;
  max-width: 100%;
  height: 46px;
  margin: 0;
  padding-right: 5px;
  box-shadow: var(--ab-sh-pill);
}
.ab-header.small .ab-seg { padding: 0 16px; gap: 0; }
.ab-header.small .ab-seg:first-child { flex-grow: 1.2; }
.ab-header.small .ab-seg-label { display: none; }   /* une seule ligne condensée */
.ab-header.small .ab-seg-val,
.ab-header.small .ab-seg input { font: 500 14px/1 var(--ab-font); color: var(--ab-text); }

/* ⚠️ DEUX LONGUEURS DE VALEUR, LE CSS TRANCHE (18/08).
   Repliée, la pilule fait 380px : ~107px par segment. « Tous les domaines »
   et « N'importe quand » s'y affichaient « Tous les… » / « N'import… »
   (mesuré au navigateur). `airbnb-chrome.js` émet, quand elles diffèrent,
   une seconde valeur courte ; on montre l'une OU l'autre selon l'état. Le
   JS n'a rien à re-peindre au défilement. Quand la personne a CHOISI une
   valeur, le script n'émet pas de version courte : son choix s'affiche
   entier dans les deux états.

   ⚠️ La bascule est conditionnée à `:has(.ab-seg-val-court)` : le segment
   « Où » n'a JAMAIS de version courte (« Partout » tient déjà), et une
   règle inconditionnelle le vidait complètement — vu à l'écran, premier
   segment blanc et les deux autres réduits à « T… » / « Q… ». */
.ab-seg-val-court { display: none; }
.ab-header.small .ab-seg:has(.ab-seg-val-court) .ab-seg-val:not(.ab-seg-val-court) { display: none; }
.ab-header.small .ab-seg-val-court { display: block; }
.ab-header.small .ab-seg-sep { height: 22px; }
.ab-header.small .ab-go { width: 32px; height: 32px; margin-left: 2px; }
.ab-header.small .ab-go svg { width: 14px; height: 14px; }


/* ══════════════════════════════════════════════════════════════════════════
   §4 — MENU DÉROULANT (burger)
   320px, radius 12, ombre 0 10px 38px. Il DOIT être un enfant de .ab-right
   (son ancre en position:relative). L'en-tête est à z-index 1500 : le menu
   n'est plus prisonnier sous .mobile-menu (1200) comme l'était .dsh-menu.
   ══════════════════════════════════════════════════════════════════════════ */
.ab-menu {
  position: absolute; top: calc(100% - 12px); right: 0; z-index: 10;
  width: 320px; max-width: calc(100vw - 32px);
  background: var(--ab-white);
  border: 1px solid var(--ab-line);
  border-radius: var(--ab-r12);
  box-shadow: var(--ab-sh-menu);
  padding: 8px 0; overflow: hidden;
  font-family: var(--ab-font);
  opacity: 0; transform: translateY(-6px) scale(.98); transform-origin: top right;
  pointer-events: none;
  transition: opacity .15s ease, transform .15s ease;
}
.ab-menu.on { opacity: 1; transform: none; pointer-events: auto; }

.ab-menu a, .ab-menu .ab-menu-item {
  display: flex; align-items: center; gap: 12px; width: 100%;
  min-height: 44px; padding: 11px 18px;
  border: none; background: none; cursor: pointer; text-align: left;
  font: 500 15px var(--ab-font); color: var(--ab-text); text-decoration: none;
  transition: background var(--ab-ease);
}
.ab-menu a:hover, .ab-menu .ab-menu-item:hover { background: var(--ab-grey); }
.ab-menu-ic { width: 18px; height: 18px; flex: none; color: var(--ab-sec); }

.ab-sep { height: 1px; background: var(--ab-line); margin: 8px 0; border: 0; }

/* Bloc « Espace pro » en bas du menu : titre gras + 2 lignes grises 13px,
   illustration à droite. C'est le « Devenir hôte » d'Airbnb. */
.ab-pro-bloc {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 18px; text-decoration: none;
}
.ab-pro-bloc > div { flex: 1 1 auto; min-width: 0; }
.ab-pro-bloc strong { display: block; font: 700 15px var(--ab-font); color: var(--ab-text); }
.ab-pro-bloc span   { display: block; margin-top: 3px; font: 400 13px/1.45 var(--ab-font); color: var(--ab-sec); }
.ab-pro-bloc img    { width: 44px; height: 44px; flex: none; object-fit: contain; }


/* ══════════════════════════════════════════════════════════════════════════
   §5 — RANGÉES ET CARTES (l'accueil, façon carrousel Airbnb)
   ══════════════════════════════════════════════════════════════════════════ */
.ab-row { padding: 28px 0 8px; font-family: var(--ab-font); }

.ab-row-h {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; margin-bottom: 16px;
}
/* Le titre de section. Fonctionne sur un <h2> ou un <a>. */
.ab-row-t {
  display: inline-flex; align-items: center; gap: 8px;
  font: 600 22px/1.2 var(--ab-font); letter-spacing: -.02em;
  color: var(--ab-text); text-decoration: none;
}
/* Petite flèche ronde qui suit le titre quand la section est cliquable. */
.ab-row-go {
  width: 26px; height: 26px; flex: none;
  border-radius: 50%; background: var(--ab-grey);
  display: grid; place-items: center; color: var(--ab-text);
  transition: background var(--ab-ease), transform var(--ab-ease);
}
.ab-row-t:hover .ab-row-go { background: var(--ab-grey-fort); transform: translateX(2px); }
.ab-row-go svg { width: 13px; height: 13px; }

/* Les deux flèches ‹ › à droite du titre. */
.ab-arrows { display: flex; gap: 8px; flex: none; }
.ab-arrow {
  width: 32px; height: 32px;
  border: 1px solid var(--ab-line-fort); border-radius: 50%;
  background: var(--ab-white); color: var(--ab-text);
  display: grid; place-items: center; cursor: pointer;
  transition: background var(--ab-ease), border-color var(--ab-ease), opacity var(--ab-ease);
}
.ab-arrow:hover { background: var(--ab-grey); border-color: var(--ab-text); }
.ab-arrow svg { width: 12px; height: 12px; }
.ab-arrow[disabled] { opacity: .3; pointer-events: none; }
.ab-arrow:focus-visible { outline: 2px solid var(--ab-text); outline-offset: 2px; }

/* Le carrousel. 6 cartes visibles à 1280 (193 + 12 de gap). */
.ab-rail {
  display: flex; gap: var(--ab-gap);
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scroll-padding-inline: 0;
  /* La marge négative + le padding font respirer l'ombre des cartes sans
     décaler le premier élément par rapport au titre. */
  padding-bottom: 4px;
  scrollbar-width: none; -ms-overflow-style: none;
}
.ab-rail::-webkit-scrollbar { display: none; }
.ab-rail > .ab-card { flex: 0 0 var(--ab-card-w); scroll-snap-align: start; }
@media (prefers-reduced-motion: reduce) { .ab-rail { scroll-behavior: auto; } }

/* ── LA CARTE (identique en rangée et en grille) ── */
.ab-card {
  position: relative; display: block;
  color: var(--ab-text); text-decoration: none;
  font-family: var(--ab-font);
  min-width: 0;
}
.ab-card:focus-visible { outline: 2px solid var(--ab-text); outline-offset: 4px; border-radius: var(--ab-r12); }

/* Ratio 20/19 mesuré chez Airbnb (193×183). `aspect-ratio` évite le padding-hack. */
.ab-card-img {
  position: relative; display: block;
  width: 100%; aspect-ratio: 20 / 19;
  border-radius: var(--ab-r12); overflow: hidden;
  background: var(--ab-grey);   /* aplat pendant le chargement, pas de saut */
}
.ab-card-img img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .35s cubic-bezier(.2,.6,.2,1);
}
.ab-card:hover .ab-card-img img { transform: scale(1.04); }

/* Cœur en haut à DROITE de la photo.
   ⚠️ Pas de rouge : #FF385C est banni. « Enregistré » = cœur NOIR plein. */
.ab-heart {
  position: absolute; top: 8px; right: 8px; z-index: 2;
  width: 32px; height: 32px; padding: 0;
  border: none; background: none; cursor: pointer;
  display: grid; place-items: center;
  transition: transform .12s;
}
.ab-heart:active { transform: scale(.88); }
.ab-heart svg {
  width: 24px; height: 24px;
  fill: rgba(0,0,0,.32); stroke: var(--deca-bg); stroke-width: 2;
  transition: fill var(--ab-ease);
}
.ab-heart:hover svg { fill: rgba(0,0,0,.5); }
.ab-heart.on svg { fill: var(--ab-text); stroke: var(--deca-bg); }
.ab-heart:focus-visible { outline: 2px solid #fff; outline-offset: -2px; border-radius: 50%; }

/* Pilule blanche en haut à GAUCHE (« Coup de cœur voyageurs » chez Airbnb ;
   chez nous : « Vérifié », « Nouveau », « Vegan strict »…). */
.ab-badge {
  position: absolute; top: 8px; left: 8px; z-index: 2;
  padding: 5px 10px;
  background: var(--ab-white); color: var(--ab-text);
  font: 600 12px/1 var(--ab-font);
  border-radius: var(--ab-rfull);
  box-shadow: var(--ab-sh-card);
  white-space: nowrap; max-width: calc(100% - 56px);
  overflow: hidden; text-overflow: ellipsis;
}

/* Trois lignes sous la photo.
   ⚠️ Le modèle de données du site n'a NI note d'avis NI prix en euros
   (vérifié : `rating` n'existe nulle part, `price` est un niveau 1-3).
   .ab-card-p doit donc porter €/€€/€€€, l'état ouvert/fermé ou la distance —
   jamais un « ★ 4,8 · 92 € » qui serait inventé. */
.ab-card-t {
  margin-top: 8px;
  font: 600 14px/1.35 var(--ab-font); color: var(--ab-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ab-card-s {
  margin-top: 2px;
  font: 400 14px/1.35 var(--ab-font); color: var(--ab-sec);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ab-card-p {
  margin-top: 4px;
  font: 400 14px/1.35 var(--ab-font); color: var(--ab-text);
}
.ab-card-p b, .ab-card-p strong { font-weight: 600; }
/* État ouvert / fermé, quand osm_hours existe (176 fiches sur 843). */
.ab-card-p .ab-open   { color: #2E7D4F; font-weight: 600; }
.ab-card-p .ab-closed { color: var(--ab-sec); }


/* ══════════════════════════════════════════════════════════════════════════
   §6 — GRILLE (pages de liste : la MÊME carte, sans carrousel)
   gap 24 vertical / 12 horizontal, colonnes fluides à partir de 193px.
   ══════════════════════════════════════════════════════════════════════════ */
.ab-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--ab-card-w), 1fr));
  gap: 24px var(--ab-gap);
  align-items: start;
}


/* ══════════════════════════════════════════════════════════════════════════
   §7 — FICHE
   ⚠️⚠️ TOUT ICI EST PORTÉ PAR `.ab-fiche`. C'est OBLIGATOIRE : detail-airbnb.css
   possède déjà un `.ab-actions` nu (le bloc CTA collant des 4 *-detail.html).
   Sans l'ancêtre `.ab-fiche`, les deux feuilles se marchent dessus.
   ══════════════════════════════════════════════════════════════════════════ */
.ab-fiche {
  max-width: var(--ab-fiche-w);
  margin: 0 auto;
  padding: 24px var(--ab-gut) 64px;
  font-family: var(--ab-font); color: var(--ab-text);
}

/* Ligne de titre : h1 à gauche, Partager / Enregistrer à droite. */
.ab-fiche-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 24px; margin-bottom: 16px;
}
.ab-fiche .ab-fiche-t,
.ab-fiche h1 {
  font: 500 26px/1.25 var(--ab-font); letter-spacing: -.02em;
  color: var(--ab-text); margin: 0;
  /* Airbnb ne centre jamais son h1, et il est en 500 — pas en 700. */
  text-align: left;
}

.ab-fiche .ab-actions { display: flex; align-items: center; gap: 4px; flex: none; }
.ab-act {
  display: inline-flex; align-items: center; gap: 8px;
  height: 40px; padding: 0 10px;
  border: none; background: none; cursor: pointer;
  border-radius: var(--ab-r12);
  font: 500 14px var(--ab-font); color: var(--ab-text); text-decoration: none;
  transition: background var(--ab-ease);
}
.ab-act:hover { background: var(--ab-grey); }
.ab-act span  { text-decoration: underline; text-underline-offset: 2px; }
.ab-act svg   { width: 16px; height: 16px; flex: none; }
.ab-act:focus-visible { outline: 2px solid var(--ab-text); outline-offset: 2px; }

/* ── Galerie : 1 grande à gauche + 4 petites en 2×2 à droite ──
   Les coins arrondis viennent du conteneur (overflow:hidden) : c'est ainsi
   que seuls les 4 coins EXTÉRIEURS sont arrondis, sans quatre règles
   :nth-child fragiles. */
.ab-gallery {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(2, 1fr);
  gap: 8px;
  aspect-ratio: 1120 / 580;
  border-radius: var(--ab-r12);
  overflow: hidden;
  background: var(--ab-grey);
}
.ab-gallery > * { position: relative; margin: 0; overflow: hidden; }
.ab-gallery > *:first-child { grid-column: 1 / 3; grid-row: 1 / 3; }
.ab-gallery img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: filter var(--ab-ease);
}
.ab-gallery a:hover img, .ab-gallery button:hover img { filter: brightness(.9); }
/* Moins de 5 photos : la grande occupe tout, les vides ne laissent pas de trou. */
.ab-gallery.solo { grid-template-columns: 1fr; grid-template-rows: 1fr; }
.ab-gallery.solo > *:first-child { grid-column: 1; grid-row: 1; }

.ab-gallery-all {
  position: absolute; right: 16px; bottom: 16px; z-index: 2;
  display: inline-flex; align-items: center; gap: 8px;
  height: 36px; padding: 0 14px;
  background: var(--ab-white); color: var(--ab-text);
  border: 1px solid var(--ab-text); border-radius: var(--ab-r12);
  font: 600 13px var(--ab-font); cursor: pointer;
  box-shadow: var(--ab-sh-card);
  transition: background var(--ab-ease);
}
.ab-gallery-all:hover { background: var(--ab-grey); }
.ab-gallery-all svg { width: 14px; height: 14px; }

/* ── Corps en 2 colonnes : contenu + carte collante ── */
.ab-fiche-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--ab-book-w);
  gap: clamp(32px, 5vw, 72px);
  margin-top: 32px;
  align-items: start;
}
.ab-fiche-main { min-width: 0; }

.ab-book {
  position: sticky;
  /* 80px d'en-tête + 24 de respiration : la carte ne passe jamais dessous. */
  top: calc(var(--ab-h) + 24px);
  border: 1px solid var(--ab-line);
  border-radius: var(--ab-r16);
  box-shadow: var(--ab-sh-pill);
  padding: 24px;
  background: var(--ab-white);
}
/* ⚠️ Decarmy ne réserve pas de nuits sur le site : cette carte porte les
   actions (itinéraire, site, appeler, contribuer), PAS un prix par nuit. */
.ab-book > * + * { margin-top: 12px; }


/* ══════════════════════════════════════════════════════════════════════════
   §8 — PIED DE PAGE
   ⚠️ styles.css:177 masque tout <footer> en mode app (html.deca-app) : ce
   pied de page n'est vu QU'EN DESKTOP WEB. Inutile de l'optimiser mobile.
   ══════════════════════════════════════════════════════════════════════════ */
.ab-foot {
  /* Même règle que l'en-tête : le pied ne porte plus sa propre teinte. Le
     filet du haut reste, lui — il sépare sans colorer. */
  background: var(--deca-bg);
  border-top: 1px solid var(--ab-line);
  margin-top: 64px;
  font-family: var(--ab-font); color: var(--ab-text);
}
.ab-foot-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 32px;
  padding: 48px 0;
}
.ab-foot-col { min-width: 0; }
.ab-foot-title { font: 600 14px var(--ab-font); margin: 0 0 12px; color: var(--ab-text); }
.ab-foot-list { list-style: none; margin: 0; padding: 0; }
.ab-foot-list li { margin-bottom: 10px; }
.ab-foot-list a {
  font: 400 14px var(--ab-font); color: var(--ab-sec); text-decoration: none;
  transition: color var(--ab-ease);
}
.ab-foot-list a:hover { color: var(--ab-text); text-decoration: underline; }

.ab-foot-bottom {
  border-top: 1px solid var(--ab-line);
  padding: 24px 0;
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
  font: 400 14px var(--ab-font); color: var(--ab-sec);
}
.ab-foot-legal { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ab-foot-legal a { color: var(--ab-sec); text-decoration: none; }
.ab-foot-legal a:hover { text-decoration: underline; color: var(--ab-text); }
.ab-foot-legal span { color: var(--ab-tert); }   /* le séparateur « · » */

/* Sélecteur fr / en / it à droite de la barre du bas.
   ⚠️ Il ne doit PAS créer un 4ᵉ sélecteur de langue : câbler celui qui
   existe (lang.js / window.decaApply), pas un nouveau. */
.ab-foot-lang {
  display: inline-flex; align-items: center; gap: 8px;
  height: 40px; padding: 0 14px;
  border: 1px solid var(--ab-line-fort); border-radius: var(--ab-rfull);
  background: transparent; cursor: pointer;
  font: 600 14px var(--ab-font); color: var(--ab-text);
  transition: background var(--ab-ease);
}
.ab-foot-lang:hover { background: var(--ab-grey-fort); }
.ab-foot-lang svg { width: 16px; height: 16px; }


/* ══════════════════════════════════════════════════════════════════════════
   §9 — RESPONSIVE
   Trois zones :
     ≤767px   le site garde l'interface d'APP (barre d'onglets, en-tête
              legacy) — décision d'Elia du 15/08. L'en-tête Airbnb DISPARAÎT.
     768-1100 gabarit tassé : moins de colonnes, pilule fluide.
     ≥1101    le gabarit mesuré à 1280.
   ⚠️ Tout se joue en @media. bottom-nav.js mesure IS_MOBILE_WEB UNE FOIS,
   sans listener de resize : une bascule par JS ne se rejouerait jamais.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 768 → 1100 : en-tête tassé ── */
@media (max-width: 1100px) {
  :root { --ab-gut: 24px; }
  .ab-header .ab-wrap { column-gap: 12px; }
  /* ⚠️ 14px EN BAS ICI AUSSI : sans ça, cette media query (≤1100px) écrasait
     l'écartement posé plus haut et le trait revenait coller au libellé sur la
     plupart des fenêtres. Mesuré au navigateur le 27/08 : padding-bottom 8px
     au lieu de 14. */
  .ab-tab { padding: 0 8px 14px; font-size: 13px; }
  .ab-tab-img { width: 40px; height: 40px; }
  .ab-tab.on::after { left: 8px; right: 8px; }
  .ab-search { width: 100%; }
  .ab-seg { padding: 0 16px; }
  /* « Espace pro » cède la place avant les ronds : c'est le libellé le plus
     long et le moins critique (il reste dans le menu). */
  .ab-pro-link { display: none; }
}

/* ── 768 → 900 ──
   ⚠️ LA BARRE RESTE ENTRE LA MARQUE ET LE BURGER, À TOUTES LES LARGEURS
   (Elia, 18/08 : « il y a toujours un moment où la barre est en dessous
   comme ici »). Ce palier la faisait décrocher sur sa propre ligne entre
   768 et 900px — un troisième dessin d'en-tête, en plus du desktop et du
   mobile, et c'est celui-là qu'Elia est tombé dessus en réduisant sa
   fenêtre. Il n'y a plus que DEUX dessins : la ligne unique (marque,
   barre, burger) puis les onglets, du téléphone au grand écran. Seules
   les tailles changent. */
@media (max-width: 900px) {
  .ab-header .ab-wrap {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "brand search right"
      "tabs  tabs   tabs";
    column-gap: 12px;
    row-gap: 4px;
  }
  .ab-header.small .ab-wrap {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "brand search right";
  }
  .ab-tabs { justify-self: stretch; width: 100%; }
  .ab-bar { height: 48px; }
  .ab-search { margin-bottom: 12px; }
  .ab-header.small .ab-search { width: 100%; margin-bottom: 12px; }
  .ab-fiche-body { grid-template-columns: 1fr; }
  .ab-book { position: static; }
  .ab-gallery { aspect-ratio: 3 / 2; }
}

/* ── 768–900px : LE PALIER QUI MANQUAIT (18/08) ──────────────────────────
   Elia, fenêtre réduite : « les catégories deviennent trop serrées ». Entre
   768 et 1100 il n'y avait qu'UN palier, taillé pour 1100 : à 770px les cinq
   onglets se partageaient 146px chacun et le libellé se cognait au dessin.
   On rétrécit le DESSIN avant le TEXTE — un libellé illisible coûte plus
   qu'une illustration plus petite. */
@media (max-width: 900px) {
  .ab-header .ab-wrap { grid-template-columns: auto minmax(0, 1fr) auto; }
  .ab-tab-img { width: 34px; height: 34px; }
  .ab-tab { font-size: 12px; padding: 0 4px 8px; }
  .ab-tabs { padding: 14px 4px 7px; }
  .ab-bar { height: 50px; }
  .ab-brand { font-size: 19px; }
}

/* ── ≤767px : L'EN-TÊTE RESTE, IL SE MET À L'ÉCHELLE ─────────────────────
   ⚠️ RENVERSEMENT DU 18/08. Cette feuille masquait purement et simplement
   l'en-tête sous 767px (« le site garde son interface d'app »). Résultat
   constaté par Elia en réduisant sa fenêtre : « la 2ᵉ fois on ne voit même
   plus le header ». Sa demande est explicite — « il faut que ça reste comme
   quand c'est en plein écran mais en modifiant les dimensions ».
   Et c'est aussi ce que fait l'APP : `EnteteDeca` en haut ET `DecaTabBar` en
   bas, sur un téléphone. Les deux cohabitent, elles ne se remplacent pas.
   L'en-tête passe donc sur TROIS lignes : marque + ronds, la barre, les
   onglets — au lieu de disparaître. */
@media (max-width: 767px) {
  /* ⚠️ LA BARRE EST ENTRE LA MARQUE ET LE BURGER (Elia, 18/08 : « il
     faudrait que la barre de recherche soit entre "Decarmy" et le menu
     hamburger »). Elle occupait sa propre ligne, ce qui laissait un grand
     vide à droite de la marque — c'est ce vide qu'Elia a entouré en rouge.
     Une seule ligne, donc, exactement comme en desktop. */
  .ab-header .ab-wrap {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "brand search right"
      "tabs  tabs   tabs";
    column-gap: 10px;
    row-gap: 4px;
    padding-top: 6px;
  }
  .ab-brand { height: auto; font-size: 17px; }
  .ab-bar { height: 42px; padding: 0 12px; gap: 7px; }
  .ab-bar-ic { width: 16px; height: 16px; }
  /* Le champ prend la largeur qu'on lui laisse : entre la marque et le
     burger il n'en reste pas assez pour un placeholder de 29 caractères.
     Le chrome pose un placeholder COURT sous 640px (`ab.bar.ph.court`). */
  .ab-bar-champ { font-size: 14px; width: 100%; text-align: left; }

  /* ⚠️ LES CINQ ONGLETS SE PARTAGENT LA LARGEUR À PARTS ÉGALES (Elia,
     18/08 : « elle doit prendre la même place que les autres, là ce n'est
     pas le cas »). Ils étaient en `flex: 0 0 auto` + défilement : chaque
     onglet prenait la largeur de SON libellé, donc « Communs » plus que
     « Repas ». `flex: 1 1 0` leur donne la même colonne, comme en desktop
     et comme dans l'app (`onglet: { flex: 1 }`, EnteteDeca). */
  .ab-tabs { padding: 8px 0 6px; }
  .ab-tab { flex: 1 1 0; min-width: 0; font-size: 11px; padding: 0 2px 8px; }
  .ab-tab-img { width: 30px; height: 30px; }
  /* Un libellé trop long pour sa colonne s'ellipse au lieu de la faire
     grossir — c'est la colonne qui commande, pas le mot. */
  .ab-tab > span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
  /* Le rond de langue et l'avatar cèdent la place ; le burger reste, il
     contient tout le reste. */
  .ab-right > [data-ab-lang], .ab-right > #ab-avatar { display: none; }

  /* Les listes restent lisibles en DEUX colonnes — pas une par carte. */
  .ab-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 20px 12px;
  }
  /* En carrousel, une carte occupe 44 % : la suivante dépasse et signale
     qu'on peut faire défiler. */
  .ab-rail > .ab-card { flex-basis: 44vw; }

  .ab-row { padding: 20px 0 4px; }
  .ab-row-t { font-size: 19px; }
  .ab-arrows { display: none; }          /* on fait défiler au doigt */

  .ab-fiche { padding: 16px 16px 48px; }
  .ab-fiche-head { flex-direction: column; align-items: flex-start; gap: 8px; }
  .ab-fiche .ab-fiche-t, .ab-fiche h1 { font-size: 22px; }
  .ab-gallery { aspect-ratio: 4 / 3; border-radius: 0; margin: 0 -16px; }
  .ab-gallery > *:not(:first-child) { display: none; }
  .ab-gallery { grid-template-columns: 1fr; grid-template-rows: 1fr; }
  .ab-gallery > *:first-child { grid-column: 1; grid-row: 1; }
}

/* Très petits écrans : une carte par ligne en grille reste préférable à
   deux colonnes illisibles sous 380px. */
@media (max-width: 379px) {
  .ab-grid { grid-template-columns: 1fr; }
}

/* Impression : ni en-tête collant, ni carrousel. */
@media print {
  .ab-header, .ab-arrows, .ab-heart, .ab-go { display: none !important; }
  .ab-rail { overflow: visible; flex-wrap: wrap; }
}


/* ══════════════════════════════════════════════════════════════════════════
   §10 — ⚠️ SEUL BLOC QUI SORT DU PRÉFIXE `ab-` ⚠️
   Neutralisation des en-têtes maison quand le nouvel en-tête est en place.
   Il faut poser `body.ab-on` sur la page — c'est l'INTERRUPTEUR : sans lui,
   ce fichier ne modifie rien d'existant.

   Les trois en-têtes visés :
     #header + .mobile-menu → le legacy DECA, présent dans 73 pages
     .nav                   → l'en-tête inline d'index.html
     .dsh                   → l'en-tête injecté par bottom-nav.js (buildSite)
   ⚠️ Retirer .dsh du DOM n'est PAS une option : buildSite() porte aussi la
   modale d'authentification, auth.css et l'import d'auth.js. On le masque,
   on ne l'empêche pas de se construire.

   ⚠️⚠️ TOUT EST BORNÉ À ≥768px. Sous 767px le site garde son interface d'app
   (en-tête legacy + barre d'onglets) : y masquer #header laisserait les pages
   sans aucune navigation. C'est la faute la plus facile à commettre ici.
   ══════════════════════════════════════════════════════════════════════════ */
/* ⚠️ LA BORNE ≥768px A SAUTÉ LE 18/08. Elle existait parce que l'en-tête
   Airbnb disparaissait sous 767px : masquer AUSSI le `#header` legacy aurait
   laissé les pages sans aucune navigation. Maintenant que l'en-tête reste à
   toutes les largeurs (bloc ≤767px ci-dessus), la raison d'être de la borne
   a disparu — et la garder produirait l'inverse : DEUX en-têtes empilés sur
   téléphone. La barre d'onglets du bas (`.deca-tabbar`) n'est pas dans cette
   liste et reste intacte : c'est elle, l'interface d'app. */
body.ab-on #header,
body.ab-on .mobile-menu,
body.ab-on .nav,
body.ab-on .dsh { display: none !important; }

/* ⚠️ LE BOUTON RETOUR FLOTTANT de bottom-nav.js CHEVAUCHAIT LA MARQUE
   (18/08, constaté à 390px) : il est posé en haut à gauche, exactement là
   où le nouvel en-tête écrit « Decarmy ». Il existait pour les pages qui
   n'avaient aucune navigation sur téléphone — ce n'est plus le cas, l'en-tête
   y est maintenant, avec la marque qui ramène à l'accueil et le burger qui
   ouvre le reste. */
body.ab-on .deca-back-btn { display: none !important; }

/* ⚠️ LA BARRE D'ONGLETS DU BAS QUITTE LE SITE (Elia, 18/08 : « enlève la
   barre en bas, on est sur un site pas une app »). C'était le pari du
   15/08 — donner au site l'interface de l'app sur téléphone. Il tombe :
   un site a un en-tête et un pied de page, pas une tab bar.
   ⚠️ L'APPLICATION NATIVE N'EST PAS CONCERNÉE. `airbnb-chrome.js` sort
   immédiatement en Capacitor (`if (IS_NATIVE) return`, l. 56), donc
   `body.ab-on` n'existe jamais là-bas et cette règle ne s'y applique pas :
   la barre d'onglets de l'app reste intacte. Ne pas retirer cette garde en
   déplaçant la règle hors de `body.ab-on`.
   Le bouton « + » flottant reste : c'est le seul moyen d'ajouter un lieu
   depuis un téléphone, et le pied de page qui porte la même entrée est
   tout en bas de la page. */
body.ab-on .deca-tabbar { display: none !important; }

/* ⚠️ LE FOND BLANC SORT DE LA MEDIA QUERY (18/08). Il était borné à ≥768px
   du temps où l'en-tête n'existait pas sur téléphone ; le beige #e8e6e2 de
   styles.css revenait donc dès qu'on réduisait la fenêtre, et encadrait le
   gabarit Airbnb d'une bande beige. */
body.ab-on { background: var(--deca-bg) !important; }

@media (min-width: 768px) {

  /* (le fond blanc est remonté hors media query — voir plus haut) */
}


/* ══════════════════════════════════════════════════════════════════════════
   §11 — LES CATÉGORIES : PILULES N2, INTERTITRES N3, CASES RONDES N4
   Ajouté le 18/08/2026 pour la refonte de l'accueil (Elia : « comme sur
   l'app on ne montre plus les lieux mais les différentes catégories »).
   Modèle : `app/(tabs)/explore.tsx`, styles l. 2009-2017 et 2071-2088.
   Rendu par `accueil-explore.js` depuis `db/explorer.json`.

   ⚠️ POURQUOI DE NOUVELLES CLASSES ET PAS `.ab-grid` / `.ab-card` :
   `.ab-grid` est PARTAGÉE avec `recherche.html` (colonnes de 193px, taillées
   pour une photo au format 20/19) et `.ab-card` est un rectangle photo. Une
   case de catégorie est un rond de 64-72px avec deux lignes de texte : la
   grille des fiches ne peut pas la loger sans se déformer, et la déformer
   casserait la page de résultats. Rien n'est modifié ici, tout est ajouté.

   Noms vérifiés LIBRES dans les quatre feuilles du site (airbnb.css,
   airbnb-chrome.js, detail-airbnb.css, styles.css) avant écriture :
   ab-n2-rang · ab-n2s · ab-n2 · ab-fam · ab-fam-t · ab-cases · ab-case ·
   ab-case-rond · ab-case-img · ab-case-t · ab-case-nu · ab-case-off ·
   ab-liens · ab-liens-l.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── LES PILULES N2 (« Manger chez moi | Manger dehors ») ─────────────────
   Segmented control, pas une barre d'actions : `width` au TEXTE et centré,
   jamais pleine largeur — c'est un filtre. Mesures de l'app : conteneur
   radius 100 sur l'aplat gris, padding 3 ; pastille h32, padding 14 ;
   active = fond blanc + ombre légère, libellé 700 ; inactive 600 gris. */
.ab-n2-rang {
  display: flex; justify-content: center;
  padding: 20px 0 0;
  font-family: var(--ab-font);
}
.ab-n2s {
  display: inline-flex; align-items: center;
  max-width: 100%; padding: 3px; gap: 0;
  border-radius: var(--ab-rfull);
  background: var(--ab-grey);
  overflow: hidden;
}
.ab-n2 {
  height: 32px; padding: 0 14px; min-width: 0;
  border: none; border-radius: var(--ab-rfull); background: none;
  font: 600 13.5px/1 var(--ab-font); letter-spacing: -.01em;
  color: var(--ab-sec); cursor: pointer; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
  transition: background var(--ab-ease), color var(--ab-ease);
}
.ab-n2:hover { color: var(--ab-text); }
.ab-n2.on {
  background: var(--ab-white); color: var(--ab-text); font-weight: 700;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .10);
}
.ab-n2:focus-visible { outline: 2px solid var(--ab-text); outline-offset: -2px; }

/* ── L'INTERTITRE DE FAMILLE N3 (« SOURCING FOOD ») ───────────────────────
   12,5/700 en petites capitales grises, exactement `titreFamille` de l'app.
   ⚠️ Il existait déjà un équivalent sur le site — `.ab-souligne` — mais il
   vit dans le CSS que `airbnb-chrome.js` s'injecte à lui-même : s'en servir
   rendrait l'accueil dépendant du style privé de l'en-tête. Réécrit ici, à
   son nom. */
.ab-fam { padding-top: 22px; font-family: var(--ab-font); }
.ab-fam-t {
  margin: 0 0 10px;
  font: 700 12.5px/1.2 var(--ab-font);
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--ab-sec);
}

/* ── LA GRILLE DE CASES ───────────────────────────────────────────────────
   ⚠️ SUR TÉLÉPHONE : QUATRE PAR LIGNE, comme l'app (`rondCase: width 25%`).
   Sur grand écran, c'est la CASE qui garde sa taille et la ligne qui se
   remplit (≈9 cases à 1216px) : quatre cases de 288px de large pour un rond
   de 72px laisseraient quatre trous et un écran de haut par famille. Même
   rythme physique que l'app, plus de colonnes parce que l'écran est plus
   large — c'est ce que font les grilles de catégories d'Airbnb et d'Uber
   Eats. Pour forcer 4 partout, une seule ligne à changer :
   `grid-template-columns: repeat(4, minmax(0, 1fr));`. */
.ab-cases {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 18px 8px;
  align-items: start;
}

/* ── UNE CASE ─────────────────────────────────────────────────────────────
   Rond gris NEUTRE (jamais la couleur du domaine — c'est écrit tel quel dans
   l'app), dessin 3D contenu dedans, libellé centré sur deux lignes au plus. */
.ab-case {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 0 4px;
  color: var(--ab-text); text-decoration: none;
  font-family: var(--ab-font);
  min-width: 0;
}
.ab-case-rond {
  width: 72px; height: 72px; flex: none;
  border-radius: 50%; background: var(--ab-grey);
  display: grid; place-items: center; overflow: hidden;
  transition: background var(--ab-ease);
}
.ab-case-img {
  width: 44px; height: 44px; object-fit: contain; display: block;
  transition: transform var(--ab-ease);
}
.ab-case-t {
  font: 600 11.5px/1.25 var(--ab-font); letter-spacing: -.01em;
  color: var(--ab-text); text-align: center;
  /* Deux lignes au plus, comme `numberOfLines={2}` dans l'app : au-delà, les
     rangées de la grille ne s'alignent plus. */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
  overflow-wrap: anywhere;
}
a.ab-case:hover .ab-case-rond { background: var(--ab-grey-fort); }
a.ab-case:hover .ab-case-img  { transform: scale(1.06); }
a.ab-case:focus-visible {
  outline: 2px solid var(--ab-text); outline-offset: 4px;
  border-radius: var(--ab-r12);
}

/* Repli : une case sans dessin garde un rond gris NU. On ne détourne jamais
   l'illustration d'une autre catégorie — les 233 cases ont la leur
   aujourd'hui, cette règle est le filet pour demain. */
.ab-case-nu { background: var(--ab-grey-fort); }

/* Case INERTE : les 5 pétitions n'ont pas de page sur le site
   (`petitions.html` n'existe pas). Elles s'affichent — ce sont de vraies
   catégories de la taxonomie — mais elles ne cliquent pas, et le libellé
   passe en gris tertiaire pour le dire sans écrire « bientôt ». */
.ab-case-off { cursor: default; }
.ab-case-off .ab-case-t   { color: var(--ab-tert); }
.ab-case-off .ab-case-img { opacity: .75; }

/* ── LES SIX URL INDEXÉES ─────────────────────────────────────────────────
   Liens texte, pas un carrousel : leur seule raison d'être est le maillage
   interne des slugs servis par les réécritures Firebase Hosting. */
.ab-liens { padding: 34px 0 8px; font-family: var(--ab-font); }
.ab-liens-l {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 8px 20px;
}
.ab-liens-l a {
  font: 500 13.5px/1.4 var(--ab-font);
  color: var(--ab-sec); text-decoration: none;
}
.ab-liens-l a:hover { color: var(--ab-text); text-decoration: underline; }

/* ── RESPONSIVE ───────────────────────────────────────────────────────────
   Ces règles viennent APRÈS le §9 dans le fichier : à spécificité égale,
   c'est la dernière qui gagne. Tout ce qui concerne la grille tient donc
   ici, sans aller retoucher un bloc partagé plus haut. */
@media (max-width: 900px) {
  .ab-case-rond { width: 66px; height: 66px; }
  .ab-case-img  { width: 40px; height: 40px; }
}

/* ⚠️ ≤767px : EXACTEMENT QUATRE PAR LIGNE — le dessin de l'app.
   À 375px : 375 − 48 de gouttières = 327, moins 3 gaps de 6 = 309 / 4 ≈ 77px
   par colonne, dans lesquels un rond de 64 tient. Le rond devient fluide
   (`width:100%` borné) pour ne jamais déborder de sa colonne. */
@media (max-width: 767px) {
  .ab-cases { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px 6px; }
  .ab-case { gap: 5px; padding: 0 2px; }
  .ab-case-rond { width: 100%; max-width: 64px; height: auto; aspect-ratio: 1; }
  .ab-case-img { width: 60%; height: 60%; }
  .ab-case-t { font-size: 11px; }
  .ab-fam { padding-top: 18px; }
  .ab-n2-rang { padding-top: 14px; }
  .ab-n2 { font-size: 13px; padding: 0 12px; }
}

/* Sous 380px, quatre colonnes tiennent encore — c'est le format du
   téléphone d'Elia (390pt) et celui de l'app. On rétrécit le dessin, pas le
   nombre de colonnes : passer à trois ferait une grille qui ne ressemble
   plus à l'écran Explorer. */
@media (max-width: 379px) {
  .ab-cases { gap: 14px 4px; }
  .ab-case-rond { max-width: 58px; }
  .ab-case-t { font-size: 10.5px; }
}
