/*
Theme Name: Hello Elementor Child
Theme URI: https://www.agoravita.com/
Description: Hello Elementor Child Theme
Author: Agoravita
Author URL: https://www.agoravita.com/
Template: hello-elementor
Version: 1.0.0
License: GNU General Public License v2 or later
License URL: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: hello-elementorchild
*/

.mb0 p{
    margin-bottom:0 !important;
}

.searchdesktop {
        position:absolute;
        right:0;
        top:0;
        background-color:#fe5000;
        border-radius: 0 100% 0 100% / 0 0 100% 100%;
        height: 90px;
        width: 90px;
        cursor:pointer;
        z-index:3;
        @media(min-width:1367px){
            height: 133px;
            width: 133px;
        }
}
.searchdesktop .elementor-widget-container{
        padding-top: 9px;
        padding-left: 17px;
        @media(min-width:1367px){
            padding-top:30px;
            padding-left:20px;
        }
}

.current-language-menu-item a::after{
    opacity:1 !important;
    left:0 !important;
    width:100% !important;
}
.menumetaheader .trp-language-switcher-container a{
    margin:0 8px !important
}
.menumetaheader .lang1{
    border-left:1px solid #fff !important;
    padding-left:15px !important
}
.menumetaheader .lang4{
    border-right:1px solid #fff !important;
    padding-right:15px !important
}


/* Le bloc `.subscribe-form` qui vivait ici a ete retire le 2026-08-27. Il datait de la mise en
   page « champ court + pave SEND en dessous » et huit de ses regles ne servaient plus a rien :
   le `form p` en flex visait un `<p>` que ce formulaire n'emet pas, les regles `.wpcf7-submit`
   et `.wpcf7-spinner` visaient un `<input type="submit">` et un indicateur qui ont disparu du
   gabarit, le `color:#000 important` etait une faute de frappe donc une declaration invalide,
   et l'invite etait figee a 16 px la ou la production en fait 15.
   Ce que le bloc faisait reellement se regle maintenant dans Elementor — typographie, marges et
   couleur de bordure a la saisie — et le reste est dans `.dedienne-subscribe`, plus bas. */
/* `p` retiré de cette liste le 2026-08-13 : voir le bloc « Paragraphes » plus bas. La remise à
   zéro était globale et jamais mesurée ; la production espace ses paragraphes de 10 px. */
.elementor-element h1, .elementor-element h2 {
    margin-block-start: 0em;
    margin-block-end: 0em;
}
.vignette-article h3, .vignette-article img, .vignette-article .elementor-icon svg{
   transition:all 0.3s ease-in-out
}
.vignette-article:hover h3{
    color:#fe5000 !important;
}
.vignette-article .elementor-widget-image{
    overflow: hidden;
}
.vignette-article:hover img{
    transform: scale(1.2);
}
.vignette-article:hover .elementor-icon svg{
    transform: translateX(10px);
}

.dedienne-form{
    @media(min-width:768px){
        .cl1 {
            float: left;
            width: 48% !important;
        }
        .cln2 {
            float: right;
            width: 48% !important;
        }
    }
    .mdc-layout-grid__inner{
        display: inline-block !important;
    }
   .cf7md-textarea {
        clear: both;
        margin-top: 20px !important;
        margin-bottom:20px !important;
    }
    input{
        background-color:#fff !important;
        border:1px solid #000 !important;
        border-radius:0 !important
    }
    .mdc-text-field--textarea{
        background-color:#fff !important;
        border:1px solid #000 !important;
        border-radius:0 !important
    }
    .mdc-select{
        border-bottom:1px solid #000;
        background-color:#fff !important;
        background-image: none !important;
        border-radius:0 !important;
    }
    select{
        background-image:none !important;
        -webkit-appearance: none !important;
        -moz-appearance: none !important;
        appearance: none !important;
        width:100% !important
    }
    .uael-cf7-select-custom{
         width:100% !important
    }
    .uael-cf7-select-custom:after{
        display:none !important;
    }
    .cf7md-select {
        margin-bottom: 15px !important;
    }
    .mdc-select:not(.mdc-select--disabled).mdc-select--focused .mdc-floating-label{
        color:#fe5000 !important
    }
     .cf7md-item {
         margin-top: 20px !important;
    }
    br{
        display:none !important;
    }
    label a {
        color:#000;
        text-decoration: underline;
    }
    .wpcf7-submit{
        width: auto;
        display: flex;
        padding: 15px 36px !important;
        box-shadow: none !important;
        background-color: #f8f8f8 !important;
        border:none !important;
        cursor: pointer;
        margin-top:20px !important
    }
    .wpcf7-submit:hover{
        background-color:#fe5000 !important;
        color:#fff !important;
    }
    .mdc-floating-label::after{
        color: #fe5000 !important;
    }
}

/* ==========================================================================
   Formulaire de candidature — page détail d'une offre d'emploi

   Signalé par Jérém sur /job-offers/<offre>/ : bordures de champs noires,
   textarea à double filet, bouton « Select file » surdimensionné, bouton
   d'envoi gris et collé à gauche.

   Ciblage volontairement restreint à `.elementor-element-177637a`, l'unique
   instance du widget « UAEL CF7 Styler » du template 127716 (Template Job
   offer). Les deux autres formulaires du site — Contact (11768) et Careers
   (12997) — portent la même classe `.dedienne-form` et gardent donc leur
   habillage noir : la portée demandée est la page offre d'emploi, pas la
   classe.

   La double classe `.dedienne-form.elementor-element-177637a` n'est pas
   décorative : les règles du bloc ci-dessus valent (0,1,1) et portent toutes
   `!important`. Il faut monter d'un cran en spécificité pour les dépasser.

   Cette règle remplace un `#wpcf7-f127759-p128335-o1 .wpcf7-submit` qui
   n'orangeait le bouton d'envoi que sur UNE offre — celle du post 128335,
   « Ground Support Equipment Technician ». Le sélecteur d'identifiant CF7
   contient l'ID du post conteneur : il ne pouvait pas couvrir les autres.
   ========================================================================== */

/* Bordures des champs : orange de marque, en lieu et place du noir hérité.
   #FE5000 est la couleur « Primary » du kit ; le widget, lui, tire sa
   `input_border_color` de la couleur « Accent » (#000000) — sans effet ici,
   les règles `.dedienne-form` la couvrent déjà en `!important`. */
.dedienne-form.elementor-element-177637a input[type="text"],
.dedienne-form.elementor-element-177637a input[type="email"],
.dedienne-form.elementor-element-177637a .mdc-text-field--textarea {
    border: 1px solid #fe5000 !important;
}

/* Double filet du textarea : deux traits se superposaient à 1px d'écart.
   L'extérieur vient de `.mdc-text-field--textarea`, bordé par le bloc
   ci-dessus ; l'intérieur est le `.mdc-notched-outline` de Material Design,
   qui dessine son propre contour en rgba(0,0,0,.24) sur ses trois fragments.
   On neutralise la couleur du contour interne plutôt que sa bordure : la
   largeur est conservée, donc la géométrie du champ et la découpe du label
   flottant ne bougent pas. */
.dedienne-form.elementor-element-177637a .mdc-notched-outline__leading,
.dedienne-form.elementor-element-177637a .mdc-notched-outline__notch,
.dedienne-form.elementor-element-177637a .mdc-notched-outline__trailing {
    border-color: transparent !important;
}

/* Bouton « Select file » du champ CV : 126x51px, à cause d'un `padding`
   15px/10px et d'un corps à 16px hérités de `.qbutton`, classe du thème
   borgholm déposé. Ramené à une action secondaire discrète, bordée d'orange
   comme les champs qu'elle accompagne. Le sélecteur d'identifiant l'exige :
   `.qbutton` et `.button-primary` arrivent avec leurs propres déclarations. */
.dedienne-form.elementor-element-177637a #mfcf7_zl_add_file {
    width: auto !important;
    padding: 7px 16px !important;
    font-size: 12px !important;
    line-height: 1.5 !important;
    letter-spacing: 0.5px !important;
    text-transform: uppercase !important;
    background-color: #fff !important;
    border: 1px solid #fe5000 !important;
    border-radius: 0 !important;
    color: #1d1d1d !important;
    cursor: pointer;
}

.dedienne-form.elementor-element-177637a #mfcf7_zl_add_file:hover {
    background-color: #fe5000 !important;
    color: #fff !important;
}

/* Bouton d'envoi : orange et centré. Le centrage se pose sur le conteneur
   `.cf7md-submit`, qui est déjà un `display:flex` en ligne — `justify-content`
   suffit, là où une marge automatique sur le bouton devrait composer avec le
   `margin-top:20px` du bloc ci-dessus et avec le spinner frère (masqué au
   repos, affiché pendant l'envoi). */
.dedienne-form.elementor-element-177637a .cf7md-submit {
    position: relative;
    justify-content: center;
}

/* Le `.wpcf7-spinner` de Contact Form 7 est seulement `visibility:hidden` au
   repos : il garde sa boîte de 24px et ses 2x24px de marge dans la ligne flex,
   ce qui décalait le bouton de 36px vers la gauche — centré sur « bouton +
   spinner », pas sur le conteneur. On le sort du flux au lieu de le masquer :
   le témoin d'envoi reste affiché, à droite du bouton, pendant la soumission. */
.dedienne-form.elementor-element-177637a .wpcf7-spinner {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    margin: 0;
}

/* `position` et `overflow` ne sont PAS décoratifs ici : ils réparent un débord
   horizontal de toute la page en dessous de ~690px de large. Détail plus bas. */
.dedienne-form.elementor-element-177637a .wpcf7-submit {
    position: relative;
    overflow: hidden;
    padding: 11px 28px !important;
    font-size: 13px !important;
    background-color: #fe5000 !important;
    color: #fff !important;
}

/* ==========================================================================
   Débord horizontal sous ~690px — barre blanche le long de la page

   Signalé par Jérém : entre 300 et 700px de large, une bande blanche apparaît
   au bord de toute la page et grossit à mesure que la fenêtre rétrécit.

   Mesuré : à 500px de fenêtre, `document.scrollWidth` vaut 640 — la page défile
   de 140px à l'horizontale, et ces 140px sont vides, d'où la bande. Le défaut
   disparaît entièrement si l'on masque le widget de formulaire 177637a.

   ---- La cause ----

   La feuille du plugin Material Design pose, pour le halo du bouton :

     #cf7md-form .mdc-button::before,
     #cf7md-form .mdc-button::after {
         position: absolute;
         top: calc(-50%); left: calc(-50%);
         width: 200%; height: 200%;
     }

   Un disque deux fois plus grand que le bouton, centré sur lui. Material Design
   le suppose ancré ET rogné par `.mdc-button { position: relative; overflow:
   hidden }` — deux déclarations qui vivent dans `lib/material-components-web.
   min.css`, une feuille que le plugin **ne charge pas** sur le site public. Le
   bouton reste donc `position: static`.

   Faute de bloc positionné, le `::before` remonte au premier ancêtre positionné
   qu'il trouve : le widget Elementor `.elementor-element-177637a`, en
   `position: relative`. Ses 200% se calculent alors sur le WIDGET, pas sur le
   bouton : 780px de large pour un widget de 390, débordant de 195px de chaque
   côté. Il est invisible (`opacity: 0`) mais il compte dans la largeur
   défilable du document.

   Au-dessus de ~690px de fenêtre, la marge droite de la page absorbe ce
   débordement. En dessous, il pousse `document.scrollWidth` au-delà du
   viewport — d'où l'apparition à 690px et la croissance jusqu'à ~500px.

   ---- Pourquoi ces deux déclarations et pas un `overflow: hidden` sur un
        conteneur ----

   Masquer le débord sur un ancêtre laisserait le disque mal dimensionné et
   coûterait tout `position: sticky` dans ce sous-arbre. Rendre au bouton son
   `position: relative` remet le halo à SA taille (183px au lieu de 780), et
   l'`overflow: hidden` le rogne — c'est exactement le couple que Material
   Design attend, et que la feuille manquante aurait fourni.

   Vérifié à 320, 360, 500, 600, 700, 900 et 1440px : `document.scrollWidth`
   est redevenu égal à la largeur du viewport.

   Portée limitée à la page offre d'emploi, comme les règles ci-dessus. La page
   Contact (11768) porte le même défaut, avec un débord de 190px à 500px de
   fenêtre ; elle n'est pas traitée ici.
   ========================================================================== */

/* Le survol du bloc générique repeint en orange sur orange, soit aucun retour
   visuel une fois l'état au repos déjà orange. On assombrit. */
.dedienne-form.elementor-element-177637a .wpcf7-submit:hover {
    background-color: #d94500 !important;
    color: #fff !important;
}

/* ==========================================================================
   Bouton d'envoi du formulaire Careers — orange, flèche qui dépasse

   Signalé par Jérém : sur la production, « SUBMIT » est orange et sa flèche sort du bouton à
   droite. Ici le formulaire 16448 émet un `<input type="submit">`, qui n'accepte ni
   `::before` ni `::after` : la flèche est donc peinte en arrière-plan de l'input, dans une zone
   de 36 px réservée à droite par le remplissage. Le rectangle orange s'arrête avant cette zone
   (`100% - 36px`), ce qui rend la même forme quelle que soit la langue (SUBMIT, ENVIAR, 提交).
   La flèche est celle du site (même tête que le bouton du formulaire de recherche, plus haut :
   boîte de 13,2 x 11 et triangle tracé dans son SVG), cotée sur le bouton de la production :
   la tête commence à 12,8 px du bord orange, le trait finit à 18 px de ce bord. La boîte de la tête
   fait 12 px (même triangle, recentré) et non 11 : le champ fait 52 px de haut, 11 px centrés
   tomberaient à 20,5 et le rendu descendrait la tête d'un demi-pixel sous le trait.
   Cote de la production : Work Sans 11 px / 600 / 2,2 px d'interlettrage, remplissage 15 × 36 px,
   trait de 34 px dont la moitié blanche recouvre l'orange, pointe noire. Au survol, le trait
   s'allonge de 10 px (échelle 1,3 depuis la gauche, dégradé blanc 40 % vers noir 50 %) et la
   pointe suit de 10 px, en 0,2 s ; l'orange ne change pas, comme en production. Les 10 px de marge à droite l'accueillent dans la zone réservée.
   Portée : le widget 32cc82c, seule instance de ce formulaire (page Careers 12997).
   ========================================================================== */

.dedienne-form.elementor-element-32cc82c .wpcf7-submit {
    padding: 15px 72px 15px 36px !important;
    border: 1px solid transparent !important;
    background-color: transparent !important;
    background-image:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13.2 12'%3E%3Cpolygon fill='%23000' points='4.1,3.25 7.5,6 4.1,8.75'/%3E%3C/svg%3E"),
        linear-gradient(90deg, #fff 50%, #000 50%),
        linear-gradient(#fe5000, #fe5000) !important;
    background-repeat: no-repeat !important;
    background-position: right 10px center, right 18px center, left center !important;
    background-size: 13.2px 12px, 34px 2px, calc(100% - 36px) 100% !important;
    transition: background-position 0.2s ease-in-out, background-size 0.2s ease-in-out;
    color: #fff !important;
    font-family: "Work Sans", sans-serif !important;
    font-size: 11px !important;
    font-weight: 600 !important;
    letter-spacing: 2.2px;
    text-transform: uppercase;
    line-height: 22px;
    box-sizing: border-box;
    height: 54px;
}

.dedienne-form.elementor-element-32cc82c .wpcf7-submit:hover,
.dedienne-form.elementor-element-32cc82c .wpcf7-submit:focus-visible {
    background-image:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13.2 12'%3E%3Cpolygon fill='%23000' points='4.1,3.25 7.5,6 4.1,8.75'/%3E%3C/svg%3E"),
        linear-gradient(90deg, #fff 40%, #000 50%),
        linear-gradient(#fe5000, #fe5000) !important;
    background-position: right 0 center, right 7.8px center, left center !important;
    background-size: 13.2px 12px, 44.2px 2px, calc(100% - 36px) 100% !important;
    background-color: transparent !important;
    color: #fff !important;
}
#cf7md-form .mdc-text-field .mdc-line-ripple, #cf7md-form .mdc-select:not(.mdc-select--disabled) .mdc-select__native-control:focus ~ .mdc-line-ripple, #cf7md-form .mdc-checkbox .mdc-checkbox__native-control:enabled:checked ~ .mdc-checkbox__background, #cf7md-form .mdc-checkbox .mdc-checkbox__native-control:enabled:indeterminate ~ .mdc-checkbox__background, #cf7md-form .mdc-checkbox::before, #cf7md-form .mdc-checkbox::after, #cf7md-form .mdc-radio::before, #cf7md-form .mdc-radio::after, #cf7md-form .mdc-switch.mdc-switch--checked .mdc-switch__track, #cf7md-form .mdc-switch.mdc-switch--checked .mdc-switch__thumb, #cf7md-form .mdc-switch.mdc-switch--checked .mdc-switch__thumb-underlay::before, #cf7md-form .mdc-switch.mdc-switch--checked .mdc-switch__thumb-underlay::after, #cf7md-form .mdc-switch.mdc-switch--checked .mdc-switch__thumb, #cf7md-form .mdc-switch.mdc-switch--checked .mdc-switch__thumb-underlay::before, #cf7md-form .mdc-switch.mdc-switch--checked .mdc-switch__thumb-underlay::after, #cf7md-form .mdc-switch:not(.mdc-switch--checked) .mdc-switch__thumb-underlay::before, #cf7md-form .mdc-switch:not(.mdc-switch--checked) .mdc-switch__thumb-underlay::after{
    background-color: #fe5000;
}

.search-form-popup .elementor-search-form__input{
    padding-left:0 !important;
}
/* Le `cursor: pointer` qui vivait ici a rejoint le bloc « Popup de recherche » plus bas, avec le
   reste de ce bouton : une seule adresse pour un seul element. */
.close-popup svg{
    transform: translate(13px, -11px);
    transition:all 0.3s ease-in-out;
}
.close-popup .elementor-icon{
    outline:none !important;
}
.close-popup .elementor-icon:hover{
    background-color:#fe5000 !important;
    svg{
        fill:#fff !important;
        transform: translate(13px, -11px) rotate(180deg);
    }
}
/* ==========================================================================
   Navigation principale — alignement sur la production

   Relevé sur www.dedienne-aero.com (tools/migration-check/typo-audit.mjs) :
   niveau 1   Work Sans 11px / 500, majuscules, interlettre 2px, #1D1D1D
   sous-menu  Work Sans 13px / 500, casse normale, noir

   Ciblage volontairement restreint au widget 1588c77, le menu principal de
   l'en-tête 131024. L'en-tête local compte trois menus, là où la production n'en
   a qu'un :
     252893a  barre méta   texte clair (#F5F5F5) sur fond sombre  -> NE PAS TOUCHER,
              lui appliquer #1D1D1D le rendrait illisible
     1588c77  menu principal, déjà noir sur fond clair            -> aligné ici
     637f8e2  menu secondaire, gris, casse normale                -> hors sujet

   En surcharge CSS plutôt qu'en modification des réglages Elementor de l'en-tête :
   réversible, et sans toucher au template construit en amont.
   ========================================================================== */

/* Le préfixe « body » n'est pas décoratif : Elementor génère
   .elementor-131024 .elementor-element.elementor-element-1588c77
   .elementor-nav-menu--main .elementor-item { color: var(--e-global-color-accent) }
   soit cinq classes. La couleur du menu est donc pilotée par la couleur d'accent du
   kit (#000000). Plutôt que de changer cette couleur globale — utilisée aussi par le
   corps de texte et les boutons — on dépasse la spécificité d'un sélecteur de type.
   Sans cela, seules la taille, la graisse et l'interlettrage s'appliquaient, et la
   couleur restait noire. */
body .elementor-131024 .elementor-element.elementor-element-1588c77 .elementor-nav-menu--main .elementor-item {
    font-family: "Work Sans", sans-serif;
    font-size: 11px;
    font-weight: 500;
    line-height: 19.06px;
    letter-spacing: 2px;
    text-transform: uppercase;
    color: #1d1d1d;
}

body .elementor-131024 .elementor-element.elementor-element-1588c77 .elementor-nav-menu--dropdown a.elementor-item,
body .elementor-131024 .elementor-element.elementor-element-1588c77 .elementor-nav-menu--dropdown a.elementor-sub-item {
    font-family: "Work Sans", sans-serif;
    font-size: 13px;
    font-weight: 500;
    line-height: 28px;
    letter-spacing: normal;
    text-transform: none;
    color: #000;
}

/* ==========================================================================
   Corps de texte — alignement sur la production

   Relevé : la production sert un corps à 15px / interlignage 1,733, mais un
   `p { font-size: 14px }` NU (zéro classe) venant du main.css du thème borgholm,
   qui disparaît avec lui. Les deux valeurs vont ensemble : le kit porte désormais
   15px sur le corps, cette règle rétablit les 14px des paragraphes.

   Sans elle, tous les paragraphes du site passaient de 14 à 15px. Avec seulement
   le corps à 14px (état antérieur), c'était l'interlignage hérité des conteneurs
   qui divergeait — mesuré 23,8px contre 25,995px, soit 2 à 3px d'écart de hauteur
   par bloc.

   Spécificité volontairement nulle, comme en production : tout réglage de
   typographie posé sur un widget doit continuer de primer.
   ========================================================================== */

p {
    font-size: 14px;
    /* Interlignage SANS UNITÉ, et non hérité : le kit pose « 1.733em » sur le corps,
       valeur qui se résout en 25,995px figés (15px x 1,733) puis s'hérite en pixels.
       Un paragraphe à 14px recevait donc 25,995px au lieu des 24,262px de la
       production, qui recalcule le ratio sur la taille propre de l'élément.
       C'est le même défaut d'unité que celui corrigé sur les titres h1–h6. */
    line-height: 1.733;
}

/* ==========================================================================
   Listes de contenu — alignement sur la production

   Relevé sur /ground-support-equipment/ : les listes à puces d'un panneau d'onglets
   mesurent `margin: 0 0 21px ; padding: 0` en production, contre `margin: 14px 0 ;
   padding-left: 40px` en local. Les valeurs locales sont celles du navigateur : rien
   ne les surchargeait, parce que hello-elementor ne remet pas les listes à plat.

   La production les tient de deux règles NUES du main.css de borgholm, qui disparaît
   avec le thème :

       ol, ul                        { list-style-position: inside; margin-bottom: 1.5em; padding: 0 }
       ol:not(.wp-block), ul:not(.wp-block) { margin: 0 0 1.5em }

   `list-style-position: inside` est la moitié qui compte : la puce passe DANS la boîte
   de contenu, donc le texte démarre au bord gauche du bloc au lieu d'être décalé de
   40px, et la largeur utile de chaque `li` reste celle du conteneur (mesuré 424,56px
   contre 384,56px).

   ---- Portée volontairement restreinte ----

   La règle d'origine visait tous les `ul`/`ol` du document, menus compris, et les
   composants de qode remettaient ensuite leurs propres listes à plat. Ici les
   composants d'Elementor (menu de navigation, liste d'icônes, Swiper) portent tous une
   classe sur leur `ul` ; les listes rédactionnelles, elles, n'en ont aucune. Le
   `:not([class])` sépare exactement les deux, sans avoir à énumérer les composants.

   `:where()` maintient la spécificité au niveau de la règle d'origine : tout réglage
   posé sur un widget continue de primer.

   Concerne 66 contenus par `post_content` et 10 par `_elementor_data`.
   Relève de la réconciliation CSS globale (lot 5b), traitée ici parce que mesurée.
   ========================================================================== */

:where(.elementor-widget-container, .entry-content) ol:not([class]),
:where(.elementor-widget-container, .entry-content) ul:not([class]) {
    list-style-position: inside;
    margin: 0 0 1.5em;
    padding: 0;
}

/* ==========================================================================
   Liens de contenu — la couleur de base, partie avec borgholm
   ==========================================================================

   Signalé par Jérém sur /p-i/trent-xwb-new-wes/ : le lien « Engine Stands » du fil d'Ariane
   sortait en BLEU SOULIGNÉ là où la production le rend en noir, orange au survol.

   Ce n'est pas un défaut de ce gabarit : c'est une règle NUE de borgholm qui a disparu avec la
   pile. Relevée dans le CSS agrégé de la production, en interrogeant le navigateur :

       a, p a           { color: #000; transition: color .2s ease-out; text-decoration: none }
       a:hover, p a:hover  { color: #F23801 }        <- règle n°78 de la cascade
       a:hover          { color: #FE5000 }           <- règle n°305, et c'est ELLE qui gagne

   Les deux `a:hover` ont la même spécificité : la dernière l'emporte. Le survol effectif est donc
   #FE5000, ce que la mesure confirme — `rgb(254, 80, 0)` relevé au survol réel. Ne pas se fier à
   la première règle trouvée quand plusieurs se disputent une propriété à spécificité égale.

   ---- L'ampleur : ce n'est PAS un défaut d'une page ----

   Nombre de liens rendus en `rgb(0, 0, 238)` — le bleu du navigateur, donc sans aucune couleur
   d'auteur — relevé sur huit pages :

                        production   local
       /                      0        5
       /engine-stands/        0        5
       /blog/                 0       10
       /contact/              0        5
       /p-i/trent-xwb-…/      0       12
       /civil-tooling/        0       16
       /company/              0       11
       /tooling-services/     0       14

   Tout lien rédactionnel du site était concerné.

   ---- Pourquoi c'est sans risque, et comment ça a été vérifié ----

   Une règle de TYPE nue l'emporte sur l'héritage : un lien qui tenait sa couleur d'un parent —
   le blanc de la barre du haut, par exemple — la perdrait. Le risque est réel et il a été mesuré,
   pas supposé : la règle a été injectée sur les huit pages, puis la couleur calculée de CHAQUE
   lien comparée avant/après. Résultat : elle ne change que les liens bleus, et **zéro** lien
   change depuis une autre couleur. Les composants d'Elementor posent tous leur couleur derrière
   au moins une classe, ce qui bat une règle de type.

   `!important` serait la seule façon de casser cela — un premier essai de mesure en portait un
   par erreur et annonçait 64 liens touchés par page, dont les libellés blancs de la barre du
   haut. La production n'en met pas ; ce bloc non plus.

   `p a` est repris de la production bien que `a` seul suffise ici : les deux sélecteurs y sont, et
   s'en écarter inviterait un écart au prochain relevé.

   Le SOULIGNEMENT, lui, est déjà conforme : il ne vient pas d'une règle mais du contenu —
   `<span style="text-decoration: underline">` écrit à la main dans le widget, servi à l'identique
   des deux côtés. Une décoration posée sur un ancêtre en ligne se peint à travers ses descendants
   et ne peut pas être annulée par eux. Le `text-decoration-line` calculé du lien vaut `none` en
   production comme en local.
   ========================================================================== */

a,
p a {
    color: #000;
    transition: color .2s ease-out;
}

a:hover,
p a:hover {
    color: #fe5000;
}

/* ==========================================================================
   Liste d'icônes alignée à gauche — la marge haute de 90 px
   ==========================================================================

   Signalé par Jérém sur /p-i/trent-xwb-new-wes/ : la liste d'ancres `4970bc73` est collante, et
   ses liens passaient SOUS l'entête.

   La cause n'est pas le collage — il est déjà juste. Relevé à trois positions de défilement, la
   section est `position: fixed; top: 100px` des DEUX côtés. Le seul écart est la MARGE :

                        production        local
       marge              90px 0 0          0
       y au repos         677,27            587,25      <- 90,02 d'écart
       y une fois collée  190               100         <- sous l'entête, qui occupe 32 à 122

   Une seule valeur explique les deux positions, et la corriger règle le repos ET le collage.

   La règle vient de borgholm, relevée dans le CSS agrégé de la production :

       .elementor-align-left.elementor-widget-icon-list { margin-top: 90px !important; z-index: 100 !important }

   Elle est reprise VERBATIM, sélecteur et priorité compris. C'est une règle large — tout widget
   « liste d'icônes » aligné à gauche —, mais c'est exactement ce que la production applique, et à
   exactement les mêmes éléments. Vérifié sur huit pages : un seul widget concerné par page, sur les
   quatre pages qui en portent un (`/p-i/…`, `/civil-tooling/`, `/company/`, `/tooling-services/`),
   et la production y met bien 90px là où le local mettait 0. Les quatre autres pages n'en ont aucun.

   Le local n'était donc pas « en avance » de 90 px sur ces pages : il était en RETARD, et cette
   règle rapproche.

   ---- `!important` n'est pas ici un raccourci de spécificité ----

   C'est la seule réponse possible à un style INLINE, et il a fallu deux mesures pour le voir.
   Sans lui, la marge s'appliquait au repos (y=677,25 contre 677,27 en production) et retombait à
   ZÉRO une fois la section collée. Le collant d'Elementor écrit en effet, sur l'élément :

       position: fixed; width: 145px; margin-top: 0px; margin-bottom: 0px; top: 100px; …

   Les DEUX côtés reçoivent ce même inline — relevé sur l'attribut `style` en production comme en
   local. Et pourtant la production calcule `margin-top: 90px`. Un inline ne se laisse battre que
   par une déclaration `!important` : la production en porte un, vérifié par
   `getPropertyPriority()` sur la règle. Sa position collée de 190 px, c'est donc `top: 100` plus
   cette marge de 90 — et sans la priorité, la liste revenait se cacher à 100, sous un entête qui
   occupe 32 à 122.

   `z-index: 100` est repris de la même règle et avec la même priorité. Il ne dégage rien par
   lui-même : la section passe sous l'entête des deux côtés (z-index 200 en local, 104 en
   production). C'est bien la marge qui la sort de dessous, pas l'empilement.
   ========================================================================== */

.elementor-align-left.elementor-widget-icon-list {
    margin-top: 90px !important;
    z-index: 100 !important;
}

/* ==========================================================================
   Bouton à taille fixe — le disque « IN STOCK »
   ==========================================================================

   Signalé par Jérém sur /p-i/trent-xwb-new-wes/ : le bouton sortait « ratatiné », texte noir, là
   où la production affiche un disque orange de 120 px à texte blanc.

   Le défaut avait DEUX causes distinctes, et une seule est traitée ici.

   ---- Cause 1, la géométrie : traitée en PHP ----

   Les 120 x 120 et le centrage venaient de contrôles de **Happy Addons** (`ha_fixed_size_toggle`,
   `ha_width`, `ha_height`), greffon absent depuis la migration. Les valeurs dorment en base et
   Elementor ne génère aucun CSS pour un contrôle non déclaré. Les contrôles sont redéclarés par
   `Dedienne\Elements\Bouton_Taille_Fixe`, qui pose aussi la classe `dedienne-button-fixed` sur
   laquelle ce bloc s'accroche. Voir l'en-tête de class-bouton-taille-fixe.php.

   ---- Cause 2, la couleur et la typographie : ici ----

   Ce n'est pas un réglage manquant : c'est le KIT local qui stylise `.elementor-button` alors que
   celui de la production ne le fait pas. Règle générée dans `uploads/elementor/css/post-6675.css` :

       .elementor-kit-6675 button, … , .elementor-kit-6675 .elementor-button {
           font-size: 13px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.07em;
           color: var( --e-global-color-accent );          <- #000000
           background-color: var( --e-global-color-text );
           border-radius: 0; padding: 17px 30px }

   Ses deux classes battent le `.elementor-button { color: #FFF; font-size: 15px; line-height: 1 }`
   d'Elementor, qui est ce que la production sert. D'où le texte noir en 13px capitales.

   Relevé de la production sur ce bouton : `#FFFFFF`, 15px / 400, interligne 15px,
   interlettrage normal, casse d'origine. Fond `#FE5000`, rayon 100px et remplissage
   `0 10px 10px` étaient DÉJÀ justes — ils viennent des réglages du widget, que le local a bien.

   ---- Portée volontairement limitée aux boutons à taille fixe ----

   Les 20 boutons concernés sont tous le MÊME — « IN STOCK », 120 x 120, rayon 100, sans couleur
   ni typographie propre — recensés en base. Ce bloc les couvre tous et rien d'autre.

   Il serait tentant de corriger le kit à la place, puisque c'est lui la cause. **Ce serait un
   autre chantier, et la mesure dit pourquoi** : la valeur du kit ne correspond à AUCUNE des deux
   familles de boutons de la production.

       boutons natifs de la production (IN STOCK, DOWNLOAD DATASHEET, CORPORATE BROCHURE,
       TOOLING SERVICES BROCHURE)              15 à 16px / 400, casse d'origine, sans interlettrage
       boutons qodef convertis vers Elementor  11px / 600, capitales, +2,2px
       ce que le kit impose                    13px / 500, capitales, +0,07em

   Toucher au kit déplacerait donc les deux familles à la fois, dont une — les boutons convertis —
   n'a rien à voir avec ce signalement. Et la référence typographique du chantier est le kit
   normalisé : le corriger est une décision, pas un détail. **À trancher par Jérém**, l'écart est
   consigné dans SUIVI-MAINTENANCE.md.

   `body` en préfixe : le sélecteur du kit compte deux classes, celui-ci en compte deux plus un
   sélecteur de type. Sans cela l'égalité de spécificité laisserait l'ordre de chargement décider,
   ce qui est exactement le genre d'équilibre qui se casse au prochain changement d'ordre.
   ========================================================================== */

body .dedienne-button-fixed .elementor-button {
    color: #fff;
    font-size: 15px;
    font-weight: 400;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
}

/* ==========================================================================
   Portfolio-item « article » — gouttière du modèle Elementor

   Le modèle « Portfolio Item — Article » (elementor_library 131750, condition
   in_portfolio-category = blog, 9 contenus) porte une section de 1130 px et deux colonnes
   à 75 / 25 %. Il ne manque que les 15 px de gouttière de chaque côté.

   Géométrie reprise, relevée sur /p-i/how-to-work-the-torke-to-properly-tighten-a-nut-to-a-bolt/ :

       .qodef-content-grid   1100 centré (x=170), padding 300px 0 100px
       .qodef-grid-inner     1130 (x=155)   <- marges négatives de 15px sur le cadre
       .qodef-col--9         847,50   padding 0 15px  ->  contenu  817,50  (x=170)
       .qodef-col--3         282,50   padding 0 15px  ->  aside    252,50  (x=1017,5)

   847,50 et 282,50 valent exactement 75 % et 25 % de 1130. Une section Elementor de
   1130 px centrée tombe au même x=155 que la rangée de qode : la marge négative devient
   inutile, seule la gouttière reste à poser.

   Avant : le contenu occupait toute la fenêtre, 1440 px, faute de conteneur — une colonne
   interne mesurait 550 px contre 358,75 en production.
   ========================================================================== */

.dedienne-pi-article .dedienne-pi-content > .elementor-widget-wrap,
.dedienne-pi-article .dedienne-pi-sidebar > .elementor-widget-wrap {
    padding: 0 15px;
}

/* ==========================================================================
   Images — alignement vertical

   Borgholm posait `img { vertical-align: middle; border-style: none }`, une règle nue que
   hello-elementor n'a pas. Sans elle, une image en flux `inline` repose sur la ligne de
   base et traîne l'espace du jambage sous elle : mesuré sur les trois images de
   `tooling-lines-sidebar`, 191 px en local contre 183 en production, soit 8 px par image.

   Règle globale et volontairement nue, comme l'originale : elle concerne toutes les
   images du site, pas seulement la colonne latérale.

   Relève de la réconciliation CSS globale (lot 5b), traitée ici parce que mesurée.
   ========================================================================== */

img {
    vertical-align: middle;
    border-style: none;
}

/* ==========================================================================
   Paragraphes — la règle globale de borgholm

   Production : `p { margin: 10px 0; line-height: 1.733em }`, dans
   borgholm/assets/css/main.css:1961. La hauteur de ligne arrivait déjà par le kit ; la
   MARGE, non — et le thème enfant la remettait même à zéro, par un
   `.elementor-widget-container p { margin-block: 0 }` posé lors d'une passe antérieure du
   chantier (ligne 97, dont `p` est maintenant retiré). Une remise à zéro globale, jamais
   confrontée à la référence.

   ---- Ce que le changement donne ----

   Mesuré sur onze pages à 1440 par injection au vol, avant d'écrire : huit pages se
   rapprochent de la production, aucune ne s'en éloigne. Sur l'offre d'emploi, le bloc de
   contenu passe de 848,75 à 1078,75 contre 1079,30 en production — exact au demi-pixel, sur
   26 paragraphes.

   ---- CORRECTION du 2026-08-13 : les écarts d'abord annoncés étaient faux ----

   Ce bloc portait un tableau d'« écarts à la production » de 31 à 117 px après changement.
   Ces chiffres comparaient `#qodef-page-inner` en production — le cadre du THÈME, qui porte
   son propre remplissage — à `[data-elementor-type]` en local, le document Elementor. Deux
   éléments différents : ~130 px de remplissage de cadre étaient comptés comme un écart.

   Repris avec le MÊME sélecteur des deux côtés, sur les sept pages dont les documents se
   correspondent réellement :

       /values/                       -0,47
       /locations/                    -0,76
       /the-dedienne-world/           +4,55
       /ground-support-equipment/    -23,15
       /nacelle-tooling/             -27,04
       /engine-stands/               -27,08
       /contact/                     +38,84

   Et vérifié section par section sur /values/ : les NEUF sections de la page concordent, pour
   un cumul de 0,48 px. La page était déjà juste.

   Trois pages ne se comparent pas à ce niveau, parce que le document Elementor local absorbe
   ce que la production rend en dehors du sien — et c'est voulu, les cadres du thème ayant
   disparu : /blog/ (+210,75, soit le remplissage 30/181 de sa section), l'offre d'emploi
   (+293,45, son bandeau de titre de 210 plus la gouttière de 90) et une page catalogue
   (+87,31, son bloc de titre). Sur ces trois-là, seule la comparaison bloc à bloc a un sens.

   La direction du changement, elle, reste établie : le même sélecteur servait avant et après
   l'injection, donc le fait que huit pages gagnent ne dépend pas de cette erreur.

   ---- Pourquoi /blog/ ne bouge pas, et pourquoi c'est rassurant ----

   Les cartes de /blog/ ne contiennent AUCUN `<p>` : leur extrait est un widget dont le texte
   sort nu. Les blocs déjà validés au pixel — extrait à 97, carte à 872,38 — ne peuvent donc
   pas bouger. C'est ce qui rend le changement sûr : il ne touche que là où il y a vraiment
   des paragraphes.

   Règle nue, comme l'originale, et sans `!important` : elle doit rester surchargeable par les
   réglages d'instance d'Elementor.

   ---- Ce que la règle n'atteint PAS, volontairement ----

   Deux contextes gardent leurs paragraphes à zéro, parce qu'Elementor les remet à zéro avec
   une classe — relevé sur /values/ : `.elementor-icon-box-content` (7 paragraphes) et huit
   `.elementor-widget-container` de widgets natifs. Une règle à deux classes les rattraperait
   et rendrait /values/ à 31 px de la production au lieu de 91.

   Elle n'est pas écrite, et c'est un choix : ces blocs sont des widgets NATIFS posés lors
   d'une passe antérieure à la place de widgets borgholm, si bien qu'il n'existe pas d'élément
   comparable en production. Forcer 10 px là-dedans serait reproduire une règle sur un
   balisage qui n'est pas celui de la référence — exactement le geste non mesuré que ce bloc
   remplace. Cela se traite bloc par bloc, contre la production, pas par une règle générale.

   Relève de la réconciliation CSS globale du lot 5b.
   ========================================================================== */

p {
    margin: 10px 0;
}

/* ==========================================================================
   Cartes portfolio-item — alignement du Loop Grid natif sur la production

   `borgholm_core_portfolio_list` a été converti en Loop Grid Elementor plutôt que repris :
   ses filtres et son « load more » étaient de l'AJAX borgholm, la couche même que la
   migration supprime. Le balisage change donc, et ces règles alignent le rendu.

   Le modèle de carte est « Portfolio Card — Square » (elementor_library, type loop-item) :
   container.dedienne-pc > image.dedienne-pc-image + container.dedienne-pc-content
   ( .dedienne-pc-terms, .dedienne-pc-title ).

   Valeurs relevées sur /engine-stands/, instance 78726da1 :

       item        386,656 de large, padding 0 10px  ->  contenu 366,656
       image       366,656 carrée, overflow hidden
       contenu     margin 22px 0 0, padding 0 0 10px, hauteur 62,67
       catégorie   Work Sans 11px / 500, interligne 20, +2,2px, capitales, #9e9e9e
       titre       Work Sans 25px / 300, interligne 26,675, #000

   ---- L'animation « tilt », reprise à la déclaration près ----

   Au repos, la catégorie et le titre sont `opacity: 0`, `visibility: hidden` et
   `rotateZ(5deg) translateY(8px)` avec origine à gauche ; au survol de la carte ils
   reviennent à plat en 1 s, le titre avec 0,08 s de retard. La carte ne montre donc que
   l'image tant qu'on ne la survole pas.

   Ces valeurs viennent des règles `qodef-hover-animation--tilt` de borgholm-core, et non
   d'une lecture de la matrice de transformation relevée : `matrix(0.996195, 0.0871557, …)`
   se laisse deviner en rotation de 5 degrés, mais pas le `translateY(8px)` ni l'origine.

   L'instance servie sous 1025 px porte `info_below_disable_hover_animation` en base : son
   texte est visible en permanence, sans inclinaison. D'où la classe
   `dedienne-portfolio-grid--statique`, posée par la conversion.
   ========================================================================== */

.dedienne-pc-image img {
    display: block;
    width: 100%;
}

/* Le recadrage carre ne concerne QUE /engine-stands/. Sur /the-dedienne-world/ l'image garde
   son ratio d'origine — c'est precisement ce qui donne des hauteurs inegales, donc le
   masonry. Une regle non portee ecrasait les 267,109 px de haut a 212. */
.dedienne-portfolio-grid--carre .dedienne-pc-image img {
    aspect-ratio: 1;
    object-fit: cover;
}

/* ---- L'effet de perspective au survol ----

   C'est le cœur visuel de ces cartes, et il tenait en cinq déclarations de borgholm-core que
   j'avais omises au premier passage : seule la partie TEXTE de « tilt » était reprise.
   Le cadre s'incline de -9 degrés autour de l'axe vertical en reculant de 5 %, tandis que la
   photo grossit de 10 % à l'intérieur — d'où le `perspective` sur le parent et
   l'`overflow: hidden` sur le cadre, sans lesquels il n'y a ni profondeur ni recadrage.

   Les deux durées sont VOLONTAIREMENT différentes, 0,8 s pour le cadre et 2 s pour la photo :
   c'est ce décalage qui donne l'impression de profondeur.

   DEUX classes sur l'élément, encore : le widget d'image d'Elementor pose sa propre
   transition depuis un <style> en ligne, donc postérieur à cette feuille, et gagnait à
   spécificité égale. Même mécanisme que sur la barre de filtres. */

.dedienne-pc-image {
    perspective: 1000px;
}

.dedienne-pc-image.elementor-widget-image .elementor-widget-container {
    overflow: hidden;
    transform: scale(1) rotateY(0);
    transition: all .8s cubic-bezier(.475, .425, 0, .995);
    will-change: transform;
}

.dedienne-pc-image.elementor-widget-image img {
    transform: scale(1);
    transition: transform 2s cubic-bezier(.19, 1, .22, 1);
    will-change: transform;
}

.dedienne-pc:hover .dedienne-pc-image.elementor-widget-image .elementor-widget-container {
    transform: scale(.95) rotateY(-9deg);
}

.dedienne-pc:hover .dedienne-pc-image.elementor-widget-image img {
    transform: scale(1.1);
}

/* `post-info` est le seul widget natif qui liste les termes d'un contenu, et il impose une
   icône — ici une étiquette. La production n'affiche que les liens, en ligne.

   DEUX classes sur l'élément, encore. C'est la troisième fois dans ce fichier, et le
   mécanisme est toujours le même : les feuilles de widget d'Elementor
   ( widget-icon-list.min.css ici ) sont chargées APRÈS celle du thème enfant, donc à
   spécificité égale elles gagnent. `.elementor-widget .elementor-icon-list-icon` posait
   `display: flex` et l'icône restait visible malgré la règle.

   Règle de travail pour ce fichier : toute surcharge d'un widget Elementor doit compter
   une classe de plus que la sienne, et `winning-rule.mjs` le dit en une commande. */
.dedienne-pc-terms.elementor-widget .elementor-icon-list-icon {
    display: none;
}

/* Elementor joint les termes par « , » ECRIT EN DUR dans son PHP
   ( `echo implode( ', ', $terms_list )`, post-info.php ligne 1054 ) : aucun reglage ne
   l'enleve, et le CSS ne supprime pas un noeud de texte. On le rend invisible en mettant la
   liste a `font-size: 0` et en redonnant leur taille aux seuls termes, puis on retablit
   l'ecart par une marge.

   L'enjeu n'est pas la virgule mais la LIGNE : « BLOG Tooling Expertise » tient tout juste
   dans les 212 px d'une carte de /the-dedienne-world/. Les deux caracteres en trop la
   faisaient passer sur deux lignes, soit 26 px de plus par carte — 436 au lieu de 410. */
.dedienne-pc-terms .elementor-post-info__terms-list {
    font-size: 0;
}

.dedienne-pc-terms .elementor-post-info__terms-list-item {
    font-size: 11px;
}

.dedienne-pc-terms .elementor-post-info__terms-list-item:not(:last-child) {
    /* La virgule masquee laisse deja l'espace de son noeud de texte : aucune marge a
       ajouter, et 3 px suffisaient a faire deborder la ligne. */
    margin-right: 0;
}

.dedienne-pc-terms .elementor-post-info__terms-list-item {
    line-height: 20px;
}

/* Une seule ligne, et la hauteur de ligne du conteneur plutot que celle des termes : en
   production le bloc mesure 26 px — l'interligne herite de 25,995 — tandis que le terme
   lui-meme est a 20. Sans `nowrap`, deux termes sur une carte de 212 px basculaient sur
   deux lignes, ce qui ajoutait 26 px a CHAQUE carte. */
.dedienne-pc-terms .elementor-icon-list-item {
    /* 26 px est la hauteur relevee en production : l'interligne herite de 25,995 y forme le
       bloc, tandis que le terme lui-meme est a 20. La structure d'Elementor — liste a puces
       avec icone masquee — ne reproduit pas cette boite de ligne d'elle-meme et sortait a
       29 px ; la hauteur est donc posee, sur une valeur mesuree et non choisie. */
    line-height: 25.995px;
    height: 26px;
}

.dedienne-pc-terms .elementor-icon-list-item,
.dedienne-pc-terms .elementor-post-info__item--type-terms {
    /* `nowrap` seul elargissait la carte a 214,63 px dans une colonne de 212 et decalait le
       masonry : la largeur est donc bornee au meme endroit. */
    white-space: nowrap;
    overflow: hidden;
    max-width: 100%;
}

.dedienne-pc-terms .elementor-icon-list-items {
    margin: 0;
    padding: 0;
    list-style: none;
}

/* L'interligne de 20 px appartient au LIEN, pas a son conteneur : en production
   `.qodef-e-info-category` reste a l'interligne herite de 25,995 et mesure donc 26 px de
   haut, tandis que `.qodef-e-category` est a 20. Appliquer 20 aux deux ramenait le bloc a
   20 px et la carte entiere a 445,34 au lieu de 451,33. */
/* Portée aux TROIS cartes et non aux seules grilles : la typographie des catégories est la
   même sur le carrousel de l'accueil — 11px / 500, +2,2px, capitales, #9e9e9e, relevé sur
   `.qodef-e-category` des deux côtés. Les règles étant préfixées `.dedienne-portfolio-grid`,
   le carrousel n'en recevait aucune et affichait la typographie héritée. */
.dedienne-pc-terms,
.dedienne-pc-terms a,
.dedienne-pc-terms .elementor-post-info__terms-list-item {
    font-family: "Work Sans", sans-serif;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 2.2px;
    text-transform: uppercase;
    color: #9e9e9e;
}

.dedienne-pc-terms a,
.dedienne-pc-terms .elementor-post-info__terms-list-item {
    line-height: 20px;
}

.dedienne-portfolio-grid .dedienne-pc-title,
.dedienne-portfolio-grid .dedienne-pc-title a {
    font-family: "Work Sans", sans-serif;
    font-size: 25px;
    font-weight: 300;
    line-height: 26.675px;
    letter-spacing: normal;
    text-transform: none;
    color: #000;
}

.dedienne-portfolio-grid .dedienne-pc-title {
    margin: 0;
}

/* Titre ET catégorie sont deux liens distincts, chacun orange au survol de LUI-MÊME
   (EN L5, L31, ES L6, L31, CN L8, L39). Mesuré en production : #fe5000, 0,2 s ease-out.
   Le sélecteur du titre passe par `.elementor-heading-title` : la feuille du widget Titre
   force `color: inherit` sur ce lien avec une spécificité de 0,3,1. */
.dedienne-pc-title a,
.dedienne-pc-terms a {
    transition: color 0.2s ease-out;
}

.dedienne-pc-title .elementor-heading-title a:hover,
.dedienne-pc-terms a:hover {
    color: #fe5000;
}

/* Dans les grilles, la production passe le titre en orange dès que la CARTE est survolée
   (mesuré sur /the-dedienne-world/ : titre #fe5000, catégorie restée #9e9e9e). Le carrousel
   de l'accueil n'a pas ce comportement : seul le lien survolé change. */
.dedienne-portfolio-grid .dedienne-pc:hover .dedienne-pc-title .elementor-heading-title a {
    color: #fe5000;
}

/* Une fois la catégorie devenue un lien (EN L31, ES L31), la feuille du widget Liste d'icônes
   lui impose `font-size: inherit` avec une spécificité de 0,2,1, donc 0 px sous le conteneur
   qui masque la virgule. Le séparateur « / » est un `::after` du lien, comme en production. */
.dedienne-pc-terms .elementor-icon-list-item a.elementor-post-info__terms-list-item {
    font-size: 11px;
    line-height: 20px;
}

.dedienne-pc-terms a.elementor-post-info__terms-list-item:not(:last-child)::after {
    /* L'espace avant la barre est celui que le texte du lien porte en production. */
    content: " /";
}

/* ---- État au repos et survol ---- */

/* Logique INVERSÉE : l'inclinaison est l'état par défaut d'une carte, et on s'en exclut
   explicitement. Les règles étaient d'abord portées par `.dedienne-portfolio-grid`, si bien
   que le carrousel de l'accueil — qui ne porte pas cette classe — n'en recevait aucune : son
   titre restait visible et à plat, là où la production le cache au repos. Nommer ce qui a
   l'exception plutôt que ce qui a la règle évite de répéter l'oubli à chaque nouvelle carte. */

.dedienne-pc-terms,
.dedienne-pc-title {
    opacity: 0;
    visibility: hidden;
    transform: rotateZ(5deg) translateY(8px);
    transform-origin: left;
    transition: all 1s cubic-bezier(.475, .425, 0, .995);
    will-change: transform;
}

.dedienne-pc:hover .dedienne-pc-terms,
.dedienne-pc:hover .dedienne-pc-title {
    opacity: 1;
    visibility: visible;
    transform: rotateZ(0) translateY(0);
}

.dedienne-pc:hover .dedienne-pc-title {
    transition-delay: .08s;
}

/* L'exception : `info_below_disable_hover_animation` en base, sur la grille servie sous
   1025 px. Sans survol possible, le texte doit être lisible d'emblée. */
.dedienne-portfolio-grid--statique .dedienne-pc-terms,
.dedienne-portfolio-grid--statique .dedienne-pc-title {
    opacity: 1;
    visibility: visible;
    transform: none;
}

/* ---- La même exception, mais sur le critère de la LARGEUR ----

   Sous 1024 px il n'y a pas de survol : un écran tactile ne connaît que le contact, et
   Safari iOS n'émule `:hover` qu'après un premier appui — lequel suit le lien avant d'avoir
   rien révélé. Un titre caché au repos y est donc caché DÉFINITIVEMENT.

   borgholm ne rencontrait pas le problème sur le carrousel de l'accueil : il ne le servait
   pas sous 1025 px (`hide_tablet` + `hide_mobile` sur la section). En le rendant disponible
   partout — demande de Jérém — c'est à nous de traiter le cas qu'il s'épargnait.

   ---- Comment la production obtient ce même résultat sur ses grilles ----

   Elle DUPLIQUE le widget. /engine-stands/ porte deux `borgholm_core_portfolio_list` : le
   premier animé, réservé au bureau, le second avec `info_below_disable_hover_animation` et
   réservé à la tablette et en dessous. Relevé aux quatre largeurs, des deux côtés, et le
   local suit à l'identique :

     1440   grille 0 rendue (1140), titre 0/hidden   |  grille 1 masquée
     1024   grille 0 masquée                         |  grille 1 rendue (824), titre 1/visible
      768   grille 0 masquée                         |  grille 1 rendue (568), titre 1/visible
      480   grille 0 masquée                         |  grille 1 rendue (420), titre 1/visible

   « Révéler le texte sans survol sous 1024 px » est donc bien le comportement de la
   référence, et non un écart : elle l'exprime par un second widget là où une media query
   suffit. La règle porte de ce fait sur toutes les cartes, sans préfixe — et sur
   /engine-stands/ elle est de surcroît inerte, la grille animée n'y étant pas rendue.

   Piège à ne pas retomber dedans : une première mesure avait conclu que la production
   laissait aussi son titre à `opacity: 0` en tablette. Elle interrogeait la grille MASQUÉE.
   Le signe qui l'a trahie est une boîte à 0x0 — un élément non rendu renvoie de surcroît
   `transform: none` en style calculé, ce qui donnait un faux accord avec le local.

   L'inclinaison de l'image au survol est laissée en place : elle ne masque rien, et sur
   tactile elle ne se déclenche pas. */
@media only screen and (max-width: 1024px) {

    .dedienne-pc-terms,
    .dedienne-pc-title {
        opacity: 1;
        visibility: visible;
        transform: none;
    }
}

/* ==========================================================================
   Barre de filtres portfolio — alignement du widget natif sur la production

   Le `taxonomy-filter` d'Elementor expose ses valeurs en propriétés personnalisées : on
   les redéfinit plutôt que de lutter contre la spécificité de ses règles.

   Relevé sur /engine-stands/ : libellé « Filter » et puces en **Cormorant** 18px / 700, puce
   active #FE5000, les autres #000, écart de 42 px entre textes, le tout aligné à gauche du
   conteneur. Elementor part de 15px / 400, #69727d, écart 20 px, centré, avec 8 px de
   remplissage par puce — d'où la remise à zéro du remplissage, sans quoi l'écart mesuré
   entre textes vaudrait 42 + 16.

   ---- CORRECTION du 2026-08-13 : la police et l'interligne étaient faux ----

   Ce bloc annonçait « Work Sans » et `line-height: normal`. La production sert **Cormorant**,
   avec un interligne de **25,995 px**. Conséquence mesurée : la barre faisait 21 px de haut
   contre 26, et il manquait en outre les 22 px de marge basse de `.qodef-m-filter` — soit
   27 px par page, sur les trois pages qui portent ce widget.

   L'interligne est écrit en PIXELS, et c'est voulu. Les puces sont en 18 px mais héritent du
   corps un `line-height` déjà calculé à 25,995 px — 15 x 1,733. Un ratio de 1,733 posé sur
   18 px donnerait 31,19 et une barre de 31. C'est le piège de l'interligne qui s'hérite comme
   une LONGUEUR, déjà rencontré sur l'extrait des cartes de /blog/, ici dans l'autre sens.

   ---- Écart de COMPORTEMENT : la production replie ses catégories ----

   À 1440 px, la production n'affiche que « Filter » et son icône. Les catégories sont là dans
   le HTML mais repliées — `visibility: hidden`, `opacity: 0`, `height: 0`, `overflow: hidden`
   sur `.qodef-m-filter-opener-target` — et un clic sur « Filter » les déploie en ajoutant
   `qodef-appear`. Le relevé de styles ne le disait pas : les puces mesurent bien 66 x 26 et se
   déclarent `visible`, c'est leur PARENT qui les efface. C'est la capture d'image qui l'a
   montrée, une bande où la production n'affiche qu'un mot.

   Le local les laisse visibles, en ligne. Choix assumé : l'affordance y gagne — un filtre
   qu'on voit est un filtre qu'on utilise — et le replier demanderait du JS sur mesure, le
   `taxonomy-filter` d'Elementor n'ayant pas cette notion. Même arbitrage que la pagination
   numérotée de /blog/, qui produit de vraies URLs là où l'AJAX de la production n'en produit
   aucune. À trancher par Jérém s'il préfère la fidélité.

   Conséquence sur les mesures : la HAUTEUR de la barre est juste des deux côtés, puisque la
   production réserve ses 26 px que les puces soient dépliées ou non. Seule la comparaison
   d'IMAGE de cette bande diffère, et elle diffère de tout ce que la production ne montre pas.
   ========================================================================== */

/* ---- Spécificité : pourquoi DEUX classes sur le même élément ----

   Elementor imprime le CSS de ce widget dans un `<style>` EN LIGNE, à l'intérieur du
   widget : ses règles sont donc toujours postérieures à la feuille du thème enfant, et
   gagnent toute égalité de spécificité. Or `.elementor-widget-taxonomy-filter .e-filter-item`
   commence par `all: unset`, qui remet TOUTES les propriétés à leur valeur héritée — y
   compris celles qu'on vient de poser. Une règle à une seule classe était donc écrasée
   sans laisser de trace : les puces restaient en 15px / 400 et #69727d.

   `.dedienne-portfolio-filter.elementor-widget-taxonomy-filter` cible le même élément par
   deux classes et passe devant. Et c'est aussi pourquoi une @layer serait le mauvais outil
   ici : elle ferait perdre ces règles à coup sûr, alors qu'au lot feature-list c'était
   précisément l'effet recherché. */

.dedienne-portfolio-filter-bar {
    justify-content: flex-start;
    /* `.qodef-m-filter` de la production porte `margin: 0 0 22px`. Sans elle, la grille
       remontait de 22 px et toute la page avec. */
    margin-bottom: 22px;
}

.dedienne-portfolio-filter-label,
.dedienne-portfolio-filter.elementor-widget-taxonomy-filter .e-filter-item {
    font-family: Cormorant, serif;
    font-size: 18px;
    font-weight: 700;
    letter-spacing: normal;
    text-transform: none;
    /* En PIXELS : voir la note d'en-tête. Un ratio donnerait 31,19 au lieu de 25,995. */
    line-height: 25.995px;
}

/* ---- L'icône du libellé « Filter » ----

   La production précède « Filter » d'un glyphe dripicons-v2 U+E05A : une grille de 3 x 3 petits
   carrés. Le greffon parti, la police avec, il est redessiné en SVG à partir de son encre
   MESURÉE dans un canvas sur la production, comme les deux flèches ElegantIcons du chantier :

       avance      18,000 à 18px — c'est elle qui donne la largeur de la boîte
       encre       12,96 x 12,48, à 2,52 de l'origine du tracé
       bandes X    0-2,64 · 5,16-7,68 · 10,20-12,84   -> carrés de 2,64, pas de 5,16
       bandes Y    0-2,64 · 4,92-7,44 · 9,72-12,36    -> carrés de 2,64, pas de 4,92

   Sans lui, les 21 px qu'il occupe — 18 d'avance plus 3 de marge — manquaient, et TOUTE la
   rangée de filtres glissait de 23 px vers la gauche. C'est ce que le diff d'image a montré :
   la barre avait la bonne hauteur, et chaque libellé était décalé.

   `margin-left: -2px` sur le libellé : la production le pose sur l'opener, ce qui fait
   commencer le glyphe à x=148 dans un conteneur qui débute à 150. */
.dedienne-portfolio-filter-label .elementor-heading-title::before {
    content: '';
    display: inline-block;
    width: 18px;
    height: 12.48px;
    margin-right: 3px;
    background-repeat: no-repeat;
    background-position: 2.52px 0;
    background-size: 12.96px 12.48px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12.96 12.48' fill='%23000'%3E%3Crect x='0.0' y='0.0' width='2.64' height='2.64'/%3E%3Crect x='0.0' y='4.92' width='2.64' height='2.64'/%3E%3Crect x='0.0' y='9.84' width='2.64' height='2.64'/%3E%3Crect x='5.16' y='0.0' width='2.64' height='2.64'/%3E%3Crect x='5.16' y='4.92' width='2.64' height='2.64'/%3E%3Crect x='5.16' y='9.84' width='2.64' height='2.64'/%3E%3Crect x='10.32' y='0.0' width='2.64' height='2.64'/%3E%3Crect x='10.32' y='4.92' width='2.64' height='2.64'/%3E%3Crect x='10.32' y='9.84' width='2.64' height='2.64'/%3E%3C/svg%3E");
}

/* `margin-left` seulement. Les 21 px que la production pose à droite de son opener, plus les
   21 px de marge gauche de sa première puce, font 42 — exactement l'écart flex que la barre
   porte déjà. Les ajouter décalait la rangée de 21 px de trop vers la droite : le premier
   essai partait de -23 px et arrivait à +17. */
.dedienne-portfolio-filter-label {
    margin-left: -2px;
}

/* ---- Le filtrage : les partantes sortent du flux, les survivantes glissent ----

   La production anime la BOITE de la carte — `$item.hide( 300, 'linear' )` — et cela marche chez
   elle parce que ses items sont en `float: left` : reduire une boite fait remonter les suivantes en
   continu, le retrecissement et le retassage sont le meme geste.

   Dans une grille CSS, ce geste ne se transpose pas. Deux tentatives ont echoue :

     1. le meme appel jQuery : la carte retrecit dans sa cellule, la rangee reste dimensionnee par
        sa plus grande voisine, des vignettes minuscules flottent en haut de rangees hautes ;
     2. `transform: scale()` seul : plus de desordre, mais les cartes laissent des trous et tout se
        replace d'un coup a la fin — le retassage continu, l'essentiel du mouvement, disparaissait.

   Le script separe donc les deux gestes et les joue ensemble (FLIP) : les partantes passent en
   `position: absolute`, epinglees a leur place, donc HORS du flux ; la grille se retasse aussitot ;
   les survivantes sont remises a leur ancienne position par une translation sans transition, puis
   relachees — elles glissent en 300 ms. Le conteneur doit donc etre un repere de positionnement.

   `translate` et `opacity` sont les deux seules proprietes qu'un navigateur anime sans recalculer
   la mise en page : l'animation reste fluide. */

.dedienne-portfolio-grid .elementor-loop-container {
    position: relative;
}

.dedienne-portfolio-grid .e-loop-item.dedienne-filtre-partante {
    /* Epinglee hors flux par le script, qui pose aussi ses coordonnees et ses dimensions. */
    z-index: 0;
    pointer-events: none;
    transform-origin: 0 0;
    transform: scale(.9);
    opacity: 0;
    transition: transform .3s linear, opacity .3s linear;
}

/* ---- Le repli derriere « Filter » ----

   La production n'affiche que « Filter » ; ses categories vivent dans un
   `.qodef-m-filter-opener-target` replie, qu'un clic revele en lui ajoutant `.qodef-appear` :

     .qodef-m-filter-opener-target          height: 0; opacity: 0; visibility: hidden;
                                            overflow: hidden; transition: all .3s ease
     … .qodef-appear                        height: auto; opacity: 1; visibility: visible

   Repris tel quel. `height: 0 → auto` ne s'anime pas en CSS : la revelation est donc un fondu de
   0,3 s avec un changement de hauteur immediat. Animer la hauteur serait « mieux » et ne serait
   pas la production.

   `visibility: hidden` compte autant que le reste : sans elle, les liens de categorie resteraient
   atteignables au clavier et cliquables alors qu'ils sont invisibles.

   La bascule est posee par `dedienne-elements/assets/js/filter-opener.js`. En local le libelle et
   les categories sont DEUX widgets voisins, la ou la production les rend dans le meme bloc — le
   script cherche donc la cible dans le conteneur commun. */

.dedienne-portfolio-filter.elementor-widget-taxonomy-filter {
    height: 0;
    opacity: 0;
    visibility: hidden;
    overflow: hidden;
    transition: all .3s ease;
}

/* `overflow` reste a `hidden` : la regle `.qodef-appear` de la production ne le remet pas a
   `visible`, et le premier jet ici le faisait par reflexe. Sans consequence sur ce contenu, mais
   c'est un ecart gratuit avec la reference. */
.dedienne-portfolio-filter.elementor-widget-taxonomy-filter.dedienne-appear {
    height: auto;
    opacity: 1;
    visibility: visible;
}

/* L'ouvreur se donne pour cliquable. La production met `cursor: pointer` et une transition de
   couleur de 0,3 s sur son opener. */
.dedienne-portfolio-filter-label .elementor-heading-title {
    cursor: pointer;
    transition: color .3s ease-out;
}

.dedienne-portfolio-filter.elementor-widget-taxonomy-filter {
    --e-filter-space-between: 42px;
    --e-filter-item-padding: 0px;
    --e-filter-justify-content: flex-start;
    --e-filter-normal-text-color: #000;
    --e-filter-hover-text-color: #fe5000;
    --e-filter-active-text-color: #fe5000;
}

/* ==========================================================================
   Carrousel « tooling lines » de l'accueil — section 6885b42

   La production sert ce carrousel sur `/` ; en local la section existait mais sa colonne
   était vide, le widget ayant disparu lors de la reconstruction de l'accueil en natif.
   Rétabli en `loop-carousel` par tools/templates/restore-home-carousel.php.

   Trois écarts relevés après pose, tous portés ici :

   1. Les 5 px du `qodef-swiper-fix`. borgholm posait `width: calc(100% + 5px)` sur ce
      conteneur, et c'est de là que vient l'arithmétique de la production :
      323,75 = ( 1445 - 3 x 50 ) / 4, non ( 1440 - 150 ) / 4 = 322,5.
   2. Le bloc de catégories mesure 20 px sur CETTE carte, contre 26 sur les deux autres —
      son interligne est celui du terme, pas celui hérité du conteneur. D'où la surcharge
      de la hauteur posée pour les grilles.
   3. Les diapos d'un carrousel Elementor s'étirent à la hauteur de la plus haute. La
      production les laisse à leur hauteur propre, 412,938.
   ========================================================================== */

/* Les 5 px vont sur le conteneur Swiper, non sur l'enveloppe du widget : c'est lui que
   Swiper mesure pour calculer la largeur des diapos. */
/* Les 5 px ne valent qu'au bureau, seule largeur ou la production servait ce carrousel : en
   dessous, avec une diapo par vue, ils faisaient une diapo de 485 px dans une fenetre de
   480 et un debordement horizontal de la page. */
@media only screen and (min-width: 1025px) {

    .dedienne-home-carousel .swiper {
        width: calc(100% + 5px);
    }
}

.dedienne-home-carousel .swiper {
    /* La production retire au bas du bloc l'ecart inter-diapos : son conteneur Swiper mesure
       535,88 comme le notre, mais l'enveloppe du widget n'en fait que 485,88. C'est la
       convention « no bottom space » de qode, qui compense la gouttiere de la grille. Sans
       cela la section de l'accueil serait 50 px plus haute et decalerait tout ce qui suit.

       On lit la gouttiere plutot que d'ecrire -50px : `--swiper-slides-gap` est la propriete
       qu'Elementor pose lui-meme sur l'enveloppe du widget depuis `image_spacing_custom`, et
       elle est responsive — 50px au bureau, 20px en mobile. Avec la valeur en dur, la
       compensation valait 50 la ou l'ecart n'en faisait que 20 : mesure faite, le conteneur
       depassait le bas de sa section de 50 px a 480 et empietait sur ce qui suit, la section
       n'ayant plus de remplissage bas a cette largeur pour l'absorber. La gouttiere et sa
       compensation sont la meme grandeur : les ecrire deux fois, c'etait s'exposer a les
       desaccorder au premier reglage. */
    margin-bottom: calc(-1 * var(--swiper-slides-gap, 0px));
}

.dedienne-home-carousel .dedienne-pc-terms .elementor-icon-list-item {
    height: 20px;
    line-height: 20px;
}

/* `align-items: flex-start` sur la piste : Swiper etire les diapos a la hauteur de la plus
   haute, alors que la production les laisse a leur hauteur propre. Pose sur le parent, la
   regle s'applique a TOUTES les diapos — sur l'enfant, seule la premiere suivait. */
.dedienne-home-carousel .swiper-wrapper {
    align-items: flex-start;
}

.dedienne-home-carousel .swiper-slide {
    height: auto;
}

/* Curseur de glissement de la production (`.qodef-portfolio-list.qodef-swiper-container:hover`). */
.dedienne-home-carousel:hover {
    cursor: url("assets/img/drag-cursor.svg"), auto;
}

/* ==========================================================================
   Débordement horizontal — alignement sur la production

   Borgholm posait `overflow-x: hidden` sur `body`. hello-elementor ne le fait pas, et le
   carrousel de l'accueil — dont le conteneur mesure volontairement 5 px de plus que la
   fenêtre — provoquait une barre de défilement horizontale que la production n'a pas.

   La contenir au niveau de la section serait pire : ce sont les diapos qui débordent, et les
   clipper supprimerait précisément l'effet recherché. C'est bien au niveau du document que la
   production absorbe le dépassement, en laissant les diapos sortir du cadre visible.

   Sans effet sur l'en-tête collant : Elementor implémente « sticky » en JavaScript, par
   `position: fixed`, et non par le `position: sticky` du CSS que cette règle mettrait en
   défaut. Deux conteneurs de l'en-tête 131024 sont concernés, vérifiés.
   ========================================================================== */

body {
    overflow-x: hidden;
}

/* `body { overflow-x: hidden }` ne suffit pas a lui seul : mesure faite, le document local
   annoncait encore 1445 de largeur de defilement pour 1440 de fenetre, la ou la production
   reste a 1440 avec la MEME regle. C'est donc un ancetre qui rogne chez elle.

   On rogne au niveau de la section du carrousel. Cela ne touche pas au debordement voulu :
   les diapos sont deja rognees par le conteneur Swiper, et ce qu'on voit aux bords est une
   carte partielle produite par la translation de la piste, non un contenu qui sortirait de
   la section. Verifie : abscisses des diapos inchangees apres la regle. */
.elementor-element.elementor-element-6885b42 {
    overflow-x: hidden;
}

/* ==========================================================================
   Carte d'article — /blog/, Loop Grid natif (modèle « Blog Card — Standard »)

   Valeurs relevées sur la production à 1440 px, colonne de contenu à 812,50.
   Ce qui vient du kit Elementor n'est PAS repris ici : le titre est déjà en Montserrat
   45px / 300 avec un interligne de 1em, soit exactement le h1 de la production.

   Ce que le natif ne donne pas et qui suit :
     · l'image à `scale(1.05)` au repos, `scale(1.01)` au survol, dans un cadre rogné
     · la ligne d'infos — 11px / 500, +0,15em, capitales, #9e9e9e, séparateur « / »
     · l'extrait à 88 % et 14px
     · le bouton textuel, avec son trait de 30 px et sa tête de flèche
     · la pagination : Prev et Next aux extrémités, numéros centrés, actif souligné
   ========================================================================== */

/* ---- Image : un dézoom au survol, non un zoom ----

   borgholm pose `scale(1.05)` AU REPOS et `scale(1.01)` au survol, dans un
   `.qodef-e-media-image` en `overflow: hidden`. L'image est donc toujours un peu rognée, et
   elle se détend au passage de la souris. C'est l'inverse du réflexe habituel, et l'inverse
   de ce que fait la carte portfolio — à ne pas uniformiser par étourderie.

   Le rognage va sur le conteneur du widget et non sur le widget : c'est lui qui borne la
   boîte de l'image. */
.dedienne-bc-image.elementor-widget-image .elementor-widget-container {
    overflow: hidden;
    /* La production aligne l'image à gauche ; Elementor centre les images par défaut. */
    text-align: left;
}

/* Le LIEN aussi en `display: block`, et pas seulement l'image : resté en ligne, il portait un
   talon de descendante de 8 px sous l'image — la carte faisait 893,38 au lieu de 872,44.
   borgholm le déclare explicitement, `.qodef-e-media-image a, ... img { display: block }`. */
.dedienne-bc-image.elementor-widget-image .elementor-widget-container > a {
    display: block;
}

.dedienne-bc-image.elementor-widget-image img {
    display: block;
    width: 100%;
    transform: scale(1.05);
    transition: all 1s cubic-bezier(.475, .425, 0, .995);
    will-change: transform;
}

.dedienne-bc-image.elementor-widget-image .elementor-widget-container:hover img {
    transform: scale(1.01);
}

/* ---- Ligne d'infos : date / catégorie ---- */

/* Les icônes d'Elementor — un calendrier et une étiquette — n'existent pas en production.
   DEUX classes sur l'élément : `widget-icon-list.min.css` pose `display: flex` avec
   `.elementor-widget .elementor-icon-list-icon`, et s'imprime après cette feuille. Troisième
   occurrence du même piège dans ce fichier ; voir la note du carrousel de l'accueil. */
.dedienne-bc-meta.elementor-widget .elementor-icon-list-icon {
    display: none;
}

/* `.dedienne-bc-meta.elementor-widget` — DEUX classes sur le même élément, une de plus
   qu'Elementor. Sans cela, `widget-icon-list.min.css` gagne avec
   `.elementor-widget .elementor-icon-list-item { font-size: inherit }` : la ligne restait en
   15 px, l'interligne suivait, et l'écart se propageait à toute la carte. Quatrième occurrence
   du mécanisme dans ce fichier — la règle est notée plus haut, elle n'avait pas été appliquée
   ici. */
.dedienne-bc-meta.elementor-widget .elementor-icon-list-item,
.dedienne-bc-meta.elementor-widget .elementor-icon-list-item a,
.dedienne-bc-meta.elementor-widget .elementor-icon-list-text {
    font-family: "Work Sans", sans-serif;
    font-size: 11px;
    font-weight: 500;
    /* 26 px et non les 32 que la production déclare sur le lien : chez elle, la BOÎTE de la
       ligne mesure 26 — le 32 du lien en ligne ne l'emporte pas sur la strut du bloc parent.
       Ce qui compte est la boîte, et 26 la donne directement. À 32 la carte gagnait 6 px. */
    line-height: 26px;
    text-transform: uppercase;
    color: #9e9e9e;
}

/* L'espacement des lettres va sur le LIEN, non sur la puce qui le contient — c'est là que la
   production le pose, sa puce restant à `normal`. Sur la puce, l'espacement s'ajoute aussi
   APRÈS le dernier caractère et élargissait la boîte de 2 px, décalant la catégorie d'autant. */
.dedienne-bc-meta.elementor-widget .elementor-icon-list-item a,
.dedienne-bc-meta.elementor-widget .elementor-icon-list-text {
    /* 0,15em de la production, soit 1,65px à 11px. */
    letter-spacing: .15em;
}

.dedienne-bc-meta.elementor-widget .elementor-icon-list-item a:hover {
    color: #fe5000;
}

/* Elementor sépare ses puces en ligne par 8 px de marge de chaque côté, et il le déclare avec
   `.elementor-widget .elementor-icon-list-items.elementor-inline-items .elementor-icon-list-item` —
   QUATRE classes. Une chaîne de quatre ne suffisait donc pas : les 8+8 subsistaient et
   décalaient la catégorie de 16 px. D'où les cinq ci-dessous. La production, elle, met un
   remplissage à droite et une barre oblique. */
.dedienne-bc-meta.elementor-widget .elementor-icon-list-items.elementor-inline-items .elementor-icon-list-item {
    margin: 0;
    /* 5 et non 8 : voir la note sur le centrage de la barre oblique, plus bas. */
    padding: 0 5px 0 0;
}

/* Et la LISTE elle-même porte `margin: 0 -8px`, en compensation des 8 px de ses puces. Les
   puces n'en ayant plus, la compensation décalait toute la ligne de 8 px vers la gauche. */
.dedienne-bc-meta.elementor-widget .elementor-icon-list-items.elementor-inline-items {
    margin: 0;
}

/* ---- Le séparateur, et la bordure qu'il réveille ----

   `widget-icon-list.min.css` tient son séparateur de puces en ligne prêt sur ce même
   pseudo-élément, bordure comprise :

     .elementor-inline-items .elementor-icon-list-item:after
     { border-left-width: 1px; border-style: solid; height: 100%; position: relative; right: -8px }

   Ces déclarations sont inertes tant que `content` n'est pas posé — c'est ainsi que le
   contrôle « Divider » d'Elementor fonctionne, en n'ajoutant que `content: ""`. En posant
   `content: '/'` on les a donc RÉVEILLÉES, et la barre oblique s'est doublée d'un trait
   vertical de 26 px. Il faut les défaire explicitement.

   ---- CORRECTION du 2026-08-25 : la chaîne était trop courte ----

   La première version de cette règle comptait TROIS classes et un `:not()`. Or celle d'Elementor
   en compte quatre plus un `:not()` :

     .elementor-widget .elementor-icon-list-items.elementor-inline-items
     .elementor-icon-list-item:not(:last-child):after

   Elle gagnait donc sur `border-left-width`, `height`, `position` et `right`, tout en perdant sur
   `content`, `margin-left` et `color` — que sa propre règle ne déclare pas. Le résultat était
   trompeur : la barre oblique apparaissait, sa couleur et sa marge étaient bonnes, et le trait
   vertical de 1 px restait. Chaque propriété se résout séparément ; voir la règle « au plus juste »
   ne suffit pas, il faut comparer propriété par propriété.

   L'écart était présent sur `/blog/` aussi : la carte de l'accueil ne l'a pas introduit, elle l'a
   révélé. La chaîne est portée à SIX unités, une de plus que celle d'Elementor. */
/* ---- Centrage de la barre oblique (2026-08-27) ----

   La production déclare `margin-left: 2px` avant la barre et 8 px de remplissage
   après, et cela paraît centré chez elle — parce que son lien contient des espaces
   LITTÉRAUX (« <a> 17 June 2026 </a> ») : ses glyphes s'arrêtent environ 4 px avant
   le bord de la boîte, ce qui donne ~6 px avant la barre et 8 après. Elementor rend
   `<time>17 June 2026</time>` sans espace : les mêmes valeurs donnaient 2 px avant
   et 8 après, et la barre collait le premier mot.

   Les 15 px entre la fin du texte et la fin de la puce sont donc répartis
   autrement : 5 avant, 5 px de glyphe, 5 après. La barre est centrée et la puce
   garde EXACTEMENT la largeur de la production — la catégorie ne bouge pas. */
.dedienne-bc-meta.elementor-widget .elementor-icon-list-items.elementor-inline-items .elementor-icon-list-item:not(:last-child)::after {
    content: '/';
    height: auto;
    right: auto;
    margin-left: 5px;
    border: 0;
    color: #9e9e9e;
}

/* Cinq classes ici aussi : la règle de remplissage ci-dessus en compte cinq, et une chaîne
   plus courte lui aurait cédé les 8 px de droite sur la dernière puce. */
.dedienne-bc-meta.elementor-widget .elementor-icon-list-items.elementor-inline-items .elementor-icon-list-item:last-child {
    padding-right: 0;
}

/* ---- Extrait ----

   88 % relevé sur `.qodef-blog .qodef-blog-item .qodef-e-excerpt`, et `auto` sous 769 px.
   14px n'est pas le corps du kit, qui est à 15 : la règle `p { font-size: 14px }` du haut de
   ce fichier ne s'applique pas ici, `theme-post-excerpt` rendant son texte nu dans un div. */
.dedienne-bc-excerpt .elementor-widget-container {
    width: 88%;
    font-size: 14px;
    /* Sans ratio explicite, l'interligne est hérité du corps EN PIXELS : `line-height: 1.733em`
       déclaré sur `body` s'y résout en 25,995px, et un descendant hérite la longueur, non le
       rapport. L'extrait passait donc à 4 x 26 = 104 au lieu de 4 x 24,262 = 97,06. Un ratio
       sans unité se recalcule sur la taille locale, ce qui est ici la seule écriture juste. */
    line-height: 1.733;
}

@media only screen and (max-width: 768px) {

    .dedienne-bc-excerpt .elementor-widget-container {
        width: auto;
    }
}

/* ---- Bouton « Find Out More » : la disposition textuelle de borgholm ----

   Relevé : Work Sans 11px / 600, interligne 22, +2,2px, capitales, #000, sans remplissage ni
   fond — le bouton d'Elementor arrive en 13px / 500 sur fond #f5f5f5 avec 17px 30px de
   remplissage, donc tout est à défaire.

   La flèche est faite de deux pseudo-éléments, hors de la boîte du texte :
     ::after   le trait, 30x2 en #000, à `right: -41px`, qui s'étire en `scaleX(1.3)` au survol
     ::before  la tête, un glyphe ElegantIcons « E » de 13,2x11 à `right: -49px`, qui glisse
               à -58px au survol

   Le glyphe est remplacé par un SVG en URI de données : embarquer une police de 60 Ko pour un
   seul caractère n'aurait pas de sens, et la forme — un triangle plein au bout du trait — se
   reproduit exactement. Le lot 5b aura le même arbitrage à rendre pour le formulaire de
   recherche, qui utilise un autre glyphe de la même police. */

/* ---- Les 67 px sous le bouton ne valent PAS sur la dernière carte ----

   borgholm les pose avec un `:not(:last-child)` sur l'article :

     .qodef-blog.qodef-item-layout--standard.qodef-col-num--1 article:not(:last-child) .qodef-e…
     { margin-bottom: 67px }

   D'où une dernière carte de 805,44 au lieu de 872,44 en production — 66,94 px d'écart, seul
   reliquat après alignement des quatre premières. Le réglage `_margin` du modèle ne sait pas
   distinguer la dernière itération : la règle est donc ici, et elle compte cinq classes contre
   les trois d'Elementor, ce qui suffit à passer devant son `<style>` en ligne. */
.dedienne-blog-grid .elementor-loop-container > :last-child .dedienne-bc-more > .elementor-widget-container {
    margin-bottom: 0;
}

.dedienne-bc-more .elementor-button-wrapper {
    /* La ligne basse de la production fait 26,25 px, hauteur imposée par un bloc de partage
       social dont la liste est VIDE dans le HTML servi. On ne reconstruit pas un bloc vide
       pour 0,25 px : on pose la hauteur. */
    height: 26.25px;
}

.dedienne-bc-more .elementor-button {
    display: inline-block;
    position: relative;
    padding: 0;
    background-color: transparent;
    border: 0;
    border-radius: 0;
    color: #000;
    font-family: "Work Sans", sans-serif;
    font-size: 11px;
    font-weight: 600;
    line-height: 22px;
    letter-spacing: 2.2px;
    text-transform: uppercase;
    text-align: left;
    fill: currentColor;
}

.dedienne-bc-more .elementor-button:hover,
.dedienne-bc-more .elementor-button:focus {
    background-color: transparent;
    color: #000;
}

/* Le trait. */
.dedienne-bc-more .elementor-button::after {
    content: '';
    position: absolute;
    right: -41px;
    top: 11.125px;
    width: 30px;
    height: 2px;
    background-color: #000;
    transform: translateY(-1px);
    transform-origin: left center;
    transition: transform .3s cubic-bezier(.475, .425, 0, .995);
}

/* ---- La tête de flèche, mesurée et non estimée ----

   Premier essai dessiné à vue : un triangle de 5,8 x 7,8, visiblement plus épais que celui de
   la production. L'encre du glyphe a donc été mesurée là où la police est chargée — dessin du
   caractère dans un canvas sur la page de production, à 110 px, puis lecture des pixels :

     avance         11,00 à 11px  (la boîte de 13,2 relevée = 11 + 2,2 de letter-spacing)
     encre          3,40 x 5,50, triangle PLEIN s'affinant vers la droite
     position       à 4,10 de l'origine du tracé

   Le SVG reprend ces valeurs dans une boîte de 13,2 x 11, ce qui place l'encre exactement où
   la production la met : de +39,9 à +43,3 du bord droit du texte, soit chevauchant de 1,1 px
   la fin du trait (+41) et dépassant de 2,3. C'est ce chevauchement qui soude la tête à la
   hampe ; un triangle simplement posé au bout laisserait une jointure visible.

   `translateY(-5.5px)` avec `top: 11.125px` centre la boîte sur 11,125 — l'axe du trait, dont
   la boîte de 2 px commence à 10,125. Tête et hampe sont donc alignées par construction. */
.dedienne-bc-more .elementor-button::before {
    content: '';
    position: absolute;
    right: -49px;
    top: 11.125px;
    width: 13.2px;
    height: 11px;
    background-repeat: no-repeat;
    background-position: 0 0;
    background-size: 13.2px 12px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13.2 11'%3E%3Cpolygon fill='%23000' points='4.1,2.75 7.5,5.5 4.1,8.25'/%3E%3C/svg%3E");
    transform: translateY(-5.5px);
    transition: right .3s cubic-bezier(.475, .425, 0, .995);
}

.dedienne-bc-more .elementor-button:hover::after {
    transform: translateY(-1px) scaleX(1.3);
}

.dedienne-bc-more .elementor-button:hover::before {
    right: -58px;
}

/* ==========================================================================
   Pagination numérotée — /blog/

   La production place Prev et Next aux extrémités d'une barre de 812,50, en position
   absolue dans un remplissage de 0 110px, et centre les numéros entre eux. Elementor rend
   un `nav.elementor-pagination` en bloc, avec `a.page-numbers` en ligne : on refait la
   disposition, la typographie venant des réglages du widget (Cormorant 20px / 700).

   Le numéro actif reste NOIR : ce qui le marque est un souligné orange de 19x1 px, posé
   1 px sous la ligne de base. C'est ce détail qui a fait garder `pagination_active_color`
   à #000 dans le script de conversion.
   ========================================================================== */

/* La gouttière de 30 px subsiste SOUS la dernière rangée en production : ses articles portent
   `margin: 0 0 30px`, le dernier compris. `row_gap` d'Elementor passe par `row-gap` de la
   grille CSS, qui ne pose d'espace qu'ENTRE les rangées — d'où 50 px sous la dernière carte au
   lieu des 80 relevés. Les 50 restent le `pagination_spacing_top` du widget, qui est bien la
   valeur de la production ; les 30 sont ici, du côté de la grille à laquelle ils appartiennent.

   En REMPLISSAGE et non en marge : la grille et la pagination sont frères dans le conteneur du
   widget, si bien qu'une `margin-bottom: 30px` se fusionne avec la `margin-top: 50px` de la
   pagination — `max(30, 50)` vaut 50, et rien ne bougeait. Un remplissage ne fusionne jamais.
   La production s'en tire autrement : ses articles flottent dans `.qodef-grid-inner`, ce qui
   fait de lui un contexte de formatage et empêche la fusion de traverser. */
.dedienne-blog-grid .elementor-loop-container {
    padding-bottom: 30px;
}

.dedienne-blog-grid .elementor-pagination,
.dedienne-sr-grid .elementor-pagination {
    display: flex;
    position: relative;
    align-items: center;
    justify-content: center;
    padding: 0 110px;
}

/* ---- Ces règles servent DEUX paginations ----

   `.dedienne-blog-grid` sur /blog/ et `.dedienne-sr-grid` sur la page de résultats. La
   production en sert deux variantes distinctes — `.qodef-m-pagination.qodef--standard`, celle
   de son AJAX, et `.qodef--wp`, celle de WordPress — mais leur DISPOSITION est la même :
   remplissage de 0 110px, numéros centrés, Prev et Next aux extrémités avec la flèche de
   40x10. Seule diffère la marque du numéro courant : souligné orange sous un chiffre noir sur
   /blog/, chiffre ORANGE sur la recherche. Le souligné reste donc en dessous, hors partage. */

/* Prev et Next : 12px / 600, +2,4px, EN CAPITALES, aux extrémités, suivis ou précédés d'une
   flèche de 40x10. Relevé sur la production : l'ensemble « NEXT + flèche » fait 104,61 —
   soit un libellé de 64,61 remplissage compris (0 11px) et la flèche de 40. */
.dedienne-blog-grid .elementor-pagination .page-numbers.prev,
.dedienne-blog-grid .elementor-pagination .page-numbers.next,
.dedienne-sr-grid .elementor-pagination .page-numbers.prev,
.dedienne-sr-grid .elementor-pagination .page-numbers.next {
    display: flex;
    position: absolute;
    top: calc(50% + 1px);
    align-items: center;
    transform: translateY(-50%);
    margin: 0;
    font-family: "Work Sans", sans-serif;
    font-size: 12px;
    font-weight: 600;
    line-height: 12px;
    letter-spacing: 2.4px;
    text-transform: uppercase;
}

.dedienne-blog-grid .elementor-pagination .page-numbers.prev,
.dedienne-sr-grid .elementor-pagination .page-numbers.prev {
    left: 0;
    padding: 0 11px 0 0;
}

.dedienne-blog-grid .elementor-pagination .page-numbers.next,
.dedienne-sr-grid .elementor-pagination .page-numbers.next {
    right: 0;
    padding: 0 0 0 11px;
}

/* La flèche de la pagination est un AUTRE dessin que celle du bouton « Find Out More » :
   40x10 avec une hampe de 1 px, contre 30x2 et une tête de 3,4x5,5. Celui-ci, borgholm le
   sert en SVG inline, ce qui donne ses coordonnées exactes — reprises telles quelles.

   Sur « Prev », la production fait pivoter le même dessin de 180 degrés plutôt que d'en
   dessiner un second. */
.dedienne-blog-grid .elementor-pagination .page-numbers.prev::before,
.dedienne-blog-grid .elementor-pagination .page-numbers.next::after,
.dedienne-sr-grid .elementor-pagination .page-numbers.prev::before,
.dedienne-sr-grid .elementor-pagination .page-numbers.next::after {
    content: '';
    width: 40px;
    height: 10px;
    background-repeat: no-repeat;
    background-position: center;
    background-size: 40px 10px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 39.7 9.1'%3E%3Cpolygon fill='%23000' points='35.1,5.1 35.1,7.7 38.9,4.6 35.1,1.6 35.1,4.2'/%3E%3Crect fill='%23000' x='1.1' y='4.2' width='34.1' height='1'/%3E%3C/svg%3E");
}

/* Les 11 px de l'autre côté du libellé. */
.dedienne-blog-grid .elementor-pagination .page-numbers.prev::before,
.dedienne-sr-grid .elementor-pagination .page-numbers.prev::before {
    margin-right: 11px;
    transform: rotate(180deg);
}

.dedienne-blog-grid .elementor-pagination .page-numbers.next::after,
.dedienne-sr-grid .elementor-pagination .page-numbers.next::after {
    margin-left: 11px;
}

/* Étirement au survol, comme partout ailleurs. Ici la flèche est UNE image de
   fond en flux, hampe et pointe comprises : on étire donc l'ensemble à 1,25, ce
   qui porte la largeur totale de 40 à 50 px — l'extension exacte de la production
   (hampe 34,4 → 44,7). La pointe s'allonge de 0,9 px au passage, ce qui ne se
   voit pas, et un `transform` n'est pas rogné par la boîte, contrairement à un
   fond. L'origine est du côté du libellé, pour que la flèche s'étende vers
   l'extérieur. */
.dedienne-blog-grid .elementor-pagination .page-numbers.prev::before,
.dedienne-blog-grid .elementor-pagination .page-numbers.next::after,
.dedienne-sr-grid .elementor-pagination .page-numbers.prev::before,
.dedienne-sr-grid .elementor-pagination .page-numbers.next::after {
    transition: transform .2s ease-in-out;
}

.dedienne-blog-grid .elementor-pagination .page-numbers.next::after,
.dedienne-sr-grid .elementor-pagination .page-numbers.next::after {
    transform-origin: left center;
}

.dedienne-blog-grid .elementor-pagination a.next:hover::after,
.dedienne-sr-grid .elementor-pagination a.next:hover::after {
    transform: scaleX(1.25);
}

/* La flèche « prev » est déjà tournée d'un demi-tour : son origine gauche est donc
   visuellement à droite, du côté du libellé, et la composition garde la rotation. */
.dedienne-blog-grid .elementor-pagination .page-numbers.prev::before,
.dedienne-sr-grid .elementor-pagination .page-numbers.prev::before {
    transform-origin: left center;
}

.dedienne-blog-grid .elementor-pagination a.prev:hover::before,
.dedienne-sr-grid .elementor-pagination a.prev:hover::before {
    transform: rotate(180deg) scaleX(1.25);
}

/* ---- Prev sur la première page, Next sur la dernière ----

   La production les MASQUE : sa boîte `.qodef--prev` mesure 0x0 sur la page 1. Elementor, lui,
   rend un `<span class="page-numbers prev">` inerte — un span et non un lien, faute de cible.
   C'est précisément ce qui permet de les distinguer sans compter les pages. */
.dedienne-blog-grid .elementor-pagination span.page-numbers.prev,
.dedienne-blog-grid .elementor-pagination span.page-numbers.next,
.dedienne-sr-grid .elementor-pagination span.page-numbers.prev,
.dedienne-sr-grid .elementor-pagination span.page-numbers.next {
    display: none;
}

.dedienne-blog-grid .elementor-pagination .page-numbers.current {
    position: relative;
}

.dedienne-blog-grid .elementor-pagination .page-numbers.current::after {
    content: '';
    position: absolute;
    left: 50%;
    top: 27px;
    width: 19px;
    height: 1px;
    background-color: #fe5000;
    transform: translateX(-50%);
}

/* ==========================================================================
   Bouton « catalogue » de /engine-stands/ — qi_button converti en `button` natif

   Deux instances, une par périphérique : `dqb0100` au bureau, `dqb0200` en tablette et en
   dessous. Elles ne diffèrent que par le PDF visé — et pas seulement par sa version : le
   bouton du bureau mène au catalogue 2024, l'autre à celui de 2021. Signalé, non corrigé.

   Relevé sur la production : lien 264 x 44 en `inline-flex` avec `align-items: stretch`,
   bordure 1px #111, texte 220 x 42 centré verticalement avec un remplissage 5px 10px 5px 0,
   et une boîte d'icône de 42 x 42 contenant un SVG de 16.

   La typographie, les couleurs, la bordure et le survol (#FE5000 sur fond blanc) sont portés
   par les réglages du widget, donc par le CSS généré d'Elementor. Ne reste ici que la
   disposition interne, qu'aucun contrôle n'exprime.
   ========================================================================== */

.dedienne-qi-button .elementor-button {
    display: inline-flex;
    align-items: stretch;
    justify-content: center;
}

.dedienne-qi-button .elementor-button-content-wrapper {
    align-items: stretch;
}

/* ---- La boîte d'icône est CARRÉE, et sa taille vient de la hauteur du texte ----

   qi ne l'exprime pas en CSS : son script recopie la hauteur du bloc de texte dans la largeur
   de la boîte d'icône (`initItem`, assets/js/main.js:1068). D'où les 42 relevés — 5 + 32 + 5.

   `aspect-ratio: 1` semblait dire la même chose sans script, l'étirement du conteneur flex
   rendant la hauteur définie. Il POSE bien la boîte à 42x42, mais il ne participe PAS au calcul
   de la largeur intrinsèque du conteneur : celui-ci n'a compté que les 16 px du SVG, si bien que
   le lien tombait à 238 au lieu de 264 et que la boîte d'icône débordait de son propre parent.

   D'où `calc(2em + 10px)`, qui reprend les termes mêmes de qi : 2em est l'interligne qu'il pose
   sur le bouton, donc la hauteur du texte, et 10 son remplissage vertical. La valeur suit la
   typographie comme le faisait son script, sans 42 en dur. */
.dedienne-qi-button .elementor-button-icon {
    display: flex;
    flex-grow: 0;
    align-items: center;
    justify-content: center;
    width: calc(2em + 10px);
    padding: 5px 0;
    margin: 0;
}

.dedienne-qi-button .elementor-button-icon svg {
    width: 16px;
    height: 16px;
    fill: currentColor;
}

/* `white-space: nowrap` : le libellé tient sur UNE ligne en production, et sans cette
   assertion il passait à la ligne en débordant du bouton. Le lien est `inline-flex`, donc
   dimensionné sur son contenu — mais la largeur intrinsèque calculee par Elementor pour ce bloc
   de texte reste en deçà de ce que la chaîne demande, et le retour à la ligne s'ensuit.

   Sans danger ici, contrairement au cas de la carte portfolio où la même déclaration avait
   élargi l'élément au-delà de sa colonne : le bouton vit dans une colonne de 1140, il a la place. */
.dedienne-qi-button .elementor-button-text {
    flex-grow: 0;
    align-self: center;
    padding: 5px 10px 5px 0;
    white-space: nowrap;
}

/* ==========================================================================
   Diaporamas d'images de l'article « torke » — qi_image_slider converti en natif

   Deux instances, quatre photos chacune, dans une colonne de 388,75. Relevé sur la
   production : image 388 x 247,09, flèches de 30 px en #FE5000 à 30 px des bords — donc
   À L'INTÉRIEUR du cadre — et une barre de puces de 26 px.

   Taille et couleur des flèches viennent des réglages du widget. Ne restent ici que leur
   décalage, qu'Elementor place à 10 px, et le zoom au repos de l'image.
   ========================================================================== */

/* DEUX classes sur l'enveloppe, une de plus qu'Elementor : il pose `left: 10px` avec
   `.elementor-widget-image-carousel .elementor-swiper-button-prev`, deux classes comme les
   miennes, et son `<style>` en ligne s'imprime après cette feuille. Cinquième occurrence du
   mécanisme dans ce fichier — la règle de travail est notée plus haut. */
.dedienne-qi-image-slider.elementor-widget .elementor-swiper-button-prev {
    left: 30px;
}

.dedienne-qi-image-slider.elementor-widget .elementor-swiper-button-next {
    right: 30px;
}

/* ---- La barre de puces chevauche le bas de l'image ----

   Relevé sur la production : la boîte des puces fait 26 px et commence 10 px AVANT la fin de
   l'image — de 237,09 à 263,09 pour une image qui s'arrête à 247,09 — si bien que les pastilles
   se posent sur l'arête basse de la photo. Elementor réserve 30 px sous le cadre et y place les
   puces en dessous, sans chevauchement.

   D'où 26 px de remplissage et un décalage de 10 : la boîte remonte sur l'image et la hauteur
   totale du widget retombe sur les 273 de la production. */
.dedienne-qi-image-slider.elementor-widget .swiper {
    padding-bottom: 26px;
}

/* CINQ classes, et ce n'est pas de la surenchère : `custom-frontend-lite.min.css` pose
   `bottom: 5px` avec `.elementor-element .swiper .swiper-pagination-bullets.swiper-pagination-horizontal`,
   soit quatre. Trouvé par winning-rule.mjs, qui évite d'empiler des classes à l'aveugle. */
.dedienne-qi-image-slider.elementor-element .swiper .swiper-pagination-bullets.swiper-pagination-horizontal {
    bottom: 10px;
}

/* ---- Le zoom au repos ----

   `image_hover: zoom` chez qi ne s'applique pas au survol seulement : la boîte de l'image
   mesure 395,76 pour une largeur déclarée de 388, soit un facteur 1,02 DÈS LE REPOS. Même
   parti pris que la carte d'article, dont l'image est à 1,05 au repos, et que le carrousel
   d'équipe. Le conteneur rogne, ce que Swiper fait déjà. */
.dedienne-qi-image-slider .swiper-slide img {
    transform: scale(1.02);
    transition: transform .6s cubic-bezier(.475, .425, 0, .995);
    will-change: transform;
}

/* ==========================================================================
   Modèle d'article portfolio-item — remplissage horizontal sous 1025 px

   Le modèle a été construit et validé à 1440 px seulement. Relevé ensuite aux autres
   largeurs sur la production : sa grille de contenu suit la FENÊTRE, et le local n'en
   posait rien — sa colonne prenait toute la largeur, ce qui rendait les treize widgets du
   corps plus larges de 56 px à 480. Le défaut portait donc sur les 35 articles.

     fenêtre   colonne de contenu   part de la fenêtre   remplissage par côté
      1024     798                  77,9 %                113
       768     690,47               89,9 %                 38,8
       680     614,80               90,4 %                 32,6
       600     546                  91 %                   27
       480     423,59               88,3 %                 28,2
       375     337,50               90 %                   18,75

   En POURCENTAGE, seule écriture qui suive la fenêtre comme le fait borgholm — un padding en
   pixels serait juste à une largeur et faux aux autres. Et en CSS et non dans le contrôle
   Elementor : celui-ci applique une seule unité aux quatre côtés, si bien qu'un pourcentage
   ferait résoudre le remplissage VERTICAL sur la largeur — 150 % à 768 px feraient 1152 px.

   L'empilement de la barre latérale, lui, est dans le modèle : `_inline_size_tablet: 100`.
   ========================================================================== */

/* Sur le CONTENEUR INTERNE de la section, non sur la section elle-même : le modèle règle le
   remplissage de la section — 300px 0 100px au bureau, 50px 0 50px en mobile — et Elementor
   l'écrit avec trois classes, dont un `padding-right: 0` qui l'emportait sur le mien. Le
   conteneur interne, lui, n'a aucune règle concurrente. */
/* ---- CORRECTION du 2026-08-26 : ce n'etait pas un pourcentage, mais des paliers ----

   Ce bloc posait `max-width: min(82.6%, 1130px)` au-dessus de 1024, plus un remplissage de 11 %
   sous 1024 et de 5 % sous 768. Le raisonnement etait : la colonne fait 1130 a 1440 et a 1366, mais
   990 a 1200, et comme 990 / 1200 = 82,5 % et 1130 / 1366 = 82,7 %, c'est un pourcentage plafonne.

   Deux largeurs mesurees, et ce sont precisement les deux ou un pourcentage et des paliers donnent
   le meme nombre. Les largeurs qui les separent le disent :

       fenetre        1100    1280
       82,6 %          909    1057
       paliers         990    1130
       PRODUCTION      990    1130

   Ce sont donc des paliers, et le local servait bien 909 et 1057 — l'ecart signale par Jerem.

   Sa propre table de mesures le confirmait sans qu'il le voie : 798 a 1024, 690,47 a 768, 614,80 a
   680, 546 a 600, 423,59 a 480, 337,50 a 375. Toutes ces valeurs sont `86 % + 30` puis `82 % + 30`,
   c'est-a-dire les paliers de la grille de borgholm augmentes de la gouttiere. Les pourcentages
   qu'il en avait tires — 89,9 %, 90,4 %, 91 % — variaient d'une ligne a l'autre, ce qui aurait du
   alerter : un vrai pourcentage ne varie pas.

   L'echelle complete est en fin de feuille, section « Cadre du gabarit Portfolio Item — Article ».
   Les regles de ce bloc sont retirees : elles la contrediraient. */

/* ==========================================================================
   Onglets de /locations/ — eael-adv-tabs converti en `tabs` natif

   Deux instances : verticale au bureau, horizontale à 1024 et en dessous. Le contenu de
   chaque onglet est un modèle de la bibliothèque, rendu par `[elementor-template]`.

   Relevé sur la production :

     BUREAU vertical, colonne 1140
       liste 136 x 230 en colonne · onglet 136 x 46, remplissage 15px 50px 5px 0
       actif #FE5000 · panneau 1004 x 513,47 à x=136, remplissage 15px 0 0, texte #333
     TABLETTE horizontal, colonne 568
       liste 568 x 56 en ligne · onglet 96 x 26, marge 0 0 30px · panneau à y=56
     MOBILE, colonne 420
       liste 420 x 52 · onglet 100,25 x 26, remplissage 0 10px 0 0 · panneau à y=52,
       remplissage 30px 0 0

   Elementor arrive avec 20px 25px de remplissage, une graisse 700, un interligne de 15px et
   un filet #D5D8DC : tout est à défaire.
   Chaque sélecteur porte DEUX classes sur l'enveloppe du widget, une de plus qu'Elementor :
   `widget-tabs.min.css` pose `padding: 20px 25px`, `font-weight: 700` et `line-height: 1` avec
   `.elementor-widget-tabs .elementor-tab-title`, et s'imprime après cette feuille. Huitième
   occurrence du mécanisme dans ce fichier. Indice utile au passage : la marge, elle, avait pris
   du premier coup — Elementor n'en déclare pas sur cet élément, donc rien ne s'y opposait.
   ========================================================================== */

/* ---- Le natif bascule en ACCORDÉON sous 768 px, la production non ----

   `widget-tabs.min.css` masque la liste d'onglets dès **1024 px** — et non 767 comme on
   l'attendrait d'un palier mobile — puis révèle des titres dupliqués intercalés entre les
   panneaux, d'où les dix titres relevés au lieu de cinq. Aucun contrôle ne le désactive dans
   cette version : c'est écrit dans sa feuille.

   L'override a d'abord été borné à 767, et le résultat était le pire des deux : ma déclaration
   `display: flex` sur la liste, elle, n'était pas bornée et révélait la liste à 768 pendant que
   ses titres mobiles restaient visibles. Les deux jeux s'affichaient, et le panneau démarrait
   56 px trop bas — la hauteur d'un titre mobile et de sa marge.

   La production, elle, garde ses onglets horizontaux jusqu'en bas. On rétablit donc la liste et
   on masque les titres mobiles. Les cinq titres dupliqués restent dans le DOM, invisibles —
   c'est le prix du widget natif, et il ne coûte que quelques octets. */
@media only screen and (max-width: 1024px) {

    .dedienne-adv-tabs.elementor-widget .elementor-tabs-wrapper {
        display: block;
    }

    /* QUATRE classes : le titre mobile porte `elementor-tab-title` ET
       `elementor-tab-mobile-title`, et la règle qui le révèle compte trois classes. Sonde
       trompeuse au passage — `winning-rule.mjs` annonçait `display: none` parce qu'il
       interrogeait le PREMIER élément du document, celui du widget de bureau, lui-même masqué
       à cette largeur. Vérifier sur l'élément réellement rendu, pas sur son homonyme. */
    .dedienne-adv-tabs.elementor-widget .elementor-tab-title.elementor-tab-mobile-title {
        display: none;
    }
}

/* ---- Typographie et remplissage ---- */

.dedienne-adv-tabs.elementor-widget .elementor-tab-title {
    font-weight: 400;
    /* Interligne du corps, celui de la production : 15px x 1,733. */
    line-height: 1.733;
    border: 0;
}

.dedienne-adv-tabs.elementor-widget .elementor-tab-content,
.dedienne-adv-tabs.elementor-widget .elementor-tabs-content-wrapper {
    border: 0;
}

/* La disposition verticale du bureau. */
.dedienne-adv-tabs--vertical.elementor-widget .elementor-tab-title {
    padding: 15px 50px 5px 0;
}

.dedienne-adv-tabs--vertical.elementor-widget .elementor-tab-content {
    padding: 15px 0 0;
}

/* ---- L'horizontale : une ligne FLEX dont les onglets s'étirent ----

   Elementor dispose ses onglets horizontaux en TABLE — `display: table` sur la liste,
   `table-cell` sur les titres — ce qui a deux conséquences : les marges y sont ignorées, si bien
   que les 30 px de la production restaient sans effet, et la répartition n'est pas la sienne.

   Relevé sur la production : liste en `flex`, titres en `flex: 1 1 auto`. À 768 les cinq tracés
   font 67 + 52 + 86 + 82 + 136 = 423 dans une liste de 568, et les 145 restants se répartissent
   en 29 par onglet — 96, 81, 115, 111, 165, exactement les largeurs mesurées. À 480 la somme
   dépasse la largeur et la ligne se replie en deux rangs de 26, d'où la liste de 52. */
.dedienne-adv-tabs--horizontal.elementor-widget .elementor-tabs-wrapper {
    display: flex;
    flex-wrap: wrap;
}

.dedienne-adv-tabs--horizontal.elementor-widget .elementor-tab-title {
    display: block;
    flex: 1 1 auto;
}

/* L'horizontale, à 1024 et en dessous : les onglets n'ont pas de remplissage mais 30 px de
   marge basse, et le panneau vient juste dessous. */
.dedienne-adv-tabs--horizontal.elementor-widget .elementor-tab-title {
    padding: 0;
    margin: 0 0 30px;
}

.dedienne-adv-tabs--horizontal.elementor-widget .elementor-tab-content {
    padding: 0;
}

/* En mobile la marge basse disparaît et un remplissage droit sépare les libellés. */
@media only screen and (max-width: 767px) {

    .dedienne-adv-tabs--horizontal.elementor-widget .elementor-tab-title {
        padding: 0 10px 0 0;
        margin: 0;
    }

    .dedienne-adv-tabs--horizontal.elementor-widget .elementor-tab-content {
        padding: 30px 0 0;
    }
}

/* ==========================================================================
   Tableau d'allongement de boulon — article « torke »

   `htmega-datatable-addons` converti en table HTML dans un widget `html` natif : une seule
   instance sur tout le site, contenu statique. Cinq colonnes, cinq rangs dont un VIDE — le
   double marqueur de rang de htmega, que la production affiche et qu'on garde.

   Relevé sur la production :
     table      797,50 x 174 à 1440 · 373,59 x 252 à 480, sans bordure propre
     entête     134,84 x 33, remplissage 3px, filet 1px solid #000
                Montserrat 12px / 700, fond blanc, centré
     cellule    134,84 x 35, remplissage 4px, filet 1px solid #000
                Work Sans 14px / 400, fond blanc, centré

   La première colonne est plus large — 258 contre 134,84 — parce que ses libellés sont plus
   longs. C'est le dimensionnement automatique d'une table, il n'y a rien à poser.
   ========================================================================== */

.dedienne-torque-table {
    width: 100%;
    /* Les filets sont posés cellule par cellule en production, et ils ne se doublent pas :
       les bords sont donc fusionnés. */
    border-collapse: collapse;
}

.dedienne-torque-table th,
.dedienne-torque-table td {
    border: 1px solid #000;
    background-color: #fff;
    text-align: center;
    vertical-align: middle;
}

.dedienne-torque-table th {
    padding: 3px;
    font-family: Montserrat, sans-serif;
    font-size: 12px;
    font-weight: 700;
}

.dedienne-torque-table td {
    padding: 4px;
    font-family: "Work Sans", sans-serif;
    font-size: 14px;
    font-weight: 400;
}

/* ==========================================================================
   Colonne latérale de /blog/ — espacement et liste des catégories

   La zone `shop-sidebar` est rendue par un widget `sidebar` d'Elementor, qui se contente
   d'appeler `dynamic_sidebar()` : les trois widgets sortent frères dans son conteneur,
   sans aucune des règles de mise en page que borgholm posait sur `#qodef-page-sidebar`.
   Relevé à 1440 dans une colonne de 237,50 :

       #qodef-page-sidebar   237,50 x 423,84   inline-block, marge 0 0 60px
       widget_search         237,50 x 31       marge 0 0 35px      <- lot 5b
       widget_categories     237,50 x 65,67    marge 0 0 35px      = 26,67 + 13 + 26
       blog_list « Related » 237,50 x 257,17   marge 0             = 26,67 + 13 + 217,50

   Les 35 px séparent les widgets sans s'ajouter sous le dernier — d'où le `:last-child`.

   ---- La liste des catégories est en Cormorant, et ce n'est pas un écart de kit ----

   `li` et son lien sortent en Cormorant 18px / 700, #464646, quand tout autour est en
   Work Sans 15px / 400. C'est la règle de borgholm sur les listes de colonne latérale, et
   elle est reproduite : Cormorant 700 est bien servie en local par OMGF
   (`uploads/omgf/google-fonts-593/`), aux côtés de Work Sans et Montserrat. Le kit
   Elementor normalisé reste la référence pour les TAILLES DE TITRE — ce qui est en jeu
   ici est le corps d'une liste, que le kit ne décrit pas.

   Le lien porte un souligné qui se dessine depuis la gauche : un `::before` absolu de
   0 x 1 px en #FE5000, qui passe à 100 % de large au survol, en même temps que le texte
   devient orange. Les deux en 0,2 s, comme la production.

   ---- Ce qui reste en écart, et pourquoi ----

   WordPress enveloppe la liste des catégories dans un `<nav aria-label="Category">` que la
   production ne sert pas. Aucun filtre ne permet de l'ôter, et l'élément est un bloc sans
   marge ni remplissage : il ne déplace rien. Les sélecteurs ci-dessous sont donc en
   descendance, et non en enfant direct.

   `widget_search` rend toujours le formulaire de WordPress au lieu de celui de borgholm :
   31 px en production contre 40 en local. Inscrit au lot 5b, avec le gabarit de formulaire
   et son glyphe ElegantIcons.
   ========================================================================== */

/* Les 60 px sous la colonne, invisibles à 1440 — le contenu est plus haut — mais réels dès
   1024, où la colonne empilée est le dernier bloc avant le remplissage bas de la section.
   `#qodef-page-sidebar` est en `inline-block` en production ; on reste en bloc : l'espace de
   jambage qu'ajouterait un `inline-block` ne se retrouve pas dans les mesures de la
   production, dont la colonne parente fait exactement l'aside plus ces 60 px. */
.dedienne-blog-sidebar {
    margin-bottom: 60px;
}

.dedienne-blog-sidebar .widget {
    margin-bottom: 35px;
}

.dedienne-blog-sidebar .widget:last-child {
    margin-bottom: 0;
}

.dedienne-blog-sidebar .qodef-widget-title {
    margin: 0 0 13px;
}

.dedienne-blog-sidebar .widget_categories ul,
.dedienne-blog-sidebar .widget_categories li {
    margin: 0;
    padding: 0;
    list-style: none;
}

.dedienne-blog-sidebar .widget_categories li {
    font-family: Cormorant, serif;
    font-size: 18px;
    font-weight: 700;
    color: #464646;
}

.dedienne-blog-sidebar .widget_categories li a {
    position: relative;
    color: inherit;
    transition: color .2s;
}

.dedienne-blog-sidebar .widget_categories li a::before {
    content: '';
    position: absolute;
    left: 0;
    bottom: 0;
    width: 0;
    height: 1px;
    background-color: #FE5000;
    transition: width .2s;
}

.dedienne-blog-sidebar .widget_categories li a:hover {
    color: #FE5000;
}

.dedienne-blog-sidebar .widget_categories li a:hover::before {
    width: 100%;
}

/* ==========================================================================
   `.qodef-content-grid` — le cadre de contenu du site, à ses quatre paliers

   Ce n'est PAS une particularité de page : `.qodef-content-grid` est une classe du thème,
   posée sur tout le contenu du site. Le même modèle sert donc ici deux points d'accroche —
   la section de /blog/ et le conteneur du modèle « Template Job offer » — et servira les
   suivants.

   Il n'a pas une largeur mais QUATRE, relevées sur seize largeurs de fenêtre pour trouver
   les bornes :

       > 1200        1100 px fixes
       1025 – 1200    960 px fixes
       ≤ 1024        86 %, plafonné à 768 px
       ≤  480        82 %

   Le plafond de 768 explique les valeurs intermédiaires : à 900 px, 86 % vaudrait 774, donc
   la production sert 768 ; à 769 px, 86 % vaut 661,33 et c'est cette valeur qui sort. Un
   modèle en paliers fixes n'aurait pas reproduit ça.

   `content_width` du widget vaut 1100 : juste au-delà de 1200, faux en dessous. Le palier à
   960 manquait donc de 1025 à 1200, où le local servait 1100 — un écart de 140 px que le
   relevé à 1440 seul ne pouvait pas montrer.

   La borne est à 1200 et non à 1366 : relevée à douze largeurs entre 1367 et 1200, la
   production sert 1100 jusqu'à 1201 inclus — où il ne reste que 50 px de marge de chaque
   côté — et bascule à 960 exactement à 1200. C'est aussi l'un des paliers Elementor actifs
   du site (`tablet_extra`). Un premier jet bornait à 1366 et rétrécissait les cartes de
   /blog/ de 812,50 à 709 entre 1201 et 1366.

   ---- Deux mécanismes, parce que les deux accroches n'ont pas la même nature ----

   Une SECTION Elementor plafonne son `.elementor-container`. `winning-rule.mjs` sur /blog/ :
   la règle gagnante est
   `.elementor-2862 .elementor-element.elementor-element-67b4246 > .elementor-container`,
   dans post-2862.css, soit QUATRE classes — et cette feuille est chargée après le thème
   enfant, donc une égalité à quatre perdrait. D'où la chaîne à cinq, qui n'ajoute que des
   classes déjà portées par la section.

   Un CONTENEUR flex, lui, plafonne son `.e-con-inner` par la variable
   `--container-max-width`. On ne passe pas par elle : on la neutralise à `100 %` et on donne
   la largeur au conteneur LUI-MÊME, ce qui reproduit exactement la chaîne de la production —
   `.qodef-content-grid` à 1100 px, son remplissage de 10 px à l'intérieur, les colonnes
   ensuite. Plafonner l'enfant aurait mis les 10 px dehors et décalé les colonnes de 14 px.
   Deux classes suffisent ici : la règle à battre est le `.e-con` du kit, qui n'en a qu'une.

   Troisième cas, `.dedienne-title-grid` : un bandeau qui doit rester PLEINE LARGEUR — son fond
   court d'un bord à l'autre — mais dont le contenu suit le cadre. Là il faut bien plafonner
   l'enfant, et non le conteneur. Le bandeau porte un remplissage NUL, comme
   `.qodef-page-title` : c'est aussi ce qui fait résoudre les pourcentages sur la fenêtre
   entière et non sur la fenêtre moins vingt pixels.

   ---- Deux écarts de HAUTEUR de carte qui restent, tous deux caractérisés ----

   1. Le titre de carte est un `h1`, sans typographie propre : il prend donc les paliers du
      kit Elementor — 45px, 40px sous 1025, 30px sous 768. La production, elle, tient 45px
      partout. D'où −10 px par carte à 1024 et à 768 (un titre de deux lignes), et −120 px à
      480 (quatre lignes chez elle, deux chez nous). Le kit normalisé étant la référence
      typographique retenue, il garde la main : l'écart est signalé, pas corrigé.

   2. Sous 681 px, `.qodef-info--bottom` de la production passe en `inline-block` et empile
      ses deux moitiés. La moitié droite ne contient qu'un bloc de partage social **vide** —
      mesuré à 2 x 26,3 px, dont le contenu fait 0 px de large. Avec ses 29 px d'écart, elle
      réserve 55,3 px de vide sous CHAQUE carte, soit 276 px sur une page de cinq. Ce n'est
      pas une mise en page à reproduire : c'est un élément sans contenu qui occupe de la
      place. Non reproduit, signalé.

   Ces deux écarts additionnés expliquent exactement les 175,1 px de différence de hauteur de
   carte relevés à 480 : 120 pour le titre, 55,1 pour le bloc vide.
   ========================================================================== */

.dedienne-content-grid.e-con {
    width: 100%;
    max-width: 1100px;
    margin-inline: auto;
    /* Neutralisée : c'est le conteneur qui porte la largeur, pas son enfant. */
    --container-max-width: 100%;
}

/* ---- Le palier VERS LE HAUT, qui manquait ----

   Les paliers descendants etaient bien la — 960 sous 1200, 768 sous 1024, 82 % sous 480 — mais rien
   au-dessus : la grille restait plafonnee a 1100 quelle que soit la largeur. La production passe a
   1400. Regle d'origine, relue dans `borgholm/assets/css/main.css` :

     @media only screen and (min-width: 1441px) {
       .qodef-content-grid-1400 .qodef-content-grid { width: 1400px }
     }

   La classe `qodef-content-grid-1400` est posee sur le `body` par une option du theme, donc le
   palier vaut pour TOUTE la grille du site — d'ou les trois selecteurs ici, comme pour les paliers
   descendants.

   Releve de la production, meme page : 1100 a 1280, 1366, 1400 et 1440, puis 1400 a 1441, 1500,
   1600, 1800, 1920, 2200 et 2560. Le palier est unique et la grille ne croit plus ensuite — ce n'est
   pas une largeur fluide, c'est un cran.

   Signale par Jerem sur /job-offers/stores-logistics-executive-m-f/, ou la colonne de contenu
   restait a 691 px la ou la production lui en donne 892 au-dela de 1440. Le seuil etant a 1441, le
   releve `doc-diff` a 1440 n'est pas touche. */

@media only screen and (min-width: 1441px) {

    .dedienne-blog-section.elementor-element.elementor-section.elementor-top-section.elementor-section-boxed > .elementor-container {
        max-width: 1400px;
    }

    .dedienne-content-grid.e-con {
        max-width: 1400px;
    }

    /* Elargir le conteneur ne suffit pas : son `.e-con-inner` restait plafonne a 1100 et la colonne
       de contenu ne gagnait rien — mesuree a 705 px la ou la production en donne 892. La
       neutralisation `--container-max-width: 100 %` de la regle de base est reprise par le CSS du
       kit dans sa propre requete de media, qui est chargee apres le theme. On plafonne donc l'enfant
       DIRECTEMENT, a 100 %, ce qui le laisse suivre son conteneur. */
    .dedienne-content-grid.e-con > .e-con-inner {
        max-width: 100%;
    }

    .dedienne-title-grid.e-con > .e-con-inner {
        max-width: 1400px;
    }

    /* ---- Les sections du CONTENU du post s'elargissent aussi ----

       Elargir le cadre ne suffisait pas : le contenu restait a 847 px la ou la production en donne
       1158. La section du contenu est en `layout: full_width`, donc sans plafond chez Elementor, et
       elle se contentait de remplir sa colonne de 1043.

       Borgholm ajoute a ces sections une classe `qodef-elementor-content-grid` et les plafonne au
       cadre. Regle trouvee en interrogeant le navigateur, dans le CSS agrege de la production :

         @media only screen and (min-width: 1441px) {
           .qodef-content-grid-1400 section.qodef-elementor-content-grid > .elementor-container
             { max-width: 1400px }
         }

       Le conteneur devient donc PLUS LARGE que sa section — 1400 pour 1043 — et deborde vers la
       droite. C'est bien ce que fait la production, mesure a l'appui : section 1043@260, conteneur
       1400@260.

       La classe n'existe pas en local. On vise donc les sections pleine largeur DU CONTENU du post,
       et seulement elles : la page en porte d'autres, dont une de 1920 px qui doit le rester.

       `width` et NON `max-width` : un plafond n'agrandit pas une boite, et la premiere version n'a
       rien change — le conteneur restait a 1042,5 avec un `max-width: 1400px` inerte. C'est une
       largeur imposee qu'il faut, et la marge droite negative de −357,5 px que la production affiche
       n'est pas une regle : c'est la resolution automatique d'un bloc plus large que son parent.

       Sous 1441, la production laisse ce conteneur a 100 % — mesure 817,5 px a 1440 et 712,5 a 1200,
       ce que le local fait deja. Son palier a 1100 px existe bien dans le CSS de borgholm mais perd
       contre un `width: 100 %` d'une feuille plus tardive ; seul le cran de 1441, plus specifique
       d'une classe, l'emporte. On ne reproduit donc que celui-la.

       ---- RETRAIT du 2026-08-27 : la fidélité s'arrêtait ici ----

       Ce qui précède est exact et la mesure était juste : au-dessus de 1440, la production sert bien
       un conteneur de 1400 px dans une section de 1042,5. Elle **déborde donc de 357,5 px vers la
       droite**, et le contenu passe sous la colonne latérale du gabarit.

       Signalé par Jérém sur /p-i/shock-absorbers-engine-stand/ : « la colonne de texte de gauche est
       trop large, cela déborde sous la sidebar ». Puis sa décision, sans ambiguïté : « la production
       était déjà cassée là-dessus donc il ne faut pas faire pareil qu'en production ».

       La règle est donc retirée, et non corrigée : sans elle le conteneur retombe sur le
       comportement par défaut d'Elementor — 100 % de sa section — qui est exactement ce que le local
       fait déjà sous 1441. Rien à écrire, il suffit de ne plus imposer la largeur.

       ---- Mesure du retrait, sur les NEUF pages de la famille, à 1600 et à 1920 ----

       Éléments dont le bord droit sort de la section, avant → après :

           shock-absorbers-engine-stand              149 → 0     (pire écart 357,5 → 0)
           how-to-work-the-torke-…                    20 → 0
           les sept autres                             7 → 0

       Et le conteneur passe de 1400 à 1042,5 partout, soit la largeur de sa section.

       ---- Une fausse piste, notée pour ne pas la reprendre ----

       Un compteur d'éléments « hors FENÊTRE » signalait 21 fautifs sur
       `/p-i/how-to-work-the-torke-to-properly-tighten-a-nut-to-a-bolt/`, avant comme après le
       retrait. Ce n'est pas un défaut : ce sont les diapositives d'un carrousel Swiper, que la
       piste garde positionnées hors du cadre visible — 143 en production, 25 en local, ce qui est
       le fonctionnement normal. Un débordement hors fenêtre n'est un symptôme que si l'élément est
       censé être dans le flux ; sur une page à carrousel, ce compteur ne veut rien dire.

       ---- Pourquoi le commentaire reste alors que la règle part ----

       Parce que la mesure qui l'avait fait écrire est toujours vraie : quiconque relèvera la
       production au-dessus de 1440 retrouvera ses 1400 px et sera tenté de la remettre. La trace dit
       que l'écart est ASSUMÉ, et par qui. */
}

@media only screen and (max-width: 1200px) {

    .dedienne-blog-section.elementor-element.elementor-section.elementor-top-section.elementor-section-boxed > .elementor-container {
        max-width: 960px;
    }

    .dedienne-content-grid.e-con {
        max-width: 960px;
    }

    .dedienne-title-grid.e-con > .e-con-inner {
        max-width: 960px;
    }
}

@media only screen and (max-width: 1024px) {

    .dedienne-blog-section.elementor-element.elementor-section.elementor-top-section.elementor-section-boxed > .elementor-container {
        width: 86%;
        max-width: 768px;
    }

    .dedienne-content-grid.e-con {
        width: 86%;
        max-width: 768px;
    }

    .dedienne-title-grid.e-con > .e-con-inner {
        width: 86%;
        max-width: 768px;
    }
}

@media only screen and (max-width: 480px) {

    .dedienne-blog-section.elementor-element.elementor-section.elementor-top-section.elementor-section-boxed > .elementor-container {
        width: 82%;
    }

    .dedienne-content-grid.e-con {
        width: 82%;
    }

    .dedienne-title-grid.e-con > .e-con-inner {
        width: 82%;
    }
}

/* ==========================================================================
   Formulaire de recherche — reprise de celui de borgholm

   Le balisage vient de `searchform.php`, posé dans ce thème : `get_search_form()` le trouve
   avant tout le reste, ce qui suffit à aligner TOUS les `widget_search` du site — la colonne
   latérale de /blog/, celle des articles, la zone latérale. hello-elementor n'a pas de
   `searchform.php`, et WordPress servait donc son formulaire par défaut : un `label` visible,
   un `input.search-field` et un bouton `input[type=submit]`, 79 px de haut contre 31.

   Géométrie relevée sur la production, /blog/ à 1440 dans une colonne de 237,50 :

       form            237,50 x 31, bloc, sans bordure
       inner           237,50 x 31, inline-block, position relative
       champ           237,50 x 31, remplissage 5px 50px 5px 0, filet bas 1px solid #000
                       Cormorant 17px / 500 ITALIQUE, hauteur de ligne 20px, fond transparent
                       placeholder « Search... », en #000 à pleine opacité

   L'italique n'a pas été vu au relevé des styles calculés : `font-style` ne figurait pas dans
   la liste des propriétés lues. C'est la comparaison d'IMAGES qui l'a montré — un « Search... »
   penché d'un côté, droit de l'autre, sur 1,03 % de pixels différents. Un rappel utile : le
   relevé de styles ne dit que ce qu'on lui demande, la capture montre ce qui est.
       bouton          50 x 31, absolu à droite, flex centré, transparent, curseur pointer
       bouton::before   14 x 11 à right -6px, la pointe de flèche
       bouton::after    34 x 2  à right  2px, la barre noire

   La hauteur de 31 n'est pas posée : elle se calcule — 5 + 20 + 5 + 1 de filet, en
   `border-box`. La poser en dur casserait au premier changement de corps.

   ---- La pointe de flèche, encore un glyphe ElegantIcons ----

   `content: "\45"` en ElegantIcons, à 11 px : le MÊME glyphe que le bouton « read more » des
   cartes de /blog/, dont l'encre a été mesurée dans un canvas sur la production — avance 11,00,
   encre 3,40 x 5,50, débutant à 4,10 du tracé. On reprend donc le même SVG, dans une boîte de
   14 et non 13,2 : le `letter-spacing` hérité vaut ici 3 px au lieu de 2,2, et c'est lui qui
   fixe l'avance. Les coordonnées du tracé ne changent pas, elles sont absolues.

   La largeur de 14 px est écrite en dur plutôt que laissée au `letter-spacing` : le SVG n'a pas
   d'avance typographique à hériter, et dépendre d'une propriété de texte pour la taille d'une
   image serait fragile.

   Au survol la pointe glisse de -6 à -16 px et la barre s'étire en scaleX(1,3), toutes deux en
   0,2 s — valeurs relevées sur `transition-property` et `transition-duration`.

   ---- `.screen-reader-text` ----

   Le `label` du champ existe pour l'accessibilité et doit rester hors écran. Aucun des deux
   thèmes ne définit cette classe : sans elle, « Search for: » s'afficherait au-dessus du champ.
   Version standard de WordPress, par `clip-path`, plutôt que le `top: -150000px` de qode : même
   effet de mise en page — une boîte de 1 x 1 hors flux — et une méthode qui n'invente pas une
   position absurde.
   ========================================================================== */

.screen-reader-text {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(1px, 1px, 1px, 1px);
    clip-path: inset(50%);
    border: 0;
    word-wrap: normal !important;
}

.qodef-search-form {
    display: block;
}

.qodef-search-form .qodef-search-form-inner {
    position: relative;
    display: inline-block;
    width: 100%;
    vertical-align: top;
}

.qodef-search-form .qodef-search-form-field {
    position: relative;
    display: inline-block;
    width: 100%;
    margin: 0;
    padding: 5px 50px 5px 0;
    border: 0;
    border-bottom: 1px solid #000;
    border-radius: 0;
    background-color: transparent;
    font-family: Cormorant, serif;
    font-size: 17px;
    font-style: italic;
    font-weight: 500;
    line-height: 20px;
    color: #000;
    vertical-align: top;
    box-sizing: border-box;
    outline: 0;
}

.qodef-search-form .qodef-search-form-field::placeholder {
    color: #000;
    opacity: 1;
}

.qodef-search-form .qodef-search-form-button {
    position: absolute;
    top: 0;
    right: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 50px;
    height: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    background-color: transparent;
    color: #464646;
    cursor: pointer;
}

.qodef-search-form .qodef-search-form-button::before {
    content: '';
    position: absolute;
    top: 50%;
    right: -6px;
    width: 14px;
    height: 11px;
    background-repeat: no-repeat;
    background-position: 0 0;
    background-size: 14px 11px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 11'%3E%3Cpolygon fill='%23000' points='4.1,2.75 7.5,5.5 4.1,8.25'/%3E%3C/svg%3E");
    transform: translateY(-50%);
    transition: all .2s ease-in-out;
}

.qodef-search-form .qodef-search-form-button::after {
    content: '';
    position: absolute;
    top: 50%;
    right: 2px;
    width: 34px;
    height: 2px;
    background-color: #000;
    transform: translateY(-50%);
    transform-origin: left center;
    transition: all .2s ease-in-out;
}

.qodef-search-form .qodef-search-form-button:hover::before {
    right: -16px;
}

.qodef-search-form .qodef-search-form-button:hover::after {
    transform: translateY(-50%) scaleX(1.3);
}

/* Le fond du bouton ne change PAS au survol, et il faut le dire explicitement.

   Le kit Elementor habille tous les boutons du site, et son état survolé les remplit de noir :

       .elementor-kit-6675 button:hover, ..:focus, input[type=button]:hover, .elementor-button:hover
           background-color: var( --e-global-color-accent )   #000
           color:            var( --e-global-color-text )     #F5F5F5

   Cette règle a une spécificité de (0,2,1) et bat donc `.qodef-search-form
   .qodef-search-form-button`, à (0,2,0), qui ne pose `transparent` qu'à l'état de repos. Au
   survol, le bouton devenait noir — et la flèche, dessinée en noir par ses deux
   pseudo-éléments, DISPARAISSAIT dans ce fond. Relevé au calculé :

       repos    background-color: rgba(0, 0, 0, 0)
       survol   background-color: rgb(0, 0, 0)      ::after background-color: rgb(0, 0, 0)

   Le geste du bouton est le mouvement de la flèche — la pointe qui glisse de -6 à -16 px et la
   barre qui s'étire en scaleX(1,3), juste au-dessus. Un fond qui change en plus était déjà de
   trop ; un fond qui change EN CACHANT le geste est un défaut.

   Le remède vit ici et non dans le greffon Toolfinder : le défaut touche TOUS les
   `.qodef-search-form` du site — vérifié sur la colonne latérale de /blog/, qui l'avait avant
   le widget Toolfinder. Une règle dans le greffon aurait corrigé une page sur deux.

   `:focus` autant que `:hover` : la règle du kit vise les deux, donc la navigation au clavier
   faisait disparaître la flèche exactement de la même façon. */
.qodef-search-form .qodef-search-form-button:hover,
.qodef-search-form .qodef-search-form-button:focus,
.qodef-search-form .qodef-search-form-button:focus-visible {
    background-color: transparent;
    color: #464646;
}

/* ==========================================================================
   Page de résultats de recherche

   La production sert une LISTE à une colonne — vignette de 150 px à gauche, titre et extrait à
   droite — précédée d'un bloc « New search: » avec son formulaire. Le gabarit local rendait un
   `archive-posts` en grille de quatre colonnes, et aucun formulaire : la page ne proposait
   aucun moyen de relancer une recherche depuis ses propres résultats.

   Gabarits de borgholm relus dans git, le thème étant supprimé du disque :
   `inc/search/templates/parts/post.php` et ses trois parties.

   Géométrie relevée sur /?s=nacelle à 1440, dans un cadre de 1100 :

       entête              1100 x 109,94, marge basse 60
         h3                26,67, Work Sans 25px / 300, marge 0 0 20   <- déjà le kit
         formulaire        31
         libellé           24,27, Work Sans 14px / 400, marge 8px 0 0
       item                1100 x 128,41, marge basse 30
         image             flex: 0 1 180px, remplissage 0 30px 0 0
         contenu           flex: 0 1 auto
         titre h4          15px / 300, interligne 17,505
         extrait           14px, interligne 24,262, marge 15px 0 0
       pagination          26, marge haute 50

   ---- Les 158,41 px de la colonne d'image ne sont pas une valeur ----

   La base de 180 px se fait rétrécir par `flex-shrink: 1` face au contenu, et c'est ce qui
   produit les 158,41 relevés. On déclare donc les mêmes propriétés, pas le résultat : le poser
   en dur casserait à la première autre largeur de cadre.

   ---- `:not(:has(img))` ----

   borgholm ne rend AUCUNE colonne d'image quand le contenu n'a pas de vignette — six résultats
   sur dix en ont une. Le widget natif, lui, rend un conteneur vide, qui occuperait les 180 px.
   D'où cette règle. `:has()` est acquis dans tous les navigateurs courants ; sur un navigateur
   qui l'ignore, les quatre résultats sans image gagneraient une colonne vide de 158 px — un
   décalage, pas une casse.

   ---- Le h4 ----

   Le kit déclare `h4_typography_typography: custom` SANS aucune valeur : un h4 n'hérite donc
   d'aucune taille du kit et retombe sur le corps, 15px / 400. La production le sert en 15px /
   300 avec un interligne de 17,505. Seuls le poids et l'interligne sont donc à poser — la
   taille est déjà la bonne, par accident.
   ========================================================================== */

.dedienne-sr-image {
    flex: 0 1 180px;
    padding-right: 30px;
}

.dedienne-sr-image:not(:has(img)) {
    display: none;
}

.dedienne-sr-content {
    flex: 0 1 auto;
    /* ---- `min-width: auto`, et c'est tout l'enjeu à 480 px ----

       Elementor pose `min-width: 0` sur ses conteneurs pour les laisser rétrécir librement.
       `.qodef-e-content` de la production est un `div` nu, donc en `min-width: auto` : il ne
       descend pas sous sa largeur de contenu minimale, et c'est la colonne d'IMAGE qui cède.
       Relevé à 480 : l'image y fait 130,3 en production contre 180 en local avant cette règle,
       ce qui rendait le contenu plus étroit et l'item 77 px plus haut. À 1024 et 768 la
       contrainte ne mord pas, et les deux rendus concordaient déjà au dixième. */
    min-width: auto;
}

.dedienne-sr-title .elementor-heading-title {
    font-weight: 300;
    line-height: 1.167;
}

.dedienne-sr-excerpt {
    font-size: 14px;
    line-height: 1.733;
}

.dedienne-sr-heading-label .elementor-heading-title {
    font-size: 14px;
    font-weight: 400;
    line-height: 1.733;
}

/* ==========================================================================
   /contact/ — les deux paragraphes du titre décomposé

   La première section de /contact/ portait en production UN
   `borgholm_core_section_title`. Une passe antérieure l'a décomposé en trois `text-editor`,
   et deux d'entre eux enveloppent leur texte dans un `<p>` là où la production rend autre
   chose :

       sur-titre « CONTACT »   div.qodef-m-tagline, marge 0 0 7px
       « Get in touch »        p.qodef-m-text,      marge 10px 0 0

   La règle globale `p { margin: 10px 0 }` leur donne donc 10 px en haut ET en bas, soit 20 px
   de trop sur le sur-titre et 10 sur le texte.

   ---- Pourquoi deux classes et non une règle plus étroite ----

   `.elementor-widget-text-editor .elementor-widget-container > p:only-child { margin: 0 }`
   a été essayée et mesurée : elle ramène /contact/ de 79 à 19 px d'écart, mais DÉGRADE
   /values/ de 0 à 60 et /engine-stands/ de 0 à 20 — sur ces pages, les paragraphes uniques
   ont bien leurs 10 px en production. Le cas est propre à cette section : la production n'y
   rend pas de paragraphe du tout pour le sur-titre.

   Une classe par cas, avec la valeur relevée de l'élément que la production met à sa place.
   ========================================================================== */

.dedienne-ct-surtitre p {
    margin: 0 0 7px;
}

.dedienne-ct-texte p {
    margin: 10px 0 0;
}

/* ==========================================================================
   Menu principal — alignement sur la production

   Le menu d'Elementor et celui de borgholm ne partagent aucun balisage. Ce bloc reproduit ce
   que la production SERT, relevé au navigateur sur / à 1440 px :

       rangée d'entête    1440 x 90, remplissage 0 47px
       logo               204,58 x 60 à x=47, centré dans la rangée
       nav                745 x 90, à x=491
       li                 107 x 90, marge droite 29
       a                  107 x 90, AUCUN remplissage, s'étire sur la hauteur de rangée
                          Work Sans 11px / 500, +2px, capitales, #1D1D1D, transition 0,2s ease-out
       a::before          6 x 6 en #FE5000, `top: 42px; left: -12px`
                          AU REPOS   opacity 0, translateY(5px)
                          AU SURVOL  opacity 1, translateY(0)
       sous-menu          panneau 230 de large, `top: 90px; left: -34px`,
                          ombre 0 0 16px rgba(0,0,0,.05), z-index 10, SANS bordure
       sous-menu ul       230 x 283, remplissage 26px 0 30px, fond blanc
       sous-menu li       230 x 28, remplissage 0 12px 0 28px
       sous-menu a        190 x 28, remplissage 0 12px 0 0, 13px / 500, interligne 28
                          AU SURVOL  remplissage 0 0 0 12px — le libelle glisse de 12 px

   Les hauteurs, typographies, l'ecart entre items, l'ombre et la distance du panneau sont poses
   par reglage, dans tools/templates/align-header-menu.php. Ce bloc porte ce qu'Elementor
   n'expose pas.

   ---- Trois choses qu'Elementor impose et qu'il faut defaire ----

   1. `.elementor-nav-menu--layout-horizontal .elementor-nav-menu a { flex-grow: 1 }`, une regle
      de BASE de son CSS Pro : les liens grandissent pour remplir la barre, d'ou 124,69 px de
      large au lieu de 107. Ce n'est pas le reglage « stretch » du widget — celui-la a ete mis a
      vide sans effet. Il faut `flex-grow: 0`, et a trois classes : la regle a battre en a deux
      et sa feuille est chargee apres le theme enfant.

   2. Le lien ne s'etire pas en HAUTEUR. En production il fait 90 px parce qu'il occupe la
      rangee, et c'est de cette hauteur que dependent la position du point de survol et celle du
      panneau de sous-menu. D'ou la chaine d'etirement nav > ul > li > a.

   3. Le logo se fait COMPRIMER par le flex de la rangee — 173,63 px au lieu de 205 — parce que
      la somme des trois blocs depasse la largeur utile. `flex-shrink: 0` le protege.
   ========================================================================== */

/* ---- Le lien de premier niveau : largeur du texte, hauteur de la rangee ---- */

.dedienne-menu .elementor-nav-menu--layout-horizontal .elementor-nav-menu > li > a {
    flex-grow: 0;
}

/* ---- La barre ne se replie jamais ----

   Elementor pose `flex-wrap: wrap` sur `.elementor-nav-menu`. La production sert `nowrap` sur son
   `ul.menu` : le repli y est structurellement impossible, et sa barre garde sa largeur
   intrinseque de 745 px a 1440 comme a 1220.

   En local, le porteur du menu reserve 157 px de remplissage a droite pour l'icone de recherche.
   A 1220 il reste donc 744 px pour 745 px d'items : UN pixel de trop, et « Contact » passait a la
   ligne. Le defaut ne se voyait pas avant que l'ecart entre items soit remis a 58 — avec les
   2,5 px que portait la valeur « laptop », la barre tenait large. Corriger l'ecart a donc
   decouvert ce repli, il ne l'a pas cree.

   `nowrap` plutot qu'un rabotage des 157 px : le remplissage est cale sur la production a 1440,
   le toucher decalerait toute la barre. */
.dedienne-menu .elementor-nav-menu--layout-horizontal > .elementor-nav-menu {
    flex-wrap: nowrap;
}

/* La chaine d'etirement. `height: 100%` seul ne suffit pas : contre un parent de hauteur AUTO
   il se resout en `auto`. Il faut d'abord `align-self: stretch` sur les deux boites qui sont des
   items flex — le conteneur du menu dans la rangee, puis le widget dans ce conteneur — et alors
   seulement les `height: 100%` en dessous ont une hauteur de reference. La rangee, elle, tient
   ses 90 px de son `min-height`. */
.dedienne-menu-holder,
.dedienne-menu {
    align-self: stretch;
}

.dedienne-menu-holder > .e-con-inner,
.dedienne-menu > .elementor-widget-container,
.dedienne-menu .elementor-nav-menu--main,
.dedienne-menu .elementor-nav-menu--layout-horizontal > .elementor-nav-menu,
.dedienne-menu .elementor-nav-menu--layout-horizontal > .elementor-nav-menu > li,
.dedienne-menu .elementor-nav-menu--layout-horizontal > .elementor-nav-menu > li > a {
    height: 100%;
}

/* ---- L'ecart entre items sous 1200 : un ecart de la production, assume ----

   De 1025 a 1200, l'entete de la PRODUCTION est casse. Releve en image a 1100 : son bandeau de
   745 px et son logo de 205 px ne tiennent pas ensemble, « CIVIL TOOLING » chevauche
   « DEDIENNE AEROSPACE » et son ouvreur de recherche est entierement hors ecran. Ce n'est pas une
   subtilite de mesure, cela se voit sur la capture. Il n'existe aucune largeur entre 1025 et 1090
   ou les deux blocs tiennent.

   Reproduire la production ici serait donc reproduire un entete casse. On ne le fait pas.

   La solution retenue est celle de l'auteur du gabarit local, qui avait deja vu le probleme : il
   reduisait l'ecart entre items sous 1366, par un reglage `menu_space_between_laptop` de 5. Cette
   valeur-la etait trop petite — la puce orange, posee a 12 px a gauche du lien, tombait dans le
   libelle precedent, et c'est ce que Jerem a signale. On garde l'idee, pas la valeur.

   Le calcul. Les cinq liens totalisent 513 px de texte. Le bandeau vaut donc 513 + 4 x ecart. La
   place disponible a 1025, du bord droit du logo au bord gauche du bloc de recherche, est de
   663 px : l'ecart peut monter jusqu'a (663 - 513) / 4 = 37 px. On prend 32, ce qui laisse 16 px
   de marge de chaque cote de la puce — largement plus que les 12 px dont elle a besoin.

   Le levier est la VARIABLE d'Elementor et non les marges elles-memes : `menu_space_between` est
   rendu en `--e-nav-menu-horizontal-menu-item-margin: calc( 58px / 2 )`, et cette meme variable
   pilote le decalage du panneau de sous-menu (voir plus bas). En la redefinissant, les items ET
   les panneaux suivent ensemble, sans regle supplementaire.

   La borne est 1200 et non 1366 : a 1366, 1300 et 1201 le bandeau de 745 px tient, et ces largeurs
   sont aujourd'hui identiques au pixel a la production. On n'y touche pas. */
@media (max-width: 1200px) {
    /* `!important` parce que la regle a battre est le CSS GENERE du gabarit,
       `.elementor-131024 .elementor-element.elementor-element-1588c77` : trois classes, et une
       feuille chargee apres le theme enfant. L'egaler en specificite demanderait d'empiler quatre
       classes ou de nommer l'identifiant du gabarit dans le theme — ce dernier changerait au
       moindre remontage de l'entete. Une propriete personnalisee forcee est plus lisible et plus
       robuste. */
    .dedienne-menu.elementor-widget-nav-menu {
        --e-nav-menu-horizontal-menu-item-margin: 16px !important;
    }
}

/* ---- Le bouton du menu sous 1024 : sa boite, pas son icone ----

   Le reglage `toggle_size` dimensionne l'ICONE, pas la boite : Elementor pose `padding: .25em` sur
   `.elementor-menu-toggle`, ce qui donnait une boite de 33 px pour une icone de 22. Le bord droit
   du bouton tombait juste (40 px du bord de l'ecran, comme la production), mais les 11 px de trop
   poussaient la loupe vers la GAUCHE — 93 px du bord au lieu de 82.

   Les 82 px de la production ne sont pas une valeur choisie, c'est 40 + 22 + 20 : le bord droit,
   la largeur du bouton, l'ecart. Ramener la boite a 22 replace donc la loupe sans avoir a lui
   toucher. */
@media (max-width: 1024px) {
    .dedienne-menu-holder .elementor-menu-toggle {
        padding: 0;
        position: relative;
        width: 22px;
        height: 28px;
    }

    /* ---- Le bouton : DEUX traits INEGAUX ----

       Elementor sert son icone `eicon-menu-bar`, un SVG a trois barres epaisses. La production
       dessine deux `span`, et le second est plus COURT — c'est ce qui donne son allure au bouton.
       Releve sur l'etat ferme, dans une boite de 22 x 28 posee a y=21 :

           trait 1   22 x 2   a y=29, soit 8 px du haut de la boite
           trait 2   16 x 2   a y=35, soit 14 px du haut — 6 px sous le premier

       La premiere version faisait les deux a 22 et les posait a 9 et 17 : deux traits egaux et mal
       espaces. On masque le SVG de l'etat ferme — et seulement celui-la, `--close` sert quand le
       menu est ouvert. */
    /* ---- La loupe : meme boite, meme encre, meme sens ----

       La production sert le glyphe `icon_search` d'ElegantIcons a 20 px : son encre REMPLIT la
       boite de 20. Elementor sert son SVG `eicon-search`, dont le trace n'occupe que ~14 px des
       20 — d'ou une loupe visiblement plus petite a boite egale. Et son manche pointe en bas a
       DROITE quand celui de la production pointe en bas a gauche.

       On agrandit le trace au lieu de la boite : `scale(1.4)` porte l'encre a ~20, et la boite
       reste a 20 avec le meme centre que la production (x=408 a 500 px). Agrandir la boite aurait
       decale son bord gauche de 8 px, le porteur etant aligne a droite. `scaleX(-1)` remet le
       manche du bon cote. */
    .dedienne-menu-holder .search svg {
        transform: scaleX(-1) scale(1.4);
    }

    .dedienne-menu-holder .elementor-menu-toggle__icon--open {
        display: none;
    }

    .dedienne-menu-holder .elementor-menu-toggle:not(.elementor-active)::before,
    .dedienne-menu-holder .elementor-menu-toggle:not(.elementor-active)::after {
        content: '';
        position: absolute;
        left: 0;
        height: 2px;
        background-color: #000;
    }

    .dedienne-menu-holder .elementor-menu-toggle:not(.elementor-active)::before {
        top: 8px;
        width: 22px;
    }

    .dedienne-menu-holder .elementor-menu-toggle:not(.elementor-active)::after {
        top: 14px;
        width: 16px;
    }

    /* ---- Le logo se laisse raboter sous 340 px, comme la production ----

       Elle sert 205 x 60 de 340 a 1024, puis reduit : 166 x 49 a 320. Le reglage Elementor pose
       une largeur FIXE de 205, qui ferait deborder la rangee de 47 px a 320. `min-width: 0` leve
       la taille minimale automatique de l'element flex, et `max-width: 100%` laisse l'image suivre
       la boite. Le rapport est conserve par `height: auto`. */
    .dedienne-header-logo {
        min-width: 0;
    }

    /* Le porteur ne contient plus que la loupe et le bouton, soit 62 px : il n'a AUCUNE raison de
       rétrécir. Sans cela, la rangée répartit le rabotage entre les deux enfants au prorata de
       leur taille de base — le porteur étant en largeur pleine, sa base est énorme et le logo se
       faisait raboter à 115 px dès 390, là où la production le garde à 205 jusqu'à 340. En figeant
       le porteur sur son contenu, tout le rabotage revient au logo, et seulement quand il n'y a
       plus le choix. */
    .dedienne-menu-holder.e-con {
        width: auto;
        flex: 0 0 auto;
    }

    .dedienne-header-logo img {
        max-width: 100%;
        height: auto;
    }
}

/* ---- Le chevron injecte par le JS ----

   `submenu_icon` vide ne suffit pas : SmartMenus injecte quand meme un
   `<span class="sub-arrow"><i class=""></i></span>`, qui garde 10 px de large apres avoir perdu
   son icone. La production n'affiche aucun indicateur sur ses items de premier niveau. */
.dedienne-menu .elementor-nav-menu--layout-horizontal > .elementor-nav-menu > li > a .sub-arrow {
    display: none;
}

/* ---- Le point orange du survol ----

   Elementor rend deja un `::before` et un `::after` sur chaque lien, pour ses propres effets de
   pointeur — ici desactives (`pointer: none`), donc a opacite nulle et sans dimension. On
   reprend le `::before` plutot que d'ajouter un element : le balisage ne change pas, et l'effet
   d'Elementor ne peut plus se rallumer par-dessus. */
/* CORRECTION du 2026-08-25 — deux erreurs dans la premiere version de cette puce.

   1. Elle etait CARREE. La production met `border-radius: 100%` : c'est un disque.
   2. Elle etait animee par une TRANSITION de 0,2 s sur l'opacite et la translation. La
      production n'a aucune transition — elle enchaine DEUX animations par keyframes, et le
      mouvement n'a rien de comparable : au survol la puce tombe de 12 px au-dessus en etant
      etiree en hauteur, s'ecrase a l'arrivee, rebondit de 3 px et se pose. C'est le rebond qui
      se voit, et c'est lui que l'ancienne version ne rendait pas.

   Les deux regles viennent de `borgholm/assets/css/main.css`, relu dans git au commit precedant
   cc0f06d6 (« Lot 5b : retrait physique de la pile borgholm ») :

     .qodef-header-navigation > ul > li > a:before        animation: qodef-dot-drop  .3s forwards ease
     .qodef-header-navigation > ul > li > a:hover:before  animation: qode-dot-bounce .3s forwards linear

   Noter le prefixe : `qodef-dot-drop` mais `qode-dot-bounce`, sans le `f`. Ce n'est pas une
   coquille de transcription, c'est ce qu'il y a dans la source. */

@keyframes dedienne-dot-drop {
    0%   { opacity: 1; transform: translateY(0)    scaleX(1) scaleY(1); }
    100% { opacity: 0; transform: translateY(5px)  scaleX(1) scaleY(1); }
}

@keyframes dedienne-dot-bounce {
    0%   { opacity: 0; transform: translateY(-12px) scaleX(.8) scaleY(2); }
    1%   { opacity: 1; }
    25%  { opacity: 1; transform: translateY(-6px)  scaleX(1)  scaleY(1); }
    50%  { opacity: 1; transform: translateY(0)     scaleX(2)  scaleY(.8); }
    60%  { opacity: 1; transform: translateY(0)     scaleX(1)  scaleY(1); }
    75%  { opacity: 1; transform: translateY(-3px)  scaleX(1)  scaleY(1); }
    100% { opacity: 1; transform: translateY(0)     scaleX(1)  scaleY(1); }
}

.dedienne-menu .elementor-nav-menu--layout-horizontal > .elementor-nav-menu > li > a::before {
    content: '';
    display: block;
    position: absolute;
    /* 42 px sur une rangee de 90 — mais exprime comme la production, pour suivre la hauteur. */
    top: calc(50% - 3px);
    left: -12px;
    right: auto;
    bottom: auto;
    width: 6px;
    height: 6px;
    background-color: #fe5000;
    border-radius: 100%;
    opacity: 0;
    transform-origin: center;
    will-change: transform;
    /* Elementor pose `transition: .3s cubic-bezier(.58,.3,.005,1)` sur ce pseudo-element pour
       ses effets de pointeur. Une animation l'emporte sur une transition, donc le rebond jouait
       quand meme — mais la production n'a pas de transition ici, et en laisser une invite un
       conflit au prochain reglage. */
    transition: none;
    animation: dedienne-dot-drop .3s forwards ease;
}

.dedienne-menu .elementor-nav-menu--layout-horizontal > .elementor-nav-menu > li > a:hover::before,
.dedienne-menu .elementor-nav-menu--layout-horizontal > .elementor-nav-menu > li:hover > a::before {
    animation: dedienne-dot-bounce .3s forwards linear;
}

/* La page courante garde sa puce en permanence, sans animation. Elementor pose
   `current-menu-item` / `current-menu-ancestor` sur le `li` comme WordPress, et
   `elementor-item-active` sur le lien : les trois sont couvertes.

   ---- Pourquoi `.elementor-item` est ajoute a chaque selecteur ----

   Sans lui, la puce du PARENT ne s'affichait pas quand on etait sur une page de son sous-menu,
   alors que celle de la page courante de premier niveau s'affichait bien. Le `li` porte pourtant
   `current-menu-ancestor` et `current-menu-parent`, et `animation: none` / `transform: none`
   passaient — seule l'`opacity` etait perdue. Une demi-application, donc un conflit de cascade
   sur cette seule propriete :

     .elementor-item:not(:hover):not(:focus):not(.elementor-item-active):not(.highlighted)::before
       opacity: 0    custom-pro-widget-nav-menu.min.css

   `:not()` compte la specificite de son argument : cette regle vaut CINQ unites de niveau classe
   a partir d'une seule classe. Mes selecteurs en avaient quatre, et la feuille d'Elementor est
   chargee apres le theme enfant — elle gagnait deux fois.

   Cela explique aussi pourquoi le cas de premier niveau fonctionnait : la page courante porte
   `elementor-item-active` sur son lien, donc le `:not(.elementor-item-active)` d'Elementor ne
   correspond plus et sa regle ne s'applique pas. Un ANCETRE n'a pas cette classe — le lien actif
   est celui de l'enfant — donc la regle s'appliquait et remettait la puce a zero.

   `.elementor-item` porte les selecteurs a cinq classes plus deux elements : l'ordre de chargement
   ne decide plus. Ajoute aux trois pour qu'ils restent au meme niveau. */
.dedienne-menu .elementor-nav-menu--layout-horizontal > .elementor-nav-menu > li.current-menu-item > a.elementor-item::before,
.dedienne-menu .elementor-nav-menu--layout-horizontal > .elementor-nav-menu > li.current-menu-ancestor > a.elementor-item::before,
.dedienne-menu .elementor-nav-menu--layout-horizontal > .elementor-nav-menu > li > a.elementor-item.elementor-item-active::before {
    opacity: 1;
    animation: none;
    transform: none;
    transition: all .2s ease-out;
}

/* Le `::after` d'Elementor ne sert plus a rien : il resterait a opacite 1 au survol. */
.dedienne-menu .elementor-nav-menu--layout-horizontal > .elementor-nav-menu > li > a::after {
    content: none;
}

/* ---- Le panneau de sous-menu ---- */

/* Structure : la production empile trois boites — une enveloppe absolue `.qodef-drop-down-second`
   qui porte le decalage et l'ombre, un `-inner`, puis le `ul.sub-menu` qui porte la bordure haute
   orange. En local il n'y a que le `ul` de SmartMenus : il porte les trois roles.

   ---- Pourquoi `!important` ici, et seulement ici ----

   Elementor Pro pilote ce panneau avec SmartMenus, qui ecrit ses valeurs EN LIGNE sur le `ul` a
   chaque ouverture :

     width: auto; min-width: 10em; max-width: 1000px; top: auto; left: 0px; margin-left: 0px;

   Le style en ligne bat n'importe quel selecteur de feuille : ajouter des classes ne sert a rien,
   ce n'est pas un probleme de specificite mais de cascade. Trois proprietes sont concernees.
   `width: auto` + `min-width: 10em` faisaient un panneau de 235 px au lieu de 230 — la largeur du
   contenu, pas celle voulue — et `left: 0` annulait le decalage de -34. `!important` est le seul
   moyen de reprendre la main sans desactiver SmartMenus, dont depend l'ouverture au survol.
   `padding` n'est PAS ecrit en ligne : il n'a pas besoin d'etre force. */
.dedienne-menu .elementor-nav-menu--main .elementor-nav-menu--dropdown {
    width: 230px !important;
    min-width: 230px !important;
    left: -34px !important;
    padding: 26px 0 30px;
}

/* ---- Le decalage de -34, pour les items AUTRES que le premier ----

   La regle ci-dessus ne gagnait que sur le PREMIER item du menu. Sur les quatre autres, le
   panneau s'ouvrait aligne sur le texte au lieu d'etre 34 px a sa gauche. Elementor Pro pose :

     .elementor-nav-menu--layout-horizontal .elementor-nav-menu > li:not(:first-child) > ul
       left: var(--e-nav-menu-horizontal-menu-item-margin) !important

   Egalement en `!important`, et a trois classes plus deux elements contre mes trois classes :
   elle gagnait. Son `:not(:first-child)` explique pourquoi le premier item, lui, etait correct
   — et donc pourquoi le defaut avait echappe au controle : le seul panneau que j'avais mesure
   etait celui ou le concurrent se desactive tout seul. Meme forme d'erreur que sur la puce du
   menu, releve le meme jour.

   Ce que fait cette variable : le panneau est positionne par rapport au `li`, et Elementor pose
   la moitie de l'ecart entre items en marge de debut sur chaque lien sauf le premier. `left`
   valant cette moitie, le panneau s'aligne sur le TEXTE. Il faut donc retrancher 34 de cette
   valeur, et non de zero.

   La variable est reprise telle quelle plutot que son resultat (-5 px aujourd'hui) : si l'ecart
   entre items change un jour par reglage, le decalage suit sans qu'on ait a y repenser. */
.dedienne-menu .elementor-nav-menu--main.elementor-nav-menu--layout-horizontal > .elementor-nav-menu > li:not(:first-child) > .elementor-nav-menu--dropdown {
    left: calc( var( --e-nav-menu-horizontal-menu-item-margin, 0px ) - 34px ) !important;
}

/* CORRECTION du 2026-08-25 — le remplissage doit aller sur le `li`, pas sur le lien.

   La premiere version cumulait les deux remplissages de la production sur le lien seul, en se
   disant qu'Elementor n'expose pas de controle pour le `li` et que le rendu serait identique.
   La position du texte l'etait bien, mais la structure non, et la structure PORTE un effet :

     li  remplissage 0 12px 0 28px, debordement visible
     a   190 de large, remplissage 0 12px 0 0, DEBORDEMENT MASQUE

   La puce du sous-item vit dans le lien a `left: -12px`, donc en dehors de sa boite : le
   `overflow: hidden` du lien la rogne, et elle n'apparait qu'en glissant a `left: 0`. Avec le
   remplissage cumule sur le lien, celui-ci occupait toute la largeur du panneau et la puce
   tombait a l'interieur de sa boite : visible en permanence sur les huit entrees, ce que la
   production ne fait pas. Impossible a voir en styles calcules — la sonde annoncait bien
   `opacity: 1` des deux cotes — il a fallu comparer les IMAGES au repos.

   Rien n'obligeait a passer par un controle Elementor : le remplissage du `li` s'ecrit ici.

   La bordure de 8 px vient d'Elementor — `ul.elementor-nav-menu--dropdown a { border-inline-start:
   8px solid transparent }`, son mecanisme d'indentation par niveau. Transparente, donc invisible,
   mais elle poussait le libelle de 8 px vers la droite. */
.dedienne-menu .elementor-nav-menu--main .elementor-nav-menu--dropdown > li {
    padding: 0 12px 0 28px;
}

.dedienne-menu .elementor-nav-menu--main .elementor-nav-menu--dropdown > li > a {
    padding: 0 12px 0 0;
    border-inline-start: 0;
    overflow: hidden;
    transition: padding .2s ease-out;
}

/* Le glissement : les 12 px passent de droite a gauche, le libelle avance d'autant.

   L'item COURANT est dans le meme etat que l'item survole : sa puce est a `left: 0` et son
   libelle est decale. Il manquait ici, et la puce se retrouvait donc SOUS le texte — le seul
   cas ou les deux occupent la meme position. C'est bien la regle du glissement qui etait
   incomplete, pas celle de la puce : la puce, elle, couvrait deja `current-menu-item`. */
.dedienne-menu .elementor-nav-menu--main .elementor-nav-menu--dropdown > li:hover > a,
.dedienne-menu .elementor-nav-menu--main .elementor-nav-menu--dropdown > li > a:focus,
.dedienne-menu .elementor-nav-menu--main .elementor-nav-menu--dropdown > li.current-menu-item > a,
.dedienne-menu .elementor-nav-menu--main .elementor-nav-menu--dropdown > li.current-menu-ancestor > a {
    padding: 0 0 0 12px;
}

/* La puce du sous-item : un disque de 6 px, TOUJOURS a opacite 1, que le `overflow: hidden` du
   lien masque tant qu'elle est a `left: -12px`. Seule sa position est animee — 0,2 s, la meme
   duree que le remplissage, les deux glissent ensemble. */
.dedienne-menu .elementor-nav-menu--main .elementor-nav-menu--dropdown > li > a::before {
    content: '';
    display: block;
    position: absolute;
    top: calc(50% - 4px);
    left: -12px;
    right: auto;
    bottom: auto;
    width: 6px;
    height: 6px;
    background-color: #fe5000;
    border-radius: 100%;
    opacity: 1;
    transition: left .2s ease-out, right .2s ease-out;
}

.dedienne-menu .elementor-nav-menu--main .elementor-nav-menu--dropdown > li:hover > a::before,
.dedienne-menu .elementor-nav-menu--main .elementor-nav-menu--dropdown > li.current-menu-item > a::before,
.dedienne-menu .elementor-nav-menu--main .elementor-nav-menu--dropdown > li.current-menu-ancestor > a::before {
    left: 0;
}

/* Elementor colore le fond du sous-item survole en #3f444b et son texte en blanc. La production
   ne change ni l'un ni l'autre : seuls la puce et le glissement marquent le survol. */
.dedienne-menu .elementor-nav-menu--main .elementor-nav-menu--dropdown > li > a:hover,
.dedienne-menu .elementor-nav-menu--main .elementor-nav-menu--dropdown > li > a:focus,
.dedienne-menu .elementor-nav-menu--main .elementor-nav-menu--dropdown > li > a.elementor-item-active {
    background-color: transparent;
    color: #000;
}

/* ==========================================================================
   Menu mobile DÉPLOYÉ — alignement sur la production
   ==========================================================================

   Le panneau qui s'ouvre sous 1025 px n'avait jamais été comparé à la production : tout le
   travail d'alignement de l'entête portait sur `1588c77`, le menu de BUREAU, et le menu mobile
   est un AUTRE widget — `c1d7ff2`, qui ne porte aucune classe personnalisée. Aucune des règles
   `.dedienne-menu` ne le touchait donc, et il servait le dessin par défaut d'Elementor.

   ---- Ce que la production sert, relevé au navigateur sur / (menu ouvert) ----

   Invariant de 320 à 1024 px, la rangée d'entête faisant 70 px partout :

       panneau            pleine largeur, `top: 70px`, fond blanc
                          AUCUNE bordure haute, AUCUNE ombre,
                          bordure BASSE 1px solid #E1E1E1
       liste              `margin: 0 auto`, remplissage 34px 0,
                          largeur `min(86%, 768px)` — et 82 % sous 481 px
                          (mesuré : 262,39 à 320 · 319,80 à 390 · 393,59 à 480 ·
                           413,66 à 481 · 660,47 à 768 · 768 à 900 et au-delà)
       item li            36 de haut, remplissage 5px 0
       item a             EN LIGNE, largeur du texte, aucun remplissage
                          Work Sans 12px / 600, +2,4px, capitales, #1D1D1D, interligne 20,796
       chevron            `a::after`, glyphe ElegantIcons « 5 » à 20px, #1D1D1D,
                          `position: absolute; right: 0; top: 16px` puis `translateY(-10px)`
                          encre relevée à l'image : 6 x 10 px, trait ~2px, pointe à droite,
                          bord droit de l'encre à ~7 px du bord droit de la liste
       sous-menu ul       `margin: 14px 0 5px 10px`, sans fond, sans bordure, sans ombre
       sous-item li       32 de haut, remplissage 3px 0 4px
       sous-item a        `padding: 0 12px 0 0`, CORMORANT 12px / 500, casse normale,
                          interligne 25, #000
       croix de l'ouvreur DEUX traits de 22 x 2 en #000, `top: 13px; left: 0`,
                          pivotés de ±45° autour de leur centre (`transform-origin: 11px 1px`)

   ---- Et ce que le local servait ----

       panneau            `top: 64px` (69 en tablette), bordure HAUTE 2px #FE5000,
                          ombre 0 0 10px rgba(0,0,0,.05), aucune bordure basse
       liste              pleine largeur, aucun remplissage
       item a             en BLOC pleine largeur, remplissage 9px 20px,
                          13px / 400, sans interlettrage, #000, interligne 20 → item de 38
       chevron            caret BAS de Font Awesome, collé au texte, et non à droite
       croix              le SVG `--close` d'Elementor, en ORANGE

   ---- Pourquoi en CSS et non en réglages Elementor ----

   Même raison que pour le bloc « Navigation principale » ci-dessus : réversible, et sans toucher
   au gabarit construit en amont. Trois raisons s'y ajoutent ici :

   1. La couleur des items est pilotée par la couleur d'ACCENT du kit (#000000), via
      `__globals__`. Un `color_dropdown_item` littéral serait ignoré tant que le global est là,
      et retirer le global est une opération plus fragile qu'une règle de plus.
   2. Le remplissage de la LISTE (34px 0) et son insertion (la grille de contenu de borgholm)
      ne sont exposés par aucun contrôle du widget.
   3. `tools/templates/align-header-menu.php` détient déjà `_elementor_data` du gabarit 131024,
      avec sa sauvegarde `_dedienne_backup_header`. Un second script écrivant la même méta
      exposerait à écraser la sauvegarde de l'autre.

   ---- Le garde `max-width: 1024px` ----

   `c1d7ff2` porte `hide_desktop` et son `dropdown` vaut `tablet`. Les points de rupture actifs
   du kit étant mobile (767) et tablet (1024) — voir align-breakpoints.php — le widget n'existe
   QU'À 1024 et en dessous, et il y est TOUJOURS replié derrière son bouton. Le garde recouvre
   donc exactement la plage du widget ; rien au-dessus de 1024 ne peut bouger.

   ---- Compte des classes ----

   Elementor génère `.elementor-131024 .elementor-element.elementor-element-c1d7ff2 …`, soit
   quatre classes. Le préfixe `body` et les sélecteurs de type (`nav`, `ul`, `a`) portent ces
   règles au-dessus, sans avoir à nommer deux fois l'identifiant du gabarit.
   ========================================================================== */

@media (max-width: 1024px) {

    /* ---- Le panneau ----

       `margin-top: 21px` et non 15 (mobile) ou 20 (tablette) : le bouton du menu finit à y=49
       — boîte de 28 posée à 21 — et la production démarre son panneau à 70, le bas de la rangée.
       21 est donc la seule valeur qui les fasse coïncider, et elle vaut aux deux paliers.

       La bordure et l'ombre viennent des réglages `dropdown_border_*` et `dropdown_box_shadow_*`
       du widget. Ils sont justes pour un panneau de SOUS-MENU de bureau — c'est le dessin retenu
       pour `1588c77` — mais ce widget-ci n'a pas de bureau : son seul panneau est celui du
       mobile, et la production ne lui met ni liseré orange ni ombre.

       ---- Pourquoi CE sélecteur-là, et pourquoi `!important` ----

       Les trois propriétés ne se battent pas contre la même règle. Relevé dans le CSS généré,
       `wp-content/uploads/elementor/css/post-131024.css` :

         bordure    `… .elementor-element-c1d7ff2 .elementor-nav-menu--dropdown`
                    quatre classes, sans `!important`
         ombre      `… .elementor-element-c1d7ff2 .elementor-nav-menu__container.elementor-nav-menu--dropdown`
                    CINQ classes
         marge      le même sélecteur à cinq classes, et en `!important`

       D'où les deux ajouts : `.elementor-nav-menu__container` porte le compte à cinq classes plus
       deux sélecteurs de type, et `!important` est la seule réponse à un `!important`. Une
       première version sans l'un ni l'autre n'appliquait NI la marge NI l'ombre — le panneau
       restait à y=64 avec son ombre, alors que la typographie des items, elle, passait déjà : la
       preuve qu'il ne s'agissait pas du préfixe mais du compte de classes. */
    body .elementor-131024 .elementor-element.elementor-element-c1d7ff2 nav.elementor-nav-menu__container.elementor-nav-menu--dropdown {
        margin-top: 21px !important;
        border: 0;
        border-bottom: 1px solid #e1e1e1;
        box-shadow: none;
    }

    /* ---- La liste : la grille de contenu de borgholm ----

       La production n'aligne pas ses items sur le bord de l'écran : elle les pose dans la même
       grille que le contenu des pages, centrée et bornée à 768 px. Les items tombent ainsi sous
       le logo, et non 20 px plus à gauche comme le faisait le remplissage d'Elementor. */
    body .elementor-131024 .elementor-element.elementor-element-c1d7ff2 nav.elementor-nav-menu--dropdown > ul.elementor-nav-menu {
        width: min(86%, 768px);
        margin: 0 auto;
        padding: 34px 0;
    }

    /* ---- L'item de premier niveau ----

       Les 36 px se répartissent comme en production : 5 px de remplissage sur le `li`, un
       interligne de 26 sur le lien, 5 px de remplissage. borgholm tient ses 26 de l'interligne du
       corps (15px x 1,733) ; Elementor n'en met aucun sur ses `li` et 9 px sur son lien.

       ---- Pourquoi le remplissage sur le `li` et non sur le lien ----

       Une première version le mettait sur le LIEN, la boîte fermée étant la même. Elle décalait
       l'item DÉPLIÉ de 5 px : 338 px de haut contre 343 en production. Cause, mesurée sur la
       différence exacte : la marge basse de 5 px du sous-menu s'ÉCHAPPE du `li` par fusion de
       marges quand le `li` n'a pas de remplissage bas. Les 5 px de la production ne sont donc pas
       décoratifs — ils bloquent la fusion. Reproduire sa répartition, et pas seulement son total,
       règle les deux d'un coup.

       ---- 6 et 4, et non 5 et 5 ----

       La production déclare bien `5px 0`, mais son libellé se rend 1 px PLUS BAS que le nôtre :
       boîte de texte mesurée par un Range sur le nœud de texte — la seule mesure comparable
       entre un lien en ligne et un lien en bloc — à y=116 chez elle, y=115 chez nous, pour un
       `li` identique au centième (35,09 · 104 · 319,80 · 36).

       La cause est le STRUT. Chez elle le lien est en ligne, il vit donc dans un bloc anonyme
       dont la boîte de ligne est cadencée par le strut du `li` — interligne 25,995 hérité du
       corps à 15px — et non par les 20,796 du lien. Chez nous le lien est un conteneur flex :
       il n'y a pas de strut de 15px, la boîte de ligne vaut exactement l'interligne déclaré.

       On ne peut pas reproduire le mécanisme sans rendre le lien en ligne, et le rendre en ligne
       coûterait le `margin-left: auto` qui pousse le chevron à droite. On reproduit donc le
       RÉSULTAT : 6 px en haut, 4 en bas. Le total reste 36, la marge basse reste bloquée, et le
       libellé tombe à 116 comme chez elle.

       Aucun remplissage horizontal : c'est la liste qui porte l'insertion, comme en production.

       La couleur est reprise ici pour la même raison que sur le menu de bureau : le réglage du
       widget est écrasé par la couleur d'accent du kit.

       `background-color: transparent` : le réglage `background_color_dropdown_item_hover` du
       widget vaut `#FFFFFF00`, un blanc d'opacité NULLE. Il ne se voit pas, mais il fait diverger
       le relevé de styles calculés — `rgba(255,255,255,0)` contre `rgba(0,0,0,0)` — et masquerait
       une vraie divergence de fond au prochain contrôle. */
    body .elementor-131024 .elementor-element.elementor-element-c1d7ff2 nav.elementor-nav-menu--dropdown > ul.elementor-nav-menu > li {
        padding: 6px 0 4px;
    }

    body .elementor-131024 .elementor-element.elementor-element-c1d7ff2 nav.elementor-nav-menu--dropdown a.elementor-item {
        padding: 0;
        font-family: "Work Sans", sans-serif;
        font-size: 12px;
        font-weight: 600;
        line-height: 26px;
        letter-spacing: 2.4px;
        text-transform: uppercase;
        color: #1d1d1d;
        background-color: transparent;
    }

    /* ---- Le chevron des items à sous-menu ----

       La production dessine le sien avec le glyphe `arrow_carrot-right` d'ElegantIcons. Cette
       police est partie avec la pile borgholm (commit cc0f06d6) et n'est plus servie : la
       chercher serait la réintroduire pour un seul caractère. Le chevron est donc dessiné, en
       SVG intégré, aux dimensions de l'ENCRE relevée à l'image — 6 x 10 px, trait ~2px.

       Le porteur est le `.sub-arrow` qu'Elementor injecte, et non un `::after` comme en
       production : c'est LUI qui porte l'écouteur de dépliage de SmartMenus. Un `::after` dessiné
       par-dessus ne serait pas cliquable, et le sous-menu ne s'ouvrirait plus. On lui donne donc
       une boîte de 24 x 26 — une cible de doigt correcte, comme la zone que la production accepte
       au clic — et l'encre est placée dedans par le fond.

       `margin-left: auto` : le lien est un conteneur flex chez Elementor, la marge automatique y
       pousse le chevron contre le bord droit. Le décalage de 7 px reproduit le bord droit de
       l'encre de la production, à 347,5 pour une liste qui finit à 354,9.

       Le remplissage négatif et les marges négatives du `.sub-arrow` d'Elementor sont remis à
       plat : sa boîte extérieure faisait 29,09 px de haut et aurait imposé cette hauteur à la
       ligne flex, donc à l'item. */
    body .elementor-131024 .elementor-element.elementor-element-c1d7ff2 nav.elementor-nav-menu--dropdown a.elementor-item .sub-arrow {
        width: 24px;
        height: 26px;
        margin: 0 0 0 auto;
        padding: 0;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 7 10'%3E%3Cpath d='M3.05 1 5.5 5 1.05 9' fill='none' stroke='%231d1d1d' stroke-width='1.6'/%3E%3C/svg%3E");
        background-repeat: no-repeat;
        background-position: right 7px top 5.6px;
        background-size: 7px 10px;
    }

    /* Le glyphe injecté par le réglage `submenu_icon` — un caret BAS de Font Awesome. La
       production pointe à DROITE. On masque le SVG plutôt que de vider le réglage : le
       `.sub-arrow` doit rester présent et cliquable, et Elementor l'injecte de toute façon même
       avec une icône vide (voir le bloc du menu de bureau). */
    body .elementor-131024 .elementor-element.elementor-element-c1d7ff2 nav.elementor-nav-menu--dropdown a.elementor-item .sub-arrow svg,
    body .elementor-131024 .elementor-element.elementor-element-c1d7ff2 nav.elementor-nav-menu--dropdown a.elementor-item .sub-arrow i {
        display: none;
    }

    /* ---- Le chevron PIVOTE quand le sous-menu est déplié ----

       Relevé sur la production, parent déplié : son `li` reçoit la classe `qodef--opened` et le
       `a::after` porte `transform: matrix(0, 1, -1, 0, 0, 0)`, soit `rotate(90deg)` — le chevron
       pointe alors vers le BAS. Encre mesurée à l'image : x 340 à 349, y 119 à 125.

       Le signal local est `aria-expanded`, posé par SmartMenus sur le lien. On ne prend PAS la
       classe `highlighted` qu'il ajoute au même moment : elle sert aussi au survol et au focus,
       et le chevron pivoterait au simple survol.

       La rotation porte sur le fond, donc sur la boîte : sans origine explicite elle tournerait
       autour du centre du `.sub-arrow` (12, 13) et l'encre partirait ailleurs. L'origine est donc
       posée sur le centre de l'ENCRE dans la boîte — le fond occupe x 10 à 17 et y 5,6 à 15,6, et
       le tracé remplit ces bornes à un demi-pixel près.

       ---- La translation n'est pas un bricolage ----

       Une rotation pure autour d'un point ne peut PAS reproduire la position de la production, et
       le calcul le dit : une rotation de 90° autour de `O` déplace le centre de `(-(dx+dy),
       dx+dy)` où `d` est le vecteur du centre à `O`. Les deux composantes sont donc toujours
       opposées, alors que l'écart à combler est `(+0,4 ; +1,4)` — de même signe. Aucune origine
       ne le donne.

       La raison : la production tourne un GLYPHE de police, et un glyphe transformé n'est plus
       hinté comme au repos — son encre se re-rastérise, ici 1,4 px plus bas. On ne reproduit donc
       pas son mécanisme, on cale l'encre là où elle atterrit : x 340 à 349, y 119 à 125, relevé à
       l'image sur l'état déplié. */
    body .elementor-131024 .elementor-element.elementor-element-c1d7ff2 nav.elementor-nav-menu--dropdown a.elementor-item[aria-expanded="true"] .sub-arrow {
        transform-origin: 13.55px 10.7px;
        transform: translate(0.4px, 1.4px) rotate(90deg);
    }

    /* ---- Le sous-menu déplié ----

       Il ne se distingue en rien d'un panneau chez Elementor : même classe
       `elementor-nav-menu--dropdown`, donc même liseré orange, même fond blanc et même ombre. La
       production en fait une simple liste indentée, sans cadre — et change de police : ses
       sous-items sont en Cormorant, pas en Work Sans.

       Cormorant est déjà mise en file à l'échelle du site par `dedienne_enqueue_cormorant()`
       (functions.php). Sans cet appel, une famille écrite en CSS nu ne demande AUCUNE `@font-face`
       et le navigateur retombe sur la serif du système — le piège s'est déjà refermé deux fois
       sur ce chantier. */
    /* ---- 13 et 6, là où la production met 14 et 5 ----

       Le premier niveau porte 6 px de remplissage haut au lieu de 5, pour compenser le strut
       (voir plus haut). Son lien occupe donc 110 à 136 quand celui de la production occupe 109 à
       135, et un `margin-top` de 14 posait la sous-liste à y=150 contre 149. Le point de départ se
       rattrape par 13.

       Et les 5 px du bas passent à 6, sans quoi l'item déplié perdrait le pixel repris en haut :
       343 px de haut en production, 342 avec 13 et 5. Les deux valeurs vont ensemble — corriger
       la première seule décalerait tout ce qui suit l'item déplié. */
    body .elementor-131024 .elementor-element.elementor-element-c1d7ff2 nav.elementor-nav-menu--dropdown ul.sub-menu {
        margin: 13px 0 6px 10px;
        padding: 0;
        background-color: transparent;
        border: 0;
        box-shadow: none;
    }

    /* 3 + 25 + 4 = les 32 px de la production, répartis comme chez elle : le remplissage sur le
       `li`, l'interligne sur le lien. Même raison que pour le premier niveau — la répartition
       compte autant que le total dès qu'un sous-niveau se déplie. */
    body .elementor-131024 .elementor-element.elementor-element-c1d7ff2 nav.elementor-nav-menu--dropdown ul.sub-menu > li {
        padding: 3px 0 4px;
    }

    /* `border-inline-start: 0` — le MÊME piège que sur le menu de bureau, et je l'ai repris deux
       fois. Elementor pose `ul.elementor-nav-menu--dropdown a { border-inline-start: 8px solid
       transparent }`, son mécanisme d'indentation par niveau. Transparente donc invisible, mais
       elle poussait le libellé de 8 px : boîte de texte mesurée à x=53,09 contre 45,09 en
       production, pour un `li` pourtant identique. Un relevé sur la boîte du LIEN ne l'aurait pas
       vue — c'est la boîte du TEXTE qui la révèle. */
    body .elementor-131024 .elementor-element.elementor-element-c1d7ff2 nav.elementor-nav-menu--dropdown ul.sub-menu a.elementor-sub-item {
        padding: 0 12px 0 0;
        border-inline-start: 0;
        font-family: Cormorant, serif;
        /* ---- ITALIQUE, et c'est le réseau qui l'a dit ----

           Le libellé sortait 6 % trop large : 121 px contre 114 pour « Civil Tooling – Main page »,
           76 contre 70, 71 contre 66 — un écart proportionnel au nombre de caractères, donc une
           avance de glyphe et non un remplissage.

           Trois hypothèses écartées à la mesure : le dimensionnement optique (`opsz` de none à 72,
           sans le moindre effet), la famille (`Cormorant Garamond` donne 153,97, la valeur du
           repli — donc la Cormorant locale se charge bel et bien), et le poids.

           La réponse était dans les requêtes réseau : la production télécharge
           `cormorant-ITALIC-latin-500.woff2`, le local `cormorant-NORMAL-latin-500.woff2`. Son
           `font-style` calculé vaut `italic`. Avec l'italique, le local rend 114 / 70 / 66 —
           exactement ses valeurs.

           Deux leçons. Écouter le RÉSEAU quand la famille, la taille et le poids concordent et que
           l'avance diverge : le fichier servi est la seule variable qui reste. Et une propriété
           absente de la liste d'un relevé est un angle mort — `font-style` n'y était pas, et cet
           écart a survécu à cinq passes de comparaison. */
        font-style: italic;
        font-size: 12px;
        font-weight: 500;
        line-height: 25px;
        letter-spacing: normal;
        text-transform: none;
        color: #000;
        background-color: transparent;
    }

    /* ---- La croix de l'ouvreur ----

       Elementor bascule sur son SVG `--close`, et le peint avec `toggle_color_hover` — la couleur
       PRIMAIRE du kit, d'où une croix ORANGE. La production garde l'encre noire de ses deux
       traits : ce sont les MÊMES traits que ceux de l'état fermé, portés à 22 px tous les deux et
       pivotés de ±45° autour de leur centre.

       On prolonge donc les deux pseudo-éléments déjà utilisés pour l'état fermé (voir le bloc
       « Le bouton du menu sous 1024 » plus haut) au lieu d'ajouter un dessin : un seul mécanisme
       pour les deux états, et le SVG d'Elementor ne peut pas se rallumer par-dessus.

       `transform-origin` n'est pas déclaré : sa valeur par défaut, `50% 50%`, vaut exactement les
       `11px 1px` que la production pose sur un trait de 22 x 2. */
    .dedienne-menu-holder .elementor-menu-toggle__icon--close {
        display: none;
    }

    .dedienne-menu-holder .elementor-menu-toggle.elementor-active::before,
    .dedienne-menu-holder .elementor-menu-toggle.elementor-active::after {
        content: '';
        position: absolute;
        top: 13px;
        left: 0;
        width: 22px;
        height: 2px;
        background-color: #000;
    }

    .dedienne-menu-holder .elementor-menu-toggle.elementor-active::before {
        transform: rotate(45deg);
    }

    .dedienne-menu-holder .elementor-menu-toggle.elementor-active::after {
        transform: rotate(-45deg);
    }
}

/* La grille de contenu de borgholm passe de 86 % à 82 % sous 481 px. Mesuré au pixel de part et
   d'autre de la borne : 393,59 pour 480 (82 %) et 413,66 pour 481 (86 %). */
@media (max-width: 480px) {
    body .elementor-131024 .elementor-element.elementor-element-c1d7ff2 nav.elementor-nav-menu--dropdown > ul.elementor-nav-menu {
        width: 82%;
    }
}

/* ==========================================================================
   Barre du haut — le selecteur de langue
   ==========================================================================

   La production separe les langues par une barre oblique. Elle ne vient ni d'un `li` en plus ni
   d'un titre de menu : c'est `a::after { content: "/" }`, pose sur chaque langue SAUF la
   derniere. Le premier releve l'avait manquee — il ne sondait que les pseudo-elements du `li`,
   et ils sont sur le lien.

   `:has(+ li…)` plutot que `:not(:last-child)` : la regle vaut alors quel que soit le nombre de
   langues, et ne depend pas de leur position dans le menu. Le theme enfant porte deja des
   classes `lang1` / `lang4` calees sur quatre langues — les reutiliser aurait fige ce nombre.

   ECART CONNU, non traite ici : la production ne publie que TROIS langues (EN, ES, CN), le local
   quatre (EN, ES, CN, FR). C'est un reglage TranslatePress, pas une question de style, et cela
   decale de 14,5 px vers la gauche tout le bloc aligne a droite. A trancher par Jerem. */

/* Sur le `li`, pas sur le lien. La production peut se le permettre sur le lien : son menu meta
   est un menu WordPress ordinaire, ses `a` sont en `display: inline`. Ici Elementor met
   `display: flex` sur chaque lien, le pseudo-element y devient un element flex, et comme le lien
   est dimensionne sur son texte la barre oblique passait a la ligne. Elle elargissait de surcroit
   le soulignement de la langue courante, dessine par un `::before` cale sur la boite du lien. */
.menumetaheader li.trp-language-switcher-container:has(+ li.trp-language-switcher-container)::after {
    content: '/';
    /* Elementor RESERVE ce pseudo-element pour son propre separateur d'items :

         .elementor-nav-menu--layout-horizontal .elementor-nav-menu > li:not(:last-child)::after {
             content: var(--e-nav-menu-divider-content, none);
             height: var(--e-nav-menu-divider-height, 35%);
             border-left: var(--e-nav-menu-divider-width, 2px) … var(--e-nav-menu-divider-color, #000);
             align-self: center;
         }

       Il n'est invisible que parce que son `content` vaut `none`. Y ecrire un contenu ALLUME donc
       le separateur : un trait noir de 2 px sur 35 % de hauteur apparaissait devant chaque barre
       oblique, et le `height` en pourcentage la desalignait. Les trois proprietes sont remises a
       plat ici — c'est le prix a payer pour reutiliser ce pseudo-element plutot que d'ajouter un
       element au balisage. */
    border-left: 0;
    height: auto;
    margin: 0 3px;
    color: #FFFFFF;
    align-self: baseline;
}


/* ==========================================================================
   Slider « Tooling Services » — la pagination
   ==========================================================================

   La production et Elementor ne placent pas la pagination au meme endroit, et ne dessinent pas
   les memes puces :

                        production                      Elementor
     position           DANS LE FLUX sous l'image       en absolu dans l'image, `bottom: 5px`
     bloc               816 x 44, marge haute 20        700 x 26
     puce               36 x 36 transparente, point     6 x 6 pleine, opacite 0,2 si inactive
                        de 6 px centre, marge droite 8
     puce active        un anneau SVG se dessine        la meme puce a opacite 1

   La geometrie et le point de 6 px sont ici. L'anneau, lui, est un `<circle>` SVG que
   borgholm-core injectait dans chaque puce et dont le trace se dessine — `stroke-dashoffset` de
   110 a 0 en 0,6 s, avec une rotation de 200 degres. Aucune propriete CSS ne dessine un trace
   progressif sur une bordure : le SVG est reinjecte par `dedienne-elements`, et les regles qui
   l'animent sont juste apres.

   Les regles de la production, relues dans `borgholm/assets/css/main.css` (git, commit precedant
   cc0f06d6), portaient sur `.swiper-pagination-bullets` sans restriction : elles valaient pour
   TOUS les sliders du site. Ici elles sont limitees a `.dedienne-slider-pagination`, la classe
   posee par le plugin — les autres sliders de la page n'ont pas encore ete compares a la
   production, et leur imposer ce dessin serait un pari, pas une mesure. */

/* ---- La bande du bas : 64 px, dont 20 de blanc et 44 de pagination ----

   Premiere approche, abandonnee : sortir la pagination du flux absolu pour la remettre dans le
   flux, comme en production. Elle ne peut pas marcher ici. `.elementor-main-swiper` porte la
   hauteur reglee sur le widget ET `overflow: hidden` ; une pagination poussee sous une piste de
   555 px dans une boite de 555 px est donc simplement rognee. La production s'en sort parce que
   son conteneur n'a pas de hauteur imposee : il grandit pour contenir les deux.

   On garde donc le mecanisme d'Elementor — pagination en absolu dans une reserve basse, ce qu'il
   appelle « Outside » — en lui donnant les nombres de la production : hauteur du widget 619,
   reserve 64, pagination de 44 collee en bas. La piste fait alors 619 - 64 = 555, et il reste
   20 px entre l'image et les puces. Meme resultat, sans lutter contre la mecanique du widget.

   Le compte des classes : `.elementor-element.elementor-pagination-position-outside .swiper` en a
   trois pour le remplissage, et `.elementor-element .swiper
   .swiper-pagination-bullets.swiper-pagination-horizontal` en a QUATRE pour le `bottom`. On monte
   a quatre et cinq plutot que de compter au plus juste. */

.dedienne-carousel.elementor-pagination-position-outside .elementor-main-swiper.swiper {
    padding-bottom: 64px;
    /* Aucune hauteur imposee : elle vient du rapport des diapositives, comme en production. Le
       controle `height` du widget est laisse VIDE pour n'avoir pas a le contredire. */
    height: auto;
}

/* ---- Le rapport de l'image, et la largeur de 72,5 % au-dela de 1440 ----

   La production ne fixe pas la hauteur : son `<img>` est en `width: 100%; height: auto`, donc la
   diapositive suit le rapport de l'image source — 772 x 525, soit 1,4705 — a TOUTES les largeurs.
   Le `media-carousel` d'Elementor pose l'image en arriere-plan d'un `div`, qui n'a pas de taille
   intrinseque : `aspect-ratio` la lui rend.

   Les 72,5 % viennent de borgholm, relu dans git au commit precedant cc0f06d6 :

     .qodef-slider-layout--asymmetric .swiper-slide { width: 72.5%; cursor: grab; }
     (borgholm-core/inc/shortcodes/image-gallery/assets/css/scss/_image-gallery-default.scss:45)

   Le palier est 1440, celui de borgholm, et non les 1366 d'Elementor : c'est a 1441 que la
   production passe en `slidesPerView: 'auto'`. La regle ne peut s'appliquer que dans ce mode —
   des que `slidesPerView` est un nombre, Swiper ecrit une largeur EN LIGNE sur chaque diapositive,
   qui bat n'importe quelle feuille. La bascule est faite par `carousel-asymmetric.js`.

   `cursor: grab` fait partie du dessin d'origine : le slider s'annonce comme saisissable. */

.dedienne-carousel .swiper-slide {
    aspect-ratio: 772 / 525;
    height: auto;
    cursor: grab;
}

.dedienne-carousel .swiper-slide:active {
    cursor: grabbing;
}

@media (min-width: 1441px) {
    .dedienne-carousel .swiper-slide {
        width: 72.5%;
    }
}

.dedienne-carousel .swiper .swiper-pagination-bullets.dedienne-slider-pagination.swiper-pagination-horizontal {
    bottom: 0;
    height: 44px;
    /* La production aligne ses puces A GAUCHE du panneau, pas au centre. */
    text-align: left;
}

.dedienne-carousel .dedienne-slider-pagination .swiper-pagination-bullet {
    position: relative;
    width: 36px;
    height: 36px;
    margin: 0 8px;
    background-color: transparent;
    border: none;
    border-radius: 100%;
    opacity: 1;
    color: #000;
}

/* La premiere puce est collee au bord gauche : la production ne lui met pas de marge a gauche. */
.dedienne-carousel .dedienne-slider-pagination .swiper-pagination-bullet:first-child {
    margin-left: 0;
}

/* Le point : 6 px au centre de la zone de 36. */
.dedienne-carousel .dedienne-slider-pagination .swiper-pagination-bullet::after {
    content: '';
    display: block;
    position: absolute;
    top: 50%;
    left: 50%;
    width: 6px;
    height: 6px;
    background-color: #000;
    border-radius: 100%;
    transform: translateX(-50%) translateY(-50%);
    transition: background-color .2s ease-out;
}

/* ---- L'anneau qui se dessine, injecte par dedienne-elements ---- */

.dedienne-carousel .dedienne-slider-pagination .swiper-pagination-bullet .dedienne-svg-circle {
    position: absolute;
    display: block;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    z-index: 1;
    fill: none;
    color: currentColor;
    stroke: none;
    overflow: visible;
}

.dedienne-carousel .dedienne-slider-pagination .swiper-pagination-bullet .dedienne-svg-circle circle {
    stroke-dasharray: 110;
    stroke-dashoffset: 110;
    stroke: currentColor;
    stroke-width: 1;
    transform: rotate(-145deg);
    transform-origin: center;
    transition: all .6s cubic-bezier(.43, .41, .36, .9);
}

.dedienne-carousel .dedienne-slider-pagination .swiper-pagination-bullet:hover .dedienne-svg-circle circle,
.dedienne-carousel .dedienne-slider-pagination .swiper-pagination-bullet-active .dedienne-svg-circle circle {
    stroke-dashoffset: 0;
    transform: rotate(55deg);
}


/* ==========================================================================
   Menus du pied — le soulignement qui pousse depuis la gauche
   ==========================================================================

   La production souligne le lien survole par un trait de 1 px qui CROIT depuis la gauche :

     a::before   1 px, #FFFFFF, `left: 0; bottom: 0`, largeur 0 → 100 %,
                 `transition: width .2s ease-in-out`

   Le local n'avait rien du tout — c'est l'animation de survol manquante. Les quatre widgets ont
   deja `pointer: none`, et c'est le bon reglage : l'effet de pointeur d'Elementor ne ressemble pas
   a celui de la production, le sien faisant glisser une barre de 10 px depuis la DROITE en fondu
   sur 0,3 s avec une autre courbe.

   ---- Pourquoi `inline-block` fait partie de l'animation ----

   Elementor rend ses liens de menu en `display: flex`, donc pleine largeur de colonne : 295 px
   ici, contre 41 pour le mot « Values » en production. Un soulignement a 100 % d'un tel lien
   ferait 295 px de long. Le passage en `inline-block` n'est donc pas un detail de mise en page,
   c'est ce qui donne au trait la longueur du texte.

   La transition de couleur passe aussi a `color .2s ease-out` : Elementor met un `transition: .4s`
   sur TOUT, ce qui animait au passage la largeur du trait sur 0,4 s en plus de ses 0,2 s propres. */

/* Trois classes : `.elementor-nav-menu--main .elementor-nav-menu a { transition: .4s }` en compte
   deux et sa feuille est chargee apres celle du theme enfant, donc a egalite elle gagnait. */
.dedienne-footer-menu.elementor-widget-nav-menu .elementor-nav-menu a {
    position: relative;
    display: inline-block;
    transition: color .2s ease-out;
}

.dedienne-footer-menu.elementor-widget-nav-menu .elementor-nav-menu a::before {
    content: '';
    position: absolute;
    left: 0;
    bottom: 0;
    width: 0;
    height: 1px;
    background-color: #fff;
    transition: width .2s ease-in-out;
}

/* ---- L'opacite, et un compte de specificite qui ne se devine pas ----

   Elementor pose `opacity: 0` sur ce pseudo-element tant que le lien n'est ni survole, ni
   focalise, ni actif — c'est le mecanisme de ses effets de pointeur, et il vaut aussi pour
   `::before`. Sans contre-mesure, le trait apparait en fondu EN PLUS de pousser, ce que la
   production ne fait pas : chez elle il est opaque et seule sa largeur bouge.

   Sa regle est `.elementor-item:not(:hover):not(:focus):not(.elementor-item-active):not(.highlighted)::before`.
   Une seule classe, mais QUATRE `:not()`, et un `:not()` compte la specificite de son argument :
   cela fait cinq unites de niveau classe. Mes trois classes perdaient. On reprend donc la meme
   forme, avec deux classes de plus — sept contre cinq. Compter les classes ne suffit pas quand
   des pseudo-classes entrent en jeu. */
.dedienne-footer-menu.elementor-widget-nav-menu .elementor-item:not(:hover):not(:focus):not(.elementor-item-active):not(.highlighted)::before {
    opacity: 1;
}

.dedienne-footer-menu.elementor-widget-nav-menu .elementor-nav-menu a:hover::before,
.dedienne-footer-menu.elementor-widget-nav-menu .elementor-nav-menu a:focus::before,
.dedienne-footer-menu.elementor-widget-nav-menu .elementor-nav-menu a.elementor-item-active::before {
    width: 100%;
}

/* ==========================================================================
   Pied de page — les langues sur une ligne
   ==========================================================================

   Les liens de langue ne sont pas un widget : ce sont quatre entrées du menu WordPress « Meta »,
   posées par TranslatePress, rendues en fin du widget `7489468` sous le titre « OTHER ». Elles
   sortent en `<li class="trp-language-switcher-container">` dans un `<ul>` vertical, donc empilées.

   Le client les veut côte à côte. Elementor n'expose aucun réglage de mise en page par ENTRÉE de
   menu — son réglage `layout` vaut pour tout le widget — d'où le CSS. L'autre voie aurait été de
   sortir les langues vers un menu WordPress dédié rendu par un second widget en `layout:
   horizontal` ; elle a été écartée parce que TranslatePress replace ses entrées dans « Meta » à
   chaque langue ajoutée, ce qui aurait défait la manœuvre en silence.

   Note : la production ne compte que trois langues (EN / ES / CN). Le FR a été ajouté en local,
   et c'est cette quatrième ligne qui a rendu l'empilement voyant.

   ---- Trois points qui décident du résultat ----

   La PORTÉE. Les mêmes `li.trp-language-switcher-container` existent dans l'en-tête, menus et
   sous-menus confondus — dix occurrences dans la page servie. L'ancrage sur `.dedienne-footer-menu`
   n'est donc pas décoratif : sans lui, le sélecteur de langue de l'en-tête bascule aussi.

   LES DEUX COPIES. Le widget est en `dropdown: tablet` — le défaut d'Elementor, que personne n'a
   changé. Il rend donc DEUX listes : `#menu-1-…` sous `nav.elementor-nav-menu--main`, et
   `#menu-2-…` sous `nav.elementor-nav-menu--dropdown`. Au-delà de 1024 px la première est visible
   et la seconde masquée ; à 1024 et en dessous, c'est l'inverse. Une règle ancrée sur `--main`
   seule ne tient donc QUE sur le bureau — relevé le 2026-08-28 : quatre langues sur une ligne à
   1440, quatre langues sur quatre lignes à 1024, 767 et 390. D'où les deux branches ci-dessous.

   La SPÉCIFICITÉ. Le réglage `menu_space_between` du widget génère

     .elementor-131227 .elementor-element.elementor-element-7489468
       .elementor-nav-menu--main:not(.elementor-nav-menu--layout-horizontal)
       .elementor-nav-menu > li:not(:last-child) { margin-bottom: 8px }

   soit SEPT unités de niveau classe — un `:not()` compte la spécificité de son argument, et
   `.elementor-element` en est une à lui seul, facile à oublier dans le compte. Une première version
   à six a laissé la marge basse en place : mesurée à 8 px là où la règle écrivait 0. Les huit
   unités ci-dessous l'emportent sans dépendre de l'ordre des feuilles — le thème enfant est chargé
   après `post-131227.css`, mais cette égalité-là ne doit pas être ce qui fait tenir la règle.
   La huitième unité est `.menu-item`, que WordPress pose déjà sur ces `li` : rien d'artificiel.

   Sans cela, les codes tiennent bien sur une ligne mais les trois premiers traînent 8 px sous eux
   quand le dernier en est exempt (`:not(:last-child)`) — d'où aussi le `vertical-align: top`, qui
   aligne les boîtes par le haut et rend la ligne insensible à ce reliquat.

   Le `<ul>` d'un menu vertical n'est PAS en flex — `display: flex` n'est posé par Elementor Pro
   que sur `.elementor-nav-menu--layout-horizontal`. Un `inline-block` suffit donc, et le
   soulignement au survol du bloc précédent continue de mesurer la largeur du mot. */
.dedienne-footer-menu.elementor-element.elementor-widget-nav-menu .elementor-nav-menu--main
    .elementor-nav-menu > li.menu-item.trp-language-switcher-container,
.dedienne-footer-menu.elementor-element.elementor-widget-nav-menu .elementor-nav-menu--dropdown
    .elementor-nav-menu > li.menu-item.trp-language-switcher-container {
    display: inline-block;
    vertical-align: top;
    margin-bottom: 0;
    margin-right: 16px;
}

.dedienne-footer-menu.elementor-element.elementor-widget-nav-menu .elementor-nav-menu--main
    .elementor-nav-menu > li.menu-item.trp-language-switcher-container:last-child,
.dedienne-footer-menu.elementor-element.elementor-widget-nav-menu .elementor-nav-menu--dropdown
    .elementor-nav-menu > li.menu-item.trp-language-switcher-container:last-child {
    margin-right: 0;
}


/* ==========================================================================
   Pied de page — la mise en page sous 768 px
   ==========================================================================

   Deux défauts distincts sous le point de rupture mobile, mesurés contre la production.

   ---- 1. Le palier à deux colonnes, entre 681 et 767 px ----

   La production sert son pied avec la grille du thème Borgholm :

     qodef-col-num--3                                    au-delà de 768
     @media (max-width: 768px) and (min-width: 681px)    .qodef-grid-item { width: 50% }
     @media (max-width: 680px)                           .qodef-grid-item { width: 100% }

   Le local passait de quatre colonnes à une seule d'un coup, par la règle globale
   `.elementor-column { width: 100% }` d'Elementor. Les largeurs à 50 % sont désormais dans
   `_elementor_data` (voir `tools/templates/align-footer-colonnes.php`) : Elementor les expose.

   Le seuil à 680, lui, n'existe pas dans son vocabulaire — le kit n'a que deux points de rupture
   actifs, mobile 767 et tablette 1024. En ajouter un troisième régénérerait le CSS de toutes les
   pages du site pour un pied de page. Ce seuil vit donc ICI, et nulle part ailleurs.

   Spécificité : Elementor écrit ses largeurs de colonne en TROIS classes
   (`.elementor-131227 .elementor-element.elementor-element-ba44cc2`). Les cinq ci-dessous
   l'emportent sans dépendre de l'ordre de chargement des feuilles.

   ---- 2. Les marges latérales : 15 px là où la production en donne 7 % ----

   La production pose `.qodef-content-grid { width: 86% }` sous 800 px — soit 7 % de chaque côté —
   puis ANNULE la gouttière de 15 px de sa grille par un `margin: 0 -15px` sur le conteneur. Le
   contenu commence donc exactement à 7 % du bord.

   Le local n'a pas ce rattrapage : l'écart de colonnes « étendu » d'Elementor met 15 px de
   remplissage sur chaque `.elementor-element-populated`, et c'était là toute la respiration —
   15 px fixes, contre 27 px en production sur un écran de 390.

   D'où le `calc(7% - 15px)` sur la colonne extérieure : les 15 px de la gouttière s'y ajoutent et
   le total retombe sur les 7 % de la production à toute largeur. Un remplissage en pourcentage
   plat aurait donné 7 % + 15 px, soit 42 px à 390 — presque trois fois la valeur d'origine, là où
   la demande était de respirer « légèrement plus ». Le contrôle de remplissage d'Elementor ne
   prend pas de `calc`, et son unité est commune aux quatre côtés : il ne peut pas tenir 20 px en
   haut et 7 % sur les côtés. C'est la raison du CSS ici.

   La bande du bas (copyright / conditions) hérite de la même colonne extérieure ; avec ses 12 px
   propres elle atterrit à 7 % + 2 px. Cet écart de 2 px est laissé tel quel. */
@media (max-width: 767px) {
    .elementor-131227 .elementor-element.elementor-element-3bdd2a3.elementor-column > .elementor-element-populated {
        padding-left: calc(7% - 15px);
        padding-right: calc(7% - 15px);
    }
}

/* La bande noire du bas (copyright / conditions) est dans la colonne qui porte ce remplissage : elle
   s'arrêtait à 7 % - 15 px de chaque bord. On annule le remplissage de la colonne par une marge
   négative (7vw = 7 % de la colonne, qui fait la largeur de l'écran) et on le rend en remplissage de
   la bande, pour que le texte reste où il est : à 7 % + 12 px. */
@media (max-width: 767px) {
    .elementor-131227 .elementor-element.elementor-element-cc8f89e {
        margin-left: calc(15px - 7vw);
        margin-right: calc(15px - 7vw);
        width: calc(100% + 14vw - 30px);
        padding-left: calc(7vw - 3px);
        padding-right: calc(7vw - 3px);
    }
}

@media (max-width: 680px) {
    .elementor-131227 .elementor-element.elementor-element-af873b1 > .elementor-container > .elementor-column {
        width: 100%;
    }
}

/* ==========================================================================
   Sommaires d'ancres collés au bord — le même soulignement qu'au pied de page
   ==========================================================================

   Le sommaire latéral qui suit le défilement est, sur les 33 contenus publiés qui en portent un,
   toujours le même objet : un widget Elementor `icon-list` dont le réglage `sticky` est armé, et
   dont chaque entrée pointe une ancre `#…`. Aucun de ces 93 widgets (révisions comprises) ne
   porte de classe CSS, donc rien de nommé à quoi s'accrocher.

   ---- Pourquoi viser `data-settings` et non une classe ----

   Trois candidats, un seul tient :

     `.elementor-widget-icon-list`          trop large : 9 autres listes d'icônes sur la seule
                                            page /civil-tooling/, aucune n'est un sommaire.
     `.elementor-sticky`                    c'est le frontend d'Elementor Pro qui la POSE, en JS,
                                            à l'initialisation. Elle est absente du HTML servi :
                                            un survol avant l'init ne soulignerait rien.
     `[data-settings*='"sticky"']`          présent dans le HTML servi, donc valable dès le
                                            premier octet et sans JS.

   Le troisième donc. Le réglage `sticky` est un réglage « frontend », qu'Elementor sérialise en
   JSON dans `data-settings` de l'enveloppe du widget — `{"sticky":"top","sticky_offset":150,…}`.
   Les guillemets encadrant la clé sont ce qui évite de ferrer au passage `sticky_offset`,
   `sticky_on` et `sticky_effects_offset`. Vérifié : 1 widget retenu sur 10 sur /civil-tooling/,
   1 sur 9 sur /tooling-services/, 1 sur 4 sur /p-i/trent-7000/.

   Corollaire : toute page qui recevra plus tard un sommaire collant héritera de l'effet sans
   qu'on y revienne. C'est le motif du réglage qui est visé, pas un inventaire de pages.

   ---- Où poser le trait, et pourquoi pas sur le lien ----

   Deux emplacements sont déjà pris ou inadaptés :

     `li::after`   c'est le SÉPARATEUR d'Elementor (`divider: yes`) : 1 px pleine largeur de
                   colonne, à `bottom: 0`, sous les 7,5 px de `padding-bottom` de l'entrée.
                   L'écraser ferait disparaître les filets qui séparent les entrées.
     `a::before`   libre, mais inutile ici. Au pied de page il fallait d'abord repasser le lien
                   en `inline-block`, Elementor rendant ses liens de menu en `display: flex`
                   pleine largeur. Ici l'entrée `li` est elle-même `display: flex` avec
                   `justify-content: flex-start` et le lien pour unique enfant : il est donc DÉJÀ
                   à la largeur de son texte. Rien à convertir.

   Reste `.elementor-icon-list-text::after`, sur le `span` : libre, et déjà à la largeur exacte du
   texte puisqu'il est élément flexible du lien. Le trait se place à 7,5 px au-dessus du
   séparateur, sans le toucher.

   ---- La couleur ----

   `currentColor`, et non la couleur globale en dur. C'est le `span` lui-même qui porte
   `color: var(--e-global-color-secondary)` — le pseudo-élément hérite donc de la bonne teinte, et
   suivra un contenu qui la changerait. Le pied de page peut se permettre `#fff` en dur : son fond
   est sombre partout. Ici les sommaires vivent sur fond clair, en couleur secondaire.

   ---- Les 3 px, et pourquoi pas `bottom: 0` ----

   Signalé par Jérém : le trait était trop bas. `bottom: 0` le colle au bas de la boîte de LIGNE,
   pas au bas des glyphes — et l'interligne de ces sommaires est large : 12 px de corps pour une
   boîte de 25,995 px, soit 6 px de vide sous la jambe des lettres.

   La référence est le pied de page, dont l'interligne est bien plus serré : 13 px de corps pour
   20 px de boîte, donc 3 px de vide. C'est cet écart-là qu'il faut reproduire, pas la valeur
   `bottom: 0` : 6 - 3 = 3 px.

   Une valeur en dur se défend ici parce que la typographie ne varie pas. Relevé sur les 31
   contenus publiés qui portent un sommaire, 137 entrées au total : 12 px / 25,995 px partout, et
   un vide de 6 px sur CHAQUE entrée, sans un dixième d'écart. Si un jour un sommaire adopte un
   autre corps, c'est cette ligne qu'il faudra revoir.

   Le reste est repris tel quel du pied de page : 1 px, `left: 0`, largeur 0 → 100 %,
   `transition: width .2s ease-in-out`. La transition est déclarée sur le pseudo-élément, pas
   héritée : `transition` n'est pas une propriété héritable, et le `transition: color .3s` que
   pose Elementor sur le `span` ne l'atteint pas.

   `:focus` accompagne `:hover` — posé sur le lien lui-même, qui est ce qui reçoit le focus : le
   sommaire est le seul moyen de navigation interne de ces pages, il doit répondre au clavier. */
.elementor-widget-icon-list[data-settings*='"sticky"'] .elementor-icon-list-text {
    position: relative;
}

.elementor-widget-icon-list[data-settings*='"sticky"'] .elementor-icon-list-text::after {
    content: '';
    position: absolute;
    left: 0;
    bottom: 3px;
    width: 0;
    height: 1px;
    background-color: currentColor;
    transition: width .2s ease-in-out;
}

.elementor-widget-icon-list[data-settings*='"sticky"'] .elementor-icon-list-item a:hover .elementor-icon-list-text::after,
.elementor-widget-icon-list[data-settings*='"sticky"'] .elementor-icon-list-item a:focus .elementor-icon-list-text::after {
    width: 100%;
}

/* Recette 1, T02 et T05 : ces sommaires portent `divider: yes` dans leurs données Elementor, ce
   qui trace un filet orange de 1 px sous chaque entrée (`li::after`). La production n'en trace
   aucun : seul le soulignement au survol ci-dessus existe. */
.elementor-widget-icon-list[data-settings*='"sticky"'] .elementor-icon-list-item::after {
    display: none;
}

/* ==========================================================================
   Cartes « Our latest news »
   ==========================================================================

   Le modele de carte est reconstruit en widgets natifs ; ce bloc porte les trois choses que les
   controles d'Elementor n'expriment pas.

   ---- 1. La couleur heritee ----

   Le conteneur de la carte est rendu en `<a>` (`html_tag: a`), et un `<a>` sans regle de couleur
   prend le bleu de lien du navigateur : `rgb(0, 0, 238)`. Tout ce qui, dans la carte, ne declare
   pas sa propre couleur en heritait. La production rend un `<article>`, qui herite du noir du
   corps. C'est le defaut le plus VISIBLE de la carte, et le plus facile a manquer en lisant les
   reglages : aucun d'eux ne dit « bleu ».

   ---- 2. La barre orange ----

   La production ne met pas de bordure : `.qodef-e-inner::before` est une barre absolue de 2 px sur
   toute la hauteur de la carte. Ce n'est pas equivalent a une bordure — une bordure prend 2 px sur
   la largeur du contenu, un pseudo-element non. Avec la bordure de 3 px que portait le local, le
   contenu tombait a 311,67 la ou la production en met 313,7. La barre est donc dessinee ici et le
   reglage de bordure retire.

   ---- 3. L'extrait a 88 % ----

     .qodef-blog .qodef-blog-item .qodef-e-excerpt { margin: 17px 0 0; width: 88%; }
     (borgholm/assets/css/main.css, git, commit precedant cc0f06d6)

   Soit 276,06 sur les 313,7 du contenu — exactement la mesure. En dessous de 768 la production
   repasse en `width: auto`, ce que la derniere regle reproduit. */

.vignette-article {
    position: relative;
    color: #000;
}

.vignette-article::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 2px;
    height: 100%;
    background-color: #fe5000;
}

/* Seule la largeur. Les 17 px de marge haute sont deja portes par le `_margin` du widget : les
   redeclarer ici les DOUBLAIT, et l'extrait gagnait une ligne. */
.vignette-article .elementor-widget-theme-post-excerpt p {
    width: 88%;
    margin: 0;
}

@media (max-width: 768px) {
    .vignette-article .elementor-widget-theme-post-excerpt p {
        width: auto;
    }
}

/* ---- « Find out more » : le bouton textuel, fleche DEHORS ----

   Meme dessin que `.dedienne-bc-more`, dont les nombres sont repris a l'identique — hampe de
   30 x 2 a `right: -41px`, tete de 13,2 x 11 a `right: -49px`, et le meme SVG mesure au canvas.
   La difference est le porteur : ici un `icon-box`, dont l'icone est VIDEE dans le modele plutot
   que masquee — `custom-widget-icon-box.min.css` est imprime dans le corps de page, donc apres
   cette feuille, et redonnait son affichage a `.elementor-icon-box-icon`. Vider le reglage a la
   source est plus court et ne se laisse pas rattraper. */

.dedienne-news-more .elementor-icon-box-title {
    position: relative;
    display: inline-block;
    margin: 0;
    color: #000;
}

.dedienne-news-more .elementor-icon-box-title::after {
    content: '';
    position: absolute;
    right: -41px;
    top: 11.125px;
    width: 30px;
    height: 2px;
    background-color: #000;
    transform: translateY(-1px);
    transform-origin: left center;
    transition: transform .3s cubic-bezier(.475, .425, 0, .995);
}

.dedienne-news-more .elementor-icon-box-title::before {
    content: '';
    position: absolute;
    right: -49px;
    top: 11.125px;
    width: 13.2px;
    height: 11px;
    background-repeat: no-repeat;
    background-position: 0 0;
    background-size: 13.2px 12px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13.2 11'%3E%3Cpolygon fill='%23000' points='4.1,2.75 7.5,5.5 4.1,8.25'/%3E%3C/svg%3E");
    transform: translateY(-5.5px);
    transition: right .3s cubic-bezier(.475, .425, 0, .995);
}

.vignette-article:hover .dedienne-news-more .elementor-icon-box-title::after {
    transform: translateY(-1px) scaleX(1.3);
}

.vignette-article:hover .dedienne-news-more .elementor-icon-box-title::before {
    right: -58px;
}

/* ==========================================================================
   Colonne de texte de « Tooling Services » — la typographie qui n'atteint pas son <p>
   ==========================================================================

   Un widget `text-editor` rend son contenu dans un `<p>`, et Elementor declare la typographie du
   widget sur la RACINE du widget. Le `<p>` n'en herite donc que par cascade — et une valeur
   heritee perd contre n'importe quelle regle declaree. Or ce projet conserve, plus haut dans cette
   feuille, le `p { font-size: 14px; margin: 10px 0 0 }` que servait le main.css de borgholm.
   Resultat : les reglages de taille et d'interligne des widgets de texte etaient simplement
   annules sur le paragraphe rendu — le surtitre demandait 11 px et sortait a 14.

   La production n'a pas ce probleme : son titre de section rend le surtitre et le sous-titre dans
   des `<div>`, qui heritent normalement.

   On rend donc l'heritage a ces deux blocs, et on neutralise la marge du `<p>` : leur ecart vient
   des marges de widget, aux valeurs de la production. Le paragraphe de corps, lui, GARDE le
   `margin: 10px 0 0` global — c'est exactement ce que la production applique au sien.

   La regle est deliberement limitee a `.dedienne-ts-plat`. Le meme piege vaut pour tous les
   widgets de texte du site, mais les pages deja alignees au pixel visaient une taille de 14 px,
   que la regle globale donnait par accident : les corriger en bloc les decalerait toutes. */

.dedienne-ts-texte .dedienne-ts-plat p {
    font-size: inherit;
    line-height: inherit;
    letter-spacing: inherit;
    margin: 0;
}

/* Le paragraphe de corps garde sa marge HAUTE de 10 px, comme la production, mais pas la basse :
   la regle globale de cette feuille pose `p { margin: 10px 0 }` — deux valeurs, mesurees et
   documentees plus haut — alors que la production sert `margin: 10px 0 0` sur cette partie de son
   titre de section. Les 10 px du bas s'ajoutaient aux 24 px que le bouton apporte deja. La regle
   globale n'est PAS touchee : toutes les pages deja alignees au pixel reposent dessus. */
.dedienne-ts-texte .dedienne-ts-corps p {
    margin: 10px 0 0;
}

/* ==========================================================================
   Bouton « To Tooling Services » — la fleche, dessinee HORS du pave
   ==========================================================================

   Meme famille que `.dedienne-bc-more`, autre variante : la production a deux boutons a fleche,
   l'un plat sur fond transparent — l'article de blog — l'autre en pave plein. Les nombres
   diffferent, la tete de fleche est la meme.

     ::after   la hampe, 34 x 2 a `right: -18px`, origine gauche, `scaleX(1.3)` au survol
     ::before  la tete, 13,2 x 11 a `right: -26px`, qui glisse a -36px au survol
     les deux  `top: 26px`, transition 0,2 s ease-in-out

   La hampe n'est PAS un aplat : c'est `linear-gradient(90deg, #fff 50%, #000 50%)`. Seule sa
   moitie droite se voit donc — 17 px de trait a l'arret — et le `scaleX(1.3)` depuis le bord
   gauche fait glisser la separation vers la droite en l'allongeant a 22,1 px. Le trait a l'air de
   pousser vers la pointe alors que la boite ne fait que s'etirer. Un aplat de 34 px avec la meme
   transformation grandirait des DEUX bouts et ne donnerait pas ce mouvement.

   Le fond blanc de la moitie gauche n'est pas neutre : il suppose un fond de page blanc, ce qui
   est le cas ici. C'est la production qui fait ce pari, on le reprend tel quel.

   La tete reprend le SVG mesure de `.dedienne-bc-more` — meme glyphe ElegantIcons, meme boite de
   13,2 x 11, encre relevee au canvas sur la page de production. Voir le commentaire la-bas pour
   les mesures. */

.dedienne-ts-button .elementor-button {
    position: relative;
    /* La fleche sort du pave : rien ne doit la rogner. */
    overflow: visible;
    /* Une bordure TRANSPARENTE de 1 px. C'est ce qui explique les 238,81 x 54 de la production
       la ou le contenu et le remplissage n'en font que 236,81 x 52 : la boite est en border-box
       mais sans largeur imposee, donc elle grandit de la bordure. borgholm la pose pour qu'une
       bordure au survol puisse apparaitre sans decaler quoi que ce soit. Sans elle, le bouton
       etait juste a 2 px pres dans les deux dimensions. */
    border: 1px solid rgba(0, 0, 0, 0);
}

.dedienne-ts-button .elementor-button::after {
    content: '';
    position: absolute;
    right: -18px;
    top: 26px;
    width: 34px;
    height: 2px;
    background-image: linear-gradient(90deg, #fff 50%, #000 50%);
    transform: translateY(-1px);
    transform-origin: left center;
    transition: transform .2s ease-in-out;
}

.dedienne-ts-button .elementor-button::before {
    content: '';
    position: absolute;
    right: -26px;
    top: 26px;
    width: 13.2px;
    height: 11px;
    background-repeat: no-repeat;
    background-position: 0 0;
    background-size: 13.2px 12px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13.2 11'%3E%3Cpolygon fill='%23000' points='4.1,2.75 7.5,5.5 4.1,8.25'/%3E%3C/svg%3E");
    transform: translateY(-5.5px);
    transition: right .2s ease-in-out;
}

.dedienne-ts-button .elementor-button:hover::after,
.dedienne-ts-button .elementor-button:focus::after {
    transform: translateY(-1px) scaleX(1.3);
}

.dedienne-ts-button .elementor-button:hover::before,
.dedienne-ts-button .elementor-button:focus::before {
    right: -36px;
}

/* ==========================================================================
   Inscription infolettre — la fleche seule tient lieu de bouton d'envoi
   ==========================================================================

   Troisieme et derniere variante de la fleche maison, apres `.dedienne-bc-more` (plate, sur fond
   transparent) et `.dedienne-ts-button` (dans un pave plein). Ici il n'y a pas de pave du tout :
   le bouton d'envoi est une boite VIDE de 34 x 22, en position absolue au bout du champ, dont les
   deux pseudo-elements dessinent toute la fleche. Le gabarit CF7 130178 sort le `<button>` sans
   le moindre contenu — c'est ce que fait la production.

   Structure, posee par le gabarit CF7 et non par Elementor :

       .dedienne-subscribe            l'enveloppe, en `relative` : c'est le repere de la fleche
         span.wpcf7-form-control-wrap  emis par CF7 autour du champ
           input[type=email]           a 100 %, bordure basse noire
         button.dedienne-subscribe__envoi  la fleche

   Mesures de production du 2026-08-27, viewport 1440 :

       enveloppe  456 x 26,  `position: relative`
       champ      456 x 25,  remplissage 2 px 0, bordure basse 1 px #000, Work Sans 15/20
       bouton     34 x 22 en border-box, remplissage 10 px 16 px, bordure 1 px transparente,
                  `top: 50%` + `translateY(-50%)`, `right: 0`
       ::after    la hampe, 34 x 2, `right: 0`, centree verticalement, origine gauche,
                  `scaleX(1.3)` au survol
       ::before   la tete, 13,2 x 11, `right: -7px` qui glisse a -19px au survol
       les deux   transition `all .2s ease-in-out`

   Deux differences a ne pas confondre avec `.dedienne-ts-button` :

   1. La hampe est un APLAT noir, pas le degrade blanc/noir de l'autre variante. Là-bas la moitie
      gauche blanche masquait le trait pour donner l'illusion qu'il pousse ; ici la production
      s'en passe et se contente de l'etirement. Reprendre le degrade donnerait un trait deux fois
      trop court sur un fond #F5F5F5 qui n'est pas blanc.
   2. Le repere n'est pas le bouton mais l'enveloppe : le bouton est lui-meme absolu. Ses
      pseudo-elements se calent donc sur sa boite de remplissage, large de 32 px et non de 34 —
      d'ou un `right: 0` qui pose la hampe de 34 px a -2 px sur la gauche. Les nombres de la
      production s'expliquent tous par la, il n'y a rien a arrondir.

   La tete reprend le SVG des deux autres variantes : meme glyphe ElegantIcons, meme boite de
   13,2 x 11. La production sert la vraie fonte d'icones, d'ou ses 13,2031 px — 0,016 px d'ecart,
   le meme que sur les deux autres boutons. */

.dedienne-subscribe {
    position: relative;
}

.dedienne-subscribe input[type="email"] {
    /* Le champ occupe toute l'enveloppe. Sans cette ligne il retombe sur sa largeur intrinseque,
       celle que lui donne son attribut `size="40"` — 362 px, soit un champ visiblement plus court
       que la colonne et decale sur la gauche. Aucun reglage d'UAEL ne couvre la largeur du champ,
       la production le fait aussi en CSS. */
    width: 100%;
    box-sizing: border-box;
    /* Le champ est un `inline-block` dans une enveloppe de 26 px. Sur la ligne de base par defaut
       il descendait de 1 px pour laisser la place aux jambages ; la production l'aligne en haut.
       Un pixel, mais c'est celui qui decalait la fleche par rapport au trait. */
    vertical-align: top;
}

.dedienne-subscribe input[type="email"]::placeholder {
    /* Taille et famille viennent du champ, reglees dans Elementor. Ne restent ici que les deux
       proprietes qu'aucun controle n'expose. */
    opacity: 1;
    font-style: italic;
}

/* Les trois etats dans une seule liste, parce que la production ne touche PAS a la boite au
   survol : seuls les deux pseudo-elements bougent. C'est aussi ce qui regle la specificite.
   Le kit Elementor 6675 style le selecteur nu `button` — `.elementor-kit-6675 button` vaut une
   classe + un type, donc plus que `.dedienne-subscribe__envoi` seul, qui perdait le remplissage
   (17 px 30 px au lieu de 10 px 16 px), le fond, la taille de fonte, et voyait son survol
   basculer en pave noir. `.dedienne-subscribe button.dedienne-subscribe__envoi` vaut deux classes
   plus un type et gagne franchement, y compris sur `.elementor-kit-6675 button:hover`. Pas un
   seul `!important` : c'est la specificite qui tranche, pas la force. */
.dedienne-subscribe button.dedienne-subscribe__envoi,
.dedienne-subscribe button.dedienne-subscribe__envoi:hover,
.dedienne-subscribe button.dedienne-subscribe__envoi:focus {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    /* 34 x 22 en border-box pour 32 px de remplissage et 2 px de bordure : le contenu est nul,
       la boite n'existe que pour porter les deux pseudo-elements. */
    box-sizing: border-box;
    width: 34px;
    height: 22px;
    padding: 10px 16px;
    border: 1px solid rgba(0, 0, 0, 0);
    background: none;
    /* Herite par les deux pseudo-elements. Sans lui, le survol du kit les repeignait en #F5F5F5. */
    color: #000;
    line-height: 22px;
    font-size: 11px;
    cursor: pointer;
    /* La fleche sort de la boite sur la droite : rien ne doit la rogner. */
    overflow: visible;
}

.dedienne-subscribe__envoi::after {
    content: '';
    position: absolute;
    right: 0;
    top: 50%;
    width: 34px;
    height: 2px;
    background-color: #000;
    transform: translateY(-1px);
    transform-origin: left center;
    transition: transform .2s ease-in-out;
}

.dedienne-subscribe__envoi::before {
    content: '';
    position: absolute;
    right: -7px;
    top: 50%;
    width: 13.2px;
    height: 11px;
    background-repeat: no-repeat;
    background-position: 0 0;
    background-size: 13.2px 12px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13.2 11'%3E%3Cpolygon fill='%23000' points='4.1,2.75 7.5,5.5 4.1,8.25'/%3E%3C/svg%3E");
    transform: translateY(-5.5px);
    /* Sans effet de rendu ici — seul `right` s'anime — mais aligne sur la production pour que le
       harnais n'ait pas un faux ecart a signaler a chaque relevé. */
    transform-origin: left center;
    transition: right .2s ease-in-out;
}

.dedienne-subscribe__envoi:hover::after,
.dedienne-subscribe__envoi:focus-visible::after {
    transform: translateY(-1px) scaleX(1.3);
}

.dedienne-subscribe__envoi:hover::before,
.dedienne-subscribe__envoi:focus-visible::before {
    right: -19px;
}

/* ==========================================================================
   Popup de recherche — la meme fleche, dans le champ du widget Elementor
   ==========================================================================

   Le widget est un `search-form` d'Elementor Pro, pas un formulaire maison. Son bouton d'envoi
   n'emet plus rien : dans la popup 131512, `button_type` est passe a « text » avec un libelle
   VIDE, ce qui court-circuite les deux branches du rendu et laisse un `<button>` nu — le meme que
   le `.qodef-search-form-button` de la production. L'`aria-label="Search"` est pose hors du test,
   le bouton garde donc son nom accessible. Rien n'est masque en CSS : il n'y a rien a masquer.

   (Note pour plus tard : le bloc `.dedienne-art-side`, plus bas, masque le SVG du meme widget en
   affirmant que « le widget ne propose que ses propres icones ». C'est inexact — voir ci-dessus.
   Ce bloc-la n'a PAS ete touche, sa fleche est une autre variante et son chantier est clos.)

   Mesures relevees sur la production le 2026-08-27, regles lues a la source dans sa feuille :

       .qodef-search-form-button          absolu, colle au bord droit du champ, fond transparent
       ::after   la hampe, 34 x 2, `right: 1px`, aplat #000, origine gauche, `scaleX(1.3)` au survol
       ::before  la tete, `right: -8px` qui glisse a -19px au survol
       les deux  `top: 50%` + `translateY(-50%)`, transition `all .2s ease-in-out`

   C'est la fleche de l'infolettre au pixel pres, a un detail : la production part de `right: -8px`
   ici et de `right: -7px` la-bas, et les deux arrivent a -19px. Un pixel d'ecart a l'arret, decide
   par la production elle-meme ; on reprend ses nombres de chaque cote plutot que de les unifier. */

.search-form-popup .elementor-search-form__container {
    /* Elementor pose `overflow: hidden` sur ce conteneur. La tete de fleche depasse le bord droit
       du champ de 8 px a l'arret et de 19 px au survol : sans cette ligne elle est rognee, et
       l'animation ne se voit pas. La production laisse la sienne deborder de la meme facon. */
    overflow: visible;
}

.search-form-popup .elementor-search-form__submit {
    position: relative;
    cursor: pointer;
}

.search-form-popup .elementor-search-form__submit::after {
    content: '';
    position: absolute;
    top: 50%;
    right: 1px;
    width: 34px;
    height: 2px;
    background-color: #000;
    transform: translateY(-50%);
    transform-origin: left center;
    transition: transform .2s ease-in-out;
}

.search-form-popup .elementor-search-form__submit::before {
    content: '';
    position: absolute;
    top: 50%;
    right: -8px;
    width: 13.2px;
    height: 11px;
    background-repeat: no-repeat;
    background-position: 0 0;
    background-size: 13.2px 12px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13.2 11'%3E%3Cpolygon fill='%23000' points='4.1,2.75 7.5,5.5 4.1,8.25'/%3E%3C/svg%3E");
    transform: translateY(-50%);
    transition: right .2s ease-in-out;
}

.search-form-popup .elementor-search-form__submit:hover::after,
.search-form-popup .elementor-search-form__submit:focus-visible::after {
    transform: translateY(-50%) scaleX(1.3);
}

.search-form-popup .elementor-search-form__submit:hover::before,
.search-form-popup .elementor-search-form__submit:focus-visible::before {
    right: -19px;
}

/* ---- Le logo, que le flex de la rangee comprimait ----

   Borne a 1025 et au-dela. Sa raison d'etre est le menu de bureau : la somme logo + barre + icone
   depasse la largeur utile, et sans cette regle le logo tombait a 173,63 px au lieu de 205. Sous
   1024 le menu de bureau n'est plus la et c'est l'inverse qu'il faut — la production rabote son
   logo a 166 px a 320 pour garder son entete sur une ligne.

   Cette regle avait d'ailleurs la meme specificite que celle qui la contredit dans le bloc
   responsive, mais venait APRES dans le fichier : elle gagnait. Une media query n'ajoute aucune
   specificite. Plutot que de surencherir, on borne la regle a la plage ou elle a un sens. */
@media (min-width: 1025px) {
    .dedienne-header-logo {
        flex-shrink: 0;
    }
}


/* ==========================================================================
   Rangee de pictogrammes en carrousel sous 768
   ==========================================================================

   Le balisage est monte par `picto-slider.js` : le `.elementor-container` de la section recoit
   `swiper`, ses colonnes deviennent des `swiper-slide` dans un `.swiper-wrapper` ajoute, et deux
   fleches sont posees en fin de conteneur. Tout est retire au-dessus de 768.

   Les regles restent SOUS 768 et ne sont pas dans une couche : Swiper pose ses propres largeurs en
   ligne sur les slides, et ses regles de base ne sont dans aucune `@layer` — une regle en couche
   perdrait, comme sur la galerie du shim. */

@media (max-width: 767px) {
    .dedienne-picto-swiper {
        position: relative;
        overflow: hidden;
    }

    /* Elementor donne aux colonnes une largeur en pourcentage — 25 % pour quatre pictos. Swiper
       calcule la sienne et l'ecrit en ligne ; il faut donc neutraliser celle d'Elementor, sinon
       les deux se cumulent et la vue deborde. */
    .dedienne-picto-swiper > .swiper-wrapper > .elementor-column {
        width: auto;
        max-width: none;
        flex: 0 0 auto;
    }

    /* ---- Le remplissage de la section qui porte la rangee ----

       Ces sections gardent 100 px de remplissage horizontal jusqu'en bas, alors que les sections
       voisines passent a 30 sur mobile. Le conteneur du carrousel tombait donc a 300 px a 500, soit
       des vues de 140 ou les libelles passaient a la ligne. A 30 px de remplissage le conteneur
       fait 440, comme celui du carrousel de produits, et les vues 210.

       `!important` : la regle a battre est le CSS genere de la page, qui nomme l'identifiant du
       gabarit et de l'element — trois classes. `:has()` en ajoute une seule, et surencherir en
       nommant ces identifiants dans le theme les figerait. */
    .elementor-section:has( .dedienne-picto-swiper ) {
        padding-left: 30px !important;
        padding-right: 30px !important;
    }

    /* Toutes les boites INTERMEDIAIRES entre la section la plus exterieure et le carrousel sont
       remises a zero, sinon leurs remplissages se cumulent.

       Trois versions ont ete necessaires, chacune parce que la precedente ne regardait pas au bon
       endroit. La premiere posait 30 px sur toute section ancetre : sur une rangee imbriquee dans
       deux sections, les 30 se cumulaient et le conteneur tombait a 380 au lieu de 440. La
       deuxieme remettait a zero la seule section portant DIRECTEMENT le carrousel — ce qui suffit
       quand la chaine ne compte que des sections. Sur /ground-support-equipment/ les 100 px
       horizontaux sont sur la COLONNE, et le conteneur tombait a 240 pour 440 attendus.

       D'ou `:is()` sur les quatre types de boites qu'Elementor empile. La regle est plus
       specifique que celle des 30 px — elle exige un ancetre de plus — donc la plus exterieure,
       qui n'a pas d'ancetre porteur, garde ses 30. */
    .elementor-section:has( .dedienne-picto-swiper )
    :is( .elementor-section, .elementor-column, .elementor-element-populated, .elementor-container ):has( .dedienne-picto-swiper ) {
        padding-left: 0 !important;
        padding-right: 0 !important;
    }

    /* Les fleches : un chevron trace en bordure, comme celles du carrousel de produits. */
    .dedienne-picto-prev,
    .dedienne-picto-next {
        position: absolute;
        top: 50%;
        z-index: 2;
        width: 22px;
        height: 22px;
        margin-top: -11px;
        cursor: pointer;
        border-top: 2px solid #000;
        border-right: 2px solid #000;
        transition: opacity .2s ease-out;
    }

    /* 5 px et non 0 : le chevron est un carre de 22 tourne de 45 degres, sa boite englobante fait
       donc 31 et depasse de 4,5 px de chaque cote. A `left: 0` la fleche partait a x=25 pour un
       cadre commencant a 30, et le `overflow: hidden` que Swiper exige lui coupait 5 px. */
    .dedienne-picto-prev {
        left: 5px;
        transform: rotate(-135deg);
    }

    .dedienne-picto-next {
        right: 5px;
        transform: rotate(45deg);
    }

    /* ---- Centrer le picto dans sa vue ----

       L'enveloppe de colonne garde le remplissage droit de 25 px qui sert de gouttiere dans la
       grille de bureau : le picto occupait 185 px d'une vue de 210 et se retrouvait cale a gauche,
       d'ou l'impression de vues non centrees. En slider la gouttiere est portee par
       `spaceBetween`, ce remplissage n'a plus d'objet. */
    .dedienne-picto-swiper > .swiper-wrapper > .elementor-column > .elementor-element-populated {
        padding-left: 0;
        padding-right: 0;
    }

    /* Le centrage du picto dans sa vue n'est PAS ici : c'est un réglage `text_align_mobile`, posé
       par tools/templates/align-pictos-mobile.php. Elementor écrit l'alignement dans le CSS généré
       de la page, sur un sélecteur nommant le gabarit et l'élément — quatre classes. Trois
       surenchères depuis le thème ont perdu avant qu'on prenne le bon levier. */

    .dedienne-picto-prev:hover,
    .dedienne-picto-next:hover {
        opacity: .55;
    }

    /* Swiper masque une fleche inactive par cette classe. En boucle elle ne sert pas, mais la
       regle evite un chevron mort si la boucle etait desactivee un jour. */
    .dedienne-picto-prev.swiper-button-disabled,
    .dedienne-picto-next.swiper-button-disabled {
        opacity: .25;
        pointer-events: none;
    }

    /* Pas de remplissage sur le `.swiper-wrapper` : Swiper le TRANSLATE et calcule la largeur des
       vues sur le conteneur, un remplissage la lui fausse — les vues tombaient a 140 px au lieu de
       210. Les fleches surplombent donc les vues, exactement comme celles du carrousel de produits.
       C'est aussi pour cela que leur zone cliquable est petite : elle ne doit pas manger la vue. */
}


/* ==========================================================================
   Onglets verticaux — le style « tableau » de la production
   ==========================================================================

   Sur /company/, /locations/, /careers/ et /contact/ ces blocs sont des widgets `tabs` NATIFS, et
   ils sortaient avec le style par defaut d'Elementor : un cadre de 1 px #D5D8DC autour de chaque
   titre et autour du panneau, ce qui donne bien l'aspect d'un tableau brut. Ailleurs sur le site les
   memes blocs passent par le shim `qi_addons_for_elementor_tabs_horizontal`, qui porte le dessin
   voulu — d'ou le « style deja present dans d'autres pages » signale par Jerem.

   Releve sur la production, /company/ a 1440 :

       ul                     pas de bordure, pas de remplissage
       li                     45 de haut, pas de bordure
       a                      remplissage 0 20 0 0, interligne 45, 13px / 500, +0,1px, capitales
                              bordure DROITE de 2 px — et c'est elle qui dessine le filet vertical
       a inactif              #CACACA, texte ET bordure
       a actif                #FE5000, texte ET bordure
       contenu                pas de bordure, texte a 20 px a droite du filet

   Le filet vertical n'est donc pas un trait pose sur le conteneur : c'est la bordure droite de
   chaque ancre, empilee. C'est pour cela que le segment de l'onglet actif est orange et le reste
   gris — un seul trait n'aurait pas pu faire les deux.

   La frise horizontale de la meme page (`tabs-history`, huit annees) n'est pas concernee : elle
   porte `elementor-tabs-view-horizontal` et le selecteur ne l'atteint pas.

   Quatre niveaux de classes pour battre le CSS genere par Elementor, qui nomme le gabarit et
   l'element : `.elementor-tabs-wrapper` et `.elementor-tabs-content-wrapper` sont ajoutes a la
   chaine uniquement pour cela. */

/* Le cadre est pose a TROIS endroits par Elementor : chaque titre, le panneau, et l'enveloppe des
   panneaux. Oublier la troisieme laissait un liseré de 1 px #D5D8DC sur trois cotes autour du
   contenu — invisible dans les styles calcules du panneau, visible sur la capture. */
.elementor-widget-tabs.elementor-tabs-view-vertical .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title,
.elementor-widget-tabs.elementor-tabs-view-vertical .elementor-tabs .elementor-tabs-content-wrapper,
.elementor-widget-tabs.elementor-tabs-view-vertical .elementor-tabs .elementor-tabs-content-wrapper .elementor-tab-content {
    border: 0;
}

.elementor-widget-tabs.elementor-tabs-view-vertical .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title {
    padding: 0 20px 0 0;
    border-right: 2px solid #cacaca;
    color: #cacaca;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: .1px;
    line-height: 45px;
    text-transform: uppercase;
    transition: color .25s ease-out, border-color .25s ease-out;
}

.elementor-widget-tabs.elementor-tabs-view-vertical .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title:hover,
.elementor-widget-tabs.elementor-tabs-view-vertical .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title:focus-visible,
.elementor-widget-tabs.elementor-tabs-view-vertical .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title.elementor-active {
    border-right-color: #fe5000;
    color: #fe5000;
}

.elementor-widget-tabs.elementor-tabs-view-vertical .elementor-tabs .elementor-tabs-content-wrapper .elementor-tab-content {
    padding: 0 0 0 20px;
}

/* ---- La variante HORIZONTALE : le meme principe, tourne d'un quart de tour ----

   Meme bloc, meme page : la frise des annees (`tabs-history`). Elle est restee au cadre d'Elementor
   parce que la premiere passe ne visait que `elementor-tabs-view-vertical`.

   Releve sur la production, /company/ a 1440 :

       ul        display: flex, 584 de large, 31 de haut, ni bordure ni remplissage
       li        58 x 31, ACCOLES — 258, 316, 374, 432 : un pas de 58 pour dix items,
                 soit 584 / 10. Les ancres se partagent la largeur a parts egales.
       a         58 x 31, remplissage 0, interligne 29, 13px / 500, +0,4px, capitales,
                 bordure BASSE de 2 px, texte cale a gauche
       a inactif #CACACA, texte ET bordure
       a actif   #FE5000, texte ET bordure
       contenu   pas de bordure, remplissage 26 0 0

   Le filet horizontal est donc, comme le vertical, fait des bordures des ancres mises bout a bout —
   d'ou le segment orange sous l'onglet actif. L'interlettrage differe de la variante verticale :
   0,4 px contre 0,1.

   `flex: 1` sur les titres reproduit le partage a parts egales. Sans lui, Elementor les dimensionne
   sur leur contenu — mesure en local, 85 puis 87 px — et le filet reste continu mais les onglets ne
   sont plus alignes sur une trame. */

.elementor-widget-tabs.elementor-tabs-view-horizontal .elementor-tabs .elementor-tabs-wrapper {
    display: flex;
}

.elementor-widget-tabs.elementor-tabs-view-horizontal .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title,
.elementor-widget-tabs.elementor-tabs-view-horizontal .elementor-tabs .elementor-tabs-content-wrapper,
.elementor-widget-tabs.elementor-tabs-view-horizontal .elementor-tabs .elementor-tabs-content-wrapper .elementor-tab-content {
    border: 0;
}

.elementor-widget-tabs.elementor-tabs-view-horizontal .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title {
    /* CORRECTION : `flex: 1` etait faux. Les items de la production ne se partagent PAS la largeur
       — mesures a 58 px chacun a 1440, 1200 et 1100, donc une largeur FIXE et non un pourcentage,
       et la frise s'arrete a 722 sur les 584 disponibles au lieu de les remplir. C'est ce que Jerem
       a vu : « la frise ne prend pas 100% de la largeur ».

       Ici on met seulement `0 0 auto` : les onglets se dimensionnent sur leur libelle et se tassent
       a gauche. Les 58 px sont une metrique de FRISE D'ANNEES, posee plus bas sur `.tabs-history`
       seule — l'imposer a tout onglet horizontal couperait n'importe quel libelle plus long. */
    flex: 0 0 auto;
    padding: 0;
    border-bottom: 2px solid #cacaca;
    color: #cacaca;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: .4px;
    line-height: 29px;
    text-align: left;
    text-transform: uppercase;
    transition: color .2s ease-out, border-color .2s ease-out;
}

.elementor-widget-tabs.elementor-tabs-view-horizontal .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title.elementor-active {
    border-bottom-color: #fe5000;
    color: #fe5000;
}

.elementor-widget-tabs.elementor-tabs-view-horizontal .elementor-tabs .elementor-tabs-content-wrapper .elementor-tab-content {
    padding: 26px 0 0;
}

/* ---- La frise des annees : 58 px par onglet ----

   Releve sur la production a 1440, 1200 et 1100 : les huit annees font 58 px CHACUNE aux trois
   largeurs. Ce n'est donc pas un partage ni un pourcentage, c'est une largeur fixe calee sur un
   libelle de quatre chiffres. La frise occupe 8 x 58 = 464 px et laisse le reste vide.

   `padding-right` plutot que `width` : le libelle reste cale a gauche de son onglet, comme en
   production ou le span de 31 px commence exactement au bord de l'ancre. */
.elementor-widget-tabs.tabs-history .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title {
    flex: 0 0 58px;
}

/* ---- La regle « infinie » d'Elementor, a eteindre ----

   Elementor trace sur CHAQUE titre d'onglet un `::before` ET un `::after` de 1 px de haut et
   12987 px de large, en position absolue a `bottom: 0`, l'un parti a `left: -12987px` et l'autre a
   `left: 58px`. C'est son mecanisme pour prolonger le soulignement de part et d'autre des onglets.

   Superposes a la bordure de 2 px que sert la production, ils donnent une DOUBLE ligne, et celui du
   dernier onglet continue au-dela — apres « 2023 » dans la frise. Signale par Jerem.

   Ils avaient echappe a deux relevés successifs : le premier ne regardait que les bordures des
   ELEMENTS, le second n'elargissait que la bande verticale de recherche. Un trait peut venir d'un
   pseudo-element, et `querySelectorAll` ne les voit pas — il faut les demander nommement a
   `getComputedStyle`.

   Eteints sur les deux variantes : la production n'a aucun pseudo-element sur ces titres. */

.elementor-widget-tabs.elementor-tabs-view-horizontal .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title::before,
.elementor-widget-tabs.elementor-tabs-view-horizontal .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title::after,
.elementor-widget-tabs.elementor-tabs-view-vertical .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title::before,
.elementor-widget-tabs.elementor-tabs-view-vertical .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title::after {
    content: none;
}

/* Actualités : les images « large » de WordPress (800 px) gardent leur attribut width et restaient 13 px
   plus étroites que la colonne (813 px) ; en production elles occupent toute la largeur. */
.elementor-widget-theme-post-content img.size-large {
    width: 100%;
    height: auto;
}

/* ---- Frise des annees en mobile : l'accordeon seul ----

   Sous 768 px Elementor remplace la bande d'onglets par un accordeon (un titre `elementor-tab-mobile-title`
   par onglet) et masque la bande. Sur les onglets horizontaux, sa regle `display: flex` est posee sans
   media query avec une specificite plus forte que ce masquage : la frise des huit annees restait affichee
   AU-DESSUS de l'accordeon, qui repete les memes annees. On garde l'accordeon, comme les onglets verticaux. */
@media (max-width: 767px) {
    .elementor-widget-tabs.tabs-history .elementor-tabs .elementor-tabs-wrapper {
        display: none;
    }

    /* Titres d'accordéon sans cadre : Elementor en pose un de 1 px #D5D8DC sur trois côtés de chaque titre. */
    .elementor-widget-tabs.elementor-widget .elementor-tabs .elementor-tab-title.elementor-tab-mobile-title {
        padding: 10px 0;
        border: 0;
    }

    /* /contact/ : l'onglet vertical des localisations passe en bande horizontale sous 768 px, comme les
       onglets de /locations/ (bande à la ligne, filet bas de 2 px, panneau dessous). */
    .elementor-widget-tabs.elementor-tabs-view-vertical.dedienne-adv-tabs--vertical .elementor-tabs .elementor-tabs-wrapper {
        display: flex;
        flex-wrap: wrap;
        gap: 6px 28px;
        width: 100%;
        float: none;
        margin-bottom: 20px;
    }

    .elementor-widget-tabs.elementor-tabs-view-vertical.dedienne-adv-tabs--vertical .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title {
        flex: 0 0 auto;
        padding: 0;
        border-right: 0;
        border-bottom: 2px solid #cacaca;
        line-height: 29px;
    }

    .elementor-widget-tabs.elementor-tabs-view-vertical.dedienne-adv-tabs--vertical .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title:hover,
    .elementor-widget-tabs.elementor-tabs-view-vertical.dedienne-adv-tabs--vertical .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title:focus-visible,
    .elementor-widget-tabs.elementor-tabs-view-vertical.dedienne-adv-tabs--vertical .elementor-tabs .elementor-tabs-wrapper .elementor-tab-title.elementor-active {
        border-bottom-color: #fe5000;
    }

    .elementor-widget-tabs.elementor-tabs-view-vertical.dedienne-adv-tabs--vertical .elementor-tabs .elementor-tabs-content-wrapper .elementor-tab-content {
        padding: 0;
    }

    /* Accordéon des années : même habillage que celui des onglets verticaux de la page (« OEM SPECIFICATION »,
       « DESIGN AND BUILD ») : 500, capitales, gris #b3b3b3 à l'état replié, contenu décalé de 20 px. */
    .elementor-widget-tabs.tabs-history .elementor-tabs .elementor-tab-mobile-title {
        font-weight: 500;
        text-transform: uppercase;
    }

    .elementor-widget-tabs.tabs-history .elementor-tabs .elementor-tab-mobile-title:not(.elementor-active) {
        color: #b3b3b3;
    }

    .elementor-widget-tabs.tabs-history .elementor-tabs .elementor-tabs-content-wrapper .elementor-tab-content {
        padding: 0 0 0 20px;
    }
}

/* Carrousel de produits (liste Qi) : Swiper dessine ses chevrons en `content` sur `:after` (police swiper-icons)
   alors que Qi pose déjà son propre SVG dans le bouton, d'où les flèches en double sur /aircraft-tooling/.
   Même neutralisation que pour le carrousel de témoignages du plugin dedienne-elements. */
.qodef-team-list .swiper-button-prev:after,
.qodef-team-list .swiper-button-next:after {
    display: none;
}

/* Onglets horizontaux de /locations/ (régions) : sans padding ni écart, les libellés se touchaient. La bande
   reste affichée à toute largeur (ces onglets n'ont pas de titres d'accordéon visibles) et passe à la ligne. */
.elementor-widget-tabs.elementor-tabs-view-horizontal:not(.tabs-history) .elementor-tabs .elementor-tabs-wrapper {
    flex-wrap: wrap;
    gap: 6px 28px;
}

/* ==========================================================================
   Numeros de telephone : le bleu du navigateur, encore
   ==========================================================================

   Sur les blocs Locations, huit numeros sortaient en `rgb(0, 0, 238)` — le bleu par defaut de
   l'agent utilisateur pour un `<a>` sans regle de couleur. Les vingt-six autres sont noirs parce
   que leur widget porte un reglage de couleur de lien ; ceux-la n'en ont pas. La production sert
   TOUS ses numeros en `rgb(0, 0, 0)`.

   Quatrieme occurrence de ce piege sur le chantier, apres le conteneur des cartes d'actualite, le
   lien du titre de section et celui du bloc /full-refurbishment/. Un `<a>` sans couleur n'herite
   PAS : il prend le defaut de l'agent utilisateur.

   `#000` et non `inherit` : la couleur heritee autour de ces liens est #333, alors que la
   production met du noir franc.

   Le pied de page ne porte aucun lien `tel:` — verifie — donc cette regle ne peut pas y noircir un
   lien sur fond sombre. */

.elementor-widget-text-editor a[href^="tel"] {
    color: #000;
}


/* ==========================================================================
   Cadre du gabarit « Portfolio Item — Article » — l'echelle complete
   ==========================================================================

   Le reglage Elementor de cette section pose `content_width: 1130`, soit la grille de 1100 plus les
   30 px de gouttiere. Elementor en fait un PLAFOND : entre 1025 et 1399 le cadre devenait donc
   fluide, alors que la production sert des largeurs FIXES par palier. D'ou un cadre plus etroit en
   local sur toute cette plage, signale par Jerem.

   Releve de la production, cadre mesure sur `/p-i/shock-absorbers-engine-stand/` :

       fenetre   1440  1400  1366  1280  1201 | 1200  1100  1025 | 1024   900   801 | 800   700   500 | 480   390
       cadre     1130  1130  1130  1130  1130 |  990   990   990 |  798   798   798 | 718   632   460 | 424   350

   Et le local avant correction, sur les memes largeurs : 1130, 1130, 1128, 1057, 992, 991, 909 —
   une rampe au lieu de quatre crans.

   Les valeurs se lisent toutes comme « palier de la grille + 30 » :

       1430 = 1400 + 30      990 = 960 + 30            718 = 800 x 86 % + 30
       1130 = 1100 + 30      798 = 768 + 30            424 = 480 x 82 % + 30

   Ce sont exactement les paliers de `.dedienne-content-grid`, ce qui confirme la lecture : ce cadre
   EST la grille de contenu, augmentee de sa gouttiere.

   `width` et non `max-width` : c'est une largeur imposee, et un plafond laisserait la rampe. La
   chaine de selecteurs est longue parce que la regle a battre est le CSS genere du gabarit,
   `.elementor-131750 .elementor-element.elementor-element-dpia100 > .elementor-container`, a trois
   classes et charge apres le theme.
   ========================================================================== */

.dedienne-pi-article.elementor-section.elementor-top-section.elementor-section-boxed > .elementor-container {
    width: 1130px;
    max-width: 100%;
}

@media only screen and (max-width: 1200px) {

    .dedienne-pi-article.elementor-section.elementor-top-section.elementor-section-boxed > .elementor-container {
        width: 990px;
    }
}

@media only screen and (max-width: 1024px) {

    .dedienne-pi-article.elementor-section.elementor-top-section.elementor-section-boxed > .elementor-container {
        width: 798px;
    }
}

@media only screen and (max-width: 800px) {

    .dedienne-pi-article.elementor-section.elementor-top-section.elementor-section-boxed > .elementor-container {
        width: calc(86% + 30px);
    }
}

@media only screen and (max-width: 480px) {

    .dedienne-pi-article.elementor-section.elementor-top-section.elementor-section-boxed > .elementor-container {
        width: calc(82% + 30px);
    }
}

/* Le cran du haut vient EN DERNIER, et pas avec les autres paliers de 1441 plus haut dans la
   feuille. Il y etait d'abord, et la regle de base de cette echelle — posee plus bas — l'ecrasait :
   meme specificite, mais plus tard dans le fichier. Mesure : le cadre retombait a 1130 a 1441 alors
   qu'il valait bien 1430 avant l'ajout de l'echelle. Une requete de media ne protege pas d'une regle
   ulterieure de meme poids. */
@media only screen and (min-width: 1441px) {

    .dedienne-pi-article.elementor-section.elementor-top-section.elementor-section-boxed > .elementor-container {
        width: 1430px;
    }
}

/* ---------------------------------------------------------------------------
   Gabarit « Template Article » (131537) — cadre calé sur la grille de production

   La production place l'article dans un cadre suivant les mêmes paliers que le
   reste du site, avec une gouttière de 50 px (le gabarit portfolio en utilise 30) :

     viewport   cadre   contenu (75 %)   latérale (25 %)
      ≥ 1441    1450         1088             363
        1440    1150          863             288
        1200    1010          758             253
      ≤ 1024     818          818             818   (empilé)
         800     738          738             738
         480     444          444             444

   Le cadre ne porte aucun remplissage latéral, chaque colonne en porte 25 px :
   le contenu utile fait donc exactement la largeur de grille (1150 − 50 = 1100).
   Un pourcentage ne peut pas reproduire ces paliers — le gabarit portait 80 %,
   ce qui ne coïncide avec la production qu'à une seule largeur.

   `flex-shrink: 0` n'est pas décoratif : un balisage en ligne mal fermé dans le
   contenu (une traduction avec un <i> non refermé, par exemple) est reconstruit
   par l'analyseur HTML au niveau du conteneur et devient un frère flex. Sans
   cette règle, ce frère fantôme écrase la colonne de contenu — mesuré à 452 px
   au lieu de 863 px avant correction.
   --------------------------------------------------------------------------- */

.dedienne-art-grid.e-con {
    width: 1150px;
    max-width: 100%;
    gap: 0;
    padding-left: 0;
    padding-right: 0;
}

.dedienne-art-grid > .dedienne-art-main.e-con { width: 75%; }
.dedienne-art-grid > .dedienne-art-side.e-con { width: 25%; }

.dedienne-art-grid > .dedienne-art-main.e-con,
.dedienne-art-grid > .dedienne-art-side.e-con {
    flex-shrink: 0;
    padding-left: 25px;
    padding-right: 25px;
}

@media (max-width: 1200px) {
    .dedienne-art-grid.e-con { width: 1010px; }
}

@media (max-width: 1024px) {
    .dedienne-art-grid.e-con {
        width: 818px;
        flex-direction: column;
        row-gap: 30px;
    }
    .dedienne-art-grid > .dedienne-art-main.e-con,
    .dedienne-art-grid > .dedienne-art-side.e-con { width: 100%; }
}

@media (max-width: 800px) {
    .dedienne-art-grid.e-con { width: calc( 86% + 50px ); }
}

@media (max-width: 480px) {
    .dedienne-art-grid.e-con { width: calc( 82% + 50px ); }
}

/* Le palier haut se place en dernier : à poids de sélecteur égal, c'est l'ordre
   du fichier qui tranche, et la règle de base l'emporterait sinon. */
@media (min-width: 1441px) {
    .dedienne-art-grid.e-con { width: 1450px; }
}

/* --- Colonne latérale ---------------------------------------------------- */

/* Bloc « Category » : la production le rend en h3 25 px / 300 suivi d'une liste
   de catégories en 18 px / 700 sur #464646. Elementor enveloppe les widgets
   WordPress avec un h5, d'où le sélecteur. */
.dedienne-art-side .elementor-widget-wp-widget-categories h5 {
    margin: 0 0 13px;
    color: #000;
    font-size: 25px;
    font-weight: 300;
    line-height: 26.675px;
    /* Le kit met les h5 en capitales interlettrées ; la production affiche ce
       titre tel qu'il est saisi, comme les autres titres de la latérale. */
    text-transform: none;
    letter-spacing: normal;
}

.dedienne-art-side .elementor-widget-wp-widget-categories ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

.dedienne-art-side .elementor-widget-wp-widget-categories li {
    /* Le compteur « (26) » est un nœud texte de la puce, placé HORS du lien par
       le widget WordPress. La police doit donc être portée par la puce, sinon le
       nombre reste dans celle du kit alors que le terme passe en Cormorant.
       C'est aussi ce que fait la production : puce et lien y sont identiques. */
    font-family: 'Cormorant', Georgia, serif;
    font-size: 18px;
    font-weight: 700;
    line-height: 26px;
    color: #464646;
}

/* Sans règle de couleur, un <a> retombe sur le bleu par défaut du navigateur. */
.dedienne-art-side .elementor-widget-wp-widget-categories li a { color: #464646; }

/* Articles liés : titre seul, 15 px / 17,5 en graisse 300, items espacés de 30. */
.dedienne-art-side .elementor-widget-posts .elementor-posts { --grid-row-gap: 30px; }

.dedienne-art-side .elementor-widget-posts .elementor-post__title {
    margin: 0;
    font-size: 15px;
    font-weight: 300;
    line-height: 17.505px;
}

.dedienne-art-side .elementor-widget-posts .elementor-post__title a { color: #000; }

/* --- Corps de l'article : rythme des widgets ------------------------------
   La production laisse 20 px sous chaque widget du contenu, via la règle
   `.elementor-widget:not(:last-child)` d'Elementor. En local cette règle est
   battue par `.e-con .elementor-widget.elementor-widget { margin-block-end: 0 }`,
   qu'Elementor applique dès qu'un conteneur est ancêtre — l'espacement y est
   censé venir du `gap` du conteneur. Le gabarit local est en conteneurs, la
   production en sections : les sept blocs de l'article se retrouvaient jointifs
   et le corps perdait 125 px sur sa hauteur.

   La règle est bornée au contenu de l'article : ailleurs, l'espacement par le
   `gap` du conteneur est le bon modèle et ne doit pas être rétabli à l'aveugle.
   -------------------------------------------------------------------------- */

.dedienne-art-main .elementor-widget-theme-post-content .elementor-widget:not(:last-child) {
    margin-block-end: 20px;
}

/* Étiquettes de l'article : la production borne la zone à la moitié de la
   colonne, d'où le passage sur deux lignes.
   Le bornage passe par `width` et non par `max-width` : Elementor gonfle son
   sélecteur à quatre unités de classe (`.elementor.elementor .e-con >
   .elementor-widget { max-width: 100% }`), hors d'atteinte sans surenchère,
   alors qu'aucune règle ne contraint la largeur d'un widget en conteneur. */
.dedienne-art-main > .dedienne-art-tags.elementor-widget { width: 50%; }

/* --- Navigation d'article -------------------------------------------------
   La production emploie ici le MÊME composant que la navigation de portfolio :
   une hampe de 34 px terminée par une pointe (viewBox 0 0 39.7 9.1), et un
   libellé en 11 px / 500, interlettrage 2,2 px, #101010, capitales.

   Le widget post-navigation d'Elementor ne sait produire que des chevrons Font
   Awesome. On masque donc le glyphe et on redessine la flèche en arrière-plan,
   avec exactement le tracé de includes/widgets/class-portfolio-nav.php.

   À noter : en production, cette navigation s'affiche empilée à gauche, parce
   que le <i> non refermé de la traduction espagnole (cf.
   tools/templates/align-traduction-es-italique.php) englobe le bloc et casse sa
   mise en page. La disposition prev à gauche / next à droite est celle que la
   production rend quand la traduction est saine.
   ------------------------------------------------------------------------- */

.dedienne-art-main .elementor-widget-post-navigation .post-navigation__arrow-wrapper :is(i, svg) {
    display: none;
}

.dedienne-art-main .elementor-widget-post-navigation .post-navigation__arrow-wrapper {
    display: inline-block;
    position: relative;
    width: 40px;
    height: 10px;
    vertical-align: middle;
}

/* La hampe et la pointe sont deux pseudo-éléments plutôt qu'une seule image de
   fond : c'est le seul moyen d'étirer la première sans déformer la seconde, et
   c'est ainsi que la production s'y prend. Un fond aurait aussi été rogné par la
   boîte de 40 px quand la pointe se déplace ; en position absolue, non.
   Même vocabulaire que le bouton de `searchform.php`, plus bas dans ce fichier. */
.dedienne-art-main .elementor-widget-post-navigation .post-navigation__arrow-wrapper::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 0;
    width: 34px;
    height: 1px;
    background-color: #101010;
    transform: translateY(-50%);
    transform-origin: left center;
    transition: all .2s ease-in-out;
}

.dedienne-art-main .elementor-widget-post-navigation .post-navigation__arrow-wrapper::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 35.2px;
    width: 3.8px;
    height: 6.1px;
    background-repeat: no-repeat;
    background-size: 3.8px 6.1px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='35.1 1.6 3.8 6.1'%3E%3Cpolygon fill='%23101010' points='35.1,5.1 35.1,7.7 38.9,4.6 35.1,1.6 35.1,4.2'/%3E%3C/svg%3E");
    transform: translateY(-50%);
    transition: all .2s ease-in-out;
}

/* Le geste de la production : la hampe s'étire de 30 %, la pointe suit de 10 px. */
.dedienne-art-main .elementor-widget-post-navigation a:hover .post-navigation__arrow-wrapper::after {
    transform: translateY(-50%) scaleX(1.3);
}

.dedienne-art-main .elementor-widget-post-navigation a:hover .post-navigation__arrow-wrapper::before {
    left: 45.2px;
}

.dedienne-art-main .elementor-widget-post-navigation .post-navigation__arrow-prev {
    transform: scaleX(-1);
    margin-right: 16px;
}

.dedienne-art-main .elementor-widget-post-navigation .post-navigation__arrow-next {
    margin-left: 14px;
}

/* ---------------------------------------------------------------------------
   Cormorant — la police que la production emploie pour quelques accents

   La production rend en Cormorant le champ de recherche des colonnes latérales,
   les termes de catégorie et les puces du filtre de /the-dedienne-world/. Les
   fichiers sont bien présents sur le disque (générés par OMGF), mais plus
   servis : la feuille qui les déclarait était enqueue par le thème borgholm.
   Les quatre fontes utiles (500 et 700, latin et latin étendu) sont donc
   recopiées dans le thème plutôt que référencées dans le dossier de cache
   d'OMGF, dont le nom est un condensat susceptible d'être regénéré.
   --------------------------------------------------------------------------- */

@font-face {
    font-family: 'Cormorant';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('assets/fonts/cormorant-normal-latin-500.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: 'Cormorant';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('assets/fonts/cormorant-normal-latin-ext-500.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-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Cormorant';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('assets/fonts/cormorant-normal-latin-700.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: 'Cormorant';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('assets/fonts/cormorant-normal-latin-ext-700.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-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Cormorant';
    font-style: italic;
    font-weight: 500;
    font-display: swap;
    src: url('assets/fonts/cormorant-italic-latin-500.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: 'Cormorant';
    font-style: italic;
    font-weight: 500;
    font-display: swap;
    src: url('assets/fonts/cormorant-italic-latin-ext-500.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-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------------------------------------------------------------------------
   Gabarit article — détails relevés sur la production
   --------------------------------------------------------------------------- */

/* (La variable qui portait la flèche entière en image de fond a été retirée :
   les flèches sont désormais dessinées en deux morceaux, pour pouvoir étirer la
   hampe seule au survol.) */

/* --- Date / catégorie ----------------------------------------------------
   Rien ici : le widget porte la classe `dedienne-bc-meta`, dont le bloc est plus
   haut dans ce fichier (ligne ~1095). Il fait déjà tout ce que la production
   demande — icônes masquées, 11 px / 500 / 26, interlettrage .15em, barre
   oblique, survol orange — y compris DÉSAMORCER la bordure verticale que
   `content: '/'` réveille sur le pseudo-élément de séparateur d'Elementor.
   Une règle neuve écrite ici reproduirait ce piège. */

/* (L'exception qui rendait ici 4 px à la marge de la barre oblique a été retirée :
   la règle mutualisée répartit désormais l'espace de part et d'autre, pour le
   gabarit article comme pour les cartes.) */

/* --- Champ de recherche --------------------------------------------------
   Le texte de substitution est noir et opaque en production, dans la même
   Cormorant que le champ ; sans `opacity: 1`, les navigateurs l'atténuent. */

.dedienne-art-side .elementor-search-form__input::placeholder {
    color: #000;
    opacity: 1;
    font-family: 'Cormorant', Georgia, serif;
    font-size: 17px;
    font-weight: 500;
    /* La production met tout le champ en italique, texte saisi compris ; le
       réglage du widget couvre le champ, pas son texte de substitution. */
    font-style: italic;
}

/* Le widget ne propose que ses propres icônes ; on masque celle-ci et on
   redessine la flèche de la production, la même que prev / next. */
.dedienne-art-side .elementor-search-form__submit .e-font-icon-svg-container,
.dedienne-art-side .elementor-search-form__submit svg {
    display: none;
}

.dedienne-art-side .elementor-search-form__submit {
    position: relative;
}

.dedienne-art-side .elementor-search-form__submit::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 34px;
    height: 1px;
    margin-left: -20px;
    background-color: #101010;
    transform: translateY(-50%);
    transform-origin: left center;
    transition: all .2s ease-in-out;
}

.dedienne-art-side .elementor-search-form__submit::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 3.8px;
    height: 6.1px;
    margin-left: 14px;
    background-repeat: no-repeat;
    background-size: 3.8px 6.1px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='35.1 1.6 3.8 6.1'%3E%3Cpolygon fill='%23101010' points='35.1,5.1 35.1,7.7 38.9,4.6 35.1,1.6 35.1,4.2'/%3E%3C/svg%3E");
    transform: translateY(-50%);
    transition: all .2s ease-in-out;
}

.dedienne-art-side .elementor-search-form__submit:hover::after {
    transform: translateY(-50%) scaleX(1.3);
}

.dedienne-art-side .elementor-search-form__submit:hover::before {
    margin-left: 24px;
}

/* --- Terme de catégorie --------------------------------------------------
   Production : Cormorant 18 px / 700 sur #464646, passage à l'orange au survol,
   accompagné d'un trait de 1 px qui se dessine de gauche à droite. */

.dedienne-art-side .elementor-widget-wp-widget-categories li a {
    position: relative;
    display: inline-block;
    color: #464646;
    font-family: 'Cormorant', Georgia, serif;
    font-size: 18px;
    font-weight: 700;
    line-height: 26px;
    transition: color .2s ease-out;
}

.dedienne-art-side .elementor-widget-wp-widget-categories li a::before {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    width: 0;
    height: 1px;
    background: #FE5000;
    transition: width .2s ease-in-out;
}

.dedienne-art-side .elementor-widget-wp-widget-categories li a:hover {
    color: #FE5000;
}

.dedienne-art-side .elementor-widget-wp-widget-categories li a:hover::before {
    width: 100%;
}

/* --- Articles liés ------------------------------------------------------- */

.dedienne-art-side .elementor-widget-posts .elementor-post__title a {
    transition: color .2s ease-out;
}

.dedienne-art-side .elementor-widget-posts .elementor-post__title a:hover {
    color: #FE5000;
}

/* --- Étiquettes ----------------------------------------------------------
   Production : soulignées d'un trait de 1 px posé à 7 px du bas de la ligne,
   noir au repos, orange au survol en même temps que le texte. Le trait est un
   pseudo-élément et non `text-decoration` : c'est ainsi que la production le
   dessine, et cela garde le contrôle exact de sa position dans une ligne de
   32 px. */

/* Quatre classes sont nécessaires : Elementor pose `display: inline` et la
   couleur du widget avec trois classes plus un élément — plus lourd que deux
   classes, quelle que soit l'ordre des feuilles. */
.dedienne-art-main .dedienne-art-tags .elementor-icon-list-text .elementor-post-info__terms-list-item {
    position: relative;
    display: inline-block;
    color: #000;
    transition: color .2s ease-out;
}

.dedienne-art-main .dedienne-art-tags .elementor-icon-list-text .elementor-post-info__terms-list-item::before {
    content: "";
    position: absolute;
    bottom: 7px;
    left: 0;
    width: 100%;
    height: 1px;
    background: #000;
    transition: background-color .2s ease-out;
}

/* La production place sa virgule DANS le lien, en pseudo-élément : son trait la
   franchit et la ligne paraît soulignée d'un seul tenant. Elementor écrit « , »
   en nœud texte ENTRE les liens (post-info.php:1054), hors de portée du CSS. Le
   trait est donc prolongé de la largeur d'une virgule et d'une espace — sauf sur
   le dernier terme, qui n'en est pas suivi. */
.dedienne-art-main .dedienne-art-tags .elementor-icon-list-text .elementor-post-info__terms-list-item:not(:last-child)::before {
    width: calc( 100% + 8px );
}

.dedienne-art-main .dedienne-art-tags .elementor-icon-list-text .elementor-post-info__terms-list-item:hover {
    color: #FE5000;
}

.dedienne-art-main .dedienne-art-tags .elementor-icon-list-text .elementor-post-info__terms-list-item:hover::before {
    background-color: #FE5000;
}

/* ---------------------------------------------------------------------------
   Gabarit des archives d'articles (131801)

   L'archive réemploie la carte de /blog/ — le gabarit de boucle 131754 — mais la
   production ne les habille pas tout à fait pareil : elle titre ses cartes
   d'archive en 40 px Work Sans, et celles de /blog/ en 45 px Montserrat. Le
   même article passe donc de deux à trois lignes si on laisse le 45.

   Quatre unités de classe : le CSS généré du gabarit de boucle pose la
   typographie avec trois classes, et la feuille du thème étant chargée avant
   celle d'Elementor, une chaîne de trois lui céderait la place.
   --------------------------------------------------------------------------- */

.dedienne-archive-section .dedienne-archive-grid .dedienne-bc-title .elementor-heading-title,
.dedienne-loc-section .dedienne-loc-grid .dedienne-bc-title .elementor-heading-title {
    font-family: "Work Sans", sans-serif;
    font-size: 40px;
    /* L'interligne de la production reste à 45 alors que le corps descend à 40 :
       deux lignes font donc 90 px, et non 80. */
    line-height: 45px;
}

/* Extrait : la production coupe à ~180 caractères, ce qui tient exactement sur
   deux lignes de 24,262 px — elle tronque au caractère, sans points de suspension.
   Elementor tronque au MOT, et son réglage vit dans le gabarit de boucle, partagé
   avec /blog/ où la production montre des extraits plus longs. On borne donc
   l'affichage côté archive seulement, plutôt que de dupliquer la carte et d'avoir
   deux gabarits à maintenir pour deux lignes de texte.

   `max-height` plutôt que `-webkit-line-clamp` : ce dernier impose
   `display: -webkit-box` et ajoute des points de suspension que la production n'a
   pas. */
.dedienne-archive-section .dedienne-bc-excerpt .elementor-widget-container,
.dedienne-loc-section .dedienne-bc-excerpt .elementor-widget-container {
    max-height: calc( 24.262px * 2 );
    overflow: hidden;
}

/* La pagination de la production est celle de WordPress : elle n'affiche « Prev »
   qu'à partir de la deuxième page. Elementor rend toujours les deux extrémités,
   sous forme de <span> quand elles ne mènent nulle part — ce sont ces spans
   inertes qu'on retire, en gardant les <a>. */
.dedienne-archive-section .elementor-pagination > span.page-numbers.prev,
.dedienne-archive-section .elementor-pagination > span.page-numbers.next {
    display: none;
}

/* Écart assumé : la production ne met pas de marge à gauche de son premier
   numéro, ce qui décale la série centrée de 8 px par rapport au local. Elementor
   pose cette marge avec `body:not(.rtl)` + trois classes + `:not(:first-child)`,
   soit six unités ; et comme le « Prev » masqué reste le premier enfant, la règle
   ne peut pas être annulée par un `:first-child`. Surenchérir à sept unités pour
   8 px sur une pagination centrée n'en vaut pas le poids dans cette feuille. */

/* --- Survol du titre de carte -------------------------------------------
   La production passe le titre à l'orange au survol, en .2s. Le lien est DANS
   le titre (`<h1 class="elementor-heading-title"><a>…</a></h1>`), et c'est lui
   qui porte la couleur : quatre unités de classe pour passer devant la couleur
   que le CSS généré du gabarit de boucle pose sur le titre. */

.dedienne-bc .dedienne-bc-title .elementor-heading-title a {
    transition: color .2s ease-out;
}

.dedienne-bc .dedienne-bc-title .elementor-heading-title a:hover {
    color: #FE5000;
}

/* ---------------------------------------------------------------------------
   Archive de la taxonomie « locations » (gabarit 131850)

   Ces URLs — /locations/india/, /locations/europe/… — listent les offres
   d'emploi d'une région. La production y emploie la MÊME carte que les archives
   d'articles, en pleine largeur et sans colonne latérale, avec deux espacements
   différents :

     production          entre deux cartes 60 px, et la DERNIÈRE garde sa marge
     archives d'articles entre deux cartes 97 px, et la dernière perd la sienne

   Les 97 px de la liste d'articles se composent de 67 px de marge dans la carte
   et de 30 px d'écart de grille. Ici l'écart de grille est à zéro et la marge
   de la carte vaut 60, ce qui donne le compte sans dépendre de la grille.

   Quatre unités de classe : la marge de 67 vient du CSS généré du gabarit de
   boucle, qui en compte trois, et la feuille du thème est chargée avant lui.
   --------------------------------------------------------------------------- */

.dedienne-loc-section .dedienne-loc-grid .dedienne-bc-more > .elementor-widget-container {
    margin-bottom: 60px;
}

/* La liste d'articles annule la marge de sa dernière carte ; la production ne le
   fait pas ici — la pagination vient 50 px après ces 60 px. La règle qui annule
   est portée par `.dedienne-blog-grid`, que cette grille porte aussi pour
   hériter du dessin des flèches : il faut donc la défaire explicitement. */
.dedienne-loc-grid .elementor-loop-container > :last-child .dedienne-bc-more > .elementor-widget-container {
    margin-bottom: 60px;
}

/* ---------------------------------------------------------------------------
   Archive de « portfolio-category » (gabarit 131869)

   La production réemploie la carte des listes portfolio, à un réglage près : le
   bloc de contenu y reçoit 33 px de remplissage bas au lieu des 10 px qu'il a sur
   les pages (/engine-stands/ et les autres, où le local est déjà au pixel). D'où
   une carte de 461 px ici contre 438 sans cette règle — les 23 px d'écart mesurés.

   Le réglage vit dans le gabarit de boucle, partagé : l'ajustement est donc borné
   à cette archive. Deux unités de classe suffisent — Elementor pose le
   remplissage des conteneurs par une variable consommée par une règle d'une seule
   classe.
   --------------------------------------------------------------------------- */

.dedienne-pca-grid .dedienne-pc-content {
    padding-bottom: 33px;
}

/* En production, les cartes d'une même rangée gardent chacune leur hauteur — 580, 488 et 514
   sur la première rangée du terme `blog` — et la rangée suivante commence 20 px sous la plus
   haute. Elementor étire ses items sur toute la hauteur de la rangée : on le lui retire. */
/* Trois unités de sélecteur : Elementor pose `align-items: stretch` avec
   `.elementor-loop-container:not(.elementor-posts-masonry)`, soit deux unités, et sa feuille
   est chargée après celle du thème. Le mode maçonnerie du widget donnerait bien
   `flex-start`, mais il empile par colonnes ; la production, elle, reste en rangées. */
.dedienne-pca-grid .elementor-loop-container:not(.elementor-posts-masonry) {
    align-items: start;
}

/* Cartes de la grille portfolio : largeur minimale libérée.

   Une colonne `1fr` ne descend jamais sous le contenu le plus large de sa cellule. En espagnol,
   un mot long (« amortiguadores ») gonfle les quatre premières colonnes à 301 px et écrase la
   cinquième à 98 px, là où l'anglais en tient cinq de 212 px. `min-width: 0` rend aux cinq
   colonnes la même largeur ; le mot trop long passe à la ligne au lieu d'élargir la colonne. */

.dedienne-portfolio-grid .elementor-loop-container > .e-loop-item {
    min-width: 0;
    overflow-wrap: anywhere;
}

/* Nombre de colonnes de l'archive portfolio, aux bornes de la production.

   Relevé : 3 colonnes à 769 px et au-delà, 2 de 681 à 768, 1 à 680 et moins. Aucune de ces
   bornes ne correspond aux points d'arrêt d'Elementor — tablette ≤ 1024, mobile ≤ 767 — d'où
   un pilotage en CSS, le widget restant à 3 dans ses trois plages.

   La cible est `grid-template-columns`, PAS la variable `--grid-columns` : Elementor pose la
   variable dans le CSS du gabarit, mais la grille elle-même est pilotée par des classes —
   `.elementor-grid-3 .elementor-grid`, et ses variantes tablette et mobile. Écrire la variable
   ne changeait donc rien, alors qu'elle prenait bien la valeur voulue : mesuré
   `--grid-columns: 2` et `grid-template-columns: repeat(3, 1fr)` en même temps.

   Trois unités de classe, la règle d'Elementor en comptant deux et sa feuille étant chargée
   après celle du thème. */

@media only screen and (max-width: 768px) {

    .dedienne-pca-grid .elementor-loop-container.elementor-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media only screen and (max-width: 680px) {

    .dedienne-pca-grid .elementor-loop-container.elementor-grid {
        grid-template-columns: repeat(1, 1fr);
    }
}

/* Séparateur des termes sur l'archive portfolio.

   La production sépare ses catégories par un « / » posé en `::after` sur chaque lien sauf le
   dernier. Le thème, lui, masque la virgule d'Elementor en mettant la liste à `font-size: 0`
   — et n'ajoute pas de séparateur, faute de place : la note plus haut explique que deux
   caractères en trop faisaient passer sur deux lignes les cartes de 212 px de
   /the-dedienne-world/, soit 26 px de plus par carte.

   Ici les cartes font 353 px et ce risque n'existe pas : la règle est donc bornée à cette
   archive plutôt que posée sur la carte partagée. La taille est redonnée explicitement, la
   liste étant à zéro. */

.dedienne-pca-grid .dedienne-pc-terms .elementor-post-info__terms-list-item:not(:last-child)::after {
    content: "/";
    font-size: 11px;
    margin-left: 4px;
}

/* Le lien de l'image des cartes portfolio, et son talon de descendante.

   La production enveloppe l'image de chaque carte d'un `<a>` vers l'item ; le lien a été
   ajouté aux trois gabarits par tools/templates/align-cartes-lien-image.php. Resté en
   `display: inline`, cet ancre porte sous l'image un talon de descendante qui allonge la
   carte de 8 px — le même piège que sur la carte de blog, où borgholm le désamorce
   explicitement (`.qodef-e-media-image a, … img { display: block }`).

   La règle est posée AVANT d'avoir constaté l'écart, précisément parce qu'il est déjà
   documenté plus haut dans ce fichier pour `.dedienne-bc-image`. */

.dedienne-pc-image .elementor-widget-container > a {
    display: block;
}

/* ==========================================================================
   Formulaire de demande de devis — références Toolfinder (widget 1d02bb8)

   Signalé par Jérém : « les champs du formulaire ne reprennent pas le même
   design ». Deux causes distinctes, dont une seule est du CSS.

   La PREMIÈRE était du balisage : `wpcf7_autop` injectait un `<p>` devant
   `#cf7md-form` et 32 `<br />` dans le formulaire, ce qui sortait la grille
   Material de son imbrication. Corrigée à la source dans functions.php, qui
   porte le détail — pas ici.

   La SECONDE est celle-ci. La production sert sept surcharges écrites à la
   main par-dessus la feuille du greffon Material. Le chantier les a bien
   reprises, mais dans le bloc `.dedienne-form` plus haut dans ce fichier —
   une classe portée par les trois formulaires Contact (11768), Careers
   (12997) et offre d'emploi (gabarit 127716), et par AUCUN autre. Le
   formulaire des références n'en a jamais fait partie : ses onze
   `.cf7md-item` sortaient donc sans marge, sa grille en `display: grid` au
   lieu de `block`, et son bouton d'envoi en pleine largeur — 613 x 60 px
   mesurés contre 137 x 30 en production.

   ---- Pourquoi un bloc à part, et pas la classe `.dedienne-form` ----

   Parce que les deux jeux de règles DIVERGENT sur la grille. `.dedienne-form`
   pose `display: inline-block !important`, valeur que la production réserve
   aux pages 11768 et 12997 ; sur une référence Toolfinder elle sert
   `display: block !important`. Poser la classe sur ce widget donnerait donc
   un troisième rendu, ni celui d'ici ni celui de là-bas.

   ---- Pourquoi la portée descend au widget ----

   Les surcharges de la production sont NUES : `#cf7md-form …`, sans borne de
   page. Reprises telles quelles, elles gagneraient sur les règles
   `.dedienne-form` — un identifiant l'emporte sur deux classes — et les trois
   autres formulaires du site basculeraient de `inline-block` à `block`. La
   portée est donc bornée à `.elementor-element-1d02bb8`, l'unique instance du
   widget dans le gabarit 78542, sur le modèle du bloc
   `.elementor-element-177637a` plus haut.

   Les `!important` sont ceux de la production, gardés là où elle les met et
   nulle part ailleurs.
   ========================================================================== */

/* La grille Material redevient un flux de blocs : le greffon la met en
   `display: grid` sur douze colonnes, la production la remet en `block`. */
.elementor-element-1d02bb8 #cf7md-form .mdc-layout-grid__inner {
    display: block !important;
}

/* Les onze champs retrouvent leur respiration. Le greffon déclare
   `margin-top: 0` sur `.cf7md-item` ; la production le reprend à 20 px, et
   ajoute 15 px sous les champs de texte et les listes. */
.elementor-element-1d02bb8 #cf7md-form .cf7md-item {
    margin-top: 20px;
}

.elementor-element-1d02bb8 #cf7md-form .cf7md-text,
.elementor-element-1d02bb8 #cf7md-form .cf7md-select {
    margin-bottom: 15px;
}

.elementor-element-1d02bb8 #cf7md-form .mdc-layout-grid__inner .cf7md-textarea {
    clear: both;
}

/* Le bouton d'envoi : à gauche, à sa largeur de contenu, sous les flottants. */
.elementor-element-1d02bb8 .qodef-contact-form .cf7md-submit {
    clear: both;
    float: left;
    margin-top: 10px !important;
}

.elementor-element-1d02bb8 #cf7md-form .mdc-form-field > label {
    font-size: 14px;
}

/* L'astérisque des champs requis, en orange. Trois sélecteurs parce que le
   marqueur doit suivre l'étiquette flottante dans ses trois habillages :
   champ simple, liste, et champ à contour découpé. */
.elementor-element-1d02bb8 #cf7md-form .mdc-text-field__input:required ~ .mdc-floating-label:after,
.elementor-element-1d02bb8 #cf7md-form .mdc-select--required .mdc-floating-label:after,
.elementor-element-1d02bb8 #cf7md-form .mdc-text-field__input:required ~ .mdc-notched-outline .mdc-floating-label:after {
    margin-left: 2px;
    content: "*";
    color: #f4713b;
}

/* La ligne « Your tooling request » et sa quantité, côte à côte.

   La production les met en ligne par deux règles bornées à `.page-template-default` —
   la classe de corps que les références portaient du temps où elles étaient des `page`.
   Devenues un type de contenu, leur corps porte `single-toolfinder_reference` : les deux
   règles ont cessé de s'appliquer et le bloc est repassé en `display: block`, pleine
   largeur, 110 px de haut contre 85 en production.

   La portée est ramenée au widget plutôt qu'à la nouvelle classe de corps : `.yourtool`
   n'existe que dans le gabarit du formulaire 37499, et le bloc entier est déjà borné
   ainsi. Une règle de corps de plus n'ajouterait rien qu'une seconde façon de dire où
   s'applique le même habillage. */
.elementor-element-1d02bb8 .yourtool {
    display: inline-flex;
}

.elementor-element-1d02bb8 .yourtool .quantity {
    margin-top: 10px !important;
    margin-left: 15px !important;
}

/* La flèche du bouton d'envoi reste sur la ligne du libellé.

   Le libellé du formulaire 37499 vaut `Submit &nbsp; <div>&xrarr;</div>` : du balisage
   dans la valeur du champ d'envoi. Le greffon Material remplace l'`<input>` par un
   `<button>` en JS et y verse cette valeur telle quelle — le `<div>`, élément de bloc,
   pousse donc la flèche à la ligne. Relevé : bouton de 30 px de haut en production,
   60 px ici, sur deux lignes.

   La production ne rencontre pas le défaut parce que borgholm reconstruisait lui aussi
   le bouton, et que le `<div>` ne survit pas à sa reconstruction : son contenu rendu est
   `Submit &nbsp;⟶`, sans balise. On obtient le même rendu en mettant simplement le
   `<div>` en ligne, sans toucher au gabarit du formulaire — dont la valeur sert aussi
   les autres formulaires du site.

   Ce qui n'est PAS repris : la typographie de bouton de borgholm — `font-weight: 600` et
   `letter-spacing: .2em` sur une règle nue `button[type="submit"]`, d'où les 137 px de
   large de la production contre une centaine ici. Elle a été remplacée par celle du kit
   Elementor sur tout le site ; la rétablir pour ce seul formulaire créerait un bouton
   qui ne ressemble à aucun autre. */
.elementor-element-1d02bb8 .cf7md-submit .wpcf7-submit div {
    display: inline;
}

/* L'habillage des champs : fond blanc et filet noir de 1 px.

   C'est le second volet du signalement « les inputs n'ont pas le même design ». Le greffon
   Material sert des champs GRIS à simple trait sous le champ —
   `#cf7md-form .mdc-text-field:not(.mdc-text-field--disabled){background-color:#f5f5f5}` et
   `#cf7md-form .mdc-text-field__input{border:none;border-bottom:1px solid}`. La production
   charge la même feuille, mais l'écrase par deux règles écrites à la main, relevées avec
   winning-rule.mjs :

     #cf7md-form .mdc-text-field .mdc-text-field__input { caret-color:#fe5000; border:solid #000 1px }
     #cf7md-form .mdc-text-field:not(.mdc-text-field--disabled),
     #cf7md-form .mdc-select:not(.mdc-select--disabled)     { background-color:#fff }

   Le chantier les avait reprises dans le bloc `.dedienne-form`, que ce formulaire ne porte
   pas. D'où des champs gris à filet unique ici, blancs à filet complet là-bas et en
   production.

   Aucun `!important` : la production n'en met pas, et il n'en faut pas. Une classe de plus
   que les règles du greffon suffit à passer devant — y compris sur le fond, où le `:not()`
   compte son argument dans la spécificité des deux côtés. */
.elementor-element-1d02bb8 #cf7md-form .mdc-text-field .mdc-text-field__input {
    caret-color: #fe5000;
    border: solid #000 1px;
}

.elementor-element-1d02bb8 #cf7md-form .mdc-text-field:not(.mdc-text-field--disabled),
.elementor-element-1d02bb8 #cf7md-form .mdc-select:not(.mdc-select--disabled) {
    background-color: #fff;
}

/* Le champ de message : le filet est porté par l'enveloppe, pas par le textarea.

   La production inverse le traitement sur ce seul champ, par deux règles relevées avec
   winning-rule.mjs — l'enveloppe `.mdc-text-field--textarea.cf7md-initialized` prend le
   filet de 1 px, et le textarea lui-même le perd. Sans cette inversion, le filet posé plus
   haut sur `.mdc-text-field__input` dessinait un second cadre à l'intérieur du premier.

   La règle de production énumère aussi `.wpcf7-form-control-wrap.tech-support`,
   `.sale-support`, `.location` et `.department` : ce sont les listes du formulaire de
   contact, absentes de celui-ci. Les reprendre habillerait du code mort.

   L'ordre compte : `border: none` doit venir APRÈS le filet posé plus haut, les deux
   sélecteurs pesant le même poids (un identifiant et trois classes).

   `position: relative` vient, en production, de la règle nue `input[type="text"]` de
   borgholm. Seule cette déclaration est reprise, et bornée au widget : importer tout
   l'habillage de champ de borgholm serait une décision à l'échelle du site. */
.elementor-element-1d02bb8 #cf7md-form .mdc-text-field__input {
    position: relative;
}

.elementor-element-1d02bb8 #cf7md-form .mdc-text-field--textarea.cf7md-initialized {
    border: 1px solid #000;
}

/* Seul le textarea LUI-MÊME perd sa bordure : l'enveloppe la porte.

   La règle de production en effaçait aussi la bordure sur `.mdc-text-field--invalid` et
   sur l'enveloppe du message à l'état focus. Ces deux entrées ne sont PAS reprises : elles
   effacent la bordure exactement dans les états où elle doit maintenant passer en orange
   (voir le bloc « Champ visité » plus bas). Divergence assumée de la production, née du
   comportement demandé, et non d'un oubli. */
.elementor-element-1d02bb8 #cf7md-form .wpcf7-textarea.mdc-text-field__input {
    border: none;
}

/* Les trois champs HORS enveloppe Material : « Your tooling request », « Quantity », téléphone.

   Signalé par Jérém : « quasiment non stylisés en local ». C'est exact, et la mesure le dit
   sans ambiguïté — ils sortaient aux valeurs par défaut du navigateur : bordure `inset` de
   2 px en gris #767676, corps de 13,33 px, marge intérieure de 1px 2px. La production les
   sert avec un simple filet noir de 1 px sous le champ, en 17 px / 20 px.

   Pourquoi ces trois-là et pas les autres : ils ne portent PAS la classe
   `.mdc-text-field__input`. Le greffon Material n'enveloppe que les champs qu'il génère
   lui-même ; ces trois-ci sont des champs CF7 nus, posés à la main dans le gabarit du
   formulaire. En production ils étaient habillés par la règle NUE de borgholm sur
   `input[type=text], input[type=number], input[type=tel], …`, qui a disparu avec le thème.

   Ce qui est repris, et rien de plus : les propriétés que la mesure donne divergentes.

   ---- Le piège de l'italique, et pourquoi il coûte 17 px ----

   La règle de borgholm déclare `font-family: Cormorant`, `font-weight: 500` ET
   `font-style: italic`. Le greffon Material écrase les DEUX premières
   (`#cf7md-form input { font-family:"Roboto"; font-weight:400 }` — un identifiant l'emporte
   sur un sélecteur nu), mais PAS la troisième : il ne la déclare pas. L'italique survit donc
   en production, et il est plus large que le romain — le champ « Your tooling request »
   mesure 212 px là-bas contre 195 ici, celui de la quantité 76 contre 63.

   Écarter tout le bloc typographique parce que deux de ses trois déclarations sont écrasées
   était une erreur de raisonnement : une surcharge ne porte que sur ce qu'elle déclare. Le
   diagnostic n'est venu que d'un diff EXHAUSTIF des styles calculés — `font-style` ne fait
   pas partie des propriétés que box-diff compare, l'écart y était donc invisible.

   `cursor: pointer` et `vertical-align: top` viennent du même bloc et ont survécu de la même
   façon.

   `margin: 0 0 35px` en revanche n'est PAS repris : la mesure donne les marges déjà égales
   des deux côtés, le greffon les remettant à zéro ailleurs.

   Le téléphone reçoit ses marges intérieures en haut et en bas seulement : les 52 px à
   gauche sont la place du drapeau, posée par intlTelInput, et un raccourci `padding` les
   effacerait. */
.elementor-element-1d02bb8 #cf7md-form .yourtool input,
.elementor-element-1d02bb8 #cf7md-form input.wpcf7-intl-tel {
    position: relative;
    font-size: 17px;
    line-height: 20px;
    font-style: italic;
    vertical-align: top;
    cursor: pointer;
    border: none;
    border-bottom: 1px solid #000;
    border-radius: 0;
    background-color: transparent;
    outline: 0;
    -webkit-appearance: none;
    appearance: none;
}

.elementor-element-1d02bb8 #cf7md-form .yourtool input {
    padding: 5px 0;
}

.elementor-element-1d02bb8 #cf7md-form input.wpcf7-intl-tel {
    padding-top: 5px;
    padding-bottom: 5px;
}

/* ==========================================================================
   Champ visité : la bordure passe en orange

   Demandé par Jérém. Ce n'est PAS un rattrapage de la production : elle ne
   colore la bordure d'aucun champ, elle se contente du filet animé de
   Material. Mesuré aux trois moments — repos, focus, après saisie — les deux
   côtés se comportaient à l'identique avant cette règle.

   ---- L'orange « qui n'était pas le bon » ----

   Il l'était. Le site ne sert qu'une seule teinte orange, `rgb(254, 80, 0)`
   = #FE5000, la couleur Primary du kit 6675, en 81 occurrences sur la page.
   Ce qui la salissait, c'est la SUPERPOSITION : le filet animé de Material
   est une barre de 2 px posée exactement sur la bordure noire de 1 px du
   champ, au même pixel. Les deux se mélangeaient au rendu. D'où le
   `background-color: transparent` sur le filet plus bas : la bordure se lit
   maintenant seule, uniformément, sur 1 px.

   ---- La portée retenue, et ce qu'elle coûte ----

   `:focus, :user-valid, :user-invalid` — orange dès la première interaction,
   et l'orange RESTE, que le champ soit rempli ou laissé vide. Choix acté par
   Jérém contre les deux autres lectures possibles.

   Sa conséquence, signalée avant de l'écrire : un champ requis laissé vide
   ressort orange comme un champ correctement rempli. L'orange ne distingue
   donc plus « fait » de « à faire », et il coexiste avec l'habillage d'erreur
   de Contact Form 7, qui garde sa propre signalétique au moment de l'envoi.

   ---- Pourquoi des `!important`, ici et nulle part ailleurs ----

   Parce que l'orange doit battre l'habillage d'ERREUR de Material, qui est plus
   spécifique que tout ce qu'on peut écrire raisonnablement :

     #cf7md-form .mdc-text-field--invalid:not(--disabled):not(--outlined):not(--textarea)
       .mdc-text-field__input { border-bottom-color: #b00020 }     -> (1,5,0)
     #cf7md-form .mdc-text-field--invalid:not(--disabled) .mdc-line-ripple
                              { background-color: #b00020 }        -> (1,3,0)

   Mesuré avant de les poser : le champ requis visité puis laissé vide sortait avec
   trois côtés orange et le BAS en rouge #b00020, filet compris. On pourrait égaler
   (1,5,0) en empilant des `:not()`, mais l'égalité se tranche alors à l'ordre de
   chargement — exactement la fragilité que documente winning-rule.mjs, où « les
   valeurs par défaut du greffon gagnaient » sur une égalité de spécificité. Le
   `!important` dit ce qu'on veut dire : cet état passe devant, quoi qu'il arrive.

   L'habillage d'erreur de Contact Form 7 lui-même — message sous le champ, contour
   de la réponse — n'est pas touché : seule la couleur de bordure est reprise.

   ---- Pourquoi trois règles et non une ----

   `:user-valid` et `:has()` ne sont pas connus des navigateurs anciens, et un
   sélecteur inconnu dans une liste séparée par des virgules invalide TOUTE la
   règle. En les isolant, un navigateur qui ignore `:user-valid` garde quand
   même l'orange au focus, et celui qui ignore `:has()` garde l'orange sur les
   champs simples.
   ========================================================================== */

/* 1. Au focus — le socle, compris partout. */
.elementor-element-1d02bb8 #cf7md-form .mdc-text-field .mdc-text-field__input:focus,
.elementor-element-1d02bb8 #cf7md-form .yourtool input:focus,
.elementor-element-1d02bb8 #cf7md-form input.wpcf7-intl-tel:focus {
    border-color: #FE5000 !important;
}

/* 2. Après interaction, l'orange reste.

   Le champ « Your tooling request » est en lecture seule : il est écarté de la
   validation de contrainte par la spécification, donc `:user-valid` ne l'atteint
   jamais. Il passe à l'orange au focus seulement, par la règle ci-dessus. */
.elementor-element-1d02bb8 #cf7md-form .mdc-text-field .mdc-text-field__input:user-valid,
.elementor-element-1d02bb8 #cf7md-form .mdc-text-field .mdc-text-field__input:user-invalid,
.elementor-element-1d02bb8 #cf7md-form .yourtool input:user-valid,
.elementor-element-1d02bb8 #cf7md-form .yourtool input:user-invalid,
.elementor-element-1d02bb8 #cf7md-form input.wpcf7-intl-tel:user-valid,
.elementor-element-1d02bb8 #cf7md-form input.wpcf7-intl-tel:user-invalid {
    border-color: #FE5000 !important;
}

/* 3. Le message et la liste : leur bordure est portée par l'ENVELOPPE, pas par
   le champ — d'où `:has()`, seul moyen de remonter du champ à son enveloppe. */
.elementor-element-1d02bb8 #cf7md-form .mdc-text-field--textarea.cf7md-initialized:has(.mdc-text-field__input:focus),
.elementor-element-1d02bb8 #cf7md-form .mdc-text-field--textarea.cf7md-initialized:has(.mdc-text-field__input:user-valid),
.elementor-element-1d02bb8 #cf7md-form .mdc-text-field--textarea.cf7md-initialized:has(.mdc-text-field__input:user-invalid) {
    border-color: #FE5000 !important;
}

/* Le filet animé de 2 px s'effaçait sous la bordure et brouillait sa couleur.
   Au repos il est déjà invisible — Material le garde à `scaleX(0)` — le rendre
   transparent ne retire donc qu'un artefact, jamais un état. */
.elementor-element-1d02bb8 #cf7md-form .mdc-line-ripple {
    background-color: transparent !important;
}

/* 4. Une fois le champ quitté, l'orange reste — même sans rien y avoir saisi.

   `:user-valid` et `:user-invalid` ne suffisent PAS à la portée retenue : la
   spécification ne les fait mordre qu'après une MODIFICATION du champ ou une
   tentative d'envoi. Mesuré : « Quantity », visité puis quitté sans saisie, ne
   recevait ni l'un ni l'autre et restait noir.

   La classe est posée en JS sur `focusout` par assets/js/champs-visites.js, mis
   en file par inc/champs-visites.php sur les seules références Toolfinder. Le
   CSS n'a pas de mémoire du focus : c'est le seul moyen d'exprimer « a été
   visité ». Les règles 1 à 3 restent utiles — CF7 remanie son balisage à la
   validation, ce qui efface cette classe, là où `:user-invalid` survit. */
.elementor-element-1d02bb8 #cf7md-form .mdc-text-field .mdc-text-field__input.dedienne-champ-visite,
.elementor-element-1d02bb8 #cf7md-form .yourtool input.dedienne-champ-visite,
.elementor-element-1d02bb8 #cf7md-form input.wpcf7-intl-tel.dedienne-champ-visite {
    border-color: #FE5000 !important;
}

.elementor-element-1d02bb8 #cf7md-form .mdc-text-field--textarea.cf7md-initialized:has(.dedienne-champ-visite) {
    border-color: #FE5000 !important;
}

/* ==========================================================================
   Le débordement horizontal de la page

   Signalé par Jérém : « on voit une bordure blanche qui grandit petit à petit
   à mesure que la taille de l'écran réduit ». C'est un débordement : le
   document devient plus large que la fenêtre, la page défile latéralement et
   le fond se voit sur la droite. Proportionnellement il grandit bien quand
   l'écran rétrécit — 16 % de la fenêtre à 1440 px, 45 % à 390 px.

   Relevé de la zone défilable en trop, production contre local, avant
   correction :

     largeur   1440  1200  1024   900   768   600   480   390
     production   0     0     0     0     0     0     0     0
     local      237   282   238   207   174   282   222   177

   Et ce n'est PAS propre au gabarit Toolfinder : `/contact/` débordait de
   304 px, `/` et `/toolfinder/` de rien. Le point commun des deux pages
   touchées est le formulaire — donc le badge reCAPTCHA.

   ---- Les deux règles perdues à la bascule de thème ----

   La production porte les deux, et le thème enfant n'en avait reprise aucune :

     .grecaptcha-badge { display: none !important }
     body              { overflow-x: hidden }        (dans la règle de corps de borgholm)

   Le badge est en `position: fixed` avec `right: -186px` : posé hors champ à
   droite, il ajoute quand même sa largeur à la zone défilable du document.
   C'est la cause principale, 186 px des ~174 mesurés.

   Le reste vient du conteneur du menu déroulant mobile
   (`nav.elementor-nav-menu--dropdown`), en `position: absolute`, qui dépasse
   de 28 px. Celui-là n'est PAS corrigé à la source mais absorbé par le
   garde-fou, faute de référence : l'entête de la production n'était pas fait
   avec Elementor, ce conteneur n'y a aucun équivalent à comparer.

   ---- Ce que `overflow-x: hidden` coûte ----

   Il masque au lieu de corriger, et il peut neutraliser un `position: sticky`
   sur un descendant. On le reprend quand même parce que c'est l'état de la
   production : le site a été construit avec, et s'en passer exigerait de
   traquer chaque débordement de chaque gabarit.

   ---- La contrepartie du badge masqué ----

   Masquer le badge oblige, dans les conditions d'utilisation de Google, à
   afficher la mention d'attribution reCAPTCHA à sa place. L'obligation vaut
   déjà pour la production, qui le masque de la même façon — ce n'est pas une
   régression introduite ici, mais elle est à vérifier sur les pages à
   formulaire.
   ========================================================================== */

body {
    overflow-x: hidden;
}

.grecaptcha-badge {
    display: none !important;
}

/* L'enveloppe de contenu retrouve le rôle de l'enveloppe de page de borgholm.

   `body { overflow-x: hidden }` ne suffit PAS, et c'est mesuré : le débordement restait à
   174 px et la page défilait toujours de 174 px à l'horizontale. La raison est une règle de
   propagation du CSS — quand `html` est en `overflow: visible`, la valeur du CORPS est
   reportée sur la fenêtre, et le corps lui-même repasse en `visible`. Il ne coupe donc rien.

   La production coupait ailleurs. Sa chaîne d'ancêtres, relevée sur la même page :

     div.elementor | div.qodef-content-grid | div (sans classe) | div (sans classe) ← coupe ici
                                                                                     overflow-x: hidden
     | body | html

   Trois enveloppes de page que borgholm posait et que hello-elementor n'a pas. La troisième
   contenait le débordement à hauteur du CONTENU, pas de la fenêtre. On rend ce rôle à
   l'enveloppe de document d'Elementor, qui occupe exactement la même place.

   ---- Pourquoi les quatre exclusions ----

   `.elementor` habille AUSSI les gabarits d'entête, de pied et de fenêtre surgissante. Les
   couper serait un défaut : le menu déroulant mobile de l'entête est en `position: absolute`
   et doit pouvoir sortir de son conteneur pour s'afficher. Seul le contenu est coupé —
   `single-page` sur les références, `wp-page` sur les pages.

   La quatrième, `loop-item`, est d'une autre nature : ce n'est pas un gabarit de site, c'est
   la CARTE. Elementor enveloppe chaque élément d'une grille de boucle dans sa propre boîte
   `.elementor`, et la page /engine-stands/ en porte 34, l'accueil 12, /blog/ 5, les archives
   d'année 1 à 3. Le `:not()` d'origine ne les nommait pas : elles recevaient donc le garde-fou
   chacune pour son compte, alors qu'il n'a jamais visé qu'un objet, le document de contenu.

   Signalé par Jérém sur /engine-stands/ en préproduction : une barre de défilement à côté de
   chaque bloc produit. La préproduction servait encore `overflow-x: hidden`, donc un
   `overflow-y: auto` calculé (voir la section suivante) : 34 cartes, 34 conteneurs de
   défilement. Et il y avait bien de quoi déborder — au repos, `.dedienne-pc-terms` et
   `.dedienne-pc-title` portent `rotateZ(5deg) translateY(8px)` avec `transform-origin: left`.
   La rotation fait descendre le coin droit du titre de `largeur × sin(5°)`, soit ~26 px sur
   une carte de 300 px, quand le conteneur de contenu n'a que 10 px de `padding-bottom`.
   `visibility: hidden` ne retire rien du calcul de débordement : la barre était là en
   permanence, sans survol. Cohérent avec ce qui était observé : sous 1025 px la variante
   `.dedienne-portfolio-grid--statique` remet `transform: none`, et les barres disparaissaient.

   Le passage à `clip` supprimait déjà le symptôme, puisqu'il ne crée pas de conteneur de
   défilement. L'exclusion traite la cause : une carte n'a aucune raison de rogner quoi que ce
   soit, et son survol la fait justement déborder par dessein.

   ---- Pourquoi nommer `loop-item`, et non un critère générique ----

   Tentant : toutes les enveloppes IMBRIQUÉES — entête, pied, fenêtre surgissante, carte —
   portent `data-elementor-post-type="elementor_library"`, là où le document de contenu porte
   son propre type (`page`, `post`, `portfolio-item`). Un seul `:not()` aurait remplacé les
   quatre, et couvert d'avance ce qui viendrait ensuite.

   Réfuté par le rendu servi. Sur les archives d'année (/2015/, /2016/, /2017/), le document de
   contenu EST un gabarit : `data-elementor-type="archive"`, identifiant 131801, et donc
   `data-elementor-post-type="elementor_library"` lui aussi. Le critère générique aurait
   désarmé le garde-fou sur toutes les archives. La liste nommée reste la bonne.

   ---- Ce qui reste hors de la liste, sciemment ----

   /contact/ insère cinq gabarits imbriqués (18257 en `section`, 18291, 18297, 18302 et 18310
   en `page`) qui reçoivent eux aussi le rognage. Aucun défaut constaté : leur contenu ne sort
   pas latéralement, et `clip` ne leur coûte rien à la verticale. Laissés en l'état plutôt que
   d'allonger la liste sans motif observé. Si un jour un de ces blocs a besoin de déborder,
   c'est ici qu'il faudra l'ajouter.

   ---- `clip` / `visible` et non `hidden`, et pourquoi ----

   Signalé par Jérém sur /p-i/the-tooling-territories-paris-air-show/ : le haut du bloc de
   titre était coupé, accroche entière et 23 px du h1.

   `overflow-x: hidden` avec un `overflow-y` non déclaré ne laisse pas ce dernier à
   `visible` : la spec force la valeur calculée à `auto` dès que l'autre axe n'est ni
   `visible` ni `clip`. La boîte devenait donc un conteneur de DÉFILEMENT, et rognait aussi à
   la verticale — sans que le contenu passé au-dessus du bord haut soit atteignable.

   Or l'accroche du titre de section remonte de 42 px sur les portfolio-items
   (`.single-portfolio-item .qodef-m-tagline`, dans dedienne-elements/assets/css/
   section-title.css, valeur de la production). Le bloc de titre étant le PREMIER élément du
   document de contenu, ces 42 px sortaient par le haut de cette enveloppe — et disparaissaient.

   Mesuré à 1440, avant correction :

                       accroche   h1     bord haut de l'enveloppe
     production          290      309       0   (elle coupe tout en haut du document)
     local               290      309     332   (elle coupe à hauteur du contenu)

   La géométrie était juste des deux côtés ; seule la boîte qui rogne différait.

   `clip` sur un axe et `visible` sur l'autre est le couple que la spec PRÉSERVE : il rogne à
   l'horizontale sans créer de conteneur de défilement, donc sans rien couper à la verticale.
   Le garde-fou garde son office, vérifié sur /p-i/…, /contact/, /, /toolfinder/ et /blog/ à
   390, 800, 1024 et 1440 px : `scrollWidth` reste égal à la largeur de fenêtre partout.

   `overflow-y: visible` est déclaré explicitement, et pas seulement laissé au défaut : sans
   lui, une future déclaration d'axe vertical sur ces enveloppes ramènerait le défaut sans
   qu'on voie le lien. */
.elementor:not([data-elementor-type="header"]):not([data-elementor-type="footer"]):not([data-elementor-type="popup"]):not([data-elementor-type="loop-item"]) {
    overflow-x: clip;
    overflow-y: visible;
}

/* ==========================================================================
   Titre d'article de portfolio — la typographie du mobile, sur un seul widget

   Les articles du CPT posaient le titre DEUX fois dans la même colonne : un widget masqué
   sous 768 px dont le titre est un `h1`, et un jumeau masqué au-dessus dont le titre est un
   `h3`. Hors visibilité, titre, accroche et `title_tag`, les deux jumeaux avaient des réglages
   strictement identiques sur les huit contenus concernés : le second n'existait que pour
   changer la BALISE du titre sous 768 px, et par elle sa typographie.

   Deux défauts en sortaient. Sur /p-i/the-tooling-territories-paris-air-show/, le jumeau
   mobile avait perdu son titre : sous 768 px la page n'en affichait aucun — le défaut signalé
   par Jérém. Et sur les huit, le titre visible sous 768 px était un `h3`, le `h1` restant dans
   le HTML mais en `display: none` — compté par un moteur de recherche, absent de l'arbre
   d'accessibilité.

   Le jumeau est supprimé par tools/templates/titre-mobile-unique.php. Il ne reste qu'un
   widget, visible partout, dont le titre est un `h1`. Cette règle lui rend sous 768 px la
   typographie que le `h3` lui donnait, pour que le rendu ne bouge pas d'un pixel.

   Les valeurs sont celles du kit Elementor 6675, `h3 { font-size: 25px; font-weight: 300;
   line-height: 1.067em }`, et « Work Sans » qui vient du corps. Relevé sur le rendu servi à
   390 px avant changement : Work Sans 25 px / 26,675 px / 300.

   Le point de rupture est celui d'Elementor, `max-width: 767px` — le même que la classe
   `elementor-hidden-mobile` qui masquait le widget, dans frontend-lite.min.css.

   ---- Pourquoi huit identifiants de contenu, et pas `.single-portfolio-item` ----

   Écrite d'abord sur `.single-portfolio-item`, la règle atteignait 18 contenus de plus : toute
   la famille « produit » du CPT (ge9x, trent-*, pw*, leap-*, cfm56-*), dont le titre est un
   `h1` visible sous 768 px depuis toujours, en Montserrat 30. Elle le passait en Work Sans 25.
   Mesuré sur les 35 portfolio-items publiés, à 390 px, avant de resserrer.

   Un neuvième contenu est volontairement EXCLU : /p-i/how-to-work-the-torke-to-properly-
   tighten-a-nut-to-a-bolt/ (20369). Il appartient à la famille « article », il porte le même
   gabarit et le même identifiant de widget `246e7a42` — mais il n'a jamais eu de jumeau, donc
   son titre mobile est en Montserrat 30 depuis toujours, comme en production. Il n'a aucun
   défaut à corriger ; l'y inclure serait une divergence gratuite. Ni l'identifiant de widget
   ni celui du gabarit ne permettent de l'écarter : les deux lui sont communs avec les huit.

   La liste doit rester en phase avec DEDIENNE_TMU_CONTENUS, dans
   tools/templates/titre-mobile-unique.php.

   Divergence VOLONTAIRE avec la production, qui porte les deux mêmes défauts. Le rendu reste
   identique au sien ; la structure, non.
   ========================================================================== */

@media only screen and (max-width: 767px) {

    .postid-108224 .qodef-section-title h1.qodef-m-title,
    .postid-32574  .qodef-section-title h1.qodef-m-title,
    .postid-30797  .qodef-section-title h1.qodef-m-title,
    .postid-20812  .qodef-section-title h1.qodef-m-title,
    .postid-19930  .qodef-section-title h1.qodef-m-title,
    .postid-20085  .qodef-section-title h1.qodef-m-title,
    .postid-20608  .qodef-section-title h1.qodef-m-title,
    .postid-20618  .qodef-section-title h1.qodef-m-title {
        font-family: "Work Sans", sans-serif;
        font-size: 25px;
        font-weight: 300;
        line-height: 1.067em;
    }
}

/* ==========================================================================
   Barre de défilement du document — perdue avec le thème Borgholm

   Signalé par Jérém : la production stylise sa barre de défilement sur tout le site
   (piste presque noire, curseur orange), le site refait sert celle du navigateur.

   ---- Ce que la production sert vraiment, et pourquoi il faut DEUX blocs ----

   borgholm exprime la même barre de deux façons, dans `borgholm/assets/css/main.css` :

     html { scrollbar-color: #f23801 #0f0b12; scrollbar-width: thin }   <- propriétés standard
     body::-webkit-scrollbar       { width: 7px }                       <- voie WebKit
     body::-webkit-scrollbar-track { background-color: #e1e1e1 }
     body::-webkit-scrollbar-thumb { background-color: #f23801; outline: 1px solid #f23801 }

   Et la palette Dedienne, plus loin dans la feuille compilée, repasse le curseur en #fe5000 —
   mais seulement sur `body::-webkit-scrollbar-thumb`, pas dans le raccourci `scrollbar-color`.
   Le contour, lui, reste au #f23801 de borgholm. D'où les valeurs dissymétriques ci-dessous :
   elles ne sont pas une coquille, elles sont l'état de la production.

   Les deux blocs ne s'accordent donc PAS sur la piste — #0f0b12 d'un côté, #e1e1e1 de l'autre —
   et c'est le premier qui gagne dans Chrome : la barre du viewport résout `scrollbar-color` sur
   l'élément racine, alors que les pseudo-éléments sont posés sur `body`. C'est le fond noir que
   Jérém décrit. Les deux sont repris tels quels, sans arbitrer : la fidélité à la référence passe
   avant l'harmonisation, et le rendu local reste identique à la production dans les deux voies.

   ---- Ce qui n'est PAS repris ----

   `body.qodef-default-scrollbar--disabled` (option de thème qui masque la barre) : la classe est
   absente du `<body>` de la production sur l'accueil, /blog/, /contact/ et /p-i/cfm56-5a-5b/.
   Elle ne sert donc jamais, et le site refait n'a pas de quoi la produire.

   Relevé le 2026-08-28 par tools/migration-check, en énumérant les règles chargées dans
   Chromium : les captures de Playwright n'incluent pas la barre de défilement, la mesure au
   pixel est donc impossible ici.
   ========================================================================== */

html {
    scrollbar-color: #f23801 #0f0b12;
    scrollbar-width: thin;
}

body::-webkit-scrollbar {
    width: 7px;
}

body::-webkit-scrollbar-track {
    background-color: #e1e1e1;
}

body::-webkit-scrollbar-thumb {
    background-color: #fe5000;
    outline: 1px solid #f23801;
}

/* ==========================================================================
   Loupe de l'en-tête : blanche sur toutes les pages (recette 1, T09)
   ==========================================================================

   Le SVG `hives-light-web.svg`, inliné dans un icon-box de /values/ (et de /engine-tooling/ et
   /ground-support-equipment/), embarque son propre `<style>.st0 { fill: none; stroke: #000 }`.
   Une balise `<style>` en ligne est globale au document : elle écrase le `.st0 { fill: #fff }`
   du SVG de la loupe et la rend noire, ou invisible selon la page. La production n'inline pas
   ces SVG et n'a pas ce défaut. */
.elementor-location-header .elementor-element-8f52b8e .elementor-icon svg path {
    fill: #fff;
    stroke: none;
}

/* Pictos des pages Tooling, Values : 8 px entre l'icône et son libellé, comme la production
   (l'icône y est en ligne, la ligne de texte ajoute le blanc sous le dessin). */
.elementor-icon-box-wrapper > .elementor-icon-box-icon:has(.elementor-icon svg, .elementor-icon img) {
	margin-bottom: 8px;
}

/* Demande du client (recette 1) : le libellé est centré sous son pictogramme, ce que la production
   actuelle ne fait pas. Ni les icon-box sans pictogramme (lien « En savoir plus »), ni l'indice
   d'égalité de /careers/ (page 12997), aligné à gauche en production, ne sont touchés. */
body:not(.page-id-12997) .elementor-widget-icon-box .elementor-icon-box-wrapper:has(> .elementor-icon-box-icon .elementor-icon svg, > .elementor-icon-box-icon .elementor-icon img),
body:not(.page-id-12997) .elementor-widget-icon-box .elementor-icon-box-wrapper:has(> .elementor-icon-box-icon .elementor-icon svg, > .elementor-icon-box-icon .elementor-icon img) .elementor-icon-box-content {
	text-align: center;
}

/* Sous-titre italique sous un titre de rubrique : 16 px et 17 px d'écart avec le titre, comme la
   production. Le paragraphe prenait 14 px (corps du thème) et 30 px d'écart (20 px de marge du
   titre + 10 px de marge du paragraphe). */
.elementor-widget-text-editor:has(> .elementor-widget-container > h2) + .elementor-widget-text-editor.mb0 {
	margin-top: -3px;
}
.elementor-widget-text-editor:has(> .elementor-widget-container > h2) + .elementor-widget-text-editor.mb0 > .elementor-widget-container > p {
	font-size: inherit;
	line-height: 1.5;
	margin-top: 0;
}

/* Liens saisis à la main dans le pied de page : gris au repos, blanc au survol et au focus, comme la
   production. La couleur n'est plus portée par un style en ligne, qui interdisait tout survol. */
.elementor-location-footer .elementor-widget-text-editor a {
	color: #a8a8a8;
	transition: color 0.2s ease-out;
}
.elementor-location-footer .elementor-widget-text-editor a:hover,
.elementor-location-footer .elementor-widget-text-editor a:focus-visible {
	color: #fff;
}

/* Icônes sociales de l'en-tête et du pied, comme la production (deux cercles SVG animés par
   stroke-dashoffset, le tout pivotant de 199°) : au survol l'anneau orange se dessine pendant que
   l'anneau gris s'efface, et leur point de départ commun se déplace autour du cercle en 0,6 s.
   Ici les deux anneaux sont des pseudo-éléments masqués par un dégradé conique dont l'angle de
   départ et l'ouverture sont animés. */
@property --dedienne-arc {
	syntax: "<angle>";
	inherits: true;
	initial-value: 0deg;
}
@property --dedienne-start {
	syntax: "<angle>";
	inherits: true;
	initial-value: 305deg;
}
.elementor-location-header .elementor-social-icon,
.elementor-location-footer .elementor-social-icon {
	--dedienne-ring-rest: #e1e1e1;
	--dedienne-ring-hover: #f23801;
	position: relative;
	transition: --dedienne-arc 0.6s cubic-bezier(0.43, 0.41, 0.36, 0.9), --dedienne-start 0.6s cubic-bezier(0.43, 0.41, 0.36, 0.9), color 0.3s ease-out;
}
.elementor-location-footer .elementor-social-icon {
	--dedienne-ring-rest: #a8a8a8;
	--dedienne-ring-hover: #fe5000;
}
.elementor-location-header .elementor-social-icon::before,
.elementor-location-header .elementor-social-icon::after,
.elementor-location-footer .elementor-social-icon::before,
.elementor-location-footer .elementor-social-icon::after {
	content: "";
	position: absolute;
	inset: -1px;
	border: 1px solid var(--dedienne-ring-hover);
	border-radius: 50%;
	pointer-events: none;
	-webkit-mask: conic-gradient(from var(--dedienne-start), #000 var(--dedienne-arc), transparent 0);
	mask: conic-gradient(from var(--dedienne-start), #000 var(--dedienne-arc), transparent 0);
}
.elementor-location-header .elementor-social-icon::before,
.elementor-location-footer .elementor-social-icon::before {
	border-color: var(--dedienne-ring-rest);
	-webkit-mask: conic-gradient(from var(--dedienne-start), transparent var(--dedienne-arc), #000 0);
	mask: conic-gradient(from var(--dedienne-start), transparent var(--dedienne-arc), #000 0);
}
.elementor-location-header .elementor-social-icon:hover,
.elementor-location-header .elementor-social-icon:focus-visible,
.elementor-location-footer .elementor-social-icon:hover,
.elementor-location-footer .elementor-social-icon:focus-visible {
	--dedienne-arc: 360deg;
	--dedienne-start: 504deg;
}
.elementor-location-header .elementor-widget-social-icons.elementor-widget a.elementor-social-icon.elementor-icon,
.elementor-location-footer .elementor-widget-social-icons.elementor-widget a.elementor-social-icon.elementor-icon {
	border-color: transparent;
}
.elementor-location-footer .elementor-widget-social-icons.elementor-widget a.elementor-social-icon.elementor-icon svg {
	width: 14px;
	height: 14px;
}
.elementor-location-footer .elementor-widget-social-icons.elementor-widget a.elementor-social-icon.elementor-icon:hover svg,
.elementor-location-footer .elementor-widget-social-icons.elementor-widget a.elementor-social-icon.elementor-icon:focus-visible svg {
	fill: #fff;
}
@media (prefers-reduced-motion: reduce) {
	.elementor-location-header .elementor-social-icon,
	.elementor-location-footer .elementor-social-icon {
		transition: none;
	}
}

/* Boutons du slider d'accueil (Revolution Slider 108) : variante « outlined » de la production,
   texte noir fixe, ligne et pointe de flèche à droite. Les !important répondent aux styles
   en ligne posés par Revolution Slider. */
#rev_slider_108_1_wrapper .rs-layer.rev-btn[data-type="button"] {
	position: relative;
	box-sizing: border-box;
	padding: 12px 24px !important;
	border: 1px solid transparent !important;
	line-height: 22px !important;
	font-size: 11px !important;
	font-weight: 600 !important;
	letter-spacing: 2px !important;
	text-transform: uppercase;
	color: #000 !important;
	background-color: #f4f4f4 !important;
	overflow: visible !important;
}

#rev_slider_108_1_wrapper .rs-layer.rev-btn[data-type="button"]::before {
	content: "";
	position: absolute;
	right: -26px;
	top: 50%;
	width: 13.2031px;
	height: 11px;
	transform: translateY(-50%);
	background-repeat: no-repeat;
	background-position: left center;
	background-size: 11px 11px;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='black' transform='translate(0,480) scale(1,-1)' d='M 222.304,100.384l 122.432,112.256c 6.848,6.24, 6.848,16.384,0,22.624c-0.192,0.16-0.448,0.224-0.64,0.384 l-121.792,112c-6.848,6.24-17.984,6.24-24.832,0C 197.44,347.584, 197.408,347.488, 197.344,347.424C 194.080,344.544, 192,340.512, 192,336l0-224 c0-4.576, 2.176-8.64, 5.536-11.552l-0.064-0.064C 204.352,94.112, 215.456,94.112, 222.304,100.384z'/%3E%3C/svg%3E");
	transition: all .2s ease-in-out;
}

#rev_slider_108_1_wrapper .rs-layer.rev-btn[data-type="button"]::after {
	content: "";
	position: absolute;
	top: 50%;
	right: -18px;
	width: 34px;
	height: 2px;
	transform: translateY(-50%);
	transform-origin: left;
	background: #000;
	transition: all .2s ease-in-out;
}

#rev_slider_108_1_wrapper .rs-layer.rev-btn[data-type="button"]:hover {
	color: #000 !important;
	background-color: #f4f4f4 !important;
}

#rev_slider_108_1_wrapper .rs-layer.rev-btn[data-type="button"]:hover::before {
	right: -36px;
}

#rev_slider_108_1_wrapper .rs-layer.rev-btn[data-type="button"]:hover::after {
	transform: translateY(-50%) scaleX(1.3);
}

/* Widgets texte : la règle globale `p { font-size: 14px }` ignorait la typographie réglée sur
   le widget (étiquettes à 11px, accroches à 16px rendues à 14px). Le widget porte désormais les
   14px par défaut, à spécificité nulle, et son paragraphe en hérite : tout réglage posé sur le
   widget reprend la main, comme en production. */
:where(.elementor-widget-text-editor) {
	font-size: 14px;
	line-height: 1.733;
}

.elementor-widget-text-editor p {
	font-size: inherit;
	line-height: inherit;
}

/* Contact : blocs « General inquiries » rendus comme la liste FAQ de la production
   (titre en majuscules 14px, filet gris sous le titre et sous la liste, puces à l'intérieur). */
.dedienne-faq h3 {
	margin: 0;
	padding: 15px;
	border-bottom: 1px solid #ebebeb;
	font-size: 14px;
	font-weight: 500;
	line-height: 24.262px;
	text-transform: uppercase;
}

.dedienne-faq hr,
.dedienne-faq p {
	display: none;
}

.dedienne-faq ul {
	margin: 0 0 22px;
	padding: 16px 26px;
	border-bottom: 1px solid #ebebeb;
	list-style-position: inside;
}

/* Contact : titre de section à 25px comme en production (le kit donne 35px au h2). */
.dedienne-titre-25 h2 {
	font-size: 25px;
	line-height: 1.067;
}

/*
 * Mots orange des titres : un mot après l'autre, en glissant depuis la gauche
 * (assets/js/mots-orange.js, qui découpe chaque span orange en un span par mot).
 * Masqués seulement quand le script a posé `dedienne-mots` sur <html> : sans JavaScript, ou avec
 * « réduire les animations », ils restent visibles. Avant le découpage, le span d'origine est
 * seulement rendu transparent : il garde sa place, la ligne ne saute pas.
 */
html.dedienne-mots :is(.elementor-widget-heading, .elementor-widget-text-editor) :is(h1, h2, h3) span[style*="fe5000" i] {
	opacity: 0;
}

html.dedienne-mots .dedienne-mot {
	display: inline-block;
	opacity: 0;
	transform: translateX(-10px);
	transition: opacity 0.5s ease, transform 0.5s ease;
}

html.dedienne-mots .dedienne-mot.dedienne-mot-visible {
	opacity: 1;
	transform: translateX(0);
}

/* Contact : adresses e-mail cliquables, noires puis orange au survol comme en production. */
.dedienne-faq a[href^="mailto:"] {
	color: inherit;
	transition: color 0.2s ease-out;
}

.dedienne-faq a[href^="mailto:"]:hover,
.dedienne-faq a[href^="mailto:"]:focus-visible {
	color: #fe5000;
}

/* Careers : la liste de la colonne de droite descend de 48 px, comme en production, pour que
   « Department » s'aligne sur « Dedienne Aerospace's location ». */
.page-id-12997 #cf7md-form .cln2 .cf7md-select {
	padding-top: 48px;
}

/* Slider d'accueil (Revolution Slider 108) : la hauteur suit le contenu au lieu des hauteurs fixes
   par palier posées par Revolution. Les !important répondent aux styles en ligne du module. Les
   diapos sont superposées dans une grille ; sous 1025 px le texte et l'image sont en flux dans le
   groupe de texte, au-dessus, l'image reste en absolu et le plancher de hauteur la contient.
   La hauteur du module change donc avec la diapo affichée. Tant que assets/js/slider-accueil-pret.js
   n'a pas posé `dedienne-slider-pret`, la hauteur est plafonnée à celle d'origine du module : avant
   que Revolution dimensionne ses calques, le module mesure plus de 2000 px. */
#rev_slider_108_1_wrapper,
#rev_slider_108_1 {
	height: auto !important;
	max-height: none !important;
}
#rev_slider_108_1_wrapper {
	position: relative !important;
}
/* Le module passe dans le flux : l'espaceur que Revolution y ajoute pour le remplacer doublerait la hauteur. */
#rev_slider_108_1_forcefullwidth rs-fw-forcer {
	display: none !important;
}
#rev_slider_108_1_wrapper:not(.dedienne-slider-pret) {
	max-height: 920px !important;
	overflow: hidden;
}
@media (min-width: 1025px) {
	#rev_slider_108_1_wrapper:not(.dedienne-slider-pret) {
		max-height: 650px !important;
	}
}
#rev_slider_108_1 rs-slides {
	position: relative !important;
	display: grid !important;
	height: auto !important;
	max-height: none !important;
}
#rev_slider_108_1 rs-slide {
	position: relative !important;
	grid-area: 1 / 1;
	align-self: start;
	height: auto !important;
	box-sizing: border-box;
	padding: 40px 0 72px !important;
}
#rev_slider_108_1 rs-slide > rs-group-wrap {
	position: relative !important;
	top: auto !important;
	margin: 0 !important;
}
@media (min-width: 1025px) {
	#rev_slider_108_1 rs-slide {
		min-height: max(440px, calc(min(28.5vw, 480px) + 122px));
	}
	#rev_slider_108_1 rs-slide > rs-layer-wrap {
		top: 50px !important;
	}
}

/* Textes précédés d'un trait gris (widget « divider » dans la colonne voisine) : 14 px, graisse 400. */
.elementor-column:has(> .elementor-widget-wrap > .elementor-widget-divider) + .elementor-column .elementor-widget-text-editor,
.elementor-column:has(> .elementor-widget-wrap > .elementor-widget-divider) + .elementor-column .elementor-widget-text-editor p {
	font-size: 14px !important;
	font-weight: 400 !important;
}

/* FAQ : le contour pointillé de UAEL ne reste qu'au clavier (:focus-visible), plus au clic souris. */
.uael-question-span:focus:not(:focus-visible) {
	outline: none;
}

/*
 * Cases à cocher Material Design (shortcode md-checkbox) : le widget « UAEL CF7 Styler » réduit tout
 * `.wpcf7-checkbox input[type=checkbox]` à 1 px pour le remplacer par sa propre case. Ici la case est
 * celle de Material Design, l'input natif doit recouvrir la case pour recevoir le clic.
 */
#cf7md-form .mdc-checkbox .mdc-checkbox__native-control {
	width: 100% !important;
	height: 100% !important;
	margin: 0 !important;
	clip: auto !important;
	overflow: visible !important;
}
