/*
 * ConstruisToit — feuille de style unique.
 *
 * Mobile-first : toute media query est en min-width.
 *
 * REGLE DE CONTRASTE, NON NEGOCIABLE
 * --color-red (#B02125) sur --color-black (#231F20) donne 2,40:1 et echoue
 * WCAG AA meme en gros texte. Sur fond noir, le rouge n'est QUE du fond de
 * bouton (texte blanc dessus : 6,80:1), de la bordure ou de l'icone.
 * --color-red-light (#C94347) sur noir donne 3,40:1 : titres >= 24px,
 * bordures et icones uniquement, jamais de corps de texte.
 * Sur fond blanc, --color-red est utilisable en texte et en lien (6,80:1).
 */

/* ---------- Polices ---------- */

@font-face {
    font-family: 'Poppins';
    src: url('../fonts/poppins-600.woff2') format('woff2');
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Poppins';
    src: url('../fonts/poppins-700.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Inter';
    src: url('../fonts/inter-400.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Inter';
    src: url('../fonts/inter-500.woff2') format('woff2');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}

/* ---------- Variables ---------- */

:root {
    --color-black: #231F20;
    --color-red: #B02125;
    --color-white: #FFFFFF;
    --color-red-dark: #8A1A1D;
    --color-red-light: #C94347;
    /* Ton legerement chauffe (creme, pas gris froid) - reference client
       (fixbild.webflow.io, capture ecran). Luminance quasi identique a
       l'ancienne valeur (#F5F4F4) : les ratios de contraste documentes
       plus bas restent valables. */
    --color-gray-light: #F5F2EC;
    --color-gray-text: #4A4746;

    --font-title: 'Poppins', system-ui, sans-serif;
    --font-body: 'Inter', system-ui, sans-serif;

    --space-xs: 0.5rem;
    --space-sm: 1rem;
    --space-md: 1.5rem;
    /* space-lg/xl augmentes (demande client) : le site etait juge trop
       dense, doit "respirer" davantage entre les sections et dans les
       cartes. */
    --space-lg: 3.5rem;
    --space-xl: 6rem;

    /* La regle des 4-6px est remplacee par un compromis qui garde la meme
       intention (artisan de confiance, pas startup tech) : pilule franche
       sur ce qui appelle a l'action, rayon modere sur le contenu. */
    --radius-pill: 999px;
    --radius: 10px;
    --radius-sm: 6px;

    --wrap: 1200px;
    /* Hauteur de contenu de la pilule (hors espace de detachement) et
       espace visible entre le bord superieur de l'ecran et la pilule.
       Les deux sont redefinis, plus genereux, a partir de 64rem. */
    --header-h: 56px;
    --header-gap: var(--space-sm);
}

@media (min-width: 64rem) {
    :root {
        --header-h: 64px;
        --header-gap: var(--space-md);
    }
}

/* ---------- Base ---------- */

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    scroll-behavior: smooth;
    /* Compense la pilule flottante (fixed) lors d'un saut vers une ancre. */
    scroll-padding-top: calc(var(--header-gap) + var(--header-h) + var(--space-md));
    /*
     * Garde-fou : plusieurs sections (hero, vitrines) ont des cercles
     * decoratifs positionnes en absolu avec un decalage negatif
     * (ex. right:-6rem), coupes visuellement par l'overflow:hidden de leur
     * propre conteneur. Ce chevauchement ne devrait normalement pas
     * remonter jusqu'au document, mais un vrai defilement horizontal a
     * ete constate en test (96px, soit exactement 6rem) - retour client
     * sur la responsivite. overflow-x:hidden ici bloque tout defilement
     * horizontal du document quelle que soit la source, sans toucher au
     * rendu visuel de ces cercles.
     */
    overflow-x: hidden;
}

body {
    margin: 0;
    font-family: var(--font-body);
    font-weight: 400;
    font-size: 1rem;
    line-height: 1.6;
    color: var(--color-black);
    background: var(--color-white);
    -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
    font-family: var(--font-title);
    font-weight: 700;
    line-height: 1.2;
    margin: 0 0 var(--space-sm);
    text-wrap: balance;
}

h1 {
    font-size: clamp(1.75rem, 5vw, 3rem);
}

/*
 * Majuscules + resserrement (direction Bauhaus/fixbild, validee client
 * 2026-07-28) : uniquement les H2 de section, pas le H1 (deja tres long
 * sur certaines pages, illisible en majuscules a cette taille).
 */
h2 {
    font-size: clamp(1.375rem, 3.5vw, 2.125rem);
    text-transform: uppercase;
    letter-spacing: -0.01em;
}

/*
 * Emphase de couleur sur un mot d'un titre (reference client), plutot
 * qu'un titre uniforme d'une seule couleur. Reserve aux fonds clairs :
 * --color-red y est utilisable en texte (6,80:1) ; sur fond sombre,
 * utiliser --color-red-light a la place (voir .hero-home__title-accent).
 */
.text-accent {
    color: var(--color-red);
}

h3 {
    font-size: clamp(1.125rem, 2.5vw, 1.375rem);
    font-weight: 600;
}

p {
    margin: 0 0 var(--space-sm);
    max-width: 68ch;
}

a {
    color: var(--color-red);
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}

a:hover {
    color: var(--color-red-dark);
}

img {
    max-width: 100%;
    height: auto;
    display: block;
}

/* Anneau de focus visible partout : exigence d'accessibilite. */
:focus-visible {
    outline: 3px solid var(--color-red);
    outline-offset: 2px;
}

/* ---------- Utilitaires ---------- */

.wrap {
    width: 100%;
    max-width: var(--wrap);
    margin-inline: auto;
    padding-inline: var(--space-sm);
}

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.skip-link {
    position: absolute;
    top: -100px;
    left: var(--space-sm);
    z-index: 200;
    padding: var(--space-xs) var(--space-sm);
    background: var(--color-white);
    color: var(--color-red);
    font-weight: 500;
}

.skip-link:focus {
    top: var(--space-xs);
}

/*
 * .site-header est passe en position:fixed pour la pilule flottante : il ne
 * reserve plus d'espace dans le flux normal. On compense ici avec un
 * padding-top sur <main>, calcule a partir des memes variables que la
 * pilule (--header-gap, --header-h) pour ne jamais s'en decaler, plus une
 * marge de respiration.
 */
.site-main {
    padding-top: calc(var(--header-gap) + var(--header-h) + var(--space-md));
}

/* ---------- Sections ---------- */

.section {
    padding-block: var(--space-lg);
}

.section--gray {
    background: var(--color-gray-light);
}

.section--dark {
    background: var(--color-black);
    color: var(--color-white);
}

/*
 * Sur fond noir, les titres passent en blanc. Ils ne passent JAMAIS en
 * --color-red : 2,40:1. --color-red-light reste possible pour un titre
 * >= 24px, mais le blanc est preferable et toujours conforme.
 */
.section--dark h2,
.section--dark h3 {
    color: var(--color-white);
}

.section--dark a:not(.btn) {
    color: var(--color-white);
    text-decoration: underline;
}

.section__intro {
    margin-bottom: var(--space-md);
}

@media (min-width: 48rem) {
    .section {
        padding-block: var(--space-xl);
    }
}

/*
 * Pastille posee avant le H2 d'une section de contenu : un <p>, jamais un
 * titre (voir template-parts/section-badge.php). Fond opaque, donc le
 * contraste ne depend jamais de ce qu'il y a derriere.
 * Fond clair : --color-gray-light / --color-red (6,80:1).
 * Fond sombre (.section-badge--on-dark) : blanc a 10% / texte blanc, jamais
 * --color-red en texte sur fond sombre (2,40:1, voir .section--dark
 * plus haut) — l'icone seule reste rouge, en --color-red-light.
 */
.section-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.4em;
    margin: 0 0 var(--space-xs);
    padding: 0.35rem 0.75rem;
    background: var(--color-gray-light);
    border-radius: var(--radius-pill);
    color: var(--color-red);
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    line-height: 1.2;
}

.section-badge__icon {
    display: inline-flex;
}

.section-badge__icon .ct-icon {
    width: 1rem;
    height: 1rem;
    color: var(--color-red);
}

.section-badge--on-dark {
    background: rgb(255 255 255 / 10%);
    color: var(--color-white);
}

.section-badge--on-dark .section-badge__icon .ct-icon {
    color: var(--color-red-light);
}

/* ---------- Boutons ---------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-xs);
    /* 48px de haut minimum : cible tactile confortable. */
    min-height: 48px;
    padding: 0.75rem var(--space-md);
    border: 2px solid transparent;
    border-radius: var(--radius-pill);
    font-family: var(--font-title);
    font-weight: 600;
    font-size: 1rem;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

/* Blanc sur rouge : 6,80:1, conforme AA sur fond clair comme sur fond noir. */
.btn--primary {
    background: var(--color-red);
    color: var(--color-white);
}

.btn--primary:hover,
.btn--primary:focus {
    background: var(--color-red-dark);
    color: var(--color-white);
}

/* Bouton fantome, utilise sur fond noir : bordure rouge, texte blanc. */
.btn--ghost {
    background: transparent;
    border-color: var(--color-red);
    color: var(--color-white);
}

.btn--ghost:hover,
.btn--ghost:focus {
    background: var(--color-red);
    color: var(--color-white);
}

/* Variante sur fond clair : texte rouge sur blanc, 6,80:1. */
.btn--outline {
    background: transparent;
    border-color: var(--color-red);
    color: var(--color-red);
}

.btn--outline:hover,
.btn--outline:focus {
    background: var(--color-red);
    color: var(--color-white);
}

.btn--block {
    width: 100%;
}

/* Suffixe une fleche au CTA du header, sans la coder en dur dans le HTML. */
.btn--arrow::after {
    content: '\2192';
    margin-left: var(--space-xs);
}

@media (min-width: 30rem) {
    .btn--block {
        width: auto;
    }
}

/* ---------- Cartes ---------- */

/*
 * Registre repris de la reference client (fixbild.webflow.io, capture
 * ecran) : carte plate sur fond clair, sans bordure ni ombre, icone au
 * trait, titre en majuscules rouge, beaucoup d'air en bas de carte.
 */
.card {
    position: relative;
    display: flex;
    flex-direction: column;
    background: var(--color-gray-light);
    height: 100%;
    border-left: 4px solid transparent;
    transition: border-color 0.1s linear, transform 0.1s linear;
}

/*
 * Survol franc, mecanique (direction Bauhaus/fixbild) : une barre pleine
 * apparait instantanement, pas de fondu ni de soulevement mou.
 */
.card:hover {
    border-left-color: var(--color-red);
    transform: translateX(2px);
}

/* Sur fond gris (sections alternees), la carte s'inverse en blanc pour
   rester lisible - meme fond que sa section = invisible sinon. */
.section--gray .card {
    background: var(--color-white);
}

.card__media {
    position: relative;
}

.card__media img {
    width: 100%;
    aspect-ratio: 4 / 5;
    object-fit: cover;
}

.card--media .card__body {
    padding-top: var(--space-md);
}

.card__body {
    padding: var(--space-lg) var(--space-md) var(--space-xl);
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    flex: 1;
}

.card__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-bottom: var(--space-md);
}

/*
 * Pastille numerotee en coin (reference client : Hanover & Tyke). Simple
 * repere visuel entre les cartes d'une meme grille, pas une sequence
 * ordonnee - aria-hidden dans le template pour cette raison.
 */
.card__index {
    position: absolute;
    top: var(--space-sm);
    right: var(--space-sm);
    font-family: var(--font-title);
    font-weight: 700;
    font-size: 0.8125rem;
    color: rgb(35 31 32 / 25%);
}

.card__icon .ct-icon {
    width: 1.75rem;
    height: 1.75rem;
    color: var(--color-red);
}

/*
 * Icone et numero deviennent des pastilles opaques posees sur la photo
 * (reference client : Hanover & Tyke), plutot que du texte au-dessus -
 * la photo devient l'element dominant de la carte. Declarees apres les
 * regles de base (.card__icon/.card__index) pour l'emporter a
 * specificite egale : l'ordre de declaration compte ici.
 */
.card__icon--overlay {
    position: absolute;
    top: var(--space-sm);
    left: var(--space-sm);
    width: 2.75rem;
    height: 2.75rem;
    background: var(--color-white);
    border-radius: var(--radius-sm);
    margin: 0;
}

.card__index--overlay {
    position: absolute;
    top: var(--space-sm);
    right: var(--space-sm);
    padding: 0.25rem 0.5rem;
    background: var(--color-white);
    color: var(--color-black);
    font-size: 0.75rem;
}

.card__title {
    margin: 0;
    color: var(--color-red);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    font-size: 1.0625rem;
}

.card__text {
    margin: 0;
    color: var(--color-black);
    font-size: 0.9375rem;
}

.project__body {
    margin-top: var(--space-xs);
    color: var(--color-gray-text);
    line-height: 1.6;
}

.project__body p {
    margin: 0 0 var(--space-xs);
}

.project__body p:last-child {
    margin-bottom: 0;
}

@media (prefers-reduced-motion: reduce) {
    .card {
        transition: none;
    }
}

/* ---------- Grilles ---------- */

.grid {
    display: grid;
    gap: var(--space-sm);
    grid-template-columns: 1fr;
}

@media (min-width: 40rem) {
    .grid--2,
    .grid--3,
    .grid--4 {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (min-width: 64rem) {
    .grid--3 {
        grid-template-columns: repeat(3, 1fr);
    }

    .grid--4 {
        grid-template-columns: repeat(4, 1fr);
    }
}

/* ---------- Respect des preferences de mouvement ---------- */

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* ---------- Revelation au defilement ---------- */

/*
 * L'etat initial n'est pose que lorsque le script a pris la main (classe
 * ct-js, voir assets/js/main.js) : sans JavaScript, la classe est absente
 * et le contenu reste visible, immediatement.
 */
.ct-js [data-ct-reveal] {
    opacity: 0;
    transform: translateY(20px);
    transition: opacity 0.5s ease-out, transform 0.5s ease-out;
}

.ct-js [data-ct-reveal].is-revealed {
    opacity: 1;
    transform: none;
}

/* Cascade des enfants d'un groupe : cards, grille d'icones. */
.ct-js [data-ct-reveal][data-ct-stagger] > * {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity 0.45s ease-out, transform 0.45s ease-out;
}

.ct-js [data-ct-reveal][data-ct-stagger].is-revealed > * {
    opacity: 1;
    transform: none;
}

.ct-js [data-ct-reveal][data-ct-stagger].is-revealed > *:nth-child(2) { transition-delay: 0.08s; }
.ct-js [data-ct-reveal][data-ct-stagger].is-revealed > *:nth-child(3) { transition-delay: 0.16s; }
.ct-js [data-ct-reveal][data-ct-stagger].is-revealed > *:nth-child(4) { transition-delay: 0.24s; }
.ct-js [data-ct-reveal][data-ct-stagger].is-revealed > *:nth-child(5) { transition-delay: 0.32s; }
.ct-js [data-ct-reveal][data-ct-stagger].is-revealed > *:nth-child(6) { transition-delay: 0.40s; }






/*
 * Garde-fou non negociable : meme avec la classe ct-js posee, un visiteur
 * qui demande moins de mouvement ne doit jamais voir un contenu fige a
 * opacity:0. Regle dediee plutot que de compter sur le bloc generique
 * ci-dessus (qui neutralise la duree mais pas l'etat initial).
 */
@media (prefers-reduced-motion: reduce) {
    .ct-js [data-ct-reveal],
    .ct-js [data-ct-reveal] > * {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }
}

/* ---------- En-tete ---------- */

/*
 * Pilule flottante : reference client (pilule sombre flottante, logo a
 * gauche, liens centres, bloc contact en pilule blanche a droite),
 * reproduite dans la palette du projet (fond blanc translucide, pas la
 * palette sombre de la reference). .site-header est un conteneur plein
 * largeur, transparent, position:fixed ; padding-block-start cree l'espace
 * visible qui detache la pilule du bord superieur. .site-header__inner est
 * la pilule elle-meme : largeur contenue, fond blanc translucide + flou,
 * coins totalement arrondis (--radius-pill).
 *
 * position:fixed plutot que sticky : sticky suppose un ancrage a un bord
 * (top:0) et une bande qui redevient plate contre ce bord une fois collee.
 * Ici la pilule reste en permanence detachee du bord, meme au scroll : il
 * n'y a jamais d'etat "colle".
 */
.site-header {
    position: fixed;
    top: 0;
    inset-inline: 0;
    z-index: 100;
    padding-block-start: var(--header-gap);
    padding-inline: var(--space-sm);
}

@media (min-width: 64rem) {
    .site-header {
        padding-inline: var(--space-lg);
    }
}

/*
 * Mobile : ligne flex simple (logo, bouton hamburger, telephone), avec wrap
 * pour que le panneau de nav (menu + CTA) tombe sur une ligne dediee sous
 * cette rangee quand il s'ouvre. Desktop : grille 3 colonnes, voir plus bas.
 *
 * Vrai verre depoli (reference client : panneaux type iOS/liquid glass,
 * fond nettement visible en transparence, pas une pilule blanche a peine
 * translucide sur les bords). Les iterations precedentes restaient
 * dominees par du blanc (88-97% d'opacite) precisement pour proteger le
 * contraste du rouge au survol - insuffisant pour l'effet demande.
 *
 * Ici, la teinte blanche descend beaucoup plus bas (35-55%), et c'est
 * `brightness()` dans backdrop-filter qui protege la lisibilite : il
 * eclaircit ce qu'il y a DERRIERE avant le mélange, au lieu de compter sur
 * une couche blanche opaque par-dessus. Sur les photos du site (toutes
 * plutot claires - toits, ciel), le texte noir reste largement lisible ;
 * si une future photo de fond tres sombre est utilisee ici, revalider le
 * contraste avant de la publier telle quelle.
 * Repli @supports pour les navigateurs sans backdrop-filter : fond blanc
 * opaque, texte toujours lisible.
 */
.site-header__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-sm);
    min-height: var(--header-h);
    max-width: var(--wrap);
    margin-inline: auto;
    padding-block: var(--space-xs);
    padding-inline: var(--space-md);
    background: linear-gradient(
        135deg,
        rgb(255 255 255 / 55%) 0%,
        rgb(255 255 255 / 40%) 45%,
        rgb(255 255 255 / 32%) 100%
    );
    backdrop-filter: blur(30px) saturate(160%) brightness(1.25);
    -webkit-backdrop-filter: blur(30px) saturate(160%) brightness(1.25);
    border: 1px solid rgb(255 255 255 / 60%);
    border-radius: var(--radius-pill);
    box-shadow: 0 8px 30px rgb(35 31 32 / 14%), inset 0 1px 0 rgb(255 255 255 / 90%);
}

@supports not (backdrop-filter: blur(1px)) {
    .site-header__inner {
        background: var(--color-white);
    }
}

/*
 * Panneau mobile ouvert : le conteneur grandit pour accueillir le menu et le
 * CTA replies sous la ligne logo/telephone (display:flex + flex-wrap sur
 * .site-header__inner, voir plus haut). On garde le meme fond translucide,
 * le meme flou et les memes marges laterales que la pilule fermee : c'est
 * le meme bloc flottant qui s'etire pour occuper la largeur disponible sous
 * la ligne du haut, pas un second element separe. Le rayon passe en
 * revanche de la pilule pleine (999px, adaptee a une seule ligne fine) a un
 * rayon plus modere : sur un bloc devenu plus haut, 999px degenererait en
 * deux demi-cercles etires en haut/bas plutot qu'en pilule lisible.
 */
.nav-is-open .site-header__inner {
    border-radius: var(--radius);
}

.site-header__brand {
    margin-right: auto;
}

.site-header__logo,
.custom-logo-link {
    display: inline-flex;
    align-items: center;
    text-decoration: none;
}

/*
 * Le logo est empile : le monogramme surmonte le mot, qui n'occupe qu'un
 * gros quart de la hauteur totale. A 44px, "ConstruisToit" tombait sous les
 * 12px et devenait illisible. On monte donc la hauteur, davantage sur les
 * grands ecrans ou la barre a de la place.
 *
 * Selecteur .custom-logo-link, pas .site-header__logo : the_custom_logo()
 * emet sa propre ancre .custom-logo-link autour de l'image (voir header.php,
 * ne jamais la reenvelopper d'une seconde ancre). .site-header__logo ne
 * cible plus que le lien de repli texte quand aucun logo personnalise n'est
 * defini.
 */
.custom-logo-link img {
    max-height: 84px;
    width: auto;
}

@media (min-width: 64rem) {
    .custom-logo-link img {
        max-height: 100px;
    }
}

/*
 * Logo texte de repli, utilise uniquement si aucun logo personnalise n'est
 * defini. Reprend les couleurs du logo reel sur fond blanc : "Construis" en
 * noir, "Toit" en rouge (6,80:1, conforme).
 */
.logo-text {
    font-family: var(--font-title);
    font-weight: 700;
    font-size: 1.25rem;
    letter-spacing: -0.02em;
    color: var(--color-black);
}

.logo-text__second {
    color: var(--color-red);
}

.site-header__toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    background: transparent;
    border: 1px solid rgb(35 31 32 / 25%);
    /* Bouton icone sans texte, meme registre que .btn : pilule (= cercle sur un carre). */
    border-radius: var(--radius-pill);
    cursor: pointer;
}

.site-header__burger,
.site-header__burger::before,
.site-header__burger::after {
    display: block;
    width: 20px;
    height: 2px;
    background: var(--color-black);
    content: '';
}

.site-header__burger::before {
    transform: translateY(-6px);
}

.site-header__burger::after {
    transform: translateY(4px);
}

/*
 * La nav elle-meme n'a jamais de boite propre : c'est display:contents en
 * permanence (mobile comme desktop). Ses enfants directs (.site-nav__list
 * et .site-header__actions) deviennent des items flex/grid directs de
 * .site-header__inner et gerent chacun leur propre visibilite. Le noeud
 * <nav> reste en place dans le DOM (display:contents ne touche que le
 * rendu, jamais la structure), donc initNav() dans main.js continue de le
 * cibler sans modification : querySelector, nav.contains(), le piege de
 * focus et la resynchronisation matchMedia fonctionnent a l'identique, et
 * couvrent maintenant aussi le telephone puisqu'il reste un descendant DOM
 * de <nav>.
 */
.site-nav {
    display: contents;
}

/* Panneau de menu, ferme par defaut sur mobile, fond blanc herite du header. */
.site-nav__list {
    display: none;
    width: 100%;
    order: 3;
    list-style: none;
    margin: 0 0 var(--space-sm);
    padding: 0;
    flex-direction: column;
    gap: var(--space-xs);
}

.nav-is-open .site-nav__list {
    display: flex;
}

.site-nav__list a {
    display: block;
    padding: 0.625rem 0;
    color: var(--color-black);
    text-decoration: none;
    font-family: var(--font-title);
    font-weight: 600;
    border-bottom: 1px solid rgb(35 31 32 / 12%);
}

.site-nav__list a:hover,
.site-nav__list .current-menu-item > a {
    /* Rouge sur blanc : 6,80:1, conforme. */
    color: var(--color-red);
    border-bottom-color: var(--color-red);
}

/*
 * CTA + telephone regroupes : sur mobile, display:contents laisse chaque
 * enfant se comporter comme un item flex independant de .site-header__inner
 * (le CTA masque par defaut, replie dans le panneau ouvert ; le telephone
 * toujours visible). Sur desktop, ce conteneur redevient une vraie boite
 * flex (voir plus bas) pour que CTA et telephone forment un seul bloc, alignes
 * a droite, dans la colonne 3 de la grille.
 */
.site-header__actions {
    display: contents;
}

.site-nav__cta {
    display: none;
    width: auto;
    order: 4;
}

.nav-is-open .site-nav__cta {
    display: inline-flex;
}

@media (min-width: 64rem) {
    .site-header__toggle {
        display: none;
    }

    /*
     * Grille a 3 colonnes : la colonne centrale porte le centrage reel du
     * menu, independamment de la largeur du bloc de droite (CTA +
     * telephone). Colonne 1 (1fr) et colonne 3 (1fr) recoivent toujours un
     * espace strictement egal, quel que soit le contenu de chacune : c'est
     * la mecanique meme des pistes "fr" qui garantit l'egalite, pas une
     * coincidence de largeurs entre le logo et le bloc CTA+telephone.
     */
    .site-header__inner {
        display: grid;
        grid-template-columns: 1fr auto 1fr;
        align-items: center;
        gap: var(--space-sm);
        min-height: var(--header-h);
        padding-block: var(--space-xs);
        padding-inline: var(--space-lg);
    }

    .site-header__brand {
        grid-column: 1;
        justify-self: start;
        margin-right: 0;
    }

    .site-nav__list {
        display: flex;
        grid-column: 2;
        justify-self: center;
        width: auto;
        order: initial;
        flex-direction: row;
        align-items: center;
        gap: var(--space-md);
        margin: 0;
    }

    .site-nav__list a {
        padding: 0.25rem 0;
        border-bottom: 2px solid transparent;
    }

    .site-header__actions {
        display: flex;
        align-items: center;
        gap: var(--space-sm);
        grid-column: 3;
        justify-self: end;
    }

    .site-nav__cta {
        display: inline-flex;
        order: initial;
        width: auto;
        flex-shrink: 0;
    }
}

/* ---------- Bande CTA ---------- */

.cta-band {
    position: relative;
    padding-block: var(--space-lg);
    /* Accent fin en haut de la bande : casse le fond noir uni, sans texte rouge. */
    border-top: 3px solid var(--color-red);
}

.cta-band__inner {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}

.cta-band__intro {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
}

/*
 * Carre (radius-sm), pas un cercle : reprend le traitement d'icone observe
 * sur la section sombre de la reference (fixbild.webflow.io, capture
 * ecran) plutot que la pastille circulaire generique.
 */
.cta-band__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 3rem;
    height: 3rem;
    background: var(--color-white);
    border-radius: var(--radius-sm);
}

.cta-band__icon .ct-icon {
    width: 1.5rem;
    height: 1.5rem;
    color: var(--color-red);
}

.cta-band__title {
    margin-bottom: var(--space-xs);
}

.cta-band__text {
    margin: 0;
    color: var(--color-white);
}

.cta-band__actions {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
}

@media (min-width: 48rem) {
    .cta-band__inner {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }

    .cta-band__actions {
        flex-direction: row;
        flex-shrink: 0;
    }
}

/* ---------- Section feature-grid (six items) ---------- */

/*
 * Reference Gaborone : fond noir de section, carte rouge a gauche (argument
 * + CTA), grille 2x3 a droite sur fonds legerement plus clairs que le fond
 * de section. Contraste : le rouge ne sert ici qu'en fond de carte, en fond
 * de cercle d'icone et en trait d'icone, jamais en texte sur fond sombre —
 * titres et sous-textes de la section restent blancs (voir .section--dark
 * plus haut pour la regle generale).
 */
.feature-grid__inner {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}

.feature-grid__card {
    padding: var(--space-md);
    background: var(--color-red);
    border-radius: var(--radius);
    color: var(--color-white);
}

.feature-grid__card-title {
    color: var(--color-white);
}

.feature-grid__card-text {
    color: var(--color-white);
}

/* Bouton clair sur la carte rouge : un bouton rouge sur fond rouge serait
   illisible, et du texte rouge sur ce fond enfreindrait la regle de
   contraste. Fond blanc, texte rouge (6,80:1) — le rouge reste sur un fond
   clair local, jamais en texte sur fond sombre. */
.feature-grid__cta {
    background: var(--color-white);
    color: var(--color-red);
}

.feature-grid__cta:hover,
.feature-grid__cta:focus {
    background: var(--color-gray-light);
    color: var(--color-red-dark);
}

.feature-grid__items {
    display: grid;
    gap: var(--space-sm);
    grid-template-columns: 1fr;
}

/*
 * Fin trait rouge a gauche plutot qu'une boite pleine (#2C2829 abandonne) :
 * reprend le separateur vertical observe sur la section sombre de la
 * reference (capture ecran fixbild.webflow.io), plus proche du registre
 * "angles nets" que d'une carte.
 */
.feature-grid__item {
    padding-left: var(--space-sm);
    border-left: 2px solid var(--color-red);
}

/*
 * Carre (radius-sm) sur fond clair, pas un cercle : reprend le traitement
 * d'icone de la section sombre observee sur la reference (capture ecran
 * fixbild.webflow.io). --color-red reste conforme (fond blanc local, pas
 * de texte rouge sur le noir - voir la regle de contraste en tete de
 * fichier).
 */
.feature-grid__item-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    margin-bottom: var(--space-xs);
    background: var(--color-white);
    border-radius: var(--radius-sm);
}

.feature-grid__item-icon .ct-icon {
    color: var(--color-red);
}

.feature-grid__item-title {
    margin: 0 0 var(--space-xs);
    color: var(--color-white);
}

.feature-grid__item-text {
    margin: 0;
    color: var(--color-white);
    font-size: 0.9375rem;
}

@media (min-width: 40rem) {
    .feature-grid__items {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (min-width: 64rem) {
    .feature-grid__inner {
        flex-direction: row;
        align-items: stretch;
    }

    .feature-grid__card {
        flex: 0 0 30%;
        display: flex;
        flex-direction: column;
        justify-content: center;
    }

    .feature-grid__items {
        flex: 1;
        grid-template-columns: repeat(3, 1fr);
    }
}

/* ---------- Barre de statistiques ---------- */

/*
 * Reference RooFix : quatre cartes chiffre + libelle, fond gris clair pour
 * se detacher du blanc environnant sans recourir a une couleur de marque.
 * Semantique <dl> (voir template-parts/stats-bar.php) : chaque .stats-bar__item
 * est le wrapper <div> autorise par la spec HTML autour d'un couple dt/dd,
 * et sert ici de cellule de grille.
 */
.stats-bar__grid {
    display: grid;
    gap: var(--space-sm);
    grid-template-columns: repeat(2, 1fr);
    margin: 0;
}

.stats-bar__item {
    padding: var(--space-md) var(--space-sm);
    background: var(--color-gray-light);
    border-radius: var(--radius);
    text-align: center;
}

.stats-bar__value {
    margin: 0;
    font-family: var(--font-title);
    font-weight: 700;
    font-size: clamp(1.75rem, 4vw, 2.5rem);
    color: var(--color-red);
}

.stats-bar__label {
    margin: var(--space-xs) 0 0;
    font-size: 0.9375rem;
    color: var(--color-gray-text);
}

@media (min-width: 48rem) {
    .stats-bar__grid {
        grid-template-columns: repeat(4, 1fr);
    }
}

/* ---------- Pied de page ---------- */

.site-footer {
    padding-top: var(--space-lg);
}

.site-footer__grid {
    display: grid;
    gap: var(--space-md);
    grid-template-columns: 1fr;
}

.site-footer__title {
    font-size: 1rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: var(--space-xs);
}

.site-footer__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
}

.site-footer__list a {
    color: var(--color-white);
}

.nap p {
    margin: 0 0 var(--space-xs);
}

.nap__phone a {
    font-family: var(--font-title);
    font-weight: 700;
    font-size: 1.25rem;
    color: var(--color-white);
}

.nap__hours {
    color: var(--color-white);
    font-size: 0.9375rem;
}

.site-footer__socials {
    display: flex;
    gap: var(--space-xs);
    margin: var(--space-sm) 0 0;
    padding: 0;
    list-style: none;
}

.site-footer__socials a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    background: rgb(255 255 255 / 10%);
    border-radius: 50%;
    color: var(--color-white);
}

.site-footer__socials a:hover,
.site-footer__socials a:focus-visible {
    background: var(--color-red);
}

.site-footer__socials .ct-icon {
    width: 1.125rem;
    height: 1.125rem;
}

.site-footer__legal {
    margin-top: var(--space-lg);
    padding-block: var(--space-sm);
    border-top: 1px solid rgb(255 255 255 / 15%);
    font-size: 0.875rem;
}

.site-footer__legal p {
    margin: 0;
}

@media (min-width: 48rem) {
    .site-footer__grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (min-width: 64rem) {
    .site-footer__grid {
        grid-template-columns: repeat(4, 1fr);
    }
}

/* ---------- Formulaire de devis ---------- */

.form-devis__lead {
    color: var(--color-gray-text);
}

/*
 * Centre le bloc entier (pastille + titre + accroche + formulaire) au lieu
 * du seul <form> : sinon le titre reste cale a gauche du .wrap pendant que
 * le formulaire se centre en dessous, deux alignements differents dans la
 * meme section. En dessous de 720px de large, l'ecran est plus etroit que
 * le bloc et margin-inline:auto ne change rien (comportement identique a
 * avant sur mobile).
 */
/*
 * Panneau lateral (form-devis-side) ajoute a cote du formulaire sur grand
 * ecran : retour client, la section semblait vide (grand espace blanc a
 * cote du formulaire centre). Sur mobile, les deux blocs restent
 * simplement empiles (aucune grille necessaire en dessous de 64rem).
 */
@media (min-width: 64rem) {
    .form-devis-layout {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 20rem;
        gap: var(--space-xl);
        align-items: start;
    }
}

.form-devis-block {
    max-width: 720px;
    margin-inline: auto;
    text-align: center;
}

@media (min-width: 64rem) {
    .form-devis-block {
        margin-inline: 0;
    }
}

/* Le contenu du formulaire (labels, champs) reste aligne a gauche : seul le
   bloc titre/accroche au-dessus est centre. */
.form-devis-block .form-devis {
    text-align: left;
}

.form-devis-side {
    display: none;
}

@media (min-width: 64rem) {
    .form-devis-side {
        display: block;
        margin-top: var(--space-xl);
    }
}

.form-devis-side__card {
    padding: var(--space-lg) var(--space-md);
    background: var(--color-gray-light);
    border-radius: var(--radius);
}

.form-devis-side__label {
    margin: 0 0 var(--space-xs);
    color: var(--color-gray-text);
    font-size: 0.8125rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 600;
}

.form-devis-side__phone {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: var(--space-md);
    color: var(--color-red);
    font-family: var(--font-title);
    font-weight: 700;
    font-size: 1.375rem;
    text-decoration: none;
}

.form-devis-side__phone .ct-icon {
    width: 1.375rem;
    height: 1.375rem;
}

.form-devis-side__list {
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
    margin: 0 0 var(--space-md);
    padding: 0;
    list-style: none;
}

.form-devis-side__list li {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    color: var(--color-black);
    font-size: 0.9375rem;
}

.form-devis-side__list .ct-icon {
    width: 1.25rem;
    height: 1.25rem;
    color: var(--color-red);
    flex-shrink: 0;
}

.form-devis-side__link {
    display: inline-block;
    color: var(--color-red);
    font-weight: 500;
    font-size: 0.9375rem;
}

.form-devis__grid {
    display: grid;
    gap: var(--space-sm);
    grid-template-columns: 1fr;
}

.form-devis__field {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    margin: 0 0 var(--space-sm);
}

.form-devis__field label {
    font-weight: 500;
    font-size: 0.9375rem;
}

.form-devis__hint {
    font-weight: 400;
    color: var(--color-gray-text);
}

.form-devis input[type='text'],
.form-devis input[type='tel'],
.form-devis input[type='email'],
.form-devis select,
.form-devis textarea {
    width: 100%;
    /* 48px : cible tactile confortable et coherente avec les boutons. */
    min-height: 48px;
    padding: 0.625rem 0.75rem;
    font-family: var(--font-body);
    font-size: 1rem;
    color: var(--color-black);
    background: var(--color-white);
    border: 1px solid rgb(35 31 32 / 30%);
    border-radius: var(--radius-sm);
}

.form-devis textarea {
    min-height: 120px;
    resize: vertical;
}

.form-devis [aria-invalid='true'] {
    border-color: var(--color-red);
    border-width: 2px;
}

/* Texte rouge sur fond blanc : 6,80:1, conforme. */
.form-devis__error {
    color: var(--color-red);
    font-size: 0.875rem;
    font-weight: 500;
}

/* Champ leurre : hors ecran plutot que display:none, que certains robots detectent. */
.form-devis__hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.form-devis__consent {
    margin-bottom: var(--space-md);
}

.form-devis__consent label {
    display: flex;
    align-items: flex-start;
    gap: var(--space-xs);
    font-size: 0.875rem;
    line-height: 1.5;
}

.form-devis__consent input {
    /* Cible tactile decente pour une case a cocher. */
    width: 22px;
    height: 22px;
    flex-shrink: 0;
    margin-top: 1px;
    accent-color: var(--color-red);
}

.form-devis__actions {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-xs);
}

.form-devis__or {
    font-size: 0.9375rem;
    color: var(--color-gray-text);
}

.form-devis__status:empty,
.form-devis__flash:empty {
    display: none;
}

.form-devis__status,
.form-devis__flash {
    padding: var(--space-xs) var(--space-sm);
    border-left: 4px solid var(--color-gray-text);
    background: var(--color-gray-light);
    font-weight: 500;
}

.form-devis__status.is-ok,
.form-devis__flash.is-ok {
    border-left-color: #1B7F3B;
    color: #14602C;
}

.form-devis__status.is-error,
.form-devis__flash.is-error {
    border-left-color: var(--color-red);
    color: var(--color-red);
}

/* Le formulaire sur fond noir garde des champs clairs et lisibles. */
.section--dark .form-devis__lead,
.section--dark .form-devis__hint,
.section--dark .form-devis__or {
    color: var(--color-white);
}

@media (min-width: 40rem) {
    .form-devis__grid {
        grid-template-columns: repeat(2, 1fr);
    }

    .form-devis__actions {
        flex-direction: row;
        align-items: center;
        gap: var(--space-sm);
    }
}

/* ---------- Hero (partage par les pages piliers Toiture/Facade) ---------- */

/*
 * Meme traitement que le hero de l'accueil (template-parts/hero-home.php) :
 * photo plein format en fond, degrade continu (pas un voile plat uniforme
 * comme la premiere version - juge insuffisant sur une photo claire),
 * cercles decoratifs, pleine hauteur d'ecran remontant sous la pilule du
 * header. Harmonisation demandee par le client le 2026-07-30, en repartant
 * de l'accueil comme reference - meme formules, memes variables.
 */
.hero {
    position: relative;
    overflow: hidden;
    min-height: 100vh;
    min-height: 100dvh;
    margin-top: calc(-1 * (var(--header-gap) + var(--header-h) + var(--space-md)));
}

.hero::before,
.hero::after {
    content: '';
    position: absolute;
    z-index: 0;
    border-radius: 50%;
    border: 1px solid rgb(255 255 255 / 18%);
    pointer-events: none;
}

.hero::before {
    top: -6rem;
    right: -6rem;
    width: 18rem;
    height: 18rem;
}

.hero::after {
    bottom: 8rem;
    right: 12rem;
    width: 8rem;
    height: 8rem;
    border-color: rgb(176 33 37 / 35%);
    display: none;
}

@media (min-width: 64rem) {
    .hero::after {
        display: block;
    }
}

.hero__media {
    position: absolute;
    inset: 0;
    background: var(--color-black);
}

.hero__img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Degrade continu, du bas (le plus sombre) au haut (le moins sombre, mais
   jamais a 0%) : memes valeurs que .hero-home__media::after, pour que les
   deux heros du site se degradent de facon identique. */
.hero__media::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(
        to top,
        rgb(35 31 32 / 90%) 0%,
        rgb(35 31 32 / 55%) 55%,
        rgb(35 31 32 / 35%) 100%
    );
    pointer-events: none;
}

.hero__inner {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding-block: var(--space-md);
}

.hero__title {
    margin: 0;
    color: var(--color-white);
    font-size: clamp(2.25rem, 5vw, 4.25rem);
    line-height: 1.05;
    letter-spacing: -0.01em;
}

.hero__title-accent {
    color: var(--color-red-light);
}

.hero__subtitle {
    color: var(--color-white);
    font-size: 1.0625rem;
    max-width: 50ch;
    margin-block: var(--space-sm) 0;
}

.hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
    margin-top: var(--space-md);
}

@media (min-width: 48rem) {
    .hero__subtitle {
        font-size: 1.125rem;
    }
}

/* ---------- Hero accueil (image scindee + carte devis) ---------- */

/*
 * Variante du hero reservee a la page d'accueil (voir template-parts/
 * hero-home.php) : image a gauche avec titre pose dessus en bas, carte
 * devis flottante a droite sur le fond clair de la page. Ne remplace pas
 * .hero (template-parts/hero.php), qui reste utilise tel quel par les
 * pages piliers.
 *
 * Mobile : empile (image+titre, puis carte), comme l'ancien hero.
 * Desktop (64rem) : deux colonnes cote a cote.
 */
/*
 * .hero-home-group regroupe la section photo et la carte devis : elles ne
 * partagent le meme repere de positionnement (la carte flottant sur la
 * photo) qu'a partir de 64rem, voir plus bas.
 */
/*
 * La photo doit remonter jusqu'au tout haut de la page, sous la pilule
 * flottante de l'en-tete (comme la maquette de reference), pas seulement
 * en dessous : .site-main pousse tout son contenu vers le bas d'un
 * padding-top qui compense l'en-tete en position:fixed (voir .site-main
 * plus haut). Ce margin-top negatif, de la meme valeur, annule ce
 * decalage pour le hero d'accueil uniquement - le fond blanc visible
 * autour de la pilule disparait, remplace par la photo. La pilule reste
 * au-dessus (position:fixed, z-index:100), la photo passe dessous.
 */
.hero-home-group {
    margin-top: calc(-1 * (var(--header-gap) + var(--header-h) + var(--space-md)));
    margin-bottom: 0;
}

/*
 * La photo occupe la section entiere, bord a bord (demande client du
 * 2026-07-27) : .hero-home__media est un enfant direct de <section>, pas
 * imbrique dans .wrap, sinon le max-width/padding-inline de .wrap la
 * fait apparaitre comme une carte inscrite avec des marges visibles,
 * pas un fond plein format. min-height est pose ICI, sur .hero-home,
 * car .hero-home__media et .hero-home__content sont tous deux en
 * position absolute : aucun des deux ne contribue a la hauteur naturelle
 * de la section, qui s'effondrerait a 0 sans ce plancher explicite.
 * Pas de border-radius/overflow:hidden non plus : un bord-a-bord n'a pas
 * de coins a couper.
 */
/*
 * 100vh (demande client) : desormais coherent puisque .hero-home-group
 * remonte au tout haut de la page (margin-top negatif ci-dessus) - la
 * section occupe alors exactement la hauteur de l'ecran au chargement,
 * pilule flottante comprise. 100dvh en repli la ou le navigateur le
 * supporte, pour eviter le saut de la barre d'adresse mobile.
 */
.hero-home {
    position: relative;
    min-height: 100vh;
    min-height: 100dvh;
    overflow: hidden;
}

/*
 * Cercles decoratifs legers (reference client, fixbild.webflow.io) : simples
 * anneaux fins, jamais de fond plein - z-index:0 pour rester entre la photo
 * (auto) et le contenu (.hero-home__inner, z-index:1).
 */
.hero-home::before,
.hero-home::after {
    content: '';
    position: absolute;
    z-index: 0;
    border-radius: 50%;
    border: 1px solid rgb(255 255 255 / 18%);
    pointer-events: none;
}

.hero-home::before {
    top: -6rem;
    right: -6rem;
    width: 18rem;
    height: 18rem;
}

.hero-home::after {
    bottom: 8rem;
    right: 12rem;
    width: 8rem;
    height: 8rem;
    border-color: rgb(176 33 37 / 35%);
    display: none;
}

@media (min-width: 64rem) {
    .hero-home::after {
        display: block;
    }
}

.hero-home__media {
    position: absolute;
    inset: 0;
    background: var(--color-black);
}

.hero-home__img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/*
 * Contraste, regle non negociable. Historique : un voile plein a 35% sur
 * toute la photo avait ete juge insuffisant sur une photo claire, remplace
 * par un degrade limite au bas de l'image - puis juge "mal degrade" (le
 * palier plat suivi d'une chute rapide vers 0% créait une transition trop
 * visible, presque une ligne). Ce degrade-ci couvre toute la section
 * (inset:0, demande client du 2026-07-28) mais reste continu du haut en
 * bas, sans palier ni retour a 0% : meme le haut de la photo garde un
 * minimum de voile (35%), le texte repose toujours sur la zone la plus
 * sombre (90%) sans bord net entre les deux.
 */
.hero-home__media::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(
        to top,
        rgb(35 31 32 / 90%) 0%,
        rgb(35 31 32 / 55%) 55%,
        rgb(35 31 32 / 35%) 100%
    );
    pointer-events: none;
}

/*
 * .hero-home__inner (.wrap) est le repere de positionnement de
 * .hero-home__content : absolute + inset:0 le fait occuper toute la boite
 * de .hero-home (la photo), tout en conservant le max-width/padding-inline
 * herites de .wrap pour l'alignement horizontal du texte. justify-content:
 * flex-end pousse le contenu vers le bas, sur la partie assombrie du
 * degrade (.hero-home__media::after).
 */
.hero-home__inner {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding-block: var(--space-md);
}

.hero-home__content {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-xs);
}

/*
 * Echelle typographique large mais mesuree : un premier passage (clamp
 * jusqu'a 5.5rem) a ete juge trop imposant et desequilibre par rapport a la
 * photo (retour client du 2026-07-28) - reduit ici sans redevenir un bloc de
 * texte modeste. Propre a hero-home, ne touche pas le h1 des autres
 * gabarits (hero.php, pages piliers).
 */
.hero-home__title {
    margin: 0;
    color: var(--color-white);
    font-size: clamp(2.25rem, 5vw, 4.25rem);
    line-height: 1.05;
    letter-spacing: -0.01em;
}

/*
 * --color-red-light, jamais --color-red plein : sur fond sombre, le rouge
 * plein ne passe pas en texte (2,40:1). red-light n'est autorise en texte
 * que sur un titre >= 24px (regle en tete de fichier) - le H1 du hero
 * demarre a 1.75rem (28px), la condition est remplie.
 */
.hero-home__title-accent {
    color: var(--color-red-light);
}

.hero-home__subtitle {
    margin: 0;
    color: var(--color-white);
    font-size: 1.0625rem;
    max-width: 42ch;
}

.hero-home__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
    margin-top: var(--space-xs);
}

.hero-badges {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
    margin: var(--space-xs) 0 0;
    padding: 0;
    list-style: none;
}

/*
 * Pastille texte, pas de logo de marque tierce (Google, BBB) : fond
 * --color-gray-light opaque, texte --color-black. Le fond de la pastille
 * est totalement opaque, donc son contraste ne depend jamais de la photo
 * ni du degrade en dessous.
 *
 * Le style vit sur .hero-badges__link (le <a> ou <span> genere par
 * hero-home.php), pas sur .hero-badges__item (<li>, simple conteneur de
 * liste) : c'est ce qui permet au badge "avis Google" de devenir un vrai
 * lien sans dupliquer la pastille.
 */
.hero-badges__link {
    display: inline-flex;
    align-items: baseline;
    gap: 0.3em;
    padding: 0.4rem 0.75rem;
    background: var(--color-gray-light);
    color: var(--color-black);
    border-radius: var(--radius-pill);
    font-size: 0.8125rem;
    line-height: 1.2;
    text-decoration: none;
}

a.hero-badges__link:hover,
a.hero-badges__link:focus {
    background: var(--color-white);
}

.hero-badges__label {
    font-weight: 500;
}

.hero-badges__note {
    font-family: var(--font-title);
    font-weight: 700;
}

/*
 * Bandeau de photos defilant sous le hero (reference client). Piste dupliquee
 * (voir hero-marquee.php) glissant de 0 a -50% en boucle infinie : la
 * duplication exacte rend la coupure invisible. Masque en degrade sur les
 * bords via mask-image, purement decoratif (aria-hidden dans le template).
 */
.hero-marquee {
    overflow: hidden;
    padding-block: var(--space-md);
    background: var(--color-black);
    -webkit-mask-image: linear-gradient(to right, transparent, black 8%, black 92%, transparent);
    mask-image: linear-gradient(to right, transparent, black 8%, black 92%, transparent);
}

.hero-marquee__track {
    display: flex;
    gap: var(--space-sm);
    width: max-content;
    animation: hero-marquee-scroll 40s linear infinite;
}

.hero-marquee__item {
    flex-shrink: 0;
    width: 9rem;
}

.hero-marquee__item:nth-child(odd) {
    transform: rotate(-2deg);
}

.hero-marquee__item:nth-child(even) {
    transform: rotate(2deg);
}

.hero-marquee__item img {
    width: 100%;
    aspect-ratio: 3 / 4;
    object-fit: cover;
    border-radius: var(--radius-sm);
}

@keyframes hero-marquee-scroll {
    from {
        transform: translateX(0);
    }

    to {
        transform: translateX(-50%);
    }
}

@media (prefers-reduced-motion: reduce) {
    .hero-marquee__track {
        animation: none;
    }
}

/* ---------- Reassurance ---------- */

/*
 * Chaque item est desormais une carte a part entiere (fond blanc, bordure,
 * ombre legere, icone en cercle plus large) plutot qu'une simple ligne
 * icone+texte : registre juge trop plat par le client sur la version
 * precedente. Meme recette que .card et .feature (bordure fine + ombre
 * discrete, plus marquee au survol) pour rester coherent avec le reste
 * du site.
 */
/*
 * Registre repris de la reference client (fixbild.webflow.io, capture
 * ecran) : cartes plates sur fond clair, sans bordure ni ombre, icone au
 * trait (pas de cercle colore derriere). Le contraste vient du fond de la
 * carte (--color-gray-light) sur le fond blanc de la section, pas d'une
 * ombre - c'est pour ca que la section repasse en blanc ici.
 */
.reassurance {
    background: var(--color-white);
    padding-block: var(--space-lg);
}

.reassurance__grid {
    display: grid;
    gap: var(--space-sm);
    /*
     * 1 colonne sous 26rem : a 2 colonnes des le plus petit telephone, des
     * libelles comme "Zone d'intervention" ou "Nous joindre" + numero
     * n'avaient pas la place et retombaient en lignes tassees, illisibles
     * (retour client : "pas responsive", capture ecran). Toujours 2
     * colonnes a partir de 26rem (~416px), comme avant.
     */
    grid-template-columns: 1fr;
}

@media (min-width: 26rem) {
    .reassurance__grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

/*
 * min-width:0 des deux cotes : sans lui, un item de grille en display:flex
 * (et son enfant texte, lui-meme item flex) refusent tous deux de
 * retrecir sous la largeur intrinseque de leur contenu (defaut
 * min-width:auto) et debordent de la colonne de grille sur mobile - meme
 * bug deja rencontre sur le telephone de l'en-tete et la fleche du
 * carousel d'avis.
 */
.reassurance__item {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-md);
    background: var(--color-gray-light);
    min-width: 0;
}

.reassurance__item > div {
    min-width: 0;
}

/*
 * Un seul item invert (fond noir) parmi les autres : casse l'uniformite
 * de la rangee, dans l'esprit de la reference (fixbild.webflow.io,
 * capture ecran, "why choose us" - une carte sur quatre est inversee).
 * red-light, jamais red plein, en texte sur fond sombre (regle en tete
 * de fichier) ; label et valeur passent en blanc.
 */
.reassurance__item:first-child {
    background: var(--color-black);
}

.reassurance__item:first-child .reassurance__icon .ct-icon {
    color: var(--color-red-light);
}

.reassurance__item:first-child .reassurance__label {
    color: var(--color-red-light);
}

.reassurance__item:first-child .reassurance__value {
    color: var(--color-white);
}

.reassurance__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.reassurance__icon .ct-icon {
    width: 1.75rem;
    height: 1.75rem;
    color: var(--color-red);
}

.reassurance__item p {
    margin: 0;
}

.reassurance__label {
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-red);
}

.reassurance__value {
    font-family: var(--font-title);
    font-weight: 600;
    font-size: 0.9375rem;
}

@media (min-width: 40rem) {
    .reassurance__grid {
        grid-template-columns: repeat(3, 1fr);
    }
}

@media (min-width: 64rem) {
    .reassurance__grid {
        grid-template-columns: repeat(5, 1fr);
    }
}

/* ---------- Arguments ---------- */

/*
 * Registre repris de la reference client (fixbild.webflow.io, capture
 * ecran) : carte plate sur fond clair, sans bordure ni ombre, icone au
 * trait (pas de cercle colore derriere), titre en majuscules rouge.
 * Rouge en texte : fond clair (--color-gray-light), la regle de contraste
 * ne s'applique qu'aux fonds sombres (#231F20), voir l'en-tete du fichier.
 */
/*
 * Liste horizontale (icone + texte + separateur), pas une 3e grille de
 * cartes identique aux sections toiture/facade precedentes : le client a
 * signale que la structure repetee rendait le site "toujours pareil".
 * Motif repris du panneau de services de la reference (fixbild.webflow.io,
 * capture ecran).
 */
.feature-list {
    margin: 0;
    padding: 0;
    list-style: none;
    border-top: 1px solid rgb(35 31 32 / 10%);
}

.feature-list__item {
    display: flex;
    align-items: flex-start;
    gap: var(--space-md);
    padding-block: var(--space-md);
    border-bottom: 1px solid rgb(35 31 32 / 10%);
}

.feature-list__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 2.5rem;
}

.feature-list__icon .ct-icon {
    width: 1.75rem;
    height: 1.75rem;
    color: var(--color-red);
}

.feature-list__title {
    margin: 0 0 0.25rem;
    color: var(--color-red);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    font-size: 1.0625rem;
}

.feature-list__text {
    margin: 0;
    color: var(--color-black);
}

@media (min-width: 40rem) {
    .feature-list__item {
        align-items: center;
    }

    .feature-list__body {
        display: flex;
        align-items: baseline;
        gap: var(--space-md);
    }

    .feature-list__title {
        margin: 0;
        flex-shrink: 0;
        width: 16ch;
    }
}

.section__more {
    margin-top: var(--space-md);
}

.card__link {
    margin: auto 0 0;
    font-weight: 500;
}

/* ---------- Vitrine des prestations (showcase epingle) ---------- */

/*
 * Empiler 7-13 blocs H2+paragraphe identiques rendait la page plate et
 * repetitive (retour client : "trop statique", references fournies montrant
 * un panneau d'intro fixe pendant que le detail defile a cote). Structure
 * reprise ici : colonne de gauche epinglee (position: sticky) le temps que
 * la colonne de droite deroule chaque prestation comme une etape numerotee.
 */
.service-showcase__grid {
    display: grid;
    gap: var(--space-xl);
    grid-template-columns: 1fr;
}

.service-showcase__intro {
    max-width: 40ch;
}

.service-showcase__intro p {
    color: var(--color-gray-text);
}

.service-showcase__intro .btn {
    margin-top: var(--space-sm);
}

.service-showcase__steps {
    display: flex;
    flex-direction: column;
}

.service-showcase__step {
    display: grid;
    gap: var(--space-md);
    grid-template-columns: 1fr;
    padding-block: var(--space-lg);
}

.service-showcase__step + .service-showcase__step {
    border-top: 1px solid rgb(35 31 32 / 8%);
}

.service-showcase__step-index {
    display: block;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-weight: 700;
    font-size: clamp(2.5rem, 6vw, 3.5rem);
    line-height: 1;
    color: rgb(35 31 32 / 14%);
    margin: 0 0 var(--space-xs);
}

.service-showcase__step-body h3 {
    margin-top: 0;
}

/*
 * Conteneur du "scroll dans le scroll" (voir initServiceShowcaseSteps dans
 * reveal.js) : l'etape reste epinglee a l'ecran pendant que ses paragraphes
 * s'enchainent l'un apres l'autre, plutot que d'empiler tout le texte d'un
 * coup - retour client, reference "Our process" fournie. JS mesure la
 * hauteur du plus grand paragraphe et l'applique ici en variable inline
 * pour reserver la place sans saut de mise en page ; sans JS (ou animations
 * reduites), les paragraphes restent simplement empiles normalement.
 */
.service-showcase__copy {
    position: relative;
}

.service-showcase__copy.is-pinned {
    height: var(--ct-copy-height, auto);
}

.service-showcase__copy.is-pinned p {
    position: absolute;
    inset: 0;
    margin: 0;
}

/*
 * Un seul paragraphe dense de 80-120 mots se lisait comme un mur de texte
 * (retour client : "entasse", "donne pas envie de lire"). Le contenu est
 * desormais fourni en 2 paragraphes (voir ct_sections) ; ici on leur donne
 * de l'air : interligne plus genereux, couleur adoucie par rapport au H3
 * pour ne pas concurrencer le titre, espace clair entre les deux.
 */
.service-showcase__step-body p {
    max-width: 62ch;
    color: var(--color-gray-text);
    line-height: 1.8;
    margin: 0 0 var(--space-md);
}

.service-showcase__step-body p:last-of-type {
    margin-bottom: var(--space-sm);
}

@media (min-width: 64rem) {
    .service-showcase__grid {
        grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
        align-items: start;
    }

    .service-showcase__intro {
        position: sticky;
        top: calc(var(--header-gap) + var(--header-h) + var(--space-xl));
    }
}

@media (min-width: 40rem) {
    .service-showcase__step {
        grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
        align-items: center;
    }
}

/* Media/repli d'une etape : meme carte que precedemment (photo ou, tant
   qu'aucune photo n'est fournie, degrade noir + icone de categorie + anneaux
   decoratifs repris du hero). */
.service-showcase__media img,
.service-showcase__placeholder {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: var(--radius);
}

.service-showcase__placeholder {
    position: relative;
    background: linear-gradient(155deg, var(--color-black), #34302f);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.service-showcase__placeholder::before,
.service-showcase__placeholder::after {
    content: '';
    position: absolute;
    border-radius: 50%;
    pointer-events: none;
}

.service-showcase__placeholder::before {
    top: -3rem;
    right: -3rem;
    width: 9rem;
    height: 9rem;
    border: 1px solid rgb(255 255 255 / 15%);
}

.service-showcase__placeholder::after {
    bottom: 1.5rem;
    left: 1.5rem;
    width: 3.5rem;
    height: 3.5rem;
    border: 1px solid rgb(176 33 37 / 45%);
}

.service-showcase__placeholder-icon {
    width: 4.5rem;
    height: 4.5rem;
    color: var(--color-white);
    stroke-width: 1.25;
    position: relative;
    z-index: 1;
}

/* ---------- FAQ ---------- */

.faq__intro {
    max-width: 38rem;
    margin-inline: auto;
    margin-bottom: var(--space-lg);
    text-align: center;
}

.faq__intro .section-badge {
    margin-inline: auto;
}

.faq {
    max-width: 44rem;
    margin-inline: auto;
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
}

.faq__item {
    border: 1px solid rgb(35 31 32 / 12%);
    border-radius: var(--radius);
    background: var(--color-white);
    transition: border-color 0.25s ease, box-shadow 0.25s ease;
}

.faq__item:hover {
    border-color: rgb(176 33 37 / 30%);
}

/*
 * L'item ouvert se detache legerement (bordure rouge + ombre douce) plutot
 * que le simple trait horizontal d'avant (retour client : "trop a
 * l'ancienne") - signal visuel clair de l'etat, coherent avec les cartes
 * utilisees ailleurs sur le site.
 */
.faq__item:has(.faq__toggle[aria-expanded='true']) {
    border-color: var(--color-red);
    box-shadow: 0 0.75rem 2rem rgb(35 31 32 / 8%);
}

.faq__heading {
    margin: 0;
    font-size: 1rem;
}

.faq__toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-sm);
    width: 100%;
    min-height: 48px;
    padding: var(--space-sm) var(--space-md);
    background: none;
    border: 0;
    font-family: var(--font-title);
    font-weight: 600;
    font-size: 1.0625rem;
    text-align: left;
    color: var(--color-black);
    cursor: pointer;
}

/*
 * Icone en pastille ronde qui pivote (+ devient x visuellement, une seule
 * glyphe, pas d'echange de contenu) plutot que le +/- instantane d'avant -
 * animation demandee par le client ("plus anime").
 */
.faq__icon {
    position: relative;
    flex-shrink: 0;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 50%;
    border: 1px solid rgb(176 33 37 / 35%);
    transition: transform 0.3s ease, background-color 0.3s ease, border-color 0.3s ease;
}

.faq__icon::before,
.faq__icon::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    background: var(--color-red);
    transition: background-color 0.3s ease;
}

.faq__icon::before {
    width: 0.75rem;
    height: 2px;
    transform: translate(-50%, -50%);
}

.faq__icon::after {
    width: 2px;
    height: 0.75rem;
    transform: translate(-50%, -50%);
}

.faq__toggle[aria-expanded='true'] .faq__icon {
    transform: rotate(135deg);
    background-color: var(--color-red);
    border-color: var(--color-red);
}

.faq__toggle[aria-expanded='true'] .faq__icon::before,
.faq__toggle[aria-expanded='true'] .faq__icon::after {
    background: var(--color-white);
}

/*
 * Hauteur animee via max-height (mesuree en JS a partir de scrollHeight,
 * voir initFaq dans main.js) : le panneau reste hidden="" pour un lecteur
 * d'ecran quand il est ferme (contrairement a un simple clip visuel en
 * hauteur 0), et l'ouverture/fermeture se fait en douceur plutot que le
 * hidden instantane d'avant.
 */
.faq__panel {
    overflow: hidden;
    max-height: 0;
    transition: max-height 0.35s ease;
}

.faq__panel-inner {
    padding: 0 var(--space-md) var(--space-md);
}

.faq__panel p {
    margin: 0;
    color: var(--color-gray-text);
}

/* ---------- Prix ---------- */

/*
 * Indice de defilement, visible uniquement tant que le tableau est plus
 * large que son conteneur (revele par JS via .is-scrollable - voir
 * initPricesScrollHint dans main.js) : iOS Safari masque sa barre de
 * defilement hors interaction tactile, sans autre indice le tableau
 * semblait juste coupe/casse (retour client : "le tableau est pas
 * responsive").
 */
.table-scroll__hint {
    display: none;
    margin: var(--space-sm) 0 0;
    font-size: 0.8125rem;
    color: var(--color-gray-text);
}

.table-scroll-wrap.is-scrollable + .table-scroll__hint {
    display: block;
}

.table-scroll-wrap {
    position: relative;
    margin-top: var(--space-md);
}

.table-scroll-wrap.is-scrollable::after {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 2.5rem;
    background: linear-gradient(to right, transparent, var(--color-gray-light));
    pointer-events: none;
}

/* Un tableau large defile dans son conteneur, jamais la page entiere. */
.table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.prices {
    width: 100%;
    border-collapse: collapse;
    background: var(--color-white);
    border-radius: var(--radius-sm);
    overflow: hidden;
}

.prices th,
.prices td {
    padding: 0.75rem var(--space-sm);
    text-align: left;
    border-bottom: 1px solid rgb(35 31 32 / 12%);
    font-size: 0.9375rem;
}

.prices thead th {
    background: var(--color-black);
    color: var(--color-white);
    font-family: var(--font-title);
    font-weight: 600;
}

.prices tbody th {
    font-weight: 500;
}

.prices__range {
    font-family: var(--font-title);
    font-weight: 600;
    white-space: nowrap;
}

/* ---------- Methode ---------- */

.method {
    counter-reset: step;
    list-style: none;
    margin: var(--space-md) 0 0;
    padding: 0;
    display: grid;
    gap: var(--space-md);
    grid-template-columns: 1fr;
}

.method__item {
    counter-increment: step;
    padding-left: 3.25rem;
    position: relative;
}

.method__item::before {
    content: counter(step);
    position: absolute;
    left: 0;
    top: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    /* Blanc sur rouge : 6,80:1. */
    background: var(--color-red);
    color: var(--color-white);
    font-family: var(--font-title);
    font-weight: 700;
}

.method__title {
    margin-bottom: var(--space-xs);
}

.method__text {
    margin: 0;
    color: var(--color-gray-text);
}

@media (min-width: 56rem) {
    .method {
        grid-template-columns: repeat(3, 1fr);
    }
}

/* ---------- Page devis ---------- */

/*
 * Version compacte du traitement hero (fond noir, anneaux decoratifs) :
 * pas de min-height:100vh ici, le formulaire doit rester visible sans
 * defiler (page de pure conversion) - voir le commentaire dans
 * page-devis.php. Coherence visuelle avec le reste du site sans en payer
 * le cout en conversion.
 */
/*
 * Fond degrade (pas un noir plat) : sans photo pour cette page, le noir
 * uni rendait la section "fade" (retour client). Meme degrade que les
 * cartes-repli du site (service-showcase, project-showcase) plutot qu'un
 * nouveau choix de couleur - une seule convention de "dark riche" sur
 * tout le site.
 */
.devis-head {
    position: relative;
    overflow: hidden;
    background: linear-gradient(155deg, var(--color-black), #34302f);
    /* Remonte sous la pilule flottante de l'en-tete, comme le hero partage
       (.hero) : sans ca, le fond blanc de <body> reste visible au-dessus
       du degrade, autour de la pilule (retour client, capture ecran). */
    margin-top: calc(-1 * (var(--header-gap) + var(--header-h) + var(--space-md)));
    padding-block: calc(var(--header-gap) + var(--header-h) + var(--space-md) + var(--space-lg)) var(--space-xl);
}

.devis-head::before,
.devis-head::after {
    content: '';
    position: absolute;
    z-index: 0;
    border-radius: 50%;
    border: 1px solid rgb(255 255 255 / 18%);
    pointer-events: none;
}

.devis-head::before {
    top: -6rem;
    right: -5rem;
    width: 18rem;
    height: 18rem;
}

.devis-head::after {
    bottom: -4rem;
    right: 10rem;
    width: 9rem;
    height: 9rem;
    border-color: rgb(176 33 37 / 40%);
    display: none;
}

@media (min-width: 48rem) {
    .devis-head::after {
        display: block;
    }
}

.devis-head .wrap {
    position: relative;
    z-index: 1;
}

.devis-head__grid {
    display: grid;
    gap: var(--space-lg);
}

@media (min-width: 56rem) {
    .devis-head__grid {
        grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
        align-items: center;
    }
}

.devis-head__trust {
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
    margin: 0;
    padding: var(--space-md);
    background: rgb(255 255 255 / 6%);
    border: 1px solid rgb(255 255 255 / 12%);
    border-radius: var(--radius);
    list-style: none;
}

.devis-head__trust li {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    color: var(--color-white);
    font-weight: 500;
    font-size: 0.9375rem;
}

.devis-head__trust-icon {
    display: inline-flex;
    flex-shrink: 0;
}

.devis-head__trust-icon .ct-icon {
    width: 1.375rem;
    height: 1.375rem;
    color: var(--color-red-light);
}

.devis-head__intro {
    color: var(--color-white);
    font-size: 1.0625rem;
    max-width: 60ch;
}

.devis-head__phone {
    margin: 0;
    color: var(--color-white);
}

.devis-head__phone a {
    font-family: var(--font-title);
    font-weight: 700;
    font-size: 1.125rem;
    color: var(--color-white);
}

.devis-info {
    display: grid;
    gap: var(--space-lg);
    grid-template-columns: 1fr;
}

.devis-info__map {
    width: 100%;
    border-radius: var(--radius);
}

.devis-perks {
    margin-top: var(--space-md);
}

/* Carte compacte (icone + une ligne), pas le padding genereux de .card
   par defaut - pense pour un titre+texte, trop d'air ici pour une seule
   ligne courte. */
.devis-perk .card__body {
    flex-direction: row;
    align-items: center;
    padding: var(--space-md);
    gap: var(--space-md);
}

.devis-perk {
    border-radius: var(--radius);
    box-shadow: 0 0.5rem 1.5rem rgb(35 31 32 / 6%);
    transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}

.devis-perk:hover {
    transform: translateY(-3px);
    box-shadow: 0 1rem 2rem rgb(35 31 32 / 10%);
    border-left-color: var(--color-red);
}

/*
 * Icone en pastille ronde (fond rouge tres clair) plutot que l'icone nue
 * d'avant, trop discrete au milieu du blanc de la carte (retour client :
 * "tu peux mieux faire").
 */
.devis-perk__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 3rem;
    height: 3rem;
    border-radius: 50%;
    background: rgb(176 33 37 / 8%);
}

.devis-perk__icon .ct-icon {
    width: 1.5rem;
    height: 1.5rem;
    color: var(--color-red);
}

.devis-perk .card__text {
    color: var(--color-black);
    font-weight: 500;
}

@media (min-width: 56rem) {
    .devis-info {
        grid-template-columns: 1fr 1fr;
    }
}

/*
 * Sans carte de zone renseignee, la 2e colonne ne rend rien : la grille
 * 2 colonnes ci-dessus reservait quand meme sa moitie d'ecran (grand vide
 * a droite - retour client). En pleine largeur, les 4 cartes-avantages
 * passent sur une seule ligne au lieu de rester coincees a gauche.
 */
@media (min-width: 56rem) {
    .devis-info--full {
        grid-template-columns: 1fr;
    }

    .devis-info--full .devis-perks {
        grid-template-columns: repeat(4, 1fr);
    }

    .devis-info--full .devis-perk .card__body {
        flex-direction: column;
        align-items: flex-start;
        text-align: left;
    }
}

/* ---------- Titre de page ---------- */

.page-head {
    padding-block: var(--space-lg);
}

.page-head__intro {
    color: var(--color-white);
    font-size: 1.0625rem;
    max-width: 60ch;
    margin: 0;
}

/* ---------- Realisations ---------- */

.project__media {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2px;
}

.project__shot {
    margin: 0;
    position: relative;
}

.project__shot img {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
}

.project__placeholder,
.project__shot:first-child img {
    border-top-left-radius: var(--radius);
}

.project__placeholder,
.project__shot:last-child img {
    border-top-right-radius: var(--radius);
}

.project__shot figcaption {
    position: absolute;
    bottom: 0;
    left: 0;
    padding: 0.25rem 0.5rem;
    /* Fond noir opaque derriere le texte blanc : lisible sur toute photo. */
    background: var(--color-black);
    color: var(--color-white);
    font-family: var(--font-title);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.project__tag {
    margin: 0;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-red);
}

/* Numero pose en pastille sur la photo (meme registre que le numero des
   etapes de prestation), pour donner du poids editorial a chaque chantier
   plutot qu'une simple grille de photos anonymes. */
.project__index {
    position: absolute;
    z-index: 1;
    top: var(--space-sm);
    left: var(--space-sm);
    width: 2.25rem;
    height: 2.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-black);
    color: var(--color-white);
    border-radius: 50%;
    font-family: var(--font-title);
    font-weight: 700;
    font-size: 0.8125rem;
}

/* Cartes "a venir" : meme structure que les chantiers reels, en retrait
   (opacite reduite, tag neutre) pour ne pas se confondre avec de vrais
   chantiers documentes. */
.project--upcoming {
    opacity: 0.7;
}

.project--upcoming .project__tag {
    color: var(--color-gray-text);
}

/*
 * ---------- Collage des chantiers (project-showcase.php) ----------
 *
 * Reference client : composant React "HeroCollage" (photos flottantes
 * disposees autour d'un titre central, ligne de chiffres-cles en bas).
 * Reproduit en CSS pur - juste une animation de flottement en boucle
 * (@keyframes plus bas), respectee par prefers-reduced-motion (aucun JS,
 * contrairement a l'ancienne vitrine en train 3D qui defilait au scroll -
 * retour client : "laisse tomber cette animation"). Les photos restent
 * cliquables (le clic ouvre la pop-up, voir initProjectModal dans
 * main.js), inchange par rapport a l'ancienne vitrine.
 *
 * Base (mobile, jusqu'a 63.999rem) : grille statique simple 2 colonnes,
 * pas de positionnement absolu - le collage en eventail suppose assez de
 * place pour etaler les photos sans qu'elles se chevauchent n'importe
 * comment, ce qui ne tient pas sur un ecran etroit.
 */
.project-collage__intro {
    max-width: 40rem;
    margin-inline: auto;
    margin-bottom: var(--space-xl);
    text-align: center;
}

.project-collage__stage {
    position: relative;
    width: 100%;
    max-width: 74rem;
    margin-inline: auto;
    padding-inline: var(--space-sm);
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-sm);
}

.project-collage__photo {
    display: block;
    width: 100%;
    /*
     * min-width:0 : sans ca, une grille CSS refuse de retrecir cet item
     * sous la largeur intrinseque de l'image qu'il contient, ce qui
     * depasse le viewport sur mobile (meme bug deja rencontre sur
     * .reassurance__item - retour client : "sur mobile c'est pas
     * responsive").
     */
    min-width: 0;
    aspect-ratio: 3 / 4;
    padding: 0;
    border: 1px solid rgb(255 255 255 / 10%);
    border-radius: var(--radius);
    background: var(--color-black);
    overflow: hidden;
    cursor: pointer;
    box-shadow: 0 1.5rem 3rem rgb(0 0 0 / 45%);
}

.project-collage__photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0.9;
    transition: opacity 0.3s ease;
}

.project-collage__photo:hover img,
.project-collage__photo:focus-visible img {
    opacity: 1;
}

.project-collage__stats {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--space-xl);
    margin-top: var(--space-xl);
    text-align: center;
}

.project-collage__stat-value {
    font-family: var(--font-title);
    font-size: 2rem;
    font-weight: 700;
    color: var(--color-white);
}

.project-collage__stat-label {
    margin-top: 0.25rem;
    color: rgb(255 255 255 / 65%);
    font-size: 0.9375rem;
}

/*
 * ---------- Rangee de vignettes qui se chevauchent (grand ecran) ----------
 *
 * A partir de 64rem : une seule rangee resserree, chaque vignette
 * chevauchant legerement la precedente (retour client : "trop eparpille",
 * reference fournie montrant une rangee compacte) plutot que des positions
 * eparpillees sur toute la scene. L'ordre naturel du DOM suffit a
 * l'empilement (chaque vignette suivante se pose sur la precedente), pas
 * de z-index a calculer a la main.
 */
@media (min-width: 64rem) {
    .project-collage__stage {
        display: flex;
        /*
         * nowrap volontaire : un retour a la ligne casserait le chevauchement
         * (le premier element de la 2e ligne heriterait quand meme de la
         * marge negative du precedent). Les largeurs en clamp() ci-dessous
         * sont calculees pour que la rangee complete tienne des 64rem.
         */
        flex-wrap: nowrap;
        align-items: center;
        justify-content: center;
        height: auto;
        padding-block: var(--space-lg) var(--space-xl);
        padding-inline: var(--space-md);
    }

    .project-collage__photo {
        position: relative;
        flex-shrink: 0;
        width: clamp(9.5rem, 13vw, 13rem);
        aspect-ratio: 3 / 4;
        margin-left: -3rem;
        /*
         * Decalage vertical propre a chaque vignette (--fy), lu par
         * l'animation de flottement ci-dessous : une seule regle
         * @keyframes pour toutes, chacune flotte simplement autour de son
         * propre point de depart au lieu de toutes partager le meme axe.
         */
        --fy: 0rem;
        animation: ct-collage-float 6s ease-in-out infinite;
    }

    .project-collage__photo:first-child {
        margin-left: 0;
    }

    .project-collage__photo:nth-child(1) {
        --fy: 0.5rem;
    }

    .project-collage__photo:nth-child(2) {
        --fy: -1.25rem;
    }

    .project-collage__photo:nth-child(3) {
        --fy: 1.5rem;
    }

    .project-collage__photo:nth-child(4) {
        --fy: -0.5rem;
    }

    .project-collage__photo:nth-child(5) {
        --fy: -1.75rem;
    }

    .project-collage__photo:nth-child(6) {
        --fy: 0.75rem;
    }

    .project-collage__photo:nth-child(7) {
        --fy: 1.25rem;
    }

    .project-collage__photo:nth-child(8) {
        --fy: -1rem;
    }
}

@keyframes ct-collage-float {
    0%,
    100% {
        transform: translateY(var(--fy, 0));
    }

    50% {
        transform: translateY(calc(var(--fy, 0) - 0.9rem));
    }
}

@media (prefers-reduced-motion: reduce) {
    .project-collage__photo {
        animation: none;
    }
}

/* ---------- Pop-up de detail de chantier ---------- */

.project-modal {
    position: fixed;
    inset: 0;
    z-index: 300;
    display: none;
    align-items: center;
    justify-content: center;
    padding: var(--space-md);
}

.project-modal.is-open {
    display: flex;
}

.project-modal__overlay {
    position: absolute;
    inset: 0;
    background: rgb(35 31 32 / 70%);
}

.project-modal__dialog {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 640px;
    max-height: 85vh;
    overflow-y: auto;
    background: var(--color-white);
    border-radius: var(--radius);
    padding: var(--space-xl) var(--space-lg) var(--space-lg);
}

.project-modal__close {
    position: absolute;
    top: var(--space-sm);
    right: var(--space-sm);
    width: 2.25rem;
    height: 2.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-gray-light);
    border: 0;
    border-radius: 50%;
    color: var(--color-black);
    cursor: pointer;
}

.project-modal__close svg {
    width: 1.125rem;
    height: 1.125rem;
}

.project-modal__tag {
    margin: 0 0 var(--space-xs);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-red);
}

.project-modal__title {
    margin: 0 0 var(--space-xs);
}

.project-modal__meta {
    margin: 0 0 var(--space-md);
    color: var(--color-gray-text);
    font-size: 0.875rem;
}

.project-modal__body p {
    color: var(--color-black);
    line-height: 1.7;
}

.ct-modal-open {
    overflow: hidden;
}

.reviews__actions {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    margin-top: var(--space-md);
}

@media (min-width: 30rem) {
    .reviews__actions {
        flex-direction: row;
    }
}

/*
 * Un chantier peut n'avoir qu'une seule des deux photos : la grille a deux
 * colonnes laisserait alors une moitie vide. La photo unique occupe toute
 * la largeur, la legende Avant ou Apres indiquant de quel etat il s'agit.
 */
.project__media--single {
    grid-template-columns: 1fr;
}

.project__media--placeholder {
    grid-template-columns: 1fr;
}

/* Meme traitement que service-showcase__placeholder (fond noir dans un
   degrade, anneaux decoratifs, icone de categorie) pour un chantier pas
   encore en photo - une seule convention de repli sur tout le site. */
.project__placeholder {
    position: relative;
    aspect-ratio: 4 / 3;
    background: linear-gradient(155deg, var(--color-black), #34302f);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.project__placeholder::before,
.project__placeholder::after {
    content: '';
    position: absolute;
    border-radius: 50%;
    pointer-events: none;
}

.project__placeholder::before {
    top: -3rem;
    right: -3rem;
    width: 9rem;
    height: 9rem;
    border: 1px solid rgb(255 255 255 / 15%);
}

.project__placeholder::after {
    bottom: 1.5rem;
    left: 1.5rem;
    width: 3.5rem;
    height: 3.5rem;
    border: 1px solid rgb(176 33 37 / 45%);
}

.project__placeholder-icon {
    width: 4.5rem;
    height: 4.5rem;
    color: var(--color-white);
    stroke-width: 1.25;
    position: relative;
    z-index: 1;
}

/* ---------- Zones ---------- */

/*
 * Vitrine horizontale epinglee des zones prioritaires (template-parts/
 * zone-highlights.php) : demande explicite du client ("un sticky
 * horizontal", pas un carrousel classique). position:sticky pour
 * l'epinglage (pas de pin:true GSAP - plus robuste), ScrollTrigger pour
 * la seule progression 0-1 (voir initZoneHighlightsScroll dans
 * reveal.js). Base = grille statique simple (fonctionne sans JavaScript
 * et sous prefers-reduced-motion) ; le modificateur --pinned, ajoute par
 * JS uniquement, active l'habillage epingle/horizontal.
 * Fond noir + anneaux decoratifs : meme registre que project-showcase.php
 * et le hero (fond creme d'origine juge "fade").
 *
 * Pas d'overflow:hidden ici : le pin epingle (position:sticky) est un
 * descendant, et un ancetre avec overflow != visible casse le sticky
 * (deja constate en production). Les anneaux decoratifs debordent
 * legerement sur tres grand ecran, effet mineur.
 */
.zone-highlights-scroll {
    position: relative;
    background: var(--color-black);
    padding-block: var(--space-lg);
}

/*
 * overflow:hidden uniquement sous 48rem (meme seuil que le garde-fou JS de
 * initZoneHighlightsScroll, qui n'active jamais l'epinglage en dessous) :
 * les anneaux decoratifs ci-dessous debordent ce conteneur avec un
 * decalage negatif, remontant jusqu'au document (scrollWidth reellement
 * plus large que le viewport) - un vrai defilement horizontal etait
 * possible au doigt sur iOS Safari malgre le html{overflow-x:hidden}
 * defensif plus haut, qui ne bloque pas toujours le rebond tactile (retour
 * client : "le site glisse de gauche a droite" sur smartphone). Pas
 * applique plus large : .zone-highlights-scroll est le parent direct de
 * .zone-highlights-scroll__pin (position:sticky) une fois epingle, et un
 * ancetre en overflow:hidden casse le sticky (bug deja rencontre sur ce
 * meme composant).
 */
@media (max-width: 47.999rem) {
    .zone-highlights-scroll {
        overflow: hidden;
    }
}

.zone-highlights-scroll::before,
.zone-highlights-scroll::after {
    content: '';
    position: absolute;
    z-index: 0;
    border-radius: 50%;
    border: 1px solid rgb(255 255 255 / 18%);
    pointer-events: none;
}

.zone-highlights-scroll::before {
    top: -6rem;
    right: -6rem;
    width: 18rem;
    height: 18rem;
}

.zone-highlights-scroll::after {
    bottom: 4rem;
    left: -4rem;
    width: 10rem;
    height: 10rem;
    border-color: rgb(176 33 37 / 35%);
}

.zone-highlights-scroll__intro {
    position: relative;
    z-index: 1;
    margin-bottom: var(--space-md);
    color: var(--color-white);
}

.zone-highlights-scroll__intro h2 {
    color: var(--color-white);
}

.zone-highlights-scroll__track {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-sm);
    padding-inline: var(--space-sm);
}

@media (min-width: 40rem) {
    .zone-highlights-scroll__track {
        grid-template-columns: repeat(3, 1fr);
    }
}

@media (min-width: 64rem) {
    .zone-highlights-scroll__track {
        grid-template-columns: repeat(4, 1fr);
    }
}

/*
 * Ni height:100vh ni centrage flex : le bloc epingle (titre + cartes) ne
 * fait qu'une fraction de la hauteur d'ecran, le centrer dans une boite
 * pleine hauteur laissait un espace vide enorme au-dessus et en dessous
 * (retour client, capture ecran). Le bloc garde sa hauteur naturelle et
 * se colle juste sous la pilule flottante de l'en-tete (meme decalage que
 * le hero/les autres sections), rien de plus.
 */
.zone-highlights-scroll--pinned .zone-highlights-scroll__pin {
    position: sticky;
    top: calc(var(--header-gap) + var(--header-h) + var(--space-md));
    overflow: hidden;
    padding-bottom: var(--space-md);
}

.zone-highlights-scroll--pinned .zone-highlights-scroll__track {
    display: flex;
    flex-wrap: nowrap;
    gap: var(--space-md);
    width: max-content;
    padding-inline: var(--space-sm);
    will-change: transform;
}

.zone-highlights-scroll--pinned .zone-highlight {
    flex: 0 0 min(80vw, 22rem);
}

/*
 * Carte elevee sur fond sombre : surface legerement plus claire que le
 * fond, accent rouge en haut (pas en texte - regle de contraste), icone +
 * numero pour rompre la monotonie d'une simple grille de texte.
 */
.zone-highlights-scroll .card.zone-highlight {
    position: relative;
    background: rgb(255 255 255 / 6%);
    border: 1px solid rgb(255 255 255 / 12%);
    border-left: none;
    border-top: 3px solid var(--color-red);
    border-radius: var(--radius-sm);
}

.zone-highlights-scroll .card.zone-highlight:hover {
    background: rgb(255 255 255 / 10%);
    border-left: none;
    transform: none;
}

.zone-highlight__icon {
    position: absolute;
    top: var(--space-sm);
    left: var(--space-sm);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    background: rgb(255 255 255 / 10%);
    border-radius: var(--radius-sm);
}

.zone-highlight__icon .ct-icon {
    width: 1.25rem;
    height: 1.25rem;
    color: var(--color-red-light);
}

.zone-highlight__index {
    position: absolute;
    top: var(--space-sm);
    right: var(--space-sm);
    font-family: var(--font-title);
    font-weight: 700;
    font-size: 0.8125rem;
    color: rgb(255 255 255 / 30%);
}

.zone-highlight .card__body {
    padding-top: calc(2.5rem + var(--space-lg));
}

/* Blanc, pas red-light : card__title fait 1.0625rem (17px), sous le seuil
   de 24px qui autorise red-light en texte sur fond sombre (regle de
   contraste en tete de fichier). Le rouge reste sur l'icone et la bordure. */
.zone-highlight .card__title {
    color: var(--color-white);
}

.zone-highlight .card__text {
    color: rgb(255 255 255 / 80%);
}


.zone-list__subheading {
    margin: var(--space-xl) 0 0;
    font-size: 1.0625rem;
}

.zone-list {
    list-style: none;
    margin: var(--space-md) 0 0;
    padding: 0;
    display: grid;
    gap: var(--space-xs);
    grid-template-columns: repeat(2, 1fr);
}

/*
 * Bloc anguleux (radius 0), pas une pilule : c'est du contenu (une liste de
 * lieux), pas un appel a l'action - la pilule reste reservee aux boutons
 * et badges (direction Bauhaus/fixbild, validee client 2026-07-28).
 */
.zone-list__item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem var(--space-sm);
    background: var(--color-gray-light);
    border-left: 3px solid transparent;
    font-weight: 500;
    font-size: 0.9375rem;
    transition: border-color 0.1s linear;
}

.zone-list__item:hover {
    border-left-color: var(--color-red);
}

.zone-list__icon {
    display: inline-flex;
    flex-shrink: 0;
}

.zone-list__icon .ct-icon {
    width: 1rem;
    height: 1rem;
    color: var(--color-red);
}

.zone-list__note {
    margin-top: var(--space-md);
    color: var(--color-gray-text);
}

.zone-map {
    width: 100%;
    margin-top: var(--space-md);
    border-radius: var(--radius);
}

@media (min-width: 40rem) {
    .zone-list {
        grid-template-columns: repeat(3, 1fr);
    }
}

@media (min-width: 64rem) {
    .zone-list {
        grid-template-columns: repeat(4, 1fr);
    }
}

/* ---------- Contenu redactionnel ---------- */

.prose {
    max-width: 70ch;
}

.prose h2 {
    margin-top: var(--space-lg);
}

.prose h3 {
    margin-top: var(--space-md);
}

.prose ul,
.prose ol {
    margin: 0 0 var(--space-sm);
    padding-left: 1.5rem;
}

.prose li {
    margin-bottom: 0.375rem;
}

.prose__nap {
    margin-top: var(--space-lg);
    padding: var(--space-sm);
    background: var(--color-gray-light);
    border-left: 3px solid var(--color-red);
    border-radius: 0 var(--radius) var(--radius) 0;
}

.about-engagement__more {
    margin-top: var(--space-md);
}

/*
 * "Qui sommes-nous" : texte a gauche, carte de faits rapides a droite -
 * casse le mur de texte plutot que d'empiler un paragraphe de plus
 * (retour client). Empile normalement sur mobile, 2 colonnes a partir de
 * 64rem (meme seuil que les autres mises en page a 2 colonnes du site).
 */
.about-intro {
    display: grid;
    gap: var(--space-lg);
    align-items: start;
}

@media (min-width: 64rem) {
    .about-intro {
        grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
    }
}

.about-facts {
    padding: var(--space-md);
    background: var(--color-gray-light);
    border-left: 3px solid var(--color-red);
    border-radius: 0 var(--radius) var(--radius) 0;
}

.about-facts__list {
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
    margin: 0;
    padding: 0;
    list-style: none;
}

.about-facts__list li {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    color: var(--color-black);
    font-weight: 500;
    font-size: 0.9375rem;
}

.about-facts__icon {
    display: inline-flex;
    flex-shrink: 0;
}

.about-facts__icon .ct-icon {
    width: 1.375rem;
    height: 1.375rem;
    color: var(--color-red);
}

/* Le NAP hors du footer est sur fond clair : texte sombre, lien rouge. */
.prose__nap .nap__phone a,
.prose__nap .nap__hours {
    color: var(--color-black);
}

.prose__nap .nap__phone a {
    color: var(--color-red);
}

/* ---------- Icones ---------- */

/* Icones decoratives (voir inc/icons.php) : la couleur vient de currentColor,
   jamais codee en dur dans le SVG, pour suivre le texte sur fond clair
   comme sur fond sombre. */
.ct-icon {
    width: 1.5rem;
    height: 1.5rem;
    flex-shrink: 0;
    display: inline-block;
    vertical-align: middle;
}

/* ---------- Refonte accueil : bandeau de garanties ---------- */

.guarantees-bar {
    padding-block: var(--space-md);
}

.guarantees-bar__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-sm);
    text-align: center;
}

@media (min-width: 40rem) {
    .guarantees-bar__grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (min-width: 64rem) {
    .guarantees-bar__grid {
        grid-template-columns: repeat(4, 1fr);
        text-align: left;
    }
}

.guarantees-bar__item {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-xs);
    padding-block: var(--space-xs);
}

@media (min-width: 64rem) {
    .guarantees-bar__item {
        justify-content: flex-start;
        border-left: 1px solid rgb(255 255 255 / 15%);
        padding-left: var(--space-sm);
    }

    .guarantees-bar__item:first-child {
        border-left: none;
        padding-left: 0;
    }
}

.guarantees-bar__icon .ct-icon {
    color: var(--color-red-light);
    width: 1.375rem;
    height: 1.375rem;
}

.guarantees-bar__label {
    font-family: var(--font-title);
    font-weight: 600;
    font-size: 0.9375rem;
    color: var(--color-white);
}

/* ---------- Refonte accueil : A propos + statistiques ---------- */

.about-stats__inner {
    display: grid;
    gap: var(--space-lg);
}

@media (min-width: 64rem) {
    .about-stats__inner {
        grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
        align-items: center;
        gap: var(--space-xl);
    }
}

.about-stats__media {
    position: relative;
}

.about-stats__media img,
.about-stats__placeholder {
    width: 100%;
    aspect-ratio: 4 / 5;
    object-fit: cover;
    border-radius: var(--radius);
}

.about-stats__placeholder {
    background: linear-gradient(135deg, var(--color-gray-light), rgb(35 31 32 / 12%));
}

/* Bouton play purement decoratif (aucune video branchee pour l'instant) :
   voir template-parts/about-stats.php, rendu en <span aria-hidden>. */
.about-stats__play {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 4.5rem;
    height: 4.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-red);
    border-radius: 50%;
    box-shadow: 0 8px 24px rgb(35 31 32 / 30%);
}

.about-stats__play svg {
    width: 1.75rem;
    height: 1.75rem;
    color: var(--color-white);
    margin-left: 0.15rem;
}

.about-stats__content h2 {
    margin-bottom: var(--space-sm);
}

.about-stats__text {
    color: var(--color-gray-text);
    margin-bottom: var(--space-md);
}

.about-stats__list {
    display: grid;
    gap: 0;
    margin: 0 0 var(--space-md);
    border-top: 1px solid rgb(35 31 32 / 12%);
}

.about-stats__item {
    display: flex;
    align-items: baseline;
    gap: var(--space-sm);
    padding-block: var(--space-sm);
    border-bottom: 1px solid rgb(35 31 32 / 12%);
}

.about-stats__value {
    font-family: var(--font-title);
    font-weight: 700;
    font-size: 1.75rem;
    color: var(--color-red);
    min-width: 4.5rem;
}

.about-stats__label {
    margin: 0;
    color: var(--color-black);
    font-size: 0.9375rem;
}

/* ---------- Refonte accueil : pourquoi nous (cards) ---------- */

/*
 * Tilt 3D en eventail (reference client - grille de cartes en perspective,
 * chacune pivotee selon sa position). --di (calcule en PHP, voir
 * template-parts/why-us-cards.php) va de -1 a +1 le long de la rangee ;
 * --ma est l'angle maximum. transform-origin recule le pivot sur l'axe z
 * (--oz) pour que les cartes s'inclinent depuis un point commun devant
 * l'ecran, comme un eventail, plutot que de pivoter chacune sur son propre
 * centre.
 *
 * Fusionne ici l'entree au defilement (translateY + fondu, remplace le
 * data-ct-stagger generique) ET le tilt de repos dans UNE seule regle de
 * transform par etat : les deux ne peuvent pas cohabiter sur des regles
 * CSS separees (une seule valeur de transform gagne, elles ne s'ajoutent
 * pas comme le feraient des proprietes translate/scale/rotate distinctes).
 */
.why-us {
    perspective: 65em;
}

.why-us__card {
    --ma: 14deg;
    --oz: 4em;
    position: relative;
    overflow: hidden;
    background: var(--color-gray-light);
    padding: var(--space-lg) var(--space-md);
    border-radius: var(--radius);
    height: 100%;
    transform-origin: 50% 50% var(--oz);
    transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0.5s ease-out;
}

.ct-js .why-us__card {
    opacity: 0;
    transform: translateY(28px) rotateY(0deg) scale(0.96);
}

/*
 * Plat au repos (retour client du 2026-07-29 : le tilt de repos derangeait,
 * inversion du sens original de la reference) - seul le survol incline la
 * carte, vers son angle en eventail (--di, calcule en PHP). Prefixe
 * identique sur les deux regles suivantes (4 classes/attribut + :hover) :
 * sans lui, :hover seul (2 niveaux) perdrait face a .is-revealed quel que
 * soit l'ordre de declaration - une regle plus specifique l'emporte
 * toujours, meme placee avant. Verifie par lecture du transform calcule
 * (matrix3d) avant et apres inversion.
 */
.ct-js [data-ct-reveal].is-revealed .why-us__card {
    opacity: 1;
    transform: translateY(0) rotateY(0deg) scale(1);
}

.ct-js [data-ct-reveal].is-revealed .why-us__card:hover {
    transform: translateY(0) rotateY(calc(var(--di) * var(--ma))) scale(1.03);
    z-index: 1;
}

/* Lueur douce dans la direction du tilt (coin oppose a l'inclinaison),
   meme esprit que la reference (radial-gradient positionne via --di). */
.why-us__card::before {
    content: '';
    position: absolute;
    inset: -20%;
    background: radial-gradient(60% 60% at calc(50% + var(--di) * 30%) 0%, rgb(176 33 37 / 12%), transparent 70%);
    pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
    .ct-js .why-us__card {
        opacity: 1;
        transform: none;
        transition: none;
    }

    .why-us__card:hover {
        transform: none !important;
    }
}

/* La derniere carte casse la repetition (fond noir), au lieu d'une 4e
   carte identique aux trois premieres - voir template-parts/why-us-cards.php. */
.why-us__card--dark {
    background: var(--color-black);
}

.why-us__card--dark .why-us__title,
.why-us__card--dark .why-us__text {
    color: var(--color-white);
}

.why-us__icon {
    display: inline-flex;
    margin-bottom: var(--space-md);
}

.why-us__icon .ct-icon {
    width: 2rem;
    height: 2rem;
    color: var(--color-red);
}

.why-us__card--dark .why-us__icon .ct-icon {
    color: var(--color-red-light);
}

.why-us__title {
    margin: 0 0 var(--space-xs);
    font-size: 1.0625rem;
    color: var(--color-black);
}

.why-us__text {
    margin: 0;
    font-size: 0.9375rem;
    color: var(--color-gray-text);
}

/* ---------- Refonte accueil : services (liste, fond sombre) ---------- */

.services-list {
    padding-block: var(--space-lg);
}

@media (min-width: 48rem) {
    .services-list {
        padding-block: var(--space-xl);
    }
}

.services-list__inner {
    display: grid;
    gap: var(--space-lg);
}

@media (min-width: 64rem) {
    .services-list__inner {
        grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
        align-items: center;
        gap: var(--space-xl);
    }

    /* Alterne le cote de la photo d'une section a l'autre (toiture puis
       facade) pour eviter deux blocs visuellement identiques d'affilee. */
    .services-list--reverse .services-list__media {
        order: 2;
    }
}

.services-list__media img,
.services-list__placeholder {
    width: 100%;
    aspect-ratio: 4 / 5;
    object-fit: cover;
    border-radius: var(--radius);
}

.services-list__placeholder {
    background: linear-gradient(135deg, rgb(255 255 255 / 8%), rgb(255 255 255 / 2%));
}

.services-list__items {
    /*
     * padding/list-style reinitialises : c'est une balise <ul>, son
     * padding-left par defaut du navigateur (40px) n'etait jamais retire.
     * Combine a la marge negative de .services-list__item (bleed edge-to-
     * edge voulu), ce padding fantome poussait chaque item 40px de trop
     * vers la droite - debordement horizontal reel du document sur mobile
     * (retour client : "le site glisse de gauche a droite").
     */
    padding: 0;
    list-style: none;
    margin: var(--space-md) 0 0;
    border-top: 1px solid rgb(255 255 255 / 15%);
    /*
     * L'entree en cascade (initServiceRowsReveal, reveal.js) part d'un
     * translateX(32px) le temps que chaque ligne entre dans l'ecran : un
     * element transforme compte pour le scrollWidth de ses ancetres meme
     * hors champ (regle CSS reelle, pas juste visuel), donc tant qu'une
     * ligne plus bas dans la page n'a pas encore ete revelee, le document
     * debordait reellement de 32px - defilement horizontal constate sur
     * mobile (retour client). Aucun descendant en position:sticky ici,
     * contrairement a .zone-highlights-scroll : pas de risque a le fixer
     * directement, sans le limiter a une largeur d'ecran.
     */
    overflow-x: hidden;
}

.services-list__item {
    /*
     * display:block plutot que le list-item par defaut d'un <li> : meme
     * avec list-style:none sur le parent, le navigateur reservait encore
     * l'espace de la marker box, decalant chaque item de 32px vers la
     * droite - largeur calculee correctement (elle comblait bien le
     * debordement voulu par la marge negative ci-dessous), mais position
     * fausse, ce qui produisait un vrai debordement horizontal du document
     * sur mobile (retour client : "le site glisse de gauche a droite").
     */
    display: block;
    position: relative;
    overflow: hidden;
    border-bottom: 1px solid rgb(255 255 255 / 15%);
    padding-block: var(--space-sm);
    padding-inline: var(--space-sm);
    margin-inline: calc(var(--space-sm) * -1);
}

/*
 * Bandeau qui glisse depuis la gauche au survol (registre "shimmer" 2026),
 * en CSS pur - independant de l'entree en cascade GSAP (assets/js/reveal.js,
 * initServiceRowsReveal) qui anime translateX/clip-path sur l'element
 * .services-list__item lui-meme, pas sur ce pseudo-element : aucun
 * conflit de proprietes entre les deux.
 */
.services-list__item::before {
    content: '';
    position: absolute;
    inset: 0;
    background: rgb(176 33 37 / 12%);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
    pointer-events: none;
}

.services-list__item:hover::before {
    transform: scaleX(1);
}

@media (prefers-reduced-motion: reduce) {
    .services-list__item::before {
        transition: none;
    }
}

.services-list__row {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-sm);
    color: var(--color-white);
    text-decoration: none;
}

a.services-list__row:hover .services-list__title,
a.services-list__row:focus .services-list__title {
    color: var(--color-red-light);
}

.services-list__title {
    font-family: var(--font-title);
    font-weight: 600;
    font-size: 1.0625rem;
    transition: color 0.15s ease-out;
}

.services-list__arrow {
    display: inline-flex;
    flex-shrink: 0;
}

.services-list__arrow svg {
    width: 1.375rem;
    height: 1.375rem;
    color: var(--color-red-light);
}

/*
 * Repli CSS de la fleche (translation au survol) : GSAP (assets/js/reveal.js)
 * prend le relais avec un easing "back" quand il est charge, mais l'effet de
 * base doit fonctionner sans JavaScript ou si GSAP echoue a se charger.
 */
a.services-list__row:hover .services-list__arrow,
a.services-list__row:focus .services-list__arrow {
    transform: translateX(6px);
}

.services-list__arrow {
    transition: transform 0.2s ease-out;
}

.services-list__text {
    position: relative;
    z-index: 1;
    margin: var(--space-xs) 0 0;
    color: rgb(255 255 255 / 70%);
    font-size: 0.9375rem;
}

@media (prefers-reduced-motion: reduce) {
    .services-list__arrow {
        transition: none;
    }
}

/* ---------- Refonte accueil : realisations mises en avant ---------- */

.realisations-featured {
    display: grid;
    gap: var(--space-md);
    margin-top: var(--space-md);
}

@media (min-width: 48rem) {
    .realisations-featured {
        grid-template-columns: repeat(2, 1fr);
        gap: var(--space-lg);
    }
}

.realisation-feature {
    background: var(--color-white);
}

.realisation-feature__media {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 2px;
}

/* Photo composite unique (deja avant+apres dans la meme image) : une seule
   colonne, pas deux moities cote a cote de la meme image. */
.realisation-feature__media--single {
    grid-template-columns: 1fr;
}

.realisation-feature__shot {
    margin: 0;
    position: relative;
}

.realisation-feature__shot img {
    width: 100%;
    aspect-ratio: 3 / 4;
    object-fit: cover;
    display: block;
}

.realisation-feature__shot--single img {
    aspect-ratio: 4 / 3;
}

.realisation-feature__shot figcaption {
    position: absolute;
    bottom: var(--space-xs);
    left: var(--space-xs);
    padding: 0.2rem 0.6rem;
    background: rgb(35 31 32 / 70%);
    color: var(--color-white);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-radius: var(--radius-sm);
}

.realisation-feature__placeholder {
    aspect-ratio: 3 / 4;
    background: linear-gradient(135deg, var(--color-gray-light), rgb(35 31 32 / 12%));
    display: flex;
    align-items: flex-end;
    padding: var(--space-xs);
}

.realisation-feature__placeholder span {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-gray-text);
}

.realisation-feature__body {
    padding: var(--space-md) 0.25rem 0;
}

.realisation-feature__tag {
    margin: 0 0 var(--space-xs);
    color: var(--color-red);
    text-transform: uppercase;
    font-size: 0.75rem;
    letter-spacing: 0.04em;
    font-weight: 600;
}

.realisation-feature__title {
    margin: 0 0 var(--space-xs);
    font-size: 1.25rem;
}

.realisation-feature__meta {
    margin: 0;
    color: var(--color-gray-text);
    font-size: 0.875rem;
}

/* ---------- Refonte accueil : CTA final pleine largeur ---------- */

/* Meme registre que .feature-grid__card (fond rouge, texte blanc, 6,80:1) -
   applique ici a une bande pleine largeur plutot qu'a une carte. */
.final-cta {
    background: var(--color-red);
    padding-block: var(--space-lg);
}

.final-cta__inner {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
    align-items: flex-start;
}

@media (min-width: 48rem) {
    .final-cta__inner {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: var(--space-lg);
    }
}

.final-cta__title {
    margin: 0 0 var(--space-xs);
    color: var(--color-white);
}

.final-cta__text {
    margin: 0;
    color: var(--color-white);
}

.final-cta__cta {
    background: var(--color-white);
    color: var(--color-black);
    flex-shrink: 0;
}

.final-cta__cta:hover,
.final-cta__cta:focus {
    background: var(--color-gray-light);
}

/* ---------- Revelation de texte au defilement (GSAP, accueil) ---------- */

/*
 * Mot par mot, chaque mot masque par son propre conteneur (overflow:hidden)
 * pendant que sa doublure interne remonte depuis le bas - c'est ce
 * chevauchement conteneur/doublure qui cree l'effet de "rideau" qui se
 * leve, impossible a obtenir avec le seul systeme fondu+translation de
 * data-ct-reveal (voir plus haut). Uniquement pose par JavaScript (voir
 * assets/js/reveal.js, initTextReveal) : un titre sans JavaScript, ou avec
 * GSAP indisponible, reste du texte simple, jamais decoupe.
 */
.reveal-word {
    display: inline-block;
    overflow: hidden;
    vertical-align: top;
}

.reveal-word__inner {
    display: inline-block;
    will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
    .reveal-word__inner {
        transform: none !important;
    }
}

/* ---------- Carousel d'avis Google ---------- */

/*
 * Remplace l'ancienne section a citation unique (demande client, reference
 * : widget d'avis Google). Etoiles jaunes/or et logo/icone "G" multicolores
 * : derogation ASSUMEE et EXPLICITE a la charte noir/rouge/blanc, validee
 * avec le client - couleurs officielles Google, jamais reutilisees
 * ailleurs sur le site.
 */
.reviews-carousel {
    padding-block: var(--space-xl);
    overflow: hidden;
}

.reviews-carousel__heading {
    text-align: center;
    margin-bottom: var(--space-lg);
}

.reviews-carousel__layout {
    display: grid;
    gap: var(--space-lg);
}

@media (min-width: 56rem) {
    .reviews-carousel__layout {
        grid-template-columns: 14rem 1fr;
        align-items: center;
    }
}

.reviews-carousel__summary {
    text-align: center;
}

.reviews-carousel__excellent {
    margin: 0 0 var(--space-xs);
    color: var(--color-white);
    font-family: var(--font-title);
    font-weight: 700;
    font-size: 1.25rem;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}

.reviews-carousel__stars-big {
    display: flex;
    justify-content: center;
    gap: 0.3rem;
    margin-bottom: var(--space-xs);
}

.reviews-carousel__stars-big .reviews-carousel__star {
    width: 2rem;
    height: 2rem;
}

.reviews-carousel__count {
    margin: 0 0 var(--space-sm);
    color: rgb(255 255 255 / 70%);
    font-size: 0.875rem;
}

.reviews-carousel__note {
    color: rgb(255 255 255 / 45%);
}

.reviews-carousel__google-word {
    font-family: Arial, sans-serif;
    font-weight: 700;
    font-size: 1.5rem;
}

.reviews-carousel__star {
    width: 1.125rem;
    height: 1.125rem;
    fill: #F2A900;
    flex-shrink: 0;
}

.reviews-carousel__star--empty {
    fill: rgb(255 255 255 / 15%);
}

.reviews-carousel__track-wrap {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    /* Meme raison que .reviews-carousel__track : sans min-width:0, ce grid
       item (colonne "1fr" de .reviews-carousel__layout) refuse lui aussi
       de se retrecir sous la largeur naturelle de son contenu (les 3
       cartes), et deborde du .wrap au lieu de laisser le track scroller. */
    min-width: 0;
}

.reviews-carousel__track {
    display: flex;
    /* flex:1 + min-width:0 : sans ca, un flex-item garde par defaut sa
       largeur intrinseque (min-width:auto) et refuse de se retrecir sous
       le total de ses cartes, poussant la fleche "suivant" hors du cadre
       visible au lieu de laisser le track scroller en interne. */
    flex: 1 1 0%;
    min-width: 0;
    gap: var(--space-sm);
    margin: 0;
    padding: 0.25rem 0.25rem var(--space-xs);
    list-style: none;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
}

.reviews-carousel__track::-webkit-scrollbar {
    display: none;
}

.reviews-carousel__card {
    flex: 0 0 auto;
    scroll-snap-align: start;
    width: min(20rem, 80vw);
    padding: var(--space-md);
    background: rgb(255 255 255 / 6%);
    border: 1px solid rgb(255 255 255 / 10%);
    border-radius: var(--radius);
    /*
     * Le survol (translation + echelle) est pilote par GSAP (voir
     * assets/js/reveal.js, initReviewCardsHover), pas par un :hover CSS :
     * l'entree en cascade (meme fichier) ecrit deja des proprietes
     * translate/scale en ligne sur ces cartes, qui gagnent silencieusement
     * sur un transform pose ici en feuille de style. Seuls le fond,
     * la bordure et l'ombre - jamais touches par GSAP - transitionnent en
     * CSS.
     */
    transition: box-shadow 0.4s cubic-bezier(0.16, 1, 0.3, 1),
        border-color 0.4s ease-out,
        background 0.4s ease-out;
}

.reviews-carousel__card:hover {
    background: rgb(255 255 255 / 9%);
    border-color: rgb(176 33 37 / 45%);
    box-shadow: 0 24px 48px rgb(0 0 0 / 35%), 0 0 0 1px rgb(176 33 37 / 25%);
}

.reviews-carousel__card-head {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    margin-bottom: var(--space-xs);
}

.reviews-carousel__avatar {
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}

.reviews-carousel__avatar--initial {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-red);
    color: var(--color-white);
    font-family: var(--font-title);
    font-weight: 700;
}

.reviews-carousel__identity {
    flex: 1;
    min-width: 0;
}

.reviews-carousel__name {
    margin: 0;
    color: var(--color-white);
    font-weight: 600;
    font-size: 0.9375rem;
}

.reviews-carousel__time {
    margin: 0;
    color: rgb(255 255 255 / 55%);
    font-size: 0.8125rem;
}

.reviews-carousel__g-icon {
    width: 1.25rem;
    height: 1.25rem;
    flex-shrink: 0;
}

.reviews-carousel__card-stars {
    display: flex;
    gap: 0.15rem;
    margin-bottom: var(--space-xs);
}

.reviews-carousel__text {
    margin: 0;
    color: rgb(255 255 255 / 80%);
    font-size: 0.9375rem;
    line-height: 1.5;
}

.reviews-carousel__arrow {
    flex-shrink: 0;
    display: none;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    background: transparent;
    border: 1px solid rgb(255 255 255 / 25%);
    border-radius: 50%;
    color: var(--color-white);
    cursor: pointer;
}

.reviews-carousel__arrow:hover,
.reviews-carousel__arrow:focus-visible {
    background: rgb(255 255 255 / 10%);
}

.reviews-carousel__arrow svg {
    width: 1.25rem;
    height: 1.25rem;
}

@media (min-width: 56rem) {
    .reviews-carousel__arrow {
        display: inline-flex;
    }
}
