/* ==========================================================================
   COFINEX — Feuille de style
   Univers  : « note de cession » — éditorial institutionnel
   Palette  : diaporama (Flat UI) + couleurs du logo (noir / orange → rouge)
   Typo     : Newsreader (titres) + Public Sans (texte)
   ========================================================================== */

/* ---------- Polices auto-hébergées ----------
   Newsreader + Public Sans (Google Fonts, licence OFL), servies depuis
   `assets/fonts/`. Elles sont déclarées ici, et non dans un fichier séparé :
   le chargement d'une seconde feuille bloquante coûtait un aller-retour de
   réseau avant le premier pixel. Aucune requête vers un domaine tiers.

   Les fichiers ont été allégés avec fontTools, sans changer le dessin :
   - sous-ensemble limité à U+0020-007E, U+00A0-00FF (Latin-1 complet, donc tout
     le français), U+0152-0153 (OE), la ponctuation typographique U+2000-206F,
     U+20AC (euro), U+2122 et U+2212 ;
   - axe `wght` ramené aux graisses réellement utilisées (Newsreader 400-500,
     Public Sans 400-700) et axe `opsz` de Newsreader borné à 16-72 px, la plus
     petite taille d'affichage étant 17 px ;
   - l'italique de Newsreader, employé une seule fois — la ligne des métiers du
     hero, en 500 — n'a pas gardé son axe `wght` : figé à 500, il passe de
     85,2 à 56,8 Ko sans différence mesurable (0,065 % des pixels de la ligne,
     écart maximal 10/255, invisible).
   520 Ko → 173 Ko au total ; le rendu mesuré est identique (écart de mise en
   page ≤ 0,04 px par bloc, écart pixel moyen 0,03/255).

   Régénérer (si un texte introduit un caractère hors de ces plages) :
     python -m fontTools.subset <fichier>.woff2 --unicodes=<plages> \
       --layout-features='*' --flavor=woff2 --output-file=<fichier>.woff2
   puis limiter les axes avec fontTools.varLib.instancer.
   Les fichiers complets se retéléchargent depuis Google Fonts (API css2) si un
   texte introduit un caractère hors de ces plages. */
@font-face {
    font-family: 'Newsreader';
    font-style: italic;
    font-weight: 500;
    font-display: swap;
    src: url("assets/fonts/cY9CfjOCX1hbuyalUrK439vCgIhCFpY.woff2") format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Newsreader';
    font-style: italic;
    font-weight: 500;
    font-display: swap;
    src: url("assets/fonts/cY9CfjOCX1hbuyalUrK439vCjohC.woff2") format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Newsreader';
    font-style: normal;
    font-weight: 400 500;
    font-display: swap;
    src: url("assets/fonts/cY9AfjOCX1hbuyalUrK439DyjJBG.woff2") format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Newsreader';
    font-style: normal;
    font-weight: 400 500;
    font-display: swap;
    src: url("assets/fonts/cY9AfjOCX1hbuyalUrK4397yjA.woff2") format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Public Sans';
    font-style: italic;
    font-weight: 400;
    font-display: swap;
    src: url("assets/fonts/ijwAs572Xtc6ZYQws9YVwnNDZpDyNjGolS673tpRgDckd1sdfg.woff2") format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Public Sans';
    font-style: italic;
    font-weight: 400;
    font-display: swap;
    src: url("assets/fonts/ijwAs572Xtc6ZYQws9YVwnNDZpDyNjGolS673tpRgDcqd1s.woff2") format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Public Sans';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url("assets/fonts/ijwRs572Xtc6ZYQws9YVwnNIfJ7Cww.woff2") format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Public Sans';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url("assets/fonts/ijwRs572Xtc6ZYQws9YVwnNGfJ4.woff2") format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
    /* --- Palette (diaporama) --- */
    --ink: #1C2833;
    --navy: #2C3E50;
    --blue: #3498DB;
    --blue-deep: #2471A3;
    --paper: #ECF0F1;
    --paper-soft: #F7F9FA;
    --white: #FFFFFF;

    /* --- Couleurs du logo (carré noir + dégradé orange → rouge) --- */
    --brand-black: #111111;
    --brand-orange: #F5821F;
    --brand-red: #C0111A;
    --brand-gradient: linear-gradient(90deg, #F5821F 0%, #E5361B 55%, #C0111A 100%);
    --orange: var(--brand-orange);
    --orange-hover: #FF9130;

    /* --- Dérivés --- */
    --text: var(--ink);
    --text-body: #4A5A6A;
    --text-muted: #5A6B7B;
    --on-dark: #ECF0F1;
    --on-dark-muted: rgba(236, 240, 241, 0.72);
    --on-dark-faint: rgba(236, 240, 241, 0.62);

    --line: rgba(44, 62, 80, 0.14);
    --line-strong: rgba(44, 62, 80, 0.26);
    --line-on-dark: rgba(236, 240, 241, 0.16);

    --font-display: "Newsreader", "Iowan Old Style", Georgia, serif;
    --font-body: "Public Sans", "Segoe UI", system-ui, sans-serif;

    /* Un seul fichier pour le symbole et le mot. Sa première partie reprend à
       l'identique le symbole de `_fichiers-de-travail/logo.webp` ; sa dernière
       ligne est la forme COFINEX, masquée séparément pour conserver les variantes
       du lockup. WebP sans perte (alpha conservée) : 71 Ko au lieu de 119 Ko en
       PNG, même dessin, mêmes pixels opaques. */
    --mark-url: url("assets/logo.webp");
    /* Le même dessin, pré-réduit pour les petites tailles. Le lockup de l'en-tête
       et du pied de page est rendu à 80 px (22 px en bas de page) : réduire le
       master de 1 024 px treize fois au vol crénelait le reflet du symbole et le
       mot COFINEX. À 3× la taille d'affichage, le navigateur n'a plus qu'à
       diviser par 1,5 — même forme, contours nets. */
    --mark-url-compact: url("assets/logo-compact.webp");
    --mark-size: 100% auto;
    --mark-pos: left top;
    --mark-ratio: 669 / 644;

    /* Le tempo de la marque animée : un tour complet. La pièce du hero, les
       sceaux des pages de service et, sur mobile, le symbole de l'en-tête sont
       réglés dessus — le reflet et la lueur s'y accordent aussi. */
    --logo-cycle: 5s;

    --maxw: 1200px;
    /* Largeur de la colonne de contenu (grille 1200 − 2 × 48 px de gouttière).
       Elle sert aux filets de section, qui s'alignent sur le texte au lieu de
       courir sur toute la largeur de la fenêtre. Réduite à ≤ 640 px, où la
       gouttière passe à 22 px. */
    --rule-w: min(calc(100% - 96px), calc(var(--maxw) - 96px));
    --radius: 16px;
    --radius-sm: 12px;
    --radius-pill: 999px;
    --ease: cubic-bezier(0.16, 1, 0.3, 1);

    /* Lavage de papier : le bleu du diaporama au nord-ouest, la chaleur du logo
       au nord-est, sur un blanc qui reprend le dessus. La page reste du papier,
       mais elle a une lumière — c'est ce qui remplace l'aplat plat. */
    --wash-paper:
        radial-gradient(70% 68% at 92% 4%, rgba(245, 130, 31, 0.10), rgba(245, 130, 31, 0) 68%),
        radial-gradient(96% 92% at 2% 0%, rgba(52, 152, 219, 0.15), rgba(52, 152, 219, 0) 60%),
        linear-gradient(180deg, #F3F8FC 0%, var(--white) 76%);

    /* Élévation — une seule source de profondeur par surface : soit un filet,
       soit une ombre, jamais les deux. L'ombre porte toujours un décalage
       vertical : un halo à décalage nul est un aplat décoratif, pas une ombre. */
    --shadow-1: 0 1px 2px rgba(28, 40, 51, 0.04), 0 14px 30px -22px rgba(28, 40, 51, 0.35);
    --shadow-2: 0 2px 4px rgba(28, 40, 51, 0.06), 0 30px 56px -30px rgba(28, 40, 51, 0.45);
    --shadow-orange: 0 12px 26px -16px rgba(245, 130, 31, 0.6);

    /* Rembourrage vertical d'une section. Il sert aussi à recaler les ancres :
       voir `section[id]` plus bas. */
    --section-pad: 128px;
}

/* ---------- Base ---------- */
*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    scroll-behavior: smooth;
    /* L'en-tête est collant : les ancres doivent se poser SOUS lui, sinon le
       titre visé disparaît derrière le chrome. On ajoute 24 px de respiration :
       sans elles, une cible sans rembourrage — `.page-block#opportunites` par
       exemple — venait se coller pile au bord bas de l'en-tête.
       `--header-h` est mesuré dans script.js avec la hauteur réelle de l'en-tête
       (elle change avec la police et le palier responsive) ; la valeur de repli
       est celle de l'en-tête desktop, utilisée si le fragment est résolu avant
       que le script ait posé la variable. */
    scroll-padding-top: calc(var(--header-h, 122px) + 24px);
    scrollbar-color: rgba(44, 62, 80, 0.35) var(--paper);
}

body {
    margin: 0;
    background: var(--white);
    color: var(--text-body);
    font-family: var(--font-body);
    font-size: 16px;
    line-height: 1.62;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    -webkit-tap-highlight-color: transparent;
}

body.no-scroll {
    overflow: hidden;
}

img {
    display: block;
    max-width: 100%;
}

a {
    color: inherit;
    text-decoration: none;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.25em;
}

button {
    font: inherit;
    color: inherit;
}

h1,
h2,
h3 {
    font-family: var(--font-display);
    font-weight: 500;
    /* Newsreader est une variable à axe optique : la laisser choisir son dessin
       pour chaque corps donne des grands titres plus fins que leur graisse. */
    font-optical-sizing: auto;
    line-height: 1.1;
    letter-spacing: -0.018em;
    margin: 0 0 20px;
    color: var(--text);
    text-wrap: balance;
}

p {
    margin: 0 0 16px;
    max-width: 68ch;
    text-wrap: pretty;
}

p:last-child {
    margin-bottom: 0;
}

/* Surfaces navigateur thémées */
::selection {
    background: var(--orange);
    color: var(--ink);
}

::-webkit-scrollbar {
    width: 12px;
    height: 12px;
}

::-webkit-scrollbar-track {
    background: var(--paper);
}

::-webkit-scrollbar-thumb {
    background: rgba(44, 62, 80, 0.35);
    border: 3px solid var(--paper);
    border-radius: 999px;
}

::-webkit-scrollbar-thumb:hover {
    background: var(--navy);
}

:focus-visible {
    outline: 2px solid var(--orange);
    outline-offset: 3px;
    border-radius: 3px;
}

.skip-link {
    position: absolute;
    left: 16px;
    top: -60px;
    z-index: 100;
    background: var(--ink);
    color: var(--on-dark);
    padding: 10px 16px;
    border-radius: var(--radius-sm);
    font-size: 14px;
    transition: top 0.2s var(--ease);
}

.skip-link:focus {
    top: 16px;
}

/* ---------- Structure ---------- */
.container {
    width: 100%;
    max-width: var(--maxw);
    margin: 0 auto;
    padding: 0 48px;
}

section {
    padding: var(--section-pad) 0;
}

/* Le filet de séparation était pleine largeur, comme un trait de navigateur.
   Il s'aligne maintenant sur la colonne de texte : la frontière se lit comme
   une règle de document, pas comme un défaut d'affichage — et la grille devient
   lisible d'un seul regard. */
section+section {
    position: relative;
    border-top: 0;
}

section+section::before {
    content: "";
    position: absolute;
    top: 0;
    left: 50%;
    width: var(--rule-w);
    height: 1px;
    background: var(--line);
    transform: translateX(-50%);
}

/* Une section place son titre APRÈS `--section-pad` de rembourrage : son bord
   supérieur se trouve donc 128 px (80 px ≤ 640 px) au-dessus de son titre.
   Ancré tel quel, le titre apparaissait 152 px sous l'en-tête, avec un grand
   vide au-dessus — c'est ce que voyait l'utilisateur en cliquant « Nos
   services ». On remonte donc le point d'arrivée d'exactement ce rembourrage,
   pour que l'ancre révèle le TITRE et non le rembourrage.
   Les cibles sans rembourrage (`#opportunites`, `main#contenu`) ne sont pas
   concernées : elles gardent les 24 px de `scroll-padding-top`. */
section[id] {
    scroll-margin-top: calc(-1 * var(--section-pad));
}

.section-head {
    max-width: 60ch;
    margin-bottom: 56px;
}

.section-head h2 {
    font-size: clamp(1.95rem, 3.4vw, 2.75rem);
    letter-spacing: -0.022em;
    margin-bottom: 14px;
}

.section-head .lede {
    font-size: 1.0625rem;
    line-height: 1.65;
    color: var(--text-muted);
    max-width: 52ch;
}

.lede {
    font-size: 1.125rem;
}

/* Tête de section en deux colonnes : le titre garde la gauche, l'amorce passe à
   droite et se cale sur sa dernière ligne. La grille du document devient
   visible, au lieu d'un bloc empilé à gauche sur toute la largeur. Le titre de
   la section contact est exclu plus bas : il vit déjà dans une colonne de
   0,78 fr, où deux colonnes supplémentaires seraient illisibles. */
@media (min-width: 901px) {
    .container>.section-head {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 0.86fr);
        gap: 24px 56px;
        align-items: end;
        max-width: none;
    }

    .container>.section-head h2 {
        margin-bottom: 0;
    }

    .container>.section-head .lede {
        /* les deux dernières lignes se répondent : le léger retrait compense la
           ligne de base plus haute de la serif */
        margin-bottom: 5px;
    }
}

/* ---------- Mention d'état du site ---------- */
/* Le site est encore en cours de rédaction : la mention est posée dans le flux,
   au-dessus de l'en-tête, donc elle défile avec la page et n'ajoute rien à la
   hauteur collante. Texte courant, pas d'« eyebrow » : elle informe, elle ne
   titraille pas. */
.site-notice {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    margin: 0;
    padding: 9px 22px;
    max-width: none;
    background: var(--paper-soft);
    color: var(--text-muted);
    font-size: 13.5px;
    line-height: 1.45;
    text-align: center;
    text-wrap: pretty;
}

.site-notice svg {
    flex: none;
    width: 16px;
    height: 16px;
    color: var(--blue-deep);
}

.site-notice strong {
    color: var(--ink);
    font-weight: 600;
}

/* ---------- En-tête ---------- */
#site-header {
    position: sticky;
    top: 0;
    z-index: 60;
    background: var(--navy);
    border-bottom: 1px solid var(--blue);
    transition: box-shadow 0.4s var(--ease), top 0.4s var(--ease);
}

/* Liseré de marque : le dégradé du logo, en haut de page */
#site-header::before {
    content: "";
    display: block;
    height: 3px;
    background-image: var(--brand-gradient);
}

/* Dès qu'on quitte le haut de page, l'en-tête se décale de 8 px vers le haut :
   le liseré de marque sort de l'écran et le chrome laisse respirer le contenu.
   On déplace l'accroche (`top` d'un élément collant) au lieu de resserrer le
   rembourrage : le reste du document n'est pas remis en page pendant le
   défilement, et `--header-h` reste la hauteur réelle de l'en-tête. */
#site-header.scrolled {
    top: -8px;
    box-shadow: 0 20px 40px -30px rgba(28, 40, 51, 0.8);
}

/* En-tête navy : le chrome passe en clair, le logo garde ses vraies couleurs
   (le carré noir se lit comme un cachet, comme au pied de page). */
#site-header .logo-name {
    color: var(--on-dark);
}

/* Liens de premier niveau seulement : le menu déroulant reste un panneau clair,
   et le bouton d'appel à l'action garde son fond orange / texte encre. */
#site-header .nav-links>li>a:not(.btn),
#site-header .nav-links .nav-link-btn {
    color: var(--on-dark-muted);
}

#site-header .nav-links>li>a:not(.btn):hover,
#site-header .nav-links .nav-link-btn:hover {
    color: var(--white);
    background: rgba(236, 240, 241, 0.12);
}

.nav {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 32px;
    max-width: var(--maxw);
    margin: 0 auto;
    padding: 10px 48px;
}

/* Lockup : le symbole empilé au-dessus du mot. La colonne est dimensionnée sur
   le mot (« min-content » = la largeur de COFINEX), donc le symbole fait
   exactement la même largeur que lui, à n'importe quelle taille de police. */
.logo {
    display: inline-grid;
    grid-template-columns: min-content;
    gap: 5px;
    flex-shrink: 0;
    line-height: 1;
}

/* Symbole recadré depuis assets/logo.webp — la recette est dans `:root`.
   Le cadre vaut 100 % de la colonne, donc la largeur de COFINEX, et la hauteur
   suit le ratio du dessin sans autre réglage. */
.logo-mark {
    display: block;
    width: 100%;
    aspect-ratio: var(--mark-ratio);
    background-image: var(--mark-url);
    background-repeat: no-repeat;
    background-size: var(--mark-size);
    background-position: var(--mark-pos);
}

.logo-name {
    position: relative;
    font-family: var(--font-body);
    font-weight: 700;
    font-size: 16px;
    letter-spacing: 0.08em;
    line-height: 1;
    color: var(--brand-black);
    /* le tracking s'ajoute après le dernier F : on l'annule pour que le symbole
       s'aligne pile sur les lettres */
    margin-right: -0.08em;
    -webkit-text-fill-color: transparent;
}

.logo-name::before,
.seal-name::before {
    content: "COFINEX";
    position: absolute;
    inset: 0;
    color: inherit;
    background-color: currentColor;
    background-repeat: no-repeat;
    -webkit-mask-image: var(--mark-url);
    -webkit-mask-size: calc(100% - 0.08em) auto;
    -webkit-mask-position: left bottom;
    -webkit-mask-repeat: no-repeat;
    mask-image: var(--mark-url);
    mask-size: calc(100% - 0.08em) auto;
    mask-position: left bottom;
    mask-repeat: no-repeat;
    pointer-events: none;
}

/* Variante pour les fonds sombres : le vrai logo, simplement agrandi */
.logo--on-dark .logo-name {
    color: var(--on-dark);
    font-size: 18px;
}

/* Variante horizontale, pour le pied de page : le symbole passe à gauche du mot
   et se cale sur la hauteur des capitales. Le lockup empilé reste réservé à
   l'en-tête — c'est ce qui évite qu'on croie voir un second en-tête en bas. */
.logo--inline {
    grid-auto-flow: column;
    align-items: center;
    gap: 8px;
}

.logo--inline .logo-mark {
    width: 22px;
}

.logo--on-dark.logo--inline .logo-name {
    font-size: 16px;
}

/* En-tête et pied de page : le lockup puise dans la version compacte. Le sceau
   du hero, lui, reste sur le master — il s'affiche à 455 px. */
#site-header .logo,
footer .logo {
    --mark-url: var(--mark-url-compact);
}

.nav-links {
    display: flex;
    align-items: center;
    gap: 4px;
    list-style: none;
    margin: 0;
    padding: 0;
}

.nav-links>li {
    position: relative;
}

.nav-links a,
.nav-links .nav-link-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: none;
    border: 0;
    cursor: pointer;
    padding: 9px 14px;
    border-radius: var(--radius-pill);
    font-size: 14.5px;
    font-weight: 500;
    color: var(--text-body);
    /* Les libellés de l'en-tête restent sur une ligne : repliés, ils font déborder
       la barre de 48 px dès 1 024 px. */
    white-space: nowrap;
    transition: color 0.2s var(--ease), background-color 0.2s var(--ease);
}

.nav-links a:hover,
.nav-links .nav-link-btn:hover {
    color: var(--ink);
    background: rgba(44, 62, 80, 0.06);
}

.chevron {
    width: 8px;
    height: 8px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(45deg) translate(-1px, -1px);
    transition: transform 0.2s var(--ease);
}

.has-dropdown.open .chevron,
.has-dropdown:hover .chevron {
    transform: rotate(225deg) translate(1px, 1px);
}

.dropdown-menu {
    position: absolute;
    top: calc(100% + 10px);
    left: 0;
    min-width: 300px;
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-2);
    padding: 10px;
    display: grid;
    gap: 2px;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity 0.18s var(--ease), transform 0.18s var(--ease), visibility 0.18s;
}

.has-dropdown:hover .dropdown-menu,
.has-dropdown.open .dropdown-menu {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.dropdown-menu a {
    display: block;
    padding: 11px 14px;
    border-radius: var(--radius-sm);
    font-size: 14px;
    color: var(--text-body);
}

.dropdown-menu a:hover {
    background: var(--paper);
    color: var(--ink);
}

/* Dernière entrée du volet : le renvoi vers la liste complète des domaines,
   détaché des services par un filet. Sur fond clair, il passe en encre et en
   demi-gras pour se lire comme un lien de synthèse, pas comme un sixième service. */
.dropdown-menu .dropdown-tous {
    margin-top: 6px;
    padding-top: 12px;
    border-top: 1px solid var(--line);
    border-radius: 0 0 var(--radius-sm) var(--radius-sm);
    font-weight: 600;
    color: var(--ink);
}

/* ---------- Boutons ---------- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 27px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    font-size: 15px;
    font-weight: 600;
    letter-spacing: 0.005em;
    cursor: pointer;
    transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease),
        color 0.2s var(--ease), box-shadow 0.3s var(--ease), transform 0.22s var(--ease);
}

/* Le bouton principal porte une ombre portée teintée de son propre orange :
   elle est décalée vers le bas, donc elle se lit comme un relief, pas comme
   un halo. Le contour reste sans ombre — un seul niveau par bouton. */
.btn-primary {
    background: var(--orange);
    color: var(--ink);
    box-shadow: var(--shadow-orange);
}

.btn-primary:hover {
    background: var(--orange-hover);
    transform: translateY(-1px);
    box-shadow: 0 16px 30px -16px rgba(245, 130, 31, 0.7);
}

.btn-primary:active {
    transform: translateY(0);
    box-shadow: var(--shadow-orange);
}

.btn-outline {
    background: transparent;
    border-color: var(--line-strong);
    color: var(--ink);
}

.btn-outline:hover {
    border-color: var(--ink);
    background: rgba(255, 255, 255, 0.72);
    transform: translateY(-1px);
    box-shadow: var(--shadow-1);
}

.btn-outline:active {
    transform: translateY(0);
    box-shadow: none;
}

.nav-cta {
    padding: 10px 20px;
    font-size: 14px;
}

/* Sur le navy de l'en-tête, l'ombre teintée du bouton principal se lit comme un
   halo orange : le bouton y reçoit une ombre neutre, qui le pose sans le faire
   briller. Sur le papier du corps, l'ombre teintée reste (décalée vers le bas,
   donc un relief, pas un halo). */
#site-header .nav-cta {
    box-shadow: 0 10px 22px -14px rgba(28, 40, 51, 0.85);
}

#site-header .nav-cta:hover {
    box-shadow: 0 14px 26px -14px rgba(28, 40, 51, 0.9);
}

.nav-cta-mobile {
    display: none;
}

.nav-toggle {
    display: none;
    width: 44px;
    height: 44px;
    border: 1px solid rgba(236, 240, 241, 0.3);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--on-dark);
    align-items: center;
    justify-content: center;
    cursor: pointer;
    position: relative;
    z-index: 3;
}

.nav-toggle svg {
    width: 20px;
    height: 20px;
}

/* ---------- Hero ----------
   Le bleu vit dans l'en-tête : le hero s'ouvre sur le lavage de papier, un peu
   plus haut qu'ailleurs pour laisser respirer le titre. Rien d'autre : le sceau
   du logo (voir plus bas) est la seule pièce posée sur ce fond. */
.hero {
    background: var(--wash-paper);
    padding: 120px 0 108px;
}

.hero-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: 72px;
    align-items: center;
}

/* Surtitre de marque : le nom du cabinet seul, au-dessus du titre — la même
   pièce que sur l'aperçu de partage. Sa présence vient de la graisse (700,
   celle du logotype) et de l'interlettrage ; son corps suit la même rampe que
   le titre (5,4 vw, bornée comme lui) pour garder partout le rapport de
   l'aperçu. Le tiret qui l'ouvre est le dégradé du liseré d'en-tête, posé à
   l'échelle du mot. */
.hero-kicker {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    margin-bottom: 1rem;
    font-family: var(--font-body);
    font-size: clamp(0.9375rem, 1.93vw, 1.5rem);
    font-weight: 700;
    letter-spacing: 0.2em;
    line-height: 1;
    color: var(--ink);
}

.hero-kicker::before {
    content: "";
    flex: none;
    width: 1.3em;
    height: 3px;
    background: var(--brand-gradient);
}

.hero-copy h1 {
    color: var(--ink);
    /* 4,2 rem est le plafond qui garde « Cabinet de conseil » — la ligne la plus
       longue du titre — dans la colonne du hero : au-delà, elle déborde de la
       gouttière. */
    font-size: clamp(2.55rem, 5.4vw, 4.2rem);
    line-height: 1.04;
    letter-spacing: -0.026em;
    margin-bottom: 24px;
}

/* Le plafond de 15 ch ne porte que sur la phrase : la ligne des métiers, elle,
   prend toute la colonne — c'est ce qui lui permet de tenir sur une seule ligne
   sans descendre sous 0,48 em. */
.hero-title-main {
    display: block;
    max-width: 15ch;
}

/* Les trois métiers sont de même rang : une seule ligne, une seule taille, un
   seul registre — l'italique de la serif, comme une ligne de sommaire — et un
   filet fin entre eux, qui est la structure du système. Aucun métier ne passe
   en tête : le titre annonce le cabinet, puis ses trois domaines à égalité.
   La ligne est en encre et en 500 : elle doit se détacher de l'amorce grise
   juste en dessous, et non se lire comme un intertitre. Sa taille (0,38 em) est
   plafonnée par la colonne du hero à deux colonnes : 20,4 fois son corps, soit
   7,8 em du titre, pour 8,1 em de colonne disponible. */
.hero-title-domains {
    display: block;
    margin-top: 20px;
    font-size: 0.38em;
    font-style: italic;
    font-weight: 500;
    letter-spacing: -0.01em;
    line-height: 1.28;
    color: var(--ink);
}

.hero-title-domains>span {
    white-space: nowrap;
}

/* Le filet est posé après chaque métier sauf le dernier : si la ligne venait à
   se replier, il fermerait la ligne au lieu de s'y retrouver en tête. */
.hero-title-domains>span:not(:last-child)::after {
    content: "";
    display: inline-block;
    width: 0.75em;
    height: 1px;
    margin: 0 0.5em;
    vertical-align: middle;
    background: currentColor;
    opacity: 0.35;
}

.hero .lede {
    font-size: 1.1875rem;
    line-height: 1.6;
    color: var(--text-muted);
    max-width: 44ch;
}

/* La première phrase de l'amorce est son accroche : elle prend ses propres lignes,
   passe en encre et en 500, à 1,05 em — soit ~20 px. C'est le contraste de valeur
   — encre contre `--text-muted` — qui la détache, pas le corps : à taille voisine
   de l'amorce, la ligne des métiers (22,4 à 25,5 px) garde le dessus, et avec elle
   le rang du titre. La phrase reste dans le paragraphe, donc la lecture et les
   lecteurs d'écran n'y voient qu'une amorce d'un seul bloc. */
.hero .lede-lead {
    display: block;
    margin-bottom: 0.45em;
    font-size: 1.05em;
    font-weight: 500;
    line-height: 1.5;
    letter-spacing: -0.005em;
    color: var(--ink);
    text-wrap: balance;
}

.hero-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 40px;
}

/* Sceau animé : le logo seul, sans disque ni anneau, sur le papier. Une rotation
   lente et continue, un tour en 5 s, pendant qu'un reflet le traverse de gauche
   à droite. Deux faces portent le lockup, la face arrière pré-tournée de 180°,
   donc le mot n'est jamais inversé ni mis en miroir. Aucune interaction : le
   survol ne change rien. `--seal-size` pilote la largeur du lockup (symbole et
   mot) ; le reflet, la lueur et la rotation partagent le même tempo. */
.seal {
    /* La colonne de droite du hero vaut (min(fenêtre, --maxw) − 96 px de gouttières
       − 72 px de gouttière de grille) × 0,475 ; le lockup en prend 0,47, soit la
       quasi-totalité. Il ne dépasse jamais la hauteur disponible : le rapport du
       lockup (hauteur = 1,21 × largeur) ramène le budget de `100vh − 350px`
       (en-tête et rembourrages du hero) à une largeur. Les 16 px ôtés à la fenêtre
       couvrent la barre de défilement, que `100vw` compte sur Windows : sans eux le
       logo dépassait sa colonne de quelques pixels. */
    --seal-size: min(calc((min(100vw - 16px, var(--maxw)) - 168px) * 0.47),
            calc((100vh - 350px) / 1.21));
    /* Le reflet et la rotation démarrent ensemble et reviennent exactement à
       leur point de départ : la boucle ne se voit jamais. */
    position: relative;
    width: var(--seal-size);
    max-width: 100%;
    /* Le recadrage du symbole laisse 16 % de vide à droite de son encre — c'est ce
       qui met le symbole et le mot à la même largeur visible. On décale donc la
       boîte de la moitié de ce vide pour centrer ce qu'on voit, et non la boîte. */
    margin: 0 auto 0 calc((100% - var(--seal-size) * 0.84) / 2);
    perspective: calc(var(--seal-size) * 8);
    animation: seal-enter 0.9s var(--ease) 0.28s both;
}

/* La lueur : un halo très doux, en bleu de marque, qui respire lentement derrière
   le logo. Pas de disque, pas de bord — la lumière n'a pas de contour. */
.seal::before {
    content: "";
    position: absolute;
    inset: -16%;
    z-index: -1;
    background-image: radial-gradient(closest-side, rgba(52, 152, 219, 0.14), rgba(52, 152, 219, 0.05) 58%, transparent 80%);
    animation: seal-glow 10s ease-in-out 1.2s infinite;
}

/* La pièce : une rotation lente et continue, à vitesse constante — la fluidité
   absolue ne supporte aucune accélération. Le délai de 1,2 s laisse la séquence
   de chargement finir avant le premier tour. */
.seal-coin {
    position: relative;
    transform-style: preserve-3d;
    animation: logo-spin var(--logo-cycle) linear 1.2s infinite;
}

.seal-face {
    display: grid;
    place-items: center;
    backface-visibility: hidden;
}

/* La face arrière est le même lockup, tourné de 180° au repos : quand la pièce a
   fait un demi-tour, c'est elle qu'on lit, et son contenu est droit. */
.seal-face--back {
    position: absolute;
    inset: 0;
    transform: rotateY(180deg);
}

/* Lockup du logo : le symbole, puis COFINEX. C'est le MOT qui fixe la largeur
   (`min-content`) et le symbole qui prend 100 % de cette largeur — les deux
   font donc exactement la même largeur, comme dans le logotype de l'en-tête.
   `align-items: start` est indispensable : par défaut un item de grille est
   étiré, et le symbole s'allongeait alors sur toute la hauteur du lockup au lieu
   de suivre son ratio. `min-width: 0` l'est tout autant : sans lui, le
   `min-width: auto` d'un item de grille élargit la boîte. */
.seal-lockup {
    display: inline-grid;
    grid-template-columns: min-content;
    align-items: start;
    justify-items: center;
    min-width: 0;
    /* Mesuré sur le lockup : l'écart vaut 1/14,9 de sa largeur. */
    gap: calc(var(--seal-size) / 14.9);
}

/* Le reflet du symbole : une bande claire inclinée qui balaie le dessin de gauche
   à droite, une fois par tour. Le masque reprend la découpe du PNG pour que rien
   ne dépasse du dessin. */
.seal-lockup .logo-mark {
    position: relative;
    width: 100%;
}

.seal-lockup .logo-mark::after {
    content: "";
    position: absolute;
    inset: 0;
    background-image: linear-gradient(100deg, transparent 42%, rgba(255, 255, 255, 0.92) 50%, transparent 58%);
    background-size: 260% 100%;
    background-repeat: no-repeat;
    animation: seal-sheen var(--logo-cycle) linear 1.2s infinite;
    -webkit-mask-image: var(--mark-url);
    -webkit-mask-size: var(--mark-size);
    -webkit-mask-position: var(--mark-pos);
    -webkit-mask-repeat: no-repeat;
    mask-image: var(--mark-url);
    mask-size: var(--mark-size);
    mask-position: var(--mark-pos);
    mask-repeat: no-repeat;
}

.seal-name {
    position: relative;
    font-family: var(--font-body);
    font-weight: 700;
    /* Mesuré sur le lockup : la lettre vaut 1/5,51 de sa largeur. */
    font-size: calc(var(--seal-size) / 5.51);
    letter-spacing: 0.16em;
    line-height: 1;
    white-space: nowrap;
    color: var(--ink);
    /* le tracking s'ajoute après le dernier X : on l'annule pour que le mot soit
       optiquement centré sous le symbole */
    margin-right: -0.16em;
    -webkit-text-fill-color: transparent;
}

.seal-name::before {
    -webkit-mask-size: calc(100% - 0.16em) auto;
    mask-size: calc(100% - 0.16em) auto;
}

/* Les lettres prennent la lumière au même instant : un halo blanc passe derrière
   elles et l'encre s'éclaircit brièvement. Un vrai reflet *sur* les glyphes
   demanderait `background-clip: text`, que le détecteur du projet classe parmi les
   tics d'interface (texte en dégradé) : l'ombre portée et le coup de lumière sur
   l'encre donnent la même sensation sans ce signal. */
.seal-name {
    animation: seal-glint var(--logo-cycle) linear 1.2s infinite;
}

.service-hero-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    align-items: center;
    gap: clamp(24px, 6vw, 72px);
}

/* ---------- À propos + pourquoi nous choisir ---------- */
.about {
    background: var(--white);
}

.about-body {
    /* En colonne unique, le paragraphe occuperait toute la largeur : la mesure
       est bornée. */
    max-width: 62ch;
    margin-bottom: 56px;
}

.about-body h2 {
    font-size: clamp(1.75rem, 2.7vw, 2.35rem);
    letter-spacing: -0.022em;
    margin-bottom: 24px;
    max-width: 22ch;
}

/* Les cinq raisons suivent le paragraphe, dans la même section, sous forme de
   blocs arrondis (`.card-grid` / `.card`). La bande étant blanche, les cartes
   gardent leur papier gris : elles se détachent par la valeur, sans filet. */
.why h2 {
    font-size: clamp(1.35rem, 1.9vw, 1.6rem);
    letter-spacing: -0.018em;
    margin-bottom: 28px;
}

/* ---------- Services ---------- */
.services {
    background: var(--paper-soft);
}

.services-list {
    border-top: 1px solid var(--line);
}

/* La ligne porte toute l'interaction : le fond s'allume, le contenu avance de
   4 px, le filet se renforce. Rien de tout cela ne s'applique au toucher —
   le survol est isolé dans le `@media (hover: hover)` plus bas. */
.service-row {
    display: grid;
    grid-template-columns: 48px minmax(0, 0.9fr) minmax(0, 1.35fr) 28px;
    gap: 28px;
    align-items: center;
    padding: 28px 0;
    border-bottom: 1px solid var(--line);
    transition: background-color 0.25s var(--ease), border-color 0.25s var(--ease);
}

.service-row>* {
    transition: transform 0.35s var(--ease);
}

/* Pastille d'icône : un carré bleu lavé donne à chaque domaine le même poids
   visuel et fait respirer la ligne sans ajouter de carte. */
.service-icon {
    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
    border-radius: 14px;
    background: rgba(52, 152, 219, 0.10);
    color: var(--blue-deep);
    transition: background-color 0.25s var(--ease), color 0.25s var(--ease),
        transform 0.35s var(--ease);
}

.service-icon svg {
    width: 22px;
    height: 22px;
    display: block;
}

/* Survol réservé aux appareils qui ont un vrai pointeur : sur écran tactile,
   `:hover` se collerait après le premier tap. */
@media (hover: hover) {
    .service-row:hover {
        /* La bande de la section est grise : la ligne s'éclaire au blanc. */
        background: var(--white);
        border-bottom-color: var(--line-strong);
    }

    .service-row:hover>*:not(.row-arrow) {
        transform: translateX(4px);
    }

    .service-row:hover .service-icon {
        background: rgba(245, 130, 31, 0.14);
        color: var(--orange);
    }
}

/* Affordance de lien : la flèche ne s'éclaire qu'au survol de la ligne */
.row-arrow {
    display: flex;
    justify-content: flex-end;
    color: var(--line-strong);
    transition: color 0.25s var(--ease), transform 0.35s var(--ease);
}

.row-arrow svg {
    display: block;
    width: 20px;
    height: 20px;
}

.service-row h3 {
    font-size: 1.2rem;
    letter-spacing: -0.02em;
    margin: 0;
    color: var(--ink);
}

.service-row p {
    margin: 0;
    font-size: 15px;
    line-height: 1.6;
    max-width: 56ch;
}

@media (hover: hover) {
    .service-row:hover .row-arrow {
        color: var(--orange);
        transform: translateX(4px);
    }
}

/* ---------- Partenaires ---------- */
.partners {
    background: var(--paper-soft);
}

/* Mur de partenaires : des tuiles blanches posées sur la bande papier. Le
   damier à filets partagés d'origine transformait la section en tableau — des
   tuiles séparées se lisent comme des logos qu'on remplacera un par un. */
.partners-list {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 16px;
    list-style: none;
    margin: 0;
    padding: 0;
}

.partners-list li {
    display: grid;
    place-items: center;
    min-height: 116px;
    background: var(--white);
    border-radius: var(--radius);
    box-shadow: var(--shadow-1);
    padding: 32px 20px;
    text-align: center;
    font-family: var(--font-display);
    font-size: 1.05rem;
    font-weight: 500;
    color: var(--text-muted);
}

/* ---------- Contact ----------
   La section ne contient plus que le formulaire : le titre et la phrase
   d'introduction reprennent la tête de section des autres blocs.
   Deux colonnes — le titre tient la gauche et reste sous les yeux pendant qu'on
   remplit à droite : le formulaire ne court plus sur 1 200 px, et la section ne
   se lit plus comme un long blanc. Bascule en une colonne ≤ 1080 px. */
.contact {
    background: var(--white);
}

.contact .container {
    display: grid;
    grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
    gap: 72px;
    align-items: start;
}

.contact .section-head {
    display: block;
    margin-bottom: 0;
    position: sticky;
    /* +24 px : la même respiration que les ancres. Le titre ne se colle que
       lorsque la page défile, donc l'en-tête est déjà reculé de 8 px — la
       garde visible sous lui est donc de 32 px, comme pour les ancres. */
    top: calc(var(--header-h, 122px) + 24px);
}

.contact form {
    max-width: none;
}

form {
    display: grid;
    gap: 18px;
}

.form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 18px;
}

label {
    display: block;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--ink);
    margin-bottom: 7px;
}

input,
textarea,
select {
    width: 100%;
    background: var(--paper-soft);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    padding: 13px 15px;
    color: var(--ink);
    font-family: var(--font-body);
    /* 16 px au minimum : en dessous, Safari iOS zoome sur le champ au focus. */
    font-size: 16px;
    caret-color: var(--orange);
    transition: border-color 0.18s var(--ease), background-color 0.18s var(--ease),
        box-shadow 0.18s var(--ease);
}

input::placeholder,
textarea::placeholder {
    color: var(--text-muted);
}

input:hover,
textarea:hover,
select:hover {
    border-color: var(--line-strong);
}

input:focus,
textarea:focus,
select:focus {
    outline: none;
    border-color: var(--orange);
    background: var(--white);
    box-shadow: 0 0 0 4px rgba(245, 130, 31, 0.16);
}

textarea {
    min-height: 132px;
    resize: vertical;
}

select {
    appearance: none;
    padding-right: 42px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232C3E50' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 14px center;
    background-size: 16px;
}

.form-note {
    font-size: 12.5px;
    color: var(--text-muted);
    margin: -4px 0 0;
}

/* Lien de la note : dans un paragraphe secondaire, la couleur seule ne suffit
   pas à signaler un lien (WCAG 1.4.1) — soulignement + bleu profond (4,9:1). */
.form-note a {
    color: var(--blue-deep);
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* Liens cités dans la prose (pages légales, renvois externes) : même signal. */
.page-block p a {
    color: var(--blue-deep);
    text-decoration: underline;
    text-underline-offset: 2px;
}

form .btn {
    justify-self: start;
}

/* ---------- Pied de page ----------
   Fond `--ink` et non `--navy` : l'encre pose une base sourde qui ne répond pas
   au navy de l'en-tête (deux bandes de même couleur se lisaient comme un
   deuxième en-tête). Bonus de contraste : liens à 7,5:1 au lieu de 5,9:1. */
footer {
    background: var(--ink);
    padding: 52px 0 34px;
}

.footer-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 22px 32px;
    padding-bottom: 22px;
    border-bottom: 1px solid var(--line-on-dark);
    margin-bottom: 22px;
}

.footer-links {
    display: flex;
    flex-wrap: wrap;
    gap: 28px;
    list-style: none;
    margin: 0;
    padding: 0;
}

.footer-links a {
    font-size: 14px;
    color: var(--on-dark-muted);
    transition: color 0.18s var(--ease);
}

.footer-links a:hover {
    color: var(--on-dark);
    text-decoration: underline;
    text-underline-offset: 4px;
}

.footer-bottom {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 16px;
}

.footer-note {
    margin: 0;
    max-width: none;
    font-size: 12.5px;
    color: var(--on-dark-faint);
}

.footer-legal {
    display: flex;
    flex-wrap: wrap;
    gap: 24px;
    list-style: none;
    margin: 0;
    padding: 0;
}

.footer-legal a {
    font-size: 12.5px;
    color: var(--on-dark-muted);
    transition: color 0.18s var(--ease);
}

.footer-legal a:hover {
    color: var(--on-dark);
    text-decoration: underline;
    text-underline-offset: 4px;
}

/* ---------- Pages de service ---------- */
.page-hero {
    background: var(--wash-paper);
    padding: 76px 0 68px;
}

.page-hero h1 {
    font-size: clamp(2.15rem, 4.6vw, 3.4rem);
    line-height: 1.05;
    letter-spacing: -0.026em;
    max-width: 22ch;
    margin-bottom: 20px;
}

.page-hero .lede {
    color: var(--text-muted);
    max-width: 56ch;
}

.page-hero .hero-actions {
    margin-top: 32px;
}

/* Fil d'Ariane */
.breadcrumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    list-style: none;
    margin: 0 0 28px;
    padding: 0;
    font-size: 13.5px;
    color: var(--text-muted);
}

.breadcrumb li {
    display: inline-flex;
    align-items: center;
    gap: 10px;
}

.breadcrumb li+li::before {
    content: "/";
    color: var(--line-strong);
}

.breadcrumb a {
    color: var(--blue-deep);
}

.breadcrumb a:hover {
    text-decoration: underline;
    text-underline-offset: 3px;
}

.breadcrumb [aria-current="page"] {
    color: var(--text-body);
}

/* Page courante : repère discret dans le menu des services */
.dropdown-menu a[aria-current="page"] {
    background: var(--paper);
    color: var(--ink);
    font-weight: 600;
}

.page-section {
    padding: 88px 0;
}

.page-section h2 {
    font-size: clamp(1.75rem, 2.7vw, 2.35rem);
    letter-spacing: -0.022em;
    margin-bottom: 20px;
    max-width: 26ch;
}

.page-intro {
    max-width: 62ch;
    margin-bottom: 0;
}

/* Même grille que les têtes de section : le titre d'introduction à gauche, la
   prose à droite. `:has(h2)` laisse de côté les introductions sans titre. */
@media (min-width: 901px) {
    .page-intro:has(h2) {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
        gap: 24px 56px;
        align-items: start;
        max-width: none;
    }

    .page-intro:has(h2) h2 {
        margin-bottom: 0;
    }

    /* La prose reste dans la colonne de droite, y compris quand l'introduction
       compte deux paragraphes : sans cela, le second retombait sous le titre. */
    .page-intro:has(h2)>p {
        grid-column: 2;
    }
}

/* Blocs de contenu d'une page de service : la respiration entre blocs est
   portée par le bloc lui-même, pas par des marges en ligne dans le HTML. */
.page-block {
    margin-top: 72px;
}

.page-block .lede {
    color: var(--text-muted);
    margin-bottom: 32px;
}

/* Mention de complétude (pages en cours de rédaction) */
.page-status {
    font-size: 13.5px;
    color: var(--text-muted);
}

.page-intro h2 {
    margin-bottom: 18px;
}

/* Déroulé numéroté. Grille plutôt que positionnement absolu : le numéro tombe
   naturellement sur la première ligne du titre, à toutes les tailles de police.
   Il prend la forme des pastilles d'icônes des services — carré bleu lavé,
   chiffres tabulaires — donc le déroulé se lit d'un coup d'œil sans ajouter un
   gros chiffre de template. */
.steps {
    list-style: none;
    counter-reset: step;
    margin: 0;
    padding: 0;
    border-top: 1px solid var(--line);
}

.steps li {
    counter-increment: step;
    display: grid;
    grid-template-columns: 40px minmax(0, 1fr);
    gap: 0 28px;
    align-items: start;
    padding: 26px 0;
    border-bottom: 1px solid var(--line);
}

.steps li::before {
    content: counter(step, decimal-leading-zero);
    grid-column: 1;
    grid-row: 1 / span 2;
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border-radius: 12px;
    background: rgba(52, 152, 219, 0.10);
    font-family: var(--font-body);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.04em;
    font-variant-numeric: tabular-nums;
    color: var(--blue-deep);
}

.steps h3 {
    grid-column: 2;
    font-size: 1.1rem;
    margin: 0 0 6px;
}

.steps p {
    grid-column: 2;
    margin: 0;
    font-size: 15px;
    max-width: 62ch;
}

/* Repères chiffrés, deux colonnes : chaque cellule porte son propre filet,
   donc aucune zone vide ne peut laisser voir un fond de grille. */
.fact-list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 56px;
    margin: 0;
}

.fact-list>div {
    padding: 20px 0;
    border-bottom: 1px solid var(--line);
}

.fact-list dt {
    font-size: 12.5px;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--blue-deep);
    margin-bottom: 6px;
}

.fact-list dd {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.15rem;
    color: var(--ink);
}

/* Cartes */
.card-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 24px;
}

.card {
    background: var(--paper-soft);
    border-radius: var(--radius);
    padding: 30px 28px;
    box-shadow: var(--shadow-1);
}

.card h3 {
    font-size: 1.05rem;
    margin: 0 0 8px;
    color: var(--ink);
}

.card p {
    margin: 0;
    font-size: 15px;
}

/* Cartes d'annonces : la ligne de repères (secteur, CA, effectif) est construite
   par script.js (`meta.className = "card-meta"`), donc absente du HTML. */
.card .card-meta {
    display: block;
    margin-top: 16px;
    padding-top: 14px;
    border-top: 1px solid var(--line);
    font-size: 12.5px;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--blue-deep);
}

/* Encart (confidentialité, réserve) */
.callout {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    max-width: 68ch;
    background: var(--paper-soft);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 24px 26px;
}

.callout svg {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    margin-top: 3px;
    color: var(--blue-deep);
}

.callout p {
    margin: 0;
    font-size: 15px;
}

/* ---------- Mouvement ---------- */
/* Le texte se dévoile en arrivant : il monte et se pose, en opacité seule — pas
   de flou, qui laissait les blocs du bas de la fenêtre visiblement flous pendant
   la révélation. Une seule séquence orchestrée au chargement du hero — pas un
   effet répété sur chaque section. */
@keyframes rise {
    from {
        opacity: 0;
        transform: translateY(18px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Rotation du logo — celle du hero et, sur mobile, celle du symbole de l'en-tête.
   Un tour complet par cycle, à vitesse constante : la fin du tour rejoint son début
   (360° = 0°), donc la boucle est parfaite et le mouvement ne connaît ni à-coup ni
   temps mort. */
@keyframes logo-spin {
    from {
        transform: rotateY(0deg);
    }

    to {
        transform: rotateY(360deg);
    }
}

/* Reflet de l'en-tête, sur mobile. La face avant du symbole est tournée vers nous
   entre 78 % et 22 % du cycle (le tour passe par 0° à l'instant 0) : c'est là, et
   là seulement, que le reflet court. Le fond fait 2,6 × la boîte, donc la bande
   est hors du cadre à 97 % (à gauche) et à 3 % (à droite), et elle passe sur le
   centre du dessin quand le lockup est de face. */
@keyframes header-sheen {

    0%,
    100% {
        background-position: 50% 0;
        opacity: 1;
    }

    22% {
        background-position: 3% 0;
        opacity: 1;
    }

    32% {
        background-position: 1% 0;
        opacity: 0;
    }

    68% {
        background-position: 99% 0;
        opacity: 0;
    }

    78% {
        background-position: 97% 0;
        opacity: 0;
    }
}

/* Les lettres du mot s'allument au même moment : un éclat bref quand le lockup
   arrive de face, puis l'encre revient au clair de l'en-tête. */
@keyframes header-glint {

    0%,
    8% {
        color: var(--white);
        text-shadow: 0 0 10px rgba(255, 255, 255, 0.7);
    }

    16%,
    92% {
        color: var(--on-dark);
        text-shadow: none;
    }
}

/* Reflet du symbole : la bande part hors du cadre à gauche et sort hors du cadre à
   droite — à 0 % comme à 100 % elle est invisible, donc la boucle ne se voit pas.
   Le fond fait 2,6 × la boîte et les pourcentages de position se lisent à l'envers
   pour un fond plus grand que la boîte : à 97 % la bande est à gauche, à 3 % à
   droite, et elle passe sur le centre à la moitié du cycle. */
@keyframes seal-sheen {
    from {
        background-position: 97% 0;
    }

    to {
        background-position: 3% 0;
    }
}

/* Les lettres s'éclairent à ce même instant : le halo se resserre sur elles et
   l'encre remonte d'un cran, puis tout revient. */
@keyframes seal-glint {

    0%,
    100% {
        color: var(--ink);
        text-shadow: 22px 0 26px rgba(255, 255, 255, 0);
    }

    50% {
        color: var(--text-body);
        text-shadow: 0 0 26px rgba(255, 255, 255, 0.9);
    }
}

/* La lueur respire sur deux tours : elle s'éteint et se rallume sans jamais
   s'arrêter net. */
@keyframes seal-glow {

    0%,
    100% {
        opacity: 0.72;
    }

    50% {
        opacity: 1;
    }
}

/* Entrée du sceau : opacité et `scale` — la propriété autonome, pas `transform`,
   qui appartient déjà à la pièce. */
@keyframes seal-enter {
    from {
        opacity: 0;
        scale: 0.94;
    }

    to {
        opacity: 1;
        scale: 1;
    }
}

.hero-copy>* {
    animation: rise 0.9s var(--ease) both;
}

.hero-copy h1 {
    animation-delay: 0.05s;
}

.hero-copy .lede {
    animation-delay: 0.13s;
}

.hero-copy .hero-actions {
    animation-delay: 0.21s;
}

/* Sur mobile, pas de logo animé sous le hero : c'est le lockup de l'en-tête qui
   reprend l'animation du sceau, à sa taille. Le symbole ET le mot COFINEX se
   retournent ensemble, et un reflet les traverse. Chaque pièce a deux faces — la
   face arrière est pré-tournée de 180° et porte la même partie du PNG que la face
   avant — donc rien ne s'aplatit et rien ne se lit à l'envers. Les deux tournent autour de leur
   propre centre horizontal, qui est le même axe : le lockup se retourne d'un bloc.

   Le logo du hero est retiré sous 901 px, et sur un appareil tactile
   (`hover: none` + `pointer: coarse`) dont la fenêtre est basse (`max-height:
   760px`) : c'est ce qui attrape un téléphone tenu en paysage — sa fenêtre dépasse
   900 px — sans toucher aux tablettes, dont la hauteur laisse la place au sceau.
   Une tablette ou un 2-en-1 en paysage (iPad Pro 1366 × 1024, Surface 1368 × 912)
   perdait sinon son logo tout en gardant la colonne de droite : un hero à moitié
   vide, et un en-tête qui disparaissait deux fois par cycle. Les autres animations
   de la page, elles, restent en place. */
@media (max-width: 900px), (hover: none) and (pointer: coarse) and (max-height: 760px) {
    .seal:not(.service-seal) {
        display: none;
    }

    /* Le sceau retiré, sa colonne resterait vide : le hero garderait deux colonnes
       et la moitié droite serait un trou. Il repasse en une colonne, exactement
       comme le hero des pages de service juste en dessous. */
    .hero-grid {
        grid-template-columns: 1fr;
        gap: 56px;
    }

    .service-hero-grid {
        grid-template-columns: 1fr;
    }

    .service-seal {
        display: none;
    }

    /* Même rapport que le sceau du hero entre la perspective et la largeur. */
    #site-header .logo {
        perspective: 650px;
    }

    #site-header .logo-mark,
    #site-header .logo-name {
        position: relative;
        transform-style: preserve-3d;
        backface-visibility: hidden;
    }

    #site-header .logo-mark {
        animation: logo-spin var(--logo-cycle) linear 1.2s infinite;
    }

    #site-header .logo-name {
        animation: logo-spin var(--logo-cycle) linear 1.2s infinite,
            header-glint var(--logo-cycle) linear 1.2s infinite;
    }

    /* Face arrière du symbole : le même PNG, recadré et pré-tourné. */
    #site-header .logo-mark::after {
        content: "";
        position: absolute;
        inset: 0;
        background-image: var(--mark-url);
        background-repeat: no-repeat;
        background-size: var(--mark-size);
        background-position: var(--mark-pos);
        transform: rotateY(180deg);
        backface-visibility: hidden;
    }

    /* Le reflet du symbole : la bande balaie la face avant, découpée à la forme du
       PNG. Elle ne court qu'entre 78 % et
       22 % du cycle — la fenêtre où cette face est tournée vers nous : de l'autre
       côté du tour, la face qui porte la bande passe derrière, et sans cela la
       lumière s'éteindrait au milieu de sa course. C'est une lumière de studio,
       qui éclaire d'un seul côté. */
    #site-header .logo-mark::before {
        content: "";
        position: absolute;
        inset: 0;
        background-image: linear-gradient(100deg, transparent 38%, rgba(255, 255, 255, 0.95) 50%, transparent 62%);
        background-size: 260% 100%;
        background-repeat: no-repeat;
        animation: header-sheen var(--logo-cycle) linear 1.2s infinite;
        -webkit-mask-image: var(--mark-url);
        -webkit-mask-size: var(--mark-size);
        -webkit-mask-position: var(--mark-pos);
        -webkit-mask-repeat: no-repeat;
        mask-image: var(--mark-url);
        mask-size: var(--mark-size);
        mask-position: var(--mark-pos);
        mask-repeat: no-repeat;
    }

    /* Face arrière du mot : la même forme du PNG, avec la couleur de la face avant. */
    #site-header .logo-name::after {
        content: "COFINEX";
        position: absolute;
        inset: 0;
        color: inherit;
        background-color: currentColor;
        -webkit-mask-image: var(--mark-url);
        -webkit-mask-size: calc(100% - 0.08em) auto;
        -webkit-mask-position: left bottom;
        -webkit-mask-repeat: no-repeat;
        mask-image: var(--mark-url);
        mask-size: calc(100% - 0.08em) auto;
        mask-position: left bottom;
        mask-repeat: no-repeat;
        transform: rotateY(180deg);
        backface-visibility: hidden;
    }
}

/* Blocs révélés au défilement : purement déclaratif (`animation-timeline`),
   donc sans observateur JS et sans risque de laisser un bloc invisible si le
   script ne tourne pas. La timeline est déclarée APRÈS le raccourci
   `animation`, qui la remettrait sinon à `auto`. Les navigateurs qui ignorent
   `view()` sautent le bloc : le contenu reste affiché normalement. */
@supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
        .section-head,
        .about-body,
        .why,
        .service-row,
        .partners-list,
        .contact form,
        .page-block,
        .callout {
            animation: rise linear both;
            animation-timeline: view();
            /* La révélation se termine tôt : un bloc encore translucide au
               milieu de l'écran se lirait mal. `cover` borne le trajet à une
               fraction de (hauteur du bloc + fenêtre), donc un grand bloc se
               révèle aussi vite qu'un petit. */
            animation-range: cover 0% cover 22%;
        }
    }
}

/* Le titre de la section contact est collant : une timeline de vue sur un
   élément qui ne bouge pas le laisserait figé à mi-course. */
.contact .section-head {
    animation: none;
}

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

    *,
    *::before,
    *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
    }

    /* La bande de reflet finit son cycle allumée, au centre : sous mouvement
       réduit on l'éteint plutôt que de la laisser figée en travers du logo. */
    .seal-lockup .logo-mark::after,
    #site-header .logo-mark::before {
        animation: none !important;
        opacity: 0 !important;
    }
}

/* ---------- Impression ----------
   À l'impression (et dans un PDF), il n'y a pas de défilement : une timeline
   `view()` reste bloquée à 0 % et laisse le contenu à `opacity: 0` — les pages
   légales sortaient donc presque blanches. On fige la révélation sur son état
   final ; les bandes de reflet, elles, sont éteintes (figées allumées, elles
   traverseraient le logo). */
@media print {
    .hero-copy>*,
    .section-head,
    .about-body,
    .why,
    .service-row,
    .partners-list,
    .contact form,
    .page-block,
    .callout {
        animation: none !important;
        opacity: 1 !important;
        transform: none !important;
    }

    .seal-lockup .logo-mark::after,
    #site-header .logo-mark::before {
        animation: none !important;
        opacity: 0 !important;
    }
}

/* ---------- Adaptatif ---------- */
@media (max-width: 1080px) {
    .hero-grid {
        grid-template-columns: 1fr;
        gap: 56px;
    }

    /* Une seule colonne : la ligne des métiers dispose de toute la largeur du
       contenu et remonte donc à 0,55 em, contre 0,38 em dans le hero à deux
       colonnes. */
    .hero-title-domains {
        font-size: 0.55em;
    }

    /* Sous 1081 px le hero n'a plus qu'une colonne : le lockup n'est plus borné
       par la colonne de droite mais par la fenêtre, dont il prend les deux tiers
       — 400 px au plus, sinon un logo de 480 px de haut écraserait le hero. */
    .seal:not(.service-seal) {
        --seal-size: min(62vw, 400px);
    }

    .hero {
        padding: 96px 0 88px;
    }

    .partners-list {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .card-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* Le formulaire repasse sous le titre : sur un écran étroit, une colonne
       collante n'a plus de sens, la page redevient une lecture verticale. */
    .contact .container {
        grid-template-columns: 1fr;
        gap: 40px;
    }

    .contact .section-head {
        position: static;
    }

    .page-hero {
        padding: 64px 0 56px;
    }

}

@media (max-width: 900px) {
    .nav-toggle {
        display: inline-flex;
    }

    .nav-cta-desktop {
        display: none;
    }

    /* Voile derrière le tiroir mobile (dans le contexte d'empilement de l'en-tête) */
    body.no-scroll #site-header::after {
        content: "";
        position: fixed;
        inset: 0;
        z-index: 1;
        background: rgba(28, 40, 51, 0.55);
    }

    .nav-links {
        position: fixed;
        top: 0;
        right: 0;
        width: min(88vw, 380px);
        height: 100dvh;
        z-index: 2;
        flex-direction: column;
        align-items: stretch;
        gap: 0;
        padding: 124px 24px 24px;
        background: var(--navy);
        box-shadow: -24px 0 48px -24px rgba(28, 40, 51, 0.6);
        border-left: 1px solid var(--line-on-dark);
        overflow-y: auto;
        transform: translateX(100%);
        transition: transform 0.3s var(--ease);
    }

    .nav-links.open {
        transform: translateX(0);
    }

    .nav-links>li {
        width: 100%;
    }

    .nav-links a,
    .nav-links .nav-link-btn {
        width: 100%;
        justify-content: space-between;
        padding: 16px 8px;
        border-radius: 0;
        border-bottom: 1px solid var(--line-on-dark);
        font-size: 16px;
        color: var(--on-dark);
    }

    .nav-links a:hover,
    .nav-links .nav-link-btn:hover {
        background: transparent;
        color: var(--white);
    }

    .dropdown-menu {
        position: static;
        min-width: 0;
        padding: 0 0 6px 14px;
        border: 0;
        border-radius: 0;
        background: transparent;
        box-shadow: none;
        transform: none;
        opacity: 1;
        visibility: visible;
        display: none;
    }

    .has-dropdown.open .dropdown-menu {
        display: grid;
    }

    .has-dropdown.open .chevron {
        transform: rotate(225deg) translate(1px, 1px);
    }

    .dropdown-menu a {
        padding: 12px 8px;
        border-bottom: 0;
        font-size: 15px;
        color: var(--on-dark-muted);
    }

    .dropdown-menu a:hover {
        background: transparent;
        color: var(--white);
    }

    /* Dans le tiroir, l'entrée de synthèse doit rester claire sur le navy :
       le filet et l'encre prévus pour le panneau blanc y seraient invisibles. */
    .dropdown-menu .dropdown-tous {
        border-top-color: var(--line-on-dark);
        color: var(--on-dark);
    }

    .nav-cta-mobile {
        display: block;
    }

    .nav-cta-mobile .nav-cta {
        width: 100%;
        justify-content: center;
        margin-top: 20px;
        border-bottom: 0;
        background: var(--orange);
        color: var(--ink);
    }

    .nav-cta-mobile .nav-cta:hover {
        background: var(--orange-hover);
        color: var(--ink);
    }


}

@media (max-width: 640px) {
    .container {
        padding: 0 22px;
    }

    .nav {
        padding: 12px 22px;
    }

    .nav .logo-name {
        font-size: 14px;
    }

    :root {
        --section-pad: 80px;
        /* la gouttière passe à 22 px : le filet de section la suit */
        --rule-w: min(calc(100% - 44px), calc(var(--maxw) - 44px));
    }

    .hero {
        padding: 72px 0;
    }

    .hero-actions .btn {
        flex: 1 1 auto;
    }

    /* La ligne passe en deux colonnes : la pastille garde sa ligne, le titre et
       la flèche partagent la suivante, le texte reprend toute la largeur. Les
       lignes sont posées explicitement — en placement automatique, le texte qui
       occupe les deux colonnes repoussait la flèche sous lui. */
    .service-row {
        grid-template-columns: minmax(0, 1fr) auto;
        gap: 10px 14px;
        padding: 26px 0;
    }

    .service-icon {
        grid-column: 1 / -1;
        grid-row: 1;
    }

    .service-row h3 {
        grid-column: 1;
        grid-row: 2;
        align-self: center;
    }

    .row-arrow {
        grid-column: 2;
        grid-row: 2;
        align-self: center;
    }

    .service-row p {
        grid-column: 1 / -1;
        grid-row: 3;
        max-width: none;
    }

    .partners-list {
        grid-template-columns: 1fr;
    }

    .form-row {
        grid-template-columns: 1fr;
    }

    .footer-top,
    .footer-bottom {
        flex-direction: column;
        align-items: flex-start;
    }

    /* Le pied de page empilé occupe vite la moitié de l'écran : on resserre
       les gouttières des deux listes plutôt que de laisser un grand vide. */
    footer {
        padding: 26px 0 22px;
    }

    .footer-top {
        gap: 14px;
    }

    .footer-links {
        gap: 10px 20px;
    }

    .footer-bottom {
        gap: 10px;
    }

    .footer-legal {
        gap: 10px 20px;
    }

    /* Pages de service */
    .page-hero {
        padding: 52px 0 44px;
    }

    .page-section {
        padding: 64px 0;
    }

    .card-grid,
    .fact-list {
        grid-template-columns: 1fr;
    }

    .steps li {
        grid-template-columns: 34px minmax(0, 1fr);
        gap: 0 16px;
        padding: 22px 0;
    }

    .steps li::before {
        width: 34px;
        height: 34px;
        border-radius: 10px;
        font-size: 12.5px;
    }

    .page-block {
        margin-top: 56px;
    }
}

/* Sous 540 px, les trois métiers ne tiennent plus sur une ligne : ils passent en
   colonne, à la même taille, et le filet s'efface — trois lignes de sommaire
   plutôt qu'une ligne repliée qui laisserait un filet orphelin en tête. */
@media (max-width: 540px) {
    .hero-title-domains {
        display: flex;
        flex-direction: column;
        margin-top: 14px;
    }

    .hero-title-domains>span:not(:last-child)::after {
        content: none;
    }
}

/* ---------- Cibles tactiles ----------
   Un doigt vise 44 px. Les liens de texte n'ont pas de boîte propre : on leur en
   donne une, uniquement sur les appareils tactiles, pour ne rien alourdir sur
   ordinateur. `.logo` reste en grille (c'est le lockup) : seule sa hauteur
   minimale change. */
@media (hover: none) and (pointer: coarse) {

    .nav-links a,
    .nav-links .nav-link-btn,
    .footer-links a,
    .footer-legal a,
    .logo {
        min-height: 44px;
    }

    .footer-links a,
    .footer-legal a {
        display: inline-flex;
        align-items: center;
    }

    .skip-link {
        padding: 12px 16px;
    }
}

/* ---------- Grands écrans ----------
   Au-delà de 1 600 px, la colonne s'élargit par paliers de 120 px au lieu de
   laisser 1 100 px de papier de chaque côté. Rien ne se déforme : la mesure de
   lecture des blocs de prose est bornée en `ch` (44 à 68 suivant le bloc), donc
   élargir le contenant ne rallonge pas les lignes ; le sceau, les filets de
   section et les grilles suivent, puisqu'ils dérivent tous de `--maxw`. */
@media (min-width: 1600px) {
    :root {
        --maxw: 1320px;
    }
}

@media (min-width: 2000px) {
    :root {
        --maxw: 1440px;
    }
}
