/* =========================================================================
   411 — ce que theme.json ne sait pas exprimer.

   Règle de travail : aucune valeur de couleur, de taille ou d'espacement
   n'est recopiée en dur ici. Tout passe par les variables générées depuis
   theme.json, pour que changer la charte reste une opération à un endroit.

   Une seule exception, assumée : les deux encres de marque apparaissent en
   clair dans les dégradés, parce que les fonctions de dégradé n'acceptent
   pas toujours une variable dans toutes les positions selon le navigateur.

   Les encres, mesurées sur blanc :
     magenta #e6007e  4,50:1  conforme en petit texte, sur blanc seulement
     cyan    #009fe3  2,97:1  aplats et dégradés uniquement, jamais de texte

   Il n'y a plus qu'un magenta. L'ancienne variante assombrie existait parce
   que le magenta précédent plafonnait à 4,05:1 ; celui-ci atteint le seuil,
   donc il porte le texte lui-même. Le jeton magenta-text reste dans la
   palette, à la même valeur, parce que des contenus enregistrés le citent.
   Son seul interdit : le fond gris, où il retombe à 4,15:1. Vérifié sur le
   site en ligne, aucun texte magenta ne tombe sur autre chose que du blanc.

     cyan lisible #0072a3  5,34:1  le cyan, lui, a toujours besoin de sa
                                   variante : 2,97:1 ne porte aucun texte
   ========================================================================= */

/* ---------- socle ------------------------------------------------------- */

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
    }
}

body { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }

/* La mesure appartient au rôle, pas à la balise. Ce plafond ne vaut plus que
   dans le contenu de page, et il ne pèse rien : n'importe quelle classe le
   reprend sans avoir à écrire max-width: none quatorze fois. */
:where(.s411-contenu) p { max-width: 62ch; }
h1, h2, h3 { text-wrap: balance; }

:where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
    outline: 3px solid var(--wp--preset--color--cyan);
    outline-offset: 3px;
    border-radius: 3px;
}

/* Une seule forme de bouton dans tout le site : la pastille. */
.wp-block-button__link,
.s411-bouton,
.s411-header-cta { border-radius: 999px; }


/* ---------- en-tête ------------------------------------------------------
   Deux états, décidés par le contenu et non par un réglage : au-dessus d'un
   hero l'en-tête s'y inscrit, transparent et en blanc ; partout ailleurs il
   reprend son fond clair. `:has()` fait ce test en CSS pur.
------------------------------------------------------------------------- */

.s411-header {
    position: sticky;
    top: 0;
    z-index: 40;
    background: var(--wp--preset--color--base);
    border-bottom: 1px solid var(--wp--preset--color--rule);
}
.s411-header::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: -3px;
    height: 3px;
    background: var(--wp--preset--gradient--quadri);
}

/* La hauteur de l'en-tête, écrite une fois : le logo plus ses deux
   rembourrages. Tout ce qui doit passer sous un en-tête fixe s'y réfère au
   lieu de recopier un nombre qui ne suivrait pas. */
:root {
    --s411-entete-h: calc(clamp(2.9rem, 4.6vw, 4.4rem) + var(--wp--preset--spacing--30) * 2);
}

.s411-logo-link { display: inline-flex; color: var(--wp--preset--color--contrast); flex: none; }
.s411-logo-mark {
    display: block;
    width: auto;
    height: clamp(2.9rem, 4.6vw, 4.4rem);
    transition: transform .3s ease;
}
.s411-logo-link:hover .s411-logo-mark { transform: translateY(-2px); }

/* Au clic, les trois chiffres se posent l'un après l'autre. `transform-box:
   fill-box` est indispensable : sans lui, une transformation dans un SVG
   s'applique au repère du document et non à la forme, et les chiffres
   partiraient chacun dans une direction différente. */
.s411-logo-mark > g > * {
    transform-box: fill-box;
    transform-origin: 50% 65%;
}
@keyframes s411-chiffre {
    0%   { transform: none; }
    38%  { transform: translateY(-16%) rotate(-7deg) scale(1.1); }
    100% { transform: none; }
}
.s411-logo-anime .s411-logo-mark > g > * {
    animation: s411-chiffre .42s cubic-bezier(.34, 1.56, .64, 1) both;
}
.s411-logo-anime .s411-logo-mark > g > *:nth-child(2) { animation-delay: .07s; }
.s411-logo-anime .s411-logo-mark > g > *:nth-child(3) { animation-delay: .14s; }

@media (prefers-reduced-motion: reduce) {
    .s411-logo-anime .s411-logo-mark > g > * { animation: none; }
}

.s411-header-droite {
    display: flex;
    align-items: center;
    gap: var(--wp--preset--spacing--30);
    flex-wrap: nowrap;
}

.wp-block-navigation .wp-block-navigation-item__content {
    font-family: var(--wp--preset--font-family--display);
    font-size: var(--wp--preset--font-size--x-small);
    letter-spacing: .1em;
    text-transform: uppercase;
    text-decoration: none;
}

.s411-header-cta {
    flex: none;
    display: inline-block;
    font-family: var(--wp--preset--font-family--display);
    font-size: var(--wp--preset--font-size--x-small);
    letter-spacing: .1em;
    line-height: 1;
    text-transform: uppercase;
    text-decoration: none;
    padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
    background: var(--wp--preset--gradient--quadri);
    color: #fff;
    white-space: nowrap;
    transition: transform .25s ease, filter .25s ease;
}
.s411-header-cta:hover { transform: translateY(-2px); filter: saturate(1.25); color: #fff; }

/* --- posé dans un hero --- */
body:has(.s411-hero, .s411-pagehero) .s411-header {
    position: absolute;
    top: 0; left: 0; right: 0;
    background: var(--s411-entete-fond);
    border-bottom: 0;
}

/* L'encre de l'en-tête est une propriété enregistrée, donc interpolable, et
   héritée : elle descend sur le logo et sur les liens du menu sans qu'on ait
   à animer chacun. C'est ce qui permet à l'en-tête de rester visible une fois
   le hero passé, au lieu d'être du blanc sur du blanc. */
@property --s411-entete-fond {
    syntax: '<color>';
    initial-value: transparent;
    inherits: true;
}
/* La jauge de lecture, en nombre plutôt qu'en transformation : une
   transformation ne s'hérite pas, un nombre si. */
@property --s411-jauge {
    syntax: '<number>';
    initial-value: 0;
    inherits: true;
}
@property --s411-entete-encre {
    syntax: '<color>';
    initial-value: #fff;
    inherits: true;
}
/* Le voile de la jauge. Un dégradé n'est pas une couleur et ne s'interpole
   pas : on ne peut donc pas animer le fond du filet du blanc vers le dégradé.
   On pose le dégradé dessous, un aplat blanc par-dessus, et c'est l'alpha de
   cet aplat qui s'anime. Blanc opaque sur le hero, transparent une fois
   l'en-tête posé, et le dégradé apparaît. */
@property --s411-jauge-voile {
    syntax: '<color>';
    initial-value: #ffffff;
    /* Hérité, et c'est tout le sujet : le trait est dessiné par ::after, qui
       n'a pas d'animation à lui. Il ne peut voir la valeur animée sur
       l'en-tête que si elle descend. Déclarée sans héritage, elle restait
       bloquée sur le blanc initial et le trait ne changeait jamais. */
    inherits: true;
}

@keyframes s411-entete-pose {
    to {
        --s411-entete-fond: #ffffff;
        --s411-entete-encre: #0b0f14;
        --s411-jauge-voile: rgba(255, 255, 255, 0);
    }
}

@supports (animation-timeline: scroll()) {
    /* `fixed` et non `sticky` : au-dessus d'un hero l'en-tête ne doit occuper
       aucune place, sinon il rouvre la bande blanche qu'on a mis longtemps à
       refermer. Fixe, il ne pousse rien et ne bouge pas. */
    body:has(.s411-hero, .s411-pagehero) .s411-header { position: fixed; }

    /* La bascule se mesure sur le défilement de la page, et non sur la sortie
       du hero par un chronomètre nommé. La version nommée était pourtant plus
       juste à écrire : un chronomètre attaché au hero lui-même, partagé par
       `timeline-scope`. Elle ne s'active pas. Vérifié en construisant le même
       chronomètre en JavaScript sur le même hero, qui lui rend bien sa
       progression : le sujet et le conteneur de défilement sont donc bons,
       c'est la résolution du nom qui reste inerte.
       On mesure donc directement, sur la hauteur du hero, qui est écrite noir
       sur blanc juste en dessous. Un seul chronomètre pour toute la page, le
       même que celui de la jauge de lecture, qui lui fonctionne. */
    body:has(.s411-hero)     { --s411-bascule: calc(clamp(28rem, 74vh, 44rem) - 4.5rem); }
    body:has(.s411-pagehero) { --s411-bascule: calc(clamp(17rem, 40vh, 26rem) - 3rem); }

    /* L'animation vit sur le corps de page et non sur l'en-tête. Un élément
       en position fixe n'est pas déplacé par le défilement du document : le
       chronomètre lui reste inactif et rien ne joue, ni la bascule ni la
       jauge. Mesuré : les deux animations étaient bien accrochées, en état
       « running », et leur chronomètre rendait un temps nul. Le corps, lui,
       défile. Les trois propriétés sont héritées, l'en-tête les reçoit. */
    body:has(.s411-hero, .s411-pagehero) {
        animation: s411-jauge linear both, s411-entete-pose linear both;
        animation-timeline: scroll(root block), scroll(root block);
        animation-range: normal, 0 var(--s411-bascule, 320px);
    }
    body:not(:has(.s411-hero, .s411-pagehero)) {
        animation: s411-jauge linear both;
        animation-timeline: scroll(root block);
    }
    body:has(.s411-hero, .s411-pagehero) .s411-header::after { display: block; }
}
body:has(.s411-hero, .s411-pagehero) .s411-header::after { display: none; }
body:has(.s411-hero, .s411-pagehero) .s411-header,
body:has(.s411-hero, .s411-pagehero) .s411-header a { color: var(--s411-entete-encre); }
body:has(.s411-hero, .s411-pagehero) .s411-header a:hover { opacity: .72; }
/* `a.` et non `.` seul : la règle générique sur .s411-header a pèse 0,2,2 et
   battait 0,2,1, ce qui donnait du texte blanc sur un fond blanc. */
/* La pastille d'appel ne suit pas la bascule : elle prend l'encre du site et
   du blanc dedans, ce qui tient aussi bien sur le dégradé (4,18:1 au point le
   plus sombre) qu'une fois l'en-tête posé sur du blanc (17,74:1). Une seule
   règle, aucune animation, et rien qui puisse se retrouver blanc sur blanc. */
body:has(.s411-hero, .s411-pagehero) a.s411-header-cta {
    background: var(--wp--preset--color--contrast);
    color: #fff;
    opacity: 1;
}
body:has(.s411-hero, .s411-pagehero) a.s411-header-cta:hover {
    background: var(--wp--preset--gradient--quadri);
    color: #fff;
}
body.admin-bar:has(.s411-hero, .s411-pagehero) .s411-header { top: 32px; }

@supports not selector(:has(*)) {
    .s411-hero, .s411-pagehero { padding-top: var(--wp--preset--spacing--60); }
}

/* L'en-tête reste un frère de <main> dans le DOM même en position absolue :
   WordPress applique donc son écart entre blocs à <main>, ce qui ouvrait une
   bande blanche de 28 px au-dessus du hero. La règle du cœur passe par
   :where() et ne pèse rien, celle-ci la couvre sans !important. */
body:has(.s411-hero, .s411-pagehero) .wp-site-blocks > main { margin-top: 0; }

@media (max-width: 900px) {
    .s411-header-cta { display: none; }
}


/* ---------- dégradés animés ----------------------------------------------
   L'angle est déclaré comme propriété typée : sans cela il n'est pas
   interpolable et l'animation sauterait d'une valeur à l'autre.

   Le mouvement est franc, et c'est voulu. Une première version dérivait de
   7 % en deux secondes et demie avec un `ease-in-out` sur 19 secondes :
   l'animation tournait bel et bien, mais elle rampait tellement près de ses
   extrémités qu'elle se lisait comme figée. Ici l'angle balaie 150 degrés,
   ce qui fait basculer les deux encres d'un bord à l'autre, et le
   déplacement du fond est en `linear` pour ne jamais s'arrêter.
------------------------------------------------------------------------- */

@property --s411-angle {
    syntax: '<angle>';
    initial-value: 115deg;
    inherits: false;
}

@keyframes s411-derive {
    from { background-position:   0% 50%; }
    to   { background-position: 100% 50%; }
}
@keyframes s411-pivot {
    from { --s411-angle:  55deg; }
    to   { --s411-angle: 205deg; }
}


/* ---------- hero d'accueil ----------------------------------------------- */

.s411-hero {
    position: relative;
    overflow: hidden;
    color: #fff;
    /* Le hero tenait 1182 px de haut pour une fenêtre de 898 : les deux
       boutons tombaient sous la ligne de flottaison, donc le premier écran
       ne proposait plus rien à faire. La hauteur est maintenant calée pour
       que l'appel à l'action reste visible sans défiler. */
    min-height: clamp(28rem, 74vh, 44rem);
    display: flex;
    align-items: flex-end;
    padding: 8rem clamp(1.25rem, 4vw, 4.5rem) var(--wp--preset--spacing--50);

    background: linear-gradient(115deg, #e6007e 0%, #009fe3 100%);
    background-size: 200% 200%;
    animation: s411-derive 11s linear infinite alternate;
}
@supports (background: linear-gradient(in oklch, red, blue)) {
    .s411-hero {
        background-image: linear-gradient(var(--s411-angle) in oklch, #e6007e 0%, #009fe3 100%);
        animation: s411-derive 11s linear infinite alternate,
                   s411-pivot  17s ease-in-out infinite alternate;
    }
}

.s411-hero-inner,
.s411-pagehero-inner {
    position: relative;
    width: 100%;
    max-width: 1780px;
    margin: 0 auto;
}

.s411-hero-eyebrow {
    font-family: var(--wp--preset--font-family--body);
    font-size: var(--wp--preset--font-size--small);
    font-weight: 600;
    letter-spacing: .2em;
    text-transform: uppercase;
    color: #fff;
    margin: 0 0 var(--wp--preset--spacing--20);
    max-width: none;
}

.s411-hero-title {
    font-family: var(--wp--preset--font-family--display);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: -.03em;
    line-height: .88;
    font-size: clamp(2.5rem, 5.9vw, 7rem);
    margin: 0 0 var(--wp--preset--spacing--20);
    max-width: 20ch;
}

.s411-hero-lede {
    font-size: clamp(1.05rem, 1.5vw, 1.6rem);
    line-height: 1.5;
    color: #fff;
    max-width: 58ch;
    margin: 0 0 var(--wp--preset--spacing--30);
}

.s411-hero-actions { display: flex; flex-wrap: wrap; gap: var(--wp--preset--spacing--20); }

.s411-hero-cta, .s411-hero-ghost {
    display: inline-block;
    font-family: var(--wp--preset--font-family--display);
    font-size: var(--wp--preset--font-size--x-small);
    letter-spacing: .1em;
    text-transform: uppercase;
    text-decoration: none;
    /* Interligne déclarée, sinon un bouton écrit en <a> hérite 1,65 et un
       bouton écrit en <button> tombe sur normal : deux hauteurs de pastille
       pour le même libellé de 13 px. */
    line-height: 1;
    padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
    border-radius: 999px;
    transition: transform .25s ease, background .25s ease, color .25s ease;
}
/* Écrits en blocs, les deux boutons du hero sont des wp-block-button : ils
   reçoivent la même carrosserie que les deux formes historiques, pour que le
   passage du PHP à l'éditeur ne se voie pas à l'écran. Même chose pour les
   liens d'action des tuiles et des cartes d'offre. */
.s411-hero-actions .wp-block-button__link,
.s411-appel-actions .wp-block-button__link {
    font-family: var(--wp--preset--font-family--display);
    font-size: var(--wp--preset--font-size--x-small);
    letter-spacing: .1em;
    text-transform: uppercase;
    line-height: 1;
    padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
    border-radius: 999px;
}
.s411-hero-actions .is-style-s411-clair .wp-block-button__link {
    background: #fff;
    color: var(--wp--preset--color--contrast);
}
.s411-hero-actions .is-style-s411-clair .wp-block-button__link:hover { transform: translateY(-2px); }
.s411-hero-actions .is-style-outline .wp-block-button__link {
    background: transparent;
    border: 1.5px solid #fff;
    color: #fff;
}
.s411-hero-actions .is-style-outline .wp-block-button__link:hover {
    background: #fff;
    color: var(--wp--preset--color--contrast);
}

/* Dans une tuile et dans une carte d'offre, le lien n'est pas une pastille :
   il garde le filet magenta sous le libellé, comme avant. */
.s411-tuile .wp-block-buttons,
.s411-offer-foot .wp-block-buttons { margin: 0; }
.s411-tuile .wp-block-button__link,
.s411-offer-foot .wp-block-button__link {
    background: none;
    padding: 0 0 3px;
    border-radius: 0;
    font-family: var(--wp--preset--font-family--display);
    font-size: var(--wp--preset--font-size--x-small);
    letter-spacing: .1em;
    line-height: 1;
    text-transform: uppercase;
    color: inherit;
    border-bottom: 2px solid var(--wp--preset--color--magenta);
}
.s411-tuile--degrade .wp-block-button__link,
.s411-tuile--photo .wp-block-button__link { border-bottom-color: #fff; }

.s411-hero-cta { background: #fff; color: var(--wp--preset--color--contrast); }
.s411-hero-cta:hover { transform: translateY(-2px); color: var(--wp--preset--color--contrast); }
.s411-hero-ghost { border: 1.5px solid #fff; color: #fff; }
.s411-hero-ghost:hover { background: #fff; color: var(--wp--preset--color--contrast); }

/* Entrée du texte : se termine seule en moins d'une seconde et demie, rien
   n'est suspendu à un observateur de défilement. */
@keyframes s411-monte {
    from { opacity: 0; transform: translate3d(0, 2rem, 0); }
    to   { opacity: 1; transform: none; }
}
.s411-hero-eyebrow, .s411-hero-lede, .s411-hero-actions,
.s411-pagehero-eyebrow, .s411-pagehero-title, .s411-pagehero-lede {
    animation: s411-monte .9s cubic-bezier(.2,.75,.3,1) both;
}
.s411-hero-eyebrow, .s411-pagehero-eyebrow { animation-delay: .05s; }
.s411-pagehero-title { animation-delay: .16s; }
/* Le titre d'accueil n'est pas animé en bloc : ce sont ses mots qui le sont,
   un par un, avec un retard calculé dans la composition. */
.s411-hero-lede    { animation-delay: .72s; }
.s411-hero-actions { animation-delay: .84s; }
.s411-pagehero-lede { animation-delay: .30s; }

@media (prefers-reduced-motion: reduce) {
    .s411-hero, .s411-pagehero { animation: none; background-position: 50% 50%; }
    .s411-hero-eyebrow, .s411-hero-title, .s411-hero-lede, .s411-hero-actions,
    .s411-mot,
    .s411-pagehero-eyebrow, .s411-pagehero-title, .s411-pagehero-lede {
        animation: none; opacity: 1; transform: none;
    }
}

@media (max-width: 640px) {
    .s411-hero {
        min-height: 30rem;
        padding: var(--wp--preset--spacing--60) clamp(1.25rem, 4vw, 4.5rem) var(--wp--preset--spacing--40);
    }
    .s411-hero-title { max-width: none; }
    .s411-hero-actions > * { width: 100%; text-align: center; }
}


/* ---------- hero de page -------------------------------------------------
   Chaque page en a un. Plus court que celui de l'accueil : il porte le titre
   et situe la page, il ne la raconte pas.
------------------------------------------------------------------------- */

.s411-pagehero {
    position: relative;
    overflow: hidden;
    color: #fff;
    display: flex;
    align-items: flex-end;
    min-height: clamp(17rem, 40vh, 26rem);
    padding: 7.5rem clamp(1.25rem, 4vw, 4.5rem) var(--wp--preset--spacing--40);

    background: linear-gradient(125deg, #009fe3 0%, #e6007e 100%);
    background-size: 200% 200%;
    animation: s411-derive 13s linear infinite alternate;
}
@supports (background: linear-gradient(in oklch, red, blue)) {
    .s411-pagehero {
        background-image: linear-gradient(var(--s411-angle) in oklch, #009fe3 0%, #e6007e 100%);
        animation: s411-derive 13s linear infinite alternate,
                   s411-pivot  21s ease-in-out infinite alternate;
    }
}

/* Le dégradé ne redémarre pas au même endroit d'une page à l'autre. Deux
   décalages tirés au sort côté PHP arrivent ici en retards négatifs : la
   dérive et le pivot sont déjà en cours quand la page s'affiche, et jamais
   au même point. Changer de page change l'image, sans changer les couleurs.
   Le repli à 0 s garde l'animation d'origine si la variable manque. */
.s411-hero, .s411-pagehero {
    animation-delay: var(--s411-phase-a, 0s), var(--s411-phase-b, 0s);
}

.s411-pagehero-eyebrow {
    font-family: var(--wp--preset--font-family--body);
    font-size: var(--wp--preset--font-size--x-small);
    font-weight: 600;
    letter-spacing: .2em;
    text-transform: uppercase;
    margin: 0 0 var(--wp--preset--spacing--20);
    max-width: none;
}
.s411-pagehero .wp-block-post-title,
.s411-pagehero-title {
    font-family: var(--wp--preset--font-family--display);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: -.025em;
    line-height: .9;
    font-size: clamp(2.6rem, 6.4vw, 7rem);
    color: #fff;
    margin: 0;
    max-width: 22ch;
}
.s411-pagehero-lede {
    font-size: clamp(1rem, 1.3vw, 1.35rem);
    line-height: 1.5;
    max-width: 58ch;
    margin: var(--wp--preset--spacing--20) 0 0;
}


/* ---------- fil d'Ariane -------------------------------------------------
   Il est dans le hero, à la place du surtitre. En bande séparée sous le hero
   il faisait descendre tout le contenu de 49 px et accrochait l'œil comme un
   élément à part entière, alors que c'est un repère qu'on consulte, pas un
   contenu qu'on lit. Ici il ne coûte pas un pixel de hauteur, et il porte
   plus que le « 411 · Montpellier » qu'il remplace, lequel répétait le logo.

   Il reprend donc exactement la graisse, le corps et l'interlettrage du
   surtitre, sur le dégradé et en blanc. Le séparateur est une flèche : c'est
   déjà le signe de direction des puces, des boutons et des liens du site.
------------------------------------------------------------------------- */

.s411-fil ol {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    list-style: none;
    margin: 0 0 var(--wp--preset--spacing--20);
    padding: 0;
    font-family: var(--wp--preset--font-family--body);
    /* Un cran plus bas et un ton plus discret : c'est un repère qu'on
       consulte, pas une ligne qu'on lit. Il pesait le corps du chapô. */
    font-size: var(--wp--preset--font-size--x-small);
    font-weight: 600;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, .72);
}
.s411-fil li { color: inherit; }
.s411-fil li + li::before {
    content: '\2192';
    margin-right: .5rem;
    letter-spacing: 0;
    /* Blanc à 70 % et non une couleur de marque : sur le dégradé, le magenta
       du site disparaîtrait dans le fond à l'endroit où il est magenta. */
    color: rgba(255, 255, 255, .7);
}
.s411-fil a {
    color: inherit;
    text-decoration: none;
    transition: color .25s ease;
}
.s411-fil a:hover { color: #fff; }
.s411-fil [aria-current="page"] { color: #fff; }

/* Le contenu vient se poser contre le hero : l'écart entre blocs rouvrait
   28 px sous une bande qui ne demandait pas à être séparée. */
body:has(.s411-pagehero) .wp-site-blocks > main > .wp-block-post-content { margin-top: 0; }

/* L'air sous le hero se règle ici, une fois. Il était écrit en style en ligne
   dans chacun des sept motifs de page, donc hors de portée de la feuille : on
   ne pouvait plus l'ajuster qu'en rouvrant sept fichiers. */
body:has(.s411-pagehero) .wp-site-blocks > main > .wp-block-post-content > :first-child {
    padding-top: var(--wp--preset--spacing--40);
}

/* Sur l'accueil, le hero vit dans le contenu de la page : c'est donc le bloc
   qui le suit qui doit prendre l'air, pas le premier enfant, qui est le hero.
   Sans ça le surtitre « Ce qu'on fait ici » venait se coller au bas du hero. */
.s411-hero + .wp-block-group { padding-top: var(--wp--preset--spacing--50); }

/* Sauf quand la page s'ouvre sur une bande de repères : elle vient alors se
   poser contre le hero, et les deux se lisent comme deux bandes qui se
   suivent plutôt que comme un bloc qui flotte sous un blanc. */
body:has(.s411-pagehero) .wp-site-blocks > main > .wp-block-post-content > :first-child:has(.s411-facts:first-child) {
    padding-top: 0;
}
.s411-facts:first-child { margin-top: 0; }


/* ---------- chapô --------------------------------------------------------
   Le paragraphe d'ouverture d'une page. Il était écrit deux fois de deux
   façons : ici en taille courante et presque noir, là en « large » et gris.
   Deux qualités de texte pour le même rôle, sur deux pages voisines. Une
   seule définition maintenant, et c'est la plus grande des deux qui gagne.
------------------------------------------------------------------------- */

/* CHAPÔ, définition de référence pour les deux feuilles. booking.css avait
   tranché la même question dans l'autre sens, et les deux cohabitaient sur la
   page réserver : 22 px en tête de page, 18 px quelques centimètres dessous.
   C'est la plus grande qui gagne, et .s411-sub la rejoint. */
.s411-chapo {
    font-size: var(--wp--preset--font-size--large);
    line-height: 1.65;
    color: var(--wp--preset--color--ink-2);
    max-width: 62ch;
}


/* ---------- styles de blocs --------------------------------------------- */

/* La couleur reçoit le !important qui lui manquait : une teinte choisie dans
   l'éditeur passait par-dessus le magenta du style de bloc alors qu'une taille
   ne passait pas. Le style laissait donc dériver exactement ce qui peut faire
   tomber le contraste et verrouillait ce qui ne risquait rien. */
.is-style-s411-eyebrow {
    font-family: var(--wp--preset--font-family--body) !important;
    font-size: var(--wp--preset--font-size--x-small) !important;
    font-weight: 600 !important;
    letter-spacing: .2em !important;
    text-transform: uppercase !important;
    color: var(--wp--preset--color--magenta-text) !important;
    line-height: 1.4 !important;
}
.is-style-s411-rule-top {
    border-top: 3px solid transparent;
    border-image: var(--wp--preset--gradient--quadri) 1;
}
.is-style-s411-duotone-frame img { border-radius: 4px; }

/* Le fond se fait en pseudo-élément : une transition d'opacité se compose
   sur le GPU, un dégradé ne s'anime pas. */
.is-style-s411-gradient > .wp-block-button__link {
    position: relative; overflow: hidden; isolation: isolate;
}
.is-style-s411-gradient > .wp-block-button__link::before {
    content: ''; position: absolute; inset: 0; z-index: -1;
    background: var(--wp--preset--gradient--quadri);
    opacity: 0; transition: opacity .3s ease;
}
.is-style-s411-gradient > .wp-block-button__link:hover::before { opacity: 1; }

.s411-arrow { display: inline-block; transition: transform .25s ease; }
a:hover .s411-arrow, .wp-block-button__link:hover .s411-arrow { transform: translateX(5px); }

/* Bouton générique, deux variantes. */
.s411-bouton {
    align-self: flex-start;
    display: inline-flex;
    align-items: center;
    gap: .5em;
    font-family: var(--wp--preset--font-family--display);
    /* .78rem était la seule taille de bouton du projet écrite hors barème :
       elle rendait 12,48 px là où les huit autres pastilles rendent 13. Et la
       hauteur de ligne était héritée de la page, 1,65, quand les boutons du
       tunnel sont des <button> qui tombent sur 1,17 : deux hauteurs de
       pastille pour le même libellé. */
    font-size: var(--wp--preset--font-size--x-small);
    line-height: 1;
    letter-spacing: .1em;
    text-transform: uppercase;
    text-decoration: none;
    padding: 1rem 1.9rem;
    background: linear-gradient(115deg, #009fe3, #e6007e);
    color: #fff;
    border: 1.5px solid transparent;
    transition: background .25s ease, color .25s ease, border-color .25s ease, transform .25s ease;
}
.s411-bouton:hover { transform: translateY(-2px); color: #fff; filter: saturate(1.3); }
.s411-bouton--clair { background: #fff; color: var(--wp--preset--color--contrast); }
.s411-bouton--clair:hover { background: transparent; border-color: #fff; color: #fff; }


/* ---------- mosaïque des activités --------------------------------------
   Six tuiles de tailles inégales sur une grille nommée. Les zones sont
   déclarées en toutes lettres : on lit la composition dans la feuille de
   style aussi bien que sur la page.

   La forme suit le contenu. Le studio fait vivre le lieu, il occupe quatre
   fois la surface d'une petite tuile ; la galerie prend une tuile haute
   parce que sa photo est en portrait, les espaces une tuile large parce que
   la leur est en paysage.
------------------------------------------------------------------------- */

.s411-mosaique {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: 19rem 19rem 22rem;
    grid-template-areas:
        "studio studio galerie coworking"
        "studio studio galerie fresque"
        "espaces espaces ateliers ateliers";
    gap: 16px;
    margin-top: var(--wp--preset--spacing--30);
}

/* La zone de grille était écrite en style en ligne par le PHP. En blocs, elle
   devient une classe : c'est la seule façon de la porter sans exposer une
   propriété de grille à la personne qui écrit. */
.s411-tuile--zone-studio    { grid-area: studio; }
.s411-tuile--zone-galerie   { grid-area: galerie; }
.s411-tuile--zone-coworking { grid-area: coworking; }
.s411-tuile--zone-fresque   { grid-area: fresque; }
.s411-tuile--zone-espaces   { grid-area: espaces; }
.s411-tuile--zone-ateliers  { grid-area: ateliers; }

.s411-tuile {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    border-radius: 14px;
    padding: var(--wp--preset--spacing--40);
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    gap: var(--wp--preset--spacing--20);
    transition: transform .4s cubic-bezier(.2,.7,.3,1), box-shadow .4s ease;
}
.s411-tuile:hover { transform: translateY(-6px); box-shadow: 0 26px 60px -30px rgba(11,15,20,.65); }

.s411-tuile--clair { background: var(--wp--preset--color--surface); color: var(--wp--preset--color--contrast); }
.s411-tuile--encre {
    background: var(--wp--preset--color--surface);
    color: var(--wp--preset--color--contrast);
    box-shadow: inset 0 0 0 1px var(--wp--preset--color--rule);
}
.s411-tuile--photo { background: var(--wp--preset--color--contrast); color: #fff; }
.s411-tuile--degrade {
    color: #fff;
    background: linear-gradient(125deg, #e6007e, #009fe3);
    background-size: 190% 190%;
    animation: s411-derive 15s linear infinite alternate;
}
@supports (background: linear-gradient(in oklch, red, blue)) {
    .s411-tuile--degrade {
        background-image: linear-gradient(var(--s411-angle) in oklch, #e6007e, #009fe3);
        animation: s411-derive 15s linear infinite alternate,
                   s411-pivot  23s ease-in-out infinite alternate;
    }
}

/* Deux formes possibles pour la même image de fond : l'ancienne, un <img> qui
   portait la classe, et celle de l'éditeur, où le bloc image pose la classe
   sur la <figure> et garde l'<img> dedans. Sans la seconde règle, c'est le
   cadre qui se retrouvait dimensionné et l'image débordait sans se recadrer :
   la tuile galerie s'affichait noire. */
.s411-tuile-image {
    position: absolute; inset: 0; z-index: -2;
    width: 100%; height: 100%;
    margin: 0;
    object-fit: cover;
    transition: transform .7s cubic-bezier(.2,.7,.3,1);
}
figure.s411-tuile-image img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
}
.s411-tuile:hover .s411-tuile-image { transform: scale(1.06); }

/* Un voile est indispensable ICI, contrairement au hero : une photo a des
   zones claires imprévisibles et le texte blanc y disparaîtrait. */
.s411-tuile--photo::after {
    content: ''; position: absolute; inset: 0; z-index: -1;
    background: linear-gradient(180deg, rgba(11,15,20,.1) 0%, rgba(11,15,20,.55) 52%, rgba(11,15,20,.9) 100%);
}

.s411-tuile-corps { display: flex; flex-direction: column; gap: var(--wp--preset--spacing--10); }
/* SURTITRE. Le .7rem était hors barème, et l'opacité de 75 % abaissait un
   contraste qu'on croyait acquis : une opacité sur du texte est un contraste
   qu'on ne sait plus calculer. */
.s411-tuile-sur {
    font-family: var(--wp--preset--font-family--body);
    font-size: var(--wp--preset--font-size--x-small);
    font-weight: 600; letter-spacing: .2em; line-height: 1.4;
    text-transform: uppercase; margin: 0; max-width: none;
}
/* TITRE DE SECTION : une tuile est large comme une section. */
.s411-tuile-titre {
    font-family: var(--wp--preset--font-family--display);
    font-weight: 400; text-transform: uppercase; letter-spacing: -.02em;
    line-height: 1.12; margin: 0;
    font-size: var(--wp--preset--font-size--x-large);
}
/* TITRE DE PAGE pour la tuile maîtresse : elle occupe quatre fois la surface
   d'une petite et ouvre la page la plus importante du site. */
.s411-tuile--degrade .s411-tuile-titre {
    font-size: var(--wp--preset--font-size--xx-large);
    letter-spacing: -.025em;
    line-height: .95;
}
/* TEXTE DE CADRE. */
.s411-tuile-texte {
    font-size: var(--wp--preset--font-size--small);
    line-height: 1.65; margin: 0; max-width: 62ch;
}
/* VALEUR EN LIGNE. */
.s411-tuile-prix {
    font-family: var(--wp--preset--font-family--display);
    font-size: var(--wp--preset--font-size--large);
    font-weight: 400; letter-spacing: -.015em;
    line-height: 1.3;
    font-variant-numeric: tabular-nums;
    margin: var(--wp--preset--spacing--10) 0 0; max-width: none;
}
.s411-tuile .s411-bouton { background: #fff; color: var(--wp--preset--color--contrast); }
.s411-tuile .s411-bouton:hover { background: transparent; border-color: currentColor; color: inherit; }
.s411-tuile--clair .s411-bouton { background: linear-gradient(115deg, #009fe3, #e6007e); color: #fff; }
.s411-tuile--clair .s411-bouton:hover { filter: saturate(1.3); }

@media (max-width: 1200px) {
    .s411-mosaique {
        grid-template-columns: repeat(2, 1fr);
        grid-template-rows: 20rem 17rem 17rem 20rem;
        grid-template-areas:
            "studio studio"
            "galerie coworking"
            "fresque ateliers"
            "espaces espaces";
    }
}
@media (max-width: 640px) {
    .s411-mosaique {
        grid-template-columns: 1fr;
        grid-template-rows: none;
        grid-auto-rows: minmax(16rem, auto);
        grid-template-areas: "studio" "galerie" "coworking" "fresque" "espaces" "ateliers";
    }
}
@media (prefers-reduced-motion: reduce) {
    .s411-tuile, .s411-tuile-image { transition: none; }
    .s411-tuile:hover, .s411-tuile:hover .s411-tuile-image { transform: none; }
}


/* ---------- bandeau de chiffres ------------------------------------------ */

.s411-chiffres {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 1px;
    border-radius: 18px;
    overflow: hidden;
    color: #fff;
    background: linear-gradient(115deg, #009fe3, #e6007e);
    background-size: 200% 200%;
    animation: s411-derive 16s linear infinite alternate;
}
@supports (background: linear-gradient(in oklch, red, blue)) {
    .s411-chiffres {
        background-image: linear-gradient(var(--s411-angle) in oklch, #009fe3, #e6007e);
        animation: s411-derive 16s linear infinite alternate,
                   s411-pivot  25s ease-in-out infinite alternate;
    }
}
.s411-chiffre {
    padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--30);
    box-shadow: inset 1px 0 0 rgba(255,255,255,.28);
}
.s411-chiffre:first-child { box-shadow: none; }
.s411-chiffre-valeur {
    font-family: var(--wp--preset--font-family--display);
    font-size: clamp(2.6rem, 4.6vw, 4.6rem);
    line-height: .9;
    margin: 0 0 10px;
    max-width: none;
    color: #fff;
}
.s411-chiffre-libelle {
    font-size: var(--wp--preset--font-size--small);
    line-height: 1.45;
    color: rgba(255,255,255,.9);
    margin: 0;
    max-width: none;
}
@media (max-width: 900px) { .s411-chiffres { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .s411-chiffres { grid-template-columns: 1fr; } }


/* ---------- détail des activités ----------------------------------------
   Le texte de fond, celui que les moteurs lisent et que les gens parcourent
   avant de décider. Alterné gauche/droite, avec une place tenue pour un
   visuel : tant qu'il n'y a pas de photo, le bloc porte un grand numéro
   rempli au dégradé, qui fait office d'image plutôt que de trou.
------------------------------------------------------------------------- */

.s411-detail {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--wp--preset--spacing--50);
    align-items: center;
    /* Le blanc au-dessus d'un filet et celui en dessous sont du même palier.
       Ici deux sources s'empilaient, le rembourrage de la section et la marge
       de rythme de .s411-contenu, qui ne fusionnent pas : le filet censé
       séparer deux sections à égalité se retrouvait à 108 px du texte du
       dessus et à 64 px de celui du dessous. */
    padding: var(--wp--preset--spacing--40) 0;
    border-top: 1px solid var(--wp--preset--color--rule);
}
.s411-detail:nth-child(even) .s411-detail-media { order: -1; }

.s411-detail-texte > * { max-width: 62ch; }
/* SURTITRE, en magenta : il est sur blanc, le seul fond où le magenta porte
   du texte (4,50:1 ; 4,15:1 sur le gris, donc jamais là). */
.s411-detail-sur {
    font-family: var(--wp--preset--font-family--body);
    font-size: var(--wp--preset--font-size--x-small);
    font-weight: 600; letter-spacing: .2em; line-height: 1.4;
    text-transform: uppercase;
    color: var(--wp--preset--color--magenta-text);
    margin: 0 0 var(--wp--preset--spacing--10);
}
/* TITRE DE SECTION. Le jeton x-large le ramenait à 32 px, soit 1,9 fois le
   texte qu'il coiffe : à cette distance deux niveaux ne se hiérarchisent plus,
   ils se ressemblent. Il garde donc une échelle à lui, calée pour tenir 2,7
   fois le corps de lecture, ce qui est l'écart qui se voit sans crier. */
.s411-detail-titre {
    font-family: var(--wp--preset--font-family--display);
    font-weight: 400; text-transform: uppercase; letter-spacing: -.02em;
    line-height: 1.12;
    font-size: clamp(2rem, 3.4vw, 3.4rem);
    margin: 0 0 var(--wp--preset--spacing--30);
}
/* TEXTE COURANT, au gris de lecture. C'est ici que se réglait le reproche sur
   les couleurs de la page studio : ce paragraphe était le seul texte de
   lecture du site en encre, et il l'était par omission, à côté d'une liste qui
   déclarait le gris. Il le déclare maintenant, comme tous les autres. */
.s411-detail-texte p:not(.s411-detail-sur):not(.s411-detail-numero) {
    margin: 0 0 var(--wp--preset--spacing--20);
    color: var(--wp--preset--color--ink-2);
    line-height: 1.65;
}
.s411-detail-texte p:not(.s411-detail-sur):not(.s411-detail-numero):last-of-type {
    margin-bottom: var(--wp--preset--spacing--30);
}

.s411-detail-media {
    position: relative;
    aspect-ratio: 4 / 3;
    border-radius: 16px;
    overflow: hidden;
    display: grid;
    place-items: center;
    background: linear-gradient(125deg, #e6007e, #009fe3);
    background-size: 190% 190%;
    animation: s411-derive 17s linear infinite alternate;
}
@supports (background: linear-gradient(in oklch, red, blue)) {
    .s411-detail-media {
        background-image: linear-gradient(var(--s411-angle) in oklch, #e6007e, #009fe3);
        animation: s411-derive 17s linear infinite alternate,
                   s411-pivot  29s ease-in-out infinite alternate;
    }
}
.s411-detail-media img {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
}
/* Le numéro n'apparaît que tant qu'il n'y a pas de photo. */
.s411-detail-media:has(img) .s411-detail-numero { display: none; }
.s411-detail-numero {
    font-family: var(--wp--preset--font-family--display);
    font-size: clamp(6rem, 14vw, 13rem);
    line-height: 1;
    color: rgba(255,255,255,.28);
    margin: 0;
    max-width: none;
    user-select: none;
}

@media (max-width: 900px) {
    .s411-detail { grid-template-columns: 1fr; gap: var(--wp--preset--spacing--30); }
    .s411-detail:nth-child(even) .s411-detail-media { order: 0; }
    .s411-detail-media { aspect-ratio: 16 / 9; }
}


/* ---------- bandeau d'appel final ---------------------------------------- */

.s411-appel {
    position: relative;
    overflow: hidden;
    border-radius: 20px;
    padding: var(--wp--preset--spacing--60) var(--wp--preset--spacing--40);
    color: #fff;
    text-align: center;
    background: linear-gradient(115deg, #009fe3, #e6007e);
    background-size: 200% 200%;
    animation: s411-derive 12s linear infinite alternate;
}
@supports (background: linear-gradient(in oklch, red, blue)) {
    .s411-appel {
        background-image: linear-gradient(var(--s411-angle) in oklch, #009fe3, #e6007e);
        animation: s411-derive 12s linear infinite alternate,
                   s411-pivot  19s ease-in-out infinite alternate;
    }
}
.s411-appel-titre {
    font-family: var(--wp--preset--font-family--display);
    font-weight: 400; text-transform: uppercase; letter-spacing: -.025em;
    line-height: .92;
    font-size: clamp(2.2rem, 5.4vw, 5.4rem);
    margin: 0 auto var(--wp--preset--spacing--30);
    max-width: 18ch;
}
.s411-appel-texte {
    font-size: clamp(1rem, 1.3vw, 1.3rem);
    line-height: 1.5;
    margin: 0 auto var(--wp--preset--spacing--40);
    max-width: 52ch;
}
.s411-appel-actions { display: flex; flex-wrap: wrap; gap: var(--wp--preset--spacing--20); justify-content: center; }
.s411-appel .s411-bouton { align-self: center; background: #fff; color: var(--wp--preset--color--contrast); }
.s411-appel .s411-bouton:hover { background: transparent; border-color: #fff; color: #fff; }
.s411-appel .s411-bouton--fantome { background: transparent; border-color: rgba(255,255,255,.55); color: #fff; }
.s411-appel .s411-bouton--fantome:hover { background: #fff; color: var(--wp--preset--color--contrast); }


/* ---------- offres coworking --------------------------------------------
   Pas de réservation en ligne : quinze places, engagement, caution et
   remise de clés se règlent en visite. Trois offres, donc trois colonnes ou
   une seule, jamais deux, qui laisserait une carte orpheline.
------------------------------------------------------------------------- */

/* WordPress applique un écart entre blocs à tous les frères sauf le premier.
   Les trois offres étant des blocs frères, les deux dernières héritaient de
   28 px de marge haute et décrochaient. Dans une grille, c'est l'écart de la
   grille qui gère l'espacement : la marge n'a rien à y faire. */
/* Le combinateur > ne couvrait que les trois cartes, pas leur contenu : à
   l'intérieur d'une carte, .s411-offer-features déclarait 28 px de marge basse
   et .s411-offer-foot recevait 28 px de marge haute qu'il ne demandait pas.
   La carte est en display: grid, où les marges ne fusionnent jamais : 56 px
   au-dessus du filet contre 28 px en dessous. Dans une grille, c'est la grille
   qui commande l'espacement, à tous les niveaux. */
.s411-offers > *,
.s411-offer > *,
.s411-offer-foot > *,
/* ---------- l'écart entre blocs n'entre pas dans une grille ---------------
   WordPress pose un écart vertical entre blocs frères. Dans un conteneur en
   flux c'est ce qu'on veut ; dans une grille, c'est une marge qui s'ajoute au
   gap et décale les cellules les unes par rapport aux autres.

   Le symptôme était visible sur toutes les pages converties : dans la bande de
   repères, le premier item restait en place et les trois suivants tombaient
   28 px plus bas ; dans les sections, la colonne du visuel se décalait de la
   colonne du texte ; dans l'encadré, le corps glissait sous son titre.

   Une seule règle pour tous les conteneurs en grille du thème, plutôt qu'un
   correctif par endroit au fil des captures d'écran.
------------------------------------------------------------------------- */

.s411-facts > *,
.s411-fact > *,
.s411-chiffres > *,
.s411-chiffre > *,
.s411-offers > *,
.s411-offer > *,
.s411-mosaique > *,
.s411-tuile > *,
.s411-detail > *,
.s411-point > *,
.s411-point-corps > *,
.s411-insta > *,
.s411-insta-grille > *,
.s411-reserver > * {
    margin-top: 0;
    margin-bottom: 0;
}
.s411-tuile.wp-block-group {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
}
.s411-tuile-corps > * { margin: 0; }
.s411-tuile-corps > * + * { margin-top: var(--wp--preset--spacing--20); }

.s411-mosaique > *,
.s411-chiffres > * { margin-top: 0; margin-block-start: 0; }

.s411-offers {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: auto auto 1fr auto auto auto;
    gap: var(--wp--preset--spacing--30);
    align-items: stretch;
}
.s411-offer {
    background: var(--wp--preset--color--base);
    border: 1px solid var(--wp--preset--color--rule);
    /* Angles droits, et c'est le filet qui commande : posé en haut d'une
       carte arrondie, le dégradé suivait la courbe et plongeait à ses deux
       extrémités. Un filet doit être droit, sinon ce n'est plus un filet
       mais un ornement. */
    border-radius: 0;
    padding: var(--wp--preset--spacing--40);
    position: relative;
    overflow: hidden;
    /* La carte emprunte les rangées de la grille parente : le prix d'une
       offre tombe exactement à la hauteur du prix des deux autres. Coller
       le pied en bas ne suffisait pas, un bloc de conditions plus haut
       remontait son prix de 42 px. */
    display: grid;
    grid-row: span 6;
    grid-template-rows: subgrid;
    row-gap: 0;
}
.s411-offer::before {
    content: '';
    position: absolute;
    /* Décalé d'un pixel vers l'extérieur pour couvrir la bordure de la carte :
       sans ça, un liseré gris dépasse à chaque extrémité du filet. */
    top: -1px; left: -1px; right: -1px;
    height: 4px;
    background: var(--wp--preset--gradient--quadri);
}
.s411-offer-foot {
    grid-row: span 3;
    display: grid; grid-template-rows: subgrid; row-gap: 0;
    padding-top: var(--wp--preset--spacing--30);
    border-top: 1px solid var(--wp--preset--color--rule);
}
@supports not (grid-template-rows: subgrid) {
    .s411-offers { grid-template-rows: none; }
    .s411-offer { display: flex; flex-direction: column; grid-row: auto; }
    .s411-offer-foot { display: block; margin-top: auto; }
}
@media (max-width: 900px) {
    .s411-offers { grid-template-columns: 1fr; grid-template-rows: none; }
    .s411-offer { display: flex; flex-direction: column; grid-row: auto; }
    .s411-offer-foot { display: block; margin-top: auto; }
}

/* TITRE DE CARTE. Il ne déclarait pas d'interlettrage et gardait celui de
   theme.json ; il le déclare. */
.s411-offer-name {
    font-family: var(--wp--preset--font-family--display);
    font-size: var(--wp--preset--font-size--large);
    font-weight: 400; text-transform: uppercase;
    letter-spacing: -.015em; line-height: 1.12;
    color: var(--wp--preset--color--contrast);
    margin: 0 0 var(--wp--preset--spacing--10);
}
/* LIBELLÉ, sous le titre qu'il accompagne. */
.s411-offer-kicker {
    font-family: var(--wp--preset--font-family--body);
    font-size: var(--wp--preset--font-size--x-small);
    font-weight: 600; letter-spacing: .2em; line-height: 1.4;
    text-transform: uppercase;
    color: var(--wp--preset--color--ink-2);
    margin: 0 0 var(--wp--preset--spacing--30);
}
/* PUCE DE LISTE. Retrait et respiration sur le barème, et identiques à ceux de
   .s411-liste : les deux listes à flèches du site se suivent sur la page
   coworking et n'étaient pas au même retrait. */
.s411-offer-features { list-style: none; margin: 0 0 var(--wp--preset--spacing--30); padding: 0; }
.s411-offer-features li {
    position: relative;
    padding: 0 0 var(--wp--preset--spacing--10) var(--wp--preset--spacing--20);
    font-size: var(--wp--preset--font-size--small); line-height: 1.65;
    color: var(--wp--preset--color--ink-2);
}
.s411-offer-features li::before {
    content: '\2192'; position: absolute; left: 0; top: 0;
    line-height: 1.65;
    color: var(--wp--preset--color--magenta);
}
.s411-offer-features strong { color: var(--wp--preset--color--contrast); font-weight: 600; }

.s411-offer-price {
    display: flex; align-items: baseline;
    gap: var(--wp--preset--spacing--10);
    font-family: var(--wp--preset--font-family--display);
}
/* CHIFFRE VEDETTE. Le 3.4rem écrit en clair valait 54,4 px pendant que le prix
   de formule du tunnel valait 52 px par le jeton : deux échelles pour le même
   prix. C'est le jeton qui tranche. À 32 px au minimum on reste en grand
   texte, où le magenta de marque est conforme (4,50:1 pour un seuil de 3). */
.s411-offer-amount {
    font-size: var(--wp--preset--font-size--xx-large);
    font-weight: 400;
    letter-spacing: 0;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    color: var(--wp--preset--color--magenta);
}
/* MENTION. */
.s411-offer-period {
    font-family: var(--wp--preset--font-family--body);
    font-size: var(--wp--preset--font-size--x-small);
    line-height: 1.65;
    color: var(--wp--preset--color--ink-2);
}
.s411-offer-terms {
    margin: var(--wp--preset--spacing--20) 0;
    font-size: var(--wp--preset--font-size--x-small); line-height: 1.65;
    color: var(--wp--preset--color--ink-2);
}
/* La nouvelle encre magenta atteint 4,50:1 sur blanc, tout juste au seuil du
   petit texte. On garde quand même la variante assombrie ici : au seuil exact,
   le moindre fond légèrement teinté fait basculer du mauvais côté. */
.s411-offer-terms strong { color: var(--wp--preset--color--magenta-text); font-weight: 600; }

/* LIEN D'ACTION. .12em était le seul interlettrage de ce nom dans le projet :
   il rejoint le .1em des capitales d'Archivo Black. L'interligne est déclarée
   pour que .s411-formula-cta, qui reprend la même recette mais vit dans un
   <button> qui n'hérite de rien, pose son soulignement à la même distance. */
.s411-offer-cta {
    display: inline-block;
    font-family: var(--wp--preset--font-family--display);
    font-size: var(--wp--preset--font-size--x-small);
    font-weight: 400;
    letter-spacing: .1em; line-height: 1;
    text-transform: uppercase; text-decoration: none;
    color: var(--wp--preset--color--contrast);
    border-bottom: 2px solid var(--wp--preset--color--magenta);
    padding-bottom: 3px;
}
.s411-offer-cta:hover { color: var(--wp--preset--color--magenta-text); }


/* ---------- point important ---------------------------------------------
   Ancienne version : un filet dégradé à gauche sur fond gris. Ça rangeait le
   bloc dans la catégorie « note en marge », alors que son contenu est
   souvent ce qui évite un malentendu coûteux. Il porte maintenant une icône
   et se présente comme une information de premier rang.
------------------------------------------------------------------------- */

/* Le texte était plafonné à 64ch dans une bande large de 1780 px : la moitié
   droite restait vide. Trois zones maintenant, le picto, le titre, puis les
   paragraphes répartis en colonnes qui remplissent ce qui reste. */
.s411-point {
    display: grid;
    grid-template-columns: auto minmax(0, 4fr) minmax(0, 8fr);
    column-gap: var(--wp--preset--spacing--30);
    row-gap: var(--wp--preset--spacing--20);
    align-items: start;
    /* Même règle que pour le filet des sections : le blanc au-dessus et celui
       en dessous sont du même palier. Il y avait 108 px d'un côté et 28 de
       l'autre, un rapport de près de quatre pour un. */
    padding: var(--wp--preset--spacing--40) 0;
    border-top: 1px solid var(--wp--preset--color--rule);
    border-bottom: 1px solid var(--wp--preset--color--rule);
}

.s411-point-icone {
    grid-column: 1;
    display: block;
    flex: none;
    /* Le picto seul, sans pastille ni fond : un carré dégradé arrondi autour
       d'une icône fait gadget et détourne l'attention de ce qui compte, qui
       est le texte à côté. */
    color: var(--wp--preset--color--magenta);
    margin-top: .15rem;
}
.s411-point-icone svg { width: 1.7rem; height: 1.7rem; display: block; }

.s411-point-corps {
    grid-column: 3;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(26ch, 1fr));
    gap: var(--wp--preset--spacing--20) var(--wp--preset--spacing--40);
    align-items: start;
}
/* TEXTE COURANT. */
.s411-point-corps > p {
    margin: 0;
    font-size: var(--wp--preset--font-size--medium);
    line-height: 1.65;
    color: var(--wp--preset--color--ink-2);
    max-width: 62ch;
}
/* TITRE DE CARTE. Il n'est pas un <h*>, il n'héritait donc pas du serrage de
   theme.json et se retrouvait à interlettrage nul : à 25 px d'Archivo Black,
   ça se voit. Il le déclare. Les deux !important partent : aucun sélecteur des
   trois fichiers ne leur disputait quoi que ce soit, et ils interdisaient tout
   réglage depuis .s411-reserver-cote, qui est précisément l'endroit où
   l'encadré change de forme. */
.s411-point-titre {
    grid-column: 2;
    font-family: var(--wp--preset--font-family--display);
    font-size: var(--wp--preset--font-size--large);
    font-weight: 400;
    letter-spacing: -.015em;
    text-transform: uppercase;
    line-height: 1.12;
    color: var(--wp--preset--color--contrast);
    margin: 0;
    max-width: 18ch;
}

@media (max-width: 1100px) {
    .s411-point { grid-template-columns: auto minmax(0, 1fr); }
    .s411-point-titre { grid-column: 2; }
    .s411-point-corps { grid-column: 2; grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
    .s411-point { grid-template-columns: 1fr; }
    .s411-point-titre, .s411-point-corps { grid-column: 1; }
}

/* L'ancienne classe reste stylée : des pages la portent encore dans leur
   contenu enregistré, et elles ne doivent pas se retrouver sans mise en
   forme le temps qu'on les repasse. */
.s411-caveat {
    padding: var(--wp--preset--spacing--40);
    border-radius: 16px;
    background: var(--wp--preset--color--base);
    border: 1px solid var(--wp--preset--color--rule);
    font-size: var(--wp--preset--font-size--medium);
    line-height: 1.65;
    /* Déclarée : c'était l'un des quatre endroits du site où du texte arrivait
       en encre sans que personne ne l'ait décidé. */
    color: var(--wp--preset--color--ink-2);
}
/* Un écart entre deux paragraphes, une seule valeur : spacing-20. Il y en
   avait trois, 17,6 px, 12,8 px et 16 px. */
.s411-caveat p { margin: 0 0 var(--wp--preset--spacing--20); max-width: 62ch; }
.s411-caveat p:last-child { margin-bottom: 0; }


/* ---------- repères pratiques -------------------------------------------
   Ancienne version : quatre boîtes bordées identiques avec un libellé en
   petites capitales. C'est le motif de tableau de bord qu'on voit partout, et
   il ne dit rien du lieu.

   Ici, plus de boîtes. Une bande de repères séparés par un simple filet, la
   valeur en gros dans la police de titre et le libellé en petit au-dessus.
   Ça se lit comme la fiche technique d'un dossier de presse, ce que c'est.
------------------------------------------------------------------------- */

.s411-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: 0;
    margin: var(--wp--preset--spacing--40) 0;
    border-top: 2px solid var(--wp--preset--color--contrast);
}
.s411-fact {
    padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--30) var(--wp--preset--spacing--30) 0;
    border-bottom: 1px solid var(--wp--preset--color--rule);
}
/* Un filet entre les colonnes, jamais avant la première : une bordure posée
   sur tous les éléments ouvre toujours la bande par un trait orphelin. */
.s411-fact + .s411-fact {
    padding-left: var(--wp--preset--spacing--30);
    border-left: 1px solid var(--wp--preset--color--rule);
}
/* LIBELLÉ. Le magenta part : un libellé se répète quatre fois par bande et
   plusieurs fois par page, et une couleur qui se répète cesse de vouloir dire
   quelque chose. Il reste au surtitre, qui n'apparaît qu'une fois par bloc, et
   au chiffre vedette. */
.s411-fact dt {
    font-family: var(--wp--preset--font-family--body);
    font-size: var(--wp--preset--font-size--x-small);
    font-weight: 600;
    letter-spacing: .2em;
    line-height: 1.4;
    text-transform: uppercase;
    color: var(--wp--preset--color--ink-2);
    margin: 0 0 var(--wp--preset--spacing--10);
}
/* VALEUR EN LIGNE. Le clamp écrit en clair valait 18,4 px, sur aucun palier. */
.s411-fact dd {
    margin: 0;
    font-family: var(--wp--preset--font-family--display);
    font-size: var(--wp--preset--font-size--large);
    font-weight: 400;
    letter-spacing: -.015em;
    text-transform: uppercase;
    line-height: 1.3;
    font-variant-numeric: tabular-nums;
    color: var(--wp--preset--color--contrast);
}
.s411-fact dd a { color: inherit; }

@media (max-width: 760px) {
    .s411-fact, .s411-fact + .s411-fact {
        padding-left: 0;
        border-left: 0;
    }
}


/* ---------- pied de page -------------------------------------------------
   Sombre, et coiffé du dégradé sur toute sa largeur. C'est la dernière chose
   qu'on voit : autant qu'elle porte la marque plutôt qu'un filet gris.
------------------------------------------------------------------------- */

.s411-footer {
    position: relative;
    background: var(--wp--preset--color--surface);
    color: var(--wp--preset--color--ink-2);
    /* La bande de la lettre d'information ouvre ce pied de page et porte déjà
       spacing-40 de rembourrage haut : cette marge s'y ajoutait pour 88 px,
       qui n'est sur aucun palier. Une bande pleine largeur touche ce qui la
       précède, c'est son rembourrage qui fait l'air. */
    margin-top: 0;
    padding: 0;
}
/* Le filet de 6 px qui coiffait le pied de page a disparu : la bande de la
   newsletter est elle-même un dégradé sur toute la largeur, deux dégradés
   collés l'un à l'autre ne séparaient plus rien. */
.s411-footer-inner {
    max-width: 1780px;
    margin: 0 auto;
    padding: var(--wp--preset--spacing--60) clamp(1.25rem, 4vw, 4.5rem) var(--wp--preset--spacing--40);
}

.s411-footer-haut {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: var(--wp--preset--spacing--50);
    padding-bottom: var(--wp--preset--spacing--50);
    border-bottom: 1px solid var(--wp--preset--color--rule);
}
/* La marque revient en bas de page, à la taille d'une signature : c'est la
   dernière chose qu'on voit avant de partir. */
.s411-footer-logo {
    display: inline-flex;
    color: var(--wp--preset--color--contrast);
    margin-bottom: var(--wp--preset--spacing--20);
}
.s411-footer-logo-mark {
    display: block;
    width: auto;
    height: clamp(3.2rem, 5vw, 4.8rem);
    transition: transform .3s ease;
}
.s411-footer-logo:hover .s411-footer-logo-mark { transform: translateY(-3px); }

/* SURTITRE sur le gris du pied : ni magenta (4,15:1) ni gris clair (2,78:1),
   donc le gris de lecture, 5,91:1. */
.s411-footer-sur {
    font-family: var(--wp--preset--font-family--body);
    font-size: var(--wp--preset--font-size--x-small);
    font-weight: 600; letter-spacing: .2em; line-height: 1.4;
    text-transform: uppercase;
    color: var(--wp--preset--color--ink-2);
    margin: 0 0 var(--wp--preset--spacing--10); max-width: none;
}
/* TITRE DE PAGE. La règle disait blanc puis disait encre, trois lignes plus
   bas, dans la même déclaration : le blanc était un reliquat de l'époque où ce
   pied était sombre, et quiconque aurait supprimé la seconde ligne en croyant
   nettoyer un doublon aurait renvoyé la phrase en blanc sur gris clair. */
.s411-footer-phrase {
    font-family: var(--wp--preset--font-family--display);
    font-weight: 400; text-transform: uppercase; letter-spacing: -.025em;
    line-height: .95;
    font-size: var(--wp--preset--font-size--xx-large);
    margin: 0 0 var(--wp--preset--spacing--30);
    max-width: 16ch;
    color: var(--wp--preset--color--contrast);
}

.s411-footer-cols {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--wp--preset--spacing--40);
}
/* LIBELLÉ, variante d'appui à l'encre : il coiffe une liste déjà en gris, et
   sans cela le titre et sa liste auraient la même couleur. En Schibsted : il
   était le seul Archivo Black du thème à porter un interlettrage POSITIF,
   c'est-à-dire à écarter ce que la fonte serre. */
.s411-footer-titre {
    font-family: var(--wp--preset--font-family--body);
    font-size: var(--wp--preset--font-size--x-small);
    font-weight: 600; letter-spacing: .2em; line-height: 1.4;
    text-transform: uppercase;
    color: var(--wp--preset--color--contrast);
    margin: 0 0 var(--wp--preset--spacing--20);
}
.s411-footer-col ul { list-style: none; margin: 0; padding: 0; }
.s411-footer-col li { margin-bottom: var(--wp--preset--spacing--10); }
/* Tout lien est souligné, sans exception. Les deux adresses de courriel de ce
   pied de page étaient strictement indiscernables du texte qui les entoure :
   même couleur, même graisse, aucun soulignement, aucun autre signe, jusqu'au
   survol. C'est le défaut que booking.css corrige chez lui en toutes lettres
   et que le thème laissait vivre sur toutes les pages du site. */
/* Pas de soulignement ici. Ces liens vivent dans des colonnes qui annoncent
   ce qu'elles contiennent, sous un titre « Le lieu » suivi de noms de pages :
   le contexte dit déjà que ce sont des liens, et huit traits sous huit lignes
   hachaient le pied de page. C'est le survol qui porte le signe. */
.s411-footer-col a {
    color: var(--wp--preset--color--ink-2);
    text-decoration: none;
    transition: color .2s ease;
}
/* Le pied de page est gris : le magenta y retomberait à 4,15:1 en petit
   texte. C'est le soulignement qui prend la couleur, et le texte s'assombrit
   au lieu de s'éclaircir. */
/* Le survol passe à l'encre, de 6,40:1 à 17,74:1 : un écart qui se voit sans
   avoir besoin d'un trait. Et le magenta n'aurait pas pu servir ici, il
   retombe à 4,15:1 sur le gris du pied de page. */
.s411-footer-col a:hover { color: var(--wp--preset--color--contrast); }
/* TEXTE DE CADRE. */
.s411-footer-bloc {
    margin: 0 0 var(--wp--preset--spacing--20);
    font-size: var(--wp--preset--font-size--small);
    line-height: 1.65;
    max-width: none;
}
.s411-footer-bloc strong { color: var(--wp--preset--color--contrast); font-weight: 600; }
/* Le gris clair ne porte plus de texte : 2,78:1 sur ce fond. */
.s411-footer-gris { color: var(--wp--preset--color--ink-2); }
/* VALEUR EN LIGNE. Le !important réglait la couleur au repos mais bloquait le
   survol : .s411-footer-col a:hover pèse 0-2-1 et ne le déclare pas en
   !important, donc le numéro de téléphone était le seul lien du pied qui ne
   changeait pas de couleur. Le bon correctif était de monter la spécificité,
   et c'est ce que fait ce sélecteur : 0-1-2 bat la règle de lien au repos
   (0-1-1) et se laisse battre par le survol (0-2-1). */
.s411-footer-col a.s411-footer-tel {
    font-family: var(--wp--preset--font-family--display);
    font-size: var(--wp--preset--font-size--large);
    font-weight: 400;
    letter-spacing: -.015em;
    line-height: 1.3;
    font-variant-numeric: tabular-nums;
    color: var(--wp--preset--color--contrast);
}

.s411-footer-bas {
    display: flex; flex-wrap: wrap; gap: var(--wp--preset--spacing--20);
    justify-content: space-between; align-items: center;
    padding-top: var(--wp--preset--spacing--30);
    border-top: 1px solid var(--wp--preset--color--rule);
    /* MENTION. Le gris clair à 13 px sur le gris du pied donnait 2,78:1 : ce
       n'était pas discret, c'était illisible. */
    font-size: var(--wp--preset--font-size--x-small);
    line-height: 1.65;
    color: var(--wp--preset--color--ink-2);
}
.s411-footer-bas p { margin: 0; max-width: none; }
.s411-footer-legal { display: flex; flex-wrap: wrap; gap: var(--wp--preset--spacing--20); }
.s411-footer-legal a {
    color: var(--wp--preset--color--ink-2);
    text-decoration: none;
    transition: color .2s ease;
}
.s411-footer-legal a:hover { color: var(--wp--preset--color--contrast); }

@media (max-width: 1000px) {
    .s411-footer-haut { grid-template-columns: 1fr; }
    .s411-footer-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
    .s411-footer-cols { grid-template-columns: 1fr; }
}


/* ---------- divers -------------------------------------------------------- */

.wp-block-table { overflow-x: auto; }
.wp-block-table table { min-width: 480px; }
.wp-block-post-title a { text-decoration: none; color: inherit; }
.wp-block-post-title a:hover { color: var(--wp--preset--color--magenta-text); }




/* ---------- contenu de page ---------------------------------------------- */

/* Le rythme de page : un seul écart entre deux blocs, spacing-40. */
.s411-contenu > * + * { margin-top: var(--wp--preset--spacing--40); }
/* Sauf pour un bloc qui porte son propre filet : il porte aussi son propre
   blanc, et le rythme ne s'y ajoute pas. Sans cela deux sources s'empilent,
   le filet se retrouve à 108 px du texte du dessus et à 64 px de celui du
   dessous, et c'est le plus gros déséquilibre de la page studio.
   C'est aussi ce qui obligeait patterns/page-studio.php à écrire un
   style="margin-top:3rem" en ligne, au poids le plus lourd de la chaîne CSS,
   pour déplacer un titre de quatre pixels : ce style en ligne peut partir. */
.s411-contenu > * + .s411-detail,
.s411-contenu > * + .s411-point,
.s411-contenu > * + .s411-questions { margin-top: 0; }

/* PUCE DE LISTE. Retrait et respiration sur le barème, et identiques à ceux de
   .s411-offer-features : les deux listes se suivent sur la page coworking. */
.s411-liste { list-style: none; margin: 0 0 var(--wp--preset--spacing--30); padding: 0; }
.s411-liste li {
    position: relative;
    padding: 0 0 var(--wp--preset--spacing--10) var(--wp--preset--spacing--20);
    line-height: 1.65;
    color: var(--wp--preset--color--ink-2);
}
/* Une flèche, pas un filet : le tiret se lisait comme une ponctuation, et
   la flèche pointe vers l'élément, ce qu'une puce est censée faire. */
.s411-liste li::before {
    content: '\2192';
    position: absolute; left: 0; top: 0;
    line-height: 1.65;
    color: var(--wp--preset--color--magenta);
}
.s411-liste strong { color: var(--wp--preset--color--contrast); font-weight: 600; }

/* ---------- page de réservation -----------------------------------------
   Le tunnel n'a pas besoin de 1 780 px de large, mais il n'a pas à vivre sur
   un axe à lui. En le centrant, la page se retrouvait avec cinq bords
   gauches : le logo à 312, le hero à 662, le chapô à 785, les tableaux à 312.
   Il garde donc sa mesure, calé à gauche sur l'axe du site, et ce qui reste
   à sa droite porte les informations pratiques au lieu de rester blanc.
------------------------------------------------------------------------- */

.s411-reserver {
    display: grid;
    grid-template-columns: minmax(0, 1080px) minmax(0, 1fr);
    gap: var(--wp--preset--spacing--50);
    align-items: start;
}
.s411-reserver-tunnel {
    min-width: 0;
    /* La gouttière propre du tunnel ferait doublon : le groupe qui le porte
       a déjà la marge de la page. */
    --s411-tunnel-gouttiere: 0px;
}
.s411-reserver-cote { min-width: 0; }

/* Dans une colonne étroite, la bande de repères se remet en pile et l'encadré
   repasse en deux zones. Les points de rupture du site sont calés sur la
   fenêtre, pas sur le conteneur : ils ne verraient pas cette colonne. */
.s411-reserver-cote .s411-facts {
    grid-template-columns: 1fr;
    margin-top: 0;
}
.s411-reserver-cote .s411-fact { padding-right: 0; }
.s411-reserver-cote .s411-fact + .s411-fact {
    padding-left: 0;
    border-left: 0;
}
.s411-reserver-cote .s411-point {
    grid-template-columns: auto minmax(0, 1fr);
    border-bottom: 0;
}
.s411-reserver-cote .s411-point-titre,
.s411-reserver-cote .s411-point-corps { grid-column: 2; }
.s411-reserver-cote .s411-point-corps { grid-template-columns: 1fr; }
.s411-reserver-cote .s411-point-corps > p { max-width: none; }

@media (max-width: 1400px) {
    .s411-reserver { grid-template-columns: 1fr; }
    .s411-reserver-cote .s411-facts { grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
    .s411-reserver-cote .s411-fact { padding-right: var(--wp--preset--spacing--30); }
    .s411-reserver-cote .s411-fact + .s411-fact {
        padding-left: var(--wp--preset--spacing--30);
        border-left: 1px solid var(--wp--preset--color--rule);
    }
}


/* ---------- contenu écrit dans l'éditeur ---------------------------------
   Les sections du site étaient fabriquées par des fonctions PHP : la mise en
   forme et les mots vivaient dans le même fichier, et changer une horaire
   demandait de toucher au thème. Ce n'est pas tenable pour un site que
   quelqu'un d'autre doit remplir.

   Les mêmes sections s'écrivent maintenant en blocs WordPress ordinaires, qui
   portent les classes du thème. Les règles ci-dessous sont les équivalences
   nécessaires : un <dl> devient un groupe de paragraphes, un <details> maison
   devient le bloc natif, et le picto de l'encadré passe en CSS pour qu'aucun
   bloc de code brut ne traîne sous les yeux de la personne qui écrit.

   Les anciennes formes restent stylées : des pages les portent encore.
------------------------------------------------------------------------- */

/* La bande de repères, écrite en paragraphes plutôt qu'en liste de
   définitions. Mêmes rôles, mêmes valeurs que dt et dd. */
.s411-fact-nom {
    font-family: var(--wp--preset--font-family--body);
    font-size: var(--wp--preset--font-size--x-small);
    font-weight: 600;
    letter-spacing: .2em;
    line-height: 1.4;
    text-transform: uppercase;
    color: var(--wp--preset--color--ink-2);
    margin: 0 0 var(--wp--preset--spacing--10);
    max-width: none;
}
.s411-fact-valeur {
    margin: 0;
    max-width: none;
    font-family: var(--wp--preset--font-family--display);
    font-size: var(--wp--preset--font-size--large);
    font-weight: 400;
    letter-spacing: -.015em;
    line-height: 1.2;
    color: var(--wp--preset--color--contrast);
}

/* Le bloc natif « détails » place sa réponse en enfant direct, là où la
   version maison l'enveloppait dans un div. La règle vaut pour les deux. */
.s411-question > :not(summary) {
    font-size: var(--wp--preset--font-size--medium);
    line-height: 1.65;
    color: var(--wp--preset--color--ink-2);
    padding: 0 0 var(--wp--preset--spacing--30);
}
.s411-question > :not(summary) > p { margin: 0 0 var(--wp--preset--spacing--20); }
.s411-question > :not(summary) > p:last-child { margin-bottom: 0; }
.s411-question > p { margin: 0 0 var(--wp--preset--spacing--20); max-width: 64ch; }
.s411-question > p:last-child { margin-bottom: 0; }

/* Le picto de l'encadré, en CSS quand aucun bloc ne le porte : un bloc de
   code brut au milieu d'un texte à écrire, c'est la première chose que la
   personne qui remplit le site casserait sans le vouloir. */
.s411-point:not(:has(.s411-point-icone))::before {
    content: '';
    grid-column: 1;
    width: 1.7rem;
    height: 1.7rem;
    margin-top: .15rem;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23e6007e' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9.2'/%3E%3Cpath d='M12 11.2v5.4'/%3E%3Cpath d='M12 7.6h.01'/%3E%3C/svg%3E") center / contain no-repeat;
}


/* ---------- espace artiste ----------------------------------------------
   Ce n'est pas une page qu'on lit, c'est un écran de travail : on y revient
   pour déposer une pièce ou suivre son dossier. Le hero de 384 px y prenait
   la moitié de la première fenêtre sans rien apprendre à personne, et
   repoussait les onglets hors de vue.

   Il devient une bande : plus de hauteur minimale, le rembourrage haut juste
   ce qu'il faut pour passer sous l'en-tête fixe, et un titre à la mesure d'un
   intitulé d'écran plutôt qu'à celle d'une couverture.
------------------------------------------------------------------------- */

body:has(.s411d-espace) .s411-pagehero {
    min-height: 0;
    padding-top: calc(var(--s411-entete-h) + var(--wp--preset--spacing--20));
    padding-bottom: var(--wp--preset--spacing--30);
}
body:has(.s411d-espace) .s411-pagehero h1,
body:has(.s411d-espace) .s411-pagehero-titre {
    font-size: clamp(1.7rem, 3vw, 2.6rem);
    line-height: 1.05;
}
/* Le hero étant plus court, l'en-tête doit basculer plus tôt : sinon il reste
   blanc alors que le dégradé est déjà passé. */
body:has(.s411d-espace) { --s411-bascule: 170px; }

/* La largeur de l'espace de travail appartient à l'extension, qui la fixe à
   1 440 px et verrouille la règle avec une double classe. Le thème n'y touche
   pas : une règle qui perd aujourd'hui et gagnerait le jour où cette double
   classe disparaît est un piège, pas un réglage. */


/* ---------- actualité Instagram ------------------------------------------
   Deux zones : le texte à gauche, la grille à droite, sur la même mesure que
   les autres blocs à deux colonnes du site. Les vignettes sont carrées et
   sans arrondi, comme les cartes d'offre : c'est le filet dégradé qui signe,
   pas le coin rond.

   Les images sont servies depuis le domaine du site, jamais depuis le réseau
   de diffusion de Meta : le visiteur ne demande rien à Instagram.
------------------------------------------------------------------------- */

.s411-insta {
    display: grid;
    grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
    gap: var(--wp--preset--spacing--50);
    align-items: start;
    padding: var(--wp--preset--spacing--40) 0;
    border-top: 1px solid var(--wp--preset--color--rule);
    border-bottom: 1px solid var(--wp--preset--color--rule);
}
/* La colonne de texte est un groupe écrit dans la page ; la grille arrive du
   shortcode, en second enfant. */
.s411-insta > .s411-insta-texte { min-width: 0; }
.s411-insta > .wp-block-shortcode { margin: 0; }

/* Le bandeau d'appel écrit en blocs : mêmes classes, mêmes rôles. */
.s411-appel .wp-block-buttons { gap: var(--wp--preset--spacing--20); }
.s411-appel .wp-block-button__link { white-space: nowrap; }
.s411-appel .is-style-s411-clair .wp-block-button__link {
    background: #fff;
    color: var(--wp--preset--color--contrast);
}
.s411-appel .is-style-s411-clair .wp-block-button__link:hover {
    background: var(--wp--preset--color--contrast);
    color: #fff;
}
.s411-appel .is-style-outline .wp-block-button__link {
    background: transparent;
    color: #fff;
    border: 1.5px solid rgba(255, 255, 255, .7);
}
.s411-appel .is-style-outline .wp-block-button__link:hover {
    background: #fff;
    color: var(--wp--preset--color--contrast);
    border-color: #fff;
}

.s411-insta-sur {
    font-family: var(--wp--preset--font-family--body);
    font-size: var(--wp--preset--font-size--x-small);
    font-weight: 600; letter-spacing: .2em; line-height: 1.4;
    text-transform: uppercase;
    color: var(--wp--preset--color--magenta);
    margin: 0 0 var(--wp--preset--spacing--10);
}
.s411-insta-titre {
    font-family: var(--wp--preset--font-family--display);
    font-weight: 400; text-transform: uppercase; letter-spacing: -.02em;
    line-height: 1.12;
    font-size: clamp(1.6rem, 2.4vw, 2.4rem);
    color: var(--wp--preset--color--contrast);
    margin: 0 0 var(--wp--preset--spacing--20);
}
.s411-insta-texte {
    font-size: var(--wp--preset--font-size--medium);
    line-height: 1.65;
    color: var(--wp--preset--color--ink-2);
    max-width: 38ch;
    margin: 0 0 var(--wp--preset--spacing--30);
}

.s411-insta-grille {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--wp--preset--spacing--20);
}

.s411-insta-vignette {
    position: relative;
    display: block;
    aspect-ratio: 1 / 1;
    overflow: hidden;
    background: var(--wp--preset--color--surface);
    text-decoration: none;
}
.s411-insta-vignette img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
    transition: transform .5s cubic-bezier(.16, 1, .3, 1);
}
.s411-insta-vignette:hover img { transform: scale(1.06); }

/* Un filet dégradé se révèle en haut au survol, comme sur les cartes du
   tunnel : c'est le seul accent dépensé ici. */
.s411-insta-vignette::before {
    content: '';
    position: absolute;
    inset: 0 0 auto;
    height: 3px;
    z-index: 2;
    background: var(--wp--preset--gradient--quadri);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .3s ease;
}
.s411-insta-vignette:hover::before { transform: scaleX(1); }
.s411-insta-vignette:focus-visible {
    outline: 3px solid var(--wp--preset--color--cyan);
    outline-offset: 3px;
}

/* La légende ne s'affiche qu'au survol : une grille de vignettes se lit
   d'abord comme des images, pas comme un mur de texte. */
.s411-insta-legende {
    position: absolute;
    inset: auto 0 0 0;
    padding: var(--wp--preset--spacing--20);
    font-size: var(--wp--preset--font-size--x-small);
    line-height: 1.45;
    color: #fff;
    background: linear-gradient(180deg, rgba(11, 15, 20, 0) 0%, rgba(11, 15, 20, .88) 100%);
    opacity: 0;
    transform: translateY(8px);
    transition: opacity .3s ease, transform .3s ease;
}
.s411-insta-vignette:hover .s411-insta-legende,
.s411-insta-vignette:focus-visible .s411-insta-legende { opacity: 1; transform: none; }

/* En attendant que le compte soit relié : la place que les images prendront,
   dans la matière de la maison plutôt qu'un carré gris. */
.s411-insta-vignette--vide {
    background: var(--wp--preset--gradient--quadri);
    background-size: 220% 220%;
    animation: s411-derive 18s linear infinite alternate;
    opacity: .28;
}
.s411-insta-vignette--vide:hover { opacity: .45; }

@media (max-width: 1000px) {
    .s411-insta { grid-template-columns: 1fr; }
}
@media (max-width: 520px) {
    .s411-insta-grille { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (prefers-reduced-motion: reduce) {
    .s411-insta-vignette img,
    .s411-insta-vignette::before,
    .s411-insta-legende { transition: none; }
    .s411-insta-vignette--vide { animation: none; }
}


/* ---------- tarifs -------------------------------------------------------- */

/* Le bloc tableau natif rend une <figure class="wp-block-table"> : les mêmes
   règles servent aux deux formes, l'ancienne en div et la nouvelle en figure.
   La figure porte en plus une marge par défaut dont on ne veut pas. */
figure.s411-tarifs { margin: 0; }
.s411-tarifs-bloc { margin: var(--wp--preset--spacing--30) 0; }
.s411-tarifs-bloc > * + * { margin-top: 0; }

.s411-tarifs {
    overflow-x: auto;
    border: 1px solid var(--wp--preset--color--rule);
    border-radius: 14px;
    background: var(--wp--preset--color--base);
}
/* Deux tableaux se suivent sur la page du studio. Sans largeurs fixées,
   chacun calait ses colonnes sur son propre contenu : la colonne du milieu
   tombait à deux endroits différents, et l'en-tête « Tarif TTC », aligné à
   gauche, flottait loin des prix alignés à droite. */
.s411-tarifs table {
    border-collapse: collapse;
    width: 100%;
    min-width: 460px;
    table-layout: fixed;
}
.s411-tarifs th:first-child  { width: 34%; }
.s411-tarifs th:nth-child(2) { width: 46%; }
.s411-tarifs th:last-child   { width: 20%; text-align: right; }
/* LIBELLÉ. Le gris clair sur le gris de l'en-tête donnait 2,78:1. */
.s411-tarifs th {
    text-align: left;
    font-family: var(--wp--preset--font-family--body);
    font-size: var(--wp--preset--font-size--x-small);
    font-weight: 600; letter-spacing: .2em; line-height: 1.4;
    text-transform: uppercase;
    color: var(--wp--preset--color--ink-2);
    padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
    background: var(--wp--preset--color--surface);
    white-space: nowrap;
}
/* TEXTE DE CADRE. Couleur déclarée : c'était l'un des quatre endroits où
   l'encre arrivait par omission. */
.s411-tarifs td {
    padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
    border-top: 1px solid var(--wp--preset--color--rule);
    font-size: var(--wp--preset--font-size--small);
    color: var(--wp--preset--color--ink-2);
    line-height: 1.65;
}
.s411-tarifs tbody tr:hover { background: var(--wp--preset--color--surface); }
/* VALEUR EN LIGNE, et correction du conflit de spécificité : .s411-tarif-prix
   pesait 0-1-0 contre 0-1-1 pour .s411-tarifs td, et la cellule gagnait quelle
   que soit la position dans le fichier. Le prix était écrit à 22 px et rendu à
   16, c'est-à-dire à la taille exacte du texte du tableau, dans la seule
   colonne que les gens viennent chercher. Le sélecteur pèse maintenant 0-2-1.
   Encre et non magenta : la ligne passe au gris #f4f6f8 au survol, où le
   magenta retombe à 4,15:1. La différence se fait à la police, à l'alignement
   et aux chiffres tabulaires, pas à la couleur. */
.s411-tarifs td.s411-tarif-prix {
    font-family: var(--wp--preset--font-family--display);
    font-size: var(--wp--preset--font-size--large);
    font-weight: 400;
    letter-spacing: -.015em;
    line-height: 1.3;
    color: var(--wp--preset--color--contrast);
    white-space: nowrap;
    text-align: right;
    font-variant-numeric: tabular-nums;
}
/* MENTION. La note appartient à son tableau : elle garde un écart plus serré
   que le rythme de page, mais sur un palier du barème et non à 14 px gagnés
   par accident d'ordre dans le fichier. */
.s411-tarifs-note {
    margin: var(--wp--preset--spacing--20) 0 0;
    max-width: none;
    font-size: var(--wp--preset--font-size--x-small);
    color: var(--wp--preset--color--ink-2);
    line-height: 1.65;
}

/* ---------- questions fréquentes ----------------------------------------
   La question devient un vrai titre et la réponse un vrai texte : la
   première version les traitait comme des libellés d'interface, ce qui les
   faisait passer pour du remplissage alors que ce sont les informations que
   les gens cherchent en premier.
------------------------------------------------------------------------- */

.s411-questions {
    border-top: 1px solid var(--wp--preset--color--rule);
}
.s411-question { border-bottom: 1px solid var(--wp--preset--color--rule); }
.s411-question summary {
    cursor: pointer;
    list-style: none;
    padding: var(--wp--preset--spacing--30) 72px var(--wp--preset--spacing--30) 0;
    position: relative;
    font-family: var(--wp--preset--font-family--display);
    /* TITRE DE CARTE. Il n'est pas un <h*>, il se retrouvait donc à
       interlettrage nul, seul de tous les titres du site avec l'encadré.
       La casse reste naturelle : une phrase interrogative en capitales ne se
       lit plus. C'est la seule exception de casse de la grammaire, et elle est
       écrite ici plutôt que constatée. */
    font-size: var(--wp--preset--font-size--large);
    font-weight: 400;
    letter-spacing: -.015em;
    line-height: 1.12;
    color: var(--wp--preset--color--contrast);
    transition: color .25s ease;
}
.s411-question summary::-webkit-details-marker { display: none; }
.s411-question summary:hover { color: var(--wp--preset--color--magenta-text); }

/* Le signe est construit en CSS : il pivote, et il reste net à toute taille. */
.s411-question summary::after,
.s411-question summary::before {
    content: '';
    position: absolute; right: 8px; top: 50%;
    width: 20px; height: 2.5px; border-radius: 3px;
    background: var(--wp--preset--color--magenta);
    transition: transform .3s cubic-bezier(.16, 1, .3, 1);
}
.s411-question summary::before { transform: translateY(-50%) rotate(90deg); }
.s411-question summary::after  { transform: translateY(-50%); }
.s411-question[open] summary::before { transform: translateY(-50%) rotate(0deg); }
.s411-question[open] summary { color: var(--wp--preset--color--magenta-text); }

.s411-question > div {
    /* Le bas valait 30 px contre 28 en haut : une question ouverte était
       asymétrique de deux pixels sans que rien ne le demande. */
    padding: 0 72px var(--wp--preset--spacing--30) 0;
    font-size: var(--wp--preset--font-size--medium);
    line-height: 1.65;
    color: var(--wp--preset--color--ink-2);
    max-width: 62ch;
}
.s411-question > div p { margin: 0 0 var(--wp--preset--spacing--20); }
.s411-question > div p:last-child { margin-bottom: 0; }
.s411-question > div a { color: var(--wp--preset--color--cyan-text); }

/* La première réponse est ouverte : un bloc entièrement replié ressemble à
   une liste de liens morts, et personne ne clique pour voir. */


/* =========================================================================
   MOUVEMENT

   Deux partis pris tenus ensemble.

   TYPOGRAPHIQUE : le texte ne se fond pas, il se dévoile. Un mot monte
   depuis sous une fenêtre qui le coupe, un titre se découvre de haut en bas
   comme on tire un rideau. Le site est en Archivo Black capitales : cette
   masse mérite mieux qu'un changement d'opacité.

   CINÉTIQUE : le défilement est le moteur. Les couches ne vont pas à la même
   vitesse, ce qui crée une profondeur réelle plutôt qu'une suite de blocs
   qui glissent ensemble.

   Amplitude : volontairement franche. Deux versions précédentes bougeaient
   de 2 rem et se lisaient comme figées. Ici on parle de plusieurs rem, de
   découpes complètes et d'échelles à 1,2. Mieux vaut corriger vers le bas
   qu'imaginer un mouvement qui n'existe pas.

   Garde-fous : tout est enfermé dans @supports et @media. Là où la
   fonctionnalité manque ou si le visiteur demande moins d'animations, aucune
   règle ne s'applique et le contenu reste simplement visible. Rien n'est
   jamais parqué à opacity: 0 en attendant un déclencheur.
   ========================================================================= */

/* ---------- 1. le mot qui monte sous son masque -------------------------- */

.s411-mot {
    display: inline-block;
    overflow: hidden;          /* c'est LUI qui coupe le mot */
    vertical-align: bottom;
    /* Marge négative compensée : sans elle, le masque rogne les jambages
       des lettres descendantes une fois l'animation terminée. */
    padding-bottom: .12em;
    margin-bottom: -.12em;
}
.s411-mot > span {
    display: inline-block;
    animation: s411-monte-masque 1s cubic-bezier(.16, 1, .3, 1) both;
}
@keyframes s411-monte-masque {
    /*
     * Le déplacement doit dépasser la hauteur du mot ET la marge intérieure
     * basse du masque, sinon le haut des lettres reste visible au repos.
     * Mesuré : 8,2 px dépassaient avec 110 %.
     *
     * Le terme en `em` couvre cette marge, et la rotation initiale : sur un
     * mot large, deux degrés soulèvent déjà le coin de plusieurs pixels.
     * Exprimer la marge en `em` la fait suivre le corps du texte, qui va de
     * 2,5 rem à 7 rem selon la largeur de la fenêtre.
     */
    from { transform: translateY(calc(100% + 0.5em)) rotate(2deg); }
    to   { transform: translateY(0) rotate(0); }
}

/* ---------- 2. le rideau sur les titres ---------------------------------
   clip-path plutôt qu'un second niveau d'éléments : ces titres viennent de
   l'éditeur ou des briques PHP, on ne peut pas y injecter des spans partout.
   Un inset animé se compose sur le GPU et ne demande aucun balisage.
------------------------------------------------------------------------- */

@keyframes s411-rideau {
    from { clip-path: inset(0 0 105% 0); transform: translateY(.35em); }
    to   { clip-path: inset(0 0 -25% 0); transform: none; }
}
@keyframes s411-monte-large {
    from { opacity: 0; transform: translate3d(0, 4.5rem, 0); }
    to   { opacity: 1; transform: none; }
}
@keyframes s411-arrive-cote {
    from { opacity: 0; transform: translate3d(-3rem, 0, 0); }
    to   { opacity: 1; transform: none; }
}
@keyframes s411-ouvre {
    from { opacity: 0; transform: scale(.9) translate3d(0, 3rem, 0); }
    to   { opacity: 1; transform: none; }
}

/* ---------- 3. parallaxe et échelle -------------------------------------- */

@keyframes s411-parallaxe        { from { transform: translate3d(0,  9%, 0); } to { transform: translate3d(0, -9%, 0); } }
@keyframes s411-parallaxe-contre { from { transform: translate3d(0, -14%, 0) scale(.92); } to { transform: translate3d(0, 14%, 0) scale(1.08); } }
@keyframes s411-zoom-sortie      { from { transform: scale(1.2); } to { transform: scale(1.02); } }
@keyframes s411-hero-sort        { to { opacity: 0; transform: translate3d(0, -7rem, 0); } }
@keyframes s411-jauge { from { --s411-jauge: 0; } to { --s411-jauge: 1; } }

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    /* --- titres : le rideau --- */
    .s411-detail-titre,
    .s411-appel-titre,
    .s411-offer-name,
    .s411-footer-phrase,
    .s411-tuile-titre {
        animation: s411-rideau linear both;
        animation-timeline: view();
        animation-range: entry 5% cover 22%;
    }

    /* --- corps de texte : montée franche, décalée --- */
    .s411-detail-texte > p,
    .s411-detail-texte > .s411-liste,
    .s411-detail-texte > .s411-bouton,
    .s411-detail-sur,
    .is-style-s411-eyebrow,
    .s411-appel-texte,
    .s411-appel-actions,
    .s411-facts,
    .s411-tarifs,
    .s411-questions,
    .s411-caveat,
    .s411-footer-col {
        animation: s411-monte-large linear both;
        animation-timeline: view();
        animation-range: entry 4% cover 24%;
    }
    /* Le surtitre annonce ce qui vient : il entre juste avant, pas en même
       temps. Il arrivait tout fait au-dessus de tuiles encore à moitié
       montées, ce qui donnait une section à moitié écrite. */
    .is-style-s411-eyebrow { animation-range: entry 2% cover 17%; }

    .s411-detail-texte > *:nth-child(3) { animation-range: entry 8% cover 27%; }
    .s411-detail-texte > *:nth-child(4) { animation-range: entry 11% cover 29%; }
    .s411-detail-texte > *:nth-child(5) { animation-range: entry 14% cover 31%; }
    .s411-detail-texte > *:nth-child(6) { animation-range: entry 17% cover 33%; }
    .s411-footer-col:nth-child(2) { animation-range: entry 7% cover 27%; }
    .s411-footer-col:nth-child(3) { animation-range: entry 10% cover 29%; }

    /* --- listes : arrivée latérale, item par item --- */
    .s411-liste li,
    .s411-offer-features li {
        animation: s411-arrive-cote linear both;
        animation-timeline: view();
        animation-range: entry 3% cover 20%;
    }
    .s411-liste li:nth-child(2), .s411-offer-features li:nth-child(2) { animation-range: entry 6% cover 22%; }
    .s411-liste li:nth-child(3), .s411-offer-features li:nth-child(3) { animation-range: entry 9% cover 24%; }
    .s411-liste li:nth-child(4), .s411-offer-features li:nth-child(4) { animation-range: entry 12% cover 26%; }
    .s411-liste li:nth-child(5), .s411-offer-features li:nth-child(5) { animation-range: entry 15% cover 28%; }

    /* --- tuiles : elles s'ouvrent au lieu de monter ---
       Six montées simultanées se lisent comme un seul bloc qui glisse ;
       une ouverture décalée fait exister chaque tuile séparément. */
    .s411-tuile, .s411-offer, .s411-chiffre {
        animation: s411-ouvre linear both;
        animation-timeline: view();
        animation-range: entry 3% cover 21%;
    }
    /*
     * Les trois offres de coworking arrivent ENSEMBLE, sans décalage.
     * Ailleurs le décalage donne du rythme, mais ici on compare trois
     * formules côte à côte : le moindre écart entre leurs hauts se lit comme
     * un défaut d'alignement, pas comme une élégance. Mesuré : 28 px de
     * décrochage suffisaient à casser la lecture comparative.
     */
    .s411-offer { animation-range: entry 3% cover 21%; }
    .s411-tuile:nth-child(2), .s411-chiffre:nth-child(2) { animation-range: entry 6% cover 23%; }
    .s411-tuile:nth-child(3), .s411-chiffre:nth-child(3) { animation-range: entry 9% cover 25%; }
    .s411-tuile:nth-child(4), .s411-chiffre:nth-child(4) { animation-range: entry 12% cover 27%; }
    .s411-tuile:nth-child(5) { animation-range: entry 15% cover 29%; }
    .s411-tuile:nth-child(6) { animation-range: entry 18% cover 31%; }

    /* --- parallaxe : les couches ne vont pas à la même vitesse ---
       C'est ce décalage qui crée la profondeur. Sans lui, tout glisse
       ensemble et le défilement reste plat. La plage `cover` couvre toute la
       traversée de la fenêtre, sinon le mouvement s'arrête en pleine vue. */
    .s411-detail-media {
        animation: s411-parallaxe linear both;
        animation-timeline: view();
        animation-range: cover;
    }
    /* Le grand numéro dérive à contresens du bloc qui le porte : deux
       vitesses opposées dans le même cadre, la profondeur devient lisible. */
    .s411-detail-numero {
        animation: s411-parallaxe-contre linear both;
        animation-timeline: view();
        animation-range: cover;
    }
    .s411-tuile-image {
        animation: s411-zoom-sortie linear both;
        animation-timeline: view();
        animation-range: cover;
    }

    /* --- le hero s'efface en montant plus vite que la page --- */
    .s411-hero-inner {
        animation: s411-hero-sort linear both;
        animation-timeline: view();
        animation-range: exit -10% exit 90%;
    }
  }
}

/* ---------- 4. jauge de lecture ------------------------------------------
   Le filet de marque sous l'en-tête devient une barre de progression. Pilotée
   par scroll() et non view() : elle mesure la page entière, pas le passage
   d'un élément. Transform seul, donc aucun recalcul de mise en page.
------------------------------------------------------------------------- */

@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .s411-header::after {
        transform-origin: left center;
        transform: scaleX(var(--s411-jauge));
    }
    /* Au-dessus d'un hero l'en-tête n'a pas de filet : on le rétablit, en
       jauge seulement, pour que le repère de lecture existe aussi là. Il est
       blanc tant qu'il court sur le dégradé, puis le voile s'efface et c'est
       le dégradé de la marque qui prend le relais sur le fond blanc. */
    body:has(.s411-hero, .s411-pagehero) .s411-header::after {
        display: block;
        top: auto; bottom: 0;
        height: 3px;
        background-image:
            linear-gradient(var(--s411-jauge-voile), var(--s411-jauge-voile)),
            var(--wp--preset--gradient--quadri);
    }
  }
}

/* ---------- 5. survols ---------------------------------------------------- */

.s411-bouton, .s411-hero-cta, .s411-hero-ghost, .s411-header-cta {
    transition: transform .3s cubic-bezier(.16, 1, .3, 1),
                background .3s ease, color .3s ease,
                border-color .3s ease, filter .3s ease;
}
.s411-bouton:hover, .s411-header-cta:hover { transform: translateY(-3px) scale(1.02); }

/* Le titre d'une tuile avance légèrement au survol : la carte entière
   répond, pas seulement son ombre. */
.s411-tuile-titre { transition: transform .4s cubic-bezier(.16, 1, .3, 1); }
.s411-tuile:hover .s411-tuile-titre { transform: translateX(.35rem); }

@media (prefers-reduced-motion: reduce) {
    .s411-mot > span { animation: none; transform: none; }
    .s411-bouton:hover, .s411-header-cta:hover,
    .s411-tuile:hover .s411-tuile-titre { transform: none; }
}

/* ---------- newsletter ---------------------------------------------------
   Elle ouvre le pied de page au lieu de le fermer : reléguée sous les
   coordonnées et les horaires, elle arrivait après que tout a été dit, au
   moment où plus personne ne lit.

   Le dégradé de la bande ne va pas jusqu'au cyan pur. Du blanc sur #009fe3
   ne donne que 2,97:1, ce qui ne porte aucun texte. En poussant l'arrivée du
   dégradé à 155 %, la bande s'arrête bien avant : son point le plus clair
   mesure 4,76:1, et son départ magenta 4,50:1. Tout le texte blanc posé
   dessus est donc conforme, sans avoir changé les deux encres de la marque.

   Et pas d'animation ici, contrairement au filet du hero : un fond qui dérive
   fait varier le contraste du texte qu'il porte.
------------------------------------------------------------------------- */

.s411-newsletter {
    /* Le pied de page est un groupe « contrained » : sans ça, WordPress
       plafonne ses enfants à la largeur de contenu et la bande cesserait
       d'être une bande. */
    max-width: none;
    background: linear-gradient(110deg, #e6007e 0%, #009fe3 155%);
    color: #fff;
}
@supports (background: linear-gradient(in oklch, red, blue)) {
    .s411-newsletter {
        background: linear-gradient(110deg in oklch, #e6007e 0%, #009fe3 155%);
    }
}

.s411-newsletter-inner {
    max-width: 1780px;
    margin: 0 auto;
    padding: var(--wp--preset--spacing--40) clamp(1.25rem, 4vw, 4.5rem);
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    column-gap: var(--wp--preset--spacing--50);
    row-gap: 12px;
    /* `start` et non `center` : centrer dans des rangées hautes écartait le
       titre de sa phrase et la case à cocher de sa saisie, de plus de cent
       pixels. Chaque élément se cale en haut de sa rangée. */
    align-items: start;
}

/* Le formulaire hérite de la grille : le texte à gauche, la saisie à droite. */
.s411-newsletter .s411-nl {
    display: contents;
    max-width: none;
}
.s411-newsletter .s411-nl-titre {
    grid-column: 1; grid-row: 1;
    font-family: var(--wp--preset--font-family--display);
    font-size: clamp(1.6rem, 2.8vw, 2.6rem);
    line-height: 1;
    letter-spacing: -.02em;
    text-transform: uppercase;
    color: #fff;
    margin: 0;
}
.s411-newsletter .s411-nl-texte {
    grid-column: 1; grid-row: 2;
    margin: 0;
    font-size: var(--wp--preset--font-size--small);
    line-height: 1.55;
    color: #fff;
    max-width: 38ch;
}
.s411-newsletter .s411-nl-ligne {
    grid-column: 2; grid-row: 1;
    margin: 0;
}
.s411-newsletter .s411-nl-consent {
    grid-column: 2; grid-row: 2;
    margin: 0;
    /* Mesuré sur la bande : 6,14:1 au début de la ligne, 5,57:1 à sa fin.
       Le blanc pur, donc, et pas une transparence qui raboterait ça. */
    /* MENTION. Écrite 13 px dans booking.css et rendue 16 ici : les deux
       feuilles s'accordent sur le jeton du rôle. Mesuré sur la bande :
       6,14:1 au début de la ligne, 5,57:1 à sa fin. */
    color: #fff;
    font-size: var(--wp--preset--font-size--x-small);
    line-height: 1.65;
}
.s411-newsletter .s411-nl-retour {
    grid-column: 2; grid-row: 3;
    margin: 10px 0 0;
}
.s411-newsletter .s411-nl-email {
    border-color: transparent;
    box-shadow: 0 10px 30px -22px rgba(11, 15, 20, .8);
}
.s411-newsletter .s411-nl-email:focus { border-color: #fff; }

/* Sur le dégradé, le bouton s'inverse : le blanc est ce qui ressort le mieux
   d'un fond coloré, et c'est déjà ce que fait le bouton de l'en-tête posé
   dans un hero. Encre sur blanc, 18,9:1. */
.s411-newsletter .s411-nl-envoi {
    background: #fff;
    color: var(--wp--preset--color--contrast);
}
.s411-newsletter .s411-nl-envoi:hover:not(:disabled) {
    background: var(--wp--preset--color--contrast);
    color: #fff;
    filter: none;
}
.s411-newsletter .s411-nl-consent input { accent-color: #fff; }
.s411-newsletter .s411-hp { position: absolute; }

@media (max-width: 900px) {
    .s411-newsletter-inner { grid-template-columns: 1fr; gap: var(--wp--preset--spacing--30); }
    .s411-newsletter .s411-nl-titre,
    .s411-newsletter .s411-nl-texte,
    .s411-newsletter .s411-nl-ligne,
    .s411-newsletter .s411-nl-consent,
    .s411-newsletter .s411-nl-retour { grid-column: 1; grid-row: auto; }
}



/* ---------- transition entre les pages ----------------------------------
   API View Transitions, en document croisé. Pas une ligne de JavaScript :
   le navigateur photographie la page qu'on quitte, celle qui arrive, et
   anime le passage de l'une à l'autre. Là où elle n'existe pas, la
   navigation reste ce qu'elle était, sans rustine ni chargeur factice.

   L'opt-in est dans une requête de média : sous « mouvement réduit », la
   transition n'est pas désactivée après coup, elle n'est jamais déclarée.

   Deux réglages font la différence entre un vrai fondu et un éclair blanc.

   Le premier est le mélange. Par défaut le navigateur superpose les deux
   images en `plus-lighter`, qui les additionne : c'est juste tant que les
   deux ne bougent pas, mais dès qu'elles glissent l'une par rapport à
   l'autre, la zone de recouvrement s'éclaircit et on voit passer du blanc.
   En mélange normal, la page qui arrive se pose simplement par-dessus celle
   qui part, et il n'y a plus rien à éclaircir.

   Le second est que la page sortante garde son opacité jusqu'au bout. Si
   elle s'efface pendant que l'autre apparaît, il y a un instant où aucune
   des deux n'est opaque, et c'est le fond du document qu'on voit au travers.
   Elle reste donc entière, et c'est la nouvelle qui se révèle par-dessus.
------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {

    @view-transition {
        navigation: auto;
    }

    /* Sans isolation, le mélange choisi plus bas n'a aucun effet : la paire
       d'images est isolée par défaut pour que `plus-lighter` fonctionne. */
    ::view-transition-image-pair(root) { isolation: auto; }

    ::view-transition-old(root),
    ::view-transition-new(root) {
        mix-blend-mode: normal;
        animation-duration: .5s;
        animation-fill-mode: both;
    }

    ::view-transition-old(root) {
        animation-name: s411-page-sort;
        animation-timing-function: cubic-bezier(.4, 0, .2, 1);
    }
    ::view-transition-new(root) {
        animation-name: s411-page-entre;
        animation-timing-function: cubic-bezier(.16, 1, .3, 1);
    }

    /* Elle ne s'efface pas, elle recule. */
    @keyframes s411-page-sort {
        from { opacity: 1; transform: none; }
        to   { opacity: 1; transform: translateY(-1rem) scale(.994); }
    }
    @keyframes s411-page-entre {
        from { opacity: 0; transform: translateY(1.5rem); }
        to   { opacity: 1; transform: none; }
    }

    /* Deux éléments sont nommés, donc suivis d'une page à l'autre au lieu
       d'être fondus avec le reste : l'en-tête, qui ne doit pas clignoter, et
       la bande de dégradé, qui se redimensionne du grand hero d'accueil au
       hero de page. Le pied de page, lui, n'est pas nommé : d'une page courte
       à une page longue il n'est pas au même endroit, et il traverserait
       l'écran en diagonale. */
    .s411-header   { view-transition-name: s411-entete; }
    .s411-hero,
    .s411-pagehero { view-transition-name: s411-ouverture; }

    /* La barre d'administration n'appartient pas au site : elle reste en
       place au lieu de traverser l'animation avec lui. */
    #wpadminbar { view-transition-name: s411-barre-admin; }

    ::view-transition-group(s411-ouverture) {
        animation-duration: .55s;
        animation-timing-function: cubic-bezier(.16, 1, .3, 1);
    }
    /* La bande de dégradé change de taille et de teinte : un fondu franc
       entre les deux états, sans addition qui la délaverait au passage. */
    ::view-transition-old(s411-ouverture),
    ::view-transition-new(s411-ouverture) {
        mix-blend-mode: normal;
        animation-duration: .55s;
    }
    ::view-transition-image-pair(s411-ouverture) { isolation: auto; }
}
