:root {
    /* Pacific Palette */
    --primary-color: #006994;
    /* Deep Ocean Blue */
    --secondary-color: #00b4db;
    /* Lagoon Turquoise */
    --accent-color: #f7b733;
    /* Golden Sand */
    --text-dark: #0f172a;
    --text-light: #f8fafc;
    --white-glass: rgba(255, 255, 255, 0.7);
    --dark-glass: rgba(15, 23, 42, 0.8);

    /* Spacing & Layout */
    --container-width: 1200px;
    --section-padding: 5rem 2rem;
    --border-radius: 1rem;

    /* ---- Mouvement -------------------------------------------------------
       Courbes et durées centralisées : chaque animation du site y puise, pour
       que le mouvement ait la même signature d'une page à l'autre.

       `--transition` ne vaut plus `all`. Une transition « all » anime aussi
       les propriétés qu'on ne visait pas — dont celles qui déclenchent une
       remise en page complète — et le navigateur ne peut plus les déléguer au
       GPU. On nomme donc les propriétés, toutes composables (couleur, ombre,
       opacité, transformation).

       Les courbes natives (`ease`, `ease-out`) sont trop molles pour de
       l'interface : elles n'ont pas d'attaque. Les trois ci-dessous sont les
       courbes de référence — sortie franche, aller-retour symétrique, et la
       courbe de tiroir façon iOS pour les panneaux qui glissent. */
    --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
    --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
    --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);

    /* Une interface reste sous 300 ms. Seule la révélation au défilement, qui
       accompagne la lecture plutôt qu'une action, se permet davantage. */
    --dur-press: 120ms;
    --dur-hover: 220ms;
    --dur-panel: 300ms;
    --dur-reveal: 620ms;

    --transition:
        color var(--dur-hover) var(--ease-out),
        background-color var(--dur-hover) var(--ease-out),
        border-color var(--dur-hover) var(--ease-out),
        box-shadow var(--dur-hover) var(--ease-out),
        opacity var(--dur-hover) var(--ease-out),
        transform var(--dur-hover) var(--ease-out);
}

html {
    background-color: #0f172a;

    /* Gouttière de barre de défilement toujours réservée.
       Sans elle, une page qui tient dans l'écran (connexion client, page
       d'erreur) récupère les ~15 px de la barre absente : la zone utile passe
       de 1265 à 1280 px et le conteneur centré décale toute la barre de
       navigation de 7,5 px. Le logo saute donc d'une page à l'autre. */
    scrollbar-gutter: stable;
}

/* Navigateurs sans `scrollbar-gutter` (Safari < 16) : on force l'affichage de
   la barre, ce qui réserve la même largeur par un autre moyen. Sur les systèmes
   à barres flottantes (macOS, mobile), aucune des deux n'a d'effet — et il n'y
   a pas de décalage non plus, puisque la barre ne prend jamais de place. */
@supports not (scrollbar-gutter: stable) {
    html { overflow-y: scroll; }
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Inter', sans-serif;
    color: var(--text-light);
    line-height: 1.6;
    /* Pacific + Tech Background (Lighter Version) */
    /* Image hébergée en local (img/bg/) : elle était chargée depuis Unsplash,
       ce qui la rendait dépendante d'un service tiers, transmettait l'IP de
       chaque visiteur, et se faisait refuser par la CSP du site. */
    background:
        /* Lighter Blue Tech Overlay - reduced opacity from 0.9 to 0.5-0.7 */
        linear-gradient(135deg, rgba(15, 32, 39, 0.7), rgba(32, 58, 67, 0.6), rgba(44, 83, 100, 0.5)),
        /* Texture/Image */
        url('../img/bg/hero-ocean.jpg') no-repeat center center fixed;
    background-size: cover;
    min-height: 100vh;
    overflow-x: clip;
}

@keyframes gradientBG {
    0% {
        background-position: 0% 50%;
    }

    50% {
        background-position: 100% 50%;
    }

    100% {
        background-position: 0% 50%;
    }
}

/* Typography */
h1,
h2,
h3,
h4 {
    font-family: 'Poppins', sans-serif;
    font-weight: 700;
    line-height: 1.2;
}

a {
    text-decoration: none;
    color: inherit;
}

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

/* Utilities */
.container {
    max-width: var(--container-width);
    margin: 0 auto;
    padding: 0 1rem;
}

.btn {
    display: inline-block;
    padding: 0.8rem 2rem;
    border-radius: 2rem;
    font-weight: 600;
    transition: var(--transition);
    cursor: pointer;
    border: none;
}

.btn-primary {
    background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
    color: white;
    box-shadow: 0 4px 15px rgba(0, 180, 219, 0.3);
}

.btn-primary:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 25px rgba(0, 180, 219, 0.4);
}

.btn-outline {
    border: 2px solid rgba(255, 255, 255, 0.5);
    color: white;
    background: rgba(255, 255, 255, 0.1);
    /* White/Transparent background */
    backdrop-filter: blur(5px);
}

.btn-outline:hover {
    background: rgba(255, 255, 255, 0.3);
    color: white;
    border-color: white;
}

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

.mb-2 {
    margin-bottom: 2rem;
}

.mb-5 {
    margin-bottom: 5rem;
}

/* Header & Nav */
header {
    position: fixed;
    top: 0;
    width: 100%;
    z-index: 1000;
    /* `padding` figure ici explicitement : c'est la seule propriété de mise en
       page animée du site, et elle l'est sciemment — la barre qui se resserre
       au défilement n'a pas d'équivalent en `transform`. Elle est isolée sur un
       élément fixe au sous-arbre court, donc le recalcul reste local. */
    transition:
        background-color var(--dur-panel) var(--ease-out),
        box-shadow var(--dur-panel) var(--ease-out),
        padding var(--dur-panel) var(--ease-out);
    padding: 1.5rem 0;
}

header.scrolled {
    background: rgba(15, 23, 42, 0.7);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
    padding: 1rem 0;
    transform: translateZ(0);
}

nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.logo {
    font-size: 1.8rem;
    font-weight: 800;
    color: white;
    /* Better contrast on dark bg */
    letter-spacing: -1px;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.logo span {
    color: var(--secondary-color);
}

.nav-links {
    display: flex;
    gap: 2rem;
    list-style: none;
    align-items: center;
}

.nav-links a {
    font-weight: 500;
    font-size: 1rem;
    color: #ffffff;
    /* White text */
    transition: var(--transition);
    position: relative;
}

/* Le trait se dessine par `scaleX` et non par `width` : animer une largeur
   remet en page le lien à chaque image, une transformation ne coûte rien.
   `transform-origin: left` reproduit le trait qui se trace de gauche à droite,
   et bascule à droite au retrait pour qu'il se rétracte par où il est venu. */
.nav-links a::after {
    content: '';
    position: absolute;
    bottom: -5px;
    left: 0;
    width: 100%;
    height: 2px;
    background: var(--secondary-color);
    transform: scaleX(0);
    transform-origin: right center;
    transition: transform var(--dur-hover) var(--ease-out);
}

.nav-links a:hover {
    color: var(--secondary-color);
}

@media (hover: hover) and (pointer: fine) {
    .nav-links a:hover::after {
        transform: scaleX(1);
        transform-origin: left center;
    }
}

.nav-links a.btn::after {
    display: none;
}

.nav-links .btn-primary:hover {
    color: white;
}

.hamburger {
    display: none;
    cursor: pointer;
}

/* Hero Section */
.hero {
    min-height: 100vh;
    display: flex;
    align-items: center;
    padding-top: 5rem;
    /* Removed individual background since body handles it now to be seamless */
    position: relative;
    overflow: clip;
}

.hero::before {
    content: '';
    position: absolute;
    top: -50%;
    right: -20%;
    width: 800px;
    height: 800px;
    background: radial-gradient(circle, rgba(0, 180, 219, 0.1) 0%, rgba(0, 0, 0, 0) 70%);
    border-radius: 50%;
    z-index: -1;
}

.hero-content {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4rem;
    align-items: center;
}

.hero-text h1 {
    font-size: 3.5rem;
    margin-bottom: 1.5rem;
    background: linear-gradient(to right, #00b4db, #f7b733);
    /* Brighter gradient for dark bg */
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.hero-text p {
    font-size: 1.2rem;
    color: var(--text-light);
    /* Enforce light text */
    margin-bottom: 2.5rem;
    max-width: 500px;
}

.hero-image {
    position: relative;
}

.hero-image img {
    border-radius: 2rem;
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.1);
    transform: perspective(1000px) rotateY(-5deg);
    transition: var(--transition);
}

.hero-image:hover img {
    transform: perspective(1000px) rotateY(0deg);
}

/* Services Section */
.services {
    padding: var(--section-padding);
    background: transparent;
}

.section-title {
    text-align: center;
    margin-bottom: 4rem;
}

.section-title h2 {
    font-size: 2.5rem;
    margin-bottom: 1rem;
    color: #c4f4fa;
}

.section-title p {
    color: #e2e8f0;
    /* Very light grey */
    max-width: 600px;
    margin: 0 auto;
}

.services-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
    gap: 2rem;
}

.service-card {
    /* La carte EST un <a> : sans `display: block`, un lien reste en ligne et
       n'accepte ni la hauteur ni les marges internes. `color`/`text-decoration`
       sont deja neutralises par la regle `a` de la typographie de base. */
    display: block;
    padding: 2.5rem;
    background: rgba(255, 255, 255, 0.1);
    /* White/Light glass */
    backdrop-filter: blur(12px);
    border-radius: 1.5rem;
    transition: var(--transition);
    border: 1px solid rgba(255, 255, 255, 0.2);
}

.service-card:hover {
    background: rgba(255, 255, 255, 0.2);
    /* Lighter on hover */
    transform: translateY(-10px);
    box-shadow: 0 15px 30px rgba(0, 0, 0, 0.3);
    border-color: var(--secondary-color);
}

.icon-box {
    width: 60px;
    height: 60px;
    background: rgba(176, 235, 255, 0.2);
    border-radius: 1rem;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 1.5rem;
    font-size: 1.5rem;
    color: var(--secondary-color);
}

.service-card h3 {
    margin-bottom: 1rem;
    font-size: 1.5rem;
    color: #e0f7fa;
    /* Very light blue */
}

.service-card p {
    color: var(--text-light);
    /* Pure light text */
}

/* Portfolio Section */
.portfolio {
    padding: var(--section-padding);
    background: transparent;
}

.portfolio-showcase {
    display: grid;
    /* La capture prend le pas sur le texte. C'est elle la preuve : le visiteur
       vient voir à quoi ressemble ce qu'on livre, pas lire une description.
       À parts égales, l'écran tombait à 420 px de large dans une carte qui en
       fait 1000, et la diapositive avait l'air d'être surtout du vide. */
    grid-template-columns: 1.15fr 0.85fr;
    gap: 3.25rem;
    align-items: center;
    background: rgba(255, 255, 255, 0.1);
    backdrop-filter: blur(12px);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 2rem;
    padding: 3rem;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}

/* Cadre du visuel — voir le commentaire de `.project-img img` plus bas :
   la capture est montée dans un cadre, jamais recadrée. */
.project-img {
    padding: 16px;
    border-radius: 1rem;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.12);
    box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
}

.project-info h3 {
    font-size: 2rem;
    margin-bottom: 1rem;
    color: #c4f4fa;
}

/* ── Carrousel des réalisations (accueil) ──────────────────────────────────

   DÉFILEMENT NATIF, ET NON UNE PISTE TRANSLATÉE.
   Le navigateur sait déjà faire glisser une zone au doigt, avec l'inertie et
   le rebond du système ; `scroll-snap` lui demande simplement de s'arrêter sur
   une diapositive entière. On y gagne trois choses qu'une piste en
   `transform` aurait fallu réécrire à la main :

     · le balayage tactile fonctionne sans une ligne de JavaScript ;
     · la molette horizontale et le trackpad marchent aussi ;
     · sans JavaScript, les six projets restent ATTEIGNABLES — une piste
       translatée n'en aurait montré qu'un, les cinq autres hors d'atteinte.

   Le script ne fait donc qu'ajouter le confort : flèches, segments, avance
   automatique.

   ── LES VOISINES DÉBORDENT ────────────────────────────────────────────────
   La diapositive n'occupe pas toute la largeur : celles d'à côté dépassent de
   part et d'autre, en retrait et légèrement réduites.

   C'est le geste principal de cette section, et il est structurel, pas
   décoratif. Une carte seule, centrée, qui change de contenu toutes les sept
   secondes, ne ressemble pas à un carrousel : elle ressemble à une carte qui
   se met à bouger sans prévenir. En laissant voir ce qui vient, on répond
   avant même qu'elle ne se pose à la seule question qui compte ici — « il y en
   a d'autres ? » — et le mouvement automatique devient la suite de ce qu'on
   avait sous les yeux plutôt qu'une surprise.

   Le retrait des voisines emprunte au vocabulaire que le site tient déjà : la
   profondeur y passe par la superposition de verre et l'opacité, jamais par un
   contour. Une voisine à 40 % d'opacité et 94 % d'échelle est simplement une
   carte posée un cran plus loin. */
.pf-carousel {
    /* Ce que les voisines laissent voir, de chaque côté. Tout le reste en
       découle — cales de centrage, largeur utile, décalage calculé par le
       script. Un seul nombre à changer.

       IL A UNE LIMITE HAUTE, et elle n'est pas esthétique : la part visible
       doit rester INFÉRIEURE À LA MARGE INTÉRIEURE de la carte (3 rem, 1,5 rem
       sous 480 px). Au-delà, on ne voit plus le bord de la voisine mais le
       début de son contenu — des demi-mots de sa description suspendus dans le
       vide, qu'on lit avant de comprendre qu'ils ne s'adressent pas à nous.
       Ce qui est réellement visible vaut :
           débordement − gouttière − (1 − échelle) × largeur ÷ 2
       soit ici ≈ 44 px pour 48 px de marge. La marge de manœuvre est mince :
       augmenter ce nombre demande de vérifier le calcul à chaque palier. */
    --pf-debord: 6.5%;
    --pf-gouttiere: 0.75rem;
    position: relative;
}

/* Une seule réalisation : il n'y a rien à faire déborder, et réserver la
   marge rétrécirait la carte pour montrer du vide. */
.pf-carousel.pf-seule {
    --pf-debord: 0%;
}

.pf-viewport {
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    /* Marge verticale seulement : elle laisse passer l'ombre portée, que le
       débordement masqué trancherait net. Le dégagement LATÉRAL, lui, ne peut
       pas se faire ici — voir les cales de `.pf-piste`. */
    padding: 18px 0;
    /* Barre de défilement cachée : les segments disent déjà où l'on en est. */
    scrollbar-width: none;
    -ms-overflow-style: none;
    /* PAS DE `mask-image` ICI. À ne pas remettre.
       Un masque avait été posé pour fondre les bords ; il faisait disparaître
       le verre dépoli des cartes. Un élément masqué devient une RACINE DE FOND :
       le `backdrop-filter` de ses descendants n'a plus rien à flouter derrière
       lui. Les diapositives perdaient donc leur dépoli sans erreur ni message,
       et il ne restait que leur voile blanc à 10 % — la photo de fond
       traversait la carte, nette. Le défaut sautait aux yeux au survol des
       flèches, qui portent elles aussi un `backdrop-filter` : le navigateur
       recomposait la zone, et le verre semblait glisser.
       Le débordement est désormais calibré pour ne montrer que la MARGE
       INTÉRIEURE de la carte voisine (voir `--pf-debord`) : il n'y a plus de
       texte tranché à cacher, donc plus rien à fondre. */
}

.pf-viewport::-webkit-scrollbar {
    display: none;
}

/* La zone défile, donc elle reçoit le clavier (voir assets/script.js) : elle
   doit pouvoir se désigner comme telle. Le contour épouse la carte affichée
   plutôt que le rectangle pleine largeur, qui aurait cerné du vide. */
.pf-viewport:focus-visible {
    outline: none;
}

.pf-viewport:focus-visible .pf-slide.actif {
    outline: 2px solid var(--secondary-color);
    outline-offset: 6px;
}

.pf-piste {
    display: flex;
    gap: var(--pf-gouttiere);
}

/* Cales de début et de fin.
   Sans elles, la PREMIÈRE et la DERNIÈRE diapositive ne peuvent pas se
   centrer : elles restent collées au bord, seules à ne pas obéir à la règle
   que suivent toutes les autres.
   Ce dégagement ne peut PAS être une marge intérieure de la zone qui défile.
   Une marge de fin posée là n'entre pas dans l'étendue défilable dès que le
   contenu déborde : le défilement s'arrête 113 px trop tôt et la dernière
   diapositive reste décalée, avec du vide à sa droite. Deux cales, elles, sont
   du contenu — elles comptent. La gouttière est retranchée de leur largeur,
   puisqu'elle s'ajoute déjà entre la cale et la diapositive voisine. */
.pf-piste::before,
.pf-piste::after {
    content: '';
    flex: 0 0 max(0px, calc(var(--pf-debord) - var(--pf-gouttiere)));
}

.pf-slide {
    /* Ce que la section laisse, une fois le débordement retiré des deux côtés :
       la diapositive est donc plus étroite que la section, et c'est cet écart
       que les voisines occupent. */
    flex: 0 0 calc(100% - 2 * var(--pf-debord));
    min-width: 0;
    scroll-snap-align: center;
    scroll-snap-stop: always;
    border-radius: 2rem;
    /* Position d'attente : un cran en arrière. Le script pose `actif` sur
       celle qui est au centre. */
    opacity: .45;
    transform: scale(.96);
    transition:
        opacity var(--dur-panel) var(--ease-out),
        transform var(--dur-panel) var(--ease-out);
}

.pf-slide.actif {
    opacity: 1;
    transform: none;
}

/* Sans JavaScript, `actif` n'est jamais posé et les diapositives resteraient
   toutes à demi effacées. Elles reprennent alors leur pleine présence : la
   page dégradée doit être sobre, pas abîmée. */
.pf-carousel:not(.pf-anime) .pf-slide {
    opacity: 1;
    transform: none;
}

/* Le visuel occupe toujours la même hauteur, image ou vidéo : sans ce cadrage,
   chaque diapositive imposerait la sienne et le carrousel sauterait d'un projet
   à l'autre.

   `contain` et non `cover` : ce qu'on montre ici est une CAPTURE DE SITE, et
   une capture ne survit pas au recadrage — on couperait la barre de navigation,
   les marges, la mise en page, c'est-à-dire précisément ce qu'on veut donner à
   voir. Les captures n'ont d'ailleurs pas toutes le même format ; sous `cover`,
   une capture large perdait un cinquième de sa hauteur.

   L'image est donc posée en entier sur une plaque sombre, dans un cadre de
   taille fixe : le cadre aligne les diapositives, l'œuvre varie à l'intérieur.
   Et aucun `scale` au survol — un agrandissement dans un cadre à débordement
   masqué rogne les bords, ce qui ramène exactement le défaut corrigé ici. */
.project-img img,
.project-img video {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: contain;
    border-radius: 0.6rem;
    background: rgba(0, 0, 0, 0.28);
}

.pf-sans-visuel {
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 16 / 9;
    border-radius: 0.6rem;
    background: rgba(0, 0, 0, 0.28);
    color: rgba(255, 255, 255, 0.2);
    font-size: 3.5rem;
}

.project-img {
    transition:
        border-color var(--dur-panel) var(--ease-out),
        box-shadow var(--dur-panel) var(--ease-out);
}

/* L'écran de la diapositive affichée est ÉCLAIRÉ : une ombre lagon sous la
   plaque, de la même famille que la lueur qui porte `.btn-primary`. Elle est
   décalée et diffuse, comme toutes les ombres du site — un halo centré et sans
   décalage n'est pas de la profondeur, c'est un contour de couleur.
   Elle ne se pose que sur la diapositive active : c'est ce qui distingue
   l'écran qu'on regarde de ceux qui attendent leur tour. */
.pf-slide.actif .project-img {
    border-color: rgba(0, 180, 219, 0.28);
    box-shadow:
        0 14px 34px rgba(0, 0, 0, 0.28),
        0 10px 40px rgba(0, 180, 219, 0.16);
}

/* Secteur : la même étiquette discrète que sur la page des réalisations
   (`.rz-secteur`), et non plus une pastille pleine qui pesait plus lourd que
   le nom du projet placé juste dessous. Deux pages montrent la même donnée ;
   elles la montrent désormais de la même façon. */
.project-info .tag {
    display: block;
    margin-bottom: 0.55rem;
    padding: 0;
    border-radius: 0;
    background: none;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--secondary-color);
}

/* Quatre lignes, ni plus ni moins.
   Toutes les diapositives partagent la hauteur de la plus haute — c'est ce qui
   empêche le carrousel de sauter d'un projet à l'autre. Une description de deux
   phrases imposait donc 170 px de verre vide aux projets décrits en une seule,
   et la carte avait l'air d'attendre quelque chose.
   Le `min-height` réserve les quatre lignes même quand le texte en fait deux,
   le `line-clamp` retient les bavards : les diapositives arrivent à la même
   hauteur, quel que soit ce qui est saisi dans l'administration. Et c'est de
   toute façon la bonne longueur ici — l'accueil donne envie, la page des
   réalisations raconte. Le texte entier y est, à un clic. */
.pf-desc {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 4;
    line-clamp: 4;
    overflow: hidden;
    min-height: calc(4 * 1.6em);
    margin-bottom: 1.5rem;
    color: white;
}

.pf-presta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 1.75rem;
}

.pf-presta-lbl {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: rgba(255, 255, 255, 0.45);
}

.pf-presta a {
    font-size: 0.8rem;
    padding: 0.3rem 0.85rem;
    border-radius: 2rem;
    color: #7fe3f5;
    background: rgba(0, 180, 219, 0.14);
    border: 1px solid rgba(0, 180, 219, 0.3);
    text-decoration: none;
    transition: var(--transition);
}

.pf-presta a:hover {
    background: rgba(0, 180, 219, 0.28);
    border-color: rgba(0, 180, 219, 0.55);
}

/* Commandes : une seule barre sous le carrousel, plutôt que des flèches posées
   par-dessus les diapositives. Sur un visuel clair, une flèche en surimpression
   devient invisible, et sur mobile elle recouvre le contenu qu'elle sert. */
.pf-commandes {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.5rem;
    margin-top: 1.25rem;
}

.pf-fleche {
    width: 46px;
    height: 46px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    font-size: 1.5rem;
    cursor: pointer;
    color: white;
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.22);
    backdrop-filter: blur(12px);
    transition: var(--transition);
}

/* Au survol, la flèche prend le dégradé et la lueur du bouton principal du
   site, et se soulève de la même façon : c'est le geste que la page fait déjà
   partout ailleurs, il n'y avait aucune raison que ses commandes l'ignorent. */
.pf-fleche:hover {
    background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
    border-color: transparent;
    transform: translateY(-2px);
    box-shadow: 0 8px 22px rgba(0, 180, 219, 0.35);
}

.pf-fleche:active {
    transform: translateY(0);
}

.pf-points {
    display: flex;
    align-items: center;
    gap: 10px;
}

/* Segment plutôt que pastille. Il dit deux choses là où un point n'en disait
   qu'une : où l'on est, ET combien de temps il reste avant que ça bouge. Le
   carrousel cesse ainsi de surprendre — on voit venir le changement, et le
   remplissage se fige sous le pointeur, ce qui montre que la pause a bien été
   prise en compte.
   La zone cliquable fait 22 px de haut alors que le trait n'en fait que 4 —
   une cible de 4 px se rate au doigt. Le rembourrage est transparent. */
.pf-point {
    width: 44px;
    height: 22px;
    padding: 9px 0;
    border: none;
    background: none;
    cursor: pointer;
    display: block;
}

.pf-point::before {
    content: '';
    display: block;
    height: 4px;
    border-radius: 2px;
    background: rgba(255, 255, 255, 0.22);
    transition: background var(--dur-hover) var(--ease-out);
}

.pf-point:hover::before {
    background: rgba(255, 255, 255, 0.42);
}

.pf-point[aria-selected="true"]::before {
    background: rgba(0, 180, 219, 0.3);
}

/* Le remplissage vit dans un `<span>` et non dans un pseudo-élément : le
   script doit pouvoir relancer son animation à chaque changement de
   diapositive, et la figer quand l'avance automatique est suspendue — deux
   choses hors de portée d'un `::after`. */
.pf-jauge {
    display: block;
    height: 4px;
    margin-top: -4px;
    border-radius: 2px;
    background: var(--secondary-color);
    transform: scaleX(0);
    transform-origin: left center;
}

@keyframes pf-progression {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
}

/* Sous « réduire les animations », rien ne défile tout seul : le segment actif
   est donc simplement plein, il n'y a aucun compte à rebours à montrer. */
@media (prefers-reduced-motion: reduce) {
    .pf-point[aria-selected="true"] .pf-jauge {
        transform: scaleX(1);
    }
}

@media (max-width: 900px) {
    .pf-carousel {
        /* Une part plus grande qu'au-dessus, et pourtant moins de pixels : le
           carrousel ne fait plus que 294 px de large à 390 px d'écran, contre
           1168 sur un portable. En pourcentage constant, le débordement serait
           tombé à une dizaine de pixels — plus assez pour lire « il y en a une
           autre ».
           La limite reste la même : sous la marge intérieure de la carte, qui
           tombe à 1,5 rem en dessous de 480 px. Mesuré à ce palier, le point le
           plus serré : 20 px de visible pour 24 px de marge. */
        --pf-debord: 8.5%;
        --pf-gouttiere: 0.5rem;
    }

    .pf-slide {
        transform: scale(.97);
    }

    /* Colonne étroite, donc lignes courtes : les quatre lignes du bureau en
       font cinq ici, et la description la plus brève se retrouvait coupée
       alors qu'elle tenait entière. On rend la ligne manquante. */
    .pf-desc {
        -webkit-line-clamp: 5;
        line-clamp: 5;
        min-height: calc(5 * 1.6em);
    }

    /* 2 rem sur 294 px de colonne coupent « Joyce Location » en deux. */
    .project-info h3 {
        font-size: 1.75rem;
    }
}

@media (max-width: 480px) {
    .pf-commandes {
        gap: 0.9rem;
    }

    .pf-point {
        width: 34px;
    }
}

/* Contact Section */
.contact {
    padding: var(--section-padding);
    background: linear-gradient(135deg, var(--primary-color), #0f2027);
    color: white;
    text-align: center;
}

.contact-container {
    max-width: 800px;
    margin: 0 auto;
}

.contact h2 {
    color: white;
    font-size: 2.5rem;
    margin-bottom: 1.5rem;
}

.contact p {
    color: rgba(255, 255, 255, 0.8);
    margin-bottom: 3rem;
    font-size: 1.2rem;
}

.contact-btn {
    background: var(--accent-color);
    color: var(--text-dark);
    padding: 1rem 3rem;
    border-radius: 2rem;
    font-size: 1.1rem;
    font-weight: 700;
    transition: var(--transition);
}

.contact-btn:hover {
    background: white;
    transform: scale(1.05);
}

/* Footer */
footer {
    background: #0f172a;
    color: #94a3b8;
    padding: 4rem 0 2rem;
}

.footer-content {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
    gap: 3rem;
    margin-bottom: 3rem;
}

.footer-col h2 {
    color: white;
    margin-bottom: 1.5rem;
    font-size: 1.2rem;
}

.footer-links {
    list-style: none;
}

.footer-links li {
    margin-bottom: 0.8rem;
}

.footer-links a:hover {
    color: var(--secondary-color);
}

.footer-bottom {
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    padding-top: 2rem;
    text-align: center;
    font-size: 0.9rem;
}

/* Mobile Responsive */
@media (max-width: 900px) {
    header {
        padding: 1.25rem 0;
    }

    .hamburger {
        display: block;
        color: var(--primary-color);
        font-size: 1.5rem;
    }

    .nav-links {
        position: fixed;
        top: 70px;
        right: -100%;
        width: 70%;
        height: calc(100vh - 70px);
        background: rgba(15, 23, 42, 0.1);
        backdrop-filter: blur(15px);
        flex-direction: column;
        align-items: center;
        justify-content: center;
        /* Le tiroir glissait en animant `right` de -100% à 0 : une propriété de
           mise en page, recalculée à chaque image pendant que le doigt attend.
           Il est désormais posé à sa place définitive et translaté hors champ,
           ce que le compositeur seul peut faire. */
        right: 0;
        transform: translateX(100%);
        transition: transform var(--dur-panel) var(--ease-drawer);
        border-left: 1px solid rgba(255, 255, 255, 0.1);
        box-shadow: -5px 0 15px rgba(0, 0, 0, 0.5);
    }

    header.scrolled .nav-links {
        background: rgba(15, 23, 42, 0.7);
    }

    .nav-links.active {
        transform: translateX(0);
    }

    /* Les entrées arrivent en cascade derrière le tiroir. Décalage de 40 ms :
       assez pour qu'on lise une succession, trop court pour qu'on attende.
       Le dernier lien est en place 240 ms après l'ouverture du panneau. */
    .nav-links li {
        opacity: 0;
        transform: translateX(18px);
        transition:
            opacity var(--dur-panel) var(--ease-out),
            transform var(--dur-panel) var(--ease-out);
    }

    .nav-links.active li {
        opacity: 1;
        transform: translateX(0);
    }

    .nav-links.active li:nth-child(1) { transition-delay: 60ms; }
    .nav-links.active li:nth-child(2) { transition-delay: 100ms; }
    .nav-links.active li:nth-child(3) { transition-delay: 140ms; }
    .nav-links.active li:nth-child(4) { transition-delay: 180ms; }
    .nav-links.active li:nth-child(5) { transition-delay: 220ms; }
    .nav-links.active li:nth-child(6) { transition-delay: 260ms; }
    .nav-links.active li:nth-child(7) { transition-delay: 300ms; }


    .hero-content {
        grid-template-columns: 1fr;
        text-align: center;
        gap: 3rem;
    }

    .hero-text h1 {
        font-size: 2.5rem;
    }

    .portfolio-showcase {
        grid-template-columns: 1fr;
    }

    /* Stack buttons on mobile */
    .hero-btns {
        display: flex;
        flex-direction: column;
        gap: 1rem;
        width: 100%;
    }

    .btn,
    .contact-btn {
        width: 100%;
        text-align: center;
        display: block;
    }

    /* Remove left margin from second button in hero on mobile */
    .hero-btns .btn-outline {
        margin-left: 0 !important;
    }

    /* Contact Page Mobile */
    .contact-wrapper {
        grid-template-columns: 1fr;
        gap: 2rem;
    }

    .contact-info h1 {
        font-size: 2.5rem;
    }

    /* Footer Mobile */
    .footer-content {
        grid-template-columns: 1fr;
        text-align: center;
    }
}

/* Contact Page Specifics */
.contact-hero {
    min-height: 100vh;
    display: flex;
    align-items: center;
    padding-top: 8rem;
    /* Account for fixed header */
    padding-bottom: 4rem;
}

.contact-wrapper {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4rem;
    align-items: center;
}

.contact-info h1 {
    font-size: 3rem;
    margin-bottom: 1.5rem;
    line-height: 1.1;
}

.contact-info .highlight {
    color: var(--secondary-color);
    position: relative;
    display: inline-block;
}

.contact-info .highlight::after {
    content: '';
    position: absolute;
    bottom: -5px;
    left: 0;
    width: 100%;
    height: 8px;
    background: rgba(0, 180, 219, 0.3);
    border-radius: 4px;
    z-index: -1;
}

.contact-info p {
    font-size: 1.1rem;
    color: var(--text-light);
    margin-bottom: 3rem;
    max-width: 90%;
}

.info-cards {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
}

.info-card {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    padding: 1.5rem;
    background: rgba(255, 255, 255, 0.05);
    /* Very subtle glass */
    border-radius: 1rem;
    transition: var(--transition);
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.info-card:hover {
    background: rgba(255, 255, 255, 0.1);
    transform: translateX(10px);
    border-color: var(--secondary-color);
}

.info-card h2 {
    margin-bottom: 0.2rem;
    font-size: 1.1rem;
}

.info-card p {
    margin-bottom: 0;
    font-size: 0.95rem;
    color: #cbd5e1;
    white-space: nowrap;
}

/* Glass Form */
.glass-form {
    background: rgba(255, 255, 255, 0.07);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    padding: 3rem;
    border-radius: 2rem;
    border: 1px solid rgba(255, 255, 255, 0.15);
    box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
}

.glass-form h3,
.glass-form .step-content > h2 {
    margin-bottom: 2rem;
    font-size: 1.8rem;
    text-align: center;
    color: #e0f2fe;
}

.input-group {
    position: relative;
    margin-bottom: 2rem;
}

.input-group i {
    position: absolute;
    left: 1.2rem;
    top: 50%;
    transform: translateY(-50%);
    font-size: 1.2rem;
    color: rgba(255, 255, 255, 0.5);
    transition: var(--transition);
    pointer-events: none;
}

.input-group.textarea-group i {
    top: 1.5rem;
    transform: none;
}

.input-group input,
.input-group textarea,
.input-group select {
    width: 100%;
    padding: 1rem 1rem 1rem 3.5rem;
    background: rgba(0, 0, 0, 0.2);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 1rem;
    color: white;
    font-size: 1rem;
    font-family: 'Inter', sans-serif;
    outline: none;
    transition: var(--transition);
}

.input-group textarea {
    min-height: 120px;
    resize: vertical;
}

.input-group label {
    position: absolute;
    left: 3.5rem;
    top: 50%;
    transform: translateY(-50%);
    color: rgba(255, 255, 255, 0.6);
    pointer-events: none;
    /* Transition dédiée : l'étiquette qui monte au-dessus du champ se déplace
       en `top`/`left` et change de corps. Ces propriétés ne sont pas dans
       `--transition` (elles remettent en page) ; on les nomme donc ici, pour
       cet unique cas où l'effet en dépend. */
    transition:
        top var(--dur-hover) var(--ease-out),
        left var(--dur-hover) var(--ease-out),
        font-size var(--dur-hover) var(--ease-out),
        padding var(--dur-hover) var(--ease-out),
        color var(--dur-hover) var(--ease-out),
        background-color var(--dur-hover) var(--ease-out);
    font-size: 1rem;
}

.input-group.textarea-group label {
    top: 1.5rem;
    transform: none;
}

/* Float Label Animation */
.input-group input:focus,
.input-group textarea:focus,
.input-group select:focus,
.input-group.focused input,
.input-group.focused textarea,
.input-group.focused select {
    background: rgba(255, 255, 255, 0.1);
    border-color: var(--secondary-color);
    box-shadow: 0 0 0 4px rgba(0, 180, 219, 0.1);
}

.input-group input:focus+label,
.input-group textarea:focus+label,
.input-group select:focus+label,
.input-group.focused label {
    top: -0.9rem;
    left: 1rem;
    font-size: 0.8rem;
    color: #ffffff;
    background: var(--secondary-color);
    padding: 0.2rem 0.8rem;
    transform: none;
    border-radius: 2rem;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
    font-weight: 500;
}

.input-group input:focus~i,
.input-group textarea:focus~i,
.input-group select:focus~i,
.input-group.focused i {
    color: var(--secondary-color);
}

.submit-btn {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    font-size: 1.1rem;
}

/* Select specific fix */
.input-group select {
    appearance: none;
    cursor: pointer;
    padding-right: 2.5rem;
    /* Make room for the arrow */
    background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='rgba(255, 255, 255, 0.7)'%3e%3cpath d='M7 10l5 5 5-5z'/%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: right 1rem center;
    background-size: 1.5rem;
}

.input-group select option {
    background: var(--primary-color);
    /* Lighter than the previous dark slate */
    color: white;
    padding: 10px;
}

@media (max-width: 900px) {
    .contact-wrapper {
        grid-template-columns: 1fr;
        gap: 3rem;
    }

    .contact-info {
        text-align: center;
    }

    .contact-info p {
        margin: 0 auto 3rem auto;
    }

    .info-card {
        justify-content: flex-start;
        /* Keep icons aligned */
        text-align: left;
    }

    .contact-hero {
        padding-top: 7rem;
    }
}

/* ==========================================================================
   Révélation au défilement
   --------------------------------------------------------------------------
   Deux utilitaires coexistaient (`.fade-in-section` et `.scroll-reveal`) avec
   des durées et des courbes différentes : sur une même page, deux blocs voisins
   n'entraient pas au même rythme. Ils partagent désormais la même mécanique et
   ne se distinguent plus que par la direction d'entrée.

   Une ANIMATION, et non une transition. La distinction n'est pas cosmétique :
   ces classes sont posées sur des composants qui ont déjà leurs propres
   transitions de survol (`.service-card`, les cartes du catalogue). Un
   utilitaire qui déclare `transition` écrase celle du composant — la carte
   entrait joliment, puis son survol claquait sans transition. Une animation ne
   touche pas à la propriété `transition` : les deux coexistent. Elle est en
   prime jouée par le compositeur, donc insensible à un fil principal occupé.

   La course est passée de 30 px à 18 px. Au-delà, le bloc semble tomber dans la
   page au lieu de s'y poser, et l'on voit l'effet avant de voir le texte.

   `--reveal-delay` est posé par le script sur CHAQUE élément (jamais sur le
   parent : une variable héritée forcerait un recalcul de style pour toute la
   descendance à chaque image). Il vaut 0 par défaut, donc un bloc révélé sans
   script se comporte correctement.
   ========================================================================== */
.fade-in-section,
.scroll-reveal {
    --reveal-delay: 0ms;
    --reveal-from: translateY(18px);
    opacity: 0;
}

/* Position d'attente. Décrite seulement AVANT la révélation : une fois le bloc
   entré, plus aucune règle de cet utilitaire ne déclare `transform`, sans quoi
   elle disputerait la propriété au survol du composant. */
.fade-in-section:not(.visible),
.scroll-reveal:not(.visible) {
    transform: var(--reveal-from);
    /* `will-change` n'est posé que pendant l'attente. Laissé en permanence, il
       maintient une couche de composition par bloc révélable pour toute la
       durée de vie de la page — sur les pages du catalogue, des dizaines de
       couches qui ne bougent plus depuis longtemps. */
    will-change: opacity, transform;
}

.fade-in-section.visible,
.scroll-reveal.visible {
    animation: revelation var(--dur-reveal) var(--ease-out) var(--reveal-delay) both;
}

@keyframes revelation {
    from {
        opacity: 0;
        transform: var(--reveal-from);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

/* Une animation en `both` conserve ses valeurs finales, et celles-ci l'emportent
   sur toute déclaration ordinaire : le `transform: none` de la dernière image
   aurait neutralisé DÉFINITIVEMENT le soulèvement au survol de la carte. Le
   script retire donc l'animation dès qu'elle est finie ; ne reste que
   l'opacité, que personne d'autre ne dispute. Si le script échoue, le `both`
   laisse malgré tout le bloc visible — jamais de contenu invisible. */
.fade-in-section.reveal-fini,
.scroll-reveal.reveal-fini {
    animation: none;
    opacity: 1;
}

/* Remove both cursor and underline from highlight class */
#dynamic-text::after {
    content: none;
}

/* Language Switcher */
.lang-switch-container {
    background: rgba(255, 255, 255, 0.15);
    padding: 0.4rem 1rem;
    border-radius: 2rem;
    border: 1px solid rgba(255, 255, 255, 0.2);
    backdrop-filter: blur(5px);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);

    color: rgba(255, 255, 255, 0.7);
    font-size: 0.9rem;
    display: flex;
    /* Ensure inline display for list item */
    align-items: center;
    gap: 0.5rem;
    margin-left: 1rem;
    transition: var(--transition);
}

/* Sélecteur de langue masqué (pages dont le contenu vient de la base).
   `visibility` et non `display` : l'élément garde sa largeur, sinon les liens
   du menu se décalaient à droite en passant de l'accueil aux prestations.
   `visibility:hidden` le retire aussi du parcours clavier et des lecteurs
   d'écran — il n'est donc pas seulement invisible, il est absent pour l'usager. */
.lang-switch-masque {
    visibility: hidden;
}

/* En colonne (menu mobile), il n'y a plus de largeur à réserver : un élément
   invisible laisserait un trou au milieu de la pile. Cette règle DOIT rester
   après `.lang-switch-container { display: flex }` — une media query n'ajoute
   aucune spécificité, seul l'ordre du fichier départage deux sélecteurs de
   même poids. */
@media (max-width: 900px) {
    .lang-switch-masque {
        display: none;
    }
}

.lang-switch-container:hover {
    background: rgba(255, 255, 255, 0.25);
    transform: translateY(-2px);
}

.lang-btn {
    cursor: pointer;
    font-weight: 500;
    transition: var(--transition);
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

/* Le drapeau se dimensionne en `em` : il suit la taille du texte au lieu de
   grandir tout seul si la barre change d'échelle. Le liseré remplace la
   bordure que la bande blanche du drapeau français perdrait sur un fond
   clair — sans lui, le drapeau se lirait comme deux bandes séparées. */
.lang-drapeau {
    width: 1.15em;
    height: 0.77em;
    flex: none;
    border-radius: 2px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);
}

.lang-btn:hover {
    color: white;
}

.lang-btn.active {
    color: var(--secondary-color);
    font-weight: 700;
    border-bottom: 2px solid var(--secondary-color);
}

/* Form Validation Styles */
.input-group {
    position: relative;
}

.input-error-message {
    position: absolute;
    top: 100%;
    left: 1rem;
    font-size: 0.8rem;
    color: #ff6b6b;
    background: rgba(255, 107, 107, 0.1);
    padding: 0.2rem 0.8rem;
    border-radius: 1rem;
    opacity: 0;
    transform: translateY(-10px);
    transition: var(--transition);
    pointer-events: none;
    border: 1px solid rgba(255, 107, 107, 0.3);
    z-index: 10;
    margin-top: 0.5rem;
    /* Space between input and error */
    white-space: nowrap;
    /* Prevent wrapping if possible */
}

.input-group.error .input-error-message {
    opacity: 1;
    transform: translateY(0);
}

.input-group.error {
    margin-bottom: 3.5rem;
    /* Increase space to accommodate error message */
}

.input-group.error input,
.input-group.error select,
.input-group.error textarea {
    border-color: #ff6b6b;
    box-shadow: 0 0 0 4px rgba(255, 107, 107, 0.1);
}

.input-group.error i {
    color: #ff6b6b;
}

.input-group.error label {
    color: #ff6b6b;
}


/* -------------------------------------------------------------------------- */
/*                                 PAGE DEVIS                                 */
/* -------------------------------------------------------------------------- */

/* --- Page Devis (Wizard) --- */
.wizard-section {
    min-height: 100vh;
    padding-top: 7rem;
    padding-bottom: 4rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

.wizard-container {
    width: 100%;
    max-width: 900px;
    margin: 0 auto;
}

/* Barre de progression */
.progress-container {
    margin-bottom: 2rem;
    padding: 0 1rem;
}

.progress-bar-bg {
    background: rgba(255, 255, 255, 0.1);
    height: 6px;
    border-radius: 10px;
    overflow: hidden;
}

.progress-bar-fill {
    height: 100%;
    background: var(--secondary-color);
    width: 0%;
    transition: width 0.4s ease;
    box-shadow: 0 0 10px var(--secondary-color);
}

.step-indicator {
    display: flex;
    justify-content: space-between;
    margin-top: 0.5rem;
    color: rgba(255, 255, 255, 0.6);
    font-size: 0.85rem;
    font-weight: 500;
}

/* Cartes de sélection - Horizontal Layout */
.options-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
    /* Slightly wider min-width */
    gap: 1.5rem;
    margin-top: 2rem;
}

.option-card {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 1rem;
    padding: 1.2rem;
    cursor: pointer;
    transition: all 0.3s ease;
    position: relative;
    /* Horizontal Layout: Icon Left | Content Right */
    display: grid;
    grid-template-columns: 60px 1fr;
    grid-template-rows: auto auto;
    column-gap: 1rem;
    row-gap: 0.3rem;
    align-items: center;
    text-align: left;
}

/* ── Ces cartes sont maintenant des <button> ───────────────────────────────
   Elles étaient des `<div onclick>` : pas de focus clavier, aucune réaction à
   `Entrée`, et rien d'annoncé par un lecteur d'écran (piège n° 15). Un bouton
   apporte tout cela gratuitement — mais il arrive avec ses propres valeurs par
   défaut, qu'il faut neutraliser : la police ne s'hérite pas, le texte est
   centré, et Safari impose son propre fond. */
.option-card {
    font-family: inherit;
    font-size: inherit;
    text-align: left;
    width: 100%;
    -webkit-appearance: none;
    appearance: none;
    color: inherit;
}

.option-card:hover {
    background: rgba(255, 255, 255, 0.1);
    transform: translateY(-3px);
}

/* Le contour de focus n'apparaît qu'au clavier : à la souris, la carte reste
   sélectionnée sans être cerclée. Il est posé en `box-shadow` plutôt qu'en
   `outline` pour épouser le rayon de bordure de la carte. */
.option-card:focus-visible {
    outline: none;
    border-color: var(--secondary-color);
    box-shadow: 0 0 0 3px rgba(0, 180, 219, 0.35);
}

.option-card.selected {
    border-color: var(--secondary-color);
    background: rgba(0, 180, 219, 0.1);
    box-shadow: 0 0 20px rgba(0, 180, 219, 0.2);
}

.option-card i {
    grid-row: 1 / -1;
    /* Icon spans both rows */
    grid-column: 1;
    font-size: 2.2rem;
    color: var(--secondary-color);
    margin: 0;
    justify-self: center;
    align-self: center;
}

.option-card h3,
.option-card .opt-titre {
    grid-row: 1;
    grid-column: 2;
    /* Poppins et la graisse venaient du sélecteur global `h1, h2, h3, h4` :
       un <span> n'en hérite pas. Les déclarer ici, c'est ce qui permet au
       libellé de rester identique après le passage du titre en span. */
    font-family: 'Poppins', sans-serif;
    font-weight: 700;
    line-height: 1.2;
    font-size: 1.05rem;
    margin: 0;
    color: #fff;
    align-self: end;
    text-align: left;
    /* Explicitly left aligned */
    justify-self: start;
    /* Grid alignment start */
}

.option-card p,
.option-card .opt-desc {
    grid-row: 2;
    grid-column: 2;
    font-size: 0.85rem;
    color: #cbd5e1;
    margin: 0;
    line-height: 1.4;
    align-self: start;
}

/* Toggles pour l'étape fonctionnalités */
.feature-option {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: rgba(255, 255, 255, 0.05);
    padding: 1rem 1.5rem;
    border-radius: 0.8rem;
    margin-bottom: 1rem;
    cursor: pointer;
    border: 1px solid rgba(255, 255, 255, 0.1);
    transition: all 0.2s;
}

.feature-option.selected {
    border-color: var(--secondary-color);
    background: rgba(0, 180, 219, 0.1);
}

.feature-info h4 {
    font-size: 1rem;
    margin-bottom: 0.2rem;
}

.feature-info p {
    font-size: 0.85rem;
    color: #cbd5e1;
    margin: 0;
}

.check-circle {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 2px solid rgba(255, 255, 255, 0.3);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s;
}

.feature-option.selected .check-circle {
    background: var(--secondary-color);
    border-color: var(--secondary-color);
}

/* Navigation Buttons */
.wizard-nav {
    display: flex;
    justify-content: space-between;
    margin-top: 3rem;
    padding-top: 1.5rem;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.step-content {
    display: none;
    animation: fadeIn 0.5s ease;
}

.step-content.active {
    display: block;
}

@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(10px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Formulaire final */
.final-form input {
    width: 100%;
    background: rgba(0, 0, 0, 0.2);
    border: 1px solid rgba(255, 255, 255, 0.1);
    padding: 1rem;
    border-radius: 0.5rem;
    color: white;
    margin-bottom: 1rem;
}

/* Sliders */
.range-selector {
    margin: 2rem 0;
}

.range-labels {
    display: flex;
    justify-content: space-between;
    margin-top: 0.5rem;
    font-size: 0.8rem;
    color: #94a3b8;
}

input[type="range"] {
    width: 100%;
    height: 6px;
    background: rgba(255, 255, 255, 0.2);
    border-radius: 5px;
    outline: none;
    -webkit-appearance: none;
    appearance: none;
}

input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 20px;
    height: 20px;
    background: var(--secondary-color);
    border-radius: 50%;
    cursor: pointer;
    box-shadow: 0 0 10px rgba(0, 180, 219, 0.5);
}

/* --- Custom Alert Modal --- */
.custom-modal {
    display: none;
    position: fixed;
    z-index: 1000;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.6);
    backdrop-filter: blur(5px);
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.3s ease;
}

.custom-modal.show {
    display: flex;
    opacity: 1;
}

.custom-modal .modal-content {
    background: rgba(20, 30, 48, 0.9);
    border: 1px solid var(--secondary-color);
    box-shadow: 0 0 20px rgba(0, 180, 219, 0.3);
    padding: 2rem;
    border-radius: 1rem;
    text-align: center;
    max-width: 400px;
    width: 90%;
    transform: scale(0.8);
    transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.custom-modal.show .modal-content {
    transform: scale(1);
}

.custom-modal .modal-icon {
    font-size: 3rem;
    color: var(--secondary-color);
    margin-bottom: 1rem;
}

.custom-modal h3 {
    margin-bottom: 0.5rem;
    font-size: 1.5rem;
    color: white;
}

.custom-modal p {
    color: #cbd5e1;
    margin-bottom: 2rem;
}

.custom-modal button {
    width: 100%;
}

/* --- Devis Dashboard (Final Step) --- */
.dashboard-result {
    width: 100%;
}

.dashboard-grid {
    display: grid;
    grid-template-columns: 1fr 1.5fr;
    gap: 2rem;
    margin-bottom: 2rem;
}

@media (max-width: 768px) {
    .dashboard-grid {
        grid-template-columns: 1fr;
    }
}

.dashboard-card {
    background: rgba(255, 255, 255, 0.05);
    border-radius: 1rem;
    padding: 1.5rem;
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.dashboard-card h4 {
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    padding-bottom: 0.8rem;
    margin-bottom: 1rem;
    color: var(--secondary-color);
    font-size: 1.1rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Summary List */
.summary-list {
    list-style: none;
    padding: 0;
}

.summary-list li {
    margin-bottom: 0.8rem;
    font-size: 0.95rem;
    color: #cbd5e1;
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    /* Ensure top alignment for multi-line */
}

.summary-list li strong {
    color: white;
    flex-shrink: 0;
    /* Prevent label from shrinking */
    margin-right: 1rem;
}

.summary-list li span {
    text-align: right;
    max-width: 70%;
    word-wrap: break-word;
    line-height: 1.4;
}

/* Analysis Content */
.analysis-content p {
    font-size: 0.95rem;
    line-height: 1.6;
    color: #cbd5e1;
    margin-bottom: 1rem;
}

.strategy-box {
    background: rgba(0, 180, 219, 0.1);
    border-left: 4px solid var(--secondary-color);
    padding: 1rem;
    border-radius: 0.5rem;
    margin: 1.5rem 0;
    display: flex;
    gap: 1rem;
    align-items: flex-start;
}

.strategy-box i {
    font-size: 1.5rem;
    color: var(--secondary-color);
    margin-top: 0.2rem;
}

.strategy-box p {
    margin: 0;
    color: white;
    font-weight: 500;
}

.contact-section-wizard {
    background: rgba(255, 255, 255, 0.02);
    padding: 1.5rem;
    border-radius: 1rem;
    margin-top: 2rem;
}

.final-form {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.final-form input {
    background: rgba(255, 255, 255, 0.05);
    /* Visible background */
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 0.5rem;
    padding: 0.8rem 1rem;
    color: white;
    font-size: 0.95rem;
    transition: all 0.3s ease;
}

.final-form input:focus {
    background: rgba(255, 255, 255, 0.1);
    border-color: var(--secondary-color);
    outline: none;
    box-shadow: 0 0 0 2px rgba(0, 180, 219, 0.2);
}

.final-form input::placeholder {
    color: rgba(255, 255, 255, 0.4);
}

/* Les etiquettes remplacent les placeholders de ce formulaire. `gap: 1rem` sur
   .final-form separerait l'etiquette de son champ autant que deux champs entre
   eux : on recolle donc l'etiquette a l'entree qu'elle nomme, et l'on retablit
   l'ecart AU-DESSUS d'elle. Le couple se lit alors comme un bloc. */
.final-form label {
    font-size: 0.85rem;
    font-weight: 500;
    color: rgba(255, 255, 255, 0.75);
    margin-bottom: -0.5rem;
}

.final-form label + input {
    margin-top: 0;
}

.final-form label:not(:first-child) {
    margin-top: 0.35rem;
}

/* ══════════════════════════════════════════════════════════════════════════
   SIMULATEUR — écran BAS
   ──────────────────────────────────────────────────────────────────────────
   Une adaptation qui ne regarde que la LARGEUR laisse de côté le cas le plus
   courant sur ordinateur portable : 1366 × 768. La largeur y est confortable,
   la hauteur ne l'est pas — une question à quatre réponses, sa barre de
   progression et ses boutons dépassaient la fenêtre, et il fallait défiler à
   chaque étape pour retrouver « Continuer ».

   `min-width: 900px` borne la règle par le bas : sous cette largeur la grille
   des options est déjà sur une colonne, et resserrer un affichage mobile n'a
   aucun sens. Aucun contenu n'est retiré, seulement les respirations.

   Placée APRÈS les règles de base qu'elle surcharge : une media query n'ajoute
   aucune spécificité, elle serait sans effet plus haut dans le fichier.
   ══════════════════════════════════════════════════════════════════════════ */
@media (min-width: 900px) and (max-height: 820px) {
    .wizard-section { min-height: 0; padding-top: 6rem; padding-bottom: 2.5rem; }
    .glass-form { padding: 2rem 2.25rem; border-radius: 1.5rem; }
    .glass-form h3,
    .glass-form .step-content > h2 { font-size: 1.5rem; margin-bottom: 1rem; }

    .progress-container { margin-bottom: 1.25rem; }

    .options-grid { gap: 1rem; margin-top: 1.25rem; }
    .option-card { padding: 0.95rem 1.1rem; grid-template-columns: 48px 1fr; column-gap: 0.8rem; }
    .option-card i { font-size: 1.8rem; }
    .option-card h3, .option-card .opt-titre { font-size: 1rem; }
    .option-card p, .option-card .opt-desc { font-size: 0.8rem; }

    .wizard-nav { margin-top: 1.75rem; padding-top: 1rem; }
}

/* --- Advanced Analysis Styles --- */

/* Diagnostic Box */
.diag-text {
    padding: 1rem;
    border-radius: 0.5rem;
    margin-bottom: 1.5rem;
    font-size: 0.9rem;
    line-height: 1.5;
}

.diag-text strong {
    display: block;
    margin-bottom: 0.3rem;
    font-size: 1rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.diag-text.danger {
    background: rgba(220, 38, 38, 0.15);
    border-left: 4px solid #ef4444;
    color: #fca5a5;
}

.diag-text.warning {
    background: rgba(245, 158, 11, 0.15);
    border-left: 4px solid #f59e0b;
    color: #fcd34d;
}

.diag-text.info {
    background: rgba(59, 130, 246, 0.15);
    border-left: 4px solid #3b82f6;
    color: #93c5fd;
}

/* Strategy Section */
.strategy-section {
    margin-bottom: 2rem;
}

/* Roadmap Box */
.roadmap-box {
    margin-top: 2rem;
    background: rgba(255, 255, 255, 0.03);
    padding: 1.5rem;
    border-radius: 0.8rem;
}

.roadmap-box h5 {
    color: var(--secondary-color);
    margin-bottom: 1rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 1.1rem;
}

.roadmap-steps {
    display: flex;
    flex-direction: column;
    gap: 0.8rem;
}

.roadmap-steps .step {
    display: flex;
    align-items: center;
    gap: 1rem;
    font-size: 0.9rem;
    color: #e2e8f0;
}

.roadmap-steps .step span {
    background: var(--secondary-color);
    color: white;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: bold;
    font-size: 0.8rem;
    flex-shrink: 0;
}

/* Le Plus Fenua */
.fenua-touch {
    margin-top: 1.5rem;
    padding-top: 1rem;
    border-top: 1px dashed rgba(255, 255, 255, 0.2);
    color: #a7f3d0;
    display: flex;
    align-items: flex-start;
    gap: 0.8rem;
}

.fenua-touch i {
    font-size: 1.5rem;
    margin-top: 0.1rem;
    flex-shrink: 0;
}

.fenua-touch strong {
    display: block;
    font-size: 1rem;
    color: var(--secondary-color);
}

/* --- Team / Skills Page --- */
.hero-small {
    padding-top: 8rem;
    padding-bottom: 0rem;
    min-height: 30vh;
    display: flex;
    align-items: center;
    justify-content: center;
}

.skills-section {
    padding: 2rem 2rem 5rem 2rem;
}

.skills-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(500px, 100%), 1fr));
    gap: 2rem;
}

@media (max-width: 768px) {
    .skills-grid {
        grid-template-columns: 1fr;
    }
}

.skill-card {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 1.5rem;
    padding: 2.5rem;
    display: flex;
    gap: 2rem;
    align-items: flex-start;
    transition: var(--transition);
}

.skill-card:hover {
    background: rgba(255, 255, 255, 0.1);
    transform: translateY(-5px);
    border-color: var(--secondary-color);
}

.skill-icon {
    width: 60px;
    height: 60px;
    background: rgba(0, 180, 219, 0.1);
    border-radius: 1rem;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2rem;
    color: var(--secondary-color);
    flex-shrink: 0;
}

.skill-content h2 {
    font-size: 1.5rem;
    margin-bottom: 1rem;
    color: white;
}

.skill-content p {
    color: #cbd5e1;
    margin-bottom: 1.5rem;
}

.skill-list {
    list-style: none;
}

.skill-list li {
    margin-bottom: 0.5rem;
    color: #94a3b8;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.skill-list li i {
    color: var(--secondary-color);
}

/* Values Section */
.values-section {
    padding: 4rem 0;
    border-top: 1px solid rgba(255, 255, 255, 0.05);
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
    background: rgba(0, 0, 0, 0.1);
}

.values-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 3rem;
    text-align: center;
}

@media (max-width: 768px) {
    .values-grid {
        grid-template-columns: 1fr;
        gap: 2rem;
    }
}

.value-item h2 {
    font-size: 1.8rem;
    margin-bottom: 1rem;
    color: var(--secondary-color);
    /* Gradient text effect? */
    background: linear-gradient(to right, #00b4db, #a7f3d0);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.value-item p {
    color: #cbd5e1;
}

/* --- BI Expertise Page --- */

/* Hero BI */
.hero-bi {
    min-height: 80vh;
    padding-top: 6rem;
    position: relative;
    overflow: clip;
}

.hero-bi .container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 4rem;
}

.hero-bi::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: radial-gradient(circle at 70% 30%, rgba(0, 180, 219, 0.15), transparent 60%),
        radial-gradient(circle at 10% 80%, rgba(247, 183, 51, 0.05), transparent 50%);
    z-index: -1;
}

.hero-bi-content {
    flex: 1;
    max-width: 600px;
    position: relative;
    z-index: 2;
}

.badge-bi {
    display: inline-block;
    padding: 0.5rem 1rem;
    background: rgba(0, 180, 219, 0.1);
    color: var(--secondary-color);
    border-radius: 2rem;
    font-size: 0.9rem;
    font-weight: 600;
    margin-bottom: 1.5rem;
    border: 1px solid rgba(0, 180, 219, 0.2);
}

.hero-bi h1 {
    font-size: 3.5rem;
    margin-bottom: 1.5rem;
    line-height: 1.1;
}

.text-gradient {
    background: linear-gradient(135deg, #00b4db, #a7f3d0);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.hero-bi p {
    font-size: 1.2rem;
    color: #cbd5e1;
    margin-bottom: 2.5rem;
    line-height: 1.6;
}

.bi-explanation {
    background: rgba(255, 255, 255, 0.05);
    border-left: 4px solid var(--secondary-color);
    padding: 1.5rem;
    margin-bottom: 2rem;
    border-radius: 0 1rem 1rem 0;
    max-width: 90%;
}

.bi-explanation h2 {
    font-size: 1.2rem;
    color: white;
    margin-bottom: 0.5rem;
}

.bi-explanation p {
    font-size: 1rem;
    margin-bottom: 0;
    color: #cbd5e1;
}

/* Data Viz Abstract */
.hero-bi-visual {
    position: relative;
    width: 500px;
    height: 500px;
    flex-shrink: 0;
}

@media (max-width: 1024px) {
    .hero-bi {
        min-height: auto;
        padding-bottom: 4rem;
    }

    .hero-bi .container {
        flex-direction: column;
        justify-content: center;
        text-align: center;
    }

    .hero-bi-content {
        max-width: 100%;
        display: flex;
        flex-direction: column;
        align-items: center;
    }

    .bi-explanation {
        max-width: 100%;
        text-align: left;
    }

    .hero-bi-visual {
        width: 100%;
        max-width: 500px;
        height: 400px;
        margin-top: 3rem;
    }
}



.data-viz-container {
    position: relative;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: 1.5rem;
}

.bar {
    width: 40px;
    background: linear-gradient(to top, rgba(0, 180, 219, 0.2), var(--secondary-color));
    border-radius: 10px 10px 0 0;
    box-shadow: 0 0 20px rgba(0, 180, 219, 0.3);
    animation: barGrow 2s ease-out forwards;
}

.bar-1 {
    height: 40%;
    animation-delay: 0.2s;
}

.bar-2 {
    height: 70%;
    animation-delay: 0.4s;
}

.bar-3 {
    height: 55%;
    animation-delay: 0.6s;
}

@keyframes barGrow {
    from {
        height: 0;
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

.floating-card {
    position: absolute;
    background: rgba(255, 255, 255, 0.1);
    backdrop-filter: blur(10px);
    padding: 1rem 1.5rem;
    border-radius: 1rem;
    border: 1px solid rgba(255, 255, 255, 0.2);
    display: flex;
    align-items: center;
    gap: 0.8rem;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
    animation: float 6s ease-in-out infinite;
}

.floating-card i {
    font-size: 1.5rem;
    color: var(--secondary-color);
}

.floating-card span {
    font-weight: 600;
    color: white;
}

.card-1 {
    top: 20%;
    right: 10%;
    animation-delay: 0s;
}

.card-2 {
    bottom: 30%;
    left: 0%;
    animation-delay: 3s;
}

@keyframes float {

    0%,
    100% {
        transform: translateY(0);
    }

    50% {
        transform: translateY(-20px);
    }
}

/* Concept Process */
.section-bi-concept {
    padding: var(--section-padding);
    background: rgba(255, 255, 255, 0.02);
}

.bi-process-grid {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 2rem;
    margin-top: 4rem;
    flex-wrap: wrap;
}

.process-step {
    background: rgba(255, 255, 255, 0.05);
    padding: 2rem;
    border-radius: 1.5rem;
    text-align: center;
    /* `width: 280px` fixe : sous 320 px, la colonne disponible tombe a ~209 px
       et l'etape debordait de 36 px, coupee par `overflow-x: clip`. `min()`
       garde les 280 px partout ou la place existe, et laisse la carte se
       reduire quand elle manque. */
    width: min(280px, 100%);
    border: 1px solid rgba(255, 255, 255, 0.1);
    transition: var(--transition);
}

.process-step:hover {
    transform: translateY(-5px);
    border-color: var(--secondary-color);
    background: rgba(255, 255, 255, 0.08);
}

.step-icon {
    width: 70px;
    height: 70px;
    background: rgba(255, 255, 255, 0.05);
    border-radius: 50%;
    margin: 0 auto 1.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2rem;
    color: var(--secondary-color);
}

.step-arrow {
    font-size: 2rem;
    color: rgba(255, 255, 255, 0.3);
}

@media (max-width: 900px) {
    .bi-process-grid {
        flex-direction: column;
    }

    .step-arrow {
        transform: rotate(90deg);
    }
}

/* Use Cases Examples */
.section-bi-examples {
    padding: var(--section-padding);
}

.example-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4rem;
    align-items: center;
    margin-bottom: 6rem;
}

.example-row:last-child {
    margin-bottom: 0;
}

.example-row.reverse .example-text {
    order: 2;
}

@media (max-width: 900px) {

    .example-row,
    .example-row.reverse {
        grid-template-columns: 1fr;
    }

    .example-row.reverse .example-text {
        order: 0;
    }
}

.example-text h3 {
    font-size: 2rem;
    margin-bottom: 1rem;
    color: white;
}

.example-features {
    list-style: none;
    margin-top: 1.5rem;
}

.example-features li {
    display: flex;
    align-items: center;
    gap: 0.8rem;
    margin-bottom: 0.8rem;
    color: #cbd5e1;
}

.example-features i {
    color: var(--secondary-color);
    font-size: 1.2rem;
}

/* Dashboard Mockup Visuals */
.dashboard-mockup {
    background: rgba(15, 23, 42, 0.6);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 1rem;
    padding: 1rem;
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.3);
    width: 100%;
    aspect-ratio: 16/9;
    display: flex;
    flex-direction: column;
}

.mock-header {
    height: 10%;
    background: rgba(255, 255, 255, 0.05);
    border-radius: 0.5rem;
    margin-bottom: 1rem;
    flex-shrink: 0;
}

.mock-grid {
    flex: 1;
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    grid-template-rows: 0.8fr 1.2fr;
    gap: 1rem;
    width: 100%;
}

.mock-widget {
    background: rgba(255, 255, 255, 0.05);
    border-radius: 0.5rem;
    width: 100%;
    height: 100%;
}

.w-full {
    grid-column: span 6;
}

.w-half {
    grid-column: span 3;
}

.w-third {
    grid-column: span 2;
}

/* Style 2 modifications if necessary, 
   but generic grid handles order naturally */
.style-2 .mock-grid {
    /* Optional: adjust row ratios if needed for specific mockup */
    grid-template-rows: 0.8fr 1.2fr;
}

/* Directions d'entrée. Les amplitudes ont été réduites de moitié (50 px -> 22,
   0.8 -> 0.96) : une entrée se remarque par son rythme, pas par sa distance, et
   un `scale(0.8)` rend le texte flou pendant toute la montée.
   Rien n'entre jamais depuis `scale(0)` — aucun objet n'apparaît de rien. */
.slide-bottom { --reveal-from: translateY(22px); }
.slide-left   { --reveal-from: translateX(-22px); }
.slide-right  { --reveal-from: translateX(22px); }
.scale-up     { --reveal-from: scale(0.96); }

/* Sur ecran etroit, les entrees LATERALES deviennent verticales.
   Deux raisons, et la premiere est un vrai defaut : un bloc en attente decale
   de 22 px vers la droite elargit la page d'autant tant qu'il n'est pas revele.
   Sur strategie.php a 320 px, cela suffisait a faire deborder toute la page
   (329 px au lieu de 307). Un decalage decoratif ne doit jamais deplacer la
   mise en page.
   La seconde : sur une colonne unique, un mouvement horizontal n'evoque plus
   rien — il n'y a pas de « cote » d'ou venir. La montee, si. */
@media (max-width: 600px) {
    .slide-left,
    .slide-right { --reveal-from: translateY(22px); }
}

/* Tooltip Styles for Devis Step 6 */
.feature-info h4 {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.tooltip-wrapper {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.tooltip-icon {
    font-size: 1.1rem;
    color: rgba(255, 255, 255, 0.5);
    cursor: help;
    transition: var(--transition);
}

.tooltip-wrapper:hover .tooltip-icon {
    color: var(--secondary-color);
}

.tooltip-text {
    visibility: hidden;
    width: 220px;
    background-color: rgba(15, 23, 42, 0.95);
    color: #f1f5f9;
    text-align: center;
    border-radius: 0.5rem;
    padding: 0.8rem;
    position: absolute;
    z-index: 100;
    bottom: 135%;
    left: 50%;
    transform: translateX(-50%) translateY(10px);
    opacity: 0;
    transition: opacity 0.3s ease, transform 0.3s ease;
    font-size: 0.85rem;
    font-weight: 400;
    line-height: 1.4;
    box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.5);
    border: 1px solid rgba(255, 255, 255, 0.1);
    backdrop-filter: blur(5px);
    pointer-events: none;
}

.tooltip-text::after {
    content: "";
    position: absolute;
    top: 100%;
    left: 50%;
    margin-left: -6px;
    border-width: 6px;
    border-style: solid;
    border-color: rgba(15, 23, 42, 0.95) transparent transparent transparent;
}

.tooltip-wrapper:hover .tooltip-text {
    visibility: visible;
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* Small Mobile Devices */
@media (max-width: 480px) {
    .container {
        padding: 0 1rem;
    }

    .section-title h2 {
        font-size: 2rem;
    }

    .services-grid,
    .options-grid {
        grid-template-columns: 1fr;
    }

    .service-card {
        padding: 1.5rem;
    }

    /* `.skill-card` avait été oublié ici, alors que ses voisines y figuraient.
       Conséquence : à 360 px, ses 172 px d'habillage fixe (padding 80 + gap 32 +
       icône 60) sur 281 px disponibles ne laissaient que 109 px au texte. Le
       contenu ne pouvant plus se comprimer, la carte débordait de 60 px — et
       comme `body` porte `overflow-x: clip`, ces 60 px étaient coupés sans
       qu'aucun défilement permette d'y accéder.

       L'icône passe au-dessus du texte plutôt qu'à côté : c'est elle qui coûtait
       le plus cher (60 px + 32 px de gouttière), et elle ne porte aucune
       information — elle décore un titre qui, lui, doit rester lisible. */
    .skill-card {
        flex-direction: column;
        padding: 1.5rem;
        gap: 1rem;
    }

    .portfolio-showcase {
        padding: 1.5rem;
    }

    .contact-info h1 {
        font-size: 2rem;
    }

    .hero-text h1 {
        font-size: 2rem;
    }

    .wizard-section {
        padding-top: 6rem;
    }

    .option-card {
        grid-template-columns: 50px 1fr;
        padding: 1rem;
    }
}

/* Custom Checkbox Styles */
.input-group.checkbox-group {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    gap: 0.8rem;
    margin-top: 1rem;
    margin-bottom: 0;
    padding-left: 0.5rem;
}

/* Checkbox Container/Input */
.checkbox-group input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    width: 1.4rem;
    height: 1.4rem;
    background: rgba(255, 255, 255, 0.05);
    border: 2px solid rgba(255, 255, 255, 0.3);
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    margin-top: 0.1rem;
    padding: 0;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    display: grid;
    place-content: center;
    flex-shrink: 0;
}

/* Checked State Background */
.checkbox-group input[type="checkbox"]:checked {
    background: var(--secondary-color);
    border-color: var(--secondary-color);
    box-shadow: 0 0 15px rgba(0, 180, 219, 0.5);
    transform: scale(1.05);
}

/* Checkmark Icon Animation */
.checkbox-group input[type="checkbox"]::before {
    content: "";
    width: 0.8em;
    height: 0.8em;
    transform: scale(0) rotate(-45deg);
    transition: 200ms transform cubic-bezier(0.4, 0, 0.2, 1);
    box-shadow: inset 1em 1em white;
    transform-origin: center;
    clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
    background-color: white;
    /* Ensure visibility */
}

/* Animate Checkmark */
.checkbox-group input[type="checkbox"]:checked::before {
    transform: scale(1) rotate(0deg);
}

/* Hover Effect */
.checkbox-group input[type="checkbox"]:hover {
    border-color: var(--secondary-color);
    background: rgba(255, 255, 255, 0.1);
}

.checkbox-group input[type="checkbox"]:checked:hover {
    background: var(--secondary-color);
    border-color: var(--secondary-color);
}

/* Focus State */
.checkbox-group input[type="checkbox"]:focus {
    box-shadow: 0 0 0 4px rgba(0, 180, 219, 0.2);
    border-color: var(--secondary-color);
}

/* Prevent label from floating or getting background on focus */
.checkbox-group input:focus+label,
.checkbox-group.focused label {
    top: auto;
    left: auto;
    font-size: 0.95rem;
    /* Match base font size */
    color: #cbd5e1;
    background: transparent;
    padding: 0;
    transform: none;
    box-shadow: none;
    font-weight: normal;
}

/* Label Styling Override */
.checkbox-group label {
    position: static;
    transform: none;
    pointer-events: auto;
    cursor: pointer;
    font-size: 0.9rem;
    line-height: 1.5;
    color: #cbd5e1;
    user-select: none;
    flex: 1;
}

/* Remove default input icon from this specific group if needed */
.checkbox-group i {
    display: none;
}

/* Error Message Animation */
@keyframes errorSlideIn {
    0% {
        opacity: 0;
        transform: translateY(-10px) scale(0.9);
    }

    70% {
        transform: translateY(2px) scale(1.02);
    }

    100% {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

/* Error Message Styling */
.input-error-message {
    color: #ff8e8e;
    /* Softer pastel red */
    font-size: 0.8rem;
    /* Slightly smaller */
    opacity: 0;
    transition: var(--transition);
    position: absolute;
    bottom: -2.2rem;
    /* Adjusted for smaller size */
    left: 0;
    width: 100%;
    text-align: center;
    pointer-events: none;
    font-weight: 500;
    letter-spacing: 0.02em;

    /* Premium Glass Style */
    background: linear-gradient(135deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.05));
    padding: 0.3rem 0.8rem;
    /* Smaller padding */
    border-radius: 10px;
    /* Slightly smaller radius */
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(255, 107, 107, 0.3);
    /* Subtle redd-ish border */
    box-shadow:
        0 4px 15px rgba(0, 0, 0, 0.2),
        inset 0 0 0 1px rgba(255, 255, 255, 0.1);

    margin: 0 1rem;
    width: calc(100% - 2rem);
    z-index: 10;

    /* Initially hidden */
    visibility: hidden;
}

.input-group.error .input-error-message {
    opacity: 1;
    visibility: visible;
    animation: errorSlideIn 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
}

/* Ensure input group creates a context for absolute positioning */
.input-group {
    position: relative;
    margin-bottom: 2.2rem;
    /* Increase margin to accommodate absolute error message */
}

/* Specific adjustment for checkbox error message */
.input-group.checkbox-group {
    margin-bottom: 2.8rem;
    /* Significantly increased to prevent overhead with submit button */
}

.checkbox-group .input-error-message {
    position: absolute;
    bottom: -2.4rem;
    left: 0;
    right: 0;
    margin-top: 0;
    width: calc(100% - 2rem);
    /* Match generic width calculation */
    margin-left: 1rem;
    /* Match generic margin */

    /* Inherit the new premium styles but reset specific positioning if needed */
    top: auto;
    transform: none;
    /* Let animation handle transform */
}



.checkbox-group.error .input-error-message {
    transform: translateY(0);
}

/* ─── Blog — liste publique ──────────────────────────────────────── */
.blog-hero { padding: 5rem 2rem 3rem; text-align: center; }
.blog-hero h1 { font-size: clamp(2rem, 5vw, 3rem); margin-bottom: 1rem; }
.blog-hero p { color: rgba(255,255,255,.6); font-size: 1.05rem; max-width: 540px; margin: 0 auto; }

.blog-cats { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; padding: 0 2rem 3rem; }
.cat-btn { background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.12); color: rgba(255,255,255,.6); border-radius: 2rem; padding: 7px 18px; font-family: 'Inter', sans-serif; font-size: .82rem; font-weight: 500; text-decoration: none; transition: all .2s; }
.cat-btn:hover { background: rgba(255,255,255,.15); color: #fff; }
.cat-btn.active { background: linear-gradient(135deg,#006994,#00b4db); border-color: transparent; color: #fff; box-shadow: 0 4px 12px rgba(0,180,219,.3); }

.blog-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr)); gap: 24px; padding: 0 2rem 5rem; max-width: 1200px; margin: 0 auto; }

.post-card { background: rgba(255,255,255,.07); border: 1px solid rgba(255,255,255,.1); border-radius: 1.2rem; overflow: hidden; text-decoration: none; color: inherit; display: flex; flex-direction: column; transition: transform .25s, border-color .25s, box-shadow .25s; }
.post-card:hover { transform: translateY(-4px); border-color: rgba(0,180,219,.4); box-shadow: 0 12px 36px rgba(0,0,0,.3); }
.post-card-img { width: 100%; height: 200px; object-fit: cover; background: rgba(255,255,255,.05); display: flex; align-items: center; justify-content: center; color: rgba(255,255,255,.15); font-size: 3rem; }
.post-card-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.post-card-body { padding: 22px; flex: 1; display: flex; flex-direction: column; }
.post-card-cat { font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: #00b4db; margin-bottom: 8px; }
.post-card-title { font-family: 'Poppins', sans-serif; font-size: 1.05rem; font-weight: 700; line-height: 1.35; margin-bottom: 10px; color: #f8fafc; }
.post-card-excerpt { font-size: .85rem; color: rgba(255,255,255,.5); line-height: 1.6; flex: 1; }
.post-card-footer { display: flex; align-items: center; justify-content: space-between; margin-top: 18px; padding-top: 14px; border-top: 1px solid rgba(255,255,255,.08); }
.post-card-date { font-size: .75rem; color: rgba(255,255,255,.3); }
.post-card-link { font-size: .78rem; font-weight: 600; color: #00b4db; display: flex; align-items: center; gap: 4px; }
.blog-empty { text-align: center; padding: 5rem 2rem; color: rgba(255,255,255,.3); }
.blog-empty i { font-size: 3rem; display: block; margin-bottom: 12px; }

/* ─── Article — page individuelle ───────────────────────────────── */
.article-wrap { max-width: 800px; margin: 0 auto; padding: 4rem 2rem 5rem; }

.article-breadcrumb { font-size: .8rem; color: rgba(255,255,255,.35); margin-bottom: 24px; display: flex; align-items: center; gap: 6px; }
.article-breadcrumb a { color: rgba(255,255,255,.35); text-decoration: none; transition: color .2s; }
.article-breadcrumb a:hover { color: #00b4db; }

.article-cat { font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: #00b4db; margin-bottom: 12px; text-decoration: none; display: inline-block; }
.article-title { font-family: 'Poppins', sans-serif; font-size: clamp(1.6rem, 4vw, 2.4rem); font-weight: 800; line-height: 1.2; margin-bottom: 16px; }
.article-meta { font-size: .8rem; color: rgba(255,255,255,.35); margin-bottom: 32px; }
.article-cover { width: 100%; border-radius: 1rem; margin-bottom: 36px; display: block; max-height: 440px; object-fit: cover; }

.article-content { font-size: 1.02rem; line-height: 1.8; color: rgba(255,255,255,.85); }
.article-content h1, .article-content h2, .article-content h3 { font-family: 'Poppins', sans-serif; color: #f8fafc; margin: 2rem 0 1rem; line-height: 1.3; }
.article-content h1 { font-size: 1.8rem; }
.article-content h2 { font-size: 1.4rem; }
.article-content h3 { font-size: 1.15rem; }
.article-content p { margin-bottom: 1.2rem; }
.article-content ul, .article-content ol { padding-left: 1.5rem; margin-bottom: 1.2rem; }
.article-content li { margin-bottom: .4rem; }
.article-content blockquote { border-left: 3px solid #00b4db; padding: .8rem 1.2rem; margin: 1.5rem 0; background: rgba(0,180,219,.08); border-radius: 0 .5rem .5rem 0; color: rgba(255,255,255,.7); font-style: italic; }
.article-content pre { background: rgba(0,0,0,.4); border: 1px solid rgba(255,255,255,.1); border-radius: .6rem; padding: 1rem 1.2rem; overflow-x: auto; margin-bottom: 1.2rem; }
.article-content code { font-family: 'Courier New', monospace; font-size: .88em; background: rgba(255,255,255,.08); padding: 2px 6px; border-radius: 4px; }
.article-content pre code { background: none; padding: 0; }
.article-content a { color: #00b4db; text-decoration: underline; }
.article-content img { max-width: 100%; border-radius: .6rem; margin: 1rem 0; }
.article-content strong { color: #f8fafc; font-weight: 600; }

.article-back { display: inline-flex; align-items: center; gap: 6px; color: rgba(255,255,255,.4); font-size: .85rem; text-decoration: none; margin-top: 36px; transition: color .2s; }
.article-back:hover { color: #00b4db; }

.related { max-width: 800px; margin: 0 auto; padding: 0 2rem 5rem; }
.related-title { font-family: 'Poppins', sans-serif; font-size: 1.1rem; font-weight: 700; margin-bottom: 18px; color: rgba(255,255,255,.6); }
.related-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr)); gap: 16px; }
.related-card { background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.09); border-radius: 1rem; overflow: hidden; text-decoration: none; color: inherit; transition: transform .2s, border-color .2s; }
.related-card:hover { transform: translateY(-3px); border-color: rgba(0,180,219,.3); }
.related-card-img { height: 120px; background: rgba(255,255,255,.05); display: flex; align-items: center; justify-content: center; color: rgba(255,255,255,.15); font-size: 2rem; overflow: hidden; }
.related-card-img img { width: 100%; height: 100%; object-fit: cover; }
.related-card-body { padding: 14px; }
.related-card-title { font-size: .85rem; font-weight: 600; color: #f8fafc; line-height: 1.4; }
.related-card-date { font-size: .72rem; color: rgba(255,255,255,.3); margin-top: 6px; }
/* ── Pages d'erreur (erreur.php, error_db.php) ────────────────────────────
   Styles partagés : ils étaient recopiés dans chaque page d'erreur. */
.error-page {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    min-height: 60vh; text-align: center; padding: 4rem 2rem;
}
/* Panneau translucide : la photo de fond comporte des zones très claires
   (ciel, sable) sur lesquelles un texte blanc à 50 % devient illisible.
   Le panneau garantit le contraste où que la page se retrouve cadrée. */
.error-page > * { position: relative; z-index: 1; }
.error-panel {
    background: rgba(8, 16, 30, .55);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, .1);
    border-radius: 1.5rem;
    padding: 3rem 2.5rem 2.5rem;
    max-width: 620px;
    display: flex; flex-direction: column; align-items: center;
}
.error-code {
    font-family: 'Poppins', sans-serif; font-size: 5rem; font-weight: 800;
    color: rgba(255, 255, 255, .07); line-height: 1; margin-bottom: .5rem;
}
.error-icon { font-size: 3.4rem; color: rgba(255, 255, 255, .22); margin-bottom: 1.4rem; }
.error-title {
    font-family: 'Poppins', sans-serif; font-size: 1.4rem; font-weight: 700; margin-bottom: 1rem;
}
.error-msg {
    color: rgba(255, 255, 255, .5); max-width: 460px; line-height: 1.7; margin-bottom: 2.2rem;
}
.error-actions { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; }
.error-links {
    display: flex; gap: 22px; flex-wrap: wrap; justify-content: center;
    margin-top: 2.6rem; padding-top: 1.6rem; border-top: 1px solid rgba(255, 255, 255, .08);
}
.error-links a {
    color: rgba(255, 255, 255, .42); text-decoration: none; font-size: .88rem; transition: color .2s;
}
.error-links a:hover { color: #00b4db; }


/* ==========================================================================
   MOUVEMENT — module commun
   --------------------------------------------------------------------------
   Chargé sur toutes les pages publiques. Tout ce qui suit s'appuie sur les
   jetons déclarés dans `:root` (--ease-*, --dur-*). Deux règles tiennent le
   reste : on n'anime que `transform` et `opacity`, et rien ne bouge au survol
   sur un écran tactile.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Ouverture de la page d'accueil
   --------------------------------------------------------------------------
   L'accroche entrait d'un bloc, portée par l'observateur de défilement — qui se
   déclenche immédiatement puisque le bloc est déjà à l'écran. Tout arrivait
   donc en même temps, ce qui ne donne aucun ordre de lecture.

   C'est ici une animation CSS et non JavaScript : au chargement, le fil
   principal analyse encore le script, les polices et les images. Une animation
   CSS est jouée par le compositeur et reste fluide pendant ce temps ; une
   animation pilotée par `requestAnimationFrame` perd des images précisément là.

   Cascade de 90 ms : titre, sous-titre, boutons, visuel. Le dernier élément est
   en place vers 950 ms — c'est la seule séquence du site à dépasser 300 ms,
   parce qu'elle accompagne une première impression et n'est dans le chemin
   d'aucune action. Elle ne bloque jamais un clic : les boutons répondent dès
   leur première image.
   -------------------------------------------------------------------------- */
.hero .hero-text,
.hero .hero-image {
    /* On neutralise l'utilitaire générique sur l'accroche : la séquence
       ci-dessous prend le relais, et les deux se cumuleraient. */
    opacity: 1;
    transform: none;
    animation: none;
}

.hero .hero-text > *,
.hero .hero-image > * {
    opacity: 0;
    transform: translateY(16px);
    animation: heroEntree 620ms var(--ease-out) forwards;
}

.hero .hero-text > h1         { animation-delay: 60ms; }
.hero .hero-text > p          { animation-delay: 150ms; }
.hero .hero-text > .hero-btns { animation-delay: 240ms; }
.hero .hero-image > *         { animation-delay: 330ms; }

@keyframes heroEntree {
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* --------------------------------------------------------------------------
   2. Retour au clic
   --------------------------------------------------------------------------
   Un bouton qui ne répond pas à l'enfoncement laisse un doute d'une demi-
   seconde — le temps que la page suivante arrive. L'enfoncement est bref
   (120 ms) et sa course minuscule : il confirme, il ne décore pas.

   `:active` n'est pas conditionné au survol : c'est le seul retour dont
   dispose le tactile, et c'est là qu'il compte le plus.
   -------------------------------------------------------------------------- */
.btn:active,
.contact-btn:active,
.pd-cta:active,
.pp-cta:active,
.ds-btn:active {
    transform: translateY(0) scale(0.97);
    transition-duration: var(--dur-press);
}

/* --------------------------------------------------------------------------
   3. Survol — réservé aux vrais pointeurs
   --------------------------------------------------------------------------
   Sur mobile, un appui déclenche un faux `:hover` qui reste collé jusqu'au
   prochain toucher ailleurs : la carte touchée reste soulevée après la
   navigation. Les déplacements au survol passent donc par cette barrière.
   Les effets de couleur, eux, restent partout — ils ne mentent pas sur l'état.
   -------------------------------------------------------------------------- */
@media (hover: hover) and (pointer: fine) {
    /* La levée était de 10 px, ce qui donne à une grille de cartes le relief
       d'un menu contextuel. 6 px suffisent à désigner la cible. */
    .service-card:hover {
        transform: translateY(-6px);
    }

    /* La flèche d'un lien avance vers l'endroit où il mène. */
    .lien-fleche i,
    .btn i {
        display: inline-block;
        transition: transform var(--dur-hover) var(--ease-out);
    }

    .lien-fleche:hover i,
    .btn:hover i {
        transform: translateX(3px);
    }
}

@media (hover: none) {
    /* Ceinture et bretelles : si un survol déplaçant subsiste ailleurs dans la
       feuille, il est annulé ici plutôt que de figer un élément soulevé. */
    .service-card:hover,
    .info-card:hover,
    .skill-card:hover {
        transform: none;
    }
}

/* --------------------------------------------------------------------------
   4. Focus clavier
   --------------------------------------------------------------------------
   Le contour de focus apparaissait sans transition et disparaissait de même.
   Il n'est rendu visible qu'au clavier (`:focus-visible`), pour ne pas cerner
   un bouton qu'on vient de cliquer à la souris.
   -------------------------------------------------------------------------- */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
    outline: 2px solid var(--secondary-color);
    outline-offset: 3px;
    border-radius: 0.35rem;
}

/* ==========================================================================
   5. Mouvement réduit
   --------------------------------------------------------------------------
   Aucune animation du site n'était conditionnée à cette préférence : un
   visiteur sujet au mal des transports recevait des cartes flottant en boucle,
   des blocs montant de 50 px et un tiroir balayant toute la largeur.

   « Réduit » ne veut pas dire « aucun ». Ce qui aide à comprendre reste :
   fondus, changements de couleur, apparition du menu. Ce qui disparaît, c'est
   le DÉPLACEMENT — translations, mises à l'échelle, et surtout les boucles
   infinies, les plus éprouvantes puisqu'on ne peut pas les attendre.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {

    /* Les boucles infinies s'arrêtent net, sur leur position de repos. */
    .floating-card,
    .bar {
        animation: none !important;
    }

    /* Les barres du graphique doivent rester visibles : leur opacité venait de
       l'animation qu'on vient de couper. */
    .bar {
        opacity: 1;
    }

    /* Les révélations deviennent de simples fondus, sans déplacement et sans
       cascade : attendre 500 ms qu'un bloc arrive est une gêne de plus. */
    .fade-in-section,
    .scroll-reveal,
    .slide-bottom,
    .slide-left,
    .slide-right,
    .scale-up {
        --reveal-from: none;
        --reveal-delay: 0ms;
        transform: none !important;
    }

    /* La révélation se réduit à un fondu court, sans déplacement ni cascade :
       attendre 500 ms qu'un bloc arrive est une gêne de plus. */
    .fade-in-section.visible,
    .scroll-reveal.visible {
        animation-duration: 200ms !important;
        animation-delay: 0ms !important;
    }

    .hero .hero-text > *,
    .hero .hero-image > * {
        animation: heroEntreeReduite 200ms var(--ease-out) forwards;
        animation-delay: 0ms !important;
        transform: none;
    }

    @keyframes heroEntreeReduite {
        to { opacity: 1; }
    }

    /* Le tiroir mobile apparaît en fondu au lieu de balayer l'écran. */
    .nav-links li {
        transform: none !important;
        transition: opacity 200ms var(--ease-out) !important;
        transition-delay: 0ms !important;
    }

    /* Plus aucun déplacement au survol ni à l'enfoncement — la couleur et
       l'ombre continuent de désigner la cible.

       La liste est explicite, et non un `*:hover`. Un sélecteur universel
       aurait aussi neutralisé les `transform` de POSITIONNEMENT : l'étiquette
       de formulaire centrée par `translateY(-50%)`, l'infobulle centrée par
       `translateX(-50%)`. Ces éléments-là ne se seraient pas immobilisés, ils
       auraient sauté de leur place. On ne désigne donc que ce qui bouge
       réellement. */
    .btn-primary:hover,
    .btn:hover i,
    .lien-fleche:hover i,
    .hero-image:hover img,
    .service-card:hover,
    .contact-btn:hover,
    .info-card:hover,
    .lang-switch-container:hover,
    .option-card:hover,
    .skill-card:hover,
    .process-step:hover,
    .post-card:hover,
    .related-card:hover,
    .btn:active,
    .contact-btn:active,
    .pd-cta:active,
    .pp-cta:active,
    .ds-btn:active {
        transform: none !important;
    }

    /* L'infobulle garde son centrage et perd sa montée : c'est exactement la
       distinction que « mouvement réduit » demande. */
    .tooltip-text,
    .tooltip-wrapper:hover .tooltip-text {
        transform: translateX(-50%) !important;
    }
}


/* ==========================================================================
   Impression
   --------------------------------------------------------------------------
   Une page imprimée ne défile pas : les blocs jamais amenés à l'écran n'ont
   jamais été révélés, et sortaient blancs. Même chose pour toute capture de
   page entière — un aperçu de partage, un outil d'audit. On force donc l'état
   final, sans animation.
   ========================================================================== */
@media print {

    .fade-in-section,
    .scroll-reveal {
        opacity: 1 !important;
        transform: none !important;
        animation: none !important;
    }

    .floating-card,
    .bar {
        animation: none !important;
        opacity: 1 !important;
    }

    .hero .hero-text > *,
    .hero .hero-image > * {
        opacity: 1 !important;
        transform: none !important;
        animation: none !important;
    }
}


/* ==========================================================================
   Lien d'evitement
   --------------------------------------------------------------------------
   Masque tant qu'il n'a pas le focus, il apparait des la premiere tabulation.

   Il est retire de l'affichage par un deplacement hors cadre et non par
   `display: none` ni `visibility: hidden` : ces deux-la le retireraient AUSSI
   de l'ordre de tabulation et des lecteurs d'ecran, c'est-a-dire des deux
   publics a qui il est destine. C'est le motif retenu par les guides du W3C,
   pour cette raison precise.
   ========================================================================== */
.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 2000;
    padding: 0.85rem 1.4rem;
    background: var(--primary-color);
    color: #fff;
    font-weight: 600;
    text-decoration: none;
    border-radius: 0 0 0.6rem 0;
    box-shadow: 0 6px 20px rgba(0, 0, 0, .4);
}

.skip-link:focus,
.skip-link:focus-visible {
    left: 0;
}

/* La cible du lien ne doit pas se retrouver sous la barre fixe : sauter au
   contenu pour le decouvrir cache derriere l'en-tete n'aurait aucun interet. */
#contenu {
    scroll-margin-top: 6rem;
}


/* ==========================================================================
   Tres petits ecrans (<= 360 px)
   --------------------------------------------------------------------------
   Trois pages debordaient a 320 px — iPhone SE de 1re generation, ecran de
   couverture d'un Galaxy Fold. Comme partout ailleurs sur le site,
   `overflow-x: clip` empeche d'aller voir ce qui depasse : le contenu etait
   perdu, pas seulement decale.
   ========================================================================== */
@media (max-width: 360px) {

    /* contact.php — la grille refusait de descendre sous la largeur minimale
       de ses enfants (`min-width: auto`, valeur par defaut d'un element de
       grille), et imposait 297 px la ou 288 etaient disponibles. `min-width: 0`
       est le remede canonique : il autorise l'enfant a se comprimer. */
    .contact-wrapper > * {
        min-width: 0;
    }
}


/* --------------------------------------------------------------------------
   Petits ecrans : titres d'expertise et maquettes decoratives
   --------------------------------------------------------------------------
   `.hero-bi h1` reste a 3,5 rem quelle que soit la largeur. Sous 400 px,
   « L'Experience Avant Tout » mesurait alors 356 px de large dans un ecran de
   320 : le titre debordait des DEUX cotes, etant centre.

   Les conteneurs de visualisation portent des elements decoratifs a dimensions
   figees (un cercle de radar de 340 px, une maquette de telephone dont la
   rotation 3D donne une emprise de 373 px). Ils sont illustratifs : mieux vaut
   les rogner que laisser la page deborder. `overflow: hidden` s'en charge, sans
   toucher aux `transform` que se partagent deja animations et survols.
   -------------------------------------------------------------------------- */
@media (max-width: 600px) {
    .hero-bi h1 { font-size: 2.4rem; }
}

@media (max-width: 400px) {
    .hero-bi h1 { font-size: 1.9rem; }
}

.strat-viz-container,
.design-viz-container {
    overflow: hidden;
}
