/*
 * AD-100 à AD-111 — Les règles de composant partagées, reprises des maquettes.
 *
 * ⛔ COPIÉES TELLES QUELLES. Chaque règle ci-dessous figure à l'identique dans
 * au moins cinq des six maquettes publiques. Aucun sélecteur renommé, aucune
 * valeur changée, aucun raccourci « plus propre ».
 *
 * Ce qui est propre à UNE page reste dans sa page (phase 5). Ce fichier ne
 * contient que ce qui est commun.
 */

/* ------------------------------------------------------------------ */
/* AD-100 — En-tête : compactage au scroll                            */
/*                                                                    */
/* `data-compact` est posé par le JS. Sans JS, l'en-tête reste à sa    */
/* taille pleine — dégradation correcte, rien ne disparaît.           */
/* ------------------------------------------------------------------ */
[data-site-header] { transition: box-shadow var(--motion-fast) var(--ease) }
[data-site-header][data-compact] { box-shadow: var(--shadow-soft) }
[data-site-header][data-compact] [data-header-inner] { padding-top: var(--space-2xs); padding-bottom: var(--space-2xs) }
[data-site-header][data-compact] [data-logo] { width: 40px; height: 40px }
[data-header-inner] { transition: padding var(--motion-fast) var(--ease) }
[data-logo] { transition: width var(--motion-fast) var(--ease), height var(--motion-fast) var(--ease) }

/* Le nom de marque et le sélecteur de langue s'effacent sur les petits écrans */
[data-brand-text] { display: none }
@media (min-width: 26rem) { [data-brand-text] { display: flex } }
[data-lang] { display: none }
@media (min-width: 48rem) { [data-lang] { display: flex } }

/* ------------------------------------------------------------------ */
/* AD-100 / AD-101 — La bascule desktop / mobile                      */
/*                                                                    */
/* Les deux navigations sont dans le DOM, une seule est affichée.     */
/* ------------------------------------------------------------------ */
[data-nav="desktop"] { display: none }
[data-nav="mobile"] { display: block }

@media (min-width: 62rem) {
    [data-nav="desktop"] { display: flex }
    [data-nav="mobile"] { display: none }
}

/* ------------------------------------------------------------------ */
/* AD-113 — Apparition au défilement, en ENRICHISSEMENT                */
/*                                                                    */
/* LE CONTENU EST VISIBLE PAR DÉFAUT. L'apparition n'est armée que si  */
/* le script pose `.has-motion` sur l'élément racine : si le JS ne se  */
/* charge pas, rien ne reste à opacité zéro. C'est l'ordre qui compte  */
/* — l'inverse cacherait la page aux visiteurs sans JavaScript.        */
/* ------------------------------------------------------------------ */
[data-reveal] { transition: opacity var(--motion-slow) var(--ease), transform var(--motion-slow) var(--ease) }
.has-motion [data-reveal] { opacity: 0; transform: translateY(18px) }
.has-motion [data-reveal].is-visible { opacity: 1; transform: none }

/* ------------------------------------------------------------------ */
/* AD-103 — Carte logement : survol et zoom de la photo                */
/* ------------------------------------------------------------------ */
[data-zoom] { overflow: hidden }
/* ⚖️ DURÉE DIFFÉRENTE SELON LA MAQUETTE (AD-397) : `--motion-zoom` (.9 s)
   sur Accueil, `--motion-slow` (.6 s) sur les trois autres. Un zoom lent sur
   une carte d'accueil qu'on survole longtemps, plus vif sur une galerie qu'on
   parcourt. Ce n'est pas une incohérence, c'est un réglage par contexte. */
[data-zoom] img { transition: transform var(--motion-slow) var(--ease) }
[data-page="accueil"] [data-zoom] img { transition: transform var(--motion-zoom) var(--ease) }
[data-card] { transition: box-shadow var(--motion-fast) var(--ease), transform var(--motion-fast) var(--ease) }
[data-card]:hover { box-shadow: var(--shadow-lifted); transform: translateY(-2px) }
[data-card]:hover [data-zoom] img,
[data-card]:focus-within [data-zoom] img { transform: scale(1.05) }

/* Défilement horizontal discret — bandeau de garanties, vignettes */
[data-scroller] { scrollbar-width: thin }
[data-sheet] > summary::-webkit-details-marker { display: none }

/* ------------------------------------------------------------------ */
/* AD-101 — Menu mobile : panneau plein écran en fondu                */
/*                                                                    */
/* Proposition nº 1, validée par le client. Le panneau est toujours    */
/* dans le DOM et n'est masqué que visuellement : `pointer-events` le  */
/* rend inatteignable fermé, l'opacité le fait apparaître.             */
/* ------------------------------------------------------------------ */
[data-menu-panel] {
    position: fixed;
    inset: 0;
    z-index: 70;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--motion-mid) var(--ease);
    display: flex;
    flex-direction: column;
}

[data-menu-open] [data-menu-panel] { opacity: 1; pointer-events: auto }

/* ------------------------------------------------------------------ */
/* AD-103 — Carte logement : mise en page en deux volets               */
/*                                                                    */
/* Une colonne sur mobile, média et texte côte à côte au-delà de       */
/* 62rem. `reverse` fait passer le média à droite — c'est ce qui       */
/* alterne les deux blocs de l'accueil sans dupliquer le composant.    */
/* Repris de la maquette à la valeur près, 1.05fr / .95fr compris.     */
/* ------------------------------------------------------------------ */
[data-split] { display: grid; grid-template-columns: 1fr; gap: var(--space-lg) }

@media (min-width: 62rem) {
    [data-split] { grid-template-columns: 1.05fr .95fr; gap: var(--space-2xl); align-items: center }
    [data-split="reverse"] > [data-split-media] { order: 2 }
}

/* ------------------------------------------------------------------ */
/* AD-105 — Boutons : primaire, secondaire, texte                     */
/*                                                                    */
/* LES NOMS DE CLASSES VIENNENT DE LA MAQUETTE. La page « Design       */
/* System » les écrit noir sur blanc : .button--primary,               */
/* .button--secondary, .button--text. Je ne les invente pas.           */
/*                                                                    */
/* ⚠️ LES VALEURS VIENNENT DES SIX PAGES RÉELLES, pas de la page       */
/* « Design System », qui utilise le vocabulaire antérieur             */
/* (--color-accent-strong, #fff, #8E1A29 en dur). Voir                 */
/* docs/design/ECARTS-TOKENS.md §3.2 : le socle des pages réelles fait  */
/* foi. Trois substitutions, une pour une :                            */
/*                                                                    */
/*   --color-accent-strong  →  --surface-accent                        */
/*   #fff                   →  --on-surface-accent                     */
/*   #8E1A29                →  --surface-accent-hover                  */
/*                                                                    */
/* ⚠️ CES CLASSES SERVENT AU BALISAGE QUE NOUS ÉCRIVONS — formulaires, */
/* tunnel, back-office. Les pages intégrées gardent les styles en      */
/* ligne de leur maquette : les remplacer casserait le diff d'AD-393.  */
/* Deux façons de faire un bouton, donc, et c'est assumé.              */
/*                                                                    */
/* 48 px de haut, cible tactile conforme, comme la maquette l'écrit.   */
/* La transition vient de base.css, qui la pose déjà sur `button`.     */
/* ------------------------------------------------------------------ */
.button--primary,
.button--secondary,
.button--text {
    font-family: var(--font-text);
    font-size: var(--text-small);
    font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
}

.button--primary {
    min-height: 48px;
    padding: 0 var(--space-md);
    border: 1px solid var(--surface-accent);
    border-radius: var(--radius-pill);
    background: var(--surface-accent);
    color: var(--on-surface-accent);
    letter-spacing: .02em;
}

.button--primary:hover {
    background: var(--surface-accent-hover);
    border-color: var(--surface-accent-hover);
}

.button--secondary {
    min-height: 48px;
    padding: 0 var(--space-md);
    border: 1px solid var(--color-brand-strong);
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--color-brand-strong);
}

.button--secondary:hover {
    background: var(--color-brand-strong);
    color: var(--on-surface-dark);
}

.button--text {
    min-height: 44px;
    padding: 0;
    border: 0;
    border-bottom: 1px solid var(--color-line-strong);
    background: none;
    color: var(--color-brand-strong);
}

.button--text:hover {
    color: var(--surface-accent);
    border-color: var(--surface-accent);
}

/*
 * LE FOCUS DOIT SE VOIR — AD-105 l'écrit en toutes lettres. L'anneau
 * s'ajoute à l'outline de base.css plutôt que de le remplacer : sur un
 * bouton plein, l'outline seul se confond avec la bordure.
 */
.button--primary:focus-visible,
.button--secondary:focus-visible,
.button--text:focus-visible { box-shadow: var(--focus-ring) }

/*
 * DÉSACTIVÉ. Repris de la maquette, qui donne les trois variantes.
 * `cursor: not-allowed` dit ce que la couleur dit déjà, pour qui ne
 * distingue pas bien les gris.
 */
.button--primary:disabled,
.button--primary[aria-disabled="true"] {
    border-color: var(--color-line);
    background: var(--color-state-disabled);
    color: var(--color-ink-subtle);
    cursor: not-allowed;
}

.button--secondary:disabled,
.button--secondary[aria-disabled="true"] {
    border-color: var(--color-line-strong);
    background: transparent;
    color: var(--color-ink-subtle);
    cursor: not-allowed;
}

.button--text:disabled,
.button--text[aria-disabled="true"] {
    color: var(--color-ink-subtle);
    border-color: var(--color-line);
    cursor: not-allowed;
}

/*
 * CHARGEMENT — absent des maquettes, complété ici : AD-105 le demande.
 *
 * TROIS CHOSES, ET AUCUNE N'EST DÉCORATIVE :
 *
 * - le bouton reste à SA LARGEUR, le libellé passant à l'invisible plutôt
 *   qu'à l'absent. Un bouton qui rétrécit pendant l'envoi déplace ce qu'il
 *   y a autour, et le visiteur clique sur autre chose ;
 * - `aria-busy` et `aria-disabled` annoncent l'attente ; c'est ce que voit
 *   un lecteur d'écran, là où les autres voient tourner le trait ;
 * - `pointer-events: none` empêche le second clic, celui qui crée la
 *   deuxième réservation (C1).
 *
 * ⚠️ AD-111 dit « pas de rond qui tourne » — et ne se contredit pas ici.
 * Cette règle vise le chargement d'un CONTENU, où le squelette dit ce que le
 * rond ne dit pas : la forme de ce qui arrive. Un bouton en vol n'a pas de
 * forme à annoncer, il a une durée. Le trait qui tourne y est à sa place, et
 * la préférence de mouvement réduit l'arrête comme le reste.
 */
.button--primary[aria-busy="true"],
.button--secondary[aria-busy="true"],
.button--text[aria-busy="true"] {
    position: relative;
    color: transparent;
    pointer-events: none;
}

.button--primary[aria-busy="true"]::after,
.button--secondary[aria-busy="true"]::after,
.button--text[aria-busy="true"]::after {
    content: "";
    position: absolute;
    width: 18px;
    height: 18px;
    border: 2px solid currentColor;
    border-radius: 50%;
    border-top-color: transparent;
    animation: button-spin .7s linear infinite;
}

.button--primary[aria-busy="true"]::after { border-color: var(--on-surface-accent); border-top-color: transparent }
.button--secondary[aria-busy="true"]::after,
.button--text[aria-busy="true"]::after { border-color: var(--color-brand-strong); border-top-color: transparent }

@keyframes button-spin { to { transform: rotate(360deg) } }

/* ------------------------------------------------------------------ */
/* AD-106 — Champs de formulaire                                      */
/*                                                                    */
/* Copiés de la maquette Contact, à la valeur près. 48 px de haut :    */
/* un champ plus court se rate au doigt, et sous iOS un champ dont la  */
/* police descend sous 16 px fait zoomer la page à la mise au point.   */
/* ------------------------------------------------------------------ */
[data-input] {
    width: 100%;
    padding: 12px 14px;
    border: 1px solid var(--color-line-strong);
    border-radius: var(--radius-md);
    background: var(--surface-page);
    font-size: var(--text-body);
    font-weight: 300;
    color: var(--on-surface-page);
    min-height: 48px;
}

[data-input]:hover:not([disabled]) { border-color: var(--color-brand-strong) }

[data-input]:focus-visible {
    border-color: var(--color-brand-strong);
    outline: 2px solid var(--color-focus);
    outline-offset: 1px;
}

/*
 * L'ERREUR SE VOIT DE DEUX FAÇONS : la bordure ET le fond. Une bordure
 * rouge seule est invisible pour une part non négligeable des hommes, et
 * c'est le champ qu'on ne retrouve pas qui fait abandonner un formulaire.
 */
[data-input][aria-invalid="true"] {
    border-color: var(--on-surface-danger);
    background: var(--surface-danger-soft);
}

[data-input][disabled] {
    background: var(--color-state-disabled);
    color: var(--color-ink-subtle);
    cursor: not-allowed;
}

/*
 * VALIDE — absent des maquettes, complété ici : AD-106 l'énumère.
 *
 * Discret À DESSEIN, et seulement sur la bordure. Un formulaire qui
 * s'illumine en vert à chaque champ rempli crie une bonne nouvelle que
 * personne n'attendait ; ce qu'on veut signaler, c'est le champ qui coince.
 */
[data-input][data-valid] { border-color: var(--color-state-success) }

/* ------------------------------------------------------------------ */
/* Le fil d'étapes du tunnel — bloc « Stepper » de la maquette Tunnel  */
/*                                                                    */
/* ⛔ CES RÈGLES N'AVAIENT JAMAIS ÉTÉ REPRISES. Le balisage portait     */
/* `data-stepper-item` depuis AD-149, aucune feuille ne le lisait : les */
/* pastilles n'avaient ni fond ni bordure, et sans `min-width:0` ni la  */
/* bascule en ronds de 44 px sous 40rem, le fil faisait 594 px de large */
/* sur un écran de 375 — toute la page défilait de côté, à chaque       */
/* étape. Trouvé en vérifiant l'étape Paiement à 375 px (26/09/2026).   */
/*                                                                    */
/* Copié de la maquette à la valeur près, avec la MÊME substitution     */
/* value-identique que le calendrier ci-dessous : `#fff` →              */
/* `--on-surface-brand-dim` (ECARTS-TOKENS.md §3.5).                    */
/* ------------------------------------------------------------------ */
[data-stepper-item]{background:var(--surface-page);border:1px solid var(--color-line);border-radius:var(--radius-pill);color:var(--color-ink-subtle);overflow:hidden;flex:1 1 auto;min-width:0;transition:background-color var(--motion-mid) var(--ease),border-color var(--motion-mid) var(--ease),box-shadow var(--motion-fast) var(--ease)}
[data-stepper-item][data-state="current"]{background:var(--color-brand-strong);border-color:var(--color-brand-strong);color:var(--on-surface-brand-dim);font-weight:500;box-shadow:var(--shadow-soft)}
[data-stepper-item][data-state="done"]{background:var(--color-brand-soft);border-color:var(--color-brand);color:var(--color-brand-strong)}
[data-stepper-item][data-state="current"] [data-stepper-num]{background:var(--on-surface-brand-dim);color:var(--color-brand-strong)}
[data-stepper-item][data-state="done"] [data-stepper-num]{background:var(--color-brand-strong);color:var(--on-surface-brand-dim)}
[data-stepper-item][data-clickable] [data-stepper-inner]{cursor:pointer}
[data-stepper-item][data-clickable]:hover{border-color:var(--color-brand);box-shadow:var(--shadow-soft)}
[data-stepper-item][data-state="done"] [data-stepper-digit],[data-stepper-item][data-state="done"] [data-stepper-check]{display:none}
[data-stepper-item][data-state="done"] [data-stepper-check]{display:block}
[data-stepper-check]{display:none}
[data-stepper-label]{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
@media (max-width:40rem){
  [data-stepper]{justify-content:space-between;gap:var(--space-2xs)}
  [data-stepper-item]{flex:0 0 44px;width:44px;height:44px;border-radius:50%}
  [data-stepper-inner]{padding:0!important;justify-content:center;min-height:0!important}
  [data-stepper-label]{display:none}
}

/* ------------------------------------------------------------------ */
/* AD-107 — Calendrier de disponibilité (front)                       */
/*                                                                    */
/* Copié de la maquette Tunnel, à la valeur près. DEUX MOIS AFFICHÉS,  */
/* UN SEUL SOUS 45rem : le second est retiré du flux plutôt que        */
/* réduit, parce qu'une grille de sept colonnes à 320 px donne des     */
/* cases de 40 px qu'on ne vise plus.                                  */
/*                                                                    */
/* ⚠️ UNE SUBSTITUTION, value-identique : la maquette écrit `#fff` sur */
/* les bornes de séjour. AD-097 exige qu'aucune valeur ne soit en dur  */
/* hors du fichier de tokens ; `--on-surface-brand-dim` vaut #FFFFFF,  */
/* et c'est précisément la paire « encre sur vert de marque ». Aucun   */
/* pixel ne change. Consigné dans ECARTS-TOKENS.md §3.6.               */
/* ------------------------------------------------------------------ */
[data-cal-grids] { display: grid; grid-template-columns: 1fr; gap: var(--space-md) }
[data-cal-month="2"] { display: none }
[data-cal-title="2"] { display: none }

@media (min-width: 45rem) {
    [data-cal-grids] { grid-template-columns: 1fr 1fr }
    [data-cal-month="2"] { display: block }
    [data-cal-title="2"] { display: inline }
}

/*
 * LES SIX ÉTATS DE CASE, et pas un de plus. AD-107 est explicite : ni
 * infobulle ni badge de quantité — ce sont des éléments du back-office. Le
 * visiteur n'a pas à savoir qu'il reste deux cottages sur quatre ; il a à
 * savoir s'il peut cliquer.
 */
[data-day] {
    background: var(--surface-page);
    border: 1px solid var(--color-line);
    color: var(--on-surface-page);
}

[data-day]:hover:not([disabled]) {
    background: var(--color-brand-soft);
    border-color: var(--color-brand);
    color: var(--color-brand-strong);
}

/* 1. Passé — présent mais éteint, pour garder la grille alignée. */
[data-day][data-state="past"] {
    background: none;
    border-color: transparent;
    color: var(--color-ink-subtle);
    opacity: .45;
    cursor: not-allowed;
}

/*
 * 2. Indisponible. LE BARRÉ DOUBLE LA COULEUR, et c'est voulu : rouge sur
 * rose ne se distingue pas de blanc sur blanc pour une part non négligeable
 * des visiteurs.
 */
[data-day][data-state="unavailable"] {
    background: var(--surface-danger-soft);
    border-color: var(--color-line-danger);
    color: var(--on-surface-danger);
    text-decoration: line-through;
    cursor: not-allowed;
}

/* 3. Indisponible ET dans la plage qu'on essaie de tracer. */
[data-day][data-state="in-range-unavailable"] {
    background: var(--surface-danger-soft);
    border-color: var(--on-surface-danger);
    color: var(--on-surface-danger);
    text-decoration: line-through;
    cursor: not-allowed;
}

/* 4 et 5. Les deux bornes du séjour. */
[data-day][data-state="check-in"],
[data-day][data-state="check-out"] {
    background: var(--color-brand-strong);
    border-color: var(--color-brand-strong);
    color: var(--on-surface-brand-dim);
    font-weight: 500;
}

/* 6. Entre les deux bornes. */
[data-day][data-state="in-range"] {
    background: var(--color-brand-soft);
    border-color: var(--color-brand-soft);
    color: var(--color-brand-deep);
}

/* Jours d'un autre mois : la case occupe sa place sans rien montrer. */
[data-day][data-state="out"] { visibility: hidden }

/* Chargement d'une plage : la grille pâlit, elle ne disparaît pas. */
[data-cal-days][data-loading] { opacity: .5 }

/* ------------------------------------------------------------------ */
/* AD-108 — Galerie photo et visionneuse plein écran                  */
/*                                                                    */
/* Copié de la maquette Villa Pastaga, à la valeur près. Deux          */
/* vignettes par ligne sur mobile, quatre au-delà de 48rem.            */
/* ------------------------------------------------------------------ */
[data-gallery-thumbs] { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-2xs) }

@media (min-width: 48rem) {
    [data-gallery-thumbs] { grid-template-columns: repeat(4, 1fr) }
}

/*
 * LA VISIONNEUSE EST DANS LE DOM, masquée. `pointer-events` la rend
 * inatteignable fermée, l'opacité la fait paraître — même mécanique que le
 * menu mobile, et même raison : rien à fabriquer au moment d'ouvrir.
 */
[data-lightbox] {
    position: fixed;
    inset: 0;
    z-index: 80;
    background: rgba(6,34,15,.94);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--motion-mid) var(--ease);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--gutter);
}

[data-lightbox][data-open] { opacity: 1; pointer-events: auto }

/* ------------------------------------------------------------------ */
/* AD-109 — Accordéon (foire aux questions)                           */
/*                                                                    */
/* SUR `<details>` / `<summary>`, PAS SUR DU JAVASCRIPT. Le navigateur */
/* donne gratuitement l'ouverture au clavier, l'état annoncé aux       */
/* lecteurs d'écran, la recherche dans la page qui déplie la bonne     */
/* section, et l'impression qui montre tout. Une réimplémentation en   */
/* boutons et divs perd les quatre, et il faut les réécrire une par    */
/* une.                                                               */
/*                                                                    */
/* Copié de la maquette Contact, à la valeur près.                     */
/* ------------------------------------------------------------------ */
summary::-webkit-details-marker { display: none }
summary { list-style: none; cursor: pointer }

[data-faq] summary {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    justify-content: space-between;
    min-height: 64px;
    padding: var(--space-sm) 0;
}

[data-faq] summary:hover { color: var(--color-brand-strong) }

[data-faq] [data-chevron] { transition: transform var(--motion-fast) var(--ease); flex: 0 0 auto }
[data-faq][open] [data-chevron] { transform: rotate(180deg) }

/* ------------------------------------------------------------------ */
/* AD-111 — Squelettes de chargement                                  */
/*                                                                    */
/* ⛔ PAS DE ROND QUI TOURNE. Un rond dit « attends » ; un squelette   */
/* dit « voici la forme de ce qui arrive ». La page ne saute pas quand */
/* le contenu se pose, parce que la place était déjà prise — et c'est  */
/* aussi le CLS d'AD-262 qu'on évite.                                  */
/*                                                                    */
/* Repris du Back-office, avec UNE substitution : `--app-surface-3`    */
/* appartient au vocabulaire du back-office, qui ne partage aucun      */
/* token avec le public (ECARTS-TOKENS.md §4). Le neutre équivalent du */
/* socle public est `--surface-muted`.                                 */
/*                                                                    */
/* L'ANIMATION EST UNE RESPIRATION D'OPACITÉ, pas un reflet qui        */
/* traverse : moins coûteuse, et elle ne donne pas l'impression que    */
/* quelque chose bouge alors que rien n'avance.                        */
/* ------------------------------------------------------------------ */
@keyframes sk { 0% { opacity: .55 } 50% { opacity: 1 } 100% { opacity: .55 } }

[data-sk] {
    background: var(--surface-muted);
    border-radius: var(--radius-sm);
    animation: sk 1.4s var(--ease) infinite;
    display: block;
    margin: 0;
}

/* ------------------------------------------------------------------ */
/* AD-112 — Gouttières latérales                                      */
/*                                                                    */
/* LE TOKEN EST DANS tokens.css, avec ses deux paliers (48rem → 24px,  */
/* 75rem → 48px), aux valeurs des maquettes. Ce qui suit est le MOTIF  */
/* qui s'en sert, et c'est lui la vraie demande d'AD-112 :             */
/*                                                                    */
/*   « Les sections à fond coloré restent PLEINE LARGEUR, seul leur    */
/*     CONTENU respecte la gouttière. »                                */
/*                                                                    */
/* D'où deux éléments et non un : la section porte le fond et va d'un  */
/* bord à l'autre, le conteneur intérieur porte la largeur maximale et */
/* la marge. Poser la gouttière sur la section elle-même laisserait    */
/* deux bandes blanches sur les côtés d'un bloc vert — le défaut que   */
/* la tâche vise.                                                      */
/*                                                                    */
/* C'est exactement ce que les maquettes écrivent en ligne, partout :  */
/* max-width:var(--measure);margin:0 auto;padding:0 var(--gutter).     */
/* La classe existe pour le balisage que NOUS écrivons ; les pages     */
/* intégrées gardent leurs styles en ligne (diff d'AD-393).            */
/* ------------------------------------------------------------------ */
[data-container] {
    max-width: var(--measure);
    margin-left: auto;
    margin-right: auto;
    padding-left: var(--gutter);
    padding-right: var(--gutter);
}

/*
 * Un conteneur DANS un conteneur ne doit pas doubler la marge — cas qui
 * arrive dès qu'un composant contenant sa propre gouttière est posé dans
 * une section qui en a déjà une.
 */
[data-container] [data-container] { padding-left: 0; padding-right: 0 }

/* ------------------------------------------------------------------ */
/* AD-115 — Confinement du contenu large                              */
/*                                                                    */
/* ⛔ AUCUN `overflow-x: hidden` SUR `body`. C'est le réflexe, et c'est */
/* un pansement : il masque le débordement au lieu de le corriger,     */
/* casse `position: sticky` sur l'en-tête, et rend le défaut           */
/* introuvable puisqu'on ne le voit plus. On CONFINE ce qui est large  */
/* dans son propre conteneur, comme AD-115 le demande en toutes        */
/* lettres.                                                            */
/*                                                                    */
/* Ce qui déborde, dans l'ordre de fréquence :                         */
/*                                                                    */
/* 1. un enfant de grille ou de flexbox dont le contenu est plus large */
/*    que sa colonne. `min-width: 0` lève la taille minimale           */
/*    automatique, qui vaut `auto` par défaut et refuse de rétrécir ;  */
/* 2. un tableau dense — il défile DANS son conteneur, pas dans la     */
/*    page ;                                                          */
/* 3. un mot sans espace : une référence, une URL collée, une adresse  */
/*    email longue.                                                    */
/* ------------------------------------------------------------------ */
[data-table-wrap] { overflow-x: auto; overscroll-behavior-x: contain }
[data-table-wrap] table { min-width: 52rem }

/*
 * `min-width: 0` là où une grille ou un flex peut recevoir du contenu
 * indéformable. Les trois premiers viennent des maquettes ; les deux
 * derniers sont les conteneurs que nous avons ajoutés.
 */
[data-container] > *,
[data-split] > *,
[data-header-inner] > *,
[data-cal-grids] > *,
[data-gallery-thumbs] > * { min-width: 0 }

/*
 * UNE RÉFÉRENCE DE RÉSERVATION NE SE COUPE PAS TOUTE SEULE. `AMD-2026-398981`
 * n'a pas d'espace : sans cette règle, elle pousse sa colonne au-delà de
 * l'écran sur un téléphone étroit. `anywhere` plutôt que `break-word` : le
 * second ne casse qu'en dernier recours et laisse quand même déborder.
 */
[data-wrap-anywhere] { overflow-wrap: anywhere }

/* ------------------------------------------------------------------ */
/* AD-124 / AD-126 — Mise en page de la fiche logement                */
/*                                                                    */
/* Colonne unique sur mobile, contenu + encart au-delà de 62rem.       */
/* Copié de la maquette Villa Pastaga, à la valeur près.               */
/*                                                                    */
/* L'ENCART EXISTE EN DEUX EXEMPLAIRES, ET C'EST LE MOTIF QUI          */
/* CONVERTIT : colonne latérale COLLANTE au desktop — elle suit le     */
/* défilement, donc le prix et le bouton restent sous les yeux pendant */
/* qu'on lit la description — et BARRE FIXE EN BAS D'ÉCRAN sur mobile, */
/* où une colonne latérale n'existe pas. Un seul exemplaire            */
/* obligerait à choisir entre les deux, et à perdre l'un des deux      */
/* parcours.                                                          */
/*                                                                    */
/* `top: 104px` n'est pas arbitraire : c'est la hauteur de l'en-tête   */
/* compacté (AD-100). L'encart s'arrête juste en dessous plutôt que de */
/* passer dessous.                                                     */
/* ------------------------------------------------------------------ */
[data-cols] { display: grid; grid-template-columns: 1fr; gap: var(--space-xl) }
[data-booking-desktop] { display: none }
[data-booking-mobile] { position: fixed; left: 0; right: 0; bottom: 0; z-index: 60 }

@media (min-width: 62rem) {
    /* ⚖️ LA GRILLE N'EST PAS LA MÊME SUR CONTACT (AD-397) : une colonne de
       formulaire n'a pas besoin d'être aussi large qu'une colonne de
       description, et la maquette le dit — 1.3fr/280px contre 1.6fr/300px.
       Unifier était un écart ; chaque page reçoit la valeur de la sienne. */
    [data-cols] { grid-template-columns: minmax(0, 1.6fr) minmax(300px, .9fr); gap: var(--space-2xl); align-items: start }
    [data-page="contact"] [data-cols] { grid-template-columns: minmax(0, 1.3fr) minmax(280px, .8fr) }
    [data-booking-desktop] { display: block; position: sticky; top: 104px }
    [data-booking-mobile] { display: none }
}

/* ------------------------------------------------------------------ */
/* AD-396 — RÈGLES DES MAQUETTES QUI MANQUAIENT À L'INTÉGRATION        */
/*                                                                    */
/* ⛔ TROUVÉES EN COMPARANT LES SÉLECTEURS UN PAR UN, pas à l'œil. Le  */
/* HTML rendu était juste, le diff d'AD-393 était vert, et quatre     */
/* pages rendaient de travers : il manquait les règles qui les        */
/* METTENT EN PAGE. Une feuille de style incomplète ne produit ni     */
/* 404 ni erreur de console — elle produit une page moche, et rien    */
/* d'automatique ne la lit.                                           */
/* ------------------------------------------------------------------ */

/* Le moteur de recherche de l'accueil : DEUX FORMES, jamais les deux */
/* à la fois. En deçà de 62rem, la feuille dépliable ; au-delà, la    */
/* barre en grille de quatre colonnes. Sans ces quatre lignes, les    */
/* deux s'affichaient l'une sous l'autre et la barre perdait sa       */
/* grille — c'est ce qui la rendait méconnaissable.                   */
[data-search="sheet"] { display: block }
[data-search="inline"] { display: none }

/* ⛔ `min-width: 0` SUR LES ENFANTS D'UNE GRILLE. Sans lui, une piste */
/* `minmax(0, 1.6fr)` est débordée par son contenu — une photo large, */
/* un mot long — et la colonne latérale est poussée hors de l'écran.   */
/* C'est le défaut de mise en page le plus fréquent en CSS grid, et   */
/* il ne se voit QUE sur un contenu réel.                             */
[data-cols] > * { min-width: 0 }

/* La photo grandit doucement au survol. C'est le seul mouvement des  */
/* galeries, et `[data-zoom] { overflow: hidden }` le contient.       */
[data-zoom]:hover img { transform: scale(1.04) }

/* ------------------------------------------------------------------ */
/* Formulaire de contact — les états que la maquette pilote en CSS    */
/* ------------------------------------------------------------------ */

/* ⚠️ LE SABLIER TOURNAIT SANS TOURNER. Le bouton d'envoi porte bien  */
/* son `<span data-spinner>` depuis AD-393, mais l'animation n'avait  */
/* jamais été reprise : un rond immobile pendant l'envoi ressemble à  */
/* un bouton en panne.                                                 */
@keyframes spin { to { transform: rotate(360deg) } }
[data-spinner] { animation: spin .8s linear infinite }

/* Un bouton désactivé doit SE VOIR désactivé. Sans cette règle, le   */
/* bouton d'envoi pendant la soumission paraît cliquable et se fait   */
/* cliquer — c'est la double soumission qu'AD-086 combat par ailleurs. */
[data-btn][disabled] { opacity: .45; cursor: not-allowed }

/* Le bandeau d'erreur global part masqué : il n'existe qu'après une  */
/* soumission invalide (AD-135). */
[data-err-global] { display: none }

@media (min-width: 62rem) {
    [data-search="sheet"] { display: none }
    [data-search="inline"] { display: grid }
}

/* ------------------------------------------------------------------ */
/* AD-149 — Mise en page du tunnel, reprise de sa maquette             */
/*                                                                    */
/* Ces règles vivent dans `Tunnel de reservation.dc.html` et n'avaient */
/* pas encore été reprises : le tunnel n'était pas intégré. Elles      */
/* arrivent avec l'écran qui les emploie, pas d'avance.                */
/* ------------------------------------------------------------------ */

/* La colonne principale et la carte récapitulative. Sous 64rem, la    */
/* carte passe SOUS le contenu — une colonne latérale de 380 px sur un */
/* téléphone n'est plus une colonne, c'est un entonnoir.               */
[data-layout] { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-md) }
[data-summary-sticky] { position: static; min-width: 0 }

/* Les champs du formulaire : une colonne sur mobile, deux au-delà de  */
/* 45rem. `[data-full]` traverse les deux — un email ou une adresse    */
/* n'a pas à être coupé en deux.                                       */
[data-field-grid] { display: grid; grid-template-columns: 1fr; gap: var(--space-sm) }
[data-two-cols] { display: grid; grid-template-columns: 1fr; gap: var(--space-xs) }

/* ⛔ `min-height: 48px` N'EST PAS DÉCORATIF : c'est la cible tactile   */
/* minimale. Un champ de 36 px se rate au doigt, et on le rate sur     */
/* l'écran où l'on saisit son email avant de payer.                    */
[data-input] {
    width: 100%;
    padding: 12px 14px;
    border: 1px solid var(--color-line-strong);
    border-radius: var(--radius-md);
    background: var(--surface-page);
    font-size: var(--text-body);
    font-weight: 300;
    color: var(--on-surface-page);
    min-height: 48px;
}

@media (min-width: 45rem) {
    [data-field-grid] { grid-template-columns: 1fr 1fr }
    [data-two-cols] { grid-template-columns: 1fr 1fr }
    [data-full] { grid-column: 1 / -1 }
}

@media (min-width: 64rem) {
    [data-layout] { grid-template-columns: minmax(0, 1fr) 380px; gap: var(--space-lg) }
    [data-summary-sticky] { position: sticky; top: 104px; align-self: start }
}

/* Les trois états du champ, tels que la maquette les écrit. Le focus  */
/* visible est un contour, jamais `outline: none` (AD-105), et         */
/* `aria-invalid` colore le champ EN PLUS du message : la couleur ne   */
/* porte jamais seule le sens.                                        */
[data-input]:hover:not([disabled]) { border-color: var(--color-brand-strong) }
[data-input]:focus-visible { border-color: var(--color-brand-strong); outline: 2px solid var(--color-focus); outline-offset: 1px }
[data-input][aria-invalid="true"] { border-color: var(--on-surface-danger); background: var(--surface-danger-soft) }

/* ------------------------------------------------------------------- */
/* AD-160 — La barre d'actions du tunnel, reprise de sa maquette       */
/*                                                                     */
/* ⛔ CES DEUX RÈGLES MANQUAIENT, et c'est tout AD-160 : « bouton       */
/* d'action principale atteignable au pouce à chaque étape ». Le        */
/* balisage portait `data-sticky` depuis AD-149, aucune feuille ne le   */
/* lisait. Le bouton vivait donc en bas d'un écran qu'il faut faire     */
/* défiler — sur l'étape Coordonnées, cela veut dire remonter après     */
/* avoir rempli douze champs, sur un téléphone tenu d'une main.         */
/*                                                                     */
/* ⚠️ RIEN N'ÉCHOUAIT POUR LE DIRE. La page s'affiche, le bouton        */
/* existe, tous les tests passent. C'est exactement la classe de        */
/* défauts d'AD-394 : un style absent ne lève aucune erreur.            */
/*                                                                     */
/* ⚖️ `62rem` EST LA VALEUR DE LA MAQUETTE. Le commentaire du gabarit   */
/* annonçait « sous 720 px » : c'était faux, 62rem font 992 px. La      */
/* maquette fait foi (AD-369), le commentaire a été corrigé.            */
/*                                                                     */
/* Les marges négatives font toucher la barre aux bords de la carte :   */
/* sans elles, un liseré de fond resterait visible de chaque côté.      */
[data-actions] { display: flex; flex-wrap: wrap; gap: var(--space-xs); justify-content: space-between; align-items: center }

@media (max-width: 62rem) {
    [data-actions][data-sticky] {
        position: sticky;
        bottom: 0;
        z-index: 5;
        margin: 0 calc(-1 * var(--space-sm)) calc(-1 * var(--space-sm));
        padding: var(--space-sm);
        background: var(--surface-page);
        border-top: 1px solid var(--color-line);
        box-shadow: 0 -6px 18px rgba(11, 62, 30, .06);
    }
}

/* ---- AD-397 — Un bloc éditorial rédigé depuis le back-office ---- */
/*
   ⛔ CES RÈGLES NE TOUCHENT AUCUNE MAQUETTE. Elles ne s'appliquent qu'au
   conteneur `[data-rich]` des pages composées en AD-395 — CGV, confidentialité,
   partenaires — dont aucune n'est dessinée dans `docs/design/`. Les pages
   validées par le client gardent leur balisage au caractère près.

   ⚠️ ET LA LISTE DES SÉLECTEURS SUIT LA LISTE BLANCHE DE `RichText`, pas une
   idée de ce qu'un éditeur pourrait produire. Sept boutons, sept balises, plus
   celles que la touche Entrée écrit. Ce qui n'est pas dans cette liste ne
   franchit pas le filtre, donc n'a rien à styler.
*/
[data-rich] > h2 {
    font-family: var(--font-display);
    font-size: var(--text-subheading);
    font-weight: 400;
    line-height: var(--leading-snug);
}

[data-rich] > h3 {
    font-family: var(--font-text);
    font-size: var(--text-body);
    font-weight: 600;
    line-height: var(--leading-snug);
}

[data-rich] > ul,
[data-rich] > ol {
    padding-left: 1.4em;
}

[data-rich] a {
    color: var(--color-brand-strong);
    font-weight: 500;
}
