/* ══════════════════════════════════════════════════════════════════════════
   V2 de l'accueil — gabarit d'essai, charge par la seule page /v2/.

   Esprit demande par Charles a partir de bois-fleuri.com : des titres de
   section courts et manuscrits, des compositions d'images asymetriques qui
   debordent de leur bande de couleur, des etiquettes posees sur les photos.
   L'identite reste celle de Montpellier Plage : bleu canard, corail, creme.
   Rien ici ne sort du fichier : les 62 autres pages n'en voient pas une ligne.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
    --v2-creme: #f7f2ea;
    --v2-pale: #e7f0f2;
    --v2-encre: #14303d;
    --v2-trait: rgba(20, 48, 61, .12);
    --v2-topbar-h: 38px;
}

/* ── Bandeau superieur ─────────────────────────────────────────────────── */

/* Le bandeau de navigation commun est en position fixe : la topbar doit donc
   l'etre aussi et le repousser d'autant. La regle est conditionnee a la
   presence reelle d'une topbar : la feuille peut desormais etre chargee sur
   tout un site (css_site), et les pages qui n'en ont pas se retrouveraient
   sinon decalees de 38 px sous un vide. */
body:has(.v2-topbar) .demo-nav { top: var(--v2-topbar-h); }
.v2-topbar {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 310;
    height: var(--v2-topbar-h);
    display: flex;
    align-items: center;
    background: var(--v2-encre);
    color: rgba(255, 255, 255, .82);
    font-size: .82rem;
    letter-spacing: .01em;
}
.v2-topbar-inner {
    max-width: 1240px;
    margin: 0 auto;
    width: 100%;
    padding: 0 24px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 18px;
}
.v2-topbar a { color: #fff; text-decoration: none; }
.v2-topbar a:hover { text-decoration: underline; }
.v2-topbar-promo { display: flex; align-items: center; gap: 9px; min-width: 0; }
.v2-topbar-promo strong { color: #ffb59f; }
.v2-topbar-pastille {
    flex: none;
    width: 7px; height: 7px;
    border-radius: 50%;
    background: #ff7a55;
    box-shadow: 0 0 0 0 rgba(255, 122, 85, .7);
    animation: v2-pulse 2.4s infinite;
}
@keyframes v2-pulse {
    70% { box-shadow: 0 0 0 9px rgba(255, 122, 85, 0); }
    100% { box-shadow: 0 0 0 0 rgba(255, 122, 85, 0); }
}
.v2-topbar-liens { display: flex; align-items: center; gap: 14px; flex: none; }
/* Le lien de suivi de dossier ne faisait que 21 px de haut : trop peu au doigt.
   La hauteur du bandeau sert de cible, sans deformer le texte. */
.v2-topbar-liens a {
    display: inline-flex;
    align-items: center;
    height: var(--v2-topbar-h);
    padding: 0 6px;
}
.v2-topbar-liens svg { width: 15px; height: 15px; vertical-align: -2px; margin-right: 5px; }
/* Deux longueurs pour la promotion : la phrase entiere sur un ecran large, une
   version courte au telephone. Tronquee par des points de suspension, la longue
   perdait justement son chiffre (« jusqu'a -20 ... », vu le 01/09). */
.v2-topbar-court { display: none; }
@media (max-width: 860px) {
    .v2-topbar-inner { padding: 8px 16px; }
    .v2-topbar { font-size: .76rem; }
    .v2-topbar-long { display: none; }
    .v2-topbar-court { display: inline; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .v2-topbar-liens .v2-topbar-tel { display: none; }
}
@media (max-width: 1100px) {
    .v2-topbar-liens .v2-topbar-mail { display: none; }
}
/* Sous 360 px, il reste 120 px a la promotion : le suivi de dossier ne garde
   que son icone (le lien reste nomme par son aria-label). */
@media (max-width: 359px) {
    .v2-topbar-lib { display: none; }
    .v2-topbar-liens svg { margin-right: 0; }
}

/* ── Hero ──────────────────────────────────────────────────────────────── */

.v2-hero {
    position: relative;
    min-height: 88vh;
    display: flex;
    /* Demande d'Eric (31/08) : le texte ne doit plus recouvrir la video.
       Le bloc s'ancre en bas, la video occupe l'ecran. */
    align-items: flex-end;
    overflow: hidden;
    background: var(--v2-encre);
}
.v2-hero-media { position: absolute; inset: 0; z-index: 0; }
.v2-hero-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Le voile est plus dense a gauche, ou se pose le titre, et s'efface a droite
   pour laisser respirer la photo. */
.v2-hero::after {
    content: '';
    position: absolute; inset: 0; z-index: 1;
    /* Le voile n'assombrit que le bas, ou vit le texte : le reste de la
       video est laisse en clair (retour d'Eric, 31/08). */
    background: linear-gradient(180deg,
        rgba(20, 48, 61, .22) 0%, rgba(20, 48, 61, 0) 26%,
        rgba(20, 48, 61, 0) 48%, rgba(20, 48, 61, .48) 74%,
        rgba(20, 48, 61, .86) 100%);
}
.v2-hero-inner {
    position: relative;
    z-index: 2;
    max-width: 1240px;
    margin: 0 auto;
    /* Le bas reserve la place de la barre de recherche, posee a -86px. */
    padding: 110px 24px 150px;
    width: 100%;
}
.v2-hero-sur {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    font-size: .82rem;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: #ffd9cd;
    margin-bottom: 14px;
}
.v2-hero-sur::before {
    content: '';
    width: 34px; height: 1px;
    background: currentColor;
}
/* Le H1 reste pour le referencement, mais c'est la promesse qui parle : le
   logo identifie deja le site, inutile de crier son nom sur la video
   (retour d'Eric, 01/09, second tour). */
.v2-hero h1 {
    font-family: var(--font-body);
    font-size: .95rem;
    font-weight: 600;
    letter-spacing: .13em;
    text-transform: uppercase;
    line-height: 1.4;
    color: rgba(255, 255, 255, .88);
    margin: 0 0 10px;
    text-shadow: 0 1px 12px rgba(0, 0, 0, .45);
}
/* La promesse a le poids visuel d'un titre sans en etre un : elle repond au H1
   au lieu de le rallonger. */
.v2-hero-promesse {
    font-family: var(--font-heading);
    font-size: clamp(2rem, 3.6vw, 3.1rem);
    line-height: 1.08;
    color: #fff;
    margin: 0;
    max-width: 22ch;
    text-shadow: 0 2px 26px rgba(0, 0, 0, .4);
}
.v2-hero-sous {
    font-size: 1.02rem;
    color: rgba(255, 255, 255, .93);
    max-width: 46ch;
    margin: 0;
    text-shadow: 0 1px 12px rgba(0, 0, 0, .4);
}

/* Barre de recherche posee a cheval sur le bas du hero.

   Pas de backdrop-filter ici non plus : c'est le panneau que Charles a vu se
   casser en haut de page le 01/09. Il chevauche le hero, la video et le debut
   du contenu defilent donc derriere lui, et son fond floute se recompose par
   tuiles a chaque frame ; l'une d'elles garde un vieil instantane et une
   moitie du panneau part dans une autre teinte. Meme cause que la barre de
   navigation, meme remede : le fond monte de 90 a 94 % et le flou disparait.
   A cette opacite il ne pesait de toute facon qu'un dixieme du pixel. */
.v2-recherche {
    position: relative;
    z-index: 3;
    max-width: 1000px;
    margin: -86px auto 0;
    background: rgba(20, 48, 61, .94);
    border: 1px solid rgba(255, 255, 255, .16);
    border-radius: 14px;
    padding: 18px 22px;
    display: grid;
    grid-template-columns: repeat(3, 1fr) auto;
    gap: 16px;
    align-items: end;
    box-shadow: 0 22px 50px rgba(20, 48, 61, .28);
}
.v2-recherche-titre {
    /* Retour d'Eric du 10/09 : la barre ne se lisait pas comme un moteur de
       reservation, notamment par la clientele senior. Le titre la nomme.
       En premiere case pleine largeur : la grille passe de 4 a 2 puis 1
       colonne sans que la regle change. */
    grid-column: 1 / -1;
    margin: 0;
    font-family: var(--font-heading);
    font-size: 1.15rem;
    font-weight: 400;
    line-height: 1.2;
    color: #fff;
}
.v2-recherche label {
    display: block;
    /* 0,72 rem tombait a 11,5 px, sous le seuil de lisibilite de 12 px sur un
       fond sombre (mesure a la recette du 28/08). */
    font-size: .79rem;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, .62);
    margin-bottom: 7px;
}
.v2-recherche input,
.v2-recherche select {
    width: 100%;
    background: transparent;
    border: 0;
    border-bottom: 1px solid rgba(255, 255, 255, .28);
    color: #fff;
    font-family: inherit;
    font-size: 1rem;
    font-weight: 600;
    padding: 6px 0;
    min-height: 34px;
    border-radius: 0;
}
.v2-recherche input:focus,
.v2-recherche select:focus { outline: 0; border-bottom-color: #7fd4d6; }
.v2-recherche select option { color: var(--v2-encre); }
.v2-recherche input::-webkit-calendar-picker-indicator { filter: invert(1); opacity: .6; cursor: pointer; }
.v2-recherche button {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    background: var(--color-cta-solid);
    color: #fff;
    border: 0;
    border-radius: 999px;
    font-family: inherit;
    font-size: .95rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    padding: 15px 27px;
    min-height: 48px;
    cursor: pointer;
    transition: transform .2s var(--ease-out), background .2s;
}
.v2-recherche button:hover { background: #a83520; transform: translateY(-2px); }
@media (max-width: 900px) {
    .v2-hero { min-height: 76vh; }
    .v2-hero-inner { padding: 84px 20px 122px; }
    .v2-recherche { grid-template-columns: 1fr 1fr; margin: -70px 16px 0; }
    .v2-recherche button { grid-column: 1 / -1; justify-content: center; }
}
@media (max-width: 560px) {
    .v2-recherche { grid-template-columns: 1fr; gap: 14px; }
}

/* ── Bandeau de reperes ────────────────────────────────────────────────── */

.v2-reperes {
    max-width: 1240px;
    margin: 0 auto;
    padding: 48px 24px 8px;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 14px;
}
.v2-repere {
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 15px 18px;
    background: #fff;
    border: 1px solid var(--v2-trait);
    border-radius: 12px;
    font-size: .92rem;
    line-height: 1.34;
}
.v2-repere svg { width: 26px; height: 26px; flex: none; color: var(--color-accent-ink, #2a7f82); }
.v2-repere strong { display: block; color: var(--v2-encre); }
.v2-repere span { color: var(--color-text-muted); font-size: .86rem; }
@media (max-width: 900px) { .v2-reperes { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .v2-reperes { grid-template-columns: 1fr; padding-top: 36px; } }

/* ── Titres de section manuscrits ──────────────────────────────────────── */

.v2-titre {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    /* DM Serif Display Italic : meme famille que tous les titres du site, deja
       chargee par le head commun (ital@0;1). L'accent chaleureux de la cursive,
       sans police etrangere : la V2 ne jure plus avec les pages interieures. */
    font-family: var(--font-heading);
    font-style: italic;
    font-weight: 400;
    font-size: clamp(2.1rem, 4.6vw, 3.4rem);
    line-height: 1;
    color: var(--color-accent-ink, #2a7f82);
    text-align: center;
    margin: 0 0 14px;
}
.v2-titre-gauche { justify-content: flex-start; text-align: left; }
/* La goutte : rappel de la reference, redessinee et non copiee. */
.v2-titre .v2-goutte {
    flex: none;
    width: .62em; height: .62em;
    color: var(--color-cta-solid);
}
.v2-chapo {
    text-align: center;
    max-width: 60ch;
    margin: 0 auto 42px;
    color: var(--color-text-muted);
    font-size: 1.05rem;
    line-height: 1.65;
}
.v2-titre-gauche + .v2-chapo { text-align: left; margin-left: 0; }

/* ── Bandes ────────────────────────────────────────────────────────────── */

.v2-bande { padding: 78px 0; }
.v2-bande-pale { background: var(--v2-pale); }
.v2-bande-creme { background: var(--v2-creme); }
.v2-bande > .container { max-width: 1240px; margin: 0 auto; padding: 0 24px; }
@media (max-width: 700px) { .v2-bande { padding: 56px 0; } }

/* ── Compositions d'images ─────────────────────────────────────────────── */

/* Deux images de tailles franchement differentes, la petite chevauchant la
   grande. Le decalage est fait au grid, pas en position absolue : la hauteur
   de la composition reste donc calculee par le navigateur, et rien ne se
   superpose au texte qui suit quand la fenetre retrecit. */
.v2-compo {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 26px;
    align-items: center;
}
.v2-compo-images {
    position: relative;
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    grid-template-rows: repeat(6, 1fr);
    aspect-ratio: 5 / 4;
}
.v2-compo-images figure { margin: 0; overflow: hidden; border-radius: 4px; }
.v2-compo-images img { width: 100%; height: 100%; object-fit: cover; display: block; }
.v2-compo-grande { grid-column: 1 / 6; grid-row: 1 / 6; box-shadow: 0 18px 44px rgba(20, 48, 61, .18); }
.v2-compo-petite {
    grid-column: 4 / 7;
    grid-row: 4 / 7;
    border: 7px solid #fff;
    box-shadow: 0 14px 34px rgba(20, 48, 61, .22);
    z-index: 1;
}
.v2-compo-inverse .v2-compo-images { order: 2; }
.v2-compo-inverse .v2-compo-texte { order: 1; }

/* Etiquette posee en bas d'image, comme sur la reference. */
.v2-etiquette { position: relative; }
.v2-etiquette figcaption {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    padding: 42px 20px 16px;
    color: #fff;
    font-size: .84rem;
    font-weight: 700;
    letter-spacing: .13em;
    text-transform: uppercase;
    background: linear-gradient(to top, rgba(20, 48, 61, .78), transparent);
}
/* La petite photo recouvre le quart bas-droit de la grande, donc exactement
   la ou l'etiquette se pose : « ENTRE MER ET ETANGS » s'y coupait en deux.
   Sur ces compositions, l'etiquette passe en haut, dans la zone laissee
   libre. Les etiquettes des triptyques, elles, gardent le bas. */
.v2-compo-grande.v2-etiquette figcaption {
    top: 0;
    bottom: auto;
    padding: 16px 20px 44px;
    background: linear-gradient(to bottom, rgba(20, 48, 61, .78), transparent);
}

@media (max-width: 860px) {
    .v2-compo { grid-template-columns: 1fr; gap: 30px; }
    .v2-compo-inverse .v2-compo-images { order: 0; }
    .v2-compo-inverse .v2-compo-texte { order: 0; }
}

/* ── Triptyque ─────────────────────────────────────────────────────────── */

.v2-trio { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.v2-trio figure { margin: 0; position: relative; overflow: hidden; border-radius: 4px; aspect-ratio: 3 / 4; }
.v2-trio img {
    width: 100%; height: 100%; object-fit: cover; display: block;
    transition: transform .7s var(--ease-out);
}
.v2-trio figure:hover img { transform: scale(1.05); }
/* La premiere case porte un texte au lieu d'une photo, comme sur la
   reference : la bande garde son rythme sans exiger une image de plus. */
.v2-trio-mot {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 30px 26px;
    background: var(--color-accent-ink, #2a7f82);
    color: #fff;
    border-radius: 4px;
}
.v2-trio-mot h3 { font-family: var(--font-heading); font-size: 1.5rem; margin: 0 0 12px; color: #fff; }
.v2-trio-mot p { margin: 0; font-size: .96rem; line-height: 1.62; color: rgba(255, 255, 255, .9); }
.v2-trio:has(> figure:nth-child(2):last-child) { grid-template-columns: 1fr 1fr; }
.v2-trio:has(> figure:nth-child(2):last-child) figure { aspect-ratio: 4 / 3; }
@media (max-width: 860px) { .v2-trio { grid-template-columns: 1fr 1fr; } }
@media (max-width: 520px) { .v2-trio { grid-template-columns: 1fr; } }

/* ── Lien d'appel ──────────────────────────────────────────────────────── */

/* L'ancienne bordure en parenthese ouverte se lisait comme un cadre a moitie
   dessine (signale le 29/08). Le lien devient un soulignement editorial : un
   trait discret au repos, qui se redessine de la gauche au survol pendant que
   la fleche avance. Pas de fond, pas de boite : le solide reste aux .btn. */
.v2-lien {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 11px;
    padding: 12px 2px;
    font-size: .84rem;
    font-weight: 700;
    letter-spacing: .13em;
    text-transform: uppercase;
    color: var(--color-accent-ink, #2a7f82);
    text-decoration: none;
}
.v2-lien::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: 6px;
    height: 1.5px;
    background: currentColor;
    opacity: .3;
}
.v2-lien::before {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: 6px;
    height: 1.5px;
    background: currentColor;
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform .35s var(--ease-out);
}
.v2-lien svg { width: 15px; height: 15px; transition: transform .3s var(--ease-out); }
.v2-lien:hover::before,
.v2-lien:focus-visible::before { transform: scaleX(1); }
.v2-lien:hover svg,
.v2-lien:focus-visible svg { transform: translateX(4px); }
.v2-lien:focus-visible { outline: 2px solid currentColor; outline-offset: 4px; }
.v2-lien-clair { color: #fff; }
@media (prefers-reduced-motion: reduce) {
    .v2-lien::before, .v2-lien svg { transition: none; }
}

/* ── Avis ──────────────────────────────────────────────────────────────── */

.v2-avis { display: grid; grid-template-columns: 1.05fr 1fr; align-items: stretch; }
.v2-avis-photo { overflow: hidden; }
.v2-avis-photo img { width: 100%; height: 100%; object-fit: cover; display: block; min-height: 340px; }
.v2-avis-texte { background: var(--v2-pale); padding: 54px 48px; display: flex; flex-direction: column; justify-content: center; }
.v2-avis-note {
    font-family: var(--font-heading);
    font-size: 1.55rem;
    line-height: 1.2;
    color: var(--v2-encre);
    margin: 10px 0 16px;
}
.v2-avis blockquote { margin: 0 0 18px; font-size: 1.02rem; line-height: 1.7; color: var(--color-text); }
.v2-avis cite { font-style: normal; font-weight: 700; color: var(--v2-encre); font-size: .94rem; }
.v2-avis-source { display: block; margin-top: 4px; font-size: .84rem; color: var(--color-text-muted); }
@media (max-width: 860px) {
    .v2-avis { grid-template-columns: 1fr; }
    .v2-avis-texte { padding: 38px 24px; }
}

/* ── Revelation au defilement ──────────────────────────────────────────── */

/* Un seul mecanisme, pilote par IntersectionObserver dans la page. Le
   deplacement reste court : au-dela, le contenu parait sauter a l'arrivee. */
.v2-anim { opacity: 0; transform: translateY(22px); transition: opacity .7s var(--ease-out), transform .7s var(--ease-out); }
.v2-anim.est-vu { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
    .v2-anim { opacity: 1; transform: none; transition: none; }
    .v2-topbar-pastille { animation: none; }
    .v2-trio figure:hover img { transform: none; }
}

/* ── Corrections issues du jury du 28/08 ───────────────────────────────── */

/* Les titres manuscrits ne disaient rien : ni a Google, ni au visiteur qui
   balaie la page ("Ame d'enfant" ne dit pas qu'on parle du club enfants). Le
   H2 porte desormais les deux, le mot en grand et la ligne utile dessous, ce
   qui garde le parti pris sans sacrifier le referencement. */
.v2-titre { flex-wrap: wrap; margin-bottom: 4px; }
.v2-titre-mot { display: block; }
.v2-titre-dit {
    max-width: 62ch;
    margin: 0 auto 14px;
    text-align: center;
    font-family: var(--font-body), sans-serif;
    font-weight: 600;
    font-size: clamp(1rem, 1.5vw, 1.18rem);
    line-height: 1.4;
    letter-spacing: 0;
    color: var(--v2-encre);
    margin-top: 6px;
}
.v2-titre-gauche + .v2-titre-dit { text-align: left; margin-left: 0; }

/* Trois verbatims au lieu d'un : le camping n'affiche aucune note globale, la
   preuve sociale ne tient donc qu'au nombre et a la source des temoignages. */
.v2-avis-liste { display: flex; flex-direction: column; gap: 20px; }
.v2-avis-liste blockquote {
    margin: 0;
    padding-left: 16px;
    border-left: 2px solid var(--color-accent-ink, #2a7f82);
    font-size: .97rem;
    line-height: 1.62;
    color: var(--color-text);
}
.v2-avis-liste cite {
    display: block;
    margin-top: 8px;
    font-style: normal;
    font-weight: 700;
    font-size: .9rem;
    color: var(--v2-encre);
}
.v2-avis-liste cite span {
    display: block;
    font-weight: 400;
    font-size: .82rem;
    color: var(--color-text-muted);
}

/* Bloc de referencement : la V2 n'en avait pas, soit 365 mots et tout le
   maillage interne de la V1 en moins. Compose en colonne etroite, il se lit
   comme un texte et non comme un pave d'optimisation. */
.v2-seo .container { max-width: 820px; }
.v2-seo h2 {
    font-family: var(--font-heading);
    font-size: 1.4rem;
    color: var(--v2-encre);
    margin: 30px 0 10px;
}
.v2-seo h2:first-child { margin-top: 0; }
.v2-seo p { font-size: .98rem; line-height: 1.72; color: var(--color-text); margin: 0; }
.v2-seo a { color: var(--color-accent-ink, #2a7f82); }

/* ── Video d'arriere-plan du hero ──────────────────────────────────────────
   Video hebergee sur le site depuis le 29/09/2026 (plus de YouTube, donc plus
   d'accord cookies a attendre). La photo sert de poster et reste l'image LCP ;
   la video la recouvre en fondu des sa premiere image (classe yt-playing posee
   par site.js). */
.v2-hero-media.hero-video { background: none; }
.v2-hero-video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    pointer-events: none;
    opacity: 0;
    transition: opacity .7s var(--ease-out);
}
.v2-hero-media.yt-playing .v2-hero-video { opacity: 1; }

/* Le formulaire porte desormais la classe booking-search, pour etre tracke et
   borne a la saison comme les autres. On neutralise ce que base.css lui
   appliquerait : sa mise en page est celle du hero, pas celle de la barre fixe. */
.v2-recherche.booking-search {
    display: grid;
    background: rgba(20, 48, 61, .94);
    padding: 18px 22px;
    gap: 16px;
}
.v2-recherche.booking-search fieldset { border: 0; margin: 0; padding: 0; }

/* ── Fiches d'hebergement du gabarit V2 ────────────────────────────────────
   Les reperes chiffres servent ici de bandeau de caracteristiques sous le
   bandeau de titre : trois ou quatre cases, et non la grille de quatre de
   l'accueil. La liste d'equipement se lit en colonnes, avec une puce dessinee
   plutot que la puce du navigateur. */
.v2-repere span strong + span { display: block; }
.picto-liste {
    list-style: none;
    padding: 0;
    margin: 14px 0 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(230px, 100%), 1fr));
    gap: 10px 24px;
}
.picto-liste li {
    position: relative;
    padding-left: 22px;
    line-height: 1.5;
    color: var(--color-text);
}
.picto-liste li::before {
    content: '';
    position: absolute;
    left: 2px; top: .55em;
    width: 7px; height: 7px;
    border-radius: 50%;
    background: var(--color-cta-solid);
}
/* Tableau des suppléments : il doit rester lisible sous 560 px, ou il s'empile. */
.tarif-table { width: 100%; border-collapse: collapse; margin: 18px 0 6px; }
.tarif-table th, .tarif-table td {
    text-align: left;
    padding: 11px 14px;
    border-bottom: 1px solid var(--v2-trait);
}
.tarif-table th { font-weight: 700; color: var(--v2-encre); background: var(--v2-pale); }
.tarif-table td:last-child { white-space: nowrap; font-weight: 600; color: var(--v2-encre); }
@media (max-width: 560px) {
    .tarif-table, .tarif-table tbody, .tarif-table tr, .tarif-table td { display: block; width: 100%; }
    .tarif-table thead { display: none; }
    .tarif-table tr { border-bottom: 1px solid var(--v2-trait); padding: 8px 0; }
    .tarif-table td { border: 0; padding: 2px 0; }
    .tarif-table td:last-child { white-space: normal; }
    /* En pile, l'en-tete disparait : sans son nom, « 40 € » ne veut plus rien
       dire sur un tableau a quatre colonnes. Chaque cellule porte donc le nom
       de sa colonne dans data-l, pose ici devant la valeur. */
    .tarif-table td[data-l]::before {
        content: attr(data-l) " : ";
        font-weight: 700;
        color: var(--color-text-muted);
    }
    .tarif-table td[data-l] { display: flex; gap: 6px; }
}

/* Modele absent du moteur de reservation : l'avertissement doit se voir sans
   crier, il n'est pas une erreur mais une information. Le liseré lateral
   colore, tic d'interface s'il en est, cede la place a un cadre entier. */
.note-indispo {
    margin: 16px 0 0;
    padding: 15px 18px;
    border: 1px solid var(--v2-trait);
    background: var(--v2-creme);
    border-radius: 8px;
    font-size: .96rem;
    line-height: 1.6;
}
.note-indispo strong { color: var(--color-cta-ink); }

/* ── Carte d'un restaurant ─────────────────────────────────────────────────
   Le plat a gauche, le prix cale a droite, avec un pointille entre les deux :
   c'est la convention d'une carte imprimee, et elle se lit d'un coup d'oeil.
   Le nom .menu-carte etait deja pris par une section entiere sur l'autre site,
   d'ou .carte-plats. */
.carte-plats { margin: 14px 0 26px; }
.carte-plats p {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin: 0;
    padding: .55em 0;
    border-bottom: 1px dotted rgba(20, 48, 61, .18);
}
.carte-plats p:last-child { border-bottom: 0; }
.carte-plats p > span:first-child { flex: 1; line-height: 1.45; }
.carte-plats p > span:last-child {
    flex: none;
    font-weight: 700;
    color: var(--v2-encre);
    white-space: nowrap;
}
.carte-plats em {
    display: block;
    font-style: normal;
    font-size: .86rem;
    color: var(--color-text-muted);
    line-height: 1.4;
}
.article-body .carte-plats + p { margin-top: -12px; font-size: .93rem; color: var(--color-text-muted); }

/* ── Galeries de photos ────────────────────────────────────────────────────
   Grille qui se remplit d'elle-meme : le nombre de colonnes suit la largeur,
   sans point de rupture a maintenir. La legende n'apparait qu'au survol sur
   les appareils qui le permettent, et reste toujours lisible au clavier. */
.galerie-grille {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
    gap: 14px;
    margin-top: 26px;
}
.galerie-grille figure {
    position: relative;
    margin: 0;
    overflow: hidden;
    border-radius: 6px;
    aspect-ratio: 4 / 3;
    background: var(--v2-trait);
}
.galerie-grille img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform .6s var(--ease-out);
}
.galerie-grille figcaption {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    padding: 30px 14px 11px;
    color: #fff;
    font-size: .86rem;
    line-height: 1.35;
    background: linear-gradient(to top, rgba(20, 48, 61, .82), transparent);
    opacity: 0;
    transform: translateY(6px);
    transition: opacity .3s var(--ease-out), transform .3s var(--ease-out);
}
.galerie-grille figure:hover img { transform: scale(1.05); }
.galerie-grille figure:hover figcaption,
.galerie-grille figure:focus-within figcaption { opacity: 1; transform: none; }
/* Au doigt il n'y a pas de survol : la legende reste affichee. */
@media (hover: none) {
    .galerie-grille figcaption { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .galerie-grille img, .galerie-grille figcaption { transition: none; }
    .galerie-grille figure:hover img { transform: none; }
}
.galerie-photos h2 {
    font-family: var(--font-heading);
    font-size: clamp(1.5rem, 2.6vw, 2rem);
    color: var(--v2-encre);
    margin: 0;
}

/* Photos agrandissables : le curseur doit l'annoncer, sans quoi rien ne dit
   qu'on peut cliquer. La visionneuse est celle du site, branchee dans site.js.
   Les selecteurs sont dans :where() pour ne rien peser : une photo qui est un
   lien doit pouvoir reprendre la main sans surenchere de specificite (voir la
   regle « a img » de base.css). */
:where(.galerie-grille, .v2-trio figure, .v2-compo-images) img { cursor: zoom-in; }

/* ── Cartes du hub avec case de comparaison ────────────────────────────────
   La case vit sous la carte et non dessus : posee en surimpression, elle
   couvrirait la legende et se cliquerait par erreur en visant le lien. */
.hub-item {
    display: flex;
    flex-direction: column;
    background: var(--color-card, #fff);
    border: 1px solid var(--v2-trait);
    border-radius: 8px;
    overflow: hidden;
}
.hub-item .hub-card { border: 0; border-radius: 0; margin: 0; }
.hub-item .ms-compare { margin-top: auto; background: var(--color-card, #fff); }
.fiche-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px 22px;
}
.fiche-actions .ms-compare { border-top: 0; padding: 0; }

/* ══════════════════════════════════════════════════════════════════════════
   Les cinquante mètres

   Le seul chiffre que les campings voisins ne peuvent pas reprendre : la
   plage est à 50 m, contre 100 chez Les Roquilles. Ecrit, il reste abstrait.
   La scene le fait marcher : les pas se posent un a un de la terrasse
   jusqu'au sable, au rythme du defilement, et le compteur suit.

   Une seule idee matérielle sur toute la page : l'eau. La houle respire ici,
   la goutte des titres tombe et ondule, le champ actif de la barre de
   recherche se remplit. Rien d'autre ne bouge.
   ══════════════════════════════════════════════════════════════════════════ */

.v2-50 {
    margin: 46px 0 8px;
    /* le SVG est une frise : on borne sa hauteur pour qu'il ne mange pas
       l'ecran en mobile, ou son ratio 4:1 l'ecraserait de toute facon */
    display: grid;
    justify-items: center;
    gap: 18px;
}
.v2-50-scene {
    width: 100%;
    max-width: 1000px;
    height: auto;
    fill: none;
    stroke: var(--v2-encre);
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: .78;
}
.v2-50-arbre { opacity: .5; }
.v2-50-sol { stroke: var(--v2-encre); stroke-width: 2; opacity: .42; }

.v2-50-houle { stroke: var(--color-accent, #47b0b3); stroke-width: 2.6; opacity: .95; }
.v2-50-chemin {
    stroke: var(--v2-encre);
    stroke-width: 2;
    stroke-dasharray: 2 10;
    opacity: .34;
}
.v2-50-traces ellipse,
.v2-50-traces circle { fill: var(--color-cta, #fe7259); stroke: none; opacity: .9; }
.v2-50-jalons path { stroke: var(--v2-encre); stroke-width: 1.6; opacity: .3; }
.v2-50-jalons text {
    fill: var(--color-text-muted, #696969);
    stroke: none;
    font-family: var(--font-body);
    font-size: 14px;
    text-anchor: middle;
    letter-spacing: .04em;
}

.v2-50-dit {
    display: grid;
    justify-items: center;
    gap: 4px;
    text-align: center;
}
.v2-50-nombre {
    font-family: var(--font-heading);
    font-size: clamp(2.4rem, 6vw, 3.6rem);
    line-height: 1;
    color: var(--v2-encre);
    font-feature-settings: 'tnum' 1;   /* le compteur ne doit pas gigoter */
}
.v2-50-val { font-variant-numeric: tabular-nums; }
.v2-50-sous {
    font-size: .95rem;
    color: var(--color-text-muted, #696969);
    max-width: 46ch;
}

/* Les pas et la houle : caches par defaut seulement si le navigateur sait les
   reveler. Sans animation, la scene reste complete et lisible. */
.v2-50-traces .v2-50-pas { opacity: 1; }

@media (prefers-reduced-motion: no-preference) {
    /* Progression liee au defilement quand le navigateur la connait : le
       visiteur pousse lui-meme la marche. La chronologie ne compte que la
       zone visible : les hauteurs du menu fixe et de la barre de reservation
       fixe (--v2-50-haut, --v2-50-bas, mesurees par le script de l'accueil)
       en sont retirees, sans quoi la marche commencait sous la barre du bas. */
    @supports (animation-timeline: view()) {
        /* Chronologie nommee portee par la figure (une boite HTML) : prise sur
           le groupe SVG des pas, elle ne suivait pas sa position reelle. Les
           plages sont relatives a la figure, dont les pas occupent le haut :
           la marche part quand ils sortent de sous la barre du bas (entry
           50 %) et s'acheve vers le haut de la zone (cover 55 %). Le script
           de l'accueil refait exactement ce calcul pour le compteur. */
        .v2-50 {
            view-timeline: --v2-50 block;
            view-timeline-inset: var(--v2-50-haut, 0px) var(--v2-50-bas, 0px);
        }
        .v2-50-traces {
            clip-path: inset(0 100% 0 0);
            animation: v2-50-marche linear both;
            animation-timeline: --v2-50;
            animation-range: entry 50% cover 55%;
        }
        .v2-50-chemin {
            stroke-dashoffset: 700;
            animation: v2-50-trace linear both;
            animation-timeline: --v2-50;
            animation-range: entry 44% cover 51%;
        }
    }
    /* Repli : la scene se joue une fois a l'entree dans l'ecran. */
    @supports not (animation-timeline: view()) {
        .v2-50-traces { clip-path: inset(0 100% 0 0); }
        .v2-50-chemin { stroke-dashoffset: 700; }
        .v2-50.est-vu .v2-50-traces { animation: v2-50-marche 1.9s var(--ease-out) both; }
        .v2-50.est-vu .v2-50-chemin { animation: v2-50-trace 1.5s var(--ease-out) both; }
    }

    /* La houle ne tourne que lorsque la scene est a l'ecran. */
    .v2-50.est-vu .v2-50-houle-1 { animation: v2-50-houle 5.5s ease-in-out infinite; }
    .v2-50.est-vu .v2-50-houle-2 { animation: v2-50-houle 7s ease-in-out infinite reverse; }
    .v2-50.est-vu .v2-50-houle-3 { animation: v2-50-houle 9s ease-in-out infinite; }
}

@keyframes v2-50-marche { to { clip-path: inset(0 0 0 0); } }
@keyframes v2-50-trace { to { stroke-dashoffset: 0; } }
@keyframes v2-50-houle {
    0%, 100% { transform: translateX(0); }
    50% { transform: translateX(-34px); }
}

.v2-50-chemin { stroke-dasharray: 3 12; }

@media (max-width: 760px) {
    .v2-50 { margin: 34px 0 4px; gap: 12px; }
    /* La frise tombe a 43 px de haut sur un telephone de 320 px : les
       graduations y font 6 px et ne se lisent plus. On les retire, la frise
       reste evocatrice et c'est le nombre, en HTML, qui porte le message. */
    .v2-50-jalons text { display: none; }
    .v2-50-scene { opacity: .72; }
    .v2-50-traces ellipse,
    .v2-50-traces circle { opacity: 1; }
}

/* ── Les deux etats d'appui, meme matiere ──────────────────────────────────

   La goutte des titres tombe et s'ecrase au lieu de monter en fondu comme le
   reste : le geste porte le motif de la marque plutot qu'une entree generique
   de plus. Le champ actif de la barre de recherche se remplit par la gauche,
   comme la mer qui gagne. Rien d'autre ne bouge sur la page.
   ------------------------------------------------------------------------- */

.v2-titre .v2-goutte { transform-origin: 50% 92%; }

@media (prefers-reduced-motion: no-preference) {
    .v2-anim .v2-goutte { opacity: 0; }
    .v2-anim.est-vu .v2-goutte { animation: v2-chute .78s var(--ease-out) .12s both; }
}

@keyframes v2-chute {
    0%   { opacity: 0; transform: translateY(-15px) scale(.84, 1.24); }
    52%  { opacity: 1; transform: translateY(0) scale(1, 1); }
    66%  { transform: translateY(0) scale(1.22, .8); }
    82%  { transform: translateY(0) scale(.94, 1.06); }
    100% { opacity: 1; transform: none; }
}

/* Le champ actif : un liseré qui monte de la gauche, sous la bordure basse
   deja presente. On decore le conteneur, jamais le champ ni le formulaire :
   le linker GA4 et Ads doit garder la main sur l'un comme sur l'autre. */
.v2-recherche > div { position: relative; }
.v2-recherche > div::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 2px;
    background: #7fd4d6;
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform .3s var(--ease-out);
    pointer-events: none;
}
.v2-recherche > div:focus-within::after { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) {
    .v2-recherche > div::after { transition: none; }
}

/* ── Une photo de l'accueil mene a sa page ────────────────────────────────

   Sur une page d'accueil, une photo qui ouvre une visionneuse est un
   cul-de-sac : le visiteur regarde, referme, et rien n'a avance. Celles de
   l'accueil menent donc a la page qui traite le sujet. Le lien enveloppe
   l'image ET son etiquette, qui devient son libelle.
   ------------------------------------------------------------------------- */

.v2-photo-lien {
    display: block;
    width: 100%;
    height: 100%;
    color: inherit;
    text-decoration: none;
    /* figcaption se positionne sur la figure, restee le conteneur positionne */
}
/* Le curseur des photos-liens vient de la regle « a img » de base.css : elle
   couvre toutes les compositions, y compris celles ajoutees plus tard. */

/* L'affordance : l'etiquette prend une fleche qui avance au survol. Sans
   etiquette, l'image seule se contente du zoom deja en place sur les trios. */
.v2-etiquette .v2-photo-lien figcaption::after {
    content: '';
    display: inline-block;
    width: .62em; height: .62em;
    margin-left: .5em;
    border-right: 2px solid currentColor;
    border-top: 2px solid currentColor;
    transform: rotate(45deg) translate(-.06em, .06em);
    transition: transform .3s var(--ease-out);
}
.v2-etiquette:hover .v2-photo-lien figcaption::after,
.v2-photo-lien:focus-visible figcaption::after {
    transform: rotate(45deg) translate(.12em, -.12em);
}
.v2-compo-images figure:hover img,
.v2-compo-images .v2-photo-lien:focus-visible img { transform: scale(1.03); }
.v2-compo-images img { transition: transform .7s var(--ease-out); }
.v2-photo-lien:focus-visible { outline: 3px solid var(--color-accent, #47b0b3); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
    .v2-compo-images figure:hover img { transform: none; }
    .v2-etiquette .v2-photo-lien figcaption::after { transition: none; }
}

/* Mention sous une galerie : d'ou viennent les photos, en petit et sans crier. */
.v2-mention {
    margin: 16px 0 0;
    font-size: .85rem;
    font-style: italic;
    color: var(--color-text-muted, #696969);
    text-align: center;
}
