/* FICHIER GÉNÉRÉ par `app:assets:bundle-css` — NE PAS ÉDITER À LA MAIN.
   Source : app.imports.css (+ ses @import). Régénérer après toute modif du CSS scindé. */
/*
app.imports.css

QUOI : MANIFESTE d'ordre du CSS du site public — liste des @import des blocs scindés, dans l'ordre EXACT
       de cascade (l'ordre fait partie de l'invariant I4). N'est PAS servi directement.

COMMENT : `app:assets:bundle-css` (backlog P2-2) lit ce manifeste et inline récursivement ses @import
          pour produire la feuille servie `app.css` (bundle, 1 requête au lieu d'une cascade). Éditer ce
          manifeste (ordre) ou les blocs scindés, puis relancer la commande.

OÙ : Consommé par `BundleCssCommand` ; le bundle généré `app.css` est chargé par tous les templates
     publics via asset('styles/app.css').

POURQUOI : Scission §4.2 (aucun fichier source > 500 lignes) + résorption de la cascade @import (P2-2)
           sans bundler Node (I3 préservé).
*/

/*
fonts.css

QUOI : Polices d'Opalenews, HÉBERGÉES sur le site (licence OFL 1.1, `assets/fonts/OFL-*.txt`, fichiers Fontsource) :
       - Instrument Sans : police principale (texte, interface ; romain + italique) — grotesque nette, un peu
         resserrée, qui tient bien dans les cartes et les listes ;
       - Bricolage Grotesque : titres et marque — grotesque à caractère (pièges à encre, « Q » et « f » dessinés),
         qui donne une voix de magazine local au lieu du rendu « gabarit » des géométriques arrondies ;
       - Plus Jakarta Sans : gardée pour l'ambiance « Moderne » des pages Pro (ThemePagePro) ;
       - Fraunces : serif « à l'ancienne » douce, police « Gourmande » des pages Pro (téléchargée seulement si une
         page Pro la choisit).

COMMENT : Une police variable par famille et par jeu de caractères (latin, latin étendu) : le navigateur ne
          télécharge que le sous-ensemble utilisé (`unicode-range`). `font-display: swap`. Fichier placé à côté du
          bundle (`assets/styles/`) : ses `url()` relatives valent pour la source ET pour `app.css` (le bundle ne
          réécrit pas les chemins) ; AssetMapper les versionne. Les fichiers latins sont préchargés par
          `_partials/_site_header.html.twig`.

OÙ : Premier bloc du bundle `app.css` (avant `base/tokens.css`).

POURQUOI : Jusqu'au 28/10/2026, aucune police n'était chargée (police système selon l'appareil). Figtree + Plus
           Jakarta Sans ont été hébergées le 28/10 au matin, puis remplacées le même jour à la demande d'Ellie :
           « mets des polices plus modernes, là ça fait encore très prompt IA ». La CSP n'autorise que
           `font-src 'self'`, et héberger évite d'envoyer l'adresse IP des visiteurs à un tiers (RGPD).
*/

@font-face {
    font-family: 'Instrument Sans';
    font-style: normal;
    font-display: swap;
    font-weight: 400 700;
    src: url("../fonts/instrument-sans-latin-wght-normal-1Ubqs2a.woff2") format('woff2-variations');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Instrument Sans';
    font-style: normal;
    font-display: swap;
    font-weight: 400 700;
    src: url("../fonts/instrument-sans-latin-ext-wght-normal-mz-WyKA.woff2") format('woff2-variations');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Instrument Sans';
    font-style: italic;
    font-display: swap;
    font-weight: 400 700;
    src: url("../fonts/instrument-sans-latin-wght-italic-8Ql4F_q.woff2") format('woff2-variations');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Instrument Sans';
    font-style: italic;
    font-display: swap;
    font-weight: 400 700;
    src: url("../fonts/instrument-sans-latin-ext-wght-italic-pP0XXdK.woff2") format('woff2-variations');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Bricolage Grotesque';
    font-style: normal;
    font-display: swap;
    font-weight: 200 800;
    src: url("../fonts/bricolage-grotesque-latin-wght-normal-XEJcKrT.woff2") format('woff2-variations');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Bricolage Grotesque';
    font-style: normal;
    font-display: swap;
    font-weight: 200 800;
    src: url("../fonts/bricolage-grotesque-latin-ext-wght-normal-xZIEQZr.woff2") format('woff2-variations');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Plus Jakarta Sans';
    font-style: normal;
    font-display: swap;
    font-weight: 200 800;
    src: url("../fonts/plus-jakarta-sans-latin-wght-normal-ZHdaFJ8.woff2") format('woff2-variations');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Plus Jakarta Sans';
    font-style: normal;
    font-display: swap;
    font-weight: 200 800;
    src: url("../fonts/plus-jakarta-sans-latin-ext-wght-normal-w14NvZZ.woff2") format('woff2-variations');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Fraunces';
    font-style: normal;
    font-display: swap;
    font-weight: 300 900;
    src: url("../fonts/fraunces-latin-wght-normal-9IHoOgJ.woff2") format('woff2-variations');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Fraunces';
    font-style: normal;
    font-display: swap;
    font-weight: 300 900;
    src: url("../fonts/fraunces-latin-ext-wght-normal-7YO3Dz0.woff2") format('woff2-variations');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/*
tokens.css

QUOI : Variables globales :root — palette marine/sable/corail, rayons, ombres, espacements, polices (import Google Fonts) et échelle typo fluide.

COMMENT : Copie telle quelle des lignes 12–81 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/


:root {
    --c-marine: #0a3d62;
    --c-mer: #1e6091;
    --c-mer-clair: #4a90b8;
    --c-sable: #f5e9d4;
    --c-sable-clair: #faf4e8;
    --c-corail: #e07856;
    --c-corail-fonce: #c6603c;
    --c-texte: #2c3e50;
    --c-texte-doux: #5a6b7a;
    --c-blanc: #ffffff;
    /* Retouche contraste 2026-07-10 : bordure sable approfondie (#e8dec8 → #ddcba4)
       pour rendre les délimitations perceptibles sur fond sable et surfaces blanches. */
    --c-bordure: #ddcba4;
    /* Contour des CHAMPS de formulaire : le sable `--c-bordure` sur fond sable plafonnait à ~1.3:1, sous le
       seuil de 3:1 qui permet de repérer un champ (WCAG 1.4.11, audit de design du 27/10/2026). */
    --c-bordure-champ: #a08c62;
    --c-focus: rgba(30, 96, 145, 0.35);
    /* Fond des boutons et pastilles d'action à texte blanc. Égal à la mer en clair ; remappé en
       sombre (theme-dark.css), où `--c-mer` devient un bleu CLAIR de texte : du blanc dessus tombait
       à ~2.3:1 (bouton « Filtrer » de l'annuaire, audit du 27/10/2026). */
    --c-action: #1e6091;

    /* ── Surfaces SÉMANTIQUES (2026-07-17) ────────────────────────────────
       `--c-blanc` reste volontairement BLANC en mode sombre (texte blanc sur pastilles
       colorées) : une surface qui consomme `--c-blanc` doit donc être ré-énumérée à la main
       dans theme-dark.css pour ne pas rester blanche la nuit. Tout oubli = carte blanche en
       mode sombre (bug constaté sur `.contributor-event`).
       Ces deux jetons sont la sortie de secours : ils portent l'INTENTION « surface de
       contenu » et sont remappés en encre par theme-dark.css — un composant qui les consomme
       suit les deux thèmes sans ligne de code supplémentaire. Même logique que les `--adm-*`
       du back-office. À préférer à `--c-blanc` pour tout fond de carte/panneau.
         --c-surface   : carte / panneau posé sur le fond de page
         --c-surface-2 : surface secondaire (encart DANS une carte, champ de formulaire) */
    --c-surface: #ffffff;
    --c-surface-2: var(--c-sable-clair);

    /* Vert « validé » (badge contributeur, statuts). Jeton plutôt que littéral : en vert FONCÉ il
       devient illisible sur l'encre du mode sombre — theme-dark.css le remappe en vert lumineux. */
    --c-succes: #1e5023;

    /* Corail porté par du TEXTE sur une surface. Jeton distinct de `--c-corail-fonce`, qui sert
       aussi de FOND à des pastilles/dégradés à texte blanc : le remapper pour la nuit casserait
       ces aplats. Ici seule la lisibilité du texte compte → theme-dark.css l'éclaircit.
       Corail approfondi (#c6603c → #a8482a) : le corail foncé tombait à 3.7:1 sur le sable clair
       (échec AA) — flagrant sur « Supprimer », un bouton d'action destructive. À #a8482a : 5.3:1
       sur sable, 5.0:1 sur voile corail. */
    --c-corail-texte: #a8482a;
    /* Corail des APLATS à texte blanc (pastilles, boutons) : le corail de marque n'y tient que 3:1 (échec AA
       sur les petits textes). Ces deux tons gardent la teinte et montent à 4.8:1 et 6.4:1 avec le blanc
       (audit de contraste du 27/10/2026). Le corail des titres, filets et accents reste `--c-corail`. */
    --c-corail-action: #b9532f;
    --c-corail-action-fonce: #9a4426;

    /* Niveaux de présence de l'annuaire (premium / gratuit) — deux métaux DÉSATURÉS.
       Un doré saturé est inutilisable ici : la pastille porte du texte de 0.62rem en gras, où AA
       exige 4.5:1. La teinte ci-dessous est donc une version assombrie et rabattue vers la charte
       (le doré tire vers l'ocre, pas vers le jaune) — ce qui la fait cohabiter avec le sable et le
       corail sans ouvrir une troisième famille chromatique.
       Contrastes mesurés sur leur propre fond : doré 7.0:1, bleu 5.2:1.
       `--c-niveau-normale-*` sert aussi de bleu informatif générique hors annuaire (légende carte,
       badge du semainier) — conservé sous ce nom malgré la fusion des niveaux pour ne pas répercuter
       un renommage sur ces usages sans rapport avec la présence commerciale. */
    --c-niveau-boostee-texte: #7a5c12;
    --c-niveau-boostee-fond: rgba(180, 140, 30, 0.14);
    --c-niveau-normale-texte: #1e6091;
    --c-niveau-normale-fond: rgba(30, 96, 145, 0.10);

    --radius-sm: 8px;
    --radius-md: 14px;
    --radius-lg: 24px;          /* coins arrondis « chirurgicaux » (cartes / bento) */
    --radius-xl: 28px;
    --radius-2xl: 34px;

    /* Ombres douces multi-niveaux (teinte marine pour rester dans la charte) */
    --shadow-xs: 0 1px 2px rgba(10, 61, 98, 0.06);
    --shadow-sm: 0 2px 6px rgba(10, 61, 98, 0.07), 0 1px 2px rgba(10, 61, 98, 0.04);
    --shadow-md: 0 8px 24px rgba(10, 61, 98, 0.10), 0 2px 6px rgba(10, 61, 98, 0.05);
    --shadow-lg: 0 20px 48px rgba(10, 61, 98, 0.15), 0 6px 16px rgba(10, 61, 98, 0.08);
    --shadow-xl: 0 32px 64px -16px rgba(10, 61, 98, 0.28), 0 12px 24px -12px rgba(10, 61, 98, 0.14);
    /* Lueur colorée discrète au survol (cartes premium) */
    --glow-mer: 0 0 0 1px rgba(74, 144, 184, 0.30), 0 18px 40px -18px rgba(30, 96, 145, 0.40);

    --space-xs: 0.5rem;
    --space-sm: 1rem;
    --space-md: 1.5rem;
    --space-lg: 2.5rem;
    --space-xl: 4rem;

    /* Instrument Sans (texte) et Bricolage Grotesque (titres), hébergées : fonts.css. */
    --font-base: 'Instrument Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-display: 'Bricolage Grotesque', var(--font-base);

    /* Échelle typographique fluide (clamp) — un seul réglage du mobile au grand écran */
    --fs-xs:   clamp(0.72rem, 0.69rem + 0.15vw, 0.8rem);
    --fs-sm:   clamp(0.82rem, 0.79rem + 0.18vw, 0.92rem);
    --fs-base: clamp(0.95rem, 0.92rem + 0.20vw, 1.05rem);
    --fs-md:   clamp(1.05rem, 1.00rem + 0.35vw, 1.25rem);
    --fs-lg:   clamp(1.20rem, 1.08rem + 0.65vw, 1.55rem);
    --fs-xl:   clamp(1.50rem, 1.22rem + 1.30vw, 2.15rem);
    --fs-2xl:  clamp(1.90rem, 1.45rem + 2.10vw, 2.95rem);
    --fs-3xl:  clamp(2.30rem, 1.65rem + 3.10vw, 3.70rem);

    /* Verre dépoli (glassmorphism) — fond translucide, filet fin, flou */
    --glass-bg: rgba(255, 255, 255, 0.62);
    --glass-bg-strong: rgba(255, 255, 255, 0.80);
    --glass-border: rgba(255, 255, 255, 0.55);
    --glass-hairline: rgba(10, 61, 98, 0.14); /* 0.08 → 0.14 : retouche contraste 2026-07-10 */
    --glass-blur: 16px;
    --glass-shadow: 0 12px 40px -12px rgba(10, 61, 98, 0.28), 0 2px 8px -2px rgba(10, 61, 98, 0.12);

    /* En-tête flottant translucide (voile marine + flou haut de gamme) */
    --header-bg: linear-gradient(135deg, rgba(10, 61, 98, 0.80) 0%, rgba(30, 96, 145, 0.80) 100%);
    --header-bg-scrolled: linear-gradient(135deg, rgba(9, 52, 84, 0.74) 0%, rgba(26, 84, 128, 0.76) 100%);

    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
    --duration-fast: 150ms;
    --duration-base: 220ms;
    --duration-slow: 360ms;
}


/*
reset.css

QUOI : Réinitialisation de base : box-sizing global, réglages html/body (fond dégradé, flex colonne) et main extensible.

COMMENT : Copie telle quelle des lignes 82–112 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

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

html {
    scroll-behavior: smooth;
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    font-family: var(--font-base);
    font-size: 16px;
    line-height: 1.6;
    font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11';
    color: var(--c-texte);
    /* Fond sable clair (rollback 2026-07-16 sur demande — le sable chaud du 2026-07-10 ne
       plaisait pas). Le contraste cartes/fond reste couvert par la bordure et les hairlines
       renforcées ce jour-là (tokens.css --c-bordure, event-card.css), conservées telles quelles. */
    background-color: var(--c-sable-clair);
    background-image:
        radial-gradient(circle at 10% 0%, rgba(74, 144, 184, 0.10) 0%, transparent 45%),
        radial-gradient(circle at 90% 100%, rgba(224, 120, 86, 0.06) 0%, transparent 40%);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

body > main {
    flex: 1;
}


/*
a11y.css

QUOI : Accessibilité transverse : focus visible renforcé (WCAG 2.4.7), classe sr-only et neutralisation des animations si prefers-reduced-motion.

COMMENT : Copie telle quelle des lignes 113–194 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

*:focus {
    outline: none;
}
*:focus-visible {
    outline: 2px solid var(--c-mer);
    outline-offset: 3px;
    border-radius: var(--radius-sm);
}

/* Règle spécifique WCAG 2.4.7 : focus visible renforcé sur éléments interactifs clés. */
a:focus-visible,
button:focus-visible,
input:focus-visible {
    outline: 3px solid var(--c-mer);
    outline-offset: 2px;
}

/* Masque visuellement un élément tout en le gardant accessible aux lecteurs d'écran. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

::selection {
    background-color: rgba(30, 96, 145, 0.22);
    color: var(--c-marine);
}

[data-reveal] {
    opacity: 0;
    transform: translateY(12px);
    transition: opacity 500ms var(--ease-out), transform 500ms var(--ease-out);
    will-change: opacity, transform;
}
[data-reveal].is-revealed {
    opacity: 1;
    transform: translateY(0);
}

[data-reveal-children] > * {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity 500ms var(--ease-out), transform 500ms var(--ease-out);
}
[data-reveal-children].is-revealed > * {
    opacity: 1;
    transform: translateY(0);
}
[data-reveal-children].is-revealed > *:nth-child(1) { transition-delay: 0ms; }
[data-reveal-children].is-revealed > *:nth-child(2) { transition-delay: 60ms; }
[data-reveal-children].is-revealed > *:nth-child(3) { transition-delay: 120ms; }
[data-reveal-children].is-revealed > *:nth-child(4) { transition-delay: 180ms; }
[data-reveal-children].is-revealed > *:nth-child(5) { transition-delay: 240ms; }
[data-reveal-children].is-revealed > *:nth-child(n+6) { transition-delay: 300ms; }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
    [data-reveal],
    [data-reveal-children] > * {
        opacity: 1 !important;
        transform: none !important;
    }
    .u-fade-in-up,
    .u-stagger > * {
        animation: none !important;
        opacity: 1 !important;
        transform: none !important;
    }
}


/*
utilities.css

QUOI : Utilitaires réutilisables : verre dépoli (.glass-*), carrousel tactile, apparition douce, système de boutons .btn et conteneur central .container.

COMMENT : Copie telle quelle des lignes 195–338 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ============================================================
   Utilitaires refonte v2.5.0 — verre dépoli, boutons, carrousels,
   apparition douce. Mobile-first, accessibles, sans framework.
   ============================================================ */

/* ── Verre dépoli (glassmorphism) ── */
.glass-card,
.glass {
    background: var(--glass-bg);
    -webkit-backdrop-filter: saturate(160%) blur(var(--glass-blur));
    backdrop-filter: saturate(160%) blur(var(--glass-blur));
    border: 1px solid var(--glass-border);
    box-shadow: var(--glass-shadow);
    border-radius: var(--radius-lg);
}

.glass--strong {
    background: var(--glass-bg-strong);
}

/* Repli sans backdrop-filter : on opacifie le fond pour préserver la lisibilité. */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
    .glass-card,
    .glass {
        background: var(--glass-bg-strong);
    }
}

/* ── Carrousel tactile horizontal (scrollbar masquée) — tags / catégories mobile ── */
.u-scroll-x {
    display: flex;
    gap: 0.5rem;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    -ms-overflow-style: none;
}
.u-scroll-x::-webkit-scrollbar { display: none; }
.u-scroll-x > * {
    scroll-snap-align: start;
    flex: 0 0 auto;
}

/* ── Apparition douce ascendante (CSS pur : état final visible même si l'anim échoue) ── */
@keyframes fade-in-up {
    from { opacity: 0; transform: translateY(18px); }
    to   { opacity: 1; transform: translateY(0); }
}
.u-fade-in-up {
    animation: fade-in-up 620ms var(--ease-out) both;
}
.u-stagger > * {
    animation: fade-in-up 620ms var(--ease-out) both;
}
.u-stagger > *:nth-child(1) { animation-delay: 40ms; }
.u-stagger > *:nth-child(2) { animation-delay: 110ms; }
.u-stagger > *:nth-child(3) { animation-delay: 180ms; }
.u-stagger > *:nth-child(4) { animation-delay: 250ms; }
.u-stagger > *:nth-child(5) { animation-delay: 320ms; }
.u-stagger > *:nth-child(n+6) { animation-delay: 390ms; }

/* ── Système de boutons partagé (.btn) ──
   Défini ici pour que les pages ne chargeant que style.css (newsletter, pied de page)
   disposent d'un bouton premium. Sur les pages admin/soumission, leur CSS dédié
   (chargé APRÈS style.css) prend le relais sans conflit. */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    min-height: 46px;
    padding: 0.7rem 1.4rem;
    font-size: 0.95rem;
    font-family: inherit;
    font-weight: 600;
    line-height: 1.2;
    border: 1.5px solid transparent;
    border-radius: 999px;
    cursor: pointer;
    text-decoration: none;
    box-shadow: var(--shadow-sm);
    transition: background-color var(--duration-fast) var(--ease-out),
                border-color var(--duration-fast) var(--ease-out),
                color var(--duration-fast) var(--ease-out),
                box-shadow var(--duration-base) var(--ease-out),
                transform var(--duration-fast) var(--ease-out);
}

.btn:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-md);
}

.btn:active {
    transform: translateY(0);
    box-shadow: var(--shadow-xs);
}

.btn:focus-visible {
    outline: 2px solid var(--c-mer);
    outline-offset: 2px;
}

.btn--primary {
    background: linear-gradient(135deg, var(--c-marine) 0%, var(--c-mer) 100%);
    color: var(--c-blanc);
    border-color: transparent;
}

.btn--primary:hover {
    box-shadow: 0 10px 26px -8px rgba(10, 61, 98, 0.45);
}

.btn--ghost {
    background-color: transparent;
    color: var(--c-texte-doux);
    border-color: var(--c-bordure);
    box-shadow: none;
}

.btn--ghost:hover {
    color: var(--c-marine);
    border-color: var(--c-mer);
    background-color: rgba(30, 96, 145, 0.05);
    box-shadow: none;
}

/* 1280 px (1440 px sur les très grands écrans, ≥ 1680 px) : à 1920 px, l'ancien plafond de 1200 px laissait
   384 px vides de chaque côté (audit ordinateur du 27/10/2026). Les pages de lecture (fiche événement, à propos)
   gardent leur colonne plus étroite. */
.container {
    width: 100%;
    max-width: 1280px;
    margin: 0 auto;
    padding-left: max(var(--space-sm), env(safe-area-inset-left));
    padding-right: max(var(--space-sm), env(safe-area-inset-right));
}

@media (min-width: 640px) {
    .container {
        padding-left: var(--space-md);
        padding-right: var(--space-md);
    }
}

@media (min-width: 1680px) {
    .container {
        max-width: 1440px;
    }
}



/*
header.css

QUOI : En-tête du site (.site-header) : bandeau sticky translucide (voile marine + flou), logo, tagline et état déroulé .is-scrolled.

COMMENT : Copie telle quelle des lignes 339–498 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

.site-header {
    position: sticky;
    top: 0;
    z-index: 50;
    /* En-tête flottant translucide : voile marine + flou d'arrière-plan haut de gamme. */
    background: var(--header-bg);
    -webkit-backdrop-filter: saturate(155%) blur(12px);
    backdrop-filter: saturate(155%) blur(12px);
    color: var(--c-blanc);
    /* Hauteur affinée (header plus discret) + marge de sécurité encoche/Dynamic Island.
       `max()` garantit un padding de base quand il n'y a pas d'inset (la valeur de repli de
       `env()` ne s'applique qu'aux navigateurs sans support, pas aux écrans sans encoche). */
    padding-block: 0.55rem;
    padding-top: max(0.55rem, env(safe-area-inset-top, 0.55rem));
    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06), var(--shadow-sm);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    transition: box-shadow var(--duration-base) var(--ease-out),
                background var(--duration-base) var(--ease-out);
}

/* Repli sans flou (très rares navigateurs) : voile marine opaque pour rester lisible. */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
    .site-header {
        background: linear-gradient(135deg, #0a3d62 0%, #1e6091 100%);
    }
}

@media (min-width: 640px) {
    .site-header {
        padding-block: 0.7rem;
        padding-top: max(0.7rem, env(safe-area-inset-top, 0.7rem));
    }
}

/* NE PAS modifier la hauteur (padding/min-height) ici : un header sticky qui
   change de taille au scroll fait osciller la position de défilement autour du
   seuil et provoque un flicker. Seuls les effets visuels sont autorisés. */
.site-header.is-scrolled {
    box-shadow: var(--shadow-md);
    background: var(--header-bg-scrolled);
    -webkit-backdrop-filter: saturate(165%) blur(16px);
    backdrop-filter: saturate(165%) blur(16px);
}

.site-header::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, transparent 70%, rgba(255, 255, 255, 0.04) 100%);
    pointer-events: none;
}

.site-header .container {
    position: relative;
    z-index: 1;
}

.site-header__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-sm);
    flex-wrap: wrap;
}

.header-brand {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}

.logo {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
    color: var(--c-blanc);
    text-decoration: none;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.45rem;
    letter-spacing: -0.02em;
    transition: opacity var(--duration-fast) var(--ease-out);
}

.logo:hover {
    opacity: 0.92;
}

.logo-mark {
    font-size: 1.8rem;
    color: var(--c-sable);
    transition: transform var(--duration-slow) var(--ease-out-quart);
    display: inline-block;
}

.logo:hover .logo-mark {
    transform: rotate(20deg);
}

.tagline {
    margin: 0;
    font-size: 0.85rem;
    opacity: 0.78;
    font-style: italic;
    letter-spacing: 0.01em;
}

@media (max-width: 479px) {
    .tagline {
        display: none;
    }
}

.header-cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    min-height: 44px;
    padding: 0.55rem 1.15rem;
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--c-marine);
    background-color: var(--c-sable);
    border: 1.5px solid transparent;
    border-radius: var(--radius-md);
    text-decoration: none;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
    white-space: nowrap;
    transition: background-color var(--duration-fast) var(--ease-out),
                transform var(--duration-fast) var(--ease-out),
                box-shadow var(--duration-fast) var(--ease-out);
}

.header-cta:hover {
    background-color: var(--c-blanc);
    transform: translateY(-1px);
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.12);
}

.header-cta:active {
    transform: translateY(0);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.10);
}

@media (min-width: 640px) {
    .header-brand {
        flex-direction: row;
        align-items: baseline;
        gap: 0.85rem;
    }

    .tagline {
        border-left: 1px solid rgba(255, 255, 255, 0.22);
        padding-left: 0.85rem;
    }
}



/*
search.css

QUOI : Zone de recherche de l'accueil : section, panneau blanc, champ avec icône et états focus.

COMMENT : Copie telle quelle des lignes 499–604 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

.search-section {
    padding: var(--space-md) 0 var(--space-sm);
    text-align: center;
}

.search-panel {
    background-color: var(--c-blanc);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-md);
    padding: var(--space-md) var(--space-sm);
    box-shadow: var(--shadow-sm);
    max-width: 880px;
    margin: 0 auto;
}

@media (min-width: 640px) {
    .search-panel {
        border-radius: var(--radius-lg);
        padding: var(--space-lg) var(--space-md);
    }
}

.search-section h1 {
    margin: 0 0 var(--space-md);
    font-family: var(--font-display);
    font-size: clamp(1.8rem, 4.5vw, 2.75rem);
    color: var(--c-marine);
    font-weight: 800;
    letter-spacing: -0.025em;
    line-height: 1.15;
    background: linear-gradient(135deg, var(--c-marine) 0%, var(--c-mer) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.search-wrapper {
    position: relative;
    max-width: 640px;
    margin: 0 auto;
}

.search-icon {
    position: absolute;
    left: var(--space-sm);
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--c-mer);
    opacity: 0.55;
    pointer-events: none;
    transition: opacity var(--duration-fast) var(--ease-out),
                color var(--duration-fast) var(--ease-out);
}

.search-wrapper:focus-within .search-icon {
    color: var(--c-marine);
    opacity: 1;
}

.search-input {
    width: 100%;
    min-height: 52px;
    padding: 1rem var(--space-sm) 1rem 3rem;
    font-size: 1.05rem;
    font-family: inherit;
    color: var(--c-texte);
    background-color: var(--c-blanc);
    border: 2px solid var(--c-bordure-champ);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    outline: none;
    -webkit-appearance: none;
    appearance: none;
    transition: border-color var(--duration-base) var(--ease-out),
                box-shadow var(--duration-base) var(--ease-out),
                transform var(--duration-base) var(--ease-out);
}

.search-input::placeholder {
    color: var(--c-texte-doux);
    opacity: 0.65;
}

.search-input:hover {
    border-color: var(--c-mer-clair);
}

.search-input:focus,
.search-input:focus-visible {
    border-color: var(--c-mer);
    box-shadow: 0 0 0 4px var(--c-focus), var(--shadow-md);
    outline: none;
    transform: translateY(-1px);
}

/* L'ancien `.results-count` (paragraphe compteur sous le moteur de recherche) est devenu la
   pastille `.section-heading__count` à côté des titres de section (cf. components/map.css). */



/*
filters.css

QUOI : Pastilles de la barre d'outils (tri, filtres, carte, date, géoloc) et popover de saisie manuelle d'adresse.

COMMENT : Copie telle quelle des lignes 605–1030 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

.search-toolbar {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 0.5rem;
    margin: var(--space-md) auto 0;
    min-height: 42px;
    padding: 0.45rem 0.65rem;
    background: linear-gradient(180deg, var(--c-sable-clair) 0%, rgba(250, 244, 232, 0.65) 100%);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-md);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.85);
}

@media (min-width: 640px) {
    .search-toolbar {
        max-width: fit-content;
        border-radius: 999px;
    }
}

@media (max-width: 539px) {
    /* Sur mobile, ces pills passent en icône-seule. On masque le libellé VISUELLEMENT
       (pattern .visually-hidden) plutôt qu'avec display:none : le texte reste dans l'arbre
       d'accessibilité, donc le bouton conserve un nom accessible (WCAG 4.1.2, niveau A) et
       le badge de comptage des filtres reste annoncé. Rendu visuel identique à display:none. */
    .toolbar-pill--filters .toolbar-pill__label,
    .toolbar-pill--map .toolbar-pill__label {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
    }
    .toolbar-pill--filters,
    .toolbar-pill--map {
        padding-left: 0.75rem;
        padding-right: 0.75rem;
    }
}

.toolbar-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    min-height: 40px;
    padding: 0.55rem 1rem;
    font-size: 0.825rem;
    font-family: inherit;
    font-weight: 600;
    line-height: 1.2;
    color: var(--c-marine);
    background-color: var(--c-blanc);
    border: 1.5px solid var(--c-bordure);
    border-radius: 999px;
    cursor: pointer;
    text-decoration: none;
    box-shadow: 0 1px 3px rgba(10, 61, 98, 0.06);
    transition: background-color var(--duration-fast) var(--ease-out),
                border-color var(--duration-fast) var(--ease-out),
                color var(--duration-fast) var(--ease-out),
                box-shadow var(--duration-fast) var(--ease-out),
                transform var(--duration-fast) var(--ease-out);
    animation: toolbar-pill-in 0.25s var(--ease-out);
}

.toolbar-pill:hover {
    border-color: var(--c-mer-clair);
    background-color: #fff;
    box-shadow: 0 3px 10px rgba(10, 61, 98, 0.10);
    transform: translateY(-1px);
}

.toolbar-pill:focus-visible {
    outline: 2px solid var(--c-mer);
    outline-offset: 2px;
}

.toolbar-pill:active {
    transform: translateY(0);
}

.toolbar-pill__icon {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    stroke-width: 2.2;
    opacity: 0.85;
}

.toolbar-pill__label {
    white-space: nowrap;
}

.toolbar-pill__separator {
    width: 1px;
    height: 14px;
    background-color: var(--c-bordure);
    margin: 0 0.15rem;
}

.toolbar-pill__sub {
    color: var(--c-texte-doux);
    font-weight: 500;
    font-size: 0.78rem;
    white-space: nowrap;
}

.toolbar-pill--geo.is-active {
    background-color: var(--c-marine);
    border-color: var(--c-marine);
    color: var(--c-blanc);
    box-shadow: 0 2px 10px rgba(10, 61, 98, 0.20);
}

.toolbar-pill--geo.is-active:hover {
    background-color: var(--c-mer);
    border-color: var(--c-mer);
}

.toolbar-pill--geo.is-loading {
    opacity: 0.65;
    cursor: progress;
}

.toolbar-pill--geo.is-error {
    color: var(--c-corail);
    border-color: var(--c-corail);
}

/* ===== Saisie manuelle d'adresse (popover) =====
   Wrapper relatif pour ancrer le panneau sous le bouton ; styles compacts cohérents
   avec les autres pills de la toolbar. */
.geo-manual {
    position: relative;
    display: inline-flex;
}

.toolbar-pill--geo-edit .toolbar-pill__icon {
    stroke-width: 2;
}

.geo-manual.is-open .toolbar-pill--geo-edit {
    background-color: var(--c-marine);
    border-color: var(--c-marine);
    color: var(--c-blanc);
}

.geo-manual__panel {
    position: absolute;
    top: calc(100% + 0.5rem);
    left: 0;
    z-index: 30;
    width: min(360px, calc(100vw - 2rem));
    background-color: var(--c-blanc);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    padding: var(--space-sm);
    animation: toolbar-pill-in 0.18s var(--ease-out);
}

.geo-manual__label {
    display: block;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--c-texte-doux);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin: 0 0 0.4rem;
}

.geo-manual__input-wrap {
    position: relative;
    display: flex;
    align-items: center;
}

.geo-manual__input {
    flex: 1;
    width: 100%;
    padding: 0.55rem 0.75rem;
    font: inherit;
    font-size: 0.92rem;
    color: var(--c-texte);
    background-color: var(--c-blanc);
    border: 1.5px solid var(--c-bordure);
    border-radius: var(--radius-sm);
    outline: none;
    transition: border-color var(--duration-fast) var(--ease-out),
                box-shadow var(--duration-fast) var(--ease-out);
}

.geo-manual__input:focus {
    border-color: var(--c-mer);
    box-shadow: 0 0 0 3px rgba(30, 96, 145, 0.15);
}

.geo-manual__spinner {
    position: absolute;
    right: 0.6rem;
    width: 16px;
    height: 16px;
    border: 2px solid var(--c-bordure);
    border-top-color: var(--c-mer);
    border-radius: 50%;
    animation: geo-manual-spin 0.7s linear infinite;
}

@keyframes geo-manual-spin {
    to { transform: rotate(360deg); }
}

.geo-manual__suggestions {
    list-style: none;
    margin: 0.4rem 0 0;
    padding: 0;
    max-height: 240px;
    overflow-y: auto;
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-sm);
    background-color: var(--c-blanc);
}

.geo-manual__suggestion {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.55rem 0.7rem;
    font-size: 0.88rem;
    color: var(--c-marine);
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-out);
}

.geo-manual__suggestion + .geo-manual__suggestion {
    border-top: 1px solid var(--c-bordure);
}

.geo-manual__suggestion svg {
    flex-shrink: 0;
    color: var(--c-mer);
}

.geo-manual__suggestion:hover,
.geo-manual__suggestion.is-active {
    background-color: var(--c-sable-clair);
}

.geo-manual__hint {
    margin: 0.5rem 0 0;
    font-size: 0.78rem;
    color: var(--c-texte-doux);
}

@media (max-width: 600px) {
    .geo-manual__panel {
        position: fixed;
        top: auto;
        bottom: 1rem;
        left: 1rem;
        right: 1rem;
        width: auto;
    }
}

.toolbar-pill--filters,
.toolbar-pill--map,
.toolbar-pill--sort {
    position: relative;
}

.toolbar-pill--filters[aria-expanded="true"],
.toolbar-pill--map[aria-expanded="true"],
.toolbar-pill--sort[aria-expanded="true"] {
    background: linear-gradient(135deg, var(--c-marine) 0%, var(--c-mer) 100%);
    border-color: var(--c-marine);
    color: var(--c-blanc);
    box-shadow: 0 2px 10px rgba(10, 61, 98, 0.22);
}

.toolbar-pill--filters[aria-expanded="true"]:hover,
.toolbar-pill--map[aria-expanded="true"]:hover,
.toolbar-pill--sort[aria-expanded="true"]:hover {
    background: linear-gradient(135deg, var(--c-mer) 0%, var(--c-mer-clair) 100%);
    border-color: var(--c-mer);
}

/* Le sous-libellé (valeur de tri courante) passe en blanc quand la pastille est ouverte/active. */
.toolbar-pill--sort[aria-expanded="true"] .toolbar-pill__sub {
    color: rgba(255, 255, 255, 0.85);
}

.toolbar-pill--sort[aria-expanded="true"] .toolbar-pill__separator {
    background-color: rgba(255, 255, 255, 0.4);
}

.toolbar-pill__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    margin-left: 0.1rem;
    padding: 0 0.35rem;
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1;
    color: var(--c-blanc);
    background-color: var(--c-corail-action);
    border-radius: 999px;
    font-variant-numeric: tabular-nums;
}

.toolbar-pill__badge[hidden] {
    display: none;
}

.toolbar-pill--filters[aria-expanded="true"] .toolbar-pill__badge {
    background-color: var(--c-corail);
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.45);
}

.toolbar-pill--date {
    background: linear-gradient(135deg, rgba(74, 144, 184, 0.12) 0%, rgba(10, 61, 98, 0.08) 100%);
    border-color: var(--c-mer-clair);
    color: var(--c-marine);
    cursor: default;
}

.toolbar-pill--date:hover {
    transform: none;
    border-color: var(--c-mer);
}

.toolbar-pill--date .toolbar-pill__icon {
    color: var(--c-mer);
    opacity: 1;
}

@keyframes toolbar-pill-in {
    from { opacity: 0; transform: translateY(-3px) scale(0.98); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

.facet-chips {
    display: flex;
    flex-direction: column;
    gap: 0.65rem;
    margin: var(--space-sm) auto 0;
    max-width: 900px;
    align-items: stretch;
    padding: var(--space-sm) var(--space-md);
    border-top: 1px solid var(--c-bordure);
    background: linear-gradient(180deg, rgba(245, 233, 212, 0.35) 0%, transparent 100%);
    border-radius: 0 0 var(--radius-md) var(--radius-md);
}

.facet-chips__group {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    justify-content: center;
    align-items: center;
}

.facet-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-height: 36px;
    padding: 0.5rem 0.95rem;
    font-size: 0.8rem;
    font-family: inherit;
    font-weight: 600;
    line-height: 1.2;
    color: var(--c-marine);
    background-color: var(--c-blanc);
    border: 1.5px solid var(--c-bordure);
    border-radius: 999px;
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(10, 61, 98, 0.05);
    transition: background-color var(--duration-fast) var(--ease-out),
                color var(--duration-fast) var(--ease-out),
                border-color var(--duration-fast) var(--ease-out),
                box-shadow var(--duration-fast) var(--ease-out),
                transform var(--duration-fast) var(--ease-out);
}

.facet-chip:hover {
    color: var(--c-marine);
    border-color: var(--c-mer-clair);
    background-color: #fff;
    box-shadow: 0 3px 10px rgba(10, 61, 98, 0.09);
    transform: translateY(-1px);
}

.facet-chip:focus-visible {
    outline: 2px solid var(--c-mer);
    outline-offset: 2px;
}

.facet-chip.is-active {
    background: linear-gradient(135deg, var(--c-marine) 0%, var(--c-mer) 100%);
    color: var(--c-blanc);
    border-color: var(--c-marine);
    font-weight: 700;
    box-shadow: 0 3px 10px rgba(10, 61, 98, 0.22);
    transform: translateY(-1px);
}

.facet-chip.is-active:hover {
    background: linear-gradient(135deg, var(--c-mer) 0%, var(--c-mer-clair) 100%);
    border-color: var(--c-mer);
    color: var(--c-blanc);
}

.facet-chip--category.is-active {
    background: linear-gradient(135deg, var(--c-mer) 0%, var(--c-mer-clair) 100%);
    border-color: var(--c-mer);
}

.facet-chip--free.is-active {
    background: linear-gradient(135deg, var(--c-corail) 0%, var(--c-corail-fonce) 100%);
    border-color: var(--c-corail);
}

.facet-chip--free.is-active:hover {
    background: linear-gradient(135deg, var(--c-corail-fonce) 0%, #b85538 100%);
    border-color: var(--c-corail-fonce);
    color: var(--c-blanc);
}


/*
filters-recap.css

QUOI : Rappel des filtres actifs, posé sous le titre « Événements N » de la section résultats —
une rangée de pastilles retirables et un « Tout effacer ».

COMMENT : Vocabulaire volontairement PLUS SOBRE que celui de la barre d'outils (`filters.css`) :
pastilles plus petites, fond sable, pas d'ombre portée au repos. Le rappel dit ce qui est appliqué,
il ne rivalise pas avec les contrôles qui l'appliquent — deux jeux de pilules de même poids sur la
même page se liraient comme deux barres d'outils concurrentes.

OÙ : Importé par `assets/styles/app.imports.css`. Markup dans `home/index.html.twig`
(`#results-recap`), peuplé par `assets/js/search/recap-ui.js`.

POURQUOI : la barre d'outils vit dans le hero ; descendu dans les résultats, on ne voit plus ce qui
a été filtré (demande du commanditaire, 2026-09-09).
*/

.results-recap {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-xs) 0.6rem;
    /* Collé au sous-titre qu'il complète, détaché de la grille qu'il qualifie. */
    margin: 0.65rem 0 var(--space-md);
}

.results-recap__label {
    font-family: var(--font-base);
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--c-texte-doux);
}

.results-recap__list {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.recap-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.32rem 0.7rem 0.32rem 0.8rem;
    border: 1px solid var(--c-bordure);
    /* 999px littéral comme toutes les pilules du système (`filters.css`) : la charte documente un
       `rounded.full` mais aucun jeton ne le porte encore dans `tokens.css`. */
    border-radius: 999px;
    background: var(--c-surface-2);
    color: var(--c-marine);
    font-family: var(--font-base);
    font-size: 0.82rem;
    font-weight: 600;
    line-height: 1.3;
    cursor: pointer;
    transition: border-color var(--duration-fast) var(--ease-out),
                color var(--duration-fast) var(--ease-out),
                box-shadow var(--duration-fast) var(--ease-out);
}

.recap-chip:hover {
    border-color: var(--c-mer);
    box-shadow: var(--shadow-xs);
}

/* La croix vire au corail au survol : retirer un filtre est la seule action destructive de la
   rangée, et le corail est justement la couleur des actions ponctuelles (Règle de la Touche
   Corail). Elle reste encre douce au repos pour ne pas transformer la rangée en guirlande. */
.recap-chip__cross {
    width: 0.72rem;
    height: 0.72rem;
    color: var(--c-texte-doux);
    transition: color var(--duration-fast) var(--ease-out);
}

.recap-chip:hover .recap-chip__cross,
.recap-chip:focus-visible .recap-chip__cross {
    color: var(--c-corail-texte);
}

.results-recap__clear {
    padding: 0.32rem 0.2rem;
    border: 0;
    background: transparent;
    color: var(--c-texte-doux);
    font-family: var(--font-base);
    font-size: 0.82rem;
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 0.22em;
    text-decoration-thickness: 1px;
    cursor: pointer;
    transition: color var(--duration-fast) var(--ease-out);
}

.results-recap__clear:hover {
    color: var(--c-marine);
}

@media (prefers-reduced-motion: reduce) {
    .recap-chip,
    .recap-chip__cross,
    .results-recap__clear {
        transition: none;
    }
}

/*
popovers.css

QUOI : Menus déroulants Tri / Filtres : popovers ancrés, options de tri (radio + coche), cases à cocher catégories et groupes de filtres.

COMMENT : Copie telle quelle des lignes 1031–1331 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ===================== Menus déroulants Tri / Filtres (barre d'outils) ===================== */
.toolbar-dropdown {
    position: relative;
    display: inline-flex;
}

/* Chevron du déclencheur : pivote quand le menu est ouvert. */
.toolbar-pill__caret {
    width: 12px;
    height: 12px;
    flex-shrink: 0;
    margin-left: -0.1rem;
    opacity: 0.6;
    transition: transform 0.22s var(--ease-out), opacity var(--duration-fast) var(--ease-out);
}

.toolbar-pill[aria-expanded="true"] .toolbar-pill__caret {
    transform: rotate(180deg);
    opacity: 0.9;
}

/* Pastille « Filtres » avec sélection active mais menu fermé : accent discret. */
.toolbar-pill--filters.is-active:not([aria-expanded="true"]) {
    border-color: var(--c-marine);
    color: var(--c-marine);
    background: linear-gradient(135deg, rgba(10, 61, 98, 0.07) 0%, rgba(74, 144, 184, 0.06) 100%);
}

/* ----- Le popover ----- */
.dropdown-menu {
    position: absolute;
    top: calc(100% + 0.55rem);
    z-index: 40;
    width: max-content;
    min-width: 248px;
    max-width: min(320px, calc(100vw - 1.5rem));
    padding: 0.45rem;
    text-align: left;
    background-color: var(--c-blanc);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    transform-origin: top center;
    animation: dropdown-in 0.16s var(--ease-out);
}

.dropdown-menu[hidden] {
    display: none;
}

/* Ancrage : le tri s'ouvre vers la droite, les filtres vers la gauche (anti-débordement). */
.dropdown-menu--sort { left: 0; }
.dropdown-menu--filters { right: 0; }

/* Petite flèche optique reliant le popover à son bouton. */
.dropdown-menu::before {
    content: "";
    position: absolute;
    top: -5px;
    width: 10px;
    height: 10px;
    background-color: var(--c-blanc);
    border-left: 1px solid var(--c-bordure);
    border-top: 1px solid var(--c-bordure);
    transform: rotate(45deg);
}

.dropdown-menu--sort::before { left: 1.4rem; }
.dropdown-menu--filters::before { right: 1.4rem; }

@keyframes dropdown-in {
    from { opacity: 0; transform: translateY(-6px) scale(0.98); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

.dropdown-menu__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.3rem 0.55rem 0.45rem;
}

.dropdown-menu__title {
    margin: 0;
    padding: 0.35rem 0.55rem 0.45rem;
    font-size: 0.7rem;
    font-weight: 700;
    color: var(--c-texte-doux);
    text-transform: uppercase;
    letter-spacing: 0.07em;
}

.dropdown-menu__head .dropdown-menu__title {
    padding: 0;
}

.dropdown-menu__clear {
    padding: 0.25rem 0.5rem;
    font: inherit;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--c-mer);
    background: transparent;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}

.dropdown-menu__clear:hover {
    color: var(--c-marine);
    background-color: var(--c-sable-clair);
}

.dropdown-menu__clear[hidden] {
    display: none;
}

/* ----- Options de tri (radio + coche) ----- */
.dropdown-menu__list {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.dropdown-option {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    width: 100%;
    padding: 0.55rem 0.55rem;
    font: inherit;
    text-align: left;
    color: var(--c-marine);
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-out);
}

.dropdown-option:hover {
    background-color: var(--c-sable-clair);
}

.dropdown-option:focus-visible {
    outline: 2px solid var(--c-mer);
    outline-offset: -2px;
}

.dropdown-option__icon {
    flex-shrink: 0;
    color: var(--c-mer);
}

.dropdown-option__label {
    display: flex;
    flex-direction: column;
    gap: 1px;
    margin-right: auto;
}

.dropdown-option__name {
    font-size: 0.9rem;
    font-weight: 600;
}

.dropdown-option__hint {
    font-size: 0.73rem;
    font-weight: 500;
    color: var(--c-texte-doux);
}

.dropdown-option__check {
    flex-shrink: 0;
    color: var(--c-mer);
    opacity: 0;
    transform: scale(0.7);
    transition: opacity 0.15s var(--ease-out), transform 0.15s var(--ease-out);
}

.dropdown-option.is-active {
    background-color: rgba(30, 96, 145, 0.08);
}

.dropdown-option.is-active .dropdown-option__icon {
    color: var(--c-marine);
}

.dropdown-option.is-active .dropdown-option__check {
    opacity: 1;
    transform: scale(1);
}

/* Géoloc active → tri par distance : les options manuelles sont neutralisées visuellement. */
.dropdown-menu__list.is-distance-mode .dropdown-option {
    opacity: 0.45;
}

/* ----- Cases à cocher catégories ----- */
.dropdown-menu__options {
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 320px;
    overflow-y: auto;
}

.dropdown-check {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    width: 100%;
    padding: 0.5rem 0.55rem;
    font: inherit;
    text-align: left;
    color: var(--c-marine);
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-out);
}

.dropdown-check:hover {
    background-color: var(--c-sable-clair);
}

.dropdown-check:focus-visible {
    outline: 2px solid var(--c-mer);
    outline-offset: -2px;
}

.dropdown-check__box {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    background-color: var(--c-blanc);
    border: 2px solid var(--c-bordure);
    border-radius: 6px;
    transition: background-color 0.15s var(--ease-out), border-color 0.15s var(--ease-out);
}

.dropdown-check__box svg {
    width: 12px;
    height: 12px;
    color: var(--c-blanc);
    opacity: 0;
    transition: opacity 0.12s var(--ease-out);
}

.dropdown-check__label {
    font-size: 0.9rem;
    font-weight: 600;
}

.dropdown-check.is-active .dropdown-check__box {
    background-color: var(--c-mer);
    border-color: var(--c-mer);
}

.dropdown-check.is-active .dropdown-check__box svg {
    opacity: 1;
}

/* Filtre « Gratuit » coché : la case se teinte en corail pour le distinguer des catégories. */
.dropdown-check--free.is-active .dropdown-check__box {
    background-color: var(--c-corail);
    border-color: var(--c-corail);
}

/* Groupes du menu Filtres : sépare visuellement le bloc « Tarif » des « Catégories »
   (sous-titre discret + filet entre les deux groupes). */
.dropdown-group__label {
    margin: 0;
    padding: 0.3rem 0.55rem 0.35rem;
    font-size: 0.68rem;
    font-weight: 700;
    color: var(--c-texte-doux);
    text-transform: uppercase;
    letter-spacing: 0.07em;
}

.dropdown-group + .dropdown-group {
    margin-top: 0.35rem;
    padding-top: 0.35rem;
    border-top: 1px solid var(--c-bordure);
}

@media (max-width: 539px) {
    /* Sur très petit écran, on n'affiche que l'icône + « Trier » (la valeur courante reste sur la pastille). */
    .toolbar-pill--sort .toolbar-pill__separator,
    .toolbar-pill--sort .toolbar-pill__sub {
        display: none;
    }
}


/*
city-groups.css

QUOI : Affichage groupé ville par ville (accueil par défaut) : sections, bouton « voir plus », spinner et états vides de résultats.

COMMENT : Copie telle quelle des lignes 1332–1586 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ===================== Affichage groupé ville par ville (accueil par défaut) ===================== */
.city-section[hidden],
.events-section[hidden] {
    display: none;
}

.city-block {
    margin-top: var(--space-lg, 2rem);
}

.city-block:first-of-type {
    margin-top: var(--space-md, 1.25rem);
}

.city-block__header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.5rem 1rem;
    margin-bottom: 0.9rem;
    padding-bottom: 0.5rem;
    border-bottom: 1.5px solid var(--c-bordure);
}

.city-block__title {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    margin: 0;
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--c-marine);
}

.city-block__title .icon-pin {
    width: 18px;
    height: 18px;
    color: var(--c-corail);
    flex-shrink: 0;
}

.city-block__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    height: 22px;
    padding: 0 0.45rem;
    font-size: 0.78rem;
    font-weight: 700;
    line-height: 1;
    color: var(--c-marine);
    background-color: var(--c-sable, rgba(245, 233, 212, 0.7));
    border-radius: 999px;
    font-variant-numeric: tabular-nums;
}

.city-block__all {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--c-mer);
    text-decoration: none;
    white-space: nowrap;
    transition: color var(--duration-fast) var(--ease-out), gap var(--duration-fast) var(--ease-out);
}

.city-block__all:hover {
    color: var(--c-marine);
    gap: 0.5rem;
}

.city-block__all svg {
    flex-shrink: 0;
}

.city-section__empty {
    margin: var(--space-lg, 2rem) 0;
    text-align: center;
    color: var(--c-texte-doux);
}

.city-section__empty[hidden] {
    display: none;
}

.load-more-wrapper {
    display: flex;
    justify-content: center;
    margin: 2rem 0 0.5rem;
}

/* `.load-more-btn { display: inline-flex }` l'emporterait sur l'attribut `hidden` (display:none de
   l'UA, priorité plus faible qu'un sélecteur de classe). Sans ces règles, le bouton resterait visible
   et cliquable une fois les résultats épuisés. On masque le bouton ET on replie son conteneur. */
.load-more-btn[hidden] {
    display: none;
}

.load-more-wrapper:has(> .load-more-btn[hidden]) {
    display: none;
}

.load-more-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-height: 48px;
    padding: 0.8rem 1.85rem;
    font-size: 0.95rem;
    font-family: inherit;
    font-weight: 600;
    color: var(--c-blanc);
    background: linear-gradient(135deg, var(--c-marine) 0%, var(--c-mer) 100%);
    border: 1px solid var(--c-marine);
    border-radius: 999px;
    cursor: pointer;
    box-shadow: 0 4px 14px rgba(10, 61, 98, 0.22);
    transition: background-color var(--duration-fast) var(--ease-out),
                transform var(--duration-fast) var(--ease-out),
                box-shadow var(--duration-fast) var(--ease-out);
}

.load-more-btn:hover {
    background-color: var(--c-mer);
    border-color: var(--c-mer);
    transform: translateY(-1px);
    box-shadow: 0 4px 14px rgba(10, 61, 98, 0.22);
}

.load-more-btn:active {
    transform: translateY(0);
}

.load-more-btn:disabled {
    opacity: 0.6;
    cursor: progress;
    transform: none;
}

/* Bouton « Charger plus » du flux par défaut de l'accueil (`home-load-more.js`) — même famille
   visuelle que `.load-more-btn` ci-dessus (résultats filtrés) via l'utilitaire `.btn.btn--ghost`,
   juste centré sous la grille. */
.home-load-more {
    display: flex;
    justify-content: center;
    margin: 2rem 0 0.5rem;
}

.home-load-more .btn:disabled {
    opacity: 0.6;
    cursor: progress;
    transform: none;
}

.geo-status {
    margin: 0.4rem 0 0;
    font-size: 0.75rem;
    color: var(--c-texte-doux);
    font-style: italic;
    text-align: center;
}

.search-spinner {
    position: absolute;
    right: var(--space-sm);
    top: 50%;
    width: 18px;
    height: 18px;
    margin-top: -9px;
    border: 2px solid var(--c-bordure);
    border-top-color: var(--c-mer);
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
    pointer-events: none;
}

.search-spinner[hidden] {
    display: none;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

.search-input[aria-busy="true"] {
    padding-right: 3rem;
}


.events-section,
.city-section {
    padding: var(--space-md) 0 var(--space-xl);
}

.events-grid {
    display: grid;
    /* `minmax(0, 1fr)` (et non `1fr` = `minmax(auto, 1fr)`) : sans ça, la taille min-content d'une
       carte — surtout l'image de couverture — empêche la piste de descendre sous sa largeur naturelle,
       la grille déborde alors de son conteneur (overflow mobile) et les tiers se déforment sur desktop. */
    grid-template-columns: minmax(0, 1fr);
    gap: 1.1rem;
}

@media (min-width: 600px) {
    .events-grid {
        gap: var(--space-md);
    }
}

.results-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    text-align: center;
    padding: var(--space-lg) var(--space-md);
    color: var(--c-texte-doux);
    font-size: 1rem;
    background-color: var(--c-sable-clair);
    border-radius: var(--radius-md);
    border: 1px dashed var(--c-bordure);
    animation: results-empty-in 0.3s var(--ease-out);
}

.results-empty[hidden] {
    display: none;
}

.results-empty strong {
    display: block;
    color: var(--c-marine);
    font-size: 1.05rem;
    font-weight: 700;
}

.results-empty__icon {
    font-size: 1.8rem;
    line-height: 1;
    opacity: 0.85;
    margin-bottom: 0.25rem;
}

.results-empty__hint {
    display: block;
    font-size: 0.85rem;
    color: var(--c-texte-doux);
    font-style: italic;
    margin-top: 0.25rem;
}

.results-empty--with-suggestions {
    background-color: rgba(74, 144, 184, 0.06);
    border-color: var(--c-mer-clair);
    border-style: solid;
}

.results-empty--with-suggestions strong {
    color: var(--c-marine);
}

@keyframes results-empty-in {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}


/*
map.css

QUOI : Carte d'accueil Leaflet : conteneur, pins et marqueurs (dont cluster et « ma position »), popups simples et listes.

COMMENT : Copie telle quelle des lignes 1587–1995 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ---------- Carte d’accueil (Leaflet + pins) ---------- */

.home-map-section {
    margin-bottom: var(--space-lg);
    background-color: var(--c-blanc);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-lg);
    padding: var(--space-md);
    box-shadow: var(--shadow-xs);
    overflow: hidden;
    max-height: 720px;
    opacity: 1;
    transition: max-height 320ms var(--ease-out),
                opacity 220ms var(--ease-out),
                margin 220ms var(--ease-out),
                padding 220ms var(--ease-out),
                border-color 220ms var(--ease-out);
}

.home-map-section.is-collapsed {
    max-height: 0;
    margin-top: 0;
    margin-bottom: 0;
    padding-top: 0;
    padding-bottom: 0;
    border-color: transparent;
    opacity: 0;
    pointer-events: none;
}

.home-map-section__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-sm);
    margin-bottom: var(--space-sm);
    flex-wrap: wrap;
}

.home-map-section__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    margin: -0.25rem -0.5rem -0.25rem 0;
    color: var(--c-texte-doux);
    background-color: transparent;
    border: 1px solid transparent;
    border-radius: 999px;
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-out),
                color var(--duration-fast) var(--ease-out),
                border-color var(--duration-fast) var(--ease-out);
}

.home-map-section__close:hover {
    color: var(--c-marine);
    background-color: var(--c-sable-clair);
    border-color: var(--c-bordure);
}

.home-map-section__close:focus-visible {
    outline: 2px solid var(--c-mer);
    outline-offset: 2px;
}

.home-map-section__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--c-marine);
}

.home-map-section__hint {
    margin: 0;
    font-size: 0.85rem;
    color: var(--c-texte-doux);
}

.section-heading {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.2rem;
    margin-bottom: var(--space-md);
}

.section-heading__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--c-marine);
}

/* Pastille compteur à côté du titre de section (« Événements à venir 267 », « Résultats 12 ») :
   remplace l'ancien paragraphe `#results-count` du hero. Tailles en `em` : la pastille suit
   l'échelle du titre qui la porte (1.25rem ici, clamp jusqu'à 2.1rem via home-bento.css).
   Jetons `--c-niveau-normale-*` (bleu mer sur voile bleu) : déjà remappés par theme-dark.css,
   la pastille suit les deux thèmes sans règle supplémentaire. */
.section-heading__count {
    display: inline-block;
    vertical-align: 0.18em;
    margin-left: 0.45em;
    padding: 0.14em 0.5em;
    border-radius: 999px;
    font-family: var(--font-base);
    font-size: 0.48em;
    font-weight: 700;
    line-height: 1.5;
    letter-spacing: 0;
    font-variant-numeric: tabular-nums;
    background: var(--c-niveau-normale-fond);
    color: var(--c-niveau-normale-texte);
}

/* `display` explicite ci-dessus : sans cette règle, il l'emporterait sur le `[hidden]` natif
   (pastille des résultats masquée tant qu'aucune recherche n'est active). */
.section-heading__count[hidden] {
    display: none;
}

.section-heading__subtitle {
    margin: 0;
    font-size: 0.88rem;
    color: var(--c-texte-doux);
}

.home-events-map {
    height: 280px;
    width: 100%;
    border-radius: var(--radius-md);
    overflow: hidden;
    border: 1px solid var(--c-bordure);
    box-shadow: var(--shadow-sm);
    background: linear-gradient(160deg, #e8f4fc 0%, var(--c-sable-clair) 100%);
    z-index: 0;
}

@media (min-width: 600px) {
    .home-events-map {
        height: 360px;
    }
}

.home-events-map--empty {
    opacity: 0.65;
}

.home-events-map .leaflet-container {
    height: 100%;
    width: 100%;
    font-family: var(--font-base);
}

.home-map-empty {
    margin: var(--space-xs) 0 0;
    font-size: 0.9rem;
    color: var(--c-texte-doux);
    text-align: center;
}

/* Échec de chargement de la carte (Leaflet KO ou tuiles indisponibles) : le canvas est
   grisé (classe --error, ajoutée par home-map.js) et le message explique la cause. */
.home-events-map--error {
    opacity: 0.55;
    filter: grayscale(1);
}

/* `:not([hidden])` : sans lui, `display:flex` (spécificité de classe) l'emporte sur la règle
   native `[hidden]{display:none}` du navigateur → la boîte d'erreur (vide tant que Leaflet charge
   bien) resterait affichée en permanence dès que la section carte est dépliée. */
.home-map-error:not([hidden]) {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    gap: 0.4rem;
    margin: var(--space-sm) 0 0;
    padding: var(--space-sm);
    font-size: 0.9rem;
    line-height: 1.45;
    text-align: center;
    color: var(--c-corail-fonce);
    background-color: #fbe9e7;
    border: 1px solid var(--c-corail);
    border-radius: var(--radius-sm);
}

/* ---------- Pins et marqueurs (home-map-marker*, home-map-user*) ---------- */

.home-map-marker-wrap {
    background: transparent;
    border: none;
}

.home-map-marker {
    position: relative;
    width: 28px;
    height: 28px;
    background: radial-gradient(circle at 35% 35%, var(--c-corail) 0%, var(--c-corail-fonce) 100%);
    border: 3px solid var(--c-blanc);
    border-radius: 50%;
    box-shadow: 0 6px 16px rgba(10, 61, 98, 0.35);
    cursor: pointer;
}

.home-map-marker::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 8px;
    height: 8px;
    background-color: var(--c-blanc);
    border-radius: 50%;
}

/* Pin "cluster" : utilisé quand plusieurs événements partagent les mêmes coordonnées.
   On masque le point central blanc (::after) et on affiche le compteur à la place. */
.home-map-marker--cluster {
    width: 34px;
    height: 34px;
    background: radial-gradient(circle at 35% 30%, var(--c-mer-clair) 0%, var(--c-marine) 100%);
    box-shadow: 0 6px 18px rgba(10, 61, 98, 0.45);
}

.home-map-marker--cluster::after {
    display: none;
}

.home-map-marker__count {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--c-blanc);
    font-family: var(--font-display);
    font-size: 0.85rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-shadow: 0 1px 2px rgba(10, 61, 98, 0.4);
}

/* Marqueur « Ma position » : point bleu pulsant, convention universelle. */
.home-map-user-wrap {
    background: transparent;
    border: none;
}

.home-map-user-marker {
    position: relative;
    width: 22px;
    height: 22px;
}

.home-map-user-marker__dot {
    position: absolute;
    inset: 4px;
    background: var(--c-mer);
    border: 3px solid var(--c-blanc);
    border-radius: 50%;
    box-shadow: 0 4px 10px rgba(10, 61, 98, 0.45);
    z-index: 2;
}

.home-map-user-marker__pulse {
    position: absolute;
    inset: 0;
    background-color: var(--c-mer);
    border-radius: 50%;
    opacity: 0.45;
    transform-origin: center;
    animation: home-map-user-pulse 2s infinite ease-out;
    z-index: 1;
}

@keyframes home-map-user-pulse {
    0% {
        transform: scale(0.6);
        opacity: 0.55;
    }
    100% {
        transform: scale(2.2);
        opacity: 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .home-map-user-marker__pulse {
        animation: none;
        opacity: 0.3;
    }
}

/* ---------- Popups Leaflet (home-map-popup*) ---------- */

.home-map-popup-wrap .leaflet-popup-content-wrapper {
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    padding: 0;
}

.home-map-popup-wrap .leaflet-popup-content {
    margin: 0;
    min-width: 200px;
}

.home-map-popup-wrap--cluster .leaflet-popup-content {
    min-width: 260px;
}

.home-map-popup {
    padding: var(--space-sm);
}

.home-map-popup__category {
    margin: 0 0 0.2rem;
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--c-mer);
}

.home-map-popup__title {
    margin: 0 0 0.35rem;
    font-size: 1rem;
    font-weight: 700;
    line-height: 1.3;
    color: var(--c-marine);
}

.home-map-popup__meta {
    margin: 0 0 0.6rem;
    font-size: 0.82rem;
    color: var(--c-texte-doux);
}

.home-map-popup__link {
    display: inline-block;
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--c-corail-fonce);
    text-decoration: none;
}

.home-map-popup__link:hover {
    text-decoration: underline;
}

/* Popup "cluster" : en-tête + liste d'événements. Le scroll est délégué à Leaflet
   (option `maxHeight` du bindPopup → classe .leaflet-popup-scrolled) pour que la
   popup ne dépasse jamais les dimensions de la carte. */
.home-map-popup--cluster {
    padding: 0;
}

.home-map-popup-wrap--cluster .leaflet-popup-scrolled {
    border-bottom: 1px solid transparent;
}

.home-map-popup__header {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.55rem 0.7rem;
    border-bottom: 1px solid var(--c-bordure);
    background: linear-gradient(180deg, var(--c-sable-clair) 0%, var(--c-blanc) 100%);
    position: sticky;
    top: 0;
    z-index: 1;
}

.home-map-popup__badge {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 26px;
    height: 26px;
    padding: 0 0.35rem;
    border-radius: 999px;
    background: radial-gradient(circle at 35% 30%, var(--c-corail-action) 0%, var(--c-corail-action-fonce) 100%);
    color: var(--c-blanc);
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.8rem;
    box-shadow: 0 2px 6px rgba(198, 96, 60, 0.35);
}

.home-map-popup__eyebrow {
    margin: 0;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--c-marine);
    line-height: 1.2;
}

.home-map-popup--cluster .home-map-popup__meta {
    margin: 0.1rem 0 0;
    font-size: 0.78rem;
    line-height: 1.2;
}

.home-map-popup-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.home-map-popup-list__item + .home-map-popup-list__item {
    border-top: 1px solid var(--c-bordure);
}

.home-map-popup-list__link {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    padding: 0.45rem 0.7rem;
    text-decoration: none;
    color: inherit;
    transition: background-color var(--duration-fast) var(--ease-out);
}

.home-map-popup-list__link:hover,
.home-map-popup-list__link:focus-visible {
    background-color: var(--c-sable-clair);
    outline: none;
}

.home-map-popup-list__category {
    font-size: 0.66rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--c-mer);
}

.home-map-popup-list__title {
    font-size: 0.88rem;
    font-weight: 700;
    line-height: 1.25;
    color: var(--c-marine);
}

.home-map-popup-list__date {
    font-size: 0.76rem;
    color: var(--c-texte-doux);
}

@media (min-width: 768px) {
    .home-events-map {
        height: 420px;
    }
}


/*
event-card.css

QUOI : Carte événement : lien-carte, tuile date « ticket », couleurs par catégorie (data-cat), titre, description et états.

COMMENT : Copie telle quelle des lignes 1996–2318 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

.event-card-link,
.event-card-link:any-link,
.event-card-link:visited,
.event-card-link:hover,
.event-card-link:active,
.event-card-link:focus,
.event-card-link:focus-visible {
    display: block;
    height: 100%;
    color: inherit;
    text-decoration: none;
    -webkit-text-decoration: none;
}

.event-card-link *,
.event-card-link h2,
.event-card-link p,
.event-card-link span {
    text-decoration: none;
}

.event-card-link .event-card__title {
    color: var(--c-marine);
}

.event-card-link .event-card__description {
    color: var(--c-texte-doux);
}

.event-card-link .event-card__ville > span {
    color: var(--c-texte);
}

.event-card-link:hover .event-card__title {
    color: var(--c-mer);
}

.event-card {
    position: relative;
    background-color: var(--c-blanc);
    border-radius: var(--radius-lg);
    padding: var(--space-md);
    box-shadow:
        0 1px 2px rgba(10, 61, 98, 0.04),
        0 8px 20px -14px rgba(10, 61, 98, 0.22);
    border: 1px solid rgba(10, 61, 98, 0.15); /* 0.08 → 0.15 : retouche contraste 2026-07-10 */
    border-left: 3px solid var(--cat-color);
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    height: 100%;
    transition: transform var(--duration-base) var(--ease-out),
                box-shadow var(--duration-base) var(--ease-out),
                border-color var(--duration-base) var(--ease-out);
}

.event-card::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg, transparent 0%, transparent 60%, rgba(74, 144, 184, 0.04) 100%);
    opacity: 0;
    transition: opacity var(--duration-base) var(--ease-out);
    pointer-events: none;
    border-radius: inherit;
    z-index: 0;
}

.event-card > * {
    position: relative;
    z-index: 1;
}

@media (hover: hover) {
    .event-card:hover {
        transform: translateY(-4px);
        box-shadow:
            0 2px 4px rgba(10, 61, 98, 0.05),
            0 18px 40px -18px rgba(10, 61, 98, 0.32);
        border-color: rgba(74, 144, 184, 0.45);
        border-left-color: var(--cat-color);
    }
}

.event-card:active {
    transform: translateY(-1px);
    box-shadow: var(--shadow-md);
}

.event-card:hover::before {
    opacity: 1;
}

.secondary-section {
    margin-top: var(--space-lg);
    padding-bottom: var(--space-xl);
}

.secondary-section[hidden] {
    display: none;
}

.secondary-divider {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin: 0 0 var(--space-sm);
}

.secondary-divider__line {
    flex: 1;
    height: 1px;
    background: linear-gradient(to right, transparent, var(--c-bordure), transparent);
}

.secondary-divider__label {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--c-mer);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    white-space: nowrap;
}

.secondary-divider__icon {
    color: var(--c-corail);
    flex-shrink: 0;
}

.secondary-note {
    text-align: center;
    margin: 0 auto var(--space-md);
    max-width: 560px;
    font-size: 0.85rem;
    color: var(--c-texte-doux);
    font-style: italic;
    line-height: 1.5;
}

.events-grid--secondary {
    opacity: 0.92;
}

.event-card--secondary {
    background-color: var(--c-sable-clair);
    border-style: dashed;
    border-color: var(--c-bordure);
    box-shadow: none;
}

.event-card--secondary:hover {
    background-color: var(--c-blanc);
    border-style: solid;
}

.event-card--secondary .event-card__title {
    color: var(--c-mer);
}

.icon-pin {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    stroke-width: 2.2;
    color: var(--c-mer);
}

.event-card__ville {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.35rem;
    margin: 0;
    font-size: 0.95rem;
    color: var(--c-texte-doux);
    font-weight: 500;
}

.event-card__ville-place {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-width: 0;
}

.event-card__ville-place > span {
    color: var(--c-texte);
}

/* Marques de droite : logo "nos events" (soumission manuelle uniquement) + chevron cliquable
   (toutes les cartes). Volontairement très discrètes — cf. spec 2026-08-20, PRODUCT.md
   « confiance éditoriale » : on valorise nos events plutôt que d'étiqueter les imports. */
.event-card__ville-marks {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex-shrink: 0;
    color: var(--c-texte-doux);
}

/* Marque « événement Opalenews » : le demi-disque du logo, dans une pastille marine de 20 px (à 11 px nu, gris
   sur blanc, il était illisible — audit ordinateur du 27/10/2026) ; infobulle au survol (`title`). */
.event-card__own-badge {
    display: inline-grid;
    place-items: center;
    width: 20px;
    height: 20px;
    font-size: 0.8rem;
    line-height: 1;
    color: #f5e9d4;
    background: #0a3d62;
    border-radius: 999px;
    cursor: help;
}

.event-card__click-chevron {
    width: 13px;
    height: 13px;
    flex-shrink: 0;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.event-card__distance {
    display: inline-flex;
    align-items: center;
    margin-left: 0.5rem;
    padding: 0.15rem 0.55rem;
    font-size: 0.72rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--c-mer);
    background-color: rgba(30, 96, 145, 0.10);
    border-radius: 999px;
    letter-spacing: 0.2px;
}

.event-card__header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.8rem;
}

/* Tuile date (style « ticket événement ») — ancre visuelle premium de la carte. */
.event-card__date-tile {
    flex-shrink: 0;
    width: 50px;
    border-radius: 12px;
    overflow: hidden;
    text-align: center;
    line-height: 1;
    font-style: normal;
    background-color: var(--c-blanc);
    border: 1px solid var(--c-bordure);
    box-shadow: 0 3px 9px -3px rgba(10, 61, 98, 0.22);
}

/* ----- Couleur par catégorie (galerie « vivante ») -----
   Chaque carte porte data-cat="<slug>" → teinte appliquée à la tuile date, la pastille et le liseré.
   Slugs alignés sur Category (Marché→marche, Conférence→conference, Découverte→decouverte). */
/* `--cat-fond` : dégradé des pastilles à texte blanc (catégorie, bandeau du mois), assombri depuis la teinte de
   la catégorie pour tenir 4.5:1 avec le blanc sur toutes les catégories (la teinte pure tombait à 2.7:1 sur
   Atelier, 3.3:1 sur Sport — mesuré le 27/10/2026). Déclaré sur `.event-card` ET `.lieu-card` (pastilles de lieux). */
:is(.event-card, .lieu-card) {
    --cat-fond: linear-gradient(135deg, color-mix(in srgb, var(--cat-color) 74%, #000) 0%, color-mix(in srgb, var(--cat-color) 56%, #000) 100%);
}

.event-card { --cat-color: var(--c-corail); }
.event-card[data-cat="musique"]     { --cat-color: #7c5cc4; }
.event-card[data-cat="sport"]       { --cat-color: #2f9e6b; }
.event-card[data-cat="culture"]     { --cat-color: #3f6cb0; }
.event-card[data-cat="brocante"]    { --cat-color: #a9763f; }
.event-card[data-cat="marche"]      { --cat-color: #6a9a3c; }
.event-card[data-cat="gastronomie"] { --cat-color: #d6603c; }
.event-card[data-cat="famille"]     { --cat-color: #2a9d9d; }
.event-card[data-cat="festival"]    { --cat-color: #d14d9a; }
.event-card[data-cat="atelier"]     { --cat-color: #e08a2e; }
.event-card[data-cat="conference"]  { --cat-color: #5566a8; }
.event-card[data-cat="decouverte"]  { --cat-color: #1e6091; }
.event-card[data-cat="spectacle"]   { --cat-color: #b23a5e; }
.event-card[data-cat="exposition"]  { --cat-color: #8c6d3f; }
.event-card[data-cat="nature"]      { --cat-color: #3b8f4e; }
.event-card[data-cat="salon"]       { --cat-color: #6f7fa6; }
.event-card[data-cat="soiree"]      { --cat-color: #4b3f9e; }

.event-card__date-tile-m {
    display: block;
    padding: 0.28rem 0;
    background: var(--cat-fond);
    color: #fff;
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.event-card__date-tile-d {
    display: block;
    padding: 0.32rem 0 0.4rem;
    color: var(--c-marine);
    font-size: 1.3rem;
    font-weight: 800;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
}

/* Date approximative (pas de jour précis, cf. Event::getDayLabel) : la tuile n'a que le bandeau mois —
   on lui redonne la hauteur qu'aurait le duo mois/jour plutôt que de laisser un simple ruban étriqué. */
.event-card__date-tile--approximate .event-card__date-tile-m {
    padding: 0.62rem 0;
}

/* Événement déjà commencé (cf. Event::isEnCours) : bandeau seul « En cours », sur deux lignes si besoin —
   la largeur de la tuile (50px) ne loge pas « EN COURS » d'un seul tenant. */
.event-card__date-tile--ongoing .event-card__date-tile-m {
    padding: 0.5rem 0.15rem;
    line-height: 1.2;
    letter-spacing: 0.02em;
    white-space: normal;
}

.event-card__heading-text {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.3rem;
    min-width: 0;
}

.event-card__category {
    display: inline-block;
    background: var(--cat-fond);
    color: var(--c-blanc);
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0.26rem 0.7rem;
    border-radius: 999px;
    box-shadow: 0 2px 6px -2px color-mix(in srgb, var(--cat-color) 55%, transparent);
}

.event-card__date {
    font-size: 0.82rem;
    color: var(--c-texte-doux);
    font-weight: 600;
}

/* Événement « Incontournable » : tuile date dorée. */
.event-card--featured .event-card__date-tile-m {
    background: linear-gradient(135deg, #d4af37 0%, #b89522 100%);
    color: #3a2e06;
}

.event-card__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.15rem;
    color: var(--c-marine);
    line-height: 1.3;
    font-weight: 700;
    letter-spacing: -0.01em;
    overflow-wrap: anywhere;
    /* Sans plafond, un titre long grandit la carte au-delà de la hauteur imposée par la grille
       (stretch sur la carte la plus haute de la rangée) et son contenu déborde silencieusement du
       cadre — deux titres de longueurs différentes rendaient alors des cartes de tailles visiblement
       différentes. Même traitement que .event-card__description (line-clamp), pour que la hauteur de
       la carte ne dépende plus jamais du nombre de mots du titre. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

@media (min-width: 768px) {
    .event-card__title {
        font-size: 1.2rem;
    }
}

.event-card__description {
    margin: var(--space-xs) 0 0;
    font-size: 0.92rem;
    color: var(--c-texte-doux);
    line-height: 1.55;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.event-card[hidden] {
    display: none;
}



/* ----- Couleur par catégorie de LIEU -----
   Même mécanique que pour les événements : la carte porte `data-cat="<slug>"`, la teinte descend
   dans la pastille et le liseré par `--cat-color`. Sans cet attribut, les seize catégories de lieux
   sortaient toutes en corail — la pastille disait le type sans qu'on le voie.

   Les teintes sont choisies pour évoquer leur sujet (le rouge des phares, le vitrail pour le
   religieux, l'ardoise pour les fortifications) ET pour rester lisibles : le blanc sur chacune tient
   au moins 4.5:1 en moyenne sur le dégradé, mesuré sur les deux extrémités. C'est ce qui écarte les
   tons clairs qu'on aurait pu vouloir pour la plage ou la balade. */
.lieu-card[data-cat="plage"]             { --cat-color: #0c7d96; }
.lieu-card[data-cat="falaise"]           { --cat-color: #4a7a92; }
.lieu-card[data-cat="musee"]             { --cat-color: #4a5fa8; }
.lieu-card[data-cat="edifice-religieux"] { --cat-color: #6b4f9e; }
.lieu-card[data-cat="chateau"]           { --cat-color: #8f3f52; }
.lieu-card[data-cat="fortification"]     { --cat-color: #5a6472; }
.lieu-card[data-cat="monument"]          { --cat-color: #8a6a3a; }
.lieu-card[data-cat="phare"]             { --cat-color: #c2452d; }
.lieu-card[data-cat="nature-et-jardin"]  { --cat-color: #3d8a52; }
.lieu-card[data-cat="parc-de-loisirs"]   { --cat-color: #c9497f; }
.lieu-card[data-cat="balade"]            { --cat-color: #5f7d35; }
.lieu-card[data-cat="village"]           { --cat-color: #b06a45; }
.lieu-card[data-cat="point-de-vue"]      { --cat-color: #2f7fa8; }
.lieu-card[data-cat="restaurant"]        { --cat-color: #c85a3c; }
.lieu-card[data-cat="hebergement"]       { --cat-color: #4f5b9c; }
.lieu-card[data-cat="commerce"]          { --cat-color: #8b5a8f; }

/* La pastille du hero d'une fiche lieu prend la teinte de sa catégorie. Elle est codée en corail
   dans `event-detail-main.css`, écrit pour les événements où le hero porte déjà la couleur ailleurs.
   L'ombre suit la teinte : une ombre corail sous une pastille violette se voit. */
.event-hero__category.lieu-card {
    background: var(--cat-fond);
    box-shadow: 0 4px 12px color-mix(in srgb, var(--cat-color) 45%, transparent);
}

/* Titre de section sur /lieux : un filet de la couleur du groupe, à gauche du libellé. Assez pour
   relier la section à ses cartes, sans transformer le titre en pastille. */
.section-title.lieu-card {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.section-title.lieu-card::before {
    content: "";
    flex: none;
    width: 0.28rem;
    height: 1.1em;
    border-radius: 999px;
    background: var(--cat-color);
}

/* Flèche « cliquable » : sur ordinateur, elle n'apparaît qu'au survol de la carte (glisse de 4 px) ; au repos
   elle n'ajoutait qu'un signe illisible de 13 px à chaque carte. Écrans tactiles : inchangé. */
@media (hover: hover) {
    .event-card__click-chevron {
        opacity: 0;
        transform: translateX(-4px);
        transition: opacity var(--duration-base) var(--ease-out), transform var(--duration-base) var(--ease-out);
    }

    .event-card-link:is(:hover, :focus-visible) .event-card__click-chevron {
        opacity: 1;
        transform: none;
        color: var(--c-action);
    }
}

/*
footer.css

QUOI : Pied de page premium : grille bento (identité, navigation, maillage SEO), réseaux sociaux et barre copyright/mentions.

COMMENT : Copie telle quelle des lignes 2319–2611 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ============================ Pied de page premium ============================
   Mobile-first STRICT : sections verticales aérées (gap 2rem), cibles tactiles ≥ 48px.
   Desktop ≥768px : grille Bento asymétrique (identité large + 3 colonnes scannables).
   Conserve le voile marine / texte sable de la charte (et le mode sombre plus bas). */
.site-footer {
    position: relative;
    background-color: var(--c-marine);
    color: var(--c-sable);
    margin-top: auto;
    padding-top: var(--space-md);
    padding-bottom: calc(var(--space-md) + env(safe-area-inset-bottom));
    font-size: var(--fs-sm);
    line-height: 1.6;
}

/* Filet lumineux discret en haut du pied de page (finition haut de gamme). */
.site-footer::before {
    content: "";
    position: absolute;
    inset: 0 0 auto;
    height: 1px;
    background: linear-gradient(90deg, transparent 0%, rgba(245, 233, 212, 0.22) 50%, transparent 100%);
}

/* ── Grille des blocs (vertical mobile, bento desktop) ── */
.site-footer__inner {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.75rem;
    padding-top: var(--space-lg);
    padding-bottom: var(--space-md);
}

/* Maillage SEO (catégories / villes) : masqué sur mobile pour alléger le pied de page,
   réaffiché en bento sur desktop (≥768px) plus bas. */
.site-footer__col--seo {
    display: none;
}

/* Bloc 1 — Identité : marque + accroche touristique + réseaux. */
.site-footer__identity {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.site-footer__logo {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 1.4rem;
    letter-spacing: -0.02em;
    color: var(--c-blanc);
    text-decoration: none;
    transition: opacity var(--duration-fast) var(--ease-out);
}

.site-footer__logo .logo-mark {
    color: var(--c-sable);
    font-size: 1.7rem;
    line-height: 1;
}

.site-footer__logo:hover,
.site-footer__logo:focus-visible {
    opacity: 0.9;
    outline: none;
}

.site-footer__pitch {
    margin: 0;
    max-width: 42ch;
    color: var(--c-sable);
    opacity: 0.74;
    font-size: 0.9rem;
    line-height: 1.65;
}

/* Réseaux sociaux (profils Coteo) — icônes minimalistes, survol progressif. */
.site-footer__social {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-top: 0.15rem;
}

.site-footer__social-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    color: var(--c-sable);
    background-color: rgba(245, 233, 212, 0.08);
    border: 1px solid rgba(245, 233, 212, 0.16);
    border-radius: 999px;
    -webkit-tap-highlight-color: transparent;
    transition: color var(--duration-base) var(--ease-out),
                background-color var(--duration-base) var(--ease-out),
                border-color var(--duration-base) var(--ease-out),
                transform var(--duration-base) var(--ease-out);
}

.site-footer__social-link svg {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.site-footer__social-link:hover,
.site-footer__social-link:focus-visible {
    color: var(--c-marine);
    background-color: var(--c-sable);
    border-color: var(--c-sable);
    transform: translateY(-2px);
    outline: none;
}

.site-footer__social-link:focus-visible {
    outline: 2px solid var(--c-sable);
    outline-offset: 3px;
}

/* Blocs 2-4 — colonnes (navigation rapide + maillage SEO catégories/villes). */
.site-footer__heading {
    margin: 0 0 0.6rem;
    font-family: var(--font-display);
    font-size: 0.78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--c-sable);
    opacity: 0.95;
}

/* Mobile-first : listes en 2 colonnes serrées → le pied de page ne « mesure plus 10 km ».
   Tous les liens restent visibles (maillage SEO intact). Repasse en 1 colonne en bento desktop. */
.site-footer__list {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.1rem 1rem;
}

/* Liens : cible tactile ≥ 44px sur mobile + soulignement linéaire moderne (sans décalage du texte). */
.site-footer__list a {
    position: relative;
    display: inline-flex;
    align-items: center;
    align-self: flex-start;
    min-height: 44px;
    padding: 0.15rem 0;
    color: var(--c-sable);
    opacity: 0.82;
    font-size: 0.92rem;
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    transition: opacity var(--duration-fast) var(--ease-out),
                color var(--duration-fast) var(--ease-out);
}

.site-footer__list a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0.7rem;
    height: 1.5px;
    border-radius: 2px;
    background-color: var(--c-sable);
    transform: scaleX(0);
    transform-origin: left center;
    opacity: 0.65;
    transition: transform var(--duration-base) var(--ease-out);
}

.site-footer__list a:hover,
.site-footer__list a:focus-visible {
    opacity: 1;
    outline: none;
}

.site-footer__list a:hover::after,
.site-footer__list a:focus-visible::after {
    transform: scaleX(0.5);
}

.site-footer__list a:focus-visible {
    outline: 2px solid var(--c-sable);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

/* ── Barre du bas : copyright + mentions légales / accès discrets ── */
.site-footer__bottom {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
    padding-top: var(--space-md);
    border-top: 1px solid rgba(245, 233, 212, 0.16);
}

/* Téléphone : la bulle de l'assistant (56 px, fixée en bas à gauche) recouvrait les derniers liens (« Gérer mes
   choix », « Admin ») une fois arrivé en bas de page — on leur réserve sa hauteur (audit du 27/10/2026). */
@media (max-width: 767px) {
    .site-footer__bottom {
        padding-bottom: calc(76px + env(safe-area-inset-bottom, 0px));
    }
}

.site-footer__copy {
    margin: 0;
    font-size: 0.8rem;
    opacity: 0.62;
}

.site-footer__legal {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.1rem 1.1rem;
}

.site-footer__legal a {
    display: inline-flex;
    align-items: center;
    min-height: 48px;
    color: var(--c-sable);
    opacity: 0.72;
    font-size: 0.82rem;
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    transition: opacity var(--duration-fast) var(--ease-out);
}

.site-footer__legal a:hover,
.site-footer__legal a:focus-visible {
    opacity: 1;
    text-decoration: underline;
    text-underline-offset: 3px;
    outline: none;
}

.site-footer__legal a:focus-visible {
    outline: 2px solid var(--c-sable);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

.site-footer__admin {
    opacity: 0.5;
}

/* ── Desktop ≥768px : grille Bento asymétrique + cibles plus compactes (pointeur fin) ── */
@media (min-width: 768px) {
    .site-footer__inner {
        grid-template-columns: 1.7fr 1fr 1fr 1fr;
        gap: 2.5rem;
        align-items: start;
    }

    /* Réaffiche le maillage SEO masqué sur mobile. */
    .site-footer__col--seo {
        display: block;
    }

    /* Bento : chaque rubrique = sa propre colonne étroite → liste verticale (annule le 2-col mobile). */
    .site-footer__list {
        grid-template-columns: 1fr;
        gap: 0;
    }

    .site-footer__list a {
        min-height: 38px;
        font-size: 0.95rem;
    }

    .site-footer__legal a {
        min-height: 36px;
    }

    .site-footer__bottom {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: 1.5rem;
    }

    .site-footer__legal {
        justify-content: flex-end;
    }
}


/*
events-grid.css

QUOI : Points de rupture responsive de la grille d'événements (2 puis 3 colonnes) et padding de la zone de recherche en desktop.

COMMENT : Copie telle quelle des lignes 2612–2629 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/


@media (min-width: 600px) {
    .events-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 960px) {
    .events-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: var(--space-lg);
    }

    .search-section {
        padding: var(--space-xl) 0 var(--space-lg);
    }
}


/*
event-detail-extras.css

QUOI : Suggestions d'événements similaires en bas de fiche événement.

COMMENT : Copie telle quelle des lignes 2630–2662 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ---------- Suggestions similaires (fiche événement) ---------- */
.event-similar {
    margin-top: var(--space-xl);
    padding-top: var(--space-lg);
    border-top: 1px solid var(--c-bordure);
}

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

.event-similar__title {
    margin: 0 0 0.4rem;
    font-family: var(--font-display);
    font-size: 1.6rem;
    color: var(--c-marine);
}

.event-similar__subtitle {
    margin: 0;
    color: var(--c-texte-doux);
    font-size: 0.95rem;
}

.event-similar__subtitle::before {
    content: '✨';
    margin-right: 0.4rem;
}

.event-similar__grid {
    margin-top: var(--space-sm);
}


/*
prose.css

QUOI : Pages textuelles (mentions légales, à propos, confidentialité) : gabarit .prose-page et lien retour intégré au hero.

COMMENT : Copie telle quelle des lignes 2663–2799 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/


/* ──────────────────────────────────────────────────
   Pages textuelles (mentions légales, à propos…)
   ────────────────────────────────────────────────── */

.prose-page {
    width: 100%;
    max-width: 720px;
    margin: 0 auto;
    /* Mobile-first : on évite le grand vide en haut ; respiration plus large ≥640px. */
    padding: var(--space-lg) max(var(--space-sm), env(safe-area-inset-left));
}

@media (min-width: 640px) {
    .prose-page {
        padding: var(--space-xl) var(--space-md);
    }
}

.prose-page h1 {
    font-family: var(--font-display);
    font-size: clamp(1.8rem, 4vw, 2.4rem);
    font-weight: 800;
    color: var(--c-marine);
    letter-spacing: -0.025em;
    line-height: 1.15;
    margin: 0 0 var(--space-lg);
    padding-bottom: var(--space-md);
    border-bottom: 2px solid var(--c-bordure);
}

.prose-page h2 {
    font-family: var(--font-display);
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--c-marine);
    margin: var(--space-lg) 0 var(--space-xs);
    padding-left: 0.875rem;
    border-left: 3px solid var(--c-corail);
    line-height: 1.3;
}

.prose-page h3 {
    font-size: 1rem;
    font-weight: 600;
    color: var(--c-texte);
    margin: var(--space-md) 0 var(--space-xs);
}

.prose-page p {
    margin: 0 0 1em;
    line-height: 1.75;
    color: var(--c-texte);
}

.prose-page ul,
.prose-page ol {
    margin: 0 0 1.25em;
    padding-left: 1.5rem;
    line-height: 1.75;
    color: var(--c-texte);
}

.prose-page li {
    margin-bottom: 0.5em;
}

.prose-page a:not(.back-link) {
    color: var(--c-mer);
    text-decoration: underline;
    text-decoration-color: rgba(30, 96, 145, 0.35);
    text-underline-offset: 2px;
    transition: color var(--duration-fast), text-decoration-color var(--duration-fast);
}

.prose-page a:not(.back-link):hover {
    color: var(--c-marine);
    text-decoration-color: var(--c-marine);
}

.prose-page strong {
    font-weight: 600;
    color: var(--c-marine);
}

/* Lien retour en bas des pages textuelles + page partenaire.
   TEXTE NU (plus de pastille « badge ») : la pilule blanche à bordure était un badge daté ; le lien
   reprend la couleur de lien du site (`--c-mer`, remappée en bleu lumineux la nuit) et se souligne au
   survol. La flèche « ← » fait partie du libellé traduit. Lisible dans les deux thèmes sans règle
   dédiée : `--c-mer` = #1e6091 sur sable (clair) et #7cb8e2 sur encre (sombre). */
.back-link {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-top: var(--space-md);
    padding: 0;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--c-mer);
    background: none;
    border: 0;
    border-radius: 0;
    text-decoration: none;
    box-shadow: none;
    transition: color var(--duration-fast) var(--ease-out),
                gap var(--duration-fast) var(--ease-out);
}

.back-link:hover {
    color: var(--c-marine);
    gap: 0.55rem;
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* Première ligne du hero : libellé (kicker) à gauche, lien retour à droite, alignés sur la même
   ligne — au lieu d'un bouton flottant au-dessus qui créait une bande vide sous l'en-tête. */
/* Lien retour INTÉGRÉ dans le hero marine, en TEXTE NU — plus de pastille « verre ».
   Pourquoi : la pilule (padding + bordure + fond) était large, et sur les heros dont le kicker est
   long (« Publié sous 48h » sur /proposer-un-evenement) elle passait à la ligne sous le kicker au
   lieu de rester dans le coin droit, cassant la ligne unique voulue par `.page-hero__topline`.
   Le lien reprend donc exactement la typographie de `.page-hero__eyebrow` (coin gauche) : les deux
   extrémités de la ligne se répondent, et l'encombrement chute assez pour tenir sur une ligne.
   Le hero étant toujours sombre (thème clair ET sombre), aucun remappage dark n'est nécessaire. */
.page-hero .back-link {
    flex: 0 0 auto;
    /* Cible tactile ≥44px sans agrandir le texte visible ni pousser le kicker : le padding élargit
       la zone cliquable, la marge négative égale l'annule dans le flux de `.page-hero__topline`
       (raccourci « Retour aux événements » → « Retour » : la boîte de texte seule tombait à 17px
       de haut, sous le minimum WCAG 2.5.5 / 44px). */
    margin: -0.85rem 0;
    padding: 0.85rem 0;
    font-size: 0.76rem; /* 0.68rem (11 px) → 12 px, comme le surtitre : lisible sans casser la ligne unique (27/10/2026) */
    font-weight: 700;
    /* Interlettrage volontairement plus serré que le kicker (0.16em) : à 0.16em, « ← Retour aux
       événements » mesurait 219px et, avec le kicker à 151px, dépassait la ligne de 345px — le lien
       repassait donc SOUS le kicker. 0.07em conserve la parenté typographique en tenant sur une
       seule ligne. */
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--c-sable);
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}
.page-hero .back-link:hover {
    color: #fff;
    background: none;
    transform: none;
    text-decoration: underline;
    text-underline-offset: 3px;
}


/*
bento.css

QUOI : Grille bento « verre dépoli » générique des pages annexes (cartes, listes à pastilles check, alias .about-*).

COMMENT : Copie telle quelle des lignes 2800–2969 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ============================ Grille bento « verre dépoli » — système réutilisable ============================
   Pages texte / annexes (À propos, mentions légales, confidentialité, newsletter…) qui ne chargent QUE
   style.css. On déclare ici une grille bento GÉNÉRIQUE réutilisant les tokens --glass-* / --radius-* /
   --space-* et la classe .glass-card. `.about-*` est conservé comme alias de `.bento-*` pour ne pas casser
   la page À propos existante. Mobile-first : 1 colonne ; ≥720px : bento 2 colonnes, carte `--feature`
   en pleine largeur. */
.about-page,
.bento-page {
    width: 100%;
    max-width: 1100px;
    margin: 0 auto;
    padding: var(--space-lg) max(var(--space-sm), env(safe-area-inset-left));
}

@media (min-width: 640px) {
    .about-page,
    .bento-page {
        padding: var(--space-xl) var(--space-md);
    }
}

.about-bento,
.bento-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-md);
}

@media (min-width: 720px) {
    .about-bento,
    .bento-grid {
        grid-template-columns: repeat(2, 1fr);
    }
    .about-card--feature,
    .bento-card--feature {
        grid-column: 1 / -1;
    }
    /* Dernière carte seule sur sa rangée (après une carte « feature » pleine largeur, un nombre pair de
       cartes laisse la dernière orpheline) : pleine largeur plutôt qu'une demi-rangée vide (audit du
       27/10/2026). Cartes de texte seul, l'élargissement ne déforme rien. */
    .about-bento > .about-card--feature:first-child ~ :last-child:nth-child(even),
    .bento-grid > .bento-card--feature:first-child ~ :last-child:nth-child(even) {
        grid-column: 1 / -1;
    }
}

.about-card,
.bento-card {
    display: flex;
    flex-direction: column;
    padding: var(--space-lg);
    transition: transform var(--duration-base) var(--ease-out),
                box-shadow var(--duration-base) var(--ease-out);
}

.about-card:hover,
.bento-card:hover {
    transform: translateY(-3px);
}

.about-card h2,
.bento-card h2,
.bento-card h3 {
    font-family: var(--font-display);
    font-size: 1.2rem;
    font-weight: 700;
    color: var(--c-marine);
    line-height: 1.3;
    margin: 0 0 var(--space-sm);
    padding-left: 0.75rem;
    border-left: 3px solid var(--c-corail);
}

.about-card p,
.bento-card p {
    /* ~75 caractères par ligne au plus : sur ordinateur, la carte « À propos » faisait 970 px de large (115
       caractères par ligne, lecture pénible). En `em` et non en `ch` : avec Figtree, le « 0 » qui définit le `ch`
       est bien plus large que la lettre moyenne (60ch laissaient passer 88 caractères). */
    max-width: 32em;
    margin: 0 0 0.9em;
    line-height: 1.75;
    color: var(--c-texte);
}

/* Dernier bloc d'une carte : pas de marge basse résiduelle (p, ul, ol…). */
.about-card p:last-child,
.bento-card > :last-child {
    margin-bottom: 0;
}

.about-card--feature p,
.bento-card--feature p {
    font-size: 1.05rem;
}

.about-card strong,
.bento-card strong {
    font-weight: 600;
    color: var(--c-marine);
}

/* Listes au sein des cartes (page confidentialité). */
.bento-card ul,
.bento-card ol {
    margin: 0 0 0.9em;
    padding-left: 1.25rem;
    line-height: 1.75;
    color: var(--c-texte);
}

.bento-card li {
    margin-bottom: 0.45em;
}

.bento-card li:last-child {
    margin-bottom: 0;
}

/* `:not(.btn)` INDISPENSABLE : cette règle habille les liens de PROSE d'une carte, mais sa
   spécificité (0,2,1) l'emportait sur `.btn--primary` (0,1,0) — tout bouton posé dans une carte
   bento perdait son texte blanc au profit de `--c-mer`, soit du bleu de mer sur le dégradé marine
   du bouton : 3,14:1, sous le seuil WCAG AA (4,5:1). Constaté sur la page 404, mais le défaut
   était générique aux deux thèmes. */
.about-card a:not(.back-link):not(.btn),
.bento-card a:not(.back-link):not(.btn) {
    color: var(--c-mer);
    font-weight: 600;
    text-decoration: underline;
    text-decoration-color: rgba(30, 96, 145, 0.35);
    text-underline-offset: 2px;
    transition: color var(--duration-fast) var(--ease-out),
                text-decoration-color var(--duration-fast) var(--ease-out);
}

.about-card a:not(.back-link):not(.btn):hover,
.bento-card a:not(.back-link):not(.btn):hover {
    color: var(--c-marine);
    text-decoration-color: var(--c-marine);
}

.about-footer,
.bento-footer {
    margin-top: var(--space-lg);
}

/* Liste de bénéfices à pastilles « check » dans une carte bento (page newsletter…). */
.bento-benefits {
    list-style: none;
    margin: var(--space-sm) 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
}

.bento-benefits li {
    display: flex;
    align-items: flex-start;
    gap: 0.65rem;
    margin: 0;
    line-height: 1.5;
    color: var(--c-texte);
}

.bento-benefits li::before {
    content: "✓";
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.45rem;
    height: 1.45rem;
    margin-top: 0.05rem;
    border-radius: 50%;
    background: var(--c-action);
    color: #fff;
    font-size: 0.8rem;
    font-weight: 700;
    line-height: 1;
}

/* Sombre : --c-mer s'éclaircit (check blanc peu lisible) → on rétablit un bleu franc. */
[data-theme="dark"] .bento-benefits li::before {
    background: #1e6091;
}


/*
event-context-nav.css

QUOI : Navigation contextuelle de la fiche événement (liens précédent/suivant en grille).

COMMENT : Copie telle quelle des lignes 2970–3026 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ---------- Navigation contextuelle (fiche événement) ---------- */
.event-context-nav {
    margin: var(--space-lg) 0;
    display: grid;
    gap: var(--space-sm);
    grid-template-columns: 1fr;
}

@media (min-width: 640px) {
    .event-context-nav {
        grid-template-columns: 1fr 1fr;
    }
}

.event-context-nav__link {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-md);
    background: linear-gradient(135deg, var(--c-blanc) 0%, var(--c-sable-clair) 100%);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    text-decoration: none;
    color: var(--c-texte);
    transition: transform var(--duration-base) var(--ease-out), box-shadow var(--duration-base) var(--ease-out), border-color var(--duration-base) var(--ease-out);
}

.event-context-nav__link:hover,
.event-context-nav__link:focus-visible {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
    border-color: var(--c-mer-clair);
}

.event-context-nav__icon {
    font-size: 1.6rem;
    flex-shrink: 0;
}

.event-context-nav__text {
    display: flex;
    flex-direction: column;
    line-height: 1.3;
}

.event-context-nav__label {
    font-size: 0.85rem;
    color: var(--c-texte-doux);
}

.event-context-nav__text strong {
    font-family: var(--font-display);
    font-size: 1.1rem;
    color: var(--c-marine);
}


/*
hero.css

QUOI : Hero de page unifié (.page-hero) : variante photo, signature « horizon opale », topline kicker, titre écran-titre, rangée méta et tags. Inclut le raccord des pages taxonomie.

COMMENT : Copie telle quelle des lignes 3027–3284 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ---------- Pages taxonomie (catégorie / ville) ---------- */
.taxonomy-page {
    padding-top: var(--space-md);
    padding-bottom: var(--space-xl);
}

/* ============================ Hero de page unifié (.page-hero) ============================
   QUOI : bandeau d'en-tête commun à TOUTES les pages secondaires (ville, catégorie, lieux, à propos,
   newsletter, mentions, partenaire, erreurs). L'accueil garde son hero éditorial propre (home.css).

   COMMENT : modèle = l'ancien hero « photo de ville ». Bloc marine profond, photo de décor optionnelle
   (`.has-photo` + `--hero-bg`) derrière un voile marine ; titre clair surdimensionné (sœur du hero
   d'accueil), kicker « live » pulsant, et la SIGNATURE « horizon opale » (`.page-hero__horizon`) :
   un filet lumineux opalescent en bas du bloc — la lumière d'opale là où la mer rejoint le ciel, ce
   qui donne son nom à la Côte d'Opale. Mobile-first ; enrichi ≥640px.

   POURQUOI : une seule identité d'en-tête sur tout le site, déclinable avec ou sans photo. */
.page-hero {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    margin: 0 0 var(--space-lg);
    padding: clamp(1.5rem, 5vw, 2.75rem) clamp(1.15rem, 3.5vw, 2.5rem) clamp(2rem, 4.5vw, 2.75rem);
    border-radius: var(--radius-xl);
    color: var(--c-blanc);
    /* Dégradé signature « mer → couchant » : marine (haut-gauche, où est le texte) qui chauffe vers le
       corail (bas-droite). Halo bleu en haut-gauche pour ancrer la lisibilité du titre. */
    background:
        radial-gradient(120% 120% at 8% 6%, rgba(74, 144, 184, 0.38) 0%, transparent 52%),
        linear-gradient(140deg, var(--c-marine) 0%, var(--c-mer) 40%, var(--c-corail) 100%);
    box-shadow:
        0 20px 48px -24px rgba(10, 61, 98, 0.55),
        0 4px 12px -6px rgba(10, 61, 98, 0.3);
}

/* Héros → contenu : un seul écart de 40 px sur toutes les largeurs (64 px de marge + 24 px de rembourrage
   de la section suivante laissaient ~90 px de vide sous l'en-tête, audit de design du 27/10/2026). */
.page-hero + .events-section {
    padding-top: 0;
}

/* Variante photo : image de décor sous un voile marine → texte lisible (thème clair ET sombre). */
.page-hero.has-photo {
    background:
        linear-gradient(140deg, rgba(10, 61, 98, 0.88) 0%, rgba(30, 96, 145, 0.66) 42%, rgba(224, 120, 86, 0.60) 100%),
        var(--hero-bg);
    background-size: auto, cover;
    background-position: center, center;
    background-repeat: no-repeat;
}

/* Reveal au chargement (neutralisé si mouvement réduit). */
@media (prefers-reduced-motion: no-preference) {
    .page-hero {
        animation: fade-in-up 640ms var(--ease-out) both;
    }
}

/* ── SIGNATURE « horizon opale » : filet lumineux opalescent + bloom doux, posé en bas du bloc.
   Le dégradé bleu pâle → sable → corail évoque la lumière d'opale sur l'horizon de la côte. ── */
.page-hero__horizon {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    border: 0;
    margin: 0;
    pointer-events: none;
    background: linear-gradient(90deg,
        transparent 3%,
        rgba(160, 205, 235, 0.95) 24%,
        rgba(255, 247, 230, 1) 50%,
        rgba(232, 138, 102, 0.95) 76%,
        transparent 97%);
    box-shadow:
        0 0 10px 0 rgba(255, 247, 230, 0.6),
        0 0 26px 2px rgba(160, 205, 235, 0.65),
        0 0 60px 10px rgba(232, 138, 102, 0.32);
    opacity: 1;
}

/* Aube qui monte de l'horizon : voile lumineux dégradé vers le haut, posé juste au-dessus du filet. */
.page-hero__horizon::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 90px;
    background: linear-gradient(to top,
        rgba(190, 214, 234, 0.22) 0%,
        rgba(190, 214, 234, 0.06) 45%,
        transparent 100%);
    pointer-events: none;
}

/* Reflet « opale » qui balaie lentement le filet (gravy — le filet reste lisible sans). */
.page-hero__horizon::after {
    content: "";
    position: absolute;
    top: -1px;
    bottom: -1px;
    width: 26%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.9), transparent);
    filter: blur(2px);
    transform: translateX(-130%);
    pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
    .page-hero__horizon::after {
        animation: opal-glint 7s ease-in-out infinite;
    }
}

@keyframes opal-glint {
    0%       { transform: translateX(-130%); }
    55%, 100% { transform: translateX(460%); }
}

/* Topline : kicker « live » (pastille corail pulsante) + lien retour. */
.page-hero__topline {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: clamp(0.9rem, 3vw, 1.4rem);
}

.page-hero__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    margin: 0;
    font-size: 0.76rem; /* 0.72rem → 12 px, même taille que le lien retour (27/10/2026) */
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--c-sable);
}

.page-hero__pulse {
    width: 8px;
    height: 8px;
    flex-shrink: 0;
    border-radius: 50%;
    background: var(--c-corail);
    animation: page-hero-pulse 2.2s ease-out infinite;
}

@keyframes page-hero-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(224, 120, 86, 0.6); }
    70%  { box-shadow: 0 0 0 9px rgba(224, 120, 86, 0); }
    100% { box-shadow: 0 0 0 0 rgba(224, 120, 86, 0); }
}

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

/* Titre surdimensionné « écran-titre » — sœur du hero d'accueil, mais en blanc sur marine. */
.page-hero__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: clamp(1.95rem, 6vw, 3.2rem);
    /* 1.04 rognait les jambages de la dernière ligne des titres qui passent sur 3 lignes en mobile
       (404 : hauteur de contenu 100px pour une boîte de 97px). 1.1 est la valeur spécifiée par
       DESIGN.md §3 pour le niveau Display — on s'aligne sur la spec plutôt que de compenser au cas
       par cas. */
    line-height: 1.1;
    font-weight: 800;
    letter-spacing: -0.035em;
    color: var(--c-blanc);
    text-wrap: balance;
}

/* Accent corail/opale sur un mot-clé du titre (ville, catégorie…). */
.page-hero__accent {
    background: linear-gradient(105deg, #ffd9a8 0%, var(--c-corail) 52%, #8fc4e6 120%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: var(--c-corail);
}

.page-hero__intro {
    margin: clamp(0.7rem, 2vw, 1rem) 0 0;
    max-width: 62ch;
    font-size: var(--fs-md);
    line-height: 1.55;
    color: rgba(255, 255, 255, 0.92);
}

/* Rangée méta : pilule de comptage + actions/filtres éventuels. */
.page-hero__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem;
    margin-top: clamp(1rem, 3vw, 1.4rem);
}

.page-hero__pill {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0;
    padding: 0.4rem 0.9rem;
    background: rgba(255, 255, 255, 0.16);
    border: 1px solid rgba(255, 255, 255, 0.22);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    border-radius: 999px;
    font-size: 0.9rem;
    font-weight: 600;
}

/* Titre de section dans le corps de page (groupes de lieux, « à proximité »…) :
   reprend le display marine, indépendant du hero. */
.section-title {
    margin: 0 0 var(--space-sm);
    font-family: var(--font-display);
    font-size: clamp(1.4rem, 3.5vw, 2rem);
    font-weight: 800;
    line-height: 1.2;
    letter-spacing: -0.02em;
    color: var(--c-marine);
}

/* Chapô sous un titre de section. */
.section-lead {
    margin: 0 0 var(--space-md);
    max-width: 60ch;
    color: var(--c-texte-doux);
    font-size: var(--fs-md);
    line-height: 1.6;
}

/* Rangée d'étiquettes (tags d'un lieu) : pastilles qui s'enroulent. Les chips n'ont pas de
   `--cat-color` ici → on leur donne un habillage sable/marine lisible (sinon texte blanc sur fond). */
.lieu-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem;
    margin: 0 0 var(--space-md);
}

.lieu-tags .event-card__category {
    background: var(--c-sable-clair);
    color: var(--c-marine);
    border: 1px solid var(--c-bordure);
    box-shadow: none;
}

[data-theme="dark"] .lieu-tags .event-card__category {
    background: rgba(124, 184, 226, 0.12);
    color: var(--c-mer-clair);
    border-color: rgba(124, 184, 226, 0.28);
}

/* Informations pratiques d'un lieu (adresse, téléphone, site web). Deux colonnes tant qu'il y a la
   place, une seule dès que l'écran se resserre : sous 30rem, un libellé et sa valeur côte à côte
   laissent à la valeur trois caractères par ligne. */
.lieu-infos {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.35rem var(--space-md);
    margin: var(--space-md) 0 0;
    padding-top: var(--space-md);
    border-top: 1px solid var(--c-bordure);
    font-size: var(--fs-md);
}

.lieu-infos dt {
    color: var(--c-texte-doux);
    font-weight: 600;
}

.lieu-infos dd {
    margin: 0;
    color: var(--c-texte);
    /* Une URL longue déborderait de sa colonne : elle doit pouvoir se couper n'importe où. */
    overflow-wrap: anywhere;
}

.lieu-infos a {
    color: var(--c-mer);
    text-decoration: underline;
    text-underline-offset: 0.15em;
}

[data-theme="dark"] .lieu-infos a {
    color: var(--c-mer-clair);
}

@media (max-width: 30rem) {
    .lieu-infos {
        grid-template-columns: 1fr;
        gap: 0;
    }

    .lieu-infos dd {
        margin-bottom: var(--space-sm);
    }
}


/* Mention de provenance d'une fiche reprise d'une source ouverte. Discrète — c'est une obligation
   légale, pas un élément éditorial — mais lisible : un crédit sous le seuil de contraste ne vaut
   pas mieux qu'un crédit absent. */
.lieu-attribution {
    margin: var(--space-md) 0 0;
    padding-top: var(--space-sm);
    border-top: 1px solid var(--c-bordure);
    font-size: 0.82rem;
    line-height: 1.5;
    color: var(--c-texte-doux);
}

/*
featured.css

QUOI : Événements « Incontournables » : liseré et tuile date dorés, badge, et contrôles admin de marquage.

COMMENT : Copie telle quelle des lignes 3285–3389 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ---------- Événements « Incontournables » (positionnement préférentiel) ----------
   Identité premium : cadre or feutré, bandeau doré en haut, badge ruban avec
   reflet, halo chaud au hover. Reste dans le langage visuel Opale (marine/corail)
   en n'utilisant l'or que comme accent. */
.event-card--featured {
    border: 1px solid rgba(212, 175, 55, 0.55);
    border-left: 3px solid #d4af37;
    background:
        radial-gradient(circle at 100% 0%, rgba(245, 215, 110, 0.18) 0%, transparent 45%),
        linear-gradient(180deg, #fffaf0 0%, var(--c-blanc) 55%);
    box-shadow:
        0 1px 2px rgba(184, 149, 34, 0.08),
        0 6px 16px rgba(184, 149, 34, 0.10);
    padding-top: calc(var(--space-md) + 0.85rem);
    overflow: hidden;
}

/* Fin liseré doré en haut de la card — accent discret mais immédiatement lisible. */
.event-card--featured::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: linear-gradient(90deg,
        rgba(212, 175, 55, 0) 0%,
        #d4af37 18%,
        #f5d76e 50%,
        #d4af37 82%,
        rgba(212, 175, 55, 0) 100%);
    z-index: 1;
    pointer-events: none;
}

/* Le gradient diagonal du `.event-card::before` reste, mais teinté or au lieu de mer. */
.event-card--featured::before {
    background: linear-gradient(135deg, transparent 0%, transparent 55%, rgba(212, 175, 55, 0.10) 100%);
}

@media (hover: hover) {
    .event-card--featured:hover {
        border-color: #d4af37;
        border-left-color: #b89522;
        box-shadow:
            0 2px 4px rgba(184, 149, 34, 0.12),
            0 14px 32px rgba(184, 149, 34, 0.22),
            0 0 0 1px rgba(212, 175, 55, 0.35);
        transform: translateY(-5px);
    }
}

.event-card__featured-badge {
    position: absolute;
    top: 0.65rem;
    left: 0.85rem;
    display: inline-flex;
    align-items: center;
    gap: 0.32rem;
    padding: 0.34rem 0.75rem;
    font-family: var(--font-display, inherit);
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: #332803; /* #4a3a08 tombait à 4.2:1 sur l'or foncé du dégradé (audit du 27/10/2026) */
    background: linear-gradient(135deg, #f5d76e 0%, #e0bf3a 55%, #c69820 100%);
    border-radius: 999px;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.55),
        inset 0 -1px 0 rgba(122, 91, 12, 0.22),
        0 3px 10px rgba(184, 149, 34, 0.38);
    line-height: 1;
    z-index: 3;
    white-space: nowrap;
}

.event-card__featured-icon {
    display: inline-block;
    font-size: 0.95rem;
    line-height: 0;
    color: #ffffff;
    text-shadow: 0 0 6px rgba(255, 235, 150, 0.9);
    transform: translateY(0.5px);
}

/* ---------- Admin : marquage et toggle « Incontournable » ---------- */
.admin-event-card--featured {
    border-left: 3px solid #d4af37;
    background: linear-gradient(180deg, rgba(212, 175, 55, 0.05) 0%, transparent 50%);
}

.admin-event-card__featured-flag {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.2rem 0.55rem;
    font-size: 0.72rem;
    font-weight: 700;
    color: #5c4708;
    background: linear-gradient(135deg, #f5d76e 0%, #d4af37 100%);
    border-radius: 999px;
    letter-spacing: 0.02em;
}


/*
flash.css

QUOI : Messages flash (succès / erreur) des pages ne chargeant que la feuille principale.

COMMENT : Copie telle quelle des lignes 3390–3410 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ── Messages flash (page newsletter et autres pages ne chargeant que style.css) ── */
.flash {
    padding: var(--space-sm);
    margin-bottom: var(--space-md);
    border-radius: var(--radius-sm);
    font-size: 0.9rem;
    border: 1px solid;
}

.flash--success {
    background-color: #e8f5e9;
    color: #1b5e20;
    border-color: #2e7d32;
}

.flash--error {
    background-color: #fbe9e7;
    color: #b71c1c;
    border-color: var(--c-corail);
}


/*
forms.css

QUOI : Erreurs de validation des formulaires (.form-errors, aria-invalid) et composant d'inscription newsletter (footer, page dédiée, carte bento).

COMMENT : Copie telle quelle des lignes 3411–3631 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ──────────────────────────────────────────────────────────────────────────
   Erreurs de validation des formulaires
   Rendu par le thème global `templates/form/opale_errors.html.twig` :
   `.form-errors` (message + icône) sous chaque champ, et `aria-invalid="true"`
   posé sur le champ fautif → bordure corail. S'applique à TOUS les formulaires
   (front + back-office), `style.css` étant chargé partout où ils apparaissent.
   ────────────────────────────────────────────────────────────────────────── */
.form-errors {
    list-style: none;
    margin: 0.4rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

/* `display: flex` ci-dessus prime sur la feuille de style user-agent qui masque `[hidden]` par défaut
   (une règle de classe d'auteur bat toujours l'UA) — sans cet override, poser l'attribut `hidden` en JS
   (ex. effacer un message d'erreur périmé quand le champ est corrigé) resterait sans effet visuel. */
.form-errors[hidden] {
    display: none;
}

.form-errors__item {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
    font-size: 0.85rem;
    font-weight: 600;
    line-height: 1.35;
    color: #b5462a;
}

.form-errors__icon {
    flex: 0 0 auto;
    width: 16px;
    height: 16px;
    margin-top: 0.08rem;
}

/* Champ invalide : bordure corail + halo, quel que soit le type (input, select, textarea, fichier). */
[aria-invalid="true"] {
    border-color: var(--c-corail) !important;
}

[aria-invalid="true"]:focus {
    box-shadow: 0 0 0 4px rgba(224, 120, 86, 0.18) !important;
}

[data-theme="dark"] .form-errors__item {
    color: #ffb9a8;
}

/* ── Composant d'inscription newsletter (footer + page dédiée) ── */
.newsletter-signup {
    width: 100%;
    max-width: 560px;
    margin: 0 auto;
    text-align: center;
}

.newsletter-signup__title {
    margin: 0 0 0.35rem;
    font-family: var(--font-display);
    font-size: 1.1rem;
    font-weight: 600;
}

.newsletter-signup__intro {
    margin: 0 0 var(--space-sm);
    font-size: 0.9rem;
    opacity: 0.85;
}

/* Label associé mais visuellement masqué : le titre/intro et le placeholder donnent le contexte. */
.newsletter-form__label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

.newsletter-form__controls {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    justify-content: center;
}

.newsletter-form__input {
    flex: 1 1 240px;
    min-width: 0;
    min-height: 48px;
    padding: 0.75rem 0.9rem;
    font-size: var(--fs-base);
    color: var(--c-texte);
    background-color: var(--c-sable-clair);
    border: 1.5px solid var(--c-bordure-champ);
    border-radius: var(--radius-md);
    outline: none;
    transition: border-color var(--duration-fast) var(--ease-out),
                box-shadow var(--duration-fast) var(--ease-out);
}

.newsletter-form__input:hover {
    border-color: var(--c-mer-clair);
}

.newsletter-form__input:focus,
.newsletter-form__input:focus-visible {
    border-color: var(--c-mer);
    box-shadow: 0 0 0 4px var(--c-focus);
    outline: none;
}

.newsletter-form__submit {
    flex: 0 0 auto;
    white-space: nowrap;
}

.newsletter-form__rgpd {
    margin: 0.7rem 0 0;
    font-size: 0.75rem;
    line-height: 1.45;
    opacity: 0.75;
}

.newsletter-form__rgpd a {
    color: inherit;
    text-underline-offset: 2px;
}

.newsletter-form__feedback {
    margin: 0.7rem 0 0;
    font-size: 0.85rem;
    font-weight: 600;
}

.newsletter-form__feedback.is-success {
    color: #1b5e20;
}

.newsletter-form__feedback.is-error {
    color: #b71c1c;
}

/* Contexte footer (fond marine) : éclaircir textes et adapter le retour inline pour le contraste. */
.site-footer__newsletter {
    padding-bottom: var(--space-md);
    margin-bottom: var(--space-sm);
    border-bottom: 1px solid rgba(245, 233, 212, 0.18);
    color: var(--c-sable);
}

.site-footer__newsletter .newsletter-form__feedback.is-success {
    color: #b8f0c0;
}

.site-footer__newsletter .newsletter-form__feedback.is-error {
    color: #ffc9c0;
}

/* Pied de page (fond marine) : le primaire devient corail pour ressortir sur le bleu. */
.site-footer__newsletter .btn--primary {
    background: linear-gradient(135deg, var(--c-corail-action) 0%, var(--c-corail-action-fonce) 100%);
    color: #fff;
}

.site-footer__newsletter .btn--primary:hover {
    box-shadow: 0 10px 26px -8px rgba(224, 120, 86, 0.50);
}

/* ── Page newsletter dédiée : le composant d'inscription devient une carte premium ── */
.prose-page .newsletter-signup {
    margin: var(--space-lg) auto var(--space-md);
    padding: clamp(1.5rem, 5vw, 2.5rem);
    background:
        radial-gradient(120% 130% at 0% 0%, rgba(74, 144, 184, 0.12) 0%, transparent 55%),
        linear-gradient(180deg, var(--c-blanc) 0%, var(--c-sable-clair) 100%);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-md);
}

/* Page bento dédiée : l'encart d'inscription devient une carte « action » verre dépoli,
   sœur visuelle des .glass-card (même rayon/filet/ombre), alignée à gauche et pleine largeur
   de sa colonne. Surface un peu plus dense (--glass-bg-strong) pour la distinguer du « pitch ».
   --glass-bg-strong est assez opaque pour rester lisible sans backdrop-filter. */
.bento-page .newsletter-signup {
    width: 100%;
    max-width: none;
    margin: 0;
    padding: var(--space-lg);
    text-align: left;
    background: var(--glass-bg-strong);
    -webkit-backdrop-filter: saturate(160%) blur(var(--glass-blur));
    backdrop-filter: saturate(160%) blur(var(--glass-blur));
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--glass-shadow);
}

.prose-page .newsletter-signup__title {
    font-size: var(--fs-lg);
    color: var(--c-marine);
}

/* Titre de l'encart bento : même poids qu'un titre de carte, sans accent de bordure
   (DESIGN.md interdit les border-left/border-right colorés sur cartes/alertes). */
.bento-page .newsletter-signup__title {
    margin: 0 0 var(--space-sm);
    font-family: var(--font-display);
    font-size: 1.2rem;
    font-weight: 700;
    line-height: 1.3;
    color: var(--c-marine);
}

.prose-page .newsletter-signup__intro {
    font-size: var(--fs-base);
}

.bento-page .newsletter-signup__intro {
    font-size: var(--fs-base);
    color: var(--c-texte-doux);
}

.prose-page .newsletter-form__controls,
.bento-page .newsletter-form__controls {
    margin-top: var(--space-sm);
}


/*
form-fields.css

QUOI : Composants de champ réellement partagés entre plusieurs contextes (au-delà d'un simple
       ajustement de valeurs sur un sélecteur déjà scopé par page). Pour l'instant : la bascule à
       choix en pilules (`.field-toggle`), généralisée depuis le sélecteur de mode de date de
       l'événement pour être réutilisable par tout futur formulaire ayant un choix binaire/court.

COMMENT : Deux `<label>` enveloppant chacun un radio natif (masqué visuellement, conservé pour le
clavier/lecteur d'écran) ; l'état coché est porté par `:has(input:checked)`, même motif que
`.toolbar-pill`/`.pub-chip`.

OÙ : Importé par assets/styles/app.imports.css. Utilisé par templates/event/submission.html.twig
     et templates/admin/edit.html.twig (bascule de mode de date).

POURQUOI : docs/superpowers/specs/2026-07-15-refonte-formulaires-publics-design.md.
*/
/* Contrôle segmenté compact : UNE piste recessée (teinte marine à peine visible, comme une
   encoche), les options n'ont ni bordure ni ombre propres — seule l'option cochée reçoit un fond
   marine plein. Largeur égale des deux segments (`flex: 1 1 0`) pour un rendu net et symétrique,
   pas deux boutons de tailles différentes flottant dans la piste. */
.field-toggle {
    display: flex;
    gap: 2px;
    max-width: 22rem;
    padding: 3px;
    margin-bottom: 1rem;
    background-color: rgba(10, 61, 98, 0.055);
    border: 1px solid rgba(10, 61, 98, 0.10);
    border-radius: 999px;
}

/* Spécificité (0,2,0) : bat `.submission-form label` (0,1,1, submission-form.css) quel que soit
   l'ordre de chargement — sans ce préfixe, l'option NON cochée héritait de la couleur marine
   pleine (règle générique de label) au lieu du gris atténué voulu, et les deux segments du
   contrôle semblaient également « actifs », sans hiérarchie visuelle. */
.field-toggle .field-toggle__option {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 1 1 0;
    min-height: 38px;
    padding: 0.4rem 0.9rem;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--c-texte-doux);
    background-color: transparent;
    border: none;
    border-radius: 999px;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color var(--duration-fast) var(--ease-out),
                color var(--duration-fast) var(--ease-out);
}

.field-toggle__option input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    opacity: 0;
    pointer-events: none;
}

/* form_label() rend un <label> IMBRIQUÉ dans la pilule : les règles de page
   `.submission-form label` (couleur marine, display block, marge) le repeignaient
   par-dessus l'état coché → marine-sur-marine en clair, texte invisible.
   Spécificité (0,2,1) pour battre (0,1,1) quel que soit l'ordre de chargement. */
.field-toggle .field-toggle__option label {
    display: inline;
    margin: 0;
    font-size: inherit;
    font-weight: inherit;
    color: inherit;
    cursor: pointer;
}

.field-toggle .field-toggle__option:hover {
    color: var(--c-marine);
}

.field-toggle .field-toggle__option:has(input:checked) {
    color: var(--c-blanc);
    background-color: var(--c-marine);
    box-shadow: 0 1px 3px rgba(10, 61, 98, 0.18);
}

.field-toggle .field-toggle__option:has(input:focus-visible) {
    outline: 2px solid var(--c-mer);
    outline-offset: 2px;
}

/* Mode sombre : --c-marine est remappé en encre CLAIRE (#eaf1f8) → l'état coché
   devenait blanc-sur-blanc (1.1:1, texte invisible). Fond « marque » saturé
   explicite, même motif que les autres pastilles actives du sombre. 8.9:1 vérifié. */
[data-theme="dark"] .field-toggle .field-toggle__option:has(input:checked) {
    color: #ffffff;
    background: linear-gradient(135deg, #0e4d7a 0%, #1e6091 100%);
}

/* Piste : encoche recessée plus visible sur fond de carte sombre. */
[data-theme="dark"] .field-toggle {
    background-color: rgba(0, 0, 0, 0.28);
    border-color: var(--c-bordure);
}

/*
theme-dark.css

QUOI : Mode sombre piloté par [data-theme="dark"] : remappage des tokens et surfaces (encre), fonds marine saturés, cas particuliers (Leaflet, incontournables, flash).

COMMENT : Copie telle quelle des lignes 3632–3796 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ============================================================
   MODE SOMBRE — piloté par [data-theme="dark"] sur <html>
   ────────────────────────────────────────────────────────────
   L'attribut est posé avant peinture par le script d'init (en-tête
   partagé, présent sur toutes les pages front) :
   - mode "auto"  → résolu selon l'APPAREIL (prefers-color-scheme) ET l'HEURE ;
   - mode "light" / "dark" → choix MANUEL mémorisé (localStorage).
   Une seule source de vérité couvre donc l'automatique ET le manuel.

   Stratégie de couleurs :
   - --c-marine devient une encre CLAIRE → corrige ~46 titres sans toucher au markup.
   - --c-blanc reste BLANC → le texte blanc sur pastilles colorées reste lisible ;
     les surfaces blanches sont, elles, redéfinies en encre.
   - Les rares fonds « marque » (texte blanc) reçoivent un dégradé marine saturé.
   ============================================================ */
:root[data-theme="dark"] {
    color-scheme: dark;

    --c-marine: #eaf1f8;        /* encre claire (titres, libellés) */
    --c-mer: #7cb8e2;           /* accent bleu lumineux */
    --c-mer-clair: #a9d4f0;
    --c-texte: #e7eef6;
    --c-texte-doux: #a3b6c6;
    /* --c-sable reste un sable CLAIR : c'est un accent posé sur l'en-tête / le pied
       (toujours sombres) — le remapper casserait ces accents. */
    --c-sable-clair: #0c1620;   /* fond de page (encre marine) */
    --c-bordure: rgba(160, 196, 224, 0.16);
    /* Contour des champs : 3:1 sur l'encre des cartes (le voile 0.16 y était quasi invisible). */
    --c-bordure-champ: #5a7891;
    --c-focus: rgba(124, 184, 226, 0.50);
    /* Bleu d'action soutenu : blanc dessus à 5:1 (le `--c-mer` nocturne est un bleu de texte). */
    --c-action: #2a6a9c;

    /* Niveaux de présence : les métaux s'inversent (texte clair sur voile sombre). Les valeurs
       claires du mode jour y tomberaient sous le seuil AA — un doré foncé sur fond marine est
       illisible. On remonte donc la luminosité en gardant la même famille de teinte, pour que la
       lecture doré / bleu reste identique d'un thème à l'autre. */
    --c-niveau-boostee-texte: #e3c169;
    --c-niveau-boostee-fond: rgba(227, 193, 105, 0.16);
    --c-niveau-normale-texte: #9cc8ef;
    --c-niveau-normale-fond: rgba(124, 184, 226, 0.16);

    /* Surfaces sémantiques (cf. tokens.css) : l'équivalent nocturne des surfaces blanches.
       `#16242f` est l'encre surélevée déjà utilisée par la liste `:is(...)` plus bas — les
       jetons portent donc la même valeur, sans nouvelle nuance à maintenir. */
    --c-surface: #16242f;
    --c-surface-2: #1d3242;
    /* Vert lumineux (même valeur que les statuts « publié » du back-office nocturne). */
    --c-succes: #6ee7b7;
    /* Corail éclairci pour rester lisible en TEXTE sur l'encre (le corail foncé y tombe à 3.9:1).
       `--c-corail` / `--c-corail-fonce` restent inchangés : ils portent des aplats à texte blanc. */
    --c-corail-texte: #f0a58a;

    --glass-bg: rgba(18, 30, 41, 0.55);
    --glass-bg-strong: rgba(18, 30, 41, 0.84);
    --glass-border: rgba(160, 196, 224, 0.18);
    --glass-hairline: rgba(160, 196, 224, 0.12);
    --glass-shadow: 0 14px 44px -12px rgba(0, 0, 0, 0.62), 0 2px 8px -2px rgba(0, 0, 0, 0.45);

    --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.45);
    --shadow-sm: 0 2px 6px rgba(0, 0, 0, 0.50), 0 1px 2px rgba(0, 0, 0, 0.35);
    --shadow-md: 0 10px 28px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.40);
    --shadow-lg: 0 24px 56px rgba(0, 0, 0, 0.62), 0 8px 20px rgba(0, 0, 0, 0.45);
    --shadow-xl: 0 36px 72px -16px rgba(0, 0, 0, 0.72), 0 14px 28px -12px rgba(0, 0, 0, 0.5);

    --header-bg: linear-gradient(135deg, rgba(8, 20, 30, 0.78) 0%, rgba(13, 36, 54, 0.80) 100%);
    --header-bg-scrolled: linear-gradient(135deg, rgba(6, 15, 23, 0.84) 0%, rgba(11, 30, 46, 0.86) 100%);
}

[data-theme="dark"] body {
    background-color: var(--c-sable-clair);
    background-image:
        radial-gradient(circle at 10% 0%, rgba(30, 96, 145, 0.22) 0%, transparent 46%),
        radial-gradient(circle at 90% 100%, rgba(224, 120, 86, 0.12) 0%, transparent 42%);
}

/* Le CTA sable conserve un texte marine FONCÉ (le token --c-marine étant désormais clair). */
[data-theme="dark"] .header-cta { color: #0a3d62; }

/* Icônes réseaux du pied de page au survol/focus : même fond sable clair qu'en mode jour →
   même besoin d'une encre marine FONCÉE fixe (sinon --c-marine clair donne du blanc sur sable,
   contraste illisible). */
[data-theme="dark"] .site-footer__social-link:hover,
[data-theme="dark"] .site-footer__social-link:focus-visible { color: #0a3d62; }

/* Pied de page : --c-marine y sert de FOND → on rétablit une encre marine profonde. */
[data-theme="dark"] .site-footer { background-color: #0a2030; }

/* ── Surfaces qui étaient blanches → encre surélevée ── */
[data-theme="dark"] :is(
    .search-panel,
    .search-input,
    .geo-manual__input,
    .geo-manual__panel,
    .geo-manual__suggestions,
    .dropdown-menu,
    .dropdown-check__box,
    .home-map-section,
    .event-card,
    .event-card__date-tile,
    .toolbar-pill,
    .facet-chip,
    .newsletter-form__input,
    .field-toggle__option
) {
    background-color: #16242f;
}

[data-theme="dark"] .dropdown-menu::before {
    background-color: #16242f;
}

/* `.back-link` est désormais un lien en TEXTE NU dans tous les contextes (plus aucune pastille « badge » :
   prose.css / submission-form.css / event-detail-main.css). Sa couleur `--c-mer` est déjà remappée en bleu
   lumineux (#7cb8e2) la nuit et son survol `--c-marine` en encre claire → aucun remappage nocturne
   nécessaire, ni pour le lien de bas de page, ni pour ceux intégrés aux heros. */

/* Barre d'outils & encarts qui mélangeaient des sables clairs codés en dur. */
[data-theme="dark"] .search-toolbar {
    background: linear-gradient(180deg, #15242f 0%, rgba(18, 30, 41, 0.6) 100%);
    box-shadow: inset 0 1px 0 rgba(160, 196, 224, 0.06);
}
[data-theme="dark"] .facet-chips {
    background: linear-gradient(180deg, rgba(124, 184, 226, 0.05) 0%, transparent 100%);
}

/* ── Fonds « marque » à texte blanc : dégradé marine saturé explicite ── */
[data-theme="dark"] :is(
    .btn--primary,
    .toolbar-pill--filters[aria-expanded="true"],
    .toolbar-pill--map[aria-expanded="true"],
    .toolbar-pill--sort[aria-expanded="true"],
    .facet-chip.is-active,
    .facet-chip--category.is-active,
    .load-more-btn
) {
    background: linear-gradient(135deg, #0e4d7a 0%, #1e6091 100%);
    color: #fff;
    border-color: #1e6091;
}
[data-theme="dark"] :is(.toolbar-pill--geo.is-active, .geo-manual.is-open .toolbar-pill--geo-edit) {
    background-color: #14517f;
    border-color: #14517f;
    color: #fff;
}
[data-theme="dark"] .home-map-marker--cluster {
    background: radial-gradient(circle at 35% 30%, #3f86b8 0%, #0e3a5c 100%);
}
[data-theme="dark"] .event-context-nav__link {
    background: linear-gradient(135deg, #16242f 0%, #11202b 100%);
}
[data-theme="dark"] .prose-page .newsletter-signup {
    background:
        radial-gradient(120% 130% at 0% 0%, rgba(124, 184, 226, 0.10) 0%, transparent 55%),
        linear-gradient(180deg, #17262f 0%, #0f1c26 100%);
}

/* Hero de page : dégradé marine plus profond en sombre pour rester somptueux. La variante photo
   (`.has-photo`) garde son propre voile (défini plus bas, sans remappage dark nécessaire). */
[data-theme="dark"] .page-hero:not(.has-photo) {
    background:
        radial-gradient(120% 120% at 8% 6%, rgba(74, 144, 184, 0.28) 0%, transparent 52%),
        linear-gradient(140deg, #0a2740 0%, #123c5c 42%, #8a4026 100%);
}

/* Carte « Incontournable » : fond crème codé en dur → encre + or, sinon texte illisible. */
[data-theme="dark"] .event-card--featured {
    background:
        radial-gradient(circle at 100% 0%, rgba(245, 215, 110, 0.12) 0%, transparent 45%),
        linear-gradient(180deg, #1c2433 0%, #16212c 60%);
    border-color: rgba(212, 175, 55, 0.45);
}
[data-theme="dark"] .event-card--featured .event-card__date-tile-d {
    color: #f5d76e;
}

/* Messages flash : on garde des pastilles vives mais sur fonds sombres translucides. */
[data-theme="dark"] .flash--success {
    background-color: rgba(46, 125, 50, 0.18);
    color: #aee3b4;
    border-color: #2e7d32;
}
[data-theme="dark"] .flash--error {
    background-color: rgba(224, 120, 86, 0.18);
    color: #ffb9a8;
    border-color: var(--c-corail);
}

/* La grille Leaflet et ses popups restent sur tuiles claires → on garde un texte foncé localement. */
[data-theme="dark"] :is(.home-map-popup__title, .home-map-popup-list__title) { color: #0a3d62; }
[data-theme="dark"] :is(.home-map-popup__meta, .home-map-popup-list__date) { color: #5a6b7a; }


/*
lieu-filters.css

QUOI : Vitrine Lieux : bandeau de filtres par type en carrousel tactile dans le hero.

COMMENT : Copie telle quelle des lignes 3797–3859 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ============================================================
   Vitrine Lieux — filtres en carrousel tactile + entrée du hero
   ============================================================ */

/* Le bandeau de filtres par type (dans le hero marine) devient un carrousel
   horizontal à défilement tactile, scrollbar masquée (mobile-first). */
.lieu-filters {
    display: flex;
    gap: 0.5rem;
    margin-top: var(--space-sm);
    margin-right: calc(-1 * var(--space-md));
    padding-bottom: 0.4rem;
    padding-right: var(--space-md);
    overflow-x: auto;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    -ms-overflow-style: none;
}
.lieu-filters::-webkit-scrollbar { display: none; }

/* Les puces (réutilisent .event-card__category) deviennent de vraies pastilles « verre »
   posées sur le hero marine — défaut translucide, active en pastille pleine. */
.lieu-filters .event-card__category {
    scroll-snap-align: start;
    flex: 0 0 auto;
    background: rgba(255, 255, 255, 0.14);
    border: 1.5px solid rgba(255, 255, 255, 0.28);
    color: #fff;
    text-decoration: none;   /* pastilles de filtre : pas de soulignement « lien » */
    box-shadow: none;
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    transition: background-color var(--duration-fast) var(--ease-out),
                border-color var(--duration-fast) var(--ease-out),
                color var(--duration-fast) var(--ease-out),
                transform var(--duration-fast) var(--ease-out);
}
.lieu-filters .event-card__category:hover {
    background: rgba(255, 255, 255, 0.24);
    border-color: rgba(255, 255, 255, 0.5);
    transform: translateY(-1px);
}
.lieu-filters .event-card__category.is-active {
    background: #fff;
    color: #0a3d62;          /* fixe : lisible même quand --c-marine devient clair (dark) */
    border-color: #fff;
}
.lieu-filters .event-card__category:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
}

@media (min-width: 640px) {
    .lieu-filters {
        flex-wrap: wrap;
        overflow-x: visible;
        margin-right: 0;
        padding-right: 0;
    }
}



/* ══════════════════════════════════════════════════════════════════
   Recherche de lieux — barre de filtres sous le hero

   POURQUOI hors du hero : les filtres y étaient posés en pastilles de verre sur le fond marine, ce
   qui allait tant qu'il y en avait cinq. À dix catégories plus une recherche, une commune et un tri,
   le hero devenait un panneau de commande. La barre descend donc sur le fond de page, où les
   contrôles peuvent être des contrôles.
   ══════════════════════════════════════════════════════════════════ */

.lieu-search {
    margin: 0 0 var(--space-lg);
    padding: var(--space-md);
    background: var(--c-blanc);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

[data-theme="dark"] .lieu-search {
    background: var(--c-surface, rgba(255, 255, 255, 0.04));
}

.lieu-search__row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 0.75rem var(--space-sm);
}

.lieu-search__field {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    min-width: 0;
    flex: 1 1 11rem;
}

.lieu-search__field--text {
    flex: 3 1 16rem;
}

.lieu-search__field label {
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--c-texte-doux);
}

.lieu-search__input-wrap {
    position: relative;
    display: flex;
    align-items: center;
}

.lieu-search__icon {
    position: absolute;
    left: 0.8rem;
    width: 1rem;
    height: 1rem;
    color: var(--c-texte-doux);
    pointer-events: none;
}

.lieu-search input[type="search"],
.lieu-search select {
    width: 100%;
    min-height: 44px;
    padding: 0.55rem 0.8rem;
    font-family: inherit;
    font-size: 0.95rem;
    color: var(--c-texte);
    background-color: var(--c-sable-clair);
    border: 1px solid var(--c-bordure-champ);
    border-radius: var(--radius-sm);
    transition: border-color var(--duration-fast) var(--ease-out),
                box-shadow var(--duration-fast) var(--ease-out);
}

/* ⚠️ Fond OPAQUE, pas un voile translucide. Chrome peint le panneau déroulant d'un `select` avec le
   fond du contrôle : un blanc à 5 % donnait un panneau presque blanc, sous un texte clair — le menu
   des tris et des communes était illisible dès qu'on l'ouvrait. Un voile convient à un champ posé
   sur une surface connue ; il ne convient pas à un calque flottant dont on ne maîtrise pas le fond. */
[data-theme="dark"] .lieu-search input[type="search"],
[data-theme="dark"] .lieu-search select {
    background-color: var(--c-surface-2, #1d3242);
}

/* Les options n'héritent de rien : sans ces deux lignes, certains navigateurs les rendent avec la
   palette système, indépendamment du thème du site. */
[data-theme="dark"] .lieu-search select option {
    color: var(--c-texte);
    background-color: var(--c-surface-2, #1d3242);
}

/* Le chevron est une image : il ne suit pas `currentColor`. Celui du mode clair est un gris ardoise
   qui disparaît sur fond sombre. */
[data-theme="dark"] .lieu-search select {
    background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='16'%20height='16'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23a3b6c6'%20stroke-width='2.5'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M6%209l6%206%206-6'/%3E%3C/svg%3E");
}

.lieu-search input[type="search"] {
    padding-left: 2.4rem;
}

.lieu-search input[type="search"]::placeholder {
    /* Le gris par défaut d'un placeholder passe sous 4.5:1 sur le sable ; le ton « texte doux » le tient. */
    color: var(--c-texte-doux);
    opacity: 1;
}

.lieu-search select {
    appearance: none;
    padding-right: 2.3rem;
    background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='16'%20height='16'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%235a6b7a'%20stroke-width='2.5'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M6%209l6%206%206-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.7rem center;
    background-size: 15px 15px;
}

.lieu-search input[type="search"]:focus,
.lieu-search select:focus {
    outline: none;
    border-color: var(--c-mer);
    box-shadow: 0 0 0 3px rgba(30, 96, 145, 0.18);
}

.lieu-search__actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex: 0 0 auto;
}

.lieu-search__geo.is-active {
    border-color: var(--c-mer);
    color: var(--c-mer);
}

.lieu-search__geo.is-error {
    border-color: #b3261e;
    color: #b3261e;
}

.lieu-search__geo[disabled] {
    opacity: 0.6;
    cursor: progress;
}

/* ---- Pastilles de catégorie ---- */

.lieu-cats {
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem;
    margin: var(--space-sm) 0 0;
    padding: var(--space-sm) 0 0;
    border: 0;
    border-top: 1px solid var(--c-bordure);
}

.lieu-cat {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.38rem 0.8rem;
    font-size: 0.84rem;
    font-weight: 600;
    color: var(--c-texte);
    text-decoration: none;
    background: var(--c-sable-clair);
    border: 1px solid var(--c-bordure);
    border-radius: 999px;
    transition: background-color var(--duration-fast) var(--ease-out),
                border-color var(--duration-fast) var(--ease-out),
                color var(--duration-fast) var(--ease-out);
}

/* Le voile à 5 % et le filet à 16 % passaient le seuil de contraste du TEXTE, mais la pastille
   elle-même ne se détachait plus de la barre : on lisait une liste de mots, pas des boutons. */
[data-theme="dark"] .lieu-cat {
    background: rgba(255, 255, 255, 0.08);
    border-color: rgba(160, 196, 224, 0.28);
}

/* La pastille porte la couleur de sa catégorie par un point, pas par son fond : dix pastilles
   pleines côte à côte se disputeraient l'attention, et celle qui est active ne se verrait plus. */
.lieu-cat__dot {
    width: 0.55rem;
    height: 0.55rem;
    flex: none;
    border-radius: 999px;
    background: var(--cat-color, var(--c-mer));
}

.lieu-cat__count {
    font-size: 0.74rem;
    font-variant-numeric: tabular-nums;
    color: var(--c-texte-doux);
}

.lieu-cat:hover {
    border-color: var(--c-mer-clair);
}

/* ⚠️ Repli en valeur FIXE, pas sur `--c-marine` : ce jeton devient une encre quasi blanche en mode
   sombre, et la pastille « Tous » écrivait alors du blanc sur du blanc. Le bleu de mer du mode clair
   tient 5.6:1 avec du texte blanc dans les deux thèmes. */
.lieu-cat.is-active {
    color: var(--c-blanc);
    background: var(--cat-color, #1e6091);
    border-color: transparent;
}

.lieu-cat.is-active .lieu-cat__dot {
    background: var(--c-blanc);
}

.lieu-cat.is-active .lieu-cat__count {
    color: rgba(255, 255, 255, 0.85);
}

.lieu-cat:focus-visible,
.lieu-search__geo:focus-visible {
    outline: 2px solid var(--c-mer);
    outline-offset: 2px;
}

/* ---- Distance et compteurs ---- */

.lieu-distance {
    flex: none;
    padding: 0.2rem 0.55rem;
    font-size: 0.75rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--c-marine);
    background: var(--c-sable);
    border-radius: 999px;
}

[data-theme="dark"] .lieu-distance {
    color: var(--c-texte);
    background: rgba(255, 255, 255, 0.10);
}

.section-title__count {
    margin-left: 0.5rem;
    font-size: 0.8rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--c-texte-doux);
}

/* ---- Aucun résultat ---- */

.poi-empty-public {
    padding: var(--space-lg) var(--space-md);
    text-align: center;
    background: var(--c-blanc);
    border: 1px dashed var(--c-bordure);
    border-radius: var(--radius-lg);
}

[data-theme="dark"] .poi-empty-public {
    background: rgba(255, 255, 255, 0.04);
}

.poi-empty-public__title {
    margin: 0 0 0.4rem;
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--c-texte);
}

.poi-empty-public__text {
    margin: 0 auto 1.1rem;
    max-width: 46ch;
    color: var(--c-texte-doux);
    line-height: 1.55;
}

/* ══════════════════════════════════════════════════════════════════
   Carte de lieu — couverture, blason, carte de tête

   POURQUOI : aucune des fiches reprises n'a de photo. La page était cent vingt-sept rectangles de
   texte gris, tous de la même taille : rien n'y donnait envie d'entrer. La couverture abstraite du
   site — déjà employée pour les événements sans visuel — rend à la grille ses couleurs, et la carte
   de tête lui rend un point d'entrée.
   ══════════════════════════════════════════════════════════════════ */

/* Le glyphe de la catégorie, posé en filigrane sur la couverture abstraite. Discret : c'est un
   repère de famille, pas une illustration du lieu — on ne prétend pas montrer ce qu'on n'a pas
   photographié. */
.lieu-card__glyphe {
    position: absolute;
    right: 0.7rem;
    bottom: 0.4rem;
    font-size: clamp(3rem, 9vw, 4.4rem);
    line-height: 1;
    opacity: 0.42;
    filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.35));
    pointer-events: none;
}

/* Pastille de catégorie posée SUR la couverture, en haut à gauche. */
.lieu-card__badge {
    position: absolute;
    top: 0.6rem;
    left: 0.6rem;
    z-index: 2;
}

/* Distance : coin opposé, pour que les deux repères ne se disputent pas la place. */
.lieu-card .lieu-distance {
    position: absolute;
    top: 0.6rem;
    right: 0.6rem;
    z-index: 2;
    background: rgba(10, 61, 98, 0.82);
    color: var(--c-blanc);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
}

/* Le corps de la carte reprend juste sous la couverture. */
.lieu-card .event-card__title {
    margin-top: 0.15rem;
}

/* ---- Carte de tête ----
   La grille des pages de listing donne déjà deux colonnes à sa première tuile (`bento-shared.css`),
   et sa couverture garde le MÊME format que les autres : sur une page, toutes les images sont au
   même ratio — c'est une convention du site, pas un réglage par page. Le vide que cela laisse à
   côté de la deuxième carte n'est pas un accident à masquer par un format sur mesure : c'est une
   case, et le bento la remplit avec un encart, comme sur l'accueil. */
@media (min-width: 980px) {
    .taxonomy-page .events-grid > .event-card-link:first-child .lieu-card__glyphe {
        font-size: 5.4rem;
    }
}

/* ---- Coût de peinture ----
   La page rend jusqu'à cent vingt-sept couvertures d'un coup, là où une page d'événements en montre
   une douzaine. Deux réglages, mesurés : sans eux, le moteur de rendu de Chrome se bloquait
   plusieurs secondes au défilement.

   1. Le grain de la couverture abstraite est peint en `mix-blend-mode: overlay`. Un mode de fusion
      force une couche de composition PAR élément : douze, c'est gratuit ; cent vingt-sept, non. Le
      grain reste, en simple superposition — la différence de rendu est invisible à l'œil, celle de
      coût ne l'est pas.
   2. Les cartes hors écran ne sont plus peintes du tout. `contain-intrinsic-size` donne au
      navigateur une hauteur présumée, sans quoi la barre de défilement sauterait à chaque carte
      atteinte. */
.lieu-card .event-cover-abstract::after {
    mix-blend-mode: normal;
    opacity: 0.07;
}

.taxonomy-page .events-grid > .event-card-link {
    content-visibility: auto;
    contain-intrinsic-size: auto 420px;
}

/* La première tuile est visible d'emblée et sert de repère de mise en page : la différer ferait
   sauter la grille au chargement, pour rien. */
.taxonomy-page .events-grid > .event-card-link:first-child {
    content-visibility: visible;
}

/* Mention « photo d'un tiers » sur la vignette. Discrète mais lisible : c'est une obligation de
   licence, pas une décoration — un crédit illisible ne vaut pas mieux qu'un crédit absent. */
.lieu-card__credit {
    position: absolute;
    left: 0.6rem;
    bottom: 0.5rem;
    z-index: 2;
    padding: 0.15rem 0.5rem;
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--c-blanc);
    background: rgba(10, 61, 98, 0.78);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    border-radius: 999px;
}

/* ══════════════════════════════════════════════════════════════════
   Fiche d'un lieu — alignée sur la fiche événement
   ══════════════════════════════════════════════════════════════════ */

/* Le glyphe de la catégorie, en filigrane sur la couverture composée du bandeau. Plus grand que sur
   les cartes : le bandeau lui donne la place, et c'est le seul visuel de la page tant qu'aucune
   photo n'est posée. */
.lieu-hero__glyphe {
    position: absolute;
    right: clamp(1rem, 4vw, 3rem);
    bottom: clamp(0.5rem, 2vw, 1.5rem);
    z-index: 1;
    font-size: clamp(4rem, 12vw, 7rem);
    line-height: 1;
    opacity: 0.38;
    filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.4));
    pointer-events: none;
}

/* Caractéristiques du lieu, dans le bandeau à côté de la pastille de catégorie. Habillage « verre »
   posé sur la couverture, comme les puces du hero des pages de listing. */
.lieu-hero__tag {
    display: inline-flex;
    align-items: center;
    padding: 0.26rem 0.7rem;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--c-blanc);
    background: rgba(255, 255, 255, 0.16);
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 999px;
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
}

/* Bouton d'itinéraire : pleine largeur en pied de panneau, c'est l'action que la page appelle. */
.lieu-itineraire {
    display: flex;
    width: 100%;
    margin-top: var(--space-sm);
}

/* Grille sans carte de tête : toutes les tuiles à la même largeur. La règle de bento
   (`bento-shared.css`) élargit la première tuile de toute grille d'une page de listing — utile là
   où l'on parcourt, déplacé sur une bande de suggestions où rien ne prime. */
@media (min-width: 980px) {
    /* Plus spécifique que la règle de bento (`:not(:has(.event-card--compact))`), qui sinon l'emportait et
       laissait un vide de ~330 px sous la 2e fiche (audit du 27/10/2026). */
    .taxonomy-page .events-grid.events-grid--egales > .event-card-link:first-child:not(:has(.event-card--compact)) {
        grid-column: auto;
    }

    /* Pas de tête bento ici : la 2e fiche s'étire comme les autres (la règle de bento la laissait à sa
       hauteur naturelle, plus courte que ses voisines). */
    .taxonomy-page .events-grid.events-grid--egales > .event-card-link:nth-child(2),
    .taxonomy-page .events-grid.events-grid--egales > .event-card-link:nth-child(2) .event-card {
        align-self: stretch;
        height: 100%;
    }

    /* Ni le titre agrandi ni la description plus longue de la tuile de tête : même carte que les voisines. */
    .taxonomy-page .events-grid.events-grid--egales > .event-card-link:first-child:not(:has(.event-card--compact)) .event-card__title {
        font-size: 1.2rem;
    }

    .taxonomy-page .events-grid.events-grid--egales > .event-card-link:first-child:not(:has(.event-card--compact)) .event-card__description {
        -webkit-line-clamp: 3;
    }

    .taxonomy-page .events-grid--egales > .event-card-link:first-child .lieu-card .event-card__media {
        aspect-ratio: 4 / 3;
    }
}

/* Le libellé du bouton d'itinéraire porte déjà une flèche dans la traduction ; combinée à l'icône,
   elle faisait passer le texte sur deux lignes dans un bouton pleine largeur. */
.lieu-itineraire {
    text-align: center;
    line-height: 1.3;
}

/* Description complète sur la fiche d'un lieu. `event-card__description` coupe à trois lignes :
   parfait sur une vignette, absurde sur la page qu'on ouvre justement pour la lire. */
.lieu-description {
    max-width: 68ch;
    color: var(--c-texte);
    font-size: var(--fs-md);
    line-height: 1.7;
    text-wrap: pretty;
}

.lieu-description br + br {
    line-height: 2.2;
}

/*
city-combobox.css

QUOI : Moteur de recherche compact à autocomplétion des villes dans le hero marine de la page
       arrondissement (/ou/{slug}). Éléments injectés par assets/js/arrondissement/city-combobox.js.

COMMENT : Le champ est posé sur le hero marine → habillage « verre » blanc translucide (mêmes valeurs
          que .header-search / .lieu-filters). La liste déroulante est un panneau de surface claire
          (jetons sémantiques --c-surface / --c-texte) pour rester lisible en listant des villes, suivi
          des thèmes clair/sombre sans bloc [data-theme] manuel. Corail réservé à l'option active.

OÙ : Importé par assets/styles/app.imports.css (après lieu-filters.css), inliné dans app.css par
     app:assets:bundle-css.

POURQUOI : T10+T12 — remplace les pastilles par un sélecteur cherchable.
*/

/* La liste brute (.lieu-filters) porte display:flex, qui écrase l'attribut [hidden] posé par le JS
   (la règle UA [hidden]{display:none} perd face à une règle auteur display:flex). On rétablit donc
   le masquage pour tout descendant [hidden] du conteneur (liste brute enrichie ET listbox fermée). */
.city-combobox-mount [hidden] {
    display: none;
}

.city-combobox {
    position: relative;
    margin-top: var(--space-sm);
    max-width: 22rem;
}

/* Champ posé sur le hero marine : verre blanc translucide (aligné .header-search). */
.city-combobox__input {
    width: 100%;
    height: 44px;
    padding: 0 0.9rem;
    font: inherit;
    font-size: 0.95rem;
    color: #fff;
    background-color: rgba(255, 255, 255, 0.12);
    border: 1.5px solid rgba(255, 255, 255, 0.28);
    border-radius: var(--radius-md);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    transition: background-color var(--duration-fast) var(--ease-out),
                border-color var(--duration-fast) var(--ease-out);
}

.city-combobox__input::placeholder {
    color: rgba(255, 255, 255, 0.7);
}

.city-combobox__input:hover {
    background-color: rgba(255, 255, 255, 0.2);
    border-color: rgba(255, 255, 255, 0.5);
}

.city-combobox__input:focus-visible {
    outline: 2px solid var(--c-sable);
    outline-offset: 2px;
    background-color: rgba(255, 255, 255, 0.2);
}

/* Panneau déroulant : surface claire détachée (lisible pour une liste de villes). Attaché au <body>
   par le JS (échappe à l'overflow:hidden du hero) ; top/left/width sont posés en inline. */
.city-combobox__list {
    position: absolute;
    z-index: 60;
    box-sizing: border-box;
    margin: 0;
    padding: 0.35rem;
    list-style: none;
    max-height: 16rem;
    overflow-y: auto;
    background-color: var(--c-surface);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
}

/* La liste vit sur <body>, hors du conteneur : son masquage a sa propre règle. */
.city-combobox__list[hidden] {
    display: none;
}

.city-combobox__option {
    padding: 0.55rem 0.7rem;
    border-radius: var(--radius-sm);
    color: var(--c-texte);
    cursor: pointer;
}

/* Corail réservé à l'accent rare : option survolée / surlignée clavier. */
.city-combobox__option.is-active,
.city-combobox__option:hover {
    background-color: var(--c-corail-action);
    color: #fff;
}

.city-combobox__empty {
    padding: 0.55rem 0.7rem;
    color: var(--c-texte-doux);
    font-size: 0.9rem;
}

/*
bento-shared.css

QUOI : Bento mutualisé accueil + taxonomie : cartes partenaires à hauteur naturelle, pile de sponsors, tuile « lead » élargie.

COMMENT : Copie telle quelle des lignes 3860–3948 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ============================ Bento mutualisé (accueil + taxonomie) ============================
   Mise en page « bento » partagée par la grille « par ville » de l'accueil ET les pages ville /
   catégorie. Activée par la classe `.events-grid--bento` (posée par `_partials/_bento_grid.html.twig`
   quand il y a ≥ 2 événements et ≥ 1 sponsor) : lead 2/3 + colonne 1/3 (2e event + sponsor empilés),
   et des piles de sponsors qui comblent les trous de la dernière rangée. Source de vérité unique →
   l'accueil et la taxonomie se comportent exactement pareil. */

/* Cartes partenaires : toujours à leur hauteur naturelle, jamais étirées sur la hauteur d'un
   événement voisin (rendu « case sponsor » compact, dans la grille ville comme dans les résultats). */
.events-grid > .partner-cell {
    align-self: start;
}

/* Pile de partenaires : une « case bento » qui occupe une cellule de la grille et empile des sponsors.
   Elle s'étire (align-self par défaut = stretch) sur toute la hauteur de la rangée pour faire EXACTEMENT
   la taille de l'événement voisin ; les sponsors à l'intérieur se partagent cette hauteur (flex: 1). */
.partner-stack {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}

/* Variante « comblement » des pages arrondissement UNIQUEMENT. Sous 980px la grille passe à une
   colonne : les cases libres n'existent plus, et la pile devient une simple rafale d'encarts à la
   suite des événements. On n'en garde donc qu'un par case — sinon une ville à 3 événements se
   terminerait par 6 entreprises d'affilée sur téléphone.
   Le modificateur est indispensable : `.partner-stack` sert aussi à l'accueil et aux pages ville,
   où la pile est voulue entière en mobile. */
@media (max-width: 979px) {
    .partner-stack--comble .partner-cell:not(:first-child) {
        display: none;
    }
}

/* `flex: 1 1 auto` (base = taille naturelle) : les cartes grandissent pour remplir quand la pile est
   étirée à côté d'un événement, MAIS gardent leur hauteur naturelle quand la pile est seule sur sa
   rangée (sinon, base 0 → les cartes s'effondrent en fines lignes). */
.partner-stack > .partner-cell {
    flex: 1 1 auto;
}

/* Contenu centré : quand une carte s'agrandit pour remplir, le logo + le nom restent équilibrés. */
.partner-stack > .partner-cell .partner-cell__link {
    justify-content: center;
}

/* Colonne droite du bento (2e event + sponsor). Par défaut (mobile/tablette) elle est « transparente »
   (display: contents) : ses enfants coulent normalement dans la grille. Elle ne devient une cellule
   flex à part entière qu'en ≥980px (cf. media query), là où le lead occupe 2 colonnes. */
.lead-aside {
    display: contents;
}

/* Encart « comble-hauteur » (accueil, emplacement `home_lead_aside`) : masqué par défaut — en
   mobile/tablette la colonne n'existe pas visuellement (`display: contents` ci-dessus) et la
   2e carte ne laisse aucun vide ; l'encart n'a de sens qu'en ≥980px (cf. media query). */
.lead-aside > .lead-aside__fill {
    display: none;
}

/* Bento pour les listes (lieux / taxonomie) : 1re tuile « lead » élargie sur grand écran,
   comme l'accueil — donne du rythme et une hiérarchie aux grilles de cartes. */
@media (min-width: 980px) {
    .taxonomy-page .events-grid {
        grid-auto-flow: dense;
    }
    /* `:not(:has(.event-card--compact))` : une carte sans photo (texte seul, cf. event-card-compact.css)
       ne doit JAMAIS être étirée en tuile lead 2 colonnes — sinon un événement isolé sans visuel
       (ex. seul résultat d'une page ville) prend la place de deux cartes pour un rendu vide/mal
       proportionné. Repéré en prod sur /ville/le-portel (1 seul événement, sans photo, étiré pleine
       largeur en tuile lead alors qu'event-card-compact.css documente déjà « jamais étiré »). */
    .taxonomy-page .events-grid > .event-card-link:first-child:not(:has(.event-card--compact)) {
        grid-column: span 2;
    }
    .taxonomy-page .events-grid > .event-card-link:first-child:not(:has(.event-card--compact)) .event-card__title {
        font-size: clamp(1.3rem, 2vw, 1.6rem);
    }
    .taxonomy-page .events-grid > .event-card-link:first-child:not(:has(.event-card--compact)) .event-card__description {
        -webkit-line-clamp: 4;
    }

    /* La 2e tuile partage la 1re rangée avec le lead 2/3 : `align-self: start` + `height: auto`
       l'empêchent de s'étirer sur la hauteur du gros visuel (miroir de l'accueil). En mode bento,
       le 2e enfant est `.lead-aside` (pas un `.event-card-link`) → cette règle ne s'y applique pas. */
    .taxonomy-page .events-grid > .event-card-link:nth-child(2) {
        align-self: start;
        height: auto;
    }
    .taxonomy-page .events-grid > .event-card-link:nth-child(2) .event-card {
        height: auto;
    }

    /* Le LEAD ne s'étire JAMAIS au-delà de sa hauteur naturelle (image au ratio 4/3 fixe,
       cf. site-images.css, + texte) — sa hauteur ne bouge pas selon ce qu'il y a à côté, c'est
       l'inverse qui doit être vrai (cf. `.lead-aside--stack` plus bas + `home-lead-aside-sync.js`,
       qui plafonne la colonne sur la hauteur RÉELLE du lead mesurée après mise en page).
       `align-self: start` est INDISPENSABLE, `height: auto` seul ne suffit pas : sur un enfant de
       grille, `align-items: stretch` (défaut) étire la BOÎTE au format de la ligne indépendamment
       de la valeur de `height` — seul `align-self` en dehors de `stretch` sort l'élément de cet
       étirement (même paire de règles déjà utilisée pour la 2e tuile juste au-dessus). Sans les
       deux ensemble, `height: 100%` (event-card.css, base de toute `.event-card-link`) — ou même
       l'étirement stretch tout court — forçait le lead à la hauteur de ligne dès que la colonne
       d'à côté est plus haute que lui, avec un vide À L'INTÉRIEUR de sa propre carte (bug constaté
       en prod, cf. rapport de tâche : `.event-card` mesurait sa hauteur naturelle mais son parent
       `.event-card-link` restait étiré à la ligne entière autour de lui). Neutre quand la colonne
       d'à côté n'est de toute façon jamais plus haute que lui (pub vendue, pages ville/catégorie). */
    .events-grid--bento > .event-card-link:first-child {
        align-self: start;
        height: auto;
    }
    .events-grid--bento > .event-card-link:first-child .event-card {
        height: auto;
    }

    /* Variante « bento » : la colonne de droite (.lead-aside) occupe UNE cellule à côté du lead 2/3
       et s'étire à sa hauteur (grille = stretch). Elle empile le 2e event (hauteur naturelle) puis un
       sponsor qui grandit (flex: 1) pour combler le reste → le sponsor fait pile la hauteur du lead. */
    .events-grid--bento .lead-aside {
        display: flex;
        flex-direction: column;
        gap: var(--space-md);
        min-height: 0;
    }

    .events-grid--bento .lead-aside > .event-card-link,
    .events-grid--bento .lead-aside > .event-card-link .event-card {
        height: auto; /* 2e event : hauteur naturelle (coupe les height:100%) */
    }

    .events-grid--bento .lead-aside > .partner-stack {
        flex: 1 1 auto; /* le sponsor remplit tout l'espace restant sous le 2e event */
        min-height: 0;
    }

    /* Encart « comble-hauteur » (home_lead_aside) : même mécanique que la pile sponsor ci-dessus —
       le conteneur grandit pour que la colonne fasse pile la hauteur du lead, et l'encart s'étire
       avec lui (le lien interne est déjà en height: 100 %, cf. encadres.css). */
    .events-grid--bento .lead-aside > .lead-aside__fill {
        display: flex;
        flex-direction: column;
        flex: 1 1 auto;
        min-height: 0;
    }

    .events-grid--bento .lead-aside > .lead-aside__fill .encart-pub {
        display: flex;
        flex-direction: column;
        flex: 1 1 auto;
        min-height: 0;
    }

    .events-grid--bento .lead-aside > .lead-aside__fill .encart-pub__link {
        flex: 1 1 auto;
    }

    /* Variante « pile » (accueil, sans encart publicitaire dans ce slot, cf. _event_feed.html.twig) :
       jusqu'à `STACK_MAX` (3) événements sans photo côte à côte du lead, à leur hauteur NATURELLE —
       le partage à parts égales (`flex: 1 1 0`) a été abandonné : compresser une carte en dessous de
       ce que son propre contenu réclame (titre 2 lignes + description 2 lignes) ne laisse pas le
       `line-clamp` faire son travail proprement, le texte est tronché en PLEIN MILIEU d'une ligne
       par l'`overflow: hidden` du conteneur plutôt que par les points de suspension du `line-clamp` —
       constaté en prod, pire que le vide qu'on cherchait à combler. `home-lead-aside-sync.js`
       masque désormais ENTIÈREMENT (jamais à moitié) toute carte qui dépasserait la hauteur du
       lead — mieux vaut 2 cartes complètes qu'une 3e à moitié coupée. */
    .events-grid--bento .lead-aside--stack > .event-card-link,
    .events-grid--bento .lead-aside--stack > .event-card-pair,
    .events-grid--bento .lead-aside--stack > .partner-stack {
        flex: 0 0 auto;
        height: auto;
    }
}


/*
encadres.css

QUOI : Encarts partenaires (variantes bento, footer, sidebar) : visuels, étiquette de transparence, adaptations sombre et reduced-motion. Nom de fichier neutre (anti-adblock).

COMMENT : Copie telle quelle des lignes 3949–4213 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ============================ Encarts publicitaires (Publicité) ============================
   Encarts auto-hébergés (entité `Publicite`) rendus par `_partials/_encart_publicite.html.twig`,
   déclinés en variantes `--bento` (tuile accueil), `--footer` (bandeau pied de page) et `--sidebar`
   (back-office). Esthétique 2026 : coins arrondis « chirurgicaux » (tokens `--radius-*`), micro-effet
   au survol (translation + léger scale + zoom doux du visuel), largeur 100 % fluide (jamais de débordement).
   Visibilité INDÉPENDANTE de motion.js (le pied de page apparaît sur des pages sans `motion.js`) :
   l'encart est toujours visible, l'entrée est une animation CSS autonome. Mode sombre via [data-theme="dark"]
   (surface en encre, le reste s'adapte par tokens). */

.encart-pub {
    position: relative;
    border-radius: var(--radius-lg);
    overflow: hidden;
    background: linear-gradient(160deg, #f3f7ff 0%, #e8f0fe 100%);
    border: 1px solid rgba(46, 109, 240, 0.16);
    box-shadow: var(--shadow-sm);
    animation: fade-in-up 600ms var(--ease-out) both;
    transition: transform var(--duration-base) var(--ease-out),
                box-shadow var(--duration-base) var(--ease-out);
}

.encart-pub:hover {
    transform: translateY(-3px) scale(1.006);
    box-shadow: var(--shadow-md);
}

.encart-pub__link {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
    height: 100%;
    padding: 1rem 1.1rem;
    text-decoration: none;
    color: inherit;
}

/* Pastille « Publicité », rétablie le 2026-09-10 — mais DANS le corps de l'encart, plus en
   surimpression sur la création, et sur tous les emplacements SAUF les deux bandeaux bannière
   (`Emplacement::afficheLaPastille`). C'est la surimpression sur les bannières qui avait été retirée
   le 2026-07-20, pas l'identification elle-même.

   Volontairement NEUTRE : ni corail, ni doré. La charte réserve le corail aux accents ponctuels qui
   appellent une action, et le doré au seul niveau premium d'une entreprise. Une mention légale doit
   être lisible sans concurrencer la création de l'annonceur qu'elle surplombe — la crier serait aussi
   mal la traiter que la taire. Bordure en `currentColor` : la pastille suit la couleur du texte doux,
   donc les deux thèmes, sans une règle de plus. */
.encart-pub__tag {
    align-self: flex-start;
    padding: 0.08rem 0.42rem;
    border: 1px solid currentColor;
    border-radius: 999px;
    color: var(--c-texte-doux);
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    line-height: 1.5;
}

.encart-pub__media {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform var(--duration-slow) var(--ease-out), opacity var(--duration-base) var(--ease-out);
}

.encart-pub:hover .encart-pub__media {
    transform: scale(1.05);
    opacity: 0.96;
}

.encart-pub__body {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
}

.encart-pub__name {
    font-family: var(--font-display);
    font-weight: 800;
    color: var(--c-marine);
    font-size: 1.02rem;
    line-height: 1.2;
}

.encart-pub__desc {
    font-size: 0.84rem;
    color: var(--c-texte-doux);
    line-height: 1.35;
}

.encart-pub__cta {
    margin-top: 0.35rem;
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--c-mer);
}

.encart-pub__cta svg {
    transition: transform var(--duration-fast) var(--ease-out);
}

.encart-pub:hover .encart-pub__cta svg {
    transform: translateX(3px);
}

/* ---------- Variante BENTO (tuile dédiée dans la grille d'accueil) ---------- */

/* Tuile texte seul : généreuse, centrée, accroche typographique. */
.encart-pub--bento .encart-pub__link:not(.encart-pub__link--media) {
    min-height: 150px;
    justify-content: center;
    padding: 1.4rem 1.5rem;
}

.encart-pub--bento .encart-pub__name {
    font-size: clamp(1.1rem, 2vw, 1.4rem);
}

/* Tuile avec visuel : empilée sur mobile (image 16:9 puis texte), scindée en deux sur desktop. */
.encart-pub--bento .encart-pub__link--media {
    padding: 0;
    gap: 0;
}

.encart-pub--bento .encart-pub__link--media .encart-pub__media {
    aspect-ratio: 16 / 9;
}

.encart-pub--bento .encart-pub__link--media .encart-pub__body {
    padding: 0.95rem 1.2rem 1.2rem;
}

@media (min-width: 720px) {
    .encart-pub--bento .encart-pub__link--media {
        flex-direction: row;
        align-items: stretch;
    }
    .encart-pub--bento .encart-pub__link--media .encart-pub__media {
        width: 46%;
        aspect-ratio: auto;
        min-height: 168px;
        flex: 0 0 auto;
    }
    .encart-pub--bento .encart-pub__link--media .encart-pub__body {
        flex: 1;
        justify-content: center;
    }
}

/* La tuile occupe TOUTE la largeur de la grille Bento dès qu'elle passe en multi-colonnes.
   `1 / -1` = de la première à la dernière ligne de grille → pleine largeur, robuste quel que soit
   le nombre de colonnes (2 dès 560px, 3 dès 980px). */
@media (min-width: 560px) {
    .city-block .events-grid > .encart-pub--bento {
        grid-column: 1 / -1;
    }
}

/* ---------- 4e case des listes (`Emplacement::FeedSlot4`) ---------- */

/* Une cellule de grille ordinaire, de la taille d'une carte événement — jamais pleine largeur.
   Le wrapper existe pour ça : `.encart-pub--bento` enfant DIRECT d'une `.events-grid` s'étire sur
   toute la rangée (règle ci-dessus, tuile bento historique). Ici l'encart PREND la place d'une
   carte, il ne doit donc pas en occuper trois. */
.feed-ad-slot {
    display: block;
    min-width: 0;
}

.feed-ad-slot > .encart-pub {
    height: 100%;
}

/* ---------- Bandeau BENTO autonome (pages ville : encart ciblé, AU-DESSUS des événements) ---------- */

/* Rendu du city_bento hors grille (une seule tuile pleine largeur) : on sépare du bloc d'événements
   qui suit. La tuile réutilise telle quelle la variante `.encart-pub--bento` ci-dessus (aucun autre style). */
/* ═══════════ ESPACEMENT UNIFORME DES ENCARTS ═══════════
   RÈGLE : tout encart publicitaire est séparé de ce qui l'entoure par exactement `--encart-gap`,
   au-dessus comme en dessous, sur TOUTES les pages.

   Pourquoi une règle unique plutôt qu'un réglage par page : l'écart réellement perçu ne dépend pas
   que de l'encart, mais aussi de la marge basse du bloc précédent et du padding haut du bloc
   suivant — or ces voisins diffèrent d'une page à l'autre (hero de ville, hero d'accueil, pied de
   page). Compenser au cas par cas donnait 8px ici et 138px là. On IMPOSE donc l'écart en
   neutralisant la contribution des voisins immédiats, au lieu de la subir. */
:root {
    --encart-gap: 2rem;
}

.container > .encart-pub--banner,
.city-bento-highlight,
.site-footer__ad {
    padding-block: 0;
    margin-block: var(--encart-gap);
}

/* Neutralisation des voisins : sans elle, la marge du bloc précédent FUSIONNE avec celle de
   l'encart (collapsing → max des deux, pas 32px) et le padding du bloc suivant s'AJOUTE. */
.page-hero:has(+ .city-bento-highlight),
.page-hero:has(+ .container > .encart-pub--banner),
.page-hero:has(+ .encart-pub--banner) {
    margin-bottom: 0;
}

.city-bento-highlight + .events-section,
.encart-pub--banner + .events-section {
    padding-top: 0;
}

/* Accueil : la carte repliée (`.home-map-section.is-collapsed`) s'intercale entre la bannière et le
   flux, ce qui court-circuitait la règle ci-dessus → 32px au-dessus de la bannière contre 58px en
   dessous (32 de marge + 24 de padding-haut de la section + 2 de bordure de la carte repliée). Mesuré
   le 13/10/2026 sur téléphone. Carte dépliée, sa propre marge reprend la main. */
.encart-pub--banner + .home-map-section.is-collapsed {
    border-width: 0;
}

.encart-pub--banner + .home-map-section.is-collapsed ~ :is(.city-section, .events-section) {
    padding-top: 0;
}

/* Pied de page : `.site-footer__inner` porte 24px de padding-bas qui s'AJOUTENT aux 32px de marge
   de l'encart (un padding ne fusionne pas avec une marge) → 56px au-dessus contre 32px en dessous.
   Défaut constaté sur toutes les pages, l'encart de pied de page étant global. */
.site-footer__inner:has(+ .site-footer__ad) {
    padding-bottom: 0;
}

/* (La respiration verticale des bannières en mobile est réglée plus bas, au niveau de la variante
   `.encart-pub--banner` elle-même — la poser ici serait écrasé par l'ordre source.) */

/* ---------- Variante FOOTER (bandeau partenaire en pied de page) ---------- */

.site-footer__ad {
    margin-bottom: 2rem;
}

.encart-pub--footer {
    border-radius: var(--radius-md);
}

.encart-pub--footer .encart-pub__link {
    flex-direction: row;
    align-items: center;
    gap: 1rem;
    padding: 0.85rem 1.05rem;
}

.encart-pub--footer .encart-pub__link--media {
    padding: 0.5rem 1.05rem 0.5rem 0.5rem;
}

.encart-pub--footer .encart-pub__media {
    flex: 0 0 auto;
    width: 132px;
    height: 76px;
    border-radius: calc(var(--radius-md) - 6px);
}

.encart-pub--footer .encart-pub__body {
    flex: 1;
}

.encart-pub--footer .encart-pub__cta {
    margin-top: 0.15rem;
}

@media (max-width: 480px) {
    .encart-pub--footer .encart-pub__link {
        flex-wrap: wrap;
    }
    .encart-pub--footer .encart-pub__media {
        width: 100%;
        height: auto;
        aspect-ratio: 16 / 9;
    }
}

/* ---------- Variante SIDEBAR (back-office, colonne étroite) ---------- */

.encart-pub--sidebar {
    border-radius: var(--radius-md);
    margin-bottom: 0.85rem;
}

.encart-pub--sidebar .encart-pub__link {
    padding: 0.7rem 0.8rem;
    gap: 0.35rem;
}

.encart-pub--sidebar .encart-pub__link--media {
    padding: 0;
}

.encart-pub--sidebar .encart-pub__link--media .encart-pub__media {
    aspect-ratio: 16 / 9;
}

.encart-pub--sidebar .encart-pub__link--media .encart-pub__body {
    padding: 0.55rem 0.8rem 0.8rem;
}

.encart-pub--sidebar .encart-pub__name {
    font-size: 0.9rem;
}

.encart-pub--sidebar .encart-pub__desc {
    font-size: 0.78rem;
}

/* ---------- Mode sombre : surface en encre (le blanc codé en dur ne se remappe pas) ---------- */
[data-theme="dark"] .encart-pub {
    background: linear-gradient(160deg, #17262f 0%, #111d26 100%);
    border-color: rgba(160, 196, 224, 0.16);
}

/* ---------- Accessibilité : pas d'animation si l'utilisateur la refuse ---------- */
@media (prefers-reduced-motion: reduce) {
    .encart-pub {
        animation: none;
        transition: none;
    }
    .encart-pub:hover {
        transform: none;
    }
    .encart-pub:hover .encart-pub__media,
    .encart-pub:hover .encart-pub__cta svg {
        transform: none;
    }
}



/* ---------- Visuel AU FORMAT du slot (bannière 728/90, rectangle 6:5, demi-page 1:2) ----------
   Posé quand l'encart possède le visuel de la forme déclarée par son emplacement (cf. Emplacement::format).
   Le visuel est servi ENTIER : aspect-ratio du format (variable --encart-ratio posée par le gabarit) +
   object-fit contain — une création d'annonceur n'est JAMAIS rognée, contrairement au repli mono-image
   historique (cover). Sous 720px, --encart-ratio-mobile prend le relais quand le slot décline un format
   mobile (le <picture> bascule la source en parallèle). */

.encart-pub__picture {
    display: contents; /* l'<img> reste l'enfant direct du lien flex, <picture> n'est qu'un porteur de <source> */
}

.encart-pub__link--media.encart-pub__link--format {
    flex-direction: column;
    align-items: stretch;
    padding: 0;
    gap: 0;
}

.encart-pub__link--media.encart-pub__link--format .encart-pub__media {
    width: 100%;
    height: auto;
    min-height: 0;
    aspect-ratio: var(--encart-ratio, 16 / 9);
    object-fit: contain;
    margin-inline: auto;
}

.encart-pub__link--media.encart-pub__link--format .encart-pub__body {
    padding: 0.95rem 1.2rem 1.2rem;
}

/* Pas de zoom au survol sur un visuel au format : la création déborderait de sa boîte. */
.encart-pub:hover .encart-pub__link--format .encart-pub__media {
    transform: none;
}

@media (max-width: 719px) {
    .encart-pub__link--media.encart-pub__link--format .encart-pub__media {
        aspect-ratio: var(--encart-ratio-mobile, var(--encart-ratio, 16 / 9));
    }
}

/* ---------- Variante BANNER (bannière d'accueil & bandeau fin de page) ----------
   Bandeau discret dans le flux : bannière au RATIO 728/90, tag « Publicité », corps texte réduit à
   l'essentiel sous le visuel. Plus de plafond de largeur : la création occupe tout l'espace
   disponible (nouveau format validé avec Alex, remplace le cap IAB leaderboard 728px). Sans
   visuel au format (encart texte ou hérité), la carte compacte par défaut s'applique, bornée à
   la largeur du contenu. */

.encart-pub--banner {
    margin: var(--space-sm) auto;
    padding-inline: max(var(--space-sm), env(safe-area-inset-left));
    background: none;
    border: none;
    box-shadow: none;
}

/* Le `padding-inline` ci-dessus sert au bandeau posé DIRECTEMENT dans la page (il lui donne sa
   gouttière). Quand il est déjà dans un `.container`, celui-ci apporte la même gouttière : les deux
   s'additionnaient et rognaient le visuel de 32px. Conséquence mesurée : à ratio 728:90 identique,
   la création de l'accueil tombait à 350×43px là où celle des pages ville faisait 382×47px.
   On neutralise donc le doublon pour que le MÊME ratio rende la MÊME taille partout. */
.container > .encart-pub--banner {
    padding-inline: 0;
}

.encart-pub--banner .encart-pub__link {
    border-radius: var(--radius-md);
}

/* Respiration verticale resserrée sur téléphone. À 43px de haut, une 728:90 encadrée de 16px de
   vide au-dessus ET en dessous affiche 70% de blanc pour 30% de création — d'où l'effet
   « vide / bannière / vide ». 8px sépare encore nettement l'encart du flux sans l'isoler. */
/* (Aucun réglage de marge par variante ici : l'espacement des encarts est centralisé plus haut par
   `--encart-gap`. Ajouter une règle de marge dans ce bloc la ré-écraserait par l'ordre source.) */

/* ---------- Bannière NUE (modificateur --seul, tous slots au format bannière) ----------
   L'encart se réduit à la création cliquable : aucune carte, aucun corps texte — juste l'image
   (ou le GIF) aux coins arrondis du site (--radius-lg, comme les cartes événement) et l'étiquette
   « Publicité » en surimpression. Le gabarit n'émet pas de body dans ce mode. */

.encart-pub.encart-pub--seul {
    background: none;
    border: none;
    box-shadow: none;
    overflow: visible; /* l'arrondi est porté par le visuel lui-même */
}

.encart-pub--seul .encart-pub__link {
    padding: 0;
    gap: 0;
}

.encart-pub--seul .encart-pub__media {
    border-radius: var(--radius-lg);
    transition: box-shadow var(--duration-base) var(--ease-out);
}

/* Survol : pas de translation de carte, juste l'ombre douce du site sur la création. */
.encart-pub.encart-pub--seul:hover {
    transform: none;
    box-shadow: none;
}

.encart-pub--seul:hover .encart-pub__media {
    box-shadow: var(--shadow-md);
}

/* Sur petit écran, la bannière 728:90 ne fait plus que ~45px de haut : un arrondi de carte (24px)
   la transforme en ovale. On redescend à un arrondi proportionné à sa hauteur. */
@media (max-width: 719px) {
    .encart-pub--seul .encart-pub__media {
        border-radius: var(--radius-sm);
    }
}

/* Bannière nue : le cadre épouse EXACTEMENT la création (taille naturelle, pas de ratio imposé ni de
   `contain`) — sinon un liseré vide apparaissait entre la bordure et l'image (retour d'Ellie, 21/10/2026). */
.encart-pub--seul .encart-pub__link--format .encart-pub__media,
.encart-pub--seul .encart-pub__media {
    width: 100%;
    height: auto;
    aspect-ratio: auto;
    object-fit: fill;
}

/* Bannière de commune dans une section ville des pages arrondissement (`arrondissement/show.html.twig`) :
   entre le titre de la ville et sa grille d'événements (27/10/2026). */
.events-section__banniere {
    margin: 0 0 var(--space-lg);
}

/* Alignée sur les bords de la grille (la variante bannière porte sinon une marge et un retrait latéral). */
.events-section__banniere > .encart-pub {
    margin: 0;
    padding-inline: 0;
}

/*
site-images.css

QUOI : Images de décor (SiteImage) : vignette 16/9 en tête de carte événement, raccord avec la carte « Incontournable ».

COMMENT : Copie telle quelle des lignes 4214–4249 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ──────────────────────────────────────────────────────────────────────────
   Images de décor (SiteImage) : bandeau photo de ville + vignettes de cartes.
   Appended en fin de fichier → l'emporte sur la base `.taxonomy-hero` (y compris
   l'override sombre) à spécificité égale, sans toucher au rendu par défaut.
   ────────────────────────────────────────────────────────────────────────── */

/* Vignette en tête de carte événement : déborde jusqu'aux bords internes
   (marges négatives = padding de la carte), coins supérieurs arrondis. */
.event-card__media {
    position: relative;
    margin: calc(var(--space-md) * -1) calc(var(--space-md) * -1) var(--space-xs);
    /* 4/3 = ratio EXACT du crop admin (image-cropper.js → 800×600). Le conteneur épouse
       le crop : object-fit:cover n'a plus rien à rogner, la vignette montre pile la zone
       sélectionnée par l'admin (correctif « décalage », anciennement 16/9 qui coupait
       ~12 % en haut et en bas de la sélection). */
    aspect-ratio: 4 / 3;
    overflow: hidden;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    background: var(--c-sable-clair);
}

/* Carte « Incontournable » : son padding-top est majoré de 0.85rem (espace réservé
   au badge). La vignette doit donc remonter d'autant pour affleurer le haut du cadre,
   sinon un jour subsiste entre le bord supérieur et la photo. Le badge (absolute)
   flotte alors par-dessus la vignette — rendu premium voulu. */
.event-card--featured .event-card__media {
    margin-top: calc((var(--space-md) + 0.85rem) * -1);
}

.event-card__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* Le <picture> ajouté pour servir un jumeau WebP (cf. webp_variant Twig) ne doit rien changer à la mise
   en page : `display: contents` le retire de la boîte, seul l'<img> qu'il contient reste stylé ci-dessus. */
.event-card__media picture {
    display: contents;
}

.event-card__media img.is-placeholder {
    opacity: 0.7;
}

/* ──────────────────────────────────────────────────────────────────────────
   Couverture abstraite générative — fallback « sans photo »
   Remplace l'ancien placeholder gris (site-image-placeholder.svg) par un visuel
   abstrait premium, DÉTERMINISTE par événement (data-variant = event.id % 6, calculé
   à l'identique côté Twig `_carte_evenement` et JS `search/cards.js`).

   COULEUR = celle de la CATÉGORIE : la couverture consomme `--cat-color` (héritée de
   `.event-card`, définie par `data-cat` dans event-card.css) — la même variable qui
   colore la tuile date et la pastille de catégorie. Le visuel « suit » donc la carte :
   chaque catégorie a sa teinte, chaque événement sa composition (6 variantes de blobs).
   Les tons dérivent de `--cat-color` par `color-mix` avec #000/#fff — MÊME langage que le
   dégradé de la tuile date (event-card.css). Repli `--cat-color` = mer si absent (hero).
   Grain fin commun pour un fini mat premium. Cohérent thème clair ET sombre.
   ────────────────────────────────────────────────────────────────────────── */
.event-cover-abstract {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    /* Tons dérivés de la couleur de catégorie (repli mer pour les contextes sans carte). */
    --cc: var(--cat-color, #1e6091);
    --ab-base: color-mix(in srgb, var(--cc) 82%, #000);
    --ab-deep: color-mix(in srgb, var(--cc) 55%, #000);
    --ab-glow: color-mix(in srgb, color-mix(in srgb, var(--cc) 58%, #fff) 55%, transparent);
    --ab-tint: color-mix(in srgb, var(--cc) 45%, transparent);
    --ab-soft: rgba(255, 255, 255, 0.10);
    --ab-shade: rgba(0, 0, 0, 0.30);
    background-color: var(--ab-base);
    background-repeat: no-repeat;
    overflow: hidden;
    isolation: isolate;
}

/* Grain fin commun (feTurbulence inline) : micro-texture en très faible opacité →
   fini « mat premium », casse le côté plat du dégradé pur. */
.event-cover-abstract::after {
    content: '';
    position: absolute;
    inset: 0;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
    opacity: 0.12;
    mix-blend-mode: overlay;
    pointer-events: none;
}

.event-cover-abstract[data-variant="0"] {
    background-image:
        radial-gradient(120% 120% at 78% 18%, var(--ab-glow) 0%, transparent 55%),
        radial-gradient(90% 90% at 12% 92%, var(--ab-soft) 0%, transparent 60%),
        linear-gradient(135deg, var(--ab-deep) 0%, var(--ab-base) 100%);
}
.event-cover-abstract[data-variant="1"] {
    background-image:
        radial-gradient(70% 70% at 22% 24%, var(--ab-glow) 0%, transparent 55%),
        radial-gradient(120% 120% at 86% 82%, var(--ab-tint) 0%, transparent 60%),
        linear-gradient(150deg, var(--ab-base) 0%, var(--ab-deep) 100%);
}
.event-cover-abstract[data-variant="2"] {
    background-image:
        radial-gradient(100% 100% at 50% -8%, var(--ab-glow) 0%, transparent 55%),
        radial-gradient(85% 85% at 50% 118%, var(--ab-shade) 0%, transparent 60%),
        linear-gradient(180deg, var(--ab-base) 0%, var(--ab-deep) 100%);
}
.event-cover-abstract[data-variant="3"] {
    background-image:
        radial-gradient(88% 88% at 84% 86%, var(--ab-soft) 0%, transparent 55%),
        radial-gradient(110% 110% at 8% 8%, var(--ab-glow) 0%, transparent 55%),
        linear-gradient(135deg, var(--ab-deep) 0%, var(--ab-base) 100%);
}
.event-cover-abstract[data-variant="4"] {
    background-image:
        conic-gradient(from 210deg at 32% 30%, var(--ab-glow), transparent 42%),
        radial-gradient(120% 120% at 82% 72%, var(--ab-tint) 0%, transparent 60%),
        linear-gradient(135deg, var(--ab-deep) 0%, var(--ab-base) 100%);
}
.event-cover-abstract[data-variant="5"] {
    background-image:
        radial-gradient(58% 58% at 26% 30%, var(--ab-glow) 0%, transparent 55%),
        radial-gradient(66% 66% at 80% 68%, var(--ab-tint) 0%, transparent 55%),
        linear-gradient(160deg, var(--ab-deep) 0%, var(--ab-base) 100%);
}

/* Motif de vagues (cercles concentriques depuis le coin bas gauche, comme une houle vue d'en haut) : relie la
   couverture à la Côte d'Opale et casse l'aplat sans rien dire de faux sur l'événement (27/10/2026). */
.event-cover-abstract::before {
    content: '';
    position: absolute;
    inset: 0;
    background: repeating-radial-gradient(circle at 0% 115%, transparent 0 26px, rgba(255, 255, 255, 0.075) 26px 27.5px);
    pointer-events: none;
}

/* Grande icône de la catégorie (sprite `#cat-*`), en filigrane dans le coin bas droit. */
.event-cover-abstract__icone {
    position: absolute;
    right: 6%;
    bottom: 8%;
    width: auto;
    height: 52%;
    aspect-ratio: 1;
    fill: none;
    stroke: #ffffff;
    stroke-width: 1.4;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: 0.3;
    transform: rotate(-8deg);
    filter: drop-shadow(0 6px 14px rgba(0, 0, 0, 0.18));
}

@media (prefers-reduced-motion: no-preference) {
    .event-cover-abstract__icone { transition: transform 0.45s var(--ease-out); }
    .event-card-link:hover .event-cover-abstract__icone { transform: rotate(-3deg) scale(1.06); }
    .event-card-link:hover .event-cover-abstract { transform: scale(1.015); }
    .event-cover-abstract { transition: transform var(--duration-base) var(--ease-out); }
}

/* ──────────────────────────────────────────────────────────────────────────
   Pastille « Quick Edit » admin — raccourci d'édition en surimpression
   Discrète (verre marine), n'apparaît QUE pour un admin (rendu conditionnel
   `is_granted('ROLE_ADMIN')` en Twig / `window.OPALE_ADMIN` en JS). Ancrée en haut
   à GAUCHE de la vignette (le bouton like occupe le coin haut-droit). Comme la carte
   est déjà enveloppée dans un <a>, c'est un <button> (interdit d'imbriquer un <a>) :
   la navigation vers le back-office est déléguée en JS (data-quick-edit).
   ────────────────────────────────────────────────────────────────────────── */
.quick-edit {
    position: absolute;
    top: 0.55rem;
    left: 0.55rem;
    z-index: 3;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    border: none;
    border-radius: 999px;
    background: rgba(10, 61, 98, 0.60);
    -webkit-backdrop-filter: blur(6px) saturate(140%);
    backdrop-filter: blur(6px) saturate(140%);
    color: #fff;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(10, 61, 98, 0.35);
    opacity: 0.88;
    transition: background var(--duration-fast) var(--ease-out),
                opacity var(--duration-fast) var(--ease-out),
                transform var(--duration-fast) var(--ease-out);
}
.quick-edit:hover {
    background: var(--c-corail);
    opacity: 1;
    transform: translateY(-1px);
}
.quick-edit:focus-visible {
    outline: 2px solid var(--c-blanc);
    outline-offset: 2px;
    opacity: 1;
}
.quick-edit__icon {
    width: 15px;
    height: 15px;
    stroke-width: 2;
}


/*
event-card-compact.css

QUOI : Variante « texte seul » de la carte événement (`.event-card--compact`, posée par
`_partials/_carte_evenement.html.twig` quand `compact: true`) et son conteneur d'appariement
(`.event-card-pair`), qui empile 2 cartes compactes dans une seule cellule de `.events-grid`.

COMMENT : Les événements sans photo de couverture (`Event::getImageCouverture() === null`) sont
regroupés par paires consécutives côté PHP (`HomePageComposer::pairConsecutiveNoPhotoEvents`) — un
slot `pair` occupe UNE cellule de la grille existante, les 2 cartes empilées verticalement à
l'intérieur. Un événement sans photo isolé (pas de second consécutif) reste seul, en carte compacte
de taille naturelle, jamais étiré pour remplir une cellule.

OÙ : Importé par assets/styles/app.css, après `event-card.css` et `site-images.css` (dont hérite la
carte compacte — seul `.event-card__media` change).

POURQUOI : Remplace le dégradé génératif plein format des événements sans photo (moins de « designed
mais vide ») par un rendu texte compact, ajusté par inspection visuelle réelle en navigateur (voir
rapport de tâche).
*/

.event-card-pair {
    display: flex;
    flex-direction: column;
    gap: 1.1rem;
    height: 100%;
}

@media (min-width: 600px) {
    .event-card-pair {
        gap: var(--space-md);
    }
}

.event-card-pair .event-card-link {
    flex: 1 1 0;
}

/* Carte compacte ISOLÉE (pas de second événement consécutif pour former une paire) : le commentaire
   d'en-tête promet « jamais étiré pour remplir une cellule », mais rien ne l'empêchait réellement
   en dehors de `.event-card-pair` — un `.event-card-link` compact posé comme enfant direct de
   `.events-grid` hérite du `align-items: stretch` par défaut de CSS Grid et s'étire sur toute la
   hauteur de sa rangée dès qu'un voisin plus haut (la tuile lead notamment) la définit. Repéré en
   prod sur l'accueil (« Le Portel d'antan », isolé dans `.city-block .events-grid--bento`, étiré à
   554px au lieu de sa hauteur naturelle). Le sélecteur `>` exclut volontairement les cartes DANS
   `.event-card-pair` (ci-dessus) : celles-ci doivent continuer à se répartir la hauteur de la
   cellule à parts égales, seule une carte vraiment isolée doit garder sa taille naturelle. */
.events-grid > .event-card-link:has(.event-card--compact) {
    align-self: start;
    height: auto;
}

.events-grid > .event-card-link:has(.event-card--compact) .event-card {
    height: auto;
}

.event-card--compact .event-card__media {
    display: none;
}

.event-card--compact {
    padding: var(--space-sm);
    gap: 0.35rem;
}

.event-card--compact .event-card__header {
    margin-bottom: 0.3rem;
}

.event-card--compact .event-card__description {
    -webkit-line-clamp: 2;
}

/* Carte compacte isolée immédiatement suivie d'un slot `sponsors` dans le flux (cf.
   `home/_partials/_event_feed_fragment.html.twig`, `consumedSponsorSlots`) : la pile sponsor est
   absorbée dans LA MÊME cellule de grille plutôt que de former sa propre cellule — la carte garde sa
   hauteur naturelle, la pile comble le reste (même logique que `.lead-aside__fill`, généralisée à
   tout le flux, pas seulement la 1re rangée). Le wrapper lui-même garde le stretch par défaut de la
   grille (pas de `.event-card-link`, donc pas concerné par la règle d'isolement ci-dessus) : c'est lui
   qui fait la hauteur de la rangée, pas la carte à l'intérieur. */
.event-card-fill {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}

.event-card-fill > .event-card-link,
.event-card-fill > .event-card-link .event-card {
    flex: 0 0 auto;
    height: auto;
}

.event-card-fill__pad {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

.event-card-fill__pad .partner-stack {
    flex: 1 1 auto;
    min-height: 0;
}

/* Un seul sponsor dans le comblement (cf. `_event_feed_fragment.html.twig`, `--single`) : sa carte
   s'étire déjà (`.partner-stack > .partner-cell { flex: 1 1 auto }`, règle bento), mais son contenu
   (pastille + logo + texte) reste, lui, une hauteur naturelle fixe — sans ce centrage, il resterait
   collé en haut de la carte étirée, avec un grand vide en dessous, façon carte à moitié vide plutôt
   qu'un encart voulu ainsi. */
.event-card-fill__pad--single .partner-cell__link {
    justify-content: center;
}

/*
like-button.css

QUOI : Bouton « j'aime » (cœur) : variantes pastille de carte et pilule de fiche, pop à la bascule, adaptations sombre.

COMMENT : Copie telle quelle des lignes 4250–4373 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* ──────────────────────────────────────────────────────────────────────────
   Bouton « j'aime » (cœur) — système de favoris
   Deux variantes : `--card` (pastille en surimpression de la vignette) et
   `--detail` (pilule cœur + libellé + compteur sur la fiche événement).
   ────────────────────────────────────────────────────────────────────────── */
.like-btn {
    --like-color: #e6396b;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    border: none;
    cursor: pointer;
    font: inherit;
    color: var(--c-encre, #1f2a37);
    background: none;
    -webkit-tap-highlight-color: transparent;
}

.like-btn__icon {
    width: 1.25rem;
    height: 1.25rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    transition: transform 0.18s ease, fill 0.18s ease, stroke 0.18s ease;
}

.like-btn.is-liked .like-btn__icon {
    fill: var(--like-color);
    stroke: var(--like-color);
}

/* Petit « pop » à la bascule. */
.like-btn:active .like-btn__icon {
    transform: scale(0.82);
}

/* ── Variante carte : pilule flottante « cœur + nombre de likes » en haut de la vignette ── */
.like-btn--card {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    z-index: 2;
    gap: 0.3rem;
    padding: 0.3rem 0.6rem;
    border-radius: 999px;
    font-size: 0.82rem;
    font-weight: 700;
    line-height: 1;
    color: #fff;
    background: rgba(15, 23, 42, 0.5);
    backdrop-filter: blur(4px);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
    transition: background 0.18s ease, transform 0.18s ease;
}

.like-btn--card:hover {
    background: rgba(15, 23, 42, 0.66);
    transform: scale(1.05);
}

.like-btn--card.is-liked {
    background: #fff;
    color: var(--like-color);
}

.like-btn--card .like-btn__icon {
    width: 1.05rem;
    height: 1.05rem;
}

/* ── Variante fiche : pilule cœur + compteur ──
   Base = MODE CLAIR : la pilule vit dans `.event-info-panel` (fond clair) → encre foncée + fond/bordure
   légèrement teintés sombre, pour rester lisible (avant, `color:#fff` la rendait blanc sur blanc = invisible).
   Le MODE SOMBRE restaure le blanc translucide (override plus bas) ; le FAB mobile impose son propre habillage
   corail (event-detail.css, spécificité supérieure) et n'est donc pas affecté. */
.like-btn--detail {
    padding: 0.55rem 1.1rem;
    border-radius: 999px;
    font-weight: 600;
    color: var(--c-encre, #1f2a37);
    background: rgba(15, 23, 42, 0.06);
    border: 1px solid rgba(15, 23, 42, 0.16);
    backdrop-filter: blur(6px);
    text-decoration: none;
    transition: background 0.18s ease, border-color 0.18s ease;
}

.like-btn--detail:hover {
    background: rgba(15, 23, 42, 0.11);
}

.like-btn--detail.is-liked {
    background: rgba(230, 57, 107, 0.10);
    color: var(--like-color);
    border-color: rgba(230, 57, 107, 0.45);
}

/* Mode sombre : la pilule vit sur un panneau sombre → blanc translucide (habillage d'origine). */
[data-theme="dark"] .like-btn--detail {
    color: #fff;
    background: rgba(255, 255, 255, 0.16);
    border-color: rgba(255, 255, 255, 0.35);
}

[data-theme="dark"] .like-btn--detail:hover {
    background: rgba(255, 255, 255, 0.26);
}

[data-theme="dark"] .like-btn--detail.is-liked {
    background: #fff;
    color: var(--like-color);
    border-color: #fff;
}

.like-btn__count {
    font-variant-numeric: tabular-nums;
    font-weight: 700;
}

.event-hero__actions {
    margin-top: var(--space-sm);
}

/* ──────────────────────────────────────────────────────────────────────────
   Toast d'erreur de favori (créé par likes.js) : message expliquant l'échec
   d'un « j'aime » (réseau KO), sinon l'annulation optimiste serait muette.
   Bas d'écran, discret, auto-masqué ; role="status" pour les lecteurs d'écran.
   ────────────────────────────────────────────────────────────────────────── */
.like-toast {
    position: fixed;
    left: 50%;
    bottom: calc(env(safe-area-inset-bottom, 0px) + var(--space-md));
    transform: translate(-50%, 1rem);
    z-index: 1000;
    max-width: min(92vw, 30rem);
    padding: 0.7rem 1rem;
    font-size: 0.9rem;
    line-height: 1.4;
    color: var(--c-blanc);
    background-color: var(--c-corail-fonce);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    opacity: 0;
    pointer-events: none;
    transition: opacity 220ms var(--ease-out), transform 220ms var(--ease-out);
}

.like-toast.is-visible {
    opacity: 1;
    transform: translate(-50%, 0);
}

@media (prefers-reduced-motion: reduce) {
    .like-toast {
        transition: opacity 220ms var(--ease-out);
    }

    .like-toast.is-visible {
        transform: translate(-50%, 0);
    }
}


/*
about-extras.css

QUOI : Photo d'illustration de la page « À propos » (slot about_photo).

COMMENT : Copie telle quelle des lignes 4374–4394 de public/css/style.css
          (scission jalon 5 — blocs contigus, zéro réécriture de règle).

OÙ : Importé par assets/styles/app.css, dans l'ordre de cascade du fichier d'origine.

POURQUOI : specs/projet.md §4.2 — aucun fichier CSS > 500 lignes, rendu identique
           au pixel (invariant I4).
*/

/* Photo d'illustration de la page « À propos » (slot about_photo). */
.about-photo {
    margin: 0 0 var(--space-lg);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-md);
}

.about-photo img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 3;
    object-fit: cover;
}

@media (min-width: 700px) {
    .about-photo img {
        aspect-ratio: 16 / 7;
    }
}

/*
pages/entreprise.css

QUOI : Fiche publique d'une entreprise (`entreprise/show.html.twig`) et bloc annuaire des pages ville
       (`_partials/_bloc_annuaire.html.twig`).

COMMENT : Uniquement des tokens (`--c-*`, `--radius-*`, `--shadow-*`, `--space-*`) : le mode sombre
          suit alors sans règle dédiée, puisque `base/theme-dark.css` redéfinit ces mêmes variables.

OÙ : Importé en fin de `app.imports.css` ; le bundle servi est `app.css`, régénéré par
     `php bin/console app:assets:bundle-css`.

POURQUOI : La fiche est volontairement sobre — elle sert les trois niveaux de présence avec le même
           gabarit, la hiérarchie vient du contenu présent (photo, description) et non d'un habillage
           différent.
*/

/* ---------- Fiche entreprise ---------- */

.entreprise {
    max-width: 60rem;
    margin: 0 auto;
    padding: var(--space-lg) var(--space-sm) var(--space-xl);
}

.entreprise__fiche {
    background: var(--c-surface);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    padding: var(--space-lg);
}

.entreprise__photo {
    display: block;
    width: 100%;
    max-height: 22rem;
    object-fit: cover;
    border-radius: var(--radius-md);
    margin-bottom: var(--space-md);
}

.entreprise__nom {
    margin: 0;
    color: var(--c-marine);
    font-size: clamp(1.6rem, 4vw, 2.25rem);
    line-height: 1.15;
}

.entreprise__soustitre {
    margin: var(--space-xs) 0 0;
    color: var(--c-texte-doux);
    font-size: 1.05rem;
}

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

.entreprise__theme {
    background: var(--c-surface-2);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-sm);
    color: var(--c-texte);
    font-size: 0.85rem;
    padding: 0.25rem 0.7rem;
}

.entreprise__description {
    margin-top: var(--space-md);
    color: var(--c-texte);
    line-height: 1.65;
}

.entreprise__infos {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-xs) var(--space-sm);
    margin: var(--space-md) 0 0;
    padding-top: var(--space-md);
    border-top: 1px solid var(--c-bordure);
}

.entreprise__infos dt {
    color: var(--c-texte-doux);
    font-size: 0.9rem;
}

.entreprise__infos dd {
    margin: 0;
    color: var(--c-texte);
}

.entreprise__infos a {
    color: var(--c-mer);
}

.entreprise__site {
    display: inline-block;
    margin-top: var(--space-md);
    padding: 0.6rem 1.4rem;
    background: var(--c-corail-action);
    color: var(--c-blanc);
    border-radius: var(--radius-sm);
    font-weight: 600;
    text-decoration: none;
}

.entreprise__site:hover,
.entreprise__site:focus-visible {
    background: var(--c-corail-fonce);
}

.entreprise__retour {
    display: inline-block;
    margin-top: var(--space-md);
    margin-left: var(--space-sm);
    color: var(--c-mer);
    font-size: 0.95rem;
}

/* ---------- Signalement (fiche entreprise) ----------
   Revenu sur le bouton plein initial (demandé « en gros ») : repositionné tout en bas de fiche, discret,
   même traitement que le lien de la fiche événement (cf. `.event-signaler-btn`, event-detail-social.css) —
   un dernier recours qu'on ne met plus en avant. */
.entreprise-signaler {
    margin: var(--space-lg) 0 0;
    padding-top: var(--space-sm);
    border-top: 1px dashed var(--c-bordure);
}

.entreprise-signaler-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.4rem 0.2rem;
    background: transparent;
    border: none;
    color: var(--c-texte-doux);
    font: inherit;
    font-size: 0.88rem;
    cursor: pointer;
    text-decoration: underline;
    text-decoration-color: rgba(90, 107, 122, 0.4);
    text-underline-offset: 3px;
    list-style: none;
    transition: color var(--duration-base, 200ms) var(--ease-out, ease-out);
}

.entreprise-signaler-btn::-webkit-details-marker {
    display: none;
}

.entreprise-signaler-btn:hover {
    color: var(--c-corail-fonce);
    text-decoration-color: currentColor;
}

.entreprise-signaler-btn__icon {
    font-size: 1rem;
    line-height: 1;
}

.entreprise-signaler-form {
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding-top: var(--space-sm);
    max-width: 32rem;
}

/* Honeypot : invisible d'un humain, mais laissé dans le flux du document — un
   `display: none` est justement ce que certains robots détectent pour l'éviter. */
.entreprise-signaler-form .honeypot-field {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.entreprise-signaler__label {
    font-size: 0.9rem;
    color: var(--c-texte-doux);
}

.entreprise-signaler__textarea {
    width: 100%;
    min-height: 96px;
    padding: 0.75rem 0.9rem;
    border: 1.5px solid var(--c-bordure);
    border-radius: var(--radius-md);
    background: var(--c-surface-2);
    color: var(--c-texte);
    font: inherit;
    font-size: 0.9rem;
    resize: vertical;
    transition: border-color var(--duration-fast, 150ms) var(--ease-out, ease-out),
                box-shadow var(--duration-fast, 150ms) var(--ease-out, ease-out);
}

.entreprise-signaler__textarea:hover {
    border-color: var(--c-mer-clair);
}

.entreprise-signaler__textarea:focus {
    outline: none;
    border-color: var(--c-mer);
    box-shadow: 0 0 0 4px var(--c-focus);
}

.entreprise-signaler__submit {
    align-self: flex-start;
}

/* ---------- Bloc annuaire des pages ville ---------- */

.bloc-annuaire {
    margin-top: var(--space-xl);
    padding-top: var(--space-lg);
    border-top: 1px solid var(--c-bordure);
}

.bloc-annuaire__titre {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    margin: 0 0 var(--space-md);
    color: var(--c-marine);
    font-size: clamp(1.3rem, 3vw, 1.75rem);
}

.bloc-annuaire__compte {
    background: var(--c-surface-2);
    border-radius: var(--radius-sm);
    color: var(--c-texte-doux);
    font-size: 0.85rem;
    font-weight: 500;
    padding: 0.15rem 0.6rem;
}

.bloc-annuaire__filtres {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
    margin-bottom: var(--space-md);
}

.bloc-annuaire__filtres input,
.bloc-annuaire__filtres select {
    background: var(--c-surface);
    border: 1px solid var(--c-bordure-champ);
    border-radius: var(--radius-sm);
    color: var(--c-texte);
    min-height: 44px; /* champs de 34 px → 44 px (cible tactile, 27/10/2026) */
    padding: 0.5rem 0.85rem;
}

/* Sans base flex explicite, le champ retombe sur la largeur par défaut du navigateur (~20
   caractères) et tronque son propre placeholder ("Rechercher un professionnel" → "Rechercher un
   profes…") — régression du passage "entreprise" → "professionnel" (mot plus long). `flex-wrap`
   du parent absorbe déjà le passage à la ligne sur mobile : un `flex-basis` généreux suffit, pas
   besoin de media query dédiée (cf. règle de l'échelle fluide unique, DESIGN.md §3). */
.bloc-annuaire__filtres input[type="search"] {
    flex: 1 1 240px;
    min-width: 0;
}

/* La liste des secteurs prend la largeur de son plus long libellé (~380 px) : sur un téléphone, elle
   débordait de l'écran et faisait défiler toute la page à l'horizontale (audit du 27/10/2026). */
.bloc-annuaire__filtres select {
    flex: 1 1 200px;
    min-width: 0;
    max-width: 100%;
}

.bloc-annuaire__filtres button {
    background: var(--c-action);
    border: 0;
    border-radius: var(--radius-sm);
    color: var(--c-blanc);
    cursor: pointer;
    font-weight: 600;
    min-height: 44px;
    padding: 0.5rem 1.25rem;
}

.bloc-annuaire__liste {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: var(--space-xs);
    list-style: none;
    margin: 0;
    padding: 0;
}

.bloc-annuaire__item a {
    display: block;
    height: 100%;
    background: var(--c-surface);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-md);
    padding: var(--space-sm);
    text-decoration: none;
}

.bloc-annuaire__item a:hover,
.bloc-annuaire__item a:focus-visible {
    box-shadow: var(--shadow-sm);
}

/* Monogramme : l'initiale du professionnel dans un rond, à gauche de la fiche — la liste n'était qu'un mur de texte
   (audit mobile du 27/10/2026). Corail plein pour les fiches qui ont une page Pro. */
.bloc-annuaire__item a {
    position: relative;
    padding-left: calc(var(--space-sm) + 3.25rem);
}

.bloc-annuaire__mono {
    position: absolute;
    top: var(--space-sm);
    left: var(--space-sm);
    display: grid;
    place-items: center;
    width: 2.6rem;
    height: 2.6rem;
    font-family: var(--font-display);
    font-size: 1.15rem;
    font-weight: 800;
    color: var(--c-mer);
    background: color-mix(in srgb, var(--c-mer) 13%, var(--c-surface));
    border-radius: 0.85rem;
}

.bloc-annuaire__item--page-pro .bloc-annuaire__mono {
    color: #ffffff;
    background: linear-gradient(135deg, var(--c-corail-action) 0%, var(--c-corail-action-fonce) 100%);
}

/* Pastille de niveau de présence — même vocabulaire que `.partner-cell__tag` des encarts, pour
   qu'une entreprise se lise pareil dans la grille et dans cette liste. C'est ici que les deux
   niveaux coexistent : la couleur est donc la seule distinction visible, doublée d'un libellé en
   toutes lettres pour les lecteurs d'écran (WCAG 1.4.1). La classe de base porte déjà la couleur
   « gratuit » (bleu) : `--premium` est le seul modificateur, il n'existe plus de 3e teinte. */
.bloc-annuaire__pastille {
    display: inline-block;
    margin-bottom: 0.35rem;
    font-size: 0.62rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0.15rem 0.45rem;
    border-radius: 999px;
    color: var(--c-niveau-normale-texte);
    background: var(--c-niveau-normale-fond);
}

.bloc-annuaire__pastille--premium {
    color: var(--c-niveau-boostee-texte);
    background: var(--c-niveau-boostee-fond);
}

/* Les premium sont déjà en tête de liste : le rang est porté par l'ordre, pas par un habillage.
   On se contente de poser la surface secondaire du système sous les premium, ce qui les détache
   sans introduire de signal supplémentaire à décoder. */
.bloc-annuaire__item--premium a {
    background: var(--c-surface-2);
}

.bloc-annuaire__nom {
    display: block;
    color: var(--c-marine);
    font-weight: 600;
}

.bloc-annuaire__soustitre {
    display: block;
    margin-top: 0.15rem;
    color: var(--c-texte-doux);
    font-size: 0.9rem;
}

/* Ville — uniquement sur la page annuaire dédiée (`annuaire/index.html.twig`) : le bloc annuaire des
   pages ville, lui, est déjà scopé à une seule ville, ce libellé y serait redondant. */
.bloc-annuaire__ville {
    display: inline-block;
    margin-top: 0.15rem;
    color: var(--c-mer);
    font-size: 0.85rem;
    font-weight: 600;
}

.bloc-annuaire__pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-sm);
    margin-top: var(--space-md);
    color: var(--c-texte-doux);
}

/* Précédent / Suivant en pilules de 44 px (un simple lien texte, difficile à viser au doigt, audit de design
   du 27/10/2026). */
.bloc-annuaire__pagination a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 1.2rem;
    color: var(--c-mer);
    font-weight: 700;
    text-decoration: none;
    background: var(--c-surface);
    border: 1px solid var(--c-bordure-champ);
    border-radius: 999px;
    transition: border-color var(--duration-fast) var(--ease-out), background-color var(--duration-fast) var(--ease-out);
}

.bloc-annuaire__pagination a:hover {
    border-color: var(--c-mer);
    background: color-mix(in srgb, var(--c-mer) 8%, var(--c-surface));
}

.bloc-annuaire__suggestion {
    margin: var(--space-md) 0 0;
    text-align: center;
}

/* ─────────────────────────────────────────────────────────────────────────────
   Formulaire de contact d'une entreprise

   La section reprend la carte de la fiche (surface, bordure, rayon, ombre teintée)
   pour se lire comme sa suite naturelle, et non comme un bloc rapporté.

   Repliée par défaut : la fiche reste une fiche. Le dépliant natif `<details>` est
   préféré à du JavaScript — il fonctionne sans script, reste accessible au clavier
   et annonce son état aux lecteurs d'écran sans un attribut de plus.
   ───────────────────────────────────────────────────────────────────────────── */
/* La section vit DANS la carte de la fiche : ni fond, ni bordure, ni ombre propres — un filet
   supérieur suffit à la séparer, comme le bloc d'informations juste au-dessus. Lui donner sa
   propre carte produisait deux blocs distincts là où il n'y a qu'une entreprise. */
.entreprise-contact {
    margin-top: var(--space-md);
    padding-top: var(--space-md);
    border-top: 1px solid var(--c-bordure);
}

.entreprise-contact__pli {
    border-radius: var(--radius-md);
    overflow: hidden;
}

/* Le marqueur natif est retiré au profit d'un chevron maîtrisé : `list-style` couvre
   Firefox, le pseudo-élément WebKit couvre Safari et Chrome. */
.entreprise-contact__declencheur {
    list-style: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    padding: var(--space-sm) 0;
    font-family: var(--font-display, inherit);
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--c-marine);
}

.entreprise-contact__declencheur::-webkit-details-marker { display: none; }

.entreprise-contact__declencheur::before {
    content: "";
    width: 0.6rem;
    height: 0.6rem;
    border-right: 2px solid var(--c-mer);
    border-bottom: 2px solid var(--c-mer);
    transform: rotate(-45deg);
    transition: transform 200ms var(--ease-out, ease);
    flex: none;
}

.entreprise-contact__pli[open] .entreprise-contact__declencheur::before {
    transform: rotate(45deg);
}

.entreprise-contact__declencheur:hover { color: var(--c-mer); }

.entreprise-contact__declencheur:focus-visible {
    outline: 3px solid var(--c-focus);
    outline-offset: -3px;
}

.entreprise-contact__intro,
.entreprise-contact__mentions {
    margin: 0 0 var(--space-md);
    color: var(--c-texte-doux);
    font-size: 0.92rem;
    line-height: 1.6;
}

.entreprise-contact__mentions {
    margin-top: var(--space-md);
    margin-bottom: 0;
    font-size: 0.82rem;
}

.entreprise-contact__form {
    padding: 0;
    display: grid;
    gap: var(--space-sm);
}

/* Symfony enveloppe chaque champ dans un `div` : on empile libellé puis contrôle,
   au lieu de l'alignement en ligne du navigateur qui collait l'un à l'autre. */
.entreprise-contact__form > div {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.entreprise-contact__form label {
    font-weight: 600;
    color: var(--c-marine);
    font-size: 0.95rem;
}

.entreprise-contact__form input[type="text"],
.entreprise-contact__form input[type="email"],
.entreprise-contact__form input[type="tel"],
.entreprise-contact__form textarea {
    width: 100%;
    padding: 0.7rem 0.85rem;
    font: inherit;
    color: var(--c-texte);
    background: var(--c-sable-clair);
    border: 1px solid var(--c-bordure-champ);
    border-radius: var(--radius-sm);
    transition: border-color 160ms var(--ease-out, ease), box-shadow 160ms var(--ease-out, ease);
}

.entreprise-contact__form textarea {
    resize: vertical;
    min-height: 9rem;
}

.entreprise-contact__form input:focus,
.entreprise-contact__form textarea:focus {
    outline: none;
    border-color: var(--c-mer);
    box-shadow: 0 0 0 3px var(--c-focus);
}

/* Case de consentement : case d'abord, libellé à côté — l'ordre vient du gabarit, qui rend le
   widget avant son libellé. Sans quoi `form_row` place le libellé en tête et rejette la case en
   fin de ligne, à plusieurs centimètres du texte qu'elle valide. */
.entreprise-contact__consentement {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    gap: var(--space-xs);
}

.entreprise-contact__form input[type="checkbox"] {
    margin-top: 0.25rem;
    width: 1.05rem;
    height: 1.05rem;
    accent-color: var(--c-mer);
    flex: none;
}

.entreprise-contact__consentement label {
    font-weight: 400;
    color: var(--c-texte);
    font-size: 0.92rem;
    line-height: 1.5;
}

.entreprise-contact__form .form-help,
.entreprise-contact__form .help-text,
.entreprise-contact__form small {
    color: var(--c-texte-doux);
    font-size: 0.85rem;
}

.entreprise-contact__form ul,
.entreprise-contact__form .form-error-message {
    margin: 0.15rem 0 0;
    padding-left: 1.1rem;
    color: var(--c-corail-texte);
    font-size: 0.85rem;
}

.entreprise-contact__form button[type="submit"] {
    justify-self: start;
    margin-top: var(--space-xs);
    padding: 0.8rem 1.6rem;
    font: inherit;
    font-weight: 700;
    color: var(--c-blanc);
    background: linear-gradient(135deg, var(--c-marine) 0%, var(--c-mer) 100%);
    border: 0;
    border-radius: 999px;
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    transition: transform 160ms var(--ease-out, ease), box-shadow 160ms var(--ease-out, ease);
}

.entreprise-contact__form button[type="submit"]:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-md);
}

.entreprise-contact__form button[type="submit"]:focus-visible {
    outline: 3px solid var(--c-focus);
    outline-offset: 2px;
}

/* Honeypot : invisible d'un humain, mais laissé dans le flux du document — un
   `display: none` est justement ce que certains robots détectent pour l'éviter. */
.entreprise-contact__form .honeypot-field {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

@media (max-width: 640px) {
    .entreprise-contact__form button[type="submit"] { justify-self: stretch; text-align: center; }
}

/*
rapport-partenaire.css

QUOI : Page publique du rapport d'audience d'un partenaire (`/partenaire/rapport/{token}`).

COMMENT : Une colonne centrée sur fond sable, une carte blanche par encart, l'accent bleu mer pour la
          période active et la courbe. Aucun menu du site : la page se suffit.
*/

.rapport {
    max-width: 820px;
    margin: 0 auto;
    padding: 2.5rem 1rem 3rem;
    color: var(--c-texte);
}

.rapport__tete {
    margin-bottom: 1.75rem;
}

.rapport__marque {
    margin: 0 0 0.35rem;
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--c-mer);
}

.rapport__titre {
    margin: 0;
    font-size: clamp(1.6rem, 4vw, 2.2rem);
    line-height: 1.15;
}

.rapport__sous-titre {
    margin: 0.35rem 0 1rem;
    color: var(--c-texte-doux);
}

.rapport__periodes {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.rapport__periode-lien {
    padding: 0.35rem 0.8rem;
    border: 1px solid var(--c-mer);
    border-radius: 999px;
    color: var(--c-mer);
    font-size: 0.86rem;
    font-weight: 600;
    text-decoration: none;
}

.rapport__periode-lien.is-active {
    background: var(--c-action);
    color: #fff;
}

.rapport__vide {
    padding: 1.5rem;
    border-radius: 12px;
    background: #fff;
    color: var(--c-texte-doux);
}

.rapport__encart {
    margin-bottom: 1.25rem;
    padding: 1.25rem 1.25rem 1rem;
    border-radius: 12px;
    background: #fff;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06);
}

.rapport__encart-nom {
    margin: 0;
    font-size: 1.15rem;
}

.rapport__emplacements {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin: 0.5rem 0 0;
}

.rapport__emplacement {
    padding: 0.1rem 0.55rem;
    border-radius: 999px;
    background: var(--c-sable-clair, #f5efe6);
    font-size: 0.78rem;
    font-weight: 600;
}

.rapport__periode {
    margin: 0.5rem 0 0;
    font-size: 0.9rem;
    color: var(--c-texte-doux);
}

.rapport__kpis {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.75rem;
    margin: 1rem 0 0;
}

.rapport__kpi {
    padding: 0.75rem 0.9rem;
    border-radius: 10px;
    background: var(--c-sable-clair, #f5efe6);
}

.rapport__kpi dt {
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--c-texte-doux);
}

.rapport__kpi-valeur {
    margin: 0.15rem 0 0;
    font-size: 1.5rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.rapport__figure {
    margin: 1rem 0 0;
}

.rapport__graphe {
    display: block;
    width: 100%;
    height: 140px;
}

.rapport__axe {
    stroke: rgba(15, 23, 42, 0.15);
    stroke-width: 1;
}

.rapport__courbe {
    fill: none;
    stroke: var(--c-mer);
    stroke-width: 2.5;
    stroke-linejoin: round;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
}

.rapport__legende {
    display: flex;
    justify-content: space-between;
    margin-top: 0.35rem;
    font-size: 0.78rem;
    color: var(--c-texte-doux);
}

.rapport__pied {
    margin-top: 2rem;
    font-size: 0.82rem;
    color: var(--c-texte-doux);
}

.rapport__pied a {
    color: var(--c-mer);
}

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

/*
actualite.css

QUOI : Carte « actualité commerciale » (visuel plein cadre, pastilles Sponsorisé / fin de diffusion, pro,
       titre, texte limité à 3 lignes, lien), bloc « Actualités » (titre + grille) et grille de la page
       « Actualité commerciale ».

COMMENT : Tokens uniquement (`--c-*`, `--radius-*`, `--shadow-*`, `--font-display`) : le thème sombre suit
          sans règle dédiée. Sans photo, la carte réutilise `.event-cover-abstract` (déjà positionné en
          absolu plein cadre) : le média n'a qu'à fixer son ratio. Les pastilles posées sur l'image ont un
          fond OPAQUE (corail plein / marine à 80 %) — jamais de texte sur verre transparent, contraste ≥ 4.5:1.
          Survol : la carte se soulève de 4 px (translate + ombre seulement), neutralisé si l'utilisateur
          demande moins d'animations.

OÙ : Importé par app.imports.css (bundle app.css). Templates `actualite/*`, slot `actualite` du flux
     d'accueil (`home/_partials/_event_feed_fragment.html.twig`).

POURQUOI : Tendances 2026 retenues (cartes image plein cadre, pastilles, coins généreux, micro-interactions
           sobres) sans quitter l'identité Opalenews (Plus Jakarta Sans, marine / mer / corail).
*/

.actualite-card {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 100%;
    background: var(--c-surface);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
    transition: transform 0.25s var(--ease-out, ease), box-shadow 0.25s var(--ease-out, ease);
}

.actualite-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-md);
}

.actualite-card--sponsorisee {
    border-color: color-mix(in srgb, var(--c-corail) 55%, var(--c-bordure));
    box-shadow: var(--shadow-sm), 0 0 0 1px color-mix(in srgb, var(--c-corail) 35%, transparent);
}

.actualite-card__media {
    position: relative;
    /* Format UNIQUE des actualités (celui du recadrage à l'envoi, comme les couvertures d'événement) : la
       photo s'affiche entière dans toutes les dispositions — carte, une, mini-site, flux. */
    aspect-ratio: 4 / 3;
    overflow: hidden;
    background: var(--c-surface-2);
}

/* Teinte de la couverture générative (sans photo), stable par entreprise : mer, corail, vert dune, sable.
   Partagée avec le bandeau de la page Pro (`.pp-hero__cover`). */
[data-teinte="0"] { --cat-color: #1e6091; }
[data-teinte="1"] { --cat-color: #c6603c; }
[data-teinte="2"] { --cat-color: #3f7d5a; }
[data-teinte="3"] { --cat-color: #b08a3e; }

.actualite-card__media img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.4s var(--ease-out, ease);
}

.actualite-card:hover .actualite-card__media img {
    transform: scale(1.04);
}

.actualite-card__badge,
.actualite-card__fin {
    position: absolute;
    z-index: 1;
    padding: 0.3rem 0.75rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 700;
    line-height: 1.2;
}

.actualite-card__badge {
    top: 0.75rem;
    left: 0.75rem;
    background: var(--c-corail-action);
    color: #fff;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
}

.actualite-card__fin {
    bottom: 0.75rem;
    left: 0.75rem;
    background: rgba(8, 24, 38, 0.8);
    color: #fff;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}

.actualite-card__body {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: 0.4rem;
    padding: 1.1rem 1.25rem 1.25rem;
}

.actualite-card__pro {
    margin: 0;
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--c-mer);
}

.actualite-card__pro a {
    color: inherit;
    text-decoration: none;
}

.actualite-card__pro a:hover,
.actualite-card__pro a:focus-visible {
    text-decoration: underline;
}

.actualite-card__ville {
    color: var(--c-texte-doux);
    font-weight: 600;
}

.actualite-card__titre {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.3rem;
    font-weight: 800;
    line-height: 1.2;
    letter-spacing: -0.01em;
    color: var(--c-marine);
}

.actualite-card__texte {
    display: -webkit-box;
    margin: 0;
    overflow: hidden;
    color: var(--c-texte-doux);
    line-height: 1.55;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
}

.actualite-card__lien {
    align-self: flex-start;
    margin-top: auto;
    padding-top: 0.5rem;
    font-weight: 700;
    color: var(--c-corail-texte);
    text-decoration: none;
}

.actualite-card__lien span {
    display: inline-block;
    transition: transform 0.2s var(--ease-out, ease);
}

.actualite-card__lien:hover span {
    transform: translateX(3px);
}

/* Vedette (« à la une ») : image 4:3 à gauche, texte à droite dès qu'il y a la place ; empilée sur mobile.
   L'image garde EXACTEMENT le format des autres cartes — plus d'image étirée en fond, recadrée au hasard
   de la hauteur du bloc. Utilisée par la une de la page Actualité commerciale et le mini-site de page Pro. */
@media (min-width: 720px) {
    .actualite-card--vedette {
        display: grid;
        grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
        align-items: stretch;
    }

    .actualite-card--vedette .actualite-card__media {
        align-self: start;
    }

    .actualite-card--vedette .actualite-card__body {
        justify-content: center;
        padding: clamp(1.25rem, 3vw, 2.5rem);
    }
}

.actualite-card.actualite-card--vedette .actualite-card__titre {
    font-size: clamp(1.6rem, 3.2vw, 2.5rem);
    line-height: 1.1;
}

.actualite-card--vedette .actualite-card__texte {
    -webkit-line-clamp: 6;
    line-clamp: 6;
    font-size: 1.05rem;
}

/* Coupon de validité (variante `prospectus`) : bord pointillé « à découper », ciseaux. */
.actualite-card__coupon {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: auto -1.25rem -1.25rem;
    padding: 0.75rem 1.25rem;
    border-top: 2px dashed color-mix(in srgb, var(--c-corail) 55%, var(--c-bordure));
    background: color-mix(in srgb, var(--c-corail) 7%, var(--c-surface));
    font-size: 0.85rem;
    color: var(--c-texte-doux);
}

.actualite-card__coupon svg {
    flex: none;
    width: 1.05rem;
    height: 1.05rem;
    color: var(--c-corail-texte);
}

.actualite-card__coupon strong {
    color: var(--c-texte);
}

.actualite-card__lien + .actualite-card__coupon,
.actualite-card__texte + .actualite-card__coupon {
    margin-top: auto;
}

.actualite-card--prospectus .actualite-card__body {
    padding-bottom: 1.25rem;
}

@media (min-width: 720px) {
    .actualite-card--vedette .actualite-card__coupon {
        margin: 1rem 0 0;
        border: 2px dashed color-mix(in srgb, var(--c-corail) 55%, var(--c-bordure));
        border-radius: var(--radius-md, 10px);
    }
}

/* ── Bloc « Actualités » (page Pro, page ville) ── */

.actualites-bloc {
    margin: 2.5rem 0;
}

.actualites-bloc__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 1.25rem;
}

.actualites-bloc__titre {
    margin: 0;
    font-family: var(--font-display);
    font-size: clamp(1.4rem, 3vw, 1.85rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    color: var(--c-marine);
}

.actualites-bloc__tout {
    padding: 0.5rem 1rem;
    border: 1px solid var(--c-bordure);
    border-radius: 999px;
    font-weight: 700;
    font-size: 0.9rem;
    color: var(--c-marine);
    text-decoration: none;
}

.actualites-bloc__tout:hover,
.actualites-bloc__tout:focus-visible {
    border-color: var(--c-mer);
}

.actualites-grille {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 270px), 1fr));
    gap: 1.25rem;
}

@media (prefers-reduced-motion: reduce) {
    .actualite-card,
    .actualite-card__media img,
    .actualite-card__lien span {
        transition: none;
    }

    .actualite-card:hover,
    .actualite-card:hover .actualite-card__media img {
        transform: none;
    }
}

/* ── Filtre « Tous les événements (N) · Actualité commerciale (M) » (accueil, page actus, villes) ── */
.filtre-actus {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0 0 1.25rem;
}

.filtre-actus__lien {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.5rem 0.95rem;
    background: var(--c-surface);
    border: 1px solid var(--c-bordure);
    border-radius: 999px;
    color: var(--c-texte);
    font-weight: 600;
    font-size: 0.92rem;
    text-decoration: none;
    transition: border-color 0.2s var(--ease-out), background-color 0.2s var(--ease-out);
}

.filtre-actus__lien:hover,
.filtre-actus__lien:focus-visible {
    border-color: var(--c-mer);
}

.filtre-actus__lien.is-active {
    background: color-mix(in srgb, var(--c-mer) 22%, var(--c-surface));
    border-color: var(--c-mer);
    color: var(--c-texte);
}

.filtre-actus__icone {
    width: 1rem;
    height: 1rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
}

.filtre-actus__nb {
    min-width: 1.6rem;
    padding: 0.05rem 0.45rem;
    background: color-mix(in srgb, currentColor 14%, transparent);
    border-radius: 999px;
    font-size: 0.8rem;
    text-align: center;
}

/*
carte-demande.css

QUOI : Encart « Afficher la carte » posé dans les mini-cartes tant que le visiteur ne l'a pas demandée.
COMMENT : Occupe tout le cadre de la carte (centré), sur la teinte de surface ; bouton pilule.
OÙ : public/js/carte-a-la-demande.js (fiche événement, fiche lieu, page Pro).
POURQUOI : Audit RGPD du 02/11/2026 : pas d'appel au serveur de tuiles CARTO avant l'accord du visiteur.
*/

.carte-demande-attente {
    display: grid;
    place-items: center;
    background:
        radial-gradient(circle at 30% 30%, color-mix(in srgb, var(--c-mer, #1e6091) 10%, transparent), transparent 60%),
        var(--c-surface-2, #f4efe6);
}

.carte-demande {
    display: grid;
    justify-items: center;
    gap: 0.6rem;
    max-width: 26rem;
    padding: 1.25rem;
    text-align: center;
}

.carte-demande__bouton {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 44px;
    padding: 0.6rem 1.2rem;
    font: inherit;
    font-weight: 700;
    color: #fff;
    background: var(--c-marine, #0a3d62);
    border: 0;
    border-radius: 999px;
    cursor: pointer;
}

.carte-demande__bouton:hover { background: var(--c-mer, #1e6091); }

.carte-demande__bouton:focus-visible {
    outline: 3px solid color-mix(in srgb, var(--c-mer, #1e6091) 50%, transparent);
    outline-offset: 2px;
}

.carte-demande__aide {
    margin: 0;
    font-size: 0.82rem;
    line-height: 1.45;
    color: var(--c-texte-doux, #5a6b7a);
}

[data-theme="dark"] .carte-demande__bouton { color: #08141e; background: #7cb8e2; }

/*
prospectus.css

QUOI : Page « Actualité commerciale » en PROSPECTUS / magazine : en-tête photo commun (édition de la semaine,
       choix de la ville dans la barre), rubriques (« À la une », « Cette semaine ») soulignées d'un double
       filet, tampon « Nouveau cette semaine », grille de cartes-coupons, encart commerçants.

COMMENT : Tokens du site uniquement (`--c-*`, `--font-display`, `--radius-*`) : clair et sombre suivent sans
          règle dédiée. Les cartes et leur format 4:3 viennent de `components/actualite.css` ; ici, seulement la
          mise en page. Colonnes qui se replient seules (`auto-fill`), aucune largeur figée : 375 px OK.

OÙ : Importé par app.imports.css (bundle app.css). Template `actualite/index.html.twig`.

POURQUOI : « Que ça ressemble un peu à un prospectus magazine » — typographie de presse, filets, coupons,
           sans quitter l'identité Opalenews (Plus Jakarta Sans, marine / mer / corail).
*/

.prospectus {
    padding-block: 1.5rem 3rem;
}

/* ── En-tête : le `.page-hero` commun (editorial-2026.css) ; ici, l'esperluette et la ville du titre. ── */
.prospectus__esperluette {
    font-weight: 400;
    font-style: italic;
    color: #f3d9a4;
}

.prospectus__tete .page-hero__title small {
    display: block;
    margin-top: 0.3rem;
    font-size: 0.45em;
    letter-spacing: -0.01em;
}

/* Barre de choix de la ville : celle de /lieux, réduite à un champ. */
html body .page-hero .prospectus__recherche { max-width: 26rem; }
html body .page-hero .prospectus__recherche .lieu-search__row { flex-wrap: nowrap; }
html body .page-hero .prospectus__recherche .lieu-search__field { flex: 1 1 auto; min-width: 0; }
html body .page-hero .prospectus__recherche .lieu-search__actions { flex: 0 0 auto; border-top: 0; padding-top: 0.25rem; }

.prospectus > .filtre-actus { margin-top: 1.75rem; }

/* ── Rubriques ── */
.prospectus__rubrique {
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    margin: 0 0 1.25rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--c-bordure);
    font-family: var(--font-display);
    font-size: 0.95rem;
    font-weight: 800;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--c-marine);
}

.prospectus__rubrique span {
    padding-bottom: 0.5rem;
    margin-bottom: -0.55rem;
    border-bottom: 3px solid var(--c-corail);
}

.prospectus__rubrique small {
    margin-left: auto;
    font-family: var(--font-base);
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: none;
    color: var(--c-texte-doux);
}

/* ── À la une ── */
.prospectus__une {
    position: relative;
    margin-top: 2.25rem;
}

.prospectus__une .actualite-card {
    border-width: 2px;
}

/* Tampon rond « Nouveau cette semaine », légèrement tourné, posé sur l'angle de la une. */
.prospectus__tampon {
    position: absolute;
    z-index: 2;
    top: 2.25rem;
    right: -0.5rem;
    display: grid;
    place-items: center;
    width: 6rem;
    height: 6rem;
    border-radius: 50%;
    background: var(--c-corail-action);
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.25);
    color: #fff;
    font-family: var(--font-display);
    font-size: 0.72rem;
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: 0.06em;
    text-align: center;
    text-transform: uppercase;
    transform: rotate(12deg);
}

@media (max-width: 719px) {
    .prospectus__tampon {
        top: 2.75rem;
        right: 0.5rem;
        width: 4.75rem;
        height: 4.75rem;
        font-size: 0.6rem;
    }
}

/* ── Cette semaine ── */
.prospectus__pages {
    margin-top: 2.5rem;
}

.prospectus__grille {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 290px), 1fr));
    gap: 1.75rem 1.5rem;
}

/* ── Page vide ── */
.prospectus__vide {
    margin: 2.5rem 0;
    padding: 2.5rem 1.5rem;
    border: 2px dashed var(--c-bordure);
    border-radius: var(--radius-lg);
    text-align: center;
    color: var(--c-texte-doux);
}

.prospectus__vide-titre {
    margin: 0 0 0.5rem;
    font-family: var(--font-display);
    font-size: 1.4rem;
    font-weight: 800;
    color: var(--c-marine);
}

/* ── Encart commerçants ── */
.prospectus__encart {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem 2rem;
    margin-top: 3rem;
    padding: 1.5rem clamp(1.25rem, 3vw, 2rem);
    border: 2px dashed color-mix(in srgb, var(--c-corail) 55%, var(--c-bordure));
    border-radius: var(--radius-lg);
    background: color-mix(in srgb, var(--c-corail) 6%, var(--c-surface));
}

.prospectus__encart > div {
    flex: 1 1 26rem;
}

.prospectus__encart p {
    margin: 0;
    color: var(--c-texte-doux);
}

.prospectus__encart-surtitre {
    font-size: 0.8rem;
    font-weight: 800;
    letter-spacing: 0.14em;
    text-transform: uppercase;
}

.prospectus__encart .prospectus__encart-titre {
    margin: 0.25rem 0 0.4rem;
    font-family: var(--font-display);
    font-size: 1.35rem;
    font-weight: 800;
    color: var(--c-marine);
}

/* Coupons sans photo : la couverture n'a pas de format à respecter, elle se réduit à un bandeau (16:9) et
   l'initiale du pro ne remplit plus la carte. Les photos gardent leur 4:3. */
@media (min-width: 600px) {
    .prospectus__grille .actualite-card__media:has(> .event-cover-abstract) { aspect-ratio: 16 / 9; }
}
.prospectus__grille .actualite-card__monogramme { font-size: clamp(3rem, 5vw, 4.25rem); }

/*
annuaire-page-pro.css

QUOI : Distinction des entreprises qui ont une page Pro EN LIGNE dans les listes de l'annuaire public (page
       Annuaire, bloc annuaire des pages ville) : liseré à la couleur d'accent et pastille « Page Pro ».

COMMENT : Tokens uniquement (`--c-*`) : clair et sombre suivent sans règle dédiée. La pastille porte le libellé
          en toutes lettres : la couleur n'est jamais la seule information (WCAG 1.4.1). Classes posées par
          `opale_a_page_pro()` (PageProExtension).

OÙ : Importé par app.imports.css. Templates `annuaire/index.html.twig`, `_partials/_bloc_annuaire.html.twig`.

POURQUOI : Les pages Pro passent en tête de l'annuaire ; on doit aussi les reconnaître d'un coup d'œil.
*/

.bloc-annuaire__item--page-pro a {
    position: relative;
    border-color: color-mix(in srgb, var(--c-corail) 55%, var(--c-bordure));
    box-shadow: inset 4px 0 0 var(--c-corail);
    background: color-mix(in srgb, var(--c-corail) 6%, var(--c-surface));
}

.bloc-annuaire__page-pro {
    /* Mêmes mesures que `.bloc-annuaire__pastille` (pages/entreprise.css) et même alignement de ligne :
       les deux pastilles côte à côte tombent pile sur la même ligne de base. */
    display: inline-block;
    margin: 0 0 0.35rem 0.35rem;
    padding: 0.15rem 0.45rem;
    border-radius: 999px;
    background: var(--c-corail-action);
    color: #fff;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.bloc-annuaire__page-pro::before {
    content: "★ ";
}

/*
tuile-proposer.css

QUOI : Tuile « Votre événement ici ? » (`_partials/_tuile_proposer.html.twig`) et sa variante « Votre bon plan
       ici ? » : carte d'invitation pleine, aux couleurs de la marque, qui comble une case libre d'une grille ou
       le bas de la colonne de tête bento.

COMMENT : Carte pleine (dégradé marine → mer, halo corail, grande icône en filigrane) plutôt qu'un cadre
          pointillé : sur une grande surface, un cadre vide se lisait comme un bug (retour d'Ellie, 27/10/2026).
          Même rayon et même ombre qu'une carte d'événement. La tuile est un conteneur de taille
          (`container-type: size`) : elle prend la place que la grille lui donne sans jamais la gonfler, et
          sa mise en page suit cette place —
          - normale : filigrane dans le coin haut droit, texte et bouton calés en bas ;
          - haute : grande icône dans la moitié haute ;
          - large : texte à gauche, bouton à droite, centrés en hauteur ;
          - petite : surtitre et texte d'appoint masqués, puis seulement titre + bouton ;
          - minuscule (colonne de tête presque pleine) : la tuile s'efface.
          Rien n'est jamais rogné. Couleurs de la carte fixes (texte blanc sur fond sombre) : lisible dans les
          deux thèmes.

OÙ : app.imports.css. Posée par `grille-sans-trou.js` (cases libres) et par les gabarits de grille (colonne).

POURQUOI : Remplace les entreprises de l'annuaire qui comblaient les grilles d'événements (retirées le
           27/10/2026, retour de Nico).
*/

.tuile-proposer {
    --tuile-fond-1: #0a3d62;
    --tuile-fond-2: #1e6091;
    --tuile-halo: rgba(224, 120, 86, 0.42);
    --tuile-bouton: var(--c-corail-action);
    --tuile-bouton-texte: #ffffff;

    position: relative;
    display: block;
    container-type: size;
    height: 100%;
    min-height: 220px;
    overflow: hidden;
    color: #ffffff;
    text-decoration: none;
    background:
        radial-gradient(rgba(255, 255, 255, 0.09) 1px, transparent 1.6px) 0 0 / 18px 18px,
        radial-gradient(120% 90% at 100% 0%, var(--tuile-halo) 0%, transparent 55%),
        linear-gradient(160deg, var(--tuile-fond-2) 0%, var(--tuile-fond-1) 70%);
    border-radius: var(--radius-lg);
    box-shadow:
        0 1px 2px rgba(10, 61, 98, 0.08),
        0 12px 28px -16px rgba(10, 61, 98, 0.55);
    isolation: isolate;
    transition: transform var(--duration-base, 0.2s) var(--ease-out, ease), box-shadow var(--duration-base, 0.2s) ease;
}

/* Variante bons plans : chaude (corail foncé → brique, pour tenir 4.5:1 avec le texte blanc), halo sable. */
.tuile-proposer--bonplan {
    --tuile-fond-1: #8f3a20;
    --tuile-fond-2: #b9532f;
    --tuile-halo: rgba(245, 233, 212, 0.32);
    --tuile-bouton: #ffffff;
    --tuile-bouton-texte: #a8482a;
}

/* Variante annuaire : prend la hauteur des cartes d'adresse (≈ 140 px) sans jamais l'agrandir — la mise en
   page compacte (titre + bouton) s'applique d'elle-même par les requêtes de conteneur ci-dessous. */
.tuile-proposer--commerce {
    min-height: 0;
}

.tuile-proposer:hover {
    transform: translateY(-3px);
    box-shadow:
        0 1px 2px rgba(10, 61, 98, 0.08),
        0 18px 36px -16px rgba(10, 61, 98, 0.6);
}

.tuile-proposer:focus-visible {
    outline: 3px solid var(--c-focus);
    outline-offset: 3px;
}

/* Grande icône en filigrane, débordant du coin haut droit. */
.tuile-proposer__filigrane {
    position: absolute;
    z-index: -1;
    top: -14%;
    right: -12%;
    width: 72%;
    max-width: 260px;
    aspect-ratio: 1;
    color: #ffffff;
    opacity: 0.13;
    transform: rotate(-12deg);
    transition: transform 0.4s var(--ease-out, ease);
}

.tuile-proposer:hover .tuile-proposer__filigrane {
    transform: rotate(-6deg) scale(1.04);
}

.tuile-proposer__corps {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    align-items: flex-start;
    gap: 0.45rem;
    padding: clamp(1rem, 7cqi, 1.6rem);
}

.tuile-proposer__surtitre {
    padding: 0.2rem 0.6rem;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #ffffff;
    background: rgba(255, 255, 255, 0.16);
    border: 1px solid rgba(255, 255, 255, 0.28);
    border-radius: 999px;
}

.tuile-proposer__titre {
    font-family: var(--font-display);
    font-size: clamp(1.3rem, 9cqi, 1.75rem);
    font-weight: 800;
    line-height: 1.12;
    letter-spacing: -0.01em;
    text-wrap: balance;
}

.tuile-proposer__sous {
    max-width: 34ch;
    font-size: 0.95rem;
    line-height: 1.45;
    color: rgba(255, 255, 255, 0.86);
    text-wrap: pretty;
}

.tuile-proposer__action {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.4rem;
    padding: 0.6rem 1.1rem;
    min-height: 44px;
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--tuile-bouton-texte);
    background: var(--tuile-bouton);
    border-radius: 999px;
    box-shadow: 0 6px 16px -8px rgba(0, 0, 0, 0.45);
    white-space: nowrap;
}

.tuile-proposer__action span {
    transition: transform var(--duration-base, 0.2s) ease;
}

.tuile-proposer:hover .tuile-proposer__action span {
    transform: translateX(3px);
}

/* ── Mise en page selon la place ── */

/* Haute : l'icône grandit et descend dans la moitié haute, pour habiter la place au-dessus du texte. */
@container (min-height: 420px) {
    .tuile-proposer__filigrane {
        top: 6%;
        right: 50%;
        width: 78%;
        max-width: 320px;
        opacity: 0.14;
        transform: translateX(50%) rotate(-8deg);
    }

    .tuile-proposer:hover .tuile-proposer__filigrane {
        transform: translateX(50%) rotate(-3deg) scale(1.04);
    }

    .tuile-proposer__titre {
        font-size: clamp(1.5rem, 9cqi, 2rem);
    }
}

/* Large (tuile étendue sur plusieurs cases) : texte à gauche, bouton à droite, centrés en hauteur. */
@container (min-width: 560px) {
    .tuile-proposer__corps {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-content: center;
        column-gap: 2rem;
        padding: clamp(1.4rem, 5cqi, 2.6rem);
    }

    .tuile-proposer__surtitre,
    .tuile-proposer__titre,
    .tuile-proposer__sous {
        grid-column: 1;
        justify-self: start;
    }

    .tuile-proposer__titre {
        font-size: clamp(1.6rem, 4.5cqi, 2.4rem);
    }

    .tuile-proposer__sous {
        max-width: 46ch;
        font-size: 1.02rem;
    }

    .tuile-proposer__filigrane {
        top: 50%;
        right: -6%;
        width: 52%;
        max-width: 340px;
        transform: translateY(-50%) rotate(-10deg);
    }

    .tuile-proposer:hover .tuile-proposer__filigrane {
        transform: translateY(-50%) rotate(-5deg) scale(1.04);
    }

    .tuile-proposer__action {
        grid-column: 2;
        grid-row: 1 / span 3;
        align-self: center;
        margin: 0;
        padding: 0.8rem 1.5rem;
        font-size: 1.02rem;
    }
}

/* Large ET basse (annuaire, rangée de cartes d'adresse) : surtitre et texte masqués plus bas — titre et bouton
   sur la même rangée, centrés (sinon les rangées vides du surtitre et du texte remontaient le titre). */
@container (min-width: 560px) and (max-height: 190px) {
    .tuile-proposer__corps {
        row-gap: 0;
    }

    .tuile-proposer__titre,
    .tuile-proposer__action {
        grid-row: 1;
        align-self: center;
    }
}

/* Petite hauteur : on garde l'essentiel. */
@container (max-height: 250px) {
    .tuile-proposer__surtitre {
        display: none;
    }
}

@container (max-height: 190px) {
    .tuile-proposer__sous {
        display: none;
    }

    .tuile-proposer__titre {
        font-size: 1.2rem;
    }
}

/* Étroite (fin de rangée de l'accueil sur téléphone, 250 px) : le bouton « Proposer un événement → » dépassait
   du bord droit. Il rétrécit et peut passer sur deux lignes, la flèche à la suite du texte (en `inline-flex`,
   le texte prenait toute la largeur et rejetait la flèche contre le bord). */
@container (max-width: 280px) {
    .tuile-proposer__action {
        display: inline-block;
        max-width: 100%;
        padding: 0.55rem 0.9rem;
        font-size: 0.88rem;
        line-height: 1.25;
        text-wrap: balance;
    }
}

/* ── Colonne de tête bento : remplit la place restante sous le 2e événement sans jamais rallonger la
   colonne (base 0, plancher 0). Trop peu de place → la tuile s'efface. ── */
.lead-aside > .lead-aside__fill:has(> .tuile-proposer--colonne) {
    flex: 1 1 0;
    min-height: 0;
    container-type: size;
}

.tuile-proposer--colonne {
    min-height: 0;
}

@container (max-height: 120px) {
    .tuile-proposer--colonne {
        display: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .tuile-proposer,
    .tuile-proposer__filigrane,
    .tuile-proposer__action span {
        transition: none;
    }

    .tuile-proposer:hover,
    .tuile-proposer:hover .tuile-proposer__filigrane,
    .tuile-proposer:hover .tuile-proposer__action span {
        transform: none;
    }
}

/*
mini-site.css

QUOI : Socle du mini-site d'une page Pro : variables dérivées, boutons, barre de navigation propre, grand
       titre expressif, visuel (couverture ou composition graphique). Les sections (actualités, infos,
       agenda, contact, pied, barre mobile) sont dans mini-site-sections.css.

COMMENT : AUCUNE couleur Opalenews en dur : tout dérive des variables posées par `ThemePagePro` sur
          `.pp-site` (`--pp-accent`, `--pp-sur-accent`, `--pp-accent-texte`, `--pp-fond`, `--pp-texte`,
          `--pp-police`, `--pp-rayon`, `--pp-schema`). Surfaces, bordures et texte secondaire sont obtenus par
          `color-mix()` du texte dans le fond : ils restent cohérents quel que soit le fond choisi, clair ou
          sombre, et le thème jour/nuit d'Opalenews n'a pas prise sur la page (c'est la DA du pro).
          Apparition au défilement en CSS pur (`animation-timeline: view()`), seulement si le navigateur
          la gère ET si l'utilisateur n'a pas demandé moins d'animations. DA 2026 : largeur portée à
          `--pp-largeur` (92rem, grands écrans) ; un bloc final NEUTRALISE les styles « Affiche » d'Opalenews
          que les classes partagées (`entreprise__*`, cartes d'actualité) importeraient dans la page du pro.

OÙ : Importé par app.imports.css après `actualite.css`. Templates `entreprise/show.html.twig`,
     `entreprise/_partials/_mini_site.html.twig`, aperçu de `pagepro/personnaliser.html.twig`.

POURQUOI : Tendances 2026 (minimalisme affirmé, typographie-héroïne, bento à rôles, contraste fort) au
           service d'une page qui ressemble au commerce, pas à l'annuaire.
*/

/* `.entreprise.pp-page` : doit battre `.entreprise` (max-width 60rem, entreprise.css) — le mini-site
   occupe toute la largeur, d'un bord à l'autre. */
.entreprise.pp-page {
    width: 100%;
    max-width: none;
    margin: 0;
    padding: 0 0 var(--space-xl);
}

.pp-site {
    /* 92rem (1472 px) : à 1920 px, la page s'étalait sur 1520 px, plus large que tout le reste du site. */
    --pp-largeur: min(92rem, 100%);
    --pp-surface: color-mix(in srgb, var(--pp-texte) 6%, var(--pp-fond));
    --pp-surface-2: color-mix(in srgb, var(--pp-texte) 11%, var(--pp-fond));
    --pp-bordure: color-mix(in srgb, var(--pp-texte) 15%, var(--pp-fond));
    --pp-doux: color-mix(in srgb, var(--pp-texte) 70%, var(--pp-fond));
    --pp-teinte: color-mix(in srgb, var(--pp-accent) 16%, var(--pp-fond));
    --pp-rayon-petit: calc(var(--pp-rayon) / 2);
    color-scheme: var(--pp-schema);
    background: var(--pp-fond);
    color: var(--pp-texte);
    font-family: var(--pp-police);
    /* `clip` et non `hidden` : rogne la composition qui déborde SANS créer de zone de défilement, sinon les
       onglets collants du téléphone (`position: sticky`) ne colleraient plus. */
    overflow: clip;
    /* Conteneur des requêtes « téléphone / tablette » du mini-site (cf. mini-site-mobile.css). */
    container: pp / inline-size;
}

/* Raccourcis ronds et onglets : téléphone uniquement (mini-site-mobile.css). Image « téléphone » de l'aperçu
   masquée hors téléphone ; sur la page publique, c'est `<picture>` qui choisit. */
.pp-onglets,
.pp-raccourcis,
.pp-hero__couverture--mobile {
    display: none;
}

/* Ancres (#infos, #contact…) posées sous l'en-tête collant du site, pas dessous (cf. `--pp-entete`, page-pro.js). */
.pp-site [id] {
    scroll-margin-top: calc(var(--pp-entete, 0px) + 1rem);
}

.pp-hero__visuel picture {
    display: contents;
}

/* `:where()` : spécificité nulle, pour que les boutons (`.pp-bouton`, texte posé sur l'accent) gardent
   leur propre couleur — `.pp-site a` l'écrasait et rendait le texte illisible sur un accent foncé. */
:where(.pp-site) a {
    color: inherit;
}

.pp-surtitre {
    margin: 0 0 0.6rem;
    font-family: var(--font-base, system-ui, sans-serif);
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--pp-accent-texte);
}

.pp-accent {
    color: var(--pp-accent-texte);
}

.pp-hero__nom .pp-accent {
    color: var(--pp-accent-titre, var(--pp-accent-texte));
}

/* ── Boutons ── */

.pp-bouton,
.pp-site .pp-bouton.entreprise__site {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0;
    padding: 0.9rem 1.5rem;
    background: var(--pp-accent);
    border: 2px solid var(--pp-accent);
    border-radius: max(var(--pp-rayon-petit), 6px);
    color: var(--pp-sur-accent);
    font-family: var(--font-base, system-ui, sans-serif);
    font-weight: 700;
    text-decoration: none;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

/* Survol : souris seulement (au doigt, l'effet restait « collé » après le toucher). */
@media (hover: hover) {
    .pp-bouton:hover {
        transform: translateY(-2px);
        box-shadow: 0 10px 24px -10px var(--pp-accent);
    }
}

.pp-bouton:focus-visible {
    transform: translateY(-2px);
    box-shadow: 0 10px 24px -10px var(--pp-accent);
}

/* Toucher : pas de zoom au double-tap ni de délai sur les commandes du mini-site. */
.pp-site :is(a, button, summary, label),
.pp-barre-mobile a {
    touch-action: manipulation;
}

.pp-bouton--contour,
.pp-site .pp-bouton--contour.entreprise__site {
    background: transparent;
    border-color: var(--pp-bordure);
    color: var(--pp-texte);
}

.pp-bouton--petit {
    padding: 0.55rem 1.1rem;
    font-size: 0.9rem;
}

.pp-lien-fleche {
    display: inline-flex;
    gap: 0.35rem;
    margin-top: 1rem;
    font-family: var(--font-base, system-ui, sans-serif);
    font-weight: 700;
    color: var(--pp-accent-texte) !important;
    text-decoration: none;
}

/* Nom de ville dans un titre : jamais coupé au tiret. */
.pp-insecable {
    white-space: nowrap;
}

/* Numéro de rubrique : réservé à l'Éditorial sur téléphone (mini-site-mobile-gabarits.css). */
.pp-surtitre__num {
    display: none;
}

/* ── Navigation du mini-site ── */

.pp-nav {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    max-width: var(--pp-largeur, 100rem);
    margin: 0 auto;
    padding: 1.25rem clamp(1rem, 4cqi, 2.5rem);
    font-family: var(--font-base, system-ui, sans-serif);
}

.pp-nav__marque {
    display: inline-flex;
    align-items: center;
    gap: 0.65rem;
    margin-right: auto;
    font-family: var(--pp-police);
    font-size: 1.1rem;
    font-weight: 800;
    text-decoration: none;
}

.pp-nav__logo {
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    background: var(--pp-accent);
    border-radius: max(var(--pp-rayon-petit), 4px);
    color: var(--pp-sur-accent);
}

.pp-nav__liens {
    display: flex;
    gap: 1.25rem;
    font-weight: 600;
}

.pp-nav__liens a {
    color: var(--pp-doux);
    text-decoration: none;
}

.pp-nav__liens a:hover {
    color: var(--pp-texte);
}

/* Ordinateur : la barre du pro reste collée sous l'en-tête d'Opalenews (69 px) pendant le défilement — passé
   le haut de page, « Appeler » et les ancres disparaissaient (audit ordinateur du 27/10/2026). Fond plein
   largeur légèrement translucide et flouté, contenu aligné sur la page. Sauf la Vitrine avec photo, dont la
   barre « en verre » est posée sur la photo, et l'aperçu de l'éditeur (pas d'en-tête du site au-dessus). */
@container pp (min-width: 861px) {
    .pp-site:not(.pp-site--apercu, .pp-site--vitrine.pp-site--photo) .pp-nav {
        position: sticky;
        top: 69px;
        z-index: 40;
        max-width: none;
        padding-block: 0.85rem;
        padding-inline: max(clamp(1rem, 4cqi, 2.5rem), calc((100% - 92rem) / 2 + 2.5rem));
        background: color-mix(in srgb, var(--pp-fond) 86%, transparent);
        -webkit-backdrop-filter: blur(14px) saturate(140%);
        backdrop-filter: blur(14px) saturate(140%);
        box-shadow: 0 1px 0 var(--pp-bordure);
    }
}

/* ── Hero ── */

.pp-hero {
    display: grid;
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    align-items: center;
    gap: clamp(2rem, 5cqi, 4.5rem);
    max-width: var(--pp-largeur, 100rem);
    margin: 0 auto;
    padding: clamp(2rem, 6cqi, 5rem) clamp(1rem, 4cqi, 2.5rem) clamp(2.5rem, 7cqi, 6rem);
}

.pp-site .pp-hero__nom {
    margin: 0;
    font-family: var(--pp-police);
    /* Taille selon la largeur de SA colonne (`cqi`, conteneur `.pp-hero__texte`) et non de l'écran : à 1024 px,
       « Boulangerie » ne tenait plus dans la moitié gauche et se coupait (relecture du 22/10/2026). */
    font-size: calc(clamp(2.3rem, 13cqi, 6.2rem) * var(--pp-echelle, 1));
    font-weight: 800;
    line-height: 0.98;
    letter-spacing: -0.035em;
    color: var(--pp-texte);
    text-wrap: balance;
}

.pp-hero__texte {
    container-type: inline-size;
}

.pp-hero__accroche {
    max-width: 44ch;
    margin: 1.4rem 0 0;
    font-size: clamp(1.1rem, 2cqi, 1.35rem);
    line-height: 1.5;
    color: var(--pp-doux);
}

.pp-hero__accroche:empty {
    display: none;
}

.pp-site .pp-pastilles {
    margin: 1.4rem 0 0;
}

.pp-site .entreprise__theme {
    padding: 0.35rem 0.9rem;
    background: var(--pp-teinte);
    border: 0;
    border-radius: 999px;
    color: var(--pp-texte);
    font-family: var(--font-base, system-ui, sans-serif);
    font-weight: 600;
}

.pp-hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-top: 2rem;
}

.pp-hero__visuel {
    position: relative;
    aspect-ratio: 4 / 5;
    max-height: 560px;
}

.pp-hero__couverture {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: var(--pp-rayon);
    box-shadow: 0 40px 80px -40px rgba(0, 0, 0, 0.5);
}

.pp-composition {
    position: absolute;
    inset: 0;
}

.pp-composition__disque {
    position: absolute;
    top: 4%;
    right: 0;
    width: 78%;
    aspect-ratio: 1;
    background: var(--pp-accent);
    border-radius: 50%;
}

.pp-composition__carre {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 62%;
    aspect-ratio: 1;
    background: var(--pp-teinte);
    /* Trame de points (couleur d'accent) : sans elle, le carré uni passait pour un emplacement d'image vide
       (audit du 21/10/2026, mini-site en 320 px). */
    background-image: radial-gradient(color-mix(in srgb, var(--pp-accent) 55%, transparent) 22%, transparent 24%);
    background-size: 18px 18px;
    border: 2px solid var(--pp-bordure);
    border-radius: var(--pp-rayon);
    backdrop-filter: blur(10px);
}

.pp-composition__lettre {
    position: absolute;
    right: 12%;
    bottom: 6%;
    font-family: var(--pp-police);
    font-size: clamp(9rem, 22cqi, 17rem);
    font-weight: 800;
    line-height: 0.8;
    color: var(--pp-texte);
    text-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
}

.pp-site .pp-hero__logo {
    position: absolute;
    bottom: -1.5rem;
    left: -1.5rem;
    width: 96px;
    height: 96px;
    max-height: none;
    margin: 0;
    padding: 10px;
    object-fit: contain;
    background: #fff;
    border-radius: var(--pp-rayon-petit);
    box-shadow: 0 16px 40px -16px rgba(0, 0, 0, 0.45);
}


/* ── Neutralisation de la DA Opalenews dans le mini-site ──
   Le mini-site réutilise des classes de la fiche entreprise (`entreprise__*`, `entreprise-contact*`) et des
   cartes d'actualité, habillées pour l'affiche Opalenews (trait encre, ombre décalée, capitales, jaune). Ici,
   c'est la DA du PRO qui s'applique : on retire ce qui ne dérive pas de ses variables `--pp-*`. */
.pp-site .entreprise__theme {
    font-size: 0.92rem;
    letter-spacing: 0;
    text-transform: none;
}

.pp-site .pp-hero__nom {
    font-stretch: normal;
    font-variation-settings: normal;
}

.pp-site .pp-hero__logo {
    border: 0;
    aspect-ratio: auto;
}

/* Logo du pro dans la carte blanche du visuel : les logos larges (nom en toutes lettres) gardent leur
   proportion au lieu de tenir, minuscules, dans un carré de 96 px. */
.pp-site .pp-hero__logo {
    width: auto;
    min-width: 96px;
    max-width: min(240px, 60%);
    height: 96px;
    padding: 12px 16px;
}

/* Logo dans la barre du mini-site : pastille blanche, hauteur fixe, largeur selon le logo. */
.pp-site .pp-nav__logo--image {
    display: block;
    width: auto;
    max-width: 140px;
    height: 2.5rem;
    padding: 4px 8px;
    object-fit: contain;
    background: #fff;
    border-radius: max(var(--pp-rayon-petit), 6px);
}

.pp-site .pp-bouton,
.pp-site .pp-bouton.entreprise__site {
    min-height: 48px;
    box-shadow: none;
}

.pp-site .entreprise__retour {
    margin-left: 0;
    min-height: 44px;
    align-items: center;
}

.pp-site .pp-infos dt,
.pp-site .pp-infos dd {
    padding: 0;
    border: 0;
    letter-spacing: 0;
    text-transform: none;
}

.pp-site .actualite-card,
.pp-site .actualite-card:hover {
    box-shadow: none;
}

@media (hover: hover) {
    .pp-site .actualite-card:hover {
        transform: translateY(-3px);
    }
}

.pp-site .actualite-card__media {
    border-bottom-color: var(--pp-bordure);
}

.pp-site :is(.actualite-card__badge, .actualite-card__fin) {
    border-color: transparent;
    box-shadow: none;
    transform: none;
}

.pp-site .actualite-card__fin {
    background: color-mix(in srgb, var(--pp-fond) 85%, transparent);
    color: var(--pp-texte);
}

.pp-site .actualite-card__coupon {
    background: var(--pp-teinte);
    border-color: var(--pp-bordure);
}

.pp-site .entreprise-contact {
    border-top: 0;
    padding-top: 0;
}

/* Déclencheur du formulaire : un vrai bouton plein, pas un titre-accordéon qui casse sur deux lignes avec un
   « + » flottant (revue design du 24/10/2026). Ouvert, il passe en contour. */
.pp-site .entreprise-contact .entreprise-contact__declencheur {
    justify-content: center;
    gap: 0.5rem;
    width: 100%;
    max-width: 26rem;
    padding: 0.75rem 1.25rem;
    background: var(--pp-accent);
    border: 2px solid var(--pp-accent);
    border-radius: max(var(--pp-rayon-petit), 6px);
    color: var(--pp-sur-accent);
    font-family: var(--font-base, system-ui, sans-serif);
    font-size: 1.05rem;
    font-weight: 700;
    font-stretch: normal;
    font-variation-settings: normal;
    cursor: pointer;
}

.pp-site .entreprise-contact .entreprise-contact__declencheur:hover {
    color: var(--pp-sur-accent);
}

.pp-site .entreprise-contact .entreprise-contact__declencheur::before {
    content: none;
    width: auto;
    height: auto;
    background: none;
    border: 0;
    color: inherit;
}

.pp-site .entreprise-contact__pli[open] .entreprise-contact__declencheur {
    margin-bottom: 1rem;
    background: transparent;
    border-color: var(--pp-bordure);
    color: var(--pp-texte);
}

.pp-site .entreprise-contact :is(input, textarea, select) {
    border-width: 1.5px;
    border-radius: var(--pp-rayon-petit);
}

/* Téléphone : avec un vrai logo (qui porte presque toujours le nom), le nom en texte à côté se coupait ; il cède
   la place au logo, un peu plus grand. Le nom reste le titre de la page juste en dessous. */
@container pp (max-width: 600px) {
    .pp-site .pp-nav__marque:has(.pp-nav__logo--image) > span { display: none; }
    .pp-site .pp-nav__logo--image { max-width: 180px; height: 2.75rem; }
}

/*
mini-site-sections.css

QUOI : Sections du mini-site d'une page Pro (actualités en bento, à propos / infos, agenda de la ville,
       contact, pied de page), barre du gestionnaire, barre d'actions fixe mobile, responsive et
       apparition au défilement.

COMMENT : Mêmes variables `--pp-*` que mini-site.css (posées par `ThemePagePro` sur `.pp-site`) ; aucune
          couleur Opalenews en dur dans le mini-site. Exception assumée : la barre du gestionnaire (`.pp-gestion`)
          appartient à Opalenews et porte la DA « Affiche ». L'apparition au défilement n'est active que si le
          navigateur gère `animation-timeline: view()` ET que l'utilisateur accepte les animations.

OÙ : Importé par app.imports.css juste après mini-site.css.

POURQUOI : Scindé de mini-site.css (limite de 500 lignes par fichier CSS, docs/ARCHITECTURE.md §5).
*/

/* ── Sections ── */

.pp-section {
    max-width: var(--pp-largeur, 100rem);
    margin: 0 auto;
    padding: clamp(2rem, 5cqi, 4rem) clamp(1rem, 4cqi, 2.5rem);
}

.pp-section__tete {
    margin-bottom: 1.75rem;
}

.pp-section__titre {
    margin: 0;
    font-family: var(--pp-police);
    font-size: clamp(1.9rem, 4.5cqi, 3.2rem);
    font-weight: 800;
    line-height: 1.05;
    letter-spacing: -0.03em;
    text-wrap: balance;
    color: var(--pp-texte);
}

.pp-tuile {
    padding: clamp(1.5rem, 3cqi, 2.25rem);
    background: var(--pp-surface);
    border: 1px solid var(--pp-bordure);
    border-radius: var(--pp-rayon);
}

/* À propos : texte en grand, colonne de lecture confortable. */
.pp-site .pp-apropos__texte {
    max-width: 62ch;
    margin: 0;
    font-size: clamp(1.15rem, 2cqi, 1.45rem);
    line-height: 1.55;
    color: var(--pp-texte);
}

.pp-site .pp-infos {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.2rem;
    margin: 0;
    padding: 0;
    border: 0;
    font-family: var(--font-base, system-ui, sans-serif);
}

.pp-site .pp-infos dt {
    margin-top: 0.75rem;
    font-size: 0.8rem;
    /* Un cran plus soutenu que --pp-doux : le thème Fitness tombait à 4,47:1 (audit du 21/10/2026). */
    color: color-mix(in srgb, var(--pp-doux) 80%, var(--pp-texte));
}

.pp-site .pp-infos dd {
    margin: 0;
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--pp-texte);
}

.pp-site .pp-infos dd a {
    color: var(--pp-texte);
    text-decoration-color: var(--pp-accent);
    text-underline-offset: 3px;
}

/* Actualités : la plus récente « à la une » sur toute la largeur (image 4:3 + texte côte à côte), les
   suivantes en cartes. Toutes les images gardent le format 4:3 du recadrage à l'envoi. */
.pp-actus {
    display: grid;
    /* Colonnes qui se partagent la rangée : une ou deux actus sous la vedette ne laissent plus de trou
       (une carte seule au tiers de la largeur, relecture du 23/10/2026). */
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
    gap: 1.25rem;
}

.pp-actus > .actualite-card--vedette {
    grid-column: 1 / -1;
}

.pp-site .actualite-card {
    background: var(--pp-surface);
    border-color: var(--pp-bordure);
    border-radius: var(--pp-rayon);
    font-family: var(--font-base, system-ui, sans-serif);
}

.pp-site .actualite-card__titre {
    font-family: var(--pp-police);
    color: var(--pp-texte);
}

.pp-site .actualite-card__texte {
    color: var(--pp-doux);
}

.pp-site .actualite-card__pro,
.pp-site .actualite-card__lien {
    color: var(--pp-accent-texte);
}

.pp-site .actualite-card__badge {
    background: var(--pp-accent);
    color: var(--pp-sur-accent);
}

.pp-site .actualite-card__media .event-cover-abstract {
    --cat-color: var(--pp-accent);
}

/* Agenda de la ville. */
.pp-agenda {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
    gap: 1rem;
}

.pp-agenda__item {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1rem;
    background: var(--pp-surface);
    border: 1px solid var(--pp-bordure);
    border-radius: var(--pp-rayon-petit);
    text-decoration: none;
    font-family: var(--font-base, system-ui, sans-serif);
    transition: border-color 0.2s ease, transform 0.2s ease;
}

@media (hover: hover) {
    .pp-agenda__item:hover {
        border-color: var(--pp-accent);
        transform: translateY(-2px);
    }
}

.pp-agenda__date {
    display: grid;
    flex: 0 0 auto;
    place-items: center;
    width: 3.75rem;
    height: 3.75rem;
    background: var(--pp-accent);
    border-radius: max(var(--pp-rayon-petit), 6px);
    color: var(--pp-sur-accent);
    line-height: 1;
}

.pp-agenda__date strong {
    font-size: 1.4rem;
}

.pp-agenda__date span {
    font-size: 0.78rem;
    text-transform: uppercase;
}

.pp-agenda__titre {
    display: block;
    font-weight: 700;
    color: var(--pp-texte);
}

.pp-agenda__lieu {
    font-size: 0.85rem;
    color: var(--pp-doux);
}

/* Contact. */
.pp-contact {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
    align-items: start;
    gap: clamp(1.5rem, 4cqi, 3rem);
}

.pp-contact__rassure {
    max-width: 36ch;
    color: var(--pp-doux);
    font-family: var(--font-base, system-ui, sans-serif);
}

.pp-site .entreprise-contact {
    margin: 0;
    font-family: var(--font-base, system-ui, sans-serif);
}

.pp-site .entreprise-contact__declencheur {
    color: var(--pp-texte);
}

.pp-site .entreprise-contact input,
.pp-site .entreprise-contact textarea {
    background: var(--pp-fond);
    border-color: var(--pp-bordure);
    color: var(--pp-texte);
}

/* Formulaire de contact (classes de la fiche annuaire) : libellés et aides aux couleurs du pro — sans cela,
   ils gardaient le texte d'Opalenews, quasi invisible sur un fond clair (audit du 22/10/2026 : 1,01:1). */
.pp-site .entreprise-contact label {
    color: var(--pp-texte);
}

.pp-site .entreprise-contact :is(.entreprise-contact__intro, .entreprise-contact__mentions, .help-text, .form-help, small) {
    color: color-mix(in srgb, var(--pp-doux) 60%, var(--pp-texte));
}

.pp-site .entreprise-contact .btn--primary {
    background: var(--pp-accent);
    border-color: var(--pp-accent);
    color: var(--pp-sur-accent);
}

.pp-pied {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 0.5rem;
    max-width: var(--pp-largeur, 100rem);
    margin: 0 auto;
    padding: 2rem clamp(1rem, 4cqi, 2.5rem);
    border-top: 1px solid var(--pp-bordure);
    font-family: var(--font-base, system-ui, sans-serif);
    font-size: 0.85rem;
    color: var(--pp-doux);
}

/* ── Hors mini-site : barre du gestionnaire, signalement, barre mobile ── */

/* Barre du gestionnaire : élément d'OPALENEWS, pas du mini-site — bandeau marine du site, libellé en surtitre,
   « Nouvelle actualité » en bouton plein clair, les deux autres en contour. Jetons du site uniquement (les `--da-*`
   de l'ancienne DA n'existent pas côté public : texte clair sur boutons blancs, relecture du 29/10/2026). */
.pp-gestion {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.6rem 1rem;
    padding: 0.85rem clamp(1rem, 4vw, 2.5rem);
    font-size: 0.92rem;
    color: #fff;
    background: #0b2c44;
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}

.pp-gestion span {
    margin-right: 0.5rem;
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: #f3d9a4;
}

.pp-gestion a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0.45rem 1.15rem;
    font-weight: 700;
    color: #fff;
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.5);
    border-radius: 999px;
    text-decoration: none;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.pp-gestion a:hover,
.pp-gestion a:focus-visible {
    background: rgba(255, 255, 255, 0.12);
    border-color: #fff;
}

.pp-gestion a.entreprise__nouvelle-actu {
    color: #0b2c44;
    background: #fff;
    border-color: #fff;
}

.pp-gestion a.entreprise__nouvelle-actu:hover,
.pp-gestion a.entreprise__nouvelle-actu:focus-visible { background: #f3d9a4; border-color: #f3d9a4; }

@media (max-width: 600px) {
    .pp-gestion span { flex-basis: 100%; margin: 0; text-align: center; }
    .pp-gestion a { flex: 1 1 auto; justify-content: center; }
}

.pp-page .entreprise-signaler {
    max-width: var(--pp-largeur, 100rem);
    margin: var(--space-lg) auto 0;
    padding: 0 clamp(1rem, 4cqi, 2.5rem);
    border-top: 0;
}

.pp-barre-mobile {
    position: fixed;
    /* Zones de sécurité : barre d'accueil de l'iPhone, encoche en paysage. */
    right: max(12px, env(safe-area-inset-right, 0px));
    bottom: calc(14px + env(safe-area-inset-bottom, 0px));
    left: calc(84px + env(safe-area-inset-left, 0px));
    z-index: 40;
    display: flex;
    gap: 6px;
    padding: 6px;
    background: color-mix(in srgb, var(--pp-fond) 94%, transparent);  /* 85 % : le texte de dessous transparaissait (audit mobile 21/10/2026) */
    border: 1px solid color-mix(in srgb, var(--pp-texte) 15%, transparent);
    border-radius: 999px;
    box-shadow: 0 18px 40px -12px rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(14px) saturate(160%);
    -webkit-backdrop-filter: blur(14px) saturate(160%);
}

.pp-barre-mobile a {
    flex: 1;
    padding: 0.75rem 0.5rem;
    border-radius: 999px;
    color: var(--pp-texte);
    font-weight: 700;
    text-align: center;
    text-decoration: none;
}

.pp-barre-mobile {
    transition: transform 0.3s ease, opacity 0.3s ease, visibility 0.3s;
}

/* Masquée tant que les boutons du haut sont à l'écran (page-pro.js) : pas d'actions en double. */
.pp-barre-mobile--masquee {
    transform: translateY(calc(100% + 24px));
    opacity: 0;
    /* `visibility` : ses liens invisibles ne reçoivent plus le focus clavier ni la lecture d'écran. */
    visibility: hidden;
    pointer-events: none;
}

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

.pp-barre-mobile a:first-child {
    background: var(--pp-accent);
    color: var(--pp-sur-accent);
}

/* Requête de CONTENEUR (`.pp-site`, conteneur « pp ») et non de fenêtre : l'aperçu de « Personnaliser »
   montre ainsi la vraie mise en page téléphone dans un cadre de 390 px. */
@container pp (max-width: 860px) {
    .pp-hero,
    .pp-contact {
        grid-template-columns: minmax(0, 1fr);
    }

    /* Pleine largeur, hauteur bornée : un ratio + une hauteur max rétrécissaient la photo à gauche (768 px). */
    .pp-hero__visuel {
        width: 100%;
        height: clamp(220px, 46cqi, 380px);
        aspect-ratio: auto;
        max-height: none;
        order: -1;
    }

    /* Sans photo, la composition n'est qu'un décor : un bandeau bas plutôt qu'un carré qui repousse le
       titre sous la ligne de flottaison (relecture téléphone du 22/10/2026). */
    .pp-site--sans-photo:not(.pp-site--vitrine) .pp-hero__visuel {
        height: auto;
        aspect-ratio: 5 / 2;
        overflow: hidden;
        border-radius: var(--pp-rayon);
    }

    .pp-site--sans-photo:not(.pp-site--vitrine) .pp-composition__lettre {
        font-size: 7.5rem;
    }

    .pp-nav__liens {
        display: none;
    }

    .pp-actus {
        grid-template-columns: minmax(0, 1fr);
    }

    .pp-actus > .actualite-card--vedette {
        grid-column: auto;
    }
}

/* Hors du conteneur : place pour la barre d'actions fixe du bas. */
@media (max-width: 860px) {
    .pp-page {
        padding-bottom: calc(6rem + env(safe-area-inset-bottom, 0px));
    }
}

@media (min-width: 768px) {
    .pp-barre-mobile {
        display: none;
    }
}

/* Apparition au défilement — amélioration progressive, jamais imposée. */
@supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
        .pp-site:not(.pp-site--apercu) .pp-revele {
            animation: pp-apparition linear both;
            animation-timeline: view();
            animation-range: entry 0% cover 22%;
        }
    }
}

@keyframes pp-apparition {
    from { opacity: 0; transform: translateY(28px); }
    to { opacity: 1; transform: none; }
}

/* Contact : moyens directs en liste à filets au-dessus du bouton « Écrire un message ». */
.pp-contact__direct {
    display: grid;
    margin: 0 0 1.25rem;
    font-family: var(--font-base, system-ui, sans-serif);
}

.pp-contact__direct > div {
    display: grid;
    grid-template-columns: 7.5rem minmax(0, 1fr);
    gap: 0.75rem;
    align-items: baseline;
    padding: 0.8rem 0;
    border-bottom: 1px solid var(--pp-bordure);
}

.pp-contact__direct > div:first-child { padding-top: 0; }

.pp-contact__direct dt {
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--pp-doux);
}

.pp-contact__direct dd { margin: 0; color: var(--pp-texte); }
.pp-contact__direct a { color: inherit; font-weight: 700; text-decoration-color: var(--pp-accent); text-underline-offset: 0.2em; }
.pp-contact__direct .pp-statut { margin: 0; }

@container pp (max-width: 520px) {
    .pp-contact__direct > div { grid-template-columns: minmax(0, 1fr); gap: 0.2rem; }
}

/* Sortie avec photo : la photo en tête (16:9, jamais déformée), la date en pastille posée sur son coin, le texte
   dessous. Sans photo, la carte garde sa ligne date | texte. */
.pp-site .pp-agenda__item.pp-agenda__item--photo {
    position: relative;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0;
    overflow: hidden;
}

.pp-agenda__photo { position: relative; display: block; aspect-ratio: 16 / 9; overflow: hidden; background: var(--pp-bordure); }
.pp-agenda__photo .event-cover-abstract { position: absolute; inset: 0; }
.pp-agenda__photo img { display: block; width: 100%; height: 100%; object-fit: cover; }

.pp-agenda__item--photo .pp-agenda__date {
    position: absolute;
    top: 0.75rem;
    left: 0.75rem;
    box-shadow: 0 8px 20px -10px rgba(0, 0, 0, 0.5);
}

.pp-agenda__item--photo .pp-agenda__texte { display: block; padding: 0.9rem 1rem 1rem; }

/* Éditorial : liste typographique (date | titre), sans photo. */
.pp-site--editorial .pp-agenda__photo { display: none; }
.pp-site--editorial .pp-agenda__item.pp-agenda__item--photo { position: static; flex-direction: row; align-items: center; gap: 1rem; padding: inherit; }
.pp-site--editorial .pp-agenda__item--photo .pp-agenda__date { position: static; box-shadow: none; }
.pp-site--editorial .pp-agenda__item--photo .pp-agenda__texte { padding: 0; }

/* Bento sur téléphone : la sortie seule en bout de rang s'étire sur toute la largeur ; avec sa photo, elle reste
   en colonne (photo dessus) au lieu de la ligne photo | texte qui écrasait le texte. */
.pp-site.pp-site--bento .pp-agenda > .pp-agenda__item--photo:last-child:nth-child(odd) { flex-direction: column; align-items: stretch; }

/*
mini-site-infos.css

QUOI : Blocs pratiques du mini-site d'une page Pro : statut « Ouvert / Fermé », tuiles d'infos pratiques
       (horaires, adresse et carte, contact et réseaux), galerie de photos et sa visionneuse, questions
       fréquentes.

COMMENT : Mêmes variables `--pp-*` que mini-site.css (posées par `ThemePagePro` sur `.pp-site`). Seule
          exception assumée : la pastille du statut (vert ouvert, ambre « ferme bientôt », rouge fermé), un
          code universel ; son texte reste à la couleur du texte du pro, donc lisible sur tous les fonds. La
          mise en page de ces blocs selon le gabarit (bento, vitrine, éditorial) est dans
          mini-site-gabarits.css ; ici, la disposition « classique ».

OÙ : Importé par app.imports.css après mini-site-sections.css. Template `entreprise/_partials/_mini_site.html.twig`.

POURQUOI : Scindé des autres fichiers du mini-site (limite de 500 lignes par fichier CSS, docs/ARCHITECTURE.md §5).
*/

/* ── Statut d'ouverture ── */

.pp-statut {
    display: inline-flex;
    align-self: flex-start;
    width: fit-content;
    align-items: center;
    gap: 0.55rem;
    margin: 1.25rem 0 0;
    padding: 0.45rem 0.95rem 0.45rem 0.75rem;
    background: var(--pp-surface);
    border: 1px solid var(--pp-bordure);
    border-radius: 999px;
    font-family: var(--font-base, system-ui, sans-serif);
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--pp-texte);
}

.pp-statut__point {
    width: 0.65rem;
    height: 0.65rem;
    border-radius: 50%;
    background: #d64545;
    box-shadow: 0 0 0 3px color-mix(in srgb, #d64545 25%, transparent);
}

.pp-statut--ouvert .pp-statut__point {
    background: #1f9d55;
    box-shadow: 0 0 0 3px color-mix(in srgb, #1f9d55 25%, transparent);
}

.pp-statut--bientot .pp-statut__point {
    background: #e0a100;
    box-shadow: 0 0 0 3px color-mix(in srgb, #e0a100 25%, transparent);
}

@media (prefers-reduced-motion: no-preference) {
    .pp-statut--ouvert .pp-statut__point {
        animation: pp-pouls 2.4s ease-out infinite;
    }
}

@keyframes pp-pouls {
    0% { box-shadow: 0 0 0 0 color-mix(in srgb, #1f9d55 55%, transparent); }
    70%, 100% { box-shadow: 0 0 0 9px color-mix(in srgb, #1f9d55 0%, transparent); }
}

/* ── Infos pratiques (disposition classique : tuiles qui se rangent seules) ── */

.pp-essentiel {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
    gap: 1.25rem;
    max-width: var(--pp-largeur, 100rem);
    margin: 0 auto;
    padding: 0 clamp(1rem, 4cqi, 2.5rem) clamp(1.5rem, 4cqi, 3rem);
    font-family: var(--font-base, system-ui, sans-serif);
}

.pp-essentiel .pp-tuile {
    display: flex;
    flex-direction: column;
}

.pp-tuile--horaires {
    background: var(--pp-teinte);
    border-color: transparent;
}

.pp-horaires {
    display: grid;
    gap: 0.15rem;
    margin: 0;
}

.pp-horaires__ligne {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 0.25rem 1rem;
    padding: 0.4rem 0.6rem;
    border-radius: var(--pp-rayon-petit);
}

.pp-horaires dt,
.pp-horaires dd {
    margin: 0;
}

.pp-horaires dt {
    flex: 1 1 auto;
    min-width: 0;
    font-weight: 600;
}

/* Les heures restent sur une ligne ; c'est le jour qui cède la place s'il le faut. */
.pp-horaires dd {
    font-variant-numeric: tabular-nums;
    text-align: right;
    white-space: nowrap;
}

/* Sur ordinateur, trois tuiles d'infos : celle des horaires prend plus de place que les autres. */
@container pp (min-width: 861px) {
    .pp-site:not(.pp-site--bento) .pp-essentiel:has(> .pp-tuile--horaires):has(> :nth-child(3)) {
        grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr) minmax(0, 1fr);
    }
}

.pp-horaires__ligne--ferme {
    color: color-mix(in srgb, var(--pp-doux) 80%, var(--pp-texte));
}

.pp-horaires__ligne--auj {
    background: var(--pp-fond);
    font-weight: 700;
    box-shadow: inset 3px 0 0 var(--pp-accent);
}

.pp-horaires__note {
    margin: 0.9rem 0 0;
    font-size: 0.92rem;
    color: var(--pp-texte);
}

.pp-adresse {
    margin: 0 0 1rem;
    font-size: 1.1rem;
    font-weight: 600;
    line-height: 1.45;
}

.pp-carte {
    flex: 1 1 auto;
    min-height: 220px;
    border: 1px solid var(--pp-bordure);
    border-radius: var(--pp-rayon-petit);
    overflow: hidden;
    z-index: 0;
}

/* Aperçu de « Personnaliser » : pas de vraie carte (Leaflet n'est pas chargé), un fond de plan stylisé. */
.pp-carte--apercu {
    background:
        radial-gradient(circle at 50% 48%, var(--pp-accent) 0 9px, transparent 10px),
        repeating-linear-gradient(35deg, transparent 0 22px, var(--pp-bordure) 22px 24px),
        var(--pp-surface);
}

/* Marqueur de la carte aux couleurs du pro (remplace le marqueur « Affiche » des fiches événement). */
.pp-carte .event-map-marker {
    width: 28px;
    height: 28px;
    background: var(--pp-accent);
    border: 3px solid #fff;
    border-radius: 50%;
    box-shadow: 0 6px 16px -4px rgba(0, 0, 0, 0.55);
}

.pp-carte.event-map--error {
    display: grid;
    place-items: center;
    padding: 1rem;
    text-align: center;
    color: var(--pp-doux);
}

.pp-essentiel .pp-lien-fleche {
    margin-top: 0.9rem;
}

.pp-reseaux {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 1rem 0 0;
    padding: 0;
    list-style: none;
}

.pp-reseaux__lien {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    min-height: 48px;
    padding: 0.4rem 1rem;
    border: 1px solid var(--pp-bordure);
    border-radius: 999px;
    font-weight: 600;
    text-decoration: none;
    transition: border-color 0.2s ease, background 0.2s ease;
}

.pp-reseaux__lien:hover,
.pp-reseaux__lien:focus-visible {
    background: var(--pp-teinte);
    border-color: var(--pp-accent);
}

.pp-contact__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: auto;
    padding-top: 1.25rem;
}

.pp-site button.pp-bouton {
    cursor: pointer;
    font-size: inherit;
}

.pp-site button.pp-bouton--petit {
    font-size: 0.9rem;
}

/* ── Galerie ── */

.pp-galerie {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
    gap: 0.75rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Une ou deux photos : pas de vignettes géantes sur grand écran. */
.pp-galerie--1 {
    max-width: 52rem;
}

.pp-galerie--2 {
    max-width: 80rem;
}

/* À partir de 5 photos, la première fait la une (mosaïque). */
@container pp (min-width: 861px) {
    .pp-galerie:is(.pp-galerie--5, .pp-galerie--6, .pp-galerie--7, .pp-galerie--8) {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }

    .pp-galerie:is(.pp-galerie--5, .pp-galerie--6, .pp-galerie--7, .pp-galerie--8) > li:first-child {
        grid-column: span 2;
        grid-row: span 2;
    }
    /* Au-delà de 5 photos, la dernière rangée (4 colonnes) se remplit sans trou : 2 photos → deux moitiés,
       3 → une moitié et deux quarts (relecture des vraies pages Pro du 29/10/2026). */
    /* 6 photos : deux rangées de trois, sans une (la 6e en bandeau rognait les portraits). */
    .pp-galerie.pp-galerie--6 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .pp-galerie.pp-galerie--6 > li:first-child { grid-column: auto; grid-row: auto; }
    .pp-galerie.pp-galerie--7 > li:nth-child(n + 6) { grid-column: span 2; }
    .pp-galerie.pp-galerie--7 > li:nth-child(n + 6) .pp-galerie__photo img { aspect-ratio: 16 / 9; }
    .pp-galerie.pp-galerie--8 > li:nth-child(6) { grid-column: span 2; }
}

.pp-galerie__photo {
    display: block;
    height: 100%;
    overflow: hidden;
    border-radius: var(--pp-rayon-petit);
    background: var(--pp-surface);
}

.pp-galerie__photo img {
    display: block;
    width: 100%;
    height: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    transition: transform 0.4s ease;
}

@media (hover: hover) {
    .pp-galerie__photo:hover img {
        transform: scale(1.04);
    }
}

.pp-galerie__photo:focus-visible img {
    transform: scale(1.04);
}

.pp-visionneuse {
    max-width: 100vw;
    max-height: 100dvh;
    width: 100vw;
    height: 100dvh;
    overscroll-behavior: contain;
    margin: 0;
    padding: 0;
    background: transparent;
    border: 0;
}

.pp-visionneuse[open] {
    display: grid;
    place-items: center;
}

.pp-visionneuse::backdrop {
    background: rgba(8, 10, 14, 0.9);
}

.pp-visionneuse img {
    max-width: min(92vw, 1400px);
    max-height: 86dvh;
    object-fit: contain;
    border-radius: 8px;
}

.pp-visionneuse button {
    position: fixed;
    display: grid;
    place-items: center;
    width: 52px;
    height: 52px;
    background: rgba(255, 255, 255, 0.14);
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    color: #fff;
    font-size: 1.8rem;
    line-height: 1;
    cursor: pointer;
    backdrop-filter: blur(8px);
}

.pp-visionneuse button:hover,
.pp-visionneuse button:focus-visible {
    background: rgba(255, 255, 255, 0.28);
}

.pp-visionneuse__fermer {
    top: max(16px, env(safe-area-inset-top, 0px));
    right: max(16px, env(safe-area-inset-right, 0px));
}

.pp-visionneuse__nav {
    top: 50%;
    transform: translateY(-50%);
}

.pp-visionneuse__nav--prec {
    left: max(16px, env(safe-area-inset-left, 0px));
}

.pp-visionneuse__nav--suiv {
    right: max(16px, env(safe-area-inset-right, 0px));
}

/* ── Questions fréquentes ── */

.pp-faq__liste {
    max-width: 62rem;
    border-top: 1px solid var(--pp-bordure);
    font-family: var(--font-base, system-ui, sans-serif);
}

.pp-faq__item {
    border-bottom: 1px solid var(--pp-bordure);
}

.pp-faq__item summary {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    padding: 1.15rem 0.25rem;
    font-family: var(--pp-police);
    font-size: clamp(1.05rem, 1.8cqi, 1.3rem);
    font-weight: 700;
    cursor: pointer;
    list-style: none;
}

.pp-faq__item summary::-webkit-details-marker {
    display: none;
}

.pp-faq__item summary::after {
    content: "+";
    display: grid;
    flex: 0 0 auto;
    place-items: center;
    width: 2rem;
    height: 2rem;
    background: var(--pp-teinte);
    border-radius: 50%;
    color: var(--pp-texte);
    font-family: var(--font-base, system-ui, sans-serif);
    transition: transform 0.25s ease;
}

.pp-faq__item[open] summary::after {
    transform: rotate(45deg);
}

.pp-faq__item p {
    max-width: 60ch;
    margin: 0;
    padding: 0 0.25rem 1.25rem;
    line-height: 1.6;
    /* Plus soutenu que --pp-doux, qui frôle 4,5:1 sur certains thèmes (audit du 21/10/2026). */
    color: color-mix(in srgb, var(--pp-doux) 60%, var(--pp-texte));
}

/* ── Ergonomie téléphone, toutes mises en page ── */

/* Nom long dans la barre : une seule ligne, coupée proprement, le bouton « Appeler » reste visible. */
.pp-nav__marque {
    min-width: 0;
}

.pp-nav__marque span:last-child {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Titre géant : dernier filet de sécurité, un mot trop large passe à la ligne plutôt que de déborder
   (la césure n'est permise que sur téléphone, cf. plus bas). */
.pp-site .pp-hero__nom {
    overflow-wrap: break-word;
}

@container pp (max-width: 600px) {
    .pp-site .pp-hero__nom {
        hyphens: auto;
    }

    /* Boutons d'action au pouce : le principal sur toute la largeur, les autres se partagent la ligne. */
    .pp-hero__actions > .pp-bouton {
        flex: 1 1 auto;
        justify-content: center;
    }

    .pp-hero__actions > .pp-bouton:first-child {
        flex-basis: 100%;
    }

    .pp-essentiel .pp-tuile {
        padding: 1.25rem;
    }

    .pp-horaires__ligne {
        padding: 0.45rem 0.5rem;
    }
}

/*
mini-site-gabarits.css

QUOI : Les gabarits de mise en page du mini-site d'une page Pro, en plus du « Classique » (titre et visuel
       côte à côte, styles de base de mini-site.css) :
       - Vitrine : la photo de couverture en plein écran, titre géant posé dessus, barre de navigation en
         verre flottante, infos pratiques qui chevauchent le bas de la photo ;
       - Bento : haut de page et infos pratiques rangés dans une même grille de tuiles ;
       - Éditorial : mise en page de magazine (bandeau filet, titre pleine largeur, chapeau, visuel à
         droite, texte avec lettrine, filets entre les rubriques) — dans mini-site-editorial.css.

COMMENT : Activé par la classe `pp-site--<gabarit>` (`ThemePagePro::gabarit()`), même HTML pour tous. Toutes
          les couleurs dérivent des variables `--pp-*` ; seule exception, le texte posé sur une PHOTO
          (gabarit Vitrine) est blanc sur un voile sombre, quelle que soit l'ambiance, pour rester lisible.
          `pp-site--photo` / `pp-site--sans-photo` disent si une couverture existe (Vitrine sans photo :
          aplat teinté et composition graphique). Bento : grille de 12 colonnes, `subgrid` pour que le haut
          de page et les infos pratiques gardent leur boîte (ancres #pp-haut et #infos) ; une tuile absente
          (pas d'horaires, pas d'adresse) est compensée par `:has()` plutôt que de laisser un trou.

OÙ : Importé par app.imports.css après mini-site-infos.css. Choisi dans « Personnaliser ma page ».

POURQUOI : Des pages Pro qui ne se ressemblent pas toutes : le restaurant met sa salle en grand, le cabinet
           range ses infos, l'artisan raconte son métier.
*/

/* ═════════════ Classique ═════════════ */

/* Avec photo : la photo « ordinateur » est demandée en paysage 16:9 — on la montre en paysage, à droite,
   plutôt que recadrée en portrait (la composition graphique, elle, garde son format 4:5). */
/* Ordinateur seulement : sinon cette règle, plus précise, battait la colonne unique du téléphone (haut de
   page coupé en deux colonnes étroites à 390 px, audit du 23/10/2026). */
@container pp (min-width: 861px) {
    .pp-site--classique.pp-site--photo .pp-hero {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
    }

    .pp-site--classique.pp-site--photo .pp-hero__visuel {
        aspect-ratio: 16 / 10;
        max-height: none;
    }
}

/* ═════════════ Vitrine ═════════════ */

.pp-site--vitrine {
    position: relative;
}

.pp-site--vitrine .pp-hero {
    position: relative;
    display: flex;
    align-items: flex-end;
    max-width: none;
    min-height: min(88svh, 860px);
    padding: clamp(7rem, 14cqi, 10rem) clamp(1rem, 4cqi, 2.5rem) clamp(5rem, 9cqi, 7.5rem);
    isolation: isolate;
}

.pp-site--vitrine .pp-hero__texte {
    width: 100%;
    max-width: var(--pp-largeur, 100rem);
    margin: 0 auto;
}

.pp-site--vitrine .pp-hero__nom {
    max-width: 14ch;
    font-size: calc(clamp(2.6rem, 12cqi, 9rem) * var(--pp-echelle, 1));
}

.pp-site--vitrine .pp-hero__visuel {
    position: absolute;
    inset: 0;
    z-index: -1;
    height: auto;
    aspect-ratio: auto;
    max-height: none;
}

.pp-site--vitrine .pp-hero__couverture {
    border-radius: 0;
    box-shadow: none;
}

.pp-site--vitrine .pp-hero__logo {
    top: clamp(6rem, 11cqi, 8rem);
    right: clamp(1rem, 4cqi, 2.5rem);
    bottom: auto;
    left: auto;
    /* Au-dessus du voile sombre de la photo (il le ternissait, relecture du 29/10/2026). */
    z-index: 2;
}

/* Avec photo : voile sombre et texte blanc, quelle que soit l'ambiance. */
.pp-site--vitrine.pp-site--photo .pp-hero__visuel::after {
    content: "";
    position: absolute;
    inset: 0;
    /* Voile calculé pour le pire cas (photo très claire) : ≥ 0,55 d'opacité partout où se pose du petit texte
       blanc (4,5:1), ≥ 0,38 en haut sous la barre de navigation (audit du 22/10/2026). */
    background: linear-gradient(to top, rgba(6, 8, 12, 0.88) 0%, rgba(6, 8, 12, 0.66) 60%, rgba(6, 8, 12, 0.38) 100%);
}

.pp-site--vitrine.pp-site--photo .pp-hero__texte {
    --pp-texte: #fff;
    --pp-doux: rgba(255, 255, 255, 0.88);
    --pp-surface: rgba(255, 255, 255, 0.14);
    --pp-teinte: rgba(255, 255, 255, 0.18);
    --pp-bordure: rgba(255, 255, 255, 0.4);
    color: #fff;
    text-shadow: 0 1px 14px rgba(0, 0, 0, 0.35);
}

/* Statut et boutons secondaires sur la photo : verre SOMBRE (un verre clair éclaircissait le fond sous le texte). */
.pp-site--vitrine.pp-site--photo .pp-hero :is(.pp-statut, .pp-bouton--contour) {
    background: rgba(6, 8, 12, 0.42);
    text-shadow: none;
}

.pp-site--vitrine.pp-site--photo .pp-hero__texte .pp-surtitre,
.pp-site--vitrine.pp-site--photo .pp-hero__nom .pp-accent {
    color: #fff;
}

/* Le dernier mot reste « à l'accent » : souligné épais à la couleur du pro, lisible sur toute photo. */
.pp-site--vitrine.pp-site--photo .pp-hero__nom .pp-accent {
    text-decoration: underline;
    text-decoration-color: var(--pp-accent);
    text-decoration-thickness: 0.09em;
    text-underline-offset: 0.12em;
    /* Trait continu : coupé par les jambages (« q » d'Aquar'aile), il donnait deux tronçons. */
    text-decoration-skip-ink: none;
}

.pp-site--vitrine.pp-site--photo .pp-hero :is(.pp-statut, .pp-bouton--contour, .entreprise__theme) {
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
}

/* Barre de navigation en verre, posée sur la photo. */
.pp-site--vitrine.pp-site--photo .pp-nav {
    position: absolute;
    top: clamp(0.75rem, 2cqi, 1.25rem);
    left: 50%;
    z-index: 3;
    width: calc(var(--pp-largeur, 100rem) - 2 * clamp(1rem, 4cqi, 2.5rem));
    padding: 0.55rem 1.1rem 0.55rem 0.55rem;
    transform: translateX(-50%);
    background: rgba(12, 14, 18, 0.55);
    border: 1px solid rgba(255, 255, 255, 0.22);
    border-radius: 999px;
    color: #fff;
    -webkit-backdrop-filter: blur(16px) saturate(150%);
    backdrop-filter: blur(16px) saturate(150%);
}

.pp-site--vitrine.pp-site--photo .pp-nav:has(> .pp-bouton) {
    padding-right: 0.55rem;
}

/* Arrondis concentriques : dans la pilule, bouton et logo suivent la courbe de la barre (sinon « coupure »,
   retour d'Ellie du 24/10/2026). */
.pp-site--vitrine.pp-site--photo .pp-nav :is(.pp-bouton, .pp-nav__logo) {
    border-radius: 999px;
}

.pp-site--vitrine.pp-site--photo .pp-nav__liens a {
    color: rgba(255, 255, 255, 0.85);
}

.pp-site--vitrine.pp-site--photo .pp-nav__liens a:hover {
    color: #fff;
}

/* Sans photo : aplat teinté, composition graphique repoussée à droite. */
.pp-site--vitrine.pp-site--sans-photo .pp-hero {
    background: var(--pp-teinte);
}

.pp-site--vitrine.pp-site--sans-photo .pp-composition {
    left: 48%;
}

/* Pastilles : sur l'aplat teinté, elles prennent la couleur du fond pour rester visibles. */
.pp-site--vitrine.pp-site--sans-photo .entreprise__theme {
    background: var(--pp-fond);
}

/* Sur l'aplat teinté, le texte secondaire passe à la couleur du texte (--pp-doux tombait à 4,38:1). */
.pp-site--vitrine.pp-site--sans-photo .pp-hero__accroche {
    color: var(--pp-texte);
}

/* Les infos pratiques chevauchent le bas du haut de page. */
.pp-site--vitrine .pp-essentiel {
    position: relative;
    z-index: 1;
    margin-top: clamp(-4rem, -6cqi, -2.5rem);
}

.pp-site--vitrine .pp-essentiel .pp-tuile {
    background: var(--pp-fond);
    box-shadow: 0 30px 60px -36px rgba(0, 0, 0, 0.55);
}

.pp-site--vitrine .pp-essentiel .pp-tuile--horaires {
    background: color-mix(in srgb, var(--pp-accent) 10%, var(--pp-fond));
}

/* ═════════════ Bento ═════════════ */

.pp-site--bento .pp-ouverture {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: clamp(0.75rem, 1.4cqi, 1.1rem);
    max-width: var(--pp-largeur, 100rem);
    margin: 0 auto;
    padding: clamp(0.5rem, 2cqi, 1.5rem) clamp(1rem, 4cqi, 2.5rem) clamp(2rem, 4cqi, 3rem);
}

.pp-site--bento :is(.pp-hero, .pp-essentiel) {
    display: grid;
    align-items: stretch;
    grid-column: 1 / -1;
    grid-template-columns: subgrid;
    gap: inherit;
    max-width: none;
    margin: 0;
    padding: 0;
}

.pp-site--bento .pp-hero__texte {
    grid-column: span 7;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    min-height: clamp(360px, 38cqi, 520px);
    padding: clamp(1.5rem, 3.5cqi, 3rem);
    background: var(--pp-surface);
    border: 1px solid var(--pp-bordure);
    border-radius: var(--pp-rayon);
}

.pp-site--bento .pp-hero__nom {
    font-size: calc(clamp(2rem, 11cqi, 5.2rem) * var(--pp-echelle, 1));
}

.pp-site--bento .pp-hero__actions {
    margin-top: 1.5rem;
}

.pp-site--bento .pp-hero__visuel {
    grid-column: span 5;
    aspect-ratio: auto;
    max-height: none;
    min-height: 280px;
    overflow: hidden;
    background: var(--pp-teinte);
    border-radius: var(--pp-rayon);
}

.pp-site--bento .pp-hero__couverture {
    position: absolute;
    inset: 0;
    border-radius: 0;
    box-shadow: none;
}

.pp-site--bento .pp-hero__logo {
    bottom: 1rem;
    left: 1rem;
}

/* Sans photo, la composition est recadrée dans sa tuile : disque et carré resserrés au centre. */
.pp-site--bento .pp-composition__disque {
    top: 12%;
    right: 8%;
    width: 62%;
}

.pp-site--bento .pp-composition__carre {
    bottom: 10%;
    left: 8%;
    width: 52%;
}

.pp-site--bento .pp-composition__lettre {
    right: 14%;
    bottom: 10%;
    font-size: clamp(7rem, 14cqi, 12rem);
}

/* Infos pratiques : 4 + 5 + 3 colonnes ; une tuile absente est compensée par ses voisines. */
.pp-site--bento .pp-tuile--horaires { grid-column: span 4; }
.pp-site--bento .pp-tuile--adresse { grid-column: span 5; }
.pp-site--bento .pp-tuile--contact { grid-column: span 3; }

.pp-site--bento .pp-essentiel:not(:has(.pp-tuile--horaires)) .pp-tuile--adresse { grid-column: span 7; }
.pp-site--bento .pp-essentiel:not(:has(.pp-tuile--horaires)) .pp-tuile--contact { grid-column: span 5; }
.pp-site--bento .pp-essentiel:not(:has(.pp-tuile--adresse)) .pp-tuile--horaires { grid-column: span 7; }
.pp-site--bento .pp-essentiel:not(:has(.pp-tuile--adresse)) .pp-tuile--contact { grid-column: span 5; }
.pp-site--bento .pp-essentiel:not(:has(.pp-tuile--horaires, .pp-tuile--adresse)) .pp-tuile--contact { grid-column: 1 / -1; }

.pp-site--bento .pp-essentiel .pp-tuile {
    padding: clamp(1.25rem, 2.4cqi, 1.75rem);
}

.pp-site--bento .pp-tuile--contact {
    background: var(--pp-accent);
    border-color: var(--pp-accent);
    --pp-texte: var(--pp-sur-accent);
    --pp-accent-texte: var(--pp-sur-accent);
    --pp-bordure: color-mix(in srgb, var(--pp-sur-accent) 35%, var(--pp-accent));
    --pp-teinte: color-mix(in srgb, var(--pp-sur-accent) 14%, var(--pp-accent));
    color: var(--pp-sur-accent);
}

.pp-site--bento .pp-tuile--contact .pp-infos dt {
    color: var(--pp-sur-accent);
    opacity: 0.8;
}

.pp-site--bento .pp-tuile--contact .pp-infos dd a {
    text-decoration-color: currentColor;
}

/* Sur la tuile à l'accent, le bouton plein prend les couleurs de la page (fond + texte d'origine), pour
   rester visible. `--pp-encre` fige la couleur du texte de la page avant sa surcharge dans la tuile. */
.pp-site--bento {
    --pp-encre: var(--pp-texte);
}

.pp-site--bento .pp-tuile--contact .pp-bouton:not(.pp-bouton--contour) {
    background: var(--pp-fond);
    border-color: var(--pp-fond);
    color: var(--pp-encre);
}

.pp-site--bento .pp-tuile--contact .pp-bouton--contour {
    color: var(--pp-sur-accent);
}

/* Réseaux sur l'aplat d'accent : un léger fond et un contour plus marqué (contraste faible sinon). */
.pp-site--bento .pp-tuile--contact .pp-reseaux__lien {
    background: color-mix(in srgb, var(--pp-sur-accent) 12%, transparent);
    border-color: color-mix(in srgb, var(--pp-sur-accent) 45%, transparent);
}

/* ═════════════ Téléphone et tablette ═════════════ */

@container pp (max-width: 860px) {
    .pp-site--vitrine .pp-hero {
        min-height: min(92svh, 720px);
    }

    .pp-site--vitrine .pp-hero__visuel {
        aspect-ratio: auto;
        order: 0;
    }

    .pp-site--vitrine.pp-site--sans-photo .pp-composition {
        left: 30%;
        opacity: 0.35;
    }

    .pp-site--vitrine .pp-hero__logo {
        width: auto;
        min-width: 72px;
        height: 72px;
    }

    .pp-site--bento :is(.pp-hero__texte, .pp-hero__visuel, .pp-essentiel .pp-tuile) {
        grid-column: 1 / -1 !important;
    }

    .pp-site--bento .pp-hero__texte {
        min-height: 0;
        padding: 1.25rem;
    }

    /* `align-self: start` : étirée, la tuile ignorerait son ratio et retomberait à 0 de haut. */
    .pp-site--bento .pp-hero__visuel {
        order: -1;
        align-self: start;
        height: auto;
        aspect-ratio: 16 / 11;
        min-height: 0;
    }

    .pp-site--bento.pp-site--sans-photo .pp-hero__visuel {
        aspect-ratio: 5 / 2;
    }

}

/* Bento sans photo : la tuile visuelle devient un aplat à l'accent portant l'initiale (plus net que la
   composition disque + carré, recadrée dans une tuile). */
.pp-site--bento.pp-site--sans-photo .pp-hero__visuel {
    background: var(--pp-accent);
}

.pp-site--bento.pp-site--sans-photo :is(.pp-composition__disque, .pp-composition__carre) {
    display: none;
}

.pp-site--bento.pp-site--sans-photo .pp-composition__lettre {
    right: auto;
    bottom: -0.08em;
    left: 6%;
    font-size: clamp(10rem, 22cqi, 20rem);
    color: var(--pp-sur-accent);
    text-shadow: none;
    opacity: 0.92;
}

/* Bento sur tablette : infos pratiques sur deux colonnes plutôt qu'empilées. */
@container pp (min-width: 601px) and (max-width: 860px) {
    .pp-site--bento .pp-essentiel .pp-tuile--horaires,
    .pp-site--bento .pp-essentiel .pp-tuile--adresse {
        grid-column: span 6 !important;
    }

    .pp-site--bento .pp-essentiel:not(:has(.pp-tuile--horaires, .pp-tuile--adresse)) .pp-tuile--contact,
    .pp-site--bento .pp-essentiel .pp-tuile--contact {
        grid-column: 1 / -1 !important;
    }

    .pp-site--bento .pp-essentiel:not(:has(.pp-tuile--horaires)) .pp-tuile--adresse,
    .pp-site--bento .pp-essentiel:not(:has(.pp-tuile--adresse)) .pp-tuile--horaires {
        grid-column: 1 / -1 !important;
    }
}

/*
mini-site-editorial.css

QUOI : Gabarit « Éditorial » du mini-site d'une page Pro : mise en page de magazine (bandeau à filets,
       titre pleine largeur, chapeau en italique, visuel à droite, infos pratiques séparées par des filets,
       texte « À propos » avec lettrine).

COMMENT : Activé par la classe `pp-site--editorial` (`ThemePagePro::gabarit()`), même HTML que les autres
          gabarits ; `.pp-hero__texte` passe en `display: contents` pour que ses éléments se rangent dans la
          grille du haut de page. Couleurs : variables `--pp-*` uniquement.

OÙ : Importé par app.imports.css après mini-site-gabarits.css.

POURQUOI : Scindé de mini-site-gabarits.css (limite de 500 lignes par fichier CSS, docs/ARCHITECTURE.md §5).
*/

.pp-site--editorial .pp-hero {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    align-items: start;
    gap: 0 clamp(1.5rem, 4cqi, 3.5rem);
    padding-top: clamp(1rem, 3cqi, 2rem);
}

.pp-site--editorial .pp-hero__texte {
    display: contents;
}

/* Bandeau : filet épais, catégorie et ville en petites capitales, comme un en-tête de journal. */
.pp-site--editorial .pp-hero .pp-surtitre {
    grid-column: 1 / -1;
    margin: 0;
    padding: 0.7rem 0;
    border-top: 4px solid var(--pp-texte);
    border-bottom: 1px solid var(--pp-texte);
    color: var(--pp-texte);
    text-align: center;
}

.pp-site--editorial .pp-hero__nom {
    grid-column: 1 / -1;
    margin: clamp(1rem, 3cqi, 2rem) 0;
    padding-bottom: clamp(1rem, 3cqi, 2rem);
    border-bottom: 1px solid var(--pp-bordure);
    font-size: calc(clamp(2.1rem, 11cqi, 10.5rem) * var(--pp-echelle, 1));
    font-weight: 700;
    line-height: 0.92;
    letter-spacing: -0.04em;
    text-align: center;
}

.pp-site--editorial .pp-hero__visuel {
    grid-column: 2;
    grid-row: 3 / span 5;
    aspect-ratio: 4 / 3;
    max-height: none;
}

.pp-site--editorial .pp-hero__couverture {
    box-shadow: none;
}

.pp-site--editorial :is(.pp-hero__accroche, .pp-statut, .pp-pastilles, .pp-hero__actions) {
    grid-column: 1;
    justify-self: start;
}

/* Chapeau : grand, en italique, comme l'attaque d'un article. */
.pp-site--editorial .pp-hero__accroche {
    max-width: none;
    margin: 0;
    font-family: var(--pp-police);
    font-size: clamp(1.35rem, 2.4cqi, 1.9rem);
    font-style: italic;
    line-height: 1.35;
    color: var(--pp-texte);
}

.pp-site--editorial .pp-hero__actions {
    margin-top: 1.5rem;
}

/* Infos pratiques : colonnes séparées par des filets, sans cartes. */
.pp-site--editorial .pp-essentiel {
    gap: 0;
    border-top: 1px solid var(--pp-texte);
    border-bottom: 1px solid var(--pp-texte);
    padding-top: 0;
    padding-bottom: 0;
    /* Pas de marge basse : la section suivante a déjà son propre espacement (trou en double sinon). */
    margin-bottom: 0;
    /* Les filets vont d'une gouttière à l'autre : la largeur est réduite de deux gouttières et la marge
       automatique les recentre — d'où AUCUN retrait intérieur (sinon gouttière en double, audit 23/10/2026). */
    max-width: calc(var(--pp-largeur, 100rem) - 2 * clamp(1rem, 4cqi, 2.5rem));
    padding-inline: 0;
}

/* Texte de la première colonne aligné sur la gouttière, comme les titres de rubrique. */
.pp-site--editorial .pp-essentiel .pp-tuile:first-child {
    padding-left: 0;
}

.pp-site--editorial .pp-essentiel .pp-tuile {
    background: none;
    border: 0;
    border-left: 1px solid var(--pp-bordure);
    border-radius: 0;
}

.pp-site--editorial .pp-essentiel .pp-tuile:first-child {
    border-left: 0;
}

/* Rubriques : filet épais au-dessus du titre. */
.pp-site--editorial .pp-section__tete {
    padding-top: 0.8rem;
    border-top: 4px solid var(--pp-texte);
}

.pp-site--editorial .pp-section__titre {
    font-weight: 700;
}

/* Une seule colonne de lecture : en colonnes CSS, Chrome posait la lettrine flottante dans la DEUXIÈME
   colonne, loin du début du texte (retour d'Ellie du 23/10/2026). */
.pp-site--editorial .pp-apropos__texte {
    max-width: 66ch;
    font-size: clamp(1.08rem, 1.5cqi, 1.22rem);
    line-height: 1.65;
}

/* Lettrine seulement sur un vrai texte : sur une ligne ou deux, la grande initiale reste isolée. */
.pp-site--editorial .pp-apropos__texte--long::first-letter {
    float: left;
    padding: 0.06em 0.12em 0 0;
    font-family: var(--pp-police);
    font-size: 4.4em;
    font-weight: 700;
    line-height: 0.8;
    color: var(--pp-accent-texte);
}

@container pp (max-width: 860px) {
    .pp-site--editorial .pp-hero {
        grid-template-columns: minmax(0, 1fr);
    }

    .pp-site--editorial .pp-hero__visuel {
        grid-column: 1;
        grid-row: auto;
        order: 0;
        margin-top: 1.5rem;
    }

    .pp-site--editorial .pp-hero__actions {
        justify-self: stretch;
    }

    .pp-site.pp-site--editorial .pp-essentiel {
        padding-inline: 0;
    }

    .pp-site--editorial .pp-essentiel .pp-tuile {
        padding-inline: 0;
        border-left: 0;
        border-top: 1px solid var(--pp-bordure);
    }

    .pp-site--editorial .pp-essentiel .pp-tuile:first-child {
        border-top: 0;
    }
}

/*
mini-site-gabarits-2026.css

QUOI : Deux gabarits de page Pro de plus (31/10/2026) et la « matière du fond » :
       - Scindé : écran partagé, la photo de couverture reste fixe à gauche sur toute la hauteur de l'écran
         pendant que la page défile à droite (restaurants, hôtels, lieux qui se vendent par l'image) ;
       - Affiche : le nom en très grand sur toute la largeur, comme une affiche, accroche et boutons sur une
         ligne, puis la photo en large bandeau ;
       - Matière du fond : uni, grain (texture papier légère) ou aurore (halo de la couleur d'accent).

COMMENT : Même HTML que les autres gabarits (classe `pp-site--<gabarit>`). Scindé : `.pp-site` devient une
          grille de deux colonnes ; `.pp-ouverture` et `.pp-hero` passent en `display: contents` pour que le
          visuel soit un enfant direct de la grille, collé (`sticky`) sur toute la hauteur de la colonne de
          gauche ; tout le reste se range à droite. Sous 1000 px d'écran (et dans l'aperçu), la page reprend une
          seule colonne, photo en tête. Grain : bruit SVG gris moyen très transparent, visible sur fond clair
          comme sur fond sombre. Aurore : deux halos de l'accent en haut de page, rien en dur.

OÙ : Importé par app.imports.css après mini-site-editorial.css ; choix dans « Personnaliser ma page »
     (ThemePagePro::GABARITS et ::MATIERES).

POURQUOI : Demande d'Ellie du 31/10/2026 : des pages Pro plus personnalisables et plus marquées (tendances
           2026 : écran partagé, typographie géante, textures et grain plutôt qu'aplats lisses).
*/

/* ═════════════ Scindé ═════════════ */

/* Requête d'ÉCRAN et non de conteneur : `.pp-site` est lui-même le conteneur `pp`, une requête de conteneur ne peut
   pas le viser. L'aperçu de « Personnaliser » (étroit) garde la version une colonne. */
@media (min-width: 1000px) {
    .pp-site--scinde:not(.pp-site--apercu) {
        display: grid;
        grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
        align-items: start;
    }

    .pp-site--scinde:not(.pp-site--apercu) > *,
    .pp-site--scinde:not(.pp-site--apercu) .pp-hero > * {
        grid-column: 2;
        min-width: 0;
    }

    .pp-site--scinde:not(.pp-site--apercu) :is(.pp-ouverture, .pp-hero) {
        display: contents;
    }

    /* La photo : collée sous l'en-tête du site, sur toute la hauteur visible, de la première à la dernière
       rangée de la colonne de droite. */
    .pp-site--scinde:not(.pp-site--apercu) .pp-hero__visuel {
        grid-column: 1;
        grid-row: 1 / span 40;
        position: sticky;
        top: var(--pp-entete, 0px);
        height: calc(100svh - var(--pp-entete, 0px));
        aspect-ratio: auto;
        max-height: none;
        overflow: hidden;
        background: var(--pp-teinte);
    }

    .pp-site--scinde:not(.pp-site--apercu) .pp-hero__couverture {
        border-radius: 0;
        box-shadow: none;
    }

    /* En haut à gauche : en bas, il passait sous le bouton de l'assistant d'Opalenews. */
    .pp-site--scinde:not(.pp-site--apercu) .pp-hero__logo {
        top: clamp(1rem, 2.4cqi, 2rem);
        right: auto;
        bottom: auto;
        left: clamp(1rem, 2.4cqi, 2rem);
        z-index: 2;
    }

    /* Colonne de droite : marges propres, largeur de lecture. */
    .pp-site--scinde:not(.pp-site--apercu) :is(.pp-nav, .pp-hero__texte, .pp-essentiel, .pp-section, .pp-pied) {
        width: 100%;
        max-width: none;
        margin: 0;
        padding-inline: clamp(1.5rem, 3.6cqi, 4rem);
    }

    .pp-site--scinde:not(.pp-site--apercu) .pp-nav {
        position: static;
        padding-block: 1.1rem;
        border-bottom: 1px solid var(--pp-bordure);
    }

    /* Le nom de l'entreprise est déjà en grand juste dessous : la barre garde le logo et les liens. */
    .pp-site--scinde:not(.pp-site--apercu) .pp-nav__marque > span {
        display: none;
    }

    .pp-site--scinde:not(.pp-site--apercu) .pp-hero__texte {
        padding-block: clamp(3rem, 7cqi, 6.5rem) clamp(2rem, 4cqi, 3.5rem);
    }

    .pp-site--scinde:not(.pp-site--apercu) .pp-hero__nom {
        font-size: calc(clamp(2.6rem, 10cqi, 6rem) * var(--pp-echelle, 1));
    }

    /* Infos pratiques en une colonne de tuiles larges (la colonne de droite fait la moitié de l'écran). */
    .pp-site--scinde:not(.pp-site--apercu) .pp-essentiel {
        grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
        padding-bottom: clamp(2rem, 4cqi, 3rem);
    }

    .pp-site--scinde:not(.pp-site--apercu) .pp-essentiel .pp-tuile--adresse {
        grid-column: 1 / -1;
    }

    /* Contact seul sur sa rangée (pas d'horaires) : toute la largeur, pas une tuile étroite et un vide. */
    .pp-site--scinde:not(.pp-site--apercu) .pp-essentiel:not(:has(.pp-tuile--horaires)) .pp-tuile--contact {
        grid-column: 1 / -1;
    }

    .pp-site--scinde:not(.pp-site--apercu) .pp-section {
        padding-block: clamp(2.5rem, 4.5cqi, 4rem);
        border-top: 1px solid var(--pp-bordure);
    }
}

/* Une seule colonne (tablette, téléphone) : la photo en tête, plein cadre, puis la page. */
@container pp (max-width: 999px) {
    /* `stretch` : centré (règle de base), le texte — conteneur de taille, sans largeur propre — tombait à 0 de large. */
    .pp-site--scinde .pp-hero {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        padding-top: 0;
    }

    .pp-site--scinde .pp-hero__visuel {
        order: -1;
        width: calc(100% + 2 * clamp(1rem, 4cqi, 2.5rem));
        margin-inline: calc(-1 * clamp(1rem, 4cqi, 2.5rem));
        aspect-ratio: 4 / 3;
        max-height: 62svh;
    }

    .pp-site--scinde .pp-hero__couverture {
        border-radius: 0;
        box-shadow: none;
    }

    .pp-site--scinde .pp-hero__logo {
        bottom: -1.75rem;
        left: clamp(1rem, 4cqi, 2.5rem);
    }

    .pp-site--scinde .pp-hero__texte {
        padding-top: 1.5rem;
    }
}

/* ═════════════ Affiche ═════════════ */

.pp-site--affiche .pp-hero {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(1.5rem, 3cqi, 2.5rem);
    padding-top: clamp(1.5rem, 4cqi, 3.5rem);
}

.pp-site--affiche .pp-hero__texte {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    column-gap: clamp(1.5rem, 4cqi, 4rem);
    padding-top: clamp(1rem, 2cqi, 1.5rem);
    border-top: 2px solid var(--pp-texte);
}

.pp-site--affiche .pp-hero__texte > * {
    grid-column: 1 / -1;
}

.pp-site--affiche .pp-hero__nom {
    margin: clamp(0.5rem, 2cqi, 1.5rem) 0 clamp(1rem, 2.5cqi, 2rem);
    font-size: calc(clamp(3rem, 15.5cqi, 15rem) * var(--pp-echelle, 1));
    line-height: 0.86;
    letter-spacing: -0.05em;
    max-width: none;
}

/* Accroche à gauche, boutons à droite, sur la même ligne (ordinateur). */
.pp-site--affiche .pp-hero__accroche {
    grid-column: 1;
    margin: 0;
}

.pp-site--affiche .pp-hero__actions {
    grid-column: 2;
    grid-row: span 3;
    align-self: end;
    margin: 0;
}

.pp-site--affiche :is(.pp-statut, .pp-pastilles) {
    grid-column: 1;
}

.pp-site--affiche .pp-hero__visuel {
    aspect-ratio: 21 / 9;
    max-height: min(68svh, 640px);
    width: 100%;
}

.pp-site--affiche .pp-hero__logo {
    bottom: auto;
    left: auto;
    top: clamp(1rem, 2cqi, 1.5rem);
    right: clamp(1rem, 2cqi, 1.5rem);
}

/* Sans photo : la composition graphique en bandeau, à l'accent. */
.pp-site--affiche.pp-site--sans-photo .pp-hero__visuel {
    aspect-ratio: 21 / 6;
    border-radius: var(--pp-rayon);
    overflow: hidden;
    background: var(--pp-teinte);
}

@container pp (max-width: 760px) {
    .pp-site--affiche .pp-hero__texte {
        grid-template-columns: minmax(0, 1fr);
    }

    .pp-site--affiche :is(.pp-hero__accroche, .pp-hero__actions, .pp-statut, .pp-pastilles) {
        grid-column: 1;
        grid-row: auto;
    }

    .pp-site--affiche .pp-hero__actions {
        margin-top: 1.25rem;
    }

    .pp-site--affiche .pp-hero__nom {
        font-size: calc(clamp(2.8rem, 19cqi, 6rem) * var(--pp-echelle, 1));
    }

    .pp-site--affiche .pp-hero__visuel {
        aspect-ratio: 4 / 3;
    }
}

/* ═════════════ Matière du fond ═════════════ */

.pp-site--matiere-grain {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .5 0 0 0 0 .5 0 0 0 0 .5 0 0 0 .16 0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23g)'/%3E%3C/svg%3E");
    background-size: 160px 160px;
}

.pp-site--matiere-aurore {
    background:
        radial-gradient(55% 60% at 8% 0%, color-mix(in srgb, var(--pp-accent) 26%, transparent), transparent 70%) top / 100% 140svh no-repeat,
        radial-gradient(45% 50% at 100% 35%, color-mix(in srgb, var(--pp-accent) 14%, transparent), transparent 70%) top / 100% 140svh no-repeat,
        var(--pp-fond);
}

/* Tuiles et cartes un peu translucides sur l'aurore et le grain : la matière transparaît. */
.pp-site:is(.pp-site--matiere-grain, .pp-site--matiere-aurore) {
    --pp-surface: color-mix(in srgb, var(--pp-texte) 6%, transparent);
}

/* Affiche : le nom d'abord, même sur téléphone et tablette (les autres gabarits y montrent la photo en tête). */
@container pp (max-width: 860px) {
    .pp-site--affiche .pp-hero__visuel {
        order: 2;
    }
}

/*
mini-site-mobile.css

QUOI : La version TÉLÉPHONE du mini-site d'une page Pro, pensée comme une appli et non comme la page
       d'ordinateur rétrécie : barre du pro sur une ligne, onglets de sections collants (sous l'en-tête du
       site), visuel bord à bord, un seul gros bouton suivi de raccourcis ronds (appeler, itinéraire, site,
       partager…), infos pratiques compactes, actualités / photos / agenda en carrousels à faire glisser.

COMMENT : Sous `@container pp (max-width: 600px)` ; barre du pro, onglets et décor de la Vitrine dès 860 px
          (tablette). Requêtes du CONTENEUR `.pp-site` (cf.
          mini-site.css), pas de la fenêtre : l'aperçu « Téléphone » de « Personnaliser » affiche donc
          exactement cette version. Couleurs : variables `--pp-*` uniquement. Les carrousels sont du
          défilement natif (`scroll-snap`), sans script ; on voit le bord de la carte suivante, ce qui invite à
          glisser. Le JS (`page-pro.js`) pose `--pp-entete` (hauteur de l'en-tête collant du site) et marque
          l'onglet actif (`aria-current`).

OÙ : Importé par app.imports.css en dernier des fichiers du mini-site. Template `_mini_site.html.twig`.

POURQUOI : Demande d'Ellie (22/10/2026) : « vraiment un site mobile et un site PC », irréprochable sur tous
           les formats.
*/

@container pp (max-width: 860px) {
    /* ── Onglets collants (téléphone et tablette ; sur ordinateur, les liens sont dans la barre) ── */

    /* Barre du pro en bandeau plein (sur tablette aussi : la barre « en verre » de la Vitrine chevaucherait
       les onglets). */
    .pp-site .pp-nav,
    .pp-site--vitrine.pp-site--photo .pp-nav {
        position: static;
        width: auto;
        gap: 0.75rem;
        padding: 0.65rem clamp(1rem, 4cqi, 2.5rem);
        transform: none;
        background: var(--pp-fond);
        border: 0;
        border-radius: 0;
        color: var(--pp-texte);
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
    }

    .pp-onglets {
        position: sticky;
        top: var(--pp-entete, 0px);
        z-index: 20;
        display: flex;
        gap: 0.4rem;
        padding: 0.5rem clamp(1rem, 4cqi, 2.5rem);
        overflow-x: auto;
        overscroll-behavior-x: contain;
        background: color-mix(in srgb, var(--pp-fond) 92%, transparent);
        border-block: 1px solid var(--pp-bordure);
        font-family: var(--font-base, system-ui, sans-serif);
        scrollbar-width: none;
        -webkit-backdrop-filter: blur(14px) saturate(150%);
        backdrop-filter: blur(14px) saturate(150%);
    }

    .pp-onglets::-webkit-scrollbar {
        display: none;
    }

    .pp-onglets a {
        display: inline-flex;
        flex: 0 0 auto;
        align-items: center;
        min-height: 40px;
        padding: 0 1rem;
        background: var(--pp-surface);
        border: 1px solid var(--pp-bordure);
        border-radius: 999px;
        color: var(--pp-texte);
        font-size: 0.9rem;
        font-weight: 700;
        text-decoration: none;
        white-space: nowrap;
    }

    .pp-onglets a[aria-current] {
        background: var(--pp-accent);
        border-color: var(--pp-accent);
        color: var(--pp-sur-accent);
    }

    /* Une ancre atteinte depuis un onglet se pose sous l'en-tête et les onglets, pas dessous. */
    .pp-site [id] {
        scroll-margin-top: calc(var(--pp-entete, 0px) + 4.25rem);
    }

    /* Vitrine sans photo : seul le disque reste, en haut, loin du texte et des raccourcis. */
    .pp-site--vitrine.pp-site--sans-photo :is(.pp-composition__lettre, .pp-composition__carre) {
        display: none;
    }

    .pp-site--vitrine.pp-site--sans-photo .pp-hero__visuel {
        overflow: hidden;
    }

    .pp-site--vitrine.pp-site--sans-photo .pp-composition {
        left: 40%;
        opacity: 0.5;
    }

    .pp-site--vitrine.pp-site--sans-photo .pp-composition__disque {
        top: -15%;
        width: 90%;
    }
}

/* Très petits écrans (320-360 px) : le statut « Ouvert · jusqu'à 19 h 30 » tient sur une ligne. */
@container pp (max-width: 360px) {
    .pp-site .pp-statut {
        padding-inline: 0.65rem 0.8rem;
        font-size: 0.86rem;
    }
}

@container pp (max-width: 600px) {
    .pp-nav__logo {
        flex: 0 0 auto;
        width: 2rem;
        height: 2rem;
    }

    .pp-nav__marque {
        font-size: 1rem;
    }

    /* ── Haut de page ── */

    .pp-site .pp-hero {
        gap: 1.25rem;
        padding: 0 1rem 1.75rem;
    }

    .pp-site .pp-hero__accroche {
        margin-top: 0.9rem;
        font-size: 1.08rem;
    }

    .pp-site .pp-pastilles {
        margin-top: 1rem;
    }

    /* Classique : photo bord à bord, comme l'en-tête d'une fiche d'appli. */
    .pp-site--classique.pp-site--photo .pp-hero__visuel {
        width: calc(100% + 2rem);
        height: auto;
        margin-inline: -1rem;
        /* 3:2 : le titre remonte dans le premier écran. */
        aspect-ratio: 3 / 2;
    }

    .pp-site--classique.pp-site--photo .pp-hero__couverture {
        border-radius: 0;
        box-shadow: none;
    }

    /* Logo : posé dans le coin du visuel, jamais rogné par le bord de l'écran. */
    .pp-site .pp-hero__logo {
        top: auto;
        right: auto;
        bottom: 0.75rem;
        left: 0.75rem;
        width: 64px;
        height: 64px;
        padding: 6px;
    }

    /* Image propre au téléphone (aperçu ; sur la page publique, `<picture>` s'en charge). */
    .pp-hero__couverture--pc {
        display: none;
    }

    .pp-hero__couverture--mobile {
        display: block;
    }

    /* Vitrine : la photo occupe l'écran sous la barre et les onglets. */
    .pp-site--vitrine .pp-hero {
        min-height: calc(100svh - var(--pp-entete, 64px) - 7.5rem);
        padding: 2.5rem 1rem 2rem;
    }

    .pp-site--vitrine .pp-hero__logo {
        top: 1rem;
        bottom: auto;
        left: auto;
        right: 1rem;
    }

    .pp-site--vitrine .pp-essentiel {
        margin-top: 0;
        padding-top: 1rem;
    }

    /* Bento : la grille porte déjà la gouttière, pas de marge en double. */
    /* (`.pp-site.pp-site--bento` : doit battre `.pp-site .pp-essentiel` plus bas, sinon les tuiles d'infos
       prenaient une gouttière de plus que le haut de page — audit du 23/10/2026.) */
    .pp-site.pp-site--bento .pp-hero,
    .pp-site.pp-site--bento .pp-essentiel {
        padding: 0;
    }

    .pp-site--bento .pp-ouverture {
        padding: 0.25rem 1rem 1.5rem;
    }

    /* Éditorial : l'espacement vient des filets et marges propres au gabarit. */
    .pp-site--editorial .pp-hero {
        gap: 0;
    }

    .pp-site--editorial :is(.pp-statut, .pp-pastilles) {
        margin-top: 1rem;
    }

    /* « Partager » et « Écrire un message » sont déjà dans les raccourcis du haut (et le formulaire en bas de
       page) : la tuile Contact garde le téléphone et les réseaux, sans vide en dessous. */
    .pp-tuile--contact .pp-contact__actions {
        display: none;
    }

    /* Un seul gros bouton ; les autres actions deviennent des raccourcis ronds. */
    .pp-hero__actions {
        margin-top: 1.4rem;
    }

    .pp-hero__actions > .pp-bouton:not(:first-child) {
        display: none;
    }

    .pp-hero__actions > .pp-bouton:first-child {
        flex: 1 1 100%;
        justify-content: center;
        min-height: 52px;
        font-size: 1.05rem;
    }

    .pp-raccourcis {
        display: grid;
        /* Colonnes égales sur toute la largeur, quel que soit le nombre de raccourcis (calés à gauche, 2 ou 3
           raccourcis laissaient un vide à droite — revue design du 24/10/2026). */
        grid-auto-columns: minmax(0, 1fr);
        grid-auto-flow: column;
        gap: 0.5rem;
        margin: 1.1rem 0 0;
        padding: 0;
        list-style: none;
    }

    .pp-raccourcis :is(a, button) {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 0.4rem;
        width: 100%;
        padding: 0.25rem 0;
        background: none;
        border: 0;
        color: var(--pp-texte);
        font: 600 0.8rem/1.2 var(--font-base, system-ui, sans-serif);
        text-align: center;
        text-decoration: none;
        cursor: pointer;
    }

    .pp-raccourcis__icone {
        display: grid;
        place-items: center;
        width: 52px;
        height: 52px;
        /* Teinte d'accent légère : les cercles ressortent sur tous les fonds (le gris-bleu se perdait). */
        background: color-mix(in srgb, var(--pp-accent) 13%, var(--pp-fond));
        border: 1px solid color-mix(in srgb, var(--pp-accent) 30%, var(--pp-fond));
        border-radius: 50%;
        color: var(--pp-accent-texte);
        transition: transform 0.15s ease;
    }

    .pp-raccourcis :is(a, button):active .pp-raccourcis__icone {
        transform: scale(0.94);
    }

    .pp-raccourcis :is(a, button):focus-visible {
        outline: none;
    }

    .pp-raccourcis :is(a, button):focus-visible .pp-raccourcis__icone {
        outline: 3px solid var(--pp-accent);
        outline-offset: 2px;
    }

    .pp-site--vitrine.pp-site--photo .pp-raccourcis__icone {
        background: rgba(6, 8, 12, 0.45);
        border-color: rgba(255, 255, 255, 0.35);
        color: #fff;
        -webkit-backdrop-filter: blur(10px);
        backdrop-filter: blur(10px);
    }

    /* ── Infos pratiques ── */

    .pp-site .pp-essentiel {
        gap: 0.75rem;
        padding: 0 1rem 1.5rem;
    }

    .pp-carte {
        min-height: 190px;
    }

    /* ── Sections ── */

    .pp-site .pp-section {
        padding: 1.75rem 1rem;
    }

    .pp-site .pp-section__tete {
        margin-bottom: 1rem;
    }

    .pp-site .pp-section__titre {
        font-size: clamp(1.75rem, 8cqi, 2.2rem);
    }

    /* Carrousels : actualités, photos, agenda — on glisse du pouce, la carte suivante dépasse. */
    .pp-site :is(.pp-actus, .pp-galerie, .pp-agenda) {
        display: flex;
        gap: 0.75rem;
        margin-inline: -1rem;
        padding: 0 1rem 0.5rem;
        overflow-x: auto;
        scroll-padding-inline: 1rem;
        scroll-snap-type: x mandatory;
        scrollbar-width: none;
        overscroll-behavior-x: contain;
    }

    .pp-site :is(.pp-actus, .pp-galerie, .pp-agenda)::-webkit-scrollbar {
        display: none;
    }

    .pp-site .pp-actus > *,
    .pp-site .pp-agenda > * {
        flex: 0 0 min(84%, 340px);
        scroll-snap-align: start;
    }

    /* Sorties en carrousel : contenu centré dans la carte (vide sous un titre court sinon). */
    .pp-site .pp-agenda__item {
        align-items: center;
    }

    /* Une seule carte : pas de carrousel, elle prend toute la largeur au lieu de laisser un vide à droite. */
    .pp-site .pp-actus > :only-child,
    .pp-site .pp-agenda > :only-child {
        flex-basis: 100%;
    }

    .pp-site .pp-galerie > li,
    .pp-site .pp-galerie > li:first-child {
        flex: 0 0 82%;
        scroll-snap-align: start;
    }

    .pp-site .pp-galerie:is(.pp-galerie--1, .pp-galerie--2) > li {
        flex-basis: 100%;
    }

    .pp-galerie__photo img {
        aspect-ratio: 4 / 5;
    }

    .pp-site .pp-apropos__texte {
        font-size: 1.08rem;
    }

    .pp-site .pp-contact .pp-tuile {
        padding: 1.25rem;
    }

    .pp-site .pp-pied {
        flex-direction: column;
        align-items: flex-start;
        padding: 1.5rem 1rem;
    }

    /* ── Propreté (revue design du 24/10/2026) ── */

    /* Formulaire replié : le bouton « Écrire un message » seul, sans carte autour. */
    .pp-site .pp-contact .pp-tuile:has(.entreprise-contact__pli:not([open])) {
        padding: 0;
        background: none;
        border: 0;
        box-shadow: none;
    }

    /* Un seul « Appeler » en haut : le gros bouton du haut de page (puis la barre du bas une fois dépassé). */
    .pp-nav .pp-bouton {
        display: none;
    }

    /* Pastilles de thème : la catégorie est déjà dans le surtitre ; une rangée de moins sous le statut. */
    .pp-site .pp-pastilles {
        display: none;
    }

    /* Une seule surface pour les tuiles d'infos (le bleu-gris des horaires à côté du beige des autres faisait sale). */
    .pp-site .pp-tuile--horaires {
        background: var(--pp-surface);
        border-color: var(--pp-bordure);
    }

    /* Carte : on zoome aux doigts ; les boutons +/− et une attribution en gros texte encombraient la vignette. */
    .pp-carte .leaflet-control-zoom {
        display: none;
    }

    .pp-carte .leaflet-control-attribution {
        font-size: 10px;
    }

    /* Actualité sans photo : le motif de remplissage reste un bandeau, pas un grand pavé vide. */
    .pp-site .actualite-card__media:has(> .event-cover-abstract) {
        aspect-ratio: 16 / 9;
    }

    /* « Tous les professionnels · Boulogne-sur-Mer → » : texte qui coule, flèche collée au dernier mot. */
    .pp-site .entreprise__retour {
        display: block;
        text-wrap: pretty;
    }
}

/*
mini-site-mobile-gabarits.css

QUOI : L'identité propre de chaque gabarit sur TÉLÉPHONE, pour que les quatre ne se ressemblent plus une fois
       passés en une colonne :
       - Classique : la base de mini-site-mobile.css (fiche d'appli, carrousels à faire glisser), rien en plus ;
       - Vitrine : immersive — photos et titres en grand, carrousel de photos presque plein écran ;
       - Bento : tout en tuiles — raccourcis en tuiles, photos et sorties en mosaïque, actualités empilées,
         questions en cartes ; aucun carrousel ;
       - Éditorial : magazine — rubriques numérotées, actualités en sommaire (vignette + titre), sorties et
         raccourcis au trait, planche de photos à angles vifs.

COMMENT : Sous `@container pp (max-width: 600px)` (même seuil que mini-site-mobile.css, donc aussi dans
          l'aperçu « Téléphone » de « Personnaliser »). Importé APRÈS mini-site-mobile.css : ces règles
          remplacent la base téléphone pour un gabarit. Couleurs : variables `--pp-*` uniquement.

OÙ : app.imports.css. Template `entreprise/_partials/_mini_site.html.twig`.

POURQUOI : Demande d'Ellie (24/10/2026) : « je veux que la version mobile soit parfaite, s'il faut
           différencier les designs pour avoir une meilleure version mobile, allons-y ».
*/

@container pp (max-width: 600px) {
    /* ── Vitrine : immersive ── */

    /* Sur téléphone tout le texte est sur la photo : voile plus dense, même sur une image très chargée. */
    .pp-site--vitrine.pp-site--photo .pp-hero__visuel::after {
        background: linear-gradient(to top, rgba(6, 8, 12, 0.94) 0%, rgba(6, 8, 12, 0.84) 50%, rgba(6, 8, 12, 0.6) 100%);
    }

    .pp-site--vitrine .pp-section__titre {
        font-size: clamp(2rem, 10cqi, 2.6rem);
    }

    /* Tuiles d'infos : surface unique et ombre discrète (l'ombre large et l'aplat teinté des horaires
       alourdissaient la page). */
    .pp-site--vitrine .pp-essentiel .pp-tuile,
    .pp-site--vitrine .pp-essentiel .pp-tuile--horaires {
        background: var(--pp-surface);
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
    }

    .pp-site--vitrine .pp-galerie > li,
    .pp-site--vitrine .pp-galerie > li:first-child {
        flex-basis: 90%;
    }

    .pp-site--vitrine .pp-galerie:is(.pp-galerie--1) > li {
        flex-basis: 100%;
    }

    .pp-site--vitrine .pp-galerie__photo img {
        aspect-ratio: 3 / 4;
    }

    /* ── Bento : tout en tuiles ── */

    /* Raccourcis : la rangée de colonnes égales de la base, chaque raccourci devient une tuile. */
    .pp-site--bento .pp-raccourcis :is(a, button) {
        justify-content: center;
        min-height: 78px;
        padding: 0.7rem 0.25rem;
        background: var(--pp-surface);
        border: 1px solid var(--pp-bordure);
        border-radius: var(--pp-rayon);
    }

    .pp-site--bento .pp-raccourcis__icone {
        width: 30px;
        height: 30px;
        background: none;
        border: 0;
    }

    .pp-site--bento .pp-raccourcis :is(a, button):active {
        transform: scale(0.96);
    }

    .pp-site--bento .pp-raccourcis :is(a, button):active .pp-raccourcis__icone {
        transform: none;
    }

    .pp-site--bento .pp-raccourcis :is(a, button):focus-visible {
        outline: 3px solid var(--pp-accent);
        outline-offset: 2px;
    }

    .pp-site--bento .pp-raccourcis :is(a, button):focus-visible .pp-raccourcis__icone {
        outline: none;
    }

    /* Plus de carrousels : actualités empilées, photos et sorties en mosaïque de deux colonnes. */
    .pp-site--bento :is(.pp-actus, .pp-galerie, .pp-agenda) {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        gap: 0.75rem;
        margin-inline: 0;
        padding: 0;
        overflow: visible;
        scroll-snap-type: none;
    }

    .pp-site--bento :is(.pp-galerie, .pp-agenda) {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .pp-site--bento :is(.pp-actus, .pp-galerie, .pp-agenda) > *,
    .pp-site--bento .pp-galerie > li:first-child {
        flex: none;
        min-width: 0;
    }

    /* Mosaïque : la première photo en grand ; la dernière s'élargit plutôt que de rester seule en bout de rang. */
    .pp-site--bento .pp-galerie > li:first-child,
    .pp-site--bento .pp-galerie > li:last-child:nth-child(even),
    .pp-site--bento .pp-agenda > :last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }

    .pp-site--bento .pp-galerie__photo img {
        aspect-ratio: 1;
    }

    .pp-site--bento .pp-galerie > li:first-child .pp-galerie__photo img,
    .pp-site--bento .pp-galerie > li:last-child:nth-child(even) .pp-galerie__photo img {
        aspect-ratio: 4 / 3;
    }

    /* Sortie en tuile : la date en haut, le titre dessous. */
    .pp-site--bento .pp-agenda__item {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.75rem;
    }


    /* Actualités empilées : bandeau bas pour le visuel de remplissage (deux cartes tenaient plus d'un écran). */
    .pp-site--bento .actualite-card__media:has(> .event-cover-abstract) {
        aspect-ratio: 2 / 1;
    }

    /* Sortie seule en bout de mosaïque (pleine largeur) : date à gauche, titre à droite. */
    .pp-site--bento .pp-agenda > :last-child:nth-child(odd) {
        flex-direction: row;
        align-items: center;
        gap: 1rem;
    }

    /* Questions : chacune dans sa carte. */
    .pp-site--bento .pp-faq__liste {
        display: grid;
        gap: 0.5rem;
        border-top: 0;
    }

    .pp-site--bento .pp-faq__item {
        padding-inline: 1rem;
        background: var(--pp-surface);
        border: 1px solid var(--pp-bordure);
        border-radius: var(--pp-rayon);
    }

    /* ── Éditorial : magazine ── */

    /* Rubriques numérotées, comme le sommaire d'un journal : « 01 — Cette semaine » (numéro posé par le template). */
    .pp-site--editorial .pp-surtitre__num {
        display: inline;
    }

    /* La une : bloc d'identité centré, photo « à la une » juste sous le titre, puis chapeau, statut, actions. */
    .pp-site--editorial .pp-hero > * ,
    .pp-site--editorial .pp-hero__texte > * {
        order: 2;
    }

    .pp-site--editorial .pp-hero .pp-surtitre,
    .pp-site--editorial .pp-hero__nom {
        order: 0;
    }

    .pp-site--editorial .pp-hero__visuel {
        order: 1;
        overflow: hidden;
        border-radius: 0;
        margin: 0 0 1.25rem;
        aspect-ratio: 4 / 3;
    }

    /* Photo à la une : angles vifs, comme dans un journal. */
    .pp-site--editorial .pp-hero__couverture {
        border-radius: 0;
    }

    .pp-site--editorial :is(.pp-hero__accroche, .pp-statut) {
        justify-self: center;
        text-align: center;
    }

    /* Raccourcis au trait, sans aplat. */
    .pp-site--editorial .pp-raccourcis__icone {
        background: none;
        border-color: var(--pp-texte);
        color: var(--pp-texte);
    }

    /* Actualités en sommaire : vignette à gauche, titre et texte à droite, séparées par des filets. */
    .pp-site--editorial :is(.pp-actus, .pp-agenda) {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        gap: 0;
        margin-inline: 0;
        padding: 0;
        overflow: visible;
        scroll-snap-type: none;
    }

    .pp-site--editorial :is(.pp-actus, .pp-agenda) > * {
        flex: none;
        min-width: 0;
    }

    .pp-site--editorial .pp-actus .actualite-card {
        display: grid;
        grid-template-columns: 8.5rem minmax(0, 1fr);
        align-items: start;
        gap: 1rem;
        padding: 1rem 0;
        background: none;
        border: 0;
        border-bottom: 1px solid var(--pp-bordure);
        border-radius: 0;
        box-shadow: none;
    }

    .pp-site--editorial .pp-actus .actualite-card:first-child {
        padding-top: 0;
    }

    .pp-site--editorial .pp-actus .actualite-card__media {
        border-radius: 0;
    }

    .pp-site--editorial .pp-actus .actualite-card__body {
        padding: 0;
    }

    /* Vignette trop petite pour deux pastilles : sur une actu boostée, seule « Sponsorisé » reste. */
    .pp-site--editorial .pp-actus .actualite-card--boostee .actualite-card__fin {
        display: none;
    }

    .pp-site--editorial .pp-actus .actualite-card__media {
        aspect-ratio: 4 / 3;
    }

    /* Dates des sorties au trait (« 31 OCT. »), pas en pavés de couleur. */
    .pp-site--editorial .pp-agenda__date {
        width: 3.25rem;
        height: auto;
        padding-right: 0.75rem;
        background: none;
        border-right: 1px solid var(--pp-bordure);
        border-radius: 0;
        color: var(--pp-accent-texte);
    }

    /* Sorties : liste à filets, sans cartes. */
    .pp-site--editorial .pp-agenda__item {
        padding: 0.9rem 0;
        background: none;
        border: 0;
        border-bottom: 1px solid var(--pp-bordure);
        border-radius: 0;
    }

    .pp-site--editorial .pp-agenda__item:first-child {
        padding-top: 0;
    }

    /* Jour en cours : liseré droit, aligné sur la gouttière (l'arrondi le faisait mordre en arc). */
    .pp-site--editorial .pp-horaires__ligne--auj {
        border-radius: 0;
    }

    /* Pas de filet fin sous les infos pratiques juste avant le filet épais de la première rubrique. */
    .pp-site--editorial .pp-essentiel {
        border-bottom: 0;
    }

    /* Filets de rubrique moins lourds que les titres ; pas de double filet après la dernière question. */
    .pp-site--editorial .pp-section__tete {
        border-top-width: 3px;
    }

    .pp-site--editorial .pp-faq__item:last-child {
        border-bottom: 0;
    }

    /* Photos : planche-contact à angles vifs, la première en pleine largeur. */
    .pp-site--editorial .pp-galerie {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 0.35rem;
        margin-inline: 0;
        padding: 0;
        overflow: visible;
        scroll-snap-type: none;
    }

    .pp-site--editorial .pp-galerie > li,
    .pp-site--editorial .pp-galerie > li:first-child {
        flex: none;
        min-width: 0;
    }

    .pp-site--editorial .pp-galerie > li:first-child,
    .pp-site--editorial .pp-galerie > li:last-child:nth-child(even) {
        grid-column: 1 / -1;
    }

    .pp-site--editorial .pp-galerie__photo,
    .pp-site--editorial .pp-galerie__photo img {
        border-radius: 0;
    }

    .pp-site--editorial .pp-galerie__photo img {
        aspect-ratio: 1;
    }

    .pp-site--editorial .pp-galerie > li:first-child .pp-galerie__photo img,
    .pp-site--editorial .pp-galerie > li:last-child:nth-child(even) .pp-galerie__photo img {
        aspect-ratio: 3 / 2;
    }
}

/*
espace-pro.css

QUOI : Espace pro « Ma page Pro » et ses formulaires (« Nouvelle actualité », « Personnaliser ») : touches
       propres à l'écran posées sur les composants de « Mon compte » — bannière aux couleurs de la page,
       sélecteur de page, pastilles d'état, aperçu d'apparence, règles ; champs supplémentaires des
       formulaires (url, date, fichier, texte long, couleur), cases de destination en cartes, aperçu à droite.

COMMENT : La mise en page vient de `pages/profile.css` (`profile-hero`, `profile-stats`, `profile-grid`,
          `profile-card`, `profile-form`, `contributor-event`) chargé par les trois templates : on reste dans la
          DA d'Opalenews. Seules la bannière (`--f` fond, `--a` accent) et l'aperçu montrent les couleurs du pro.
          Les destinations restent de vraies cases à cocher (un interrupteur laisserait croire à un effet
          immédiat, alors que rien n'est publié avant « Publier ») ; l'état coché est porté par `:has()`.

OÙ : Importé par app.imports.css après mini-site-sections.css. Templates `pagepro/*`.
*/

/* ═══ Tableau de bord ═══ */

.pp-espace__choix {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: var(--space-md);
}

.pp-espace__choix-lien {
    padding: 0.45rem 1rem;
    background: var(--c-surface);
    border: 1px solid var(--c-bordure);
    border-radius: 999px;
    color: var(--c-texte);
    font-weight: 600;
    text-decoration: none;
}

.pp-espace__choix-lien.is-active {
    background: var(--c-action);
    border-color: var(--c-mer);
    color: #fff;
}

/* Bannière : dégradé du fond de la page vers sa couleur d'accent (sinon la bannière marine de « Mon compte »). */
.pp-espace__cover[style] {
    background:
        radial-gradient(circle at 88% -10%, var(--a) 0%, transparent 52%),
        linear-gradient(120deg, var(--f) 0%, color-mix(in srgb, var(--f) 70%, var(--a)) 100%);
}

.pp-espace__avatar {
    font-family: var(--font-display);
    font-weight: 800;
}

.pp-espace__badge--active {
    color: #2e9d57;
    background-color: color-mix(in srgb, #2e9d57 16%, transparent);
}

.profile-stat dd small {
    font-size: 0.6em;
    font-weight: 600;
    color: var(--c-texte-doux);
}

.pp-espace__invite {
    margin: 0;
    color: var(--c-texte-doux);
}

/* Liste des actualités : `contributor-event` de « Mon compte » + états propres. */
.pp-espace .contributor-event__media {
    position: relative;
}

.pp-espace__statut--en-cours { background-color: #1e5023; }
.pp-espace__statut--a-venir { background-color: var(--c-mer); }
.pp-espace__statut--terminee { background-color: #5a6b7a; }

.pp-espace__actu--terminee {
    opacity: 0.65;
}

/* Apparence : mini-aperçu aux couleurs de la page + récapitulatif des réglages. */
.pp-espace__apparence {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: center;
    gap: var(--space-md);
}

.pp-espace__nuancier {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    min-height: 8.5rem;
    padding: 1rem 1.1rem;
    overflow: hidden;
    border: 1px solid var(--c-bordure);
}

.pp-espace__nuancier-disque {
    position: absolute;
    top: -2.5rem;
    right: -1.5rem;
    width: 7rem;
    height: 7rem;
    border-radius: 50%;
}

.pp-espace__nuancier-nom {
    position: relative;
    font-size: 1.35rem;
    font-weight: 800;
    line-height: 1.1;
}

.pp-espace__nuancier-bouton {
    align-self: flex-start;
    padding: 0.35rem 0.9rem;
    border-radius: 999px;
    font-family: var(--font-base);
    font-size: 0.8rem;
    font-weight: 700;
}

.pp-espace__reglages {
    display: grid;
    gap: 0.5rem;
    margin: 0;
}

.pp-espace__reglages div {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding-bottom: 0.45rem;
    border-bottom: 1px solid var(--c-bordure);
}

.pp-espace__reglages dt {
    color: var(--c-texte-doux);
}

.pp-espace__reglages dd {
    margin: 0;
    font-weight: 600;
    text-align: right;
}

.pp-espace__regles {
    display: grid;
    gap: 0.6rem;
    margin: 0;
    padding-left: 1.1rem;
    color: var(--c-texte);
    line-height: 1.5;
}

@media (max-width: 640px) {
    .pp-espace__apparence {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* ═══ Formulaires (« Nouvelle actualité », « Personnaliser ») ═══ */

.pp-espace .page-hero {
    margin-bottom: var(--space-lg);
}

.pp-form-layout {
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    align-items: start;
    gap: clamp(1.25rem, 3vw, 2.5rem);
}

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

.pagepro-form .profile-card {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}

/* `profile-form` ne style que texte/e-mail/mot de passe : on prolonge aux autres champs, à l'identique. */
.profile-form input[type="url"],
.profile-form input[type="tel"],
.profile-form input[type="date"],
.profile-form input[type="file"],
.profile-form textarea {
    width: 100%;
    min-height: 48px;
    padding: 0.7rem 0.85rem;
    background-color: var(--c-surface-2);
    border: 1.5px solid var(--c-bordure-champ);
    border-radius: var(--radius-md);
    color: var(--c-texte);
    font: inherit;
    font-size: var(--fs-base);
    transition: border-color var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out);
}

.profile-form textarea:hover {
    border-color: var(--c-mer-clair);
}

.profile-form textarea:focus {
    outline: none;
    border-color: var(--c-mer);
    box-shadow: 0 0 0 4px var(--c-focus);
}

.profile-form .form-help,
.profile-form .help-text {
    margin-top: 0.35rem;
    font-size: var(--fs-sm);
    color: var(--c-texte-doux);
}

.pagepro-form__dates {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: 1rem;
}

.pagepro-form__apercu-photo {
    max-width: 200px;
    border-radius: var(--radius-md);
}

/* Cases de destination en cartes cliquables (la case native reste visible et focusable). */
.pagepro-form .pp-dest {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: start;
    gap: 0.85rem;
    margin: 0;
    padding: 1rem 1.1rem;
    background: var(--c-surface-2);
    border: 2px solid transparent;
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s;
}

.pp-dest:hover {
    border-color: var(--c-bordure);
}

.pp-dest:has(input:checked) {
    background: color-mix(in srgb, var(--c-mer) 10%, var(--c-surface));
    border-color: var(--c-mer);
}

.pp-dest:has(input:focus-visible) {
    box-shadow: 0 0 0 4px var(--c-focus);
}

.pp-dest input {
    width: 1.25rem;
    height: 1.25rem;
    margin: 0.15rem 0 0;
    accent-color: var(--c-mer);
}

.pp-dest__titre {
    display: block;
    font-weight: 800;
    color: var(--c-marine);
}

.pp-dest__aide {
    display: block;
    margin-top: 0.2rem;
    font-size: 0.88rem;
    font-weight: 400;
    color: var(--c-texte-doux);
}

.pp-dest__prix {
    padding: 0.2rem 0.65rem;
    border-radius: 999px;
    background: var(--c-surface);
    font-size: 0.75rem;
    font-weight: 700;
    white-space: nowrap;
    color: var(--c-texte-doux);
}

.pp-dest--boost:has(input:checked) {
    background: color-mix(in srgb, var(--c-corail) 10%, var(--c-surface));
    border-color: var(--c-corail);
}

.pp-dest--boost .pp-dest__prix {
    background: var(--c-corail-action);
    color: #fff;
}

.pagepro-form__envoi {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
}

.pp-apercu {
    position: sticky;
    top: 96px;
}

.pp-apercu__label {
    margin: 0 0 0.6rem;
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--c-texte-doux);
}

.pp-apercu__note {
    margin-top: 0.75rem;
    font-size: 0.85rem;
    color: var(--c-texte-doux);
}

@media (max-width: 900px) {
    .pp-form-layout {
        grid-template-columns: minmax(0, 1fr);
    }

    .pp-apercu {
        position: static;
    }
}

/* Bandeau « Confirmez votre adresse e-mail » de « Mon compte » (styles/pages/profile.css chargé à côté). */
.compte-verification {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem 1rem;
    margin-bottom: var(--space-md);
    padding: 0.9rem 1.1rem;
    background: color-mix(in srgb, var(--c-corail) 10%, var(--c-surface));
    border: 1px solid color-mix(in srgb, var(--c-corail) 45%, var(--c-bordure));
    border-radius: var(--radius-lg);
    color: var(--c-texte);
}

.compte-verification__texte {
    flex: 1 1 22rem;
}

.compte-verification form {
    margin: 0;
}

/* QR code de la page Pro (« Ma page Pro ») : fond blanc imposé, un QR code doit rester sombre sur clair. */
.pp-espace__qrcode {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1.25rem;
}

.pp-espace__qrcode img {
    flex: none;
    padding: 0.5rem;
    background: #fff;
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-lg);
}

.pp-espace__qrcode-texte {
    flex: 1 1 16rem;
}

.pp-espace__qrcode-texte p {
    margin: 0 0 0.85rem;
    color: var(--c-texte-doux);
}

/* Page « Ce n'est pas la bonne adresse ? » : honeypot hors écran (même règle que les formulaires de la fiche
   entreprise — laissé dans le flux, un `display: none` est ce que certains robots détectent). */
.pp-correction .honeypot-field {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/*
espace-pro-stats.css

QUOI : Encart « Statistiques » de « Ma page Pro » : deux grands chiffres (vues, clics) avec leur tendance, et
       l'histogramme des vues jour par jour sur 30 jours.

COMMENT : Tokens du site (`--c-*`) : clair et sombre suivent. Histogramme en pur CSS : chaque barre reçoit sa
          hauteur en `--h` (pourcentage du maximum), posée par le gabarit. Pas d'animation imposée.

OÙ : Importé par app.imports.css. Gabarit `pagepro/_stats.html.twig`.
*/

.pp-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
    gap: 0.75rem;
}

.pp-stats__chiffre {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 1rem 1.1rem;
    background: var(--c-surface-2);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-md, 10px);
}

.pp-stats__valeur {
    font-family: var(--font-display);
    font-size: 2.2rem;
    font-weight: 800;
    line-height: 1;
    color: var(--c-marine);
}

.pp-stats__libelle {
    color: var(--c-texte-doux);
    font-size: 0.9rem;
}

.pp-stats__tendance {
    align-self: flex-start;
    margin-top: 0.35rem;
    padding: 0.1rem 0.55rem;
    border-radius: 999px;
    background: color-mix(in srgb, #2e9d57 18%, transparent);
    color: var(--c-texte);
    font-size: 0.78rem;
    font-weight: 700;
}

.pp-stats__tendance--baisse {
    background: color-mix(in srgb, var(--c-corail) 20%, transparent);
}

.pp-stats__tendance--neutre {
    background: color-mix(in srgb, var(--c-mer) 16%, transparent);
}

.pp-stats__graphe {
    display: flex;
    align-items: flex-end;
    gap: 3px;
    height: 7rem;
    margin-top: 1.25rem;
    padding: 0.5rem 0.25rem 0;
    border-bottom: 1px solid var(--c-bordure);
}

.pp-stats__barre {
    flex: 1;
    min-height: 3px;
    height: var(--h);
    border-radius: 3px 3px 0 0;
    background: var(--c-mer);
}

.pp-stats__barre--vide {
    background: var(--c-bordure);
}

.pp-stats__barre:hover {
    background: var(--c-corail);
}

.pp-stats__axe {
    display: flex;
    justify-content: space-between;
    margin-top: 0.35rem;
    font-size: 0.75rem;
    color: var(--c-texte-doux);
}

.pp-stats__vide {
    margin: 1rem 0 0;
    color: var(--c-texte-doux);
}

/*
personnaliser.css

QUOI : Écran « Personnaliser ma page » : nuanciers de thèmes, sélecteurs de couleur, cartes de choix (police,
       angles) et aperçu du mini-site dans un cadre de navigateur.

COMMENT : Les nuanciers lisent `--a` (accent) et `--f` (fond) posés en ligne depuis les constantes de
          `ThemePagePro`. Les choix restent de vrais boutons radio (clavier, lecteur d'écran), l'état coché
          porté par `:has(input:checked)`. L'aperçu est réduit par `zoom` (la mise en page reste celle du
          bureau) et rendu inerte (`pointer-events: none`) : on regarde, on ne clique pas.

OÙ : Importé par app.imports.css après espace-pro.css. Template `pagepro/personnaliser.html.twig`.
*/

.pp-perso__layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    align-items: start;
    gap: clamp(1.25rem, 3vw, 2.5rem);
}

.pp-perso__libelle {
    margin: 0.25rem 0 0;
    font-weight: 700;
    font-size: var(--fs-sm);
    color: var(--c-texte);
}

/* Thèmes : nuanciers cliquables. */
.pp-themes {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 0.75rem;
}

.pagepro-form .pp-theme {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin: 0;
    padding: 0.6rem;
    background: var(--c-surface-2);
    border: 2px solid transparent;
    border-radius: var(--radius-lg);
    cursor: pointer;
    font-weight: 600;
    transition: border-color 0.2s;
}

.pp-theme input,
.pp-choix__carte input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.pp-theme:has(input:checked),
.pp-choix__carte:has(input:checked) {
    border-color: var(--c-mer);
}

.pp-theme:has(input:focus-visible),
.pp-choix__carte:has(input:focus-visible) {
    box-shadow: 0 0 0 4px var(--c-focus);
}

.pp-theme__nuancier {
    display: block;
    position: relative;
    height: 64px;
    overflow: hidden;
    background: var(--f);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-md);
}

.pp-theme__nuancier i {
    position: absolute;
    right: -12px;
    bottom: -18px;
    width: 64px;
    height: 64px;
    background: var(--a);
    border-radius: 50%;
}

.pp-theme__nom {
    font-size: 0.85rem;
    color: var(--c-marine);
}

/* Couleurs libres. */
.pp-couleurs {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 1rem;
}

.pagepro-form input[type="color"] {
    width: 100%;
    height: 3rem;
    padding: 0.25rem;
    background: var(--c-surface-2);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-md);
    cursor: pointer;
}

/* Police et angles : cartes de choix. */
.pp-choix {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
    gap: 0.75rem;
}

.pagepro-form .pp-choix__carte {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    margin: 0;
    padding: 0.9rem 0.5rem;
    background: var(--c-surface-2);
    border: 2px solid transparent;
    border-radius: var(--radius-lg);
    cursor: pointer;
    font-size: 0.85rem;
    font-weight: 600;
}

.pp-choix__exemple {
    font-size: 2rem;
    font-weight: 800;
    line-height: 1;
    color: var(--c-marine);
}

.pp-choix__forme {
    display: block;
    width: 2.75rem;
    height: 2rem;
    background: var(--c-mer);
}

/* Aperçu dans un cadre de navigateur. */
.pp-perso__apercu {
    position: sticky;
    top: 96px;
}

.pp-navigateur {
    overflow: hidden;
    background: var(--c-surface);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
}

.pp-navigateur__barre {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 0.6rem 0.9rem;
    background: var(--c-surface-2);
    border-bottom: 1px solid var(--c-bordure);
}

.pp-navigateur__barre i {
    width: 10px;
    height: 10px;
    background: var(--c-bordure);
    border-radius: 50%;
}

.pp-navigateur__barre span {
    flex: 1;
    margin-left: 0.75rem;
    padding: 0.2rem 0.75rem;
    overflow: hidden;
    background: var(--c-surface);
    border-radius: 999px;
    font-size: 0.75rem;
    color: var(--c-texte-doux);
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pp-navigateur__ecran {
    max-height: 72vh;
    overflow-y: auto;
}

.pp-site--apercu {
    zoom: 0.5;
    pointer-events: none;
}

@media (max-width: 1000px) {
    .pp-perso__layout {
        grid-template-columns: minmax(0, 1fr);
    }

    .pp-perso__apercu {
        position: static;
        order: -1;
    }

    .pp-navigateur__ecran {
        max-height: 50vh;
    }
}

/*
personnaliser-blocs.css

QUOI : Écran « Personnaliser ma page », blocs ajoutés avec les gabarits : sommaire des sections, cartes de
       choix de la mise en page (schéma de chaque gabarit), saisie des horaires, réseaux sociaux, photos de
       la galerie, questions fréquentes.

COMMENT : Même grammaire que personnaliser.css (DA 2026 « Affiche » : cartes pointillées, pleines et teintées
          de jaune une fois cochées, vrais boutons radio masqués, état porté par `:has(input:checked)`). Les
          schémas de gabarit sont dessinés en CSS (4 blocs `<i>` placés par grille), sans image.

OÙ : Importé par app.imports.css après personnaliser.css. Template `pagepro/personnaliser.html.twig`.

POURQUOI : Scindé de personnaliser.css pour rester sous 500 lignes par fichier (docs/ARCHITECTURE.md §5).
*/

/* Sommaire : pastilles d'ancre qui défilent sur téléphone. */
.pp-perso__sommaire {
    display: flex;
    gap: 0.5rem;
    margin: 0 0 1.25rem;
    padding-bottom: 0.25rem;
    overflow-x: auto;
    scrollbar-width: thin;
}

.pp-perso__sommaire a {
    flex: 0 0 auto;
    padding: 0.4rem 0.9rem;
    background: var(--da-carte);
    border: 2px solid var(--da-encre);
    border-radius: 999px;
    font-size: var(--fs-sm);
    font-weight: 700;
    color: var(--da-encre);
    text-decoration: none;
}

.pp-perso__sommaire a:hover,
.pp-perso__sommaire a:focus-visible {
    background: var(--da-jaune);
}

.pp-perso .profile-card {
    scroll-margin-top: 96px;
}

.pp-perso__astuce {
    margin: 0;
    font-size: var(--fs-sm);
    color: var(--c-texte-doux, var(--c-texte));
}

/* ── Gabarits ── */

.pp-gabarits {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 125px), 1fr));
    gap: 0.75rem;
}

.pagepro-form .pp-gabarit {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    margin: 0;
    padding: 0.6rem 0.6rem 0.8rem;
    background: var(--da-carte);
    border: 2px dashed var(--da-trait);
    border-radius: var(--radius-lg);
    cursor: pointer;
}

.pp-gabarit input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.pp-gabarit:has(input:checked) {
    border-style: solid;
    background: color-mix(in srgb, var(--da-jaune) 45%, var(--da-carte));
    box-shadow: var(--da-ombre-s);
}

[data-theme="dark"] .pp-gabarit:has(input:checked) {
    background: color-mix(in srgb, var(--da-jaune) 14%, var(--da-carte));
}

.pp-gabarit:has(input:focus-visible) {
    outline: 3px solid var(--c-mer);
    outline-offset: 2px;
}

.pp-gabarit__nom {
    font-weight: 800;
    color: var(--c-marine);
}

.pp-gabarit__desc {
    font-size: 0.8rem;
    line-height: 1.35;
    color: var(--c-texte);
}

/* Schéma : 4 blocs (titre, visuel, infos, infos) placés selon le gabarit. */
.pp-gabarit__schema {
    display: grid;
    gap: 4px;
    height: 84px;
    padding: 6px;
    background: #f4f1ea;
    border: 2px solid var(--da-encre);
    border-radius: var(--radius-md);
}

.pp-gabarit__schema i {
    display: block;
    border-radius: 3px;
    background: #c9c3b5;
}

.pp-gabarit__schema i:nth-child(1) {
    background: var(--da-encre);
}

.pp-gabarit__schema i:nth-child(2) {
    background: var(--da-outremer);
}

.pp-gabarit__schema--classique {
    grid-template: 1fr 1fr 14px / 1.2fr 1fr;
}

.pp-gabarit__schema--classique i:nth-child(1) { grid-area: 1 / 1 / 3 / 2; margin: 10px 8px 10px 0; }
.pp-gabarit__schema--classique i:nth-child(2) { grid-area: 1 / 2 / 3 / 3; }
.pp-gabarit__schema--classique i:nth-child(3) { grid-area: 3 / 1 / 4 / 2; }
.pp-gabarit__schema--classique i:nth-child(4) { grid-area: 3 / 2 / 4 / 3; }

.pp-gabarit__schema--vitrine {
    position: relative;
    grid-template: 1fr 14px / 1fr 1fr 1fr;
    background: var(--da-outremer);
}

.pp-gabarit__schema--vitrine i:nth-child(1) { grid-area: 1 / 1 / 2 / 3; align-self: end; height: 14px; background: #fff; }
.pp-gabarit__schema--vitrine i:nth-child(2) { display: none; }
.pp-gabarit__schema--vitrine i:nth-child(3) { grid-area: 2 / 1 / 3 / 3; background: #fff; }
.pp-gabarit__schema--vitrine i:nth-child(4) { grid-area: 2 / 3 / 3 / 4; background: #fff; }

.pp-gabarit__schema--bento {
    grid-template: 1fr 1fr / 1.4fr 1fr 0.8fr;
}

.pp-gabarit__schema--bento i:nth-child(1) { grid-area: 1 / 1 / 2 / 3; }
.pp-gabarit__schema--bento i:nth-child(2) { grid-area: 1 / 3 / 2 / 4; }
.pp-gabarit__schema--bento i:nth-child(3) { grid-area: 2 / 1 / 3 / 2; }
.pp-gabarit__schema--bento i:nth-child(4) { grid-area: 2 / 2 / 3 / 4; background: var(--da-corail, #e07856); }

.pp-gabarit__schema--editorial {
    grid-template: 6px 16px 1fr / 1fr 1.4fr;
}

.pp-gabarit__schema--editorial i:nth-child(1) { grid-area: 2 / 1 / 3 / 3; }
.pp-gabarit__schema--editorial i:nth-child(2) { grid-area: 3 / 2 / 4 / 3; }
.pp-gabarit__schema--editorial i:nth-child(3) { grid-area: 1 / 1 / 2 / 3; height: 2px; align-self: center; background: var(--da-encre); }
.pp-gabarit__schema--editorial i:nth-child(4) {
    grid-area: 3 / 1 / 4 / 2;
    background: repeating-linear-gradient(to bottom, #c9c3b5 0 4px, transparent 4px 8px);
}

/* Scindé : photo pleine hauteur à gauche, page à droite. */
.pp-gabarit__schema--scinde {
    grid-template: 14px 1fr 1fr / 1fr 1fr;
}

.pp-gabarit__schema--scinde i:nth-child(1) { grid-area: 1 / 2 / 2 / 3; }
.pp-gabarit__schema--scinde i:nth-child(2) { grid-area: 1 / 1 / 4 / 2; margin: -10px 0 -10px -10px; border-radius: 0; }
.pp-gabarit__schema--scinde i:nth-child(3) { grid-area: 2 / 2 / 3 / 3; }
.pp-gabarit__schema--scinde i:nth-child(4) { grid-area: 3 / 2 / 4 / 3; }

/* Affiche : nom en très grand sur toute la largeur, bandeau photo dessous. */
.pp-gabarit__schema--affiche {
    grid-template: 1.3fr 1fr 10px / 1fr 1fr 1fr;
}

.pp-gabarit__schema--affiche i:nth-child(1) { grid-area: 1 / 1 / 2 / 4; }
.pp-gabarit__schema--affiche i:nth-child(2) { grid-area: 2 / 1 / 3 / 4; }
.pp-gabarit__schema--affiche i:nth-child(3) { grid-area: 3 / 1 / 4 / 2; }
.pp-gabarit__schema--affiche i:nth-child(4) { grid-area: 3 / 2 / 4 / 4; }

/* Matière du fond : échantillon de la texture. */
.pp-choix__matiere {
    width: 2.6rem;
    height: 2.6rem;
    border-radius: 10px;
    border: 1px solid var(--da-filet, #d9d3c5);
    background: #ece7da;
}

.pp-choix__matiere--grain {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .35 0'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23g)'/%3E%3C/svg%3E");
}

.pp-choix__matiere--aurore {
    background: radial-gradient(circle at 25% 20%, #e07856 0, transparent 60%), radial-gradient(circle at 85% 90%, #2b59c3 0, transparent 55%), #ece7da;
}

.pp-choix__titre {
    font-weight: 800;
    line-height: 1;
}

/* ── Horaires ── */

.pp-horaires-saisie {
    display: grid;
    gap: 0.4rem;
}

.pp-horaires-saisie__tete,
.pp-horaires-saisie__jour {
    display: grid;
    grid-template-columns: 6.5rem minmax(0, 1fr) minmax(0, 1fr);
    align-items: center;
    gap: 0.5rem 0.75rem;
}

.pp-horaires-saisie__tete {
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--c-texte);
}

.pp-horaires-saisie__jour {
    padding: 0.35rem 0;
    border-top: 1px dashed var(--da-trait);
}

.pp-horaires-saisie__nom {
    font-weight: 700;
}

.pp-horaires-saisie__plage {
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

.pagepro-form .pp-horaires-saisie__plage input[type="time"] {
    flex: 1 1 0;
    min-width: 0;
    padding: 0.45rem 0.4rem;
}

.pp-horaires-saisie__outils {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.4rem;
}

.pp-horaires-saisie__outils .btn {
    min-height: 40px;
    padding: 0.4rem 0.9rem;
    font-size: var(--fs-sm);
}

/* ── Réseaux, photos, FAQ ── */

.pp-reseaux-saisie {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 0 1rem;
}

.pp-galerie-saisie {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: 0.6rem;
}

.pp-galerie-saisie__photo {
    display: grid;
    gap: 0.3rem;
    margin: 0;
    padding: 0.35rem;
    background: var(--da-carte);
    border: 2px dashed var(--da-trait);
    border-radius: var(--radius-md);
    cursor: pointer;
    font-size: 0.82rem;
    font-weight: 700;
}

.pp-galerie-saisie__photo img {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: 6px;
}

.pp-galerie-saisie__photo:has(input:checked) {
    border-style: solid;
    border-color: var(--c-erreur, #b3261e);
}

.pp-galerie-saisie__photo:has(input:checked) img {
    opacity: 0.4;
}

.pp-faq-saisie {
    padding-top: 0.5rem;
    border-top: 1px dashed var(--da-trait);
}

.pp-faq-saisie__plus > summary {
    margin: 0.75rem 0;
    font-weight: 700;
    cursor: pointer;
}

@media (max-width: 560px) {
    .pp-horaires-saisie__tete {
        display: none;
    }

    .pp-horaires-saisie__jour {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* ── Photos de couverture : ordinateur (16:9) et téléphone (4:5), cadres à la bonne forme ── */

.pp-couvertures {
    display: grid;
    gap: 1.25rem;
}

/* Une ligne par écran : le cadre à gauche (à la forme de l'écran), les champs à droite, assez larges pour
   afficher le nom du fichier choisi. */
.pp-couverture {
    display: grid;
    grid-template-columns: 9.5rem minmax(0, 1fr);
    gap: 0 1rem;
    align-items: start;
}

.pp-couverture > .pp-couverture__cadre {
    grid-row: 1 / span 2;
}

.pp-couverture > :not(.pp-couverture__cadre) {
    grid-column: 2;
}

.pp-couverture__cadre {
    display: grid;
    place-items: center;
    overflow: hidden;
    margin-bottom: 0.5rem;
    background: repeating-linear-gradient(45deg, transparent 0 10px, color-mix(in srgb, var(--da-trait) 40%, transparent) 10px 11px), var(--da-carte);
    border: 2px dashed var(--da-trait);
    border-radius: var(--radius-md);
    font-weight: 800;
    color: var(--c-texte);
}

.pp-couverture--pc .pp-couverture__cadre {
    aspect-ratio: 16 / 9;
}

.pp-couverture--mobile .pp-couverture__cadre {
    justify-self: center;
    width: 6.5rem;
    aspect-ratio: 4 / 5;
}

.pp-couverture__cadre img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* ── Aperçu : bascule ordinateur / téléphone ── */

.pp-apercu__tete {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.6rem;
}

.pp-apercu__tete .pp-apercu__label {
    margin: 0;
}

.pp-apercu__ecrans {
    display: inline-flex;
    padding: 3px;
    background: var(--da-carte);
    border: 2px solid var(--da-encre);
    border-radius: 999px;
}

.pp-apercu__ecran {
    min-height: 40px;
    padding: 0.3rem 1rem;
    background: none;
    border: 0;
    border-radius: 999px;
    color: var(--c-texte);
    font: inherit;
    font-size: var(--fs-sm);
    font-weight: 800;
    cursor: pointer;
}

.pp-apercu__ecran[aria-pressed="true"] {
    background: var(--da-jaune);
    color: var(--da-encre);
}

/* Téléphone : cadre de 300 px, mini-site zoomé à 0,77 → 390 px de large pour ses requêtes de conteneur,
   soit un vrai téléphone. */
.pp-navigateur--mobile {
    width: 324px;
    max-width: 100%;
    margin-inline: auto;
    border-radius: 36px;
}

.pp-navigateur--mobile .pp-navigateur__barre span {
    display: none;
}

.pp-navigateur--mobile .pp-navigateur__ecran {
    max-height: 640px;
}

.pp-navigateur--mobile .pp-site--apercu {
    zoom: 0.77;
}

@media (max-width: 560px) {
    .pp-couverture {
        grid-template-columns: minmax(0, 1fr);
    }

    .pp-couverture > :not(.pp-couverture__cadre),
    .pp-couverture > .pp-couverture__cadre {
        grid-column: 1;
        grid-row: auto;
    }

    .pp-couverture--pc .pp-couverture__cadre {
        width: min(100%, 16rem);
    }
}

/* Champs fichier sur toute la largeur de leur colonne (le nom du fichier n'est plus tronqué en « no fi…cted »). */
.pp-couverture input[type="file"],
#perso-photos input[type="file"] {
    width: 100%;
    max-width: 100%;
    font-size: var(--fs-sm);
}

/* Case « Retirer… » sur la même ligne que son libellé, case en premier. */
.pp-couverture div:has(> input[type="checkbox"]) {
    display: flex;
    flex-direction: row-reverse;
    justify-content: flex-end;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.5rem;
}

.pp-couverture div:has(> input[type="checkbox"]) label {
    margin: 0;
    font-weight: 600;
}


/* Modernisation 2026 de la DA d'origine (transitions, apparitions, en-tête, titres) : après tous les composants. */
/*
home-rangees.css

QUOI : Rangées thématiques de l'accueil (`home/_partials/_rangees_accueil.html.twig`) : titre avec pastille d'icône,
       piste de cartes à faire glisser horizontalement, flèches sur ordinateur.

COMMENT : Piste en grille à colonnes automatiques (`grid-auto-flow: column`) : toutes les cartes ont la même
          largeur et la même hauteur (étirement de la rangée). Arrêt sur chaque carte (scroll-snap), barre de
          défilement fine. Les cartes débordent jusqu'au bord de l'écran sur téléphone (marges négatives) pour
          montrer qu'il y a une suite. Flèches masquées sur les appareils tactiles.

OÙ : app.imports.css. Script des flèches : `assets/js/rangees.js`.

POURQUOI : Refonte « Opale lumineuse » (27/10/2026).
*/

.rangees-accueil {
    display: grid;
    gap: clamp(1.75rem, 4vw, 2.75rem);
    margin-bottom: clamp(2rem, 5vw, 3.25rem);
}

.rangee__tete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-sm);
    margin-bottom: 0.85rem;
}

body .rangee__titre {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    margin: 0;
    font-family: var(--font-display);
    font-size: clamp(1.3rem, 1.05rem + 0.9vw, 1.65rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    color: var(--c-marine);
}

.rangee__pastille {
    display: grid;
    place-items: center;
    flex: none;
    width: 2.1rem;
    height: 2.1rem;
    color: var(--c-corail-texte);
    background: color-mix(in srgb, var(--c-corail) 14%, var(--c-surface));
    border-radius: 0.75rem;
}

.rangee__pastille svg {
    width: 1.15rem;
    height: 1.15rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.rangee__actions {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.rangee__tout {
    margin-right: 0.35rem;
    font-weight: 700;
    font-size: 0.92rem;
    color: var(--c-mer);
    text-decoration: none;
}

.rangee__tout:hover {
    text-decoration: underline;
    text-underline-offset: 3px;
}

.rangee__fleche {
    display: none;
    place-items: center;
    width: 40px;
    height: 40px;
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--c-marine);
    background: var(--c-surface);
    border: 1px solid var(--c-bordure-champ);
    border-radius: 999px;
    cursor: pointer;
    transition: border-color var(--duration-fast) var(--ease-out), opacity var(--duration-fast) var(--ease-out);
}

.rangee__fleche:hover {
    border-color: var(--c-mer);
}

.rangee__fleche:disabled {
    opacity: 0.35;
    cursor: default;
}

@media (hover: hover) and (min-width: 768px) {
    .rangee__fleche {
        display: grid;
    }
}

.rangee__piste {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: min(78%, 290px);
    gap: var(--space-sm);
    /* Débord jusqu'au bord de l'écran (le conteneur a un rembourrage latéral) : on voit qu'il y a une suite. */
    margin-inline: calc(-1 * max(var(--space-sm), env(safe-area-inset-left)));
    padding: 0.35rem max(var(--space-sm), env(safe-area-inset-left)) 1rem;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: max(var(--space-sm), env(safe-area-inset-left));
    scrollbar-width: thin;
    scrollbar-color: color-mix(in srgb, var(--c-mer) 35%, transparent) transparent;
}

.rangee__piste > * {
    scroll-snap-align: start;
    min-width: 0;
}

.rangee__piste:focus-visible {
    outline: 3px solid var(--c-mer);
    outline-offset: 2px;
    border-radius: var(--radius-lg);
}

/* Téléphone : cartes plus étroites et sans description (le titre, la date et le lieu suffisent pour choisir) —
   quatre rangées de cartes pleines repoussaient le flux principal de ~2 400 px. */
@media (max-width: 767px) {
    .rangee__piste {
        grid-auto-columns: min(60%, 236px);
    }

    .rangee__piste .event-card__description {
        display: none;
    }
}

/* Ordinateur : quatre cartes visibles, la piste reste dans la colonne de contenu. */
@media (min-width: 1024px) {
    .rangee__piste {
        grid-auto-columns: calc((100% - 3 * var(--space-sm)) / 4);
        margin-inline: 0;
        padding-inline: 0;
        scroll-padding-inline: 0;
    }
}

@media (prefers-reduced-motion: no-preference) {
    .rangee__piste {
        scroll-behavior: smooth;
    }
}

/* Cartes alignées entre elles : la piste définit cinq lignes (vignette, en-tête, titre, commune, description)
   que chaque carte reprend en sous-grille. Une date sur deux lignes ou un titre plus long décale désormais la
   ligne entière, pas une seule carte — les titres d'une rangée commencent tous à la même hauteur. */
@supports (grid-template-rows: subgrid) {
    .rangee__piste {
        grid-template-rows: repeat(5, auto);
        row-gap: 0;
    }

    .rangee__piste > .event-card-link,
    .rangee__piste .event-card {
        display: grid;
        grid-row: span 5;
        grid-template-rows: subgrid;
    }

    .rangee__piste .event-card {
        row-gap: var(--space-xs);
        align-content: start;
    }

    .rangee__piste .event-card__header,
    .rangee__piste .event-card__title,
    .rangee__piste .event-card__ville,
    .rangee__piste .event-card__description {
        align-self: start;
        margin-block: 0;
    }

    .rangee__piste > .tuile-proposer {
        grid-row: span 5;
    }
}

/* Tuile de fin de rangée : la hauteur d'une carte, sans marge propre. */
.rangee__piste > .tuile-proposer--rangee {
    height: auto;
    min-height: 0;
    margin: 0;
}

/*
filtre-pastilles.css

QUOI : Filtre des pages ville et catégorie (`assets/js/filtre-pastilles.js`), en liste déroulante dans l'en-tête, et
       mode « filtré » de la grille d'événements.

COMMENT : Liste déroulante au format de la barre de /lieux (depuis le 29/10/2026 ; avant : rangée de pastilles). En mode filtré
          (`.events-grid.is-filtre`), la tête bento s'efface : la 1re carte reprend une case normale, la colonne de
          tête redevient transparente et sa tuile « Votre événement ici ? » disparaît.

OÙ : app.imports.css.

POURQUOI : Refonte « Opale lumineuse » (27/10/2026) : filtres visibles en un geste, résultats toujours à l'écran
           (recommandation NN/g pour les listes sur mobile).
*/

/* Liste déroulante dans l'en-tête : la barre de /lieux (`.lieu-search`, components/editorial-2026.css), réduite à
   un champ. */
html body .page-hero .lieu-search.filtre-liste { max-width: 24rem; }
html body .page-hero .lieu-search.filtre-liste .lieu-search__field { flex: 1 1 auto; min-width: 0; border-bottom: 0; }

/* ── Grille filtrée : plus de tête bento ── */
/* Les cellules écartées portent `hidden` ; les cartes imposent `display: block` (event-card.css), qui l'emportait
   sur le style par défaut de l'attribut. */
.events-grid.is-filtre [hidden] {
    display: none !important;
}

.events-grid.is-filtre .lead-aside {
    display: contents;
}

.events-grid.is-filtre .lead-aside > .lead-aside__fill {
    display: none;
}

/* Même spécificité que la règle de tête des listes (bento-shared.css, `:not(:has(...))`) + la classe `is-filtre`. */
.taxonomy-page .events-grid.is-filtre > .event-card-link:first-child:not(:has(.event-card--compact)) {
    grid-column: auto;
}

.taxonomy-page .events-grid.is-filtre > .event-card-link:first-child:not(:has(.event-card--compact)) .event-card__title {
    font-size: 1.2rem;
}

.taxonomy-page .events-grid.is-filtre > .event-card-link:first-child:not(:has(.event-card--compact)) .event-card__description {
    -webkit-line-clamp: 3;
}

.taxonomy-page .events-grid.is-filtre > .event-card-link:nth-child(2),
.taxonomy-page .events-grid.is-filtre > .event-card-link:nth-child(2) .event-card {
    align-self: stretch;
    height: 100%;
}

/*
barre-onglets.css

QUOI : Barre d'onglets fixée en bas de l'écran sur téléphone (`_partials/_barre_onglets.html.twig`) : cinq onglets,
       « Proposer » en rond corail au centre ; et le décalage des boutons flottants (assistant, « j'aime », retour en
       haut) qui se posaient sinon par-dessus.

COMMENT : ≤ 767 px seulement (tablette et ordinateur gardent l'en-tête complet). Surface claire translucide floutée
          en thème clair, encre en thème sombre ; onglet actif en marine (clair) ou mer (sombre) avec un trait
          au-dessus. Quand la barre est présente (`body:has(.barre-onglets)`), l'en-tête cache son bouton MENU et
          son accès au compte — l'onglet « Explorer » ouvre le même tiroir, « Compte » mène au même endroit.
          Hauteur réservée en bas de page : la barre ne recouvre jamais le pied de page.

OÙ : app.imports.css.

POURQUOI : Refonte « Opale lumineuse » (27/10/2026) : navigation au pouce, standard mobile 2026.
*/

.barre-onglets {
    display: none;
}

@media (max-width: 767px) {
    :root {
        --barre-onglets-h: 64px;
    }

    .barre-onglets {
        position: fixed;
        inset: auto 0 0 0;
        z-index: 950;
        display: grid;
        grid-template-columns: repeat(5, minmax(0, 1fr));
        align-items: end;
        height: calc(var(--barre-onglets-h) + env(safe-area-inset-bottom, 0px));
        padding: 0 0.25rem env(safe-area-inset-bottom, 0px);
        background: rgba(255, 253, 249, 0.9);
        -webkit-backdrop-filter: saturate(1.4) blur(14px);
        backdrop-filter: saturate(1.4) blur(14px);
        border-top: 1px solid rgba(10, 61, 98, 0.12);
        box-shadow: 0 -8px 24px -18px rgba(10, 61, 98, 0.45);
    }

    [data-theme="dark"] .barre-onglets {
        background: rgba(12, 22, 32, 0.9);
        border-top-color: rgba(160, 196, 224, 0.14);
    }

    .barre-onglets__lien {
        position: relative;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 0.2rem;
        height: var(--barre-onglets-h);
        padding: 0;
        font: inherit;
        font-size: 0.7rem;
        font-weight: 600;
        color: var(--c-texte-doux);
        text-decoration: none;
        background: none;
        border: 0;
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }

    .barre-onglets__ico {
        width: 22px;
        height: 22px;
        fill: none;
        stroke: currentColor;
        stroke-width: 1.9;
        stroke-linecap: round;
        stroke-linejoin: round;
    }

    /* Onglet de la page courante : couleur pleine et trait au-dessus. */
    .barre-onglets__lien[aria-current="page"] {
        color: var(--c-marine);
    }

    [data-theme="dark"] .barre-onglets__lien[aria-current="page"] {
        color: var(--c-mer);
    }

    .barre-onglets__lien[aria-current="page"]::before {
        content: "";
        position: absolute;
        top: 0;
        left: 30%;
        right: 30%;
        height: 3px;
        border-radius: 0 0 3px 3px;
        background: var(--c-corail);
    }

    /* « Proposer » : l'action principale, en rond corail qui dépasse de la barre. */
    .barre-onglets__rond {
        display: grid;
        place-items: center;
        width: 48px;
        height: 48px;
        margin-top: -22px;
        color: #ffffff;
        background: linear-gradient(135deg, var(--c-corail-action) 0%, var(--c-corail-action-fonce) 100%);
        border: 3px solid rgba(255, 253, 249, 0.95);
        border-radius: 999px;
        box-shadow: 0 8px 18px -6px rgba(185, 83, 47, 0.6);
    }

    [data-theme="dark"] .barre-onglets__rond {
        border-color: rgba(12, 22, 32, 0.95);
    }

    .barre-onglets__lien--proposer {
        color: var(--c-corail-texte);
        justify-content: flex-end;
        padding-bottom: 0.55rem;
    }

    .barre-onglets__lien:active .barre-onglets__ico,
    .barre-onglets__lien:active .barre-onglets__rond {
        transform: scale(0.92);
    }

    .barre-onglets__lien:focus-visible {
        outline: 3px solid var(--c-mer);
        outline-offset: -3px;
        border-radius: 12px;
    }

    /* ── Avec la barre : l'en-tête allège, les boutons flottants remontent, le bas de page est réservé ── */
    body:has(.barre-onglets) .site-header :is(.nav-burger, .header-account, .header-account-group) {
        display: none;
    }

    body:has(.barre-onglets) {
        padding-bottom: calc(var(--barre-onglets-h) + env(safe-area-inset-bottom, 0px));
    }

    body:has(.barre-onglets) :is(.assistant__fab, .back-to-top) {
        bottom: calc(20px + var(--barre-onglets-h) + env(safe-area-inset-bottom, 0px));
    }

    body:has(.barre-onglets) .event-like-fab {
        bottom: calc(88px + var(--barre-onglets-h) + env(safe-area-inset-bottom, 0px));
    }

    /* Pendant un défilement vers le bas (`body.defile-bas`, nav/barre-onglets.js), la barre glisse hors de l'écran,
       en même temps que Safari replie sa propre barre ; elle revient dès qu'on remonte. Outre le confort de
       lecture, c'est la parade au bug de Safari sur iOS 26 : quand sa barre d'adresse se replie, un élément fixé
       à `bottom: 0` reste à la hauteur qu'elle occupait et laisse voir la page en dessous (Apple Developer Forums,
       fils 800798 et 801028, non corrigé à ce jour). */
    .barre-onglets {
        transition: transform 260ms var(--ease-out);
    }

    body.defile-bas .barre-onglets {
        transform: translateY(calc(100% + 32px));
    }

    /* Menu (tiroir) ouvert : il occupe tout l'écran, la barre s'efface pour ne pas masquer ses derniers liens. */
    body:has(#mobile-drawer.is-open) .barre-onglets {
        display: none;
    }

    /* Le bas du pied de page n'a plus à éviter la bulle : la barre réserve déjà la place. */
    body:has(.barre-onglets) .site-footer__bottom {
        padding-bottom: var(--space-md);
    }
}

@media (prefers-reduced-motion: no-preference) {
    .barre-onglets__ico,
    .barre-onglets__rond {
        transition: transform 120ms var(--ease-out);
    }
}

/*
modernite-2026.css

QUOI : Modernisation « 2026 » de la DA d'origine d'Opalenews, sans en changer l'identité (palette marine / mer /
       corail / sable, Plus Jakarta Sans + Inter, cartes arrondies, héros en dégradé, vagues) :
       - transitions fluides entre les pages (View Transitions, sans JavaScript) ;
       - apparition douce des cartes au défilement (animation pilotée par le défilement, CSS natif) ;
       - en-tête d'un bleu plus uniforme et plus net ;
       - un seul style de titre de section sur tout le site (ils variaient de 25 à 34 px, en 700 ou 800, en
         Inter ou en Plus Jakarta Sans).

COMMENT : Fichier chargé en dernier (avant `base/ios-zoom.css`) : il n'ajoute que des couches, il ne réécrit pas les
          composants. Toute animation est coupée si l'utilisateur demande à réduire les mouvements, et les deux
          mécanismes d'apparition existants (`[data-reveal]`, `.u-stagger`) sont laissés tranquilles.

OÙ : app.imports.css.

POURQUOI : Demande d'Ellie (27/10/2026) : « garder l'image d'Opalenews et son intention, mais la moderniser en
           design 2026, sans être trop original » — après l'abandon de la DA 2026 « Affiche ».
*/

/* ── Transitions entre les pages ─────────────────────────────────────────────────────────────────────────
   Navigation d'une page du site à l'autre : fondu court au lieu d'un écran qui « clignote ». L'en-tête porte
   son propre nom de transition : il reste en place pendant que le contenu change. Navigateurs sans support :
   navigation classique, rien ne casse. */
@view-transition {
    navigation: auto;
}

.site-header {
    view-transition-name: site-header;
}

::view-transition-old(root),
::view-transition-new(root) {
    animation-duration: 220ms;
    animation-timing-function: var(--ease-out);
}

@media (prefers-reduced-motion: reduce) {
    @view-transition {
        navigation: none;
    }
}

/* ── Apparition des cartes au défilement ────────────────────────────────────────────────────────────────
   Chaque carte d'une grille glisse de 16 px et s'éclaire en entrant dans l'écran. Piloté par le défilement
   (`animation-timeline: view()`) : aucun script, rien à recalculer, et la carte est toujours entièrement
   visible une fois entrée. Les grilles qui ont déjà leur propre apparition sont exclues. */
@supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
        :is(.events-grid, .actualites-grille, .prospectus__grille, .bloc-annuaire__liste, .partner-cell-grid):not(.u-stagger, [data-reveal-children]) > :not([data-reveal], .lead-aside) {
            animation: opale-apparition linear both;
            animation-timeline: view();
            animation-range: entry 0% entry 40%;
        }
    }
}

@keyframes opale-apparition {
    from {
        opacity: 0;
        transform: translateY(16px);
    }
}

/* ── En-tête ────────────────────────────────────────────────────────────────────────────────────────────
   Bleu plus uniforme (le dégradé s'éclaircissait vers la droite, où les liens perdaient du contraste) et un
   filet clair en bas pour le détacher du contenu qui défile dessous. */
:root {
    --header-bg: linear-gradient(135deg, rgba(10, 61, 98, 0.93) 0%, rgba(20, 78, 120, 0.91) 100%);
    --header-bg-scrolled: linear-gradient(135deg, rgba(9, 52, 84, 0.90) 0%, rgba(18, 70, 108, 0.90) 100%);
}

.site-header {
    box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.08), 0 8px 24px -18px rgba(10, 61, 98, 0.55);
}

/* ── Titres de section ──────────────────────────────────────────────────────────────────────────────────
   Un seul style : Plus Jakarta Sans 800, taille fluide 26 → 34 px, interlettrage serré, marine. Le titre
   « éditorial » du prospectus (petites capitales) garde le sien. Préfixe `body` : certaines pages chargent leur
   feuille (`pages/partners.css`) APRÈS le bundle, à priorité égale elle l'emportait. */
body :is(
    .section-title,
    .section-heading__title,
    .home-map-section__title,
    .event-similar__title,
    .actualites-bloc__titre,
    .bloc-annuaire__titre,
    .partner-cell-section__title
) {
    font-family: var(--font-display);
    font-size: clamp(1.6rem, 1.2rem + 1.3vw, 2.1rem);
    font-weight: 800;
    line-height: 1.15;
    letter-spacing: -0.02em;
    color: var(--c-marine);
    text-wrap: balance;
}

/* « À proximité — nos partenaires » était un petit titre de 17 px, plus discret que tout le reste de la page. */
body .partner-cell-section__title {
    margin-bottom: var(--space-sm);
}

/* ── Finitions typographiques et contrôles natifs ───────────────────────────────────────────────────────
   - titres équilibrés (lignes de longueurs proches) et paragraphes sans mot orphelin en fin de bloc ;
   - cases à cocher, boutons radio et curseurs aux couleurs de la marque au lieu du bleu système ;
   - surlignage du texte sélectionné dans le sable, texte marine (lisible dans les deux thèmes). */
:is(h1, h2, h3) {
    text-wrap: balance;
}

p {
    text-wrap: pretty;
}

:root {
    accent-color: var(--c-action);
}

::selection {
    color: #0a3d62;
    background: rgba(245, 233, 212, 0.95);
}

/* ── Appel à l'action de l'en-tête ──────────────────────────────────────────────────────────────────────
   « Proposer un événement » est l'action principale du site : sur grand écran, le « + » carré devient une
   pilule « + Proposer » (libellé court, le libellé complet reste dans `aria-label`). En dessous de 1340 px,
   l'en-tête n'a pas la place : on garde le carré. */
.header-cta__court {
    display: none;
}

@media (min-width: 1340px) {
    .site-header .header-actions .header-cta {
        width: auto;
        gap: 0.4rem;
        padding: 0 0.95rem 0 0.75rem;
    }

    .site-header .header-cta__court {
        display: inline;
        font-weight: 700;
        font-size: 0.9rem;
    }
}

/* ── Cibles cliquables sur ordinateur ───────────────────────────────────────────────────────────────────
   Liens du menu (38 px), flèches des rangées (40 px) et cœur des cartes (26 px de haut) sous les 44 / 32 px
   recommandés (audit ordinateur du 27/10/2026). L'en-tête (69 px) a la place. */
@media (min-width: 1024px) {
    .site-header .site-nav__link {
        min-height: 44px;
    }

    .rangee__fleche {
        width: 44px;
        height: 44px;
    }

    .like-btn--card {
        min-height: 32px;
    }
}

/*
mobile-2026.css

QUOI : Refonte mobile d'après l'audit du 27/10/2026 (toutes les pages publiques à 360, 390 et 430 px) :
       1. cartes d'événement et de lieu COMPACTES dans les listes sur téléphone (vignette carrée à gauche, date,
          titre et commune à droite) — la 1re carte de chaque grille reste en grand format ;
       2. un seul bouton flottant à la fois : plus de « retour en haut » sur téléphone (la barre d'onglets et le
          geste de l'appareil le remplacent), plus de bulle d'invitation de l'assistant, « j'aime » de la fiche
          événement à droite au-dessus de la barre ;
       3. cibles tactiles d'au moins 44 px et micro-textes d'au moins 11 px ;
       4. superpositions corrigées (lien retour sur la pastille du héros des lieux, commune collée à droite sur
          les cartes de lieux, barre d'actions des pages Pro sous le « retour en haut »).

COMMENT : Uniquement des couches par-dessus les composants existants (fichier chargé en dernier), presque toutes
          sous `@media (max-width: 600px | 767px)` : l'ordinateur ne change pas.

OÙ : app.imports.css.

POURQUOI : Demande d'Ellie (27/10/2026) : « mobile first, revois vraiment tout ». Une carte d'événement pleine
           faisait ~520 px de haut sur téléphone : l'accueil mesurait 17 800 px, une page de zone 46 000 px.
*/

/* ── 1. Cartes compactes dans les listes (téléphone) ─────────────────────────────────────────────────────
   Vignette carrée de 88 px à gauche, centrée verticalement avec le bloc de texte (pastille + date sur UNE ligne,
   titre sur deux lignes au plus, commune juste dessous). Revue le 27/10/2026 après le retour d'Ellie sur
   iPhone (« rien n'est bien centré ») : un vide de 45 à 69 px séparait le titre de la commune, la date passait
   sur deux lignes et les hauteurs variaient de 141 à 163 px — mesures dans `verif-fiches.mjs` (scratchpad). */
@media (max-width: 600px) {
    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-card:not(.event-card--compact) {
        --fiche-vignette: 88px;
        display: grid;
        /* La vignette est posée en absolu, centrée verticalement à gauche ; le texte occupe une grille simple
           (en-tête, titre, commune) centrée dans la hauteur de la fiche. Une vignette placée DANS la grille,
           à cheval sur les rangées, faisait gonfler celles-ci (texte décentré ou fiche trop haute). */
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            "header"
            "title"
            "ville";
        align-content: center;
        row-gap: 0;
        min-height: calc(var(--fiche-vignette) + 1.5rem);
        padding: 0.75rem 0.9rem 0.75rem calc(0.75rem + var(--fiche-vignette) + 0.85rem);
    }

    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-card:not(.event-card--compact) .event-card__media {
        position: absolute;
        top: 50%;
        left: 0.75rem;
        transform: translateY(-50%);
        width: var(--fiche-vignette);
        height: var(--fiche-vignette);
        margin: 0;
        aspect-ratio: 1;
        border-radius: 14px;
    }

    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-card:not(.event-card--compact) .event-card__header {
        grid-area: header;
        min-width: 0;
        margin: 0 0 0.3rem;
    }

    /* La date est déjà écrite à côté de la pastille de catégorie : la tuile ticket n'a plus la place. */
    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-card:not(.event-card--compact) .event-card__date-tile {
        display: none;
    }

    /* Pastille + date sur une ligne ; une date trop longue pour tenir à côté (« En cours · jusqu'au 15 janvier
       2027 ») passe ENTIÈRE sur la ligne suivante. */
    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-card:not(.event-card--compact) .event-card__heading-text {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        gap: 0.25rem 0.45rem;
        min-width: 0;
        max-width: 100%;
    }

    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-card:not(.event-card--compact) .event-card__category {
        flex: none;
        padding: 0.18rem 0.55rem;
        font-size: 0.66rem;
        letter-spacing: 0.05em;
    }

    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-card:not(.event-card--compact) .event-card__date {
        min-width: 0;
        max-width: 100%;
        font-size: 0.8rem;
        line-height: 1.3;
        /* Jamais coupée : sur les écrans les plus étroits (360 px), une longue date d'exposition prend deux lignes. */
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }

    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-card:not(.event-card--compact) .event-card__title {
        grid-area: title;
        margin: 0 0 0.25rem;
        font-size: 1rem;
        line-height: 1.25;
    }

    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-card:not(.event-card--compact) .event-card__ville {
        grid-area: ville;
        margin: 0;
        justify-content: flex-start;
        font-size: 0.86rem;
    }

    /* Les marques de droite (logo « nos événements », chevron) tiraient la commune vers le bord : toute la fiche
       est déjà un lien. */
    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-card:not(.event-card--compact) .event-card__ville-marks {
        display: none;
    }

    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-card:not(.event-card--compact) .event-card__description {
        display: none;
    }

    /* Pastille « Incontournable » : trop grande pour une vignette de 88 px ; le liseré doré suffit. */
    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-card--featured .event-card__featured-badge {
        display: none;
    }

    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-card--featured:not(.event-card--compact) {
        padding-top: 0.75rem;
    }

    /* « J'aime » en pastille ronde dans le coin de la vignette (le compteur n'a pas la place). */
    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-card:not(.event-card--compact) .like-btn--card {
        top: 0.3rem;
        right: 0.3rem;
        padding: 0.25rem;
    }

    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-card:not(.event-card--compact) .like-btn--card .like-btn__count {
        display: none;
    }

    /* Cartes de lieu : la pastille de type et le crédit photo encombraient la vignette (le type est déjà dit par
       le titre de la section). */
    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .lieu-card :is(.lieu-card__badge, .lieu-card__credit) {
        display: none;
    }

    /* Listes longues (lieux, zones) : les cartes hors écran ne sont peintes qu'à l'approche (lieu-filters.css,
       `content-visibility: auto`) ; leur hauteur réservée suit la carte compacte, sinon la barre de défilement
       promettait 420 px par carte et sautait. */
    .taxonomy-page .events-grid > .event-card-link:not(:first-child) {
        contain-intrinsic-size: auto 120px;
    }

    /* Couverture graphique : l'icône de catégorie, centrée dans la vignette. */
    :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-cover-abstract__icone {
        right: 50%;
        bottom: 50%;
        height: 56%;
        transform: translate(50%, 50%) rotate(-8deg);
    }
}

/* ── 2. Un seul bouton flottant à la fois (téléphone) ────────────────────────────────────────────────── */
@media (max-width: 767px) {
    .back-to-top {
        display: none !important;
    }

    .assistant__teaser {
        display: none !important;
    }

    /* Fiche événement : « j'aime » à droite (la place du retour en haut), au-dessus de la barre d'onglets. */
    body:has(.barre-onglets) .event-like-fab {
        left: auto;
        right: 16px;
        bottom: calc(16px + var(--barre-onglets-h, 64px) + env(safe-area-inset-bottom, 0px));
    }

    /* Pendant la lecture (défilement vers le bas), les boutons flottants s'effacent ; ils reviennent dès qu'on
       remonte (classe posée par nav/barre-onglets.js). L'assistant recouvrait sinon le bas des cartes. */
    :is(.assistant__fab, .event-like-fab) {
        transition: transform 220ms var(--ease-out), opacity 220ms var(--ease-out);
    }

    body.defile-bas :is(.assistant__fab, .event-like-fab) {
        transform: translateY(24px) scale(0.85);
        opacity: 0;
        pointer-events: none;
    }

    /* Résultats de recherche : la barre du haut ne doit pas couvrir leur titre après le défilement automatique. */
    #results-section {
        scroll-margin-top: 76px;
    }
}

/* ── 3. Cibles tactiles et micro-textes ──────────────────────────────────────────────────────────────── */
/* « J'aime » des cartes : zone de toucher étendue au-delà de la pastille visible. */
.like-btn--card::after {
    content: "";
    position: absolute;
    inset: -10px;
}

@media (max-width: 767px) {
    .toolbar-pill {
        min-height: 44px;
    }
}

.event-card__date-tile-m {
    font-size: 0.68rem; /* 0.6rem (9.6 px) → 11 px */
}

.actualite-card__badge,
.encart-pub__tag,
.bloc-annuaire__page-pro {
    font-size: max(0.7rem, 11px);
}

/* ── 4. Superpositions ───────────────────────────────────────────────────────────────────────────────── */
/* Héros d'une fiche (lieu, événement) : le lien retour est posé en haut à gauche, par-dessus le contenu ; sur un
   héros court, la pastille de catégorie passait dessous. On réserve sa ligne. */
@media (max-width: 640px) {
    .event-hero:has(> .back-link) .event-hero__content {
        padding-top: calc(var(--space-md) + 2.4rem);
    }
}

/* Cartes de lieu : sans les marques de droite des événements, `space-between` envoyait la commune contre le bord
   droit, loin de son épingle. */
.lieu-card .event-card__ville {
    justify-content: flex-start;
}

/* Pages Pro sur téléphone : leur barre d'actions en bas est la seule action flottante. */
@media (max-width: 767px) {
    body:has(.pp-barre-mobile) .assistant__fab {
        display: none;
    }

    body:has(.pp-barre-mobile) .pp-barre-mobile {
        left: max(12px, env(safe-area-inset-left, 0px));
    }
}

/* Logo : sur les plus petits écrans sans barre d'onglets (pages Pro), trois boutons d'en-tête rognaient le nom. */
@media (max-width: 379px) {
    .site-header .logo-text {
        font-size: 1.12rem;
    }
}

/* ── 5. Pages (audit mobile, 2e passe) ───────────────────────────────────────────────────────────────── */
@media (max-width: 600px) {
    /* En-têtes des pages de liste : ~250 → ~190 px, le contenu remonte d'autant. */
    .page-hero {
        padding: 1.25rem 1.1rem 1.4rem;
    }

    .page-hero__intro {
        font-size: 0.95rem;
        line-height: 1.5;
    }

    /* Pages de texte (À propos, mentions, newsletter) : 40 px de marge intérieure ne laissaient que ~32 caractères
       par ligne. */
    .about-card,
    .bento-card {
        padding: 1.25rem 1.1rem;
    }

    .about-card p,
    .bento-card p {
        line-height: 1.6;
    }

    /* Menu horizontal du compte : un fondu au bord droit montre qu'il continue (il était coupé en plein mot). */
    .profile-nav {
        -webkit-mask-image: linear-gradient(to right, #000 85%, transparent);
        mask-image: linear-gradient(to right, #000 85%, transparent);
    }
}

/* Page d'une catégorie : la pastille de catégorie répétait sur chaque carte ce que dit déjà le titre de la page
   (la page catégorie est celle qui filtre par commune). */
.taxonomy-page:has([data-filtre-par="ville"]) .events-grid .event-card:not(.lieu-card) .event-card__category {
    display: none;
}

/* Thème sombre : la photo du premier écran et les visuels publicitaires restaient en pleine luminosité sur l'encre. */
[data-theme="dark"] .home-hero__media img,
[data-theme="dark"] .encart-pub img {
    filter: brightness(0.86);
}

/*
unification-2026.css

QUOI : Uniformisation des pages publiques (inventaire mesuré le 28/10/2026, `inventaire.mjs`) :
       - titres H1 de page : graisse 800 et interlettrage −0,025em partout (900 / −0,02em sur les fiches événement
         et lieu, −0,035em ailleurs — lettres qui se touchaient selon l'audit) ;
       - titres de bloc (panneaux des fiches, cartes « À propos », mentions, newsletter) : 1,2 rem / 700 partout
         (18 ou 19 px selon les pages) ;
       - champs et bouton du filtre de l'annuaire : 48 px, arrondi 14 px comme les autres formulaires (44 px / 8 px) ;
       - boutons « Ajouter à mon agenda » : arrondi 14 px (8 px) ; champs du contact organisateur : arrondi 14 px ;
       - pages de lecture (à propos, newsletter, mentions, 404, adresse commerciale) : 24 px sous l'en-tête comme
         toutes les autres pages (64 px).

OÙ : app.imports.css, après modernite-2026.css et mobile-2026.css.

POURQUOI : Demande d'Ellie (28/10/2026) : « améliore toutes les pages pour tout uniformiser, design 2026 ».
*/

body main h1:not(.home-hero h1, .visually-hidden) {
    font-weight: 800;
    letter-spacing: -0.025em;
}

body :is(.event-panel__title, .about-card > h2, .bento-card > h2) {
    font-family: var(--font-display);
    font-size: 1.2rem;
    font-weight: 700;
    letter-spacing: -0.01em;
}

.bloc-annuaire__filtres :is(select, input, button) {
    min-height: 48px;
    border-radius: var(--radius-md);
}

body .event-calendar-btn {
    border-radius: var(--radius-md);
}

.event-organizer :is(input, textarea, select) {
    border-radius: var(--radius-md);
}

main:is(.about-page, .bento-page) {
    padding-top: 24px;
}

/*
typo-2026.css

QUOI : Voix typographique 2026 : tous les titres (h1 à h4, nom du site dans l'en-tête) en Bricolage Grotesque,
       le reste en Instrument Sans (jetons --font-display / --font-base, fonts.css).

COMMENT : Sélecteurs en `:where()` (spécificité nulle) : un composant qui fixe lui-même sa police garde la main.
          Interlettrage légèrement resserré sur les grands titres, où Bricolage respire davantage que l'ancienne
          police ; les petits titres (cartes, listes) gardent l'interlettrage normal pour rester lisibles.

OÙ : app.imports.css, après unification-2026.css.

POURQUOI : Demande d'Ellie (28/10/2026) : « mets des polices plus modernes sur le site, là ça fait encore très
           prompt IA ». Jusqu'ici presque tout le site, titres compris, était en police de texte.
*/

:where(h1, h2, h3, h4, .logo-text) {
    font-family: var(--font-display);
}

:where(main h1, main h2) {
    letter-spacing: -0.02em;
}

/* Titres équilibrés (lignes de longueur égale, plus de mot seul en dernière ligne : « Que faire près de chez /
   vous ? ») et paragraphes sans veuve. Ignoré proprement par les navigateurs qui ne le connaissent pas. */
:where(h1, h2, h3, h4) { text-wrap: balance; }
:where(p, li, dd, figcaption) { text-wrap: pretty; }

/*
components/ergonomie-2026.css

QUOI : Retouches d'ergonomie et de style relevées en passant tout le site en revue (téléphone et ordinateur).

COMMENT : Une section par retouche, chacune dit ce qu'elle corrige. Fichier chargé après unification-2026 et
          typo-2026, avant densite-mobile (qui ne fait que resserrer sur téléphone).

POURQUOI : Demande d'Ellie (28/10/2026) : « des pastilles pas bien mises, des boutons les uns sur les autres alors
           qu'ils pourraient être côte à côte… mettre le paquet sur tout le design du site ».
*/

/* ── /ou : tuiles d'arrondissement ────────────────────────────────────────────────────────────────────────
   Elles réutilisaient les cartes événement : la grille met la 1re en vedette (pleine largeur) et passe les
   suivantes en fiches compactes à vignette sur téléphone — sans vignette, le texte flottait décalé et le
   nombre de villes disparaissait. Grille dédiée, hauteurs égales, aperçu des communes. */
.zone-tuiles {
    list-style: none;
    margin: 0 0 var(--space-xl);
    padding: 0;
    /* Flex et non grille : 5 arrondissements = 3 + 2, et la rangée incomplète s'étire sur toute la largeur
       au lieu de laisser une tuile orpheline à gauche. */
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
}

.zone-tuiles > li { flex: 1 1 340px; }

.zone-tuile {
    position: relative;
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas: "nom fleche" "compte fleche" "villes villes";
    /* Dernière rangée extensible : sur une même ligne de tuiles, les titres sur 1 ou 2 lignes ne décalent pas
       le reste vers le bas de façon inégale (la liste des communes s'aligne en haut de sa rangée). */
    grid-template-rows: auto auto 1fr;
    align-items: center;
    align-content: start;
    column-gap: var(--space-sm);
    row-gap: 0.2rem;
    height: 100%;
    padding: var(--space-md);
    background: var(--c-surface);
    border: 1px solid var(--c-bordure);
    border-left: 3px solid var(--c-corail);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xs);
    color: inherit;
    text-decoration: none;
    transition: transform var(--duration-base) var(--ease-out), box-shadow var(--duration-base) var(--ease-out);
}

.zone-tuile__nom {
    grid-area: nom;
    font-family: var(--font-display);
    font-size: var(--fs-lg);
    font-weight: 700;
    line-height: 1.2;
    color: var(--c-mer);
}

.zone-tuile__compte {
    grid-area: compte;
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--c-corail-texte);
}

.zone-tuile__villes {
    grid-area: villes;
    margin-top: 0.5rem;
    padding-top: 0.6rem;
    border-top: 1px dashed var(--c-bordure);
    align-self: start;
    font-size: var(--fs-sm);
    color: var(--c-texte-doux);
}

.zone-tuile__fleche {
    grid-area: fleche;
    display: grid;
    place-items: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    background: var(--c-sable-clair);
    color: var(--c-mer);
    transition: transform var(--duration-base) var(--ease-out);
}

@media (hover: hover) {
    .zone-tuile:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
    .zone-tuile:hover .zone-tuile__fleche { transform: translateX(3px); }
}

.zone-tuile:focus-visible { outline: 3px solid var(--c-focus); outline-offset: 2px; }

/* ── Filtre « Événements / Bons plans » ─────────────────────────────────────────────────────────────────────
   Sur téléphone les deux pastilles (≈ 200 + 225 px) ne tenaient pas sur 358 px et s'empilaient. Elles deviennent
   un sélecteur à deux segments égaux, libellés courts (le libellé long reste lu par les lecteurs d'écran). */
.filtre-actus__court { display: none; }

@media (max-width: 599px) {
    .filtre-actus {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 0.25rem;
        padding: 0.25rem;
        background: color-mix(in srgb, var(--c-mer) 8%, var(--c-surface));
        border: 1px solid var(--c-bordure);
        border-radius: 999px;
    }

    .filtre-actus__lien {
        justify-content: center;
        min-height: 2.75rem;
        padding: 0.4rem 0.6rem;
        border-color: transparent;
        background: transparent;
    }

    .filtre-actus__lien.is-active {
        background: var(--c-surface);
        border-color: var(--c-bordure);
        box-shadow: var(--shadow-sm);
    }

    .filtre-actus__long {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    .filtre-actus__court { display: inline; }
}

/* ── Actualités sans photo ───────────────────────────────────────────────────────────────────────────────
   La couverture générative remplissait un 4:3 entier (≈ 270 px de dégradé muet sur téléphone, une demi-carte
   « à la une » sur ordinateur). On y pose l'initiale du pro, et sur téléphone (une seule colonne, donc aucun
   voisin à aligner) la couverture devient un bandeau. Les photos gardent leur 4:3 (format du recadrage). */
.actualite-card__monogramme {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    font-family: var(--font-display);
    font-size: clamp(4rem, 9vw, 7rem);
    font-weight: 800;
    line-height: 1;
    color: rgba(255, 255, 255, 0.9);
    text-shadow: 0 6px 30px rgba(0, 0, 0, 0.25);
    pointer-events: none;
}

.actualite-card--vedette .actualite-card__monogramme { font-size: clamp(5rem, 12vw, 10rem); }

@media (max-width: 599px) {
    .actualite-card__media:has(> .event-cover-abstract) { aspect-ratio: 5 / 2; }
    .actualite-card__monogramme { font-size: 3.5rem; }
}

/* ── Champs de formulaire : police du site ──────────────────────────────────────────────────────────────
   Les navigateurs n'héritent pas la police dans les champs : la recherche de l'annuaire s'affichait en Arial.
   `:where` (spécificité nulle) : tout composant qui fixe sa propre police garde la main. */
:where(input, select, textarea, button) { font-family: inherit; }

/* ── Annuaire : une seule pastille par fiche ────────────────────────────────────────────────────────────
   « Professionnel » + « Page Pro » ne tenaient pas côte à côte dans une fiche de 240 px : elles s'empilaient
   sur deux lignes au-dessus du nom. Dans un annuaire de professionnels, « Professionnel » n'apprend rien ; le
   niveau qu'elle portait reste lu par les lecteurs d'écran, et les fiches premium gardent leur fond distinct
   (et leur place en tête). Reste la seule pastille utile : « Page Pro ». */
.bloc-annuaire__item .bloc-annuaire__pastille {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.bloc-annuaire__item .bloc-annuaire__page-pro { margin: 0 0 0.35rem; }

/* ── Fiche événement, bande « catégorie · date · ville · prix » (téléphone) ─────────────────────────────────
   Avec 16 px entre chaque fait, le prix partait seul sur une seconde ligne. Écart resserré, puis grille 2 × 2
   sur les petits téléphones. */
@media (max-width: 900px) {
    .event-hero__meta--below { column-gap: 0.85rem; row-gap: 0.5rem; }
}

/* Sous 480 px les quatre faits ne tiennent plus sur une ligne : grille 2 × 2 alignée plutôt qu'un prix orphelin. */
@media (max-width: 479px) {
    .event-hero__meta--below {
        display: grid;
        grid-template-columns: max-content 1fr;
        column-gap: 1.25rem;
    }
}

/* ── À propos : cartes pleine largeur sans grand vide à droite ───────────────────────────────────────────────
   Le texte est plafonné à ~75 caractères par ligne (lisibilité) : dans les cartes pleine largeur (« Notre
   mission », et la dernière carte seule sur sa rangée) il occupait la moitié gauche, la droite restait vide.
   Ordinateur : la mission passe en deux colonnes (un paragraphe chacune), la carte finale met son titre à gauche. */
@media (min-width: 1024px) {
    .about-bento > .about-card--feature {
        display: grid;
        grid-template-columns: 1fr 1fr;
        column-gap: var(--space-lg);
    }

    .about-bento > .about-card--feature h2 { grid-column: 1 / -1; }
    .about-bento > .about-card--feature p { max-width: none; margin-bottom: 0; }

    .about-bento > .about-card--feature:first-child ~ :last-child:nth-child(even) {
        display: grid;
        grid-template-columns: minmax(12rem, 1fr) 2fr;
        column-gap: var(--space-lg);
        align-items: baseline;
    }

    .about-bento > .about-card--feature:first-child ~ :last-child:nth-child(even) h2 { margin: 0; }
}

/* ── Annuaire : mêmes champs que la recherche de lieux ──────────────────────────────────────────────────────
   Les filtres de l'annuaire gardaient les listes déroulantes du système (chevron natif, 13 px) à côté de champs
   « maison » partout ailleurs. Alignés sur `.lieu-search` (components/lieu-filters.css) : fond sable, 15 px,
   chevron dessiné, y compris en sombre. */
.bloc-annuaire__filtres input,
.bloc-annuaire__filtres select {
    font-size: 0.95rem;
    background-color: var(--c-sable-clair);
}

.bloc-annuaire__filtres select {
    appearance: none;
    padding-right: 2.3rem;
    background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='16'%20height='16'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%235a6b7a'%20stroke-width='2.5'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M6%209l6%206%206-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.7rem center;
    background-size: 15px 15px;
}

[data-theme="dark"] .bloc-annuaire__filtres input,
[data-theme="dark"] .bloc-annuaire__filtres select { background-color: var(--c-surface-2, #1d3242); }

[data-theme="dark"] .bloc-annuaire__filtres select {
    background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='16'%20height='16'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23a3b6c6'%20stroke-width='2.5'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M6%209l6%206%206-6'/%3E%3C/svg%3E");
}

/* ── Mon compte : cases à cocher et boutons radio à côté de leur libellé ────────────────────────────────────
   Le rendu par défaut de Symfony pose le libellé AU-DESSUS de la case (et chaque radio sur sa propre ligne,
   au-dessus de son texte) : on ne savait plus quelle case allait avec quelle phrase. Case à gauche, texte à
   droite, cible de clic de 44 px. */
.profile-form div:has(> input[type="radio"]) {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    column-gap: 0.65rem;
    row-gap: 0.25rem;
}

.profile-form div:has(> input[type="checkbox"]):not(:has(> input:not([type="checkbox"]))) {
    display: flex;
    align-items: center;
    gap: 0.65rem;
}

.profile-form div > input[type="checkbox"] { order: -1; }

.profile-form div:has(> input[type="radio"]) > label,
.profile-form div:has(> input[type="checkbox"]) > label {
    display: flex;
    align-items: center;
    min-height: 44px;
    margin: 0;
    font-weight: 500;
    cursor: pointer;
}

.profile-form div > input:is([type="radio"], [type="checkbox"]) {
    width: 1.25rem;
    height: 1.25rem;
    margin: 0;
    accent-color: var(--c-action);
}

/* ── Barre d'outils de l'accueil sur tablette ───────────────────────────────────────────────────────────────
   Entre 540 et 1023 px, « Trier | Pertinence » rallongeait la pastille de tri et « Voir la carte » partait seule
   sur une seconde ligne. Comme sur téléphone, la valeur du tri n'apparaît plus que dans le panneau ouvert :
   les cinq pastilles tiennent sur une ligne. */
@media (max-width: 1023px) {
    .toolbar-pill--sort:not([aria-expanded="true"]) .toolbar-pill__separator,
    .toolbar-pill--sort:not([aria-expanded="true"]) .toolbar-pill__sub { display: none; }
}

/* ── Fiche événement, carte « Partager » ───────────────────────────────────────────────────────────────────
   Écart titre → boutons de 40 px (marge du titre + écart du panneau), contre 16 px dans les autres cartes. */
.event-share-panel > .event-panel__title { margin-bottom: 0; }

/* ── Filtres annuaire et lieux sur tablette ─────────────────────────────────────────────────────────────────
   Annuaire : le bouton « Filtrer » partait seul sur une seconde ligne. Lieux : les trois champs côte à côte
   coupaient « Toutes les commun… » et le texte d'aide de la recherche. Entre 600 et 1023 px, la recherche prend
   toute la première ligne, les listes et le bouton se partagent la seconde. */
@media (min-width: 600px) and (max-width: 1023px) {
    .bloc-annuaire__filtres input[type="search"] { flex-basis: 100%; }
    .bloc-annuaire__filtres button { flex: 0 0 auto; }
    .lieu-search__field--text { flex-basis: 100%; }
    /* Les listes gardent leur libellé entier : faute de place, les boutons passent à la ligne. */
    .lieu-search__field:not(.lieu-search__field--text) { min-width: 12.5rem; }
}

/* ── Accueil, titre du héros sur ordinateur ─────────────────────────────────────────────────────────────────
   « près de chez vous ? » (≈ 760 px à 88 px) ne tenait pas dans la colonne de 510-680 px : « vous ? » tombait
   seul sur une troisième ligne. Déborder sur la photo ruinait le contraste en sombre ; la taille suit donc la
   largeur (≈ 72 px à 1280) pour garder les deux lignes voulues par le <br>. */
@media (min-width: 1024px) {
    .home-hero .home-hero__title { font-size: clamp(2.6rem, 5.6vw, 4.6rem); }
}

/* ── Formulaires « Proposer » : écart régulier entre les champs ─────────────────────────────────────────────
   Les champs posés seuls dans une section (Adresse, Téléphone, Site web) n'avaient aucun écart avec le suivant :
   « Site web » collait au champ Téléphone (10 px, contre 25 px partout ailleurs). */
.form-section > div:not([class]) + div { margin-top: 0.95rem; }

/* ── Newsletter : champ et bouton côte à côte ───────────────────────────────────────────────────────────────
   Dans la carte de la page Newsletter (≈ 300 px utiles), le champ réclamait 240 px et « S'inscrire » passait
   dessous, centré. Base plus courte : les deux restent sur une ligne, comme dans le pied de page. */
.newsletter-form__input { flex-basis: 10rem; }
.newsletter-form__submit { flex: 0 0 auto; }

/* ── Micro-interactions communes ────────────────────────────────────────────────────────────────────────────
   Retour tactile au toucher : boutons et pastilles s'enfoncent légèrement (propriété `scale`, indépendante des
   `transform` déjà posés par les composants — survol qui soulève, bouton flottant…). Cases et radios aux couleurs
   du site, sélection de texte teintée corail. Rien pour qui demande moins d'animations. */
:root { accent-color: var(--c-action); }

::selection { background: color-mix(in srgb, var(--c-corail) 30%, transparent); }

@media (prefers-reduced-motion: no-preference) {
    :where(.btn, button, .toolbar-pill, .filtre-actus__lien, .lieu-cat, .page-hero__pill, .event-share__btn,
           .barre-onglets__lien, .zone-tuile__fleche) {
        transition-property: scale, background-color, border-color, color, box-shadow, transform, opacity;
        transition-duration: 0.15s;
        transition-timing-function: var(--ease-out);
    }

    :where(.btn, button, .toolbar-pill, .filtre-actus__lien, .lieu-cat, .event-share__btn,
           .barre-onglets__lien):active:not(:disabled) { scale: 0.97; }
}

/* ── Cartes sans photo en tête de liste (téléphone) ─────────────────────────────────────────────────────────
   La carte vedette d'une liste (lieux par catégorie, événements) gardait un 4:3 de dégradé quand il n'y a pas de
   photo : ≈ 270 px de couleur avant le nom. Une seule colonne, aucun voisin à aligner : bandeau 5:2. Les cartes
   avec photo ne bougent pas (4:3 = format du recadrage). */
@media (max-width: 599px) {
    .events-grid .event-card__media:not(:has(img)) { aspect-ratio: 5 / 2; }
}

/* ── Mon compte et espace Pro, téléphone et tablette : menu des rubriques en grille ─────────────
   Le ruban horizontal cachait la moitié des rubriques (« Apparence », « QR code »… hors écran, fondu
   au bord). Comme dans le back-office 2026 : boutons sur deux colonnes, tout visible d'un coup d'œil,
   le dernier seul prend la ligne. Chiffres du haut sur une seule rangée quand il y en a trois. */
@media (max-width: 899px) {
    /* `html body` : pages/profile-forms.css est chargée après le bundle. */
    html body .profile-nav {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 0.45rem;
        overflow: visible;
        -webkit-mask-image: none;
        mask-image: none;
    }

    html body .profile-nav__link {
        min-height: 44px;
        padding: 0.5rem 0.75rem;
        color: var(--c-marine);
        white-space: normal;
        line-height: 1.2;
        border-radius: var(--radius-md);
    }


    .profile-stats:has(> .profile-stat:nth-child(3):last-child) {
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .profile-stats:has(> .profile-stat:nth-child(3):last-child) .profile-stat {
        min-width: 0;
        padding: 0.6rem 0.65rem;
    }
}

@media (max-width: 599px) {
    html body .profile-nav__link:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }

    .profile-stat dt {
        letter-spacing: 0.02em;
    }
}

@media (min-width: 600px) and (max-width: 899px) {
    html body .profile-nav {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

/* ── Pied de page, téléphone : plus ramassé ─────────────────────────────────────────────────────
   867 px de haut à 390 px, dont un grand vide sous la newsletter et des réseaux seuls sur leur ligne.
   La marque et les réseaux partagent la première ligne (dès 375 px : en dessous, quatre cibles de 44 px
   ne tiennent pas à côté du nom), l'accroche passe en petit corps, les blocs se resserrent. */
@media (max-width: 767px) {
    html body .site-footer__inner {
        gap: 1.1rem;
        padding-top: 1.25rem;
    }

    html body .site-footer__identity {
        gap: 0.6rem;
    }

    html body .site-footer__pitch {
        font-size: 0.86rem;
        line-height: 1.5;
    }
}

@media (min-width: 375px) and (max-width: 767px) {
    html body .site-footer__identity {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: center;
    }

    html body .site-footer__logo { grid-column: 1; grid-row: 1; }

    html body .site-footer__social {
        grid-column: 2;
        grid-row: 1;
        gap: 0.25rem;
        margin: 0;
    }

    html body .site-footer__pitch { grid-column: 1 / -1; }
}

/* ── Points d'intérêt : tuile de tête sans photo, en affiche ─────────────────────────────────────
   La tête de section prend la première fiche avec photo (lieu/index). Quand aucune n'en a (musées,
   fortifications…), la tuile 2/3 restait un aplat de 600 px au-dessus d'un petit titre. Le titre, la
   commune et l'accroche passent DANS la couverture, en bas, sur un dégradé : une affiche typographique. */
@media (min-width: 768px) {
    .events-grid--bento > .event-card-link:first-child:not(:has(img)) > .lieu-card {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: minmax(20rem, 1fr) auto auto auto;
        height: 100%;
        padding: 0;
        overflow: hidden;
    }

    .events-grid--bento > .event-card-link:first-child:not(:has(img)) {
        display: block;
        height: 100%;
    }

    .events-grid--bento > .event-card-link:first-child:not(:has(img)) > .lieu-card > .event-card__media {
        grid-row: 1 / -1;
        grid-column: 1;
        height: 100%;
        margin: 0;
        aspect-ratio: auto;
    }

    .events-grid--bento > .event-card-link:first-child:not(:has(img)) > .lieu-card > .event-card__media::after {
        content: "";
        position: absolute;
        inset: 40% 0 0;
        background: linear-gradient(to top, rgba(6, 30, 48, 0.82), transparent);
        pointer-events: none;
    }

    .events-grid--bento > .event-card-link:first-child:not(:has(img)) > .lieu-card > :not(.event-card__media) {
        position: relative;
        z-index: 1;
        grid-column: 1;
        margin-inline: 0;
        padding-inline: clamp(1.25rem, 2.5vw, 2rem);
        color: #fff;
    }

    .events-grid--bento > .event-card-link:first-child:not(:has(img)) .event-card__title {
        grid-row: 2;
        font-size: clamp(1.6rem, 2.6vw, 2.3rem);
        line-height: 1.1;
    }

    .events-grid--bento > .event-card-link:first-child:not(:has(img)) .event-card__ville { grid-row: 3; }

    .events-grid--bento > .event-card-link:first-child:not(:has(img)) .event-card__ville :is(svg, span) { color: inherit; }

    .events-grid--bento > .event-card-link:first-child:not(:has(img)) .event-card__description {
        grid-row: 4;
        display: -webkit-box;
        max-width: 60ch;
        margin-bottom: clamp(1.25rem, 2.5vw, 2rem);
        overflow: hidden;
        color: rgba(255, 255, 255, 0.88);
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 3;
        line-clamp: 3;
    }
}

/*
components/densite-mobile.css

QUOI : Densité téléphone (< 768 px) : marges, titres et en-têtes de page un cran plus serrés.

COMMENT : Racine à 15 px (le rem rétrécit, le texte courant est figé en px), puis on resserre les jetons d'espacement (--space-md/lg/xl, utilisés par les cartes, sections et formulaires)
          et les titres. Le texte courant (15 px), les champs (16 px, seuil de zoom iOS) et les zones tactiles
          (44 px) ne bougent pas. Les vignettes gardent leur 4/3 : c'est le ratio exact du recadrage admin.

POURQUOI : Demande d'Ellie (28/10/2026) : « sur mobile on a toujours tout en gros », dézoomer un peu sans
           perdre en lisibilité.
*/
@media (max-width: 767px) {
    /* Échelle générale 16 → 15 px : tout ce qui est en rem (marges, boutons, icônes, titres) perd ~6 %.
       Les jetons de texte courant sont repris en px équivalents 16 px pour ne PAS rapetisser la lecture. */
    html { font-size: 93.75%; }

    :root {
        --fs-xs:   clamp(11.5px, 11px + 0.15vw, 12.8px);
        --fs-sm:   clamp(13.1px, 12.6px + 0.18vw, 14.7px);
        --fs-base: clamp(15.2px, 14.7px + 0.20vw, 16.8px);
        --fs-md:   clamp(16.8px, 16px + 0.35vw, 20px);
        --space-md: 1.1rem;
        --space-lg: 1.85rem;
        --space-xl: 2.75rem;
        --fs-xl:  clamp(1.3rem, 1.1rem + 1.1vw, 2.15rem);
        --fs-2xl: clamp(1.6rem, 1.3rem + 1.8vw, 2.95rem);
        --fs-3xl: clamp(1.9rem, 1.5rem + 2.6vw, 3.70rem);
    }

    /* Titres de héros : 36 → 30 px (accueil), 31 → 27 px (pages). */
    body .home-hero .home-hero__title { font-size: clamp(1.75rem, 7.6vw, 2.4rem); }
    .page-hero__title { font-size: clamp(1.6rem, 6.8vw, 2rem); }

    /* Titres de section : 24-26 → 21 px (`html body` : modernite-2026 les fixe déjà avec `body`,
       pages/home-bento.css, chargée après le bundle, avec la section parente). */
    html body :is(.section-title, .section-heading__title, .home-map-section__title, .event-similar__title,
        .actualites-bloc__titre, .bloc-annuaire__titre, .partner-cell-section__title),
    body :is(.city-section, .events-section) .section-heading__title { font-size: 1.3rem; }

    /* Plancher des petites étiquettes : rien sous 11 px. */
    html body :is(.weekday__dow, .section-heading__count, .partner-cell__tag, .event-card__date-tile-m,
        .event-card__category, .lieu-card__credit, .home-hero__eyebrow, .page-hero__eyebrow, .back-link,
        .event-card__featured-badge, .tuile-proposer__surtitre, .event-date-tile__month, .event-info-item__label,
        .barre-onglets__lien span),
    html body :is(.events-grid > .event-card-link:not(:first-child), .events-grid .lead-aside > .event-card-link) .event-card:not(.event-card--compact) .event-card__category { font-size: 11px; }

    /* Tampon « Nouveau cette semaine » des bons plans : 0.6rem tombait à 9 px avec la racine à 15 px. */
    .prospectus__tampon { width: 5.4rem; height: 5.4rem; font-size: 11px; }
}

/* Style « magazine » commun (28/10/2026) : après densite-mobile, dont il reprend certains éléments. */
/*
editorial-2026.css

QUOI : Style « magazine de la côte » commun à tout le site public, décliné de l'accueil (pages/home-editorial.css) :
       - en-têtes de page (`.page-hero`) : photo de la côte voilée de marine au lieu du dégradé bleu → corail,
         surtitre précédé d'un filet (plus de point clignotant ni de filet lumineux animé), compteurs en texte
         séparés par « · » au lieu de pastilles, accent du titre en sable plein ;
       - compteur à côté des titres de section : chiffre en exposant, plus une pastille ;
       - Événements / Actualité commerciale : onglets soulignés ;
       - cartes d'événement (fond et cadre conservés, demande d'Ellie) : catégorie en surtitre puis date, sans
         tuile de date ni pastille de catégorie ; cœur sans compteur sur la vignette ; description sur 2 lignes.

COMMENT : Uniquement de la mise en forme. Préfixe `html body` : passe devant ergonomie-2026 et densite-mobile
          (même préfixe, chargés avant). Une page qui a sa photo (`.page-hero.has-photo`, `--hero-bg`) la garde ;
          les autres prennent la photo du Cap Blanc-Nez (public/img/cote-opale-blanc-nez.*, 2400 px, JackyM59,
          CC BY-SA 4.0 via Wikimedia Commons : crédit dans le pied de page).

OÙ : Paquet app.css, en dernier des composants 2026 (app.imports.css).

POURQUOI : Ellie (28/10/2026) : « refais toutes les pages » pour uniformiser avec le nouvel accueil, jugé
           moins « SaaS ».
*/

/* ── En-têtes de page ─────────────────────────────────────────────────────────────────────────────── */

html body .page-hero,
:root[data-theme="dark"] body .page-hero:not(.has-photo) {
    border-radius: 0;
    box-shadow: none;
    background:
        linear-gradient(90deg, rgba(6, 32, 50, 0.86) 0%, rgba(6, 32, 50, 0.6) 55%, rgba(6, 32, 50, 0.3) 100%),
        linear-gradient(180deg, rgba(6, 32, 50, 0) 40%, rgba(6, 32, 50, 0.45) 100%),
        var(--hero-bg, var(--photo-cote));
    background-size: auto, auto, cover;
    background-position: center, center, center 45%;
    background-repeat: no-repeat;
}

html body .page-hero__horizon,
html body .page-hero__pulse { display: none; }

html body .page-hero__eyebrow {
    color: rgba(255, 255, 255, 0.86);
}

html body .page-hero__eyebrow::before {
    content: "";
    width: 1.75rem;
    height: 1px;
    background: currentColor;
}

/* Photo des en-têtes ; la version 1200 px suffit sur téléphone et tablette. */
html body { --photo-cote: image-set(url("/img/cote-opale-blanc-nez.webp") type("image/webp"), url("/img/cote-opale-blanc-nez.jpg") type("image/jpeg")); }

@media (max-width: 900px) {
    html body {
        --photo-cote: image-set(url("/img/cote-opale-blanc-nez-1200.webp") type("image/webp"), url("/img/cote-opale-blanc-nez-1200.jpg") type("image/jpeg"));
    }
}

html body .page-hero__title { text-shadow: 0 2px 24px rgba(6, 32, 50, 0.35); }

html body .page-hero__accent {
    background: none;
    -webkit-text-fill-color: currentColor;
    color: #f3d9a4;
}

html body .page-hero .back-link { color: rgba(255, 255, 255, 0.86); }

html body .page-hero__meta { gap: 0 0.6rem; }

html body .page-hero__pill {
    padding: 0;
    background: none;
    border: 0;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    border-radius: 0;
    color: rgba(255, 255, 255, 0.92);
}

html body .page-hero__pill + .page-hero__pill::before {
    content: "·";
    margin-right: 0.6rem;
}

/* Fiches événement et lieu sans photo : même photo de la côte que les en-têtes de page, au lieu du dégradé de
   catégorie (événement) ou du bloc marine (lieu). */
html body .event-hero--no-image,
:root[data-theme="dark"] body .event-hero--no-image {
    background:
        linear-gradient(90deg, rgba(6, 32, 50, 0.86) 0%, rgba(6, 32, 50, 0.6) 55%, rgba(6, 32, 50, 0.3) 100%),
        var(--photo-cote) center 45% / cover no-repeat;
}

html body .event-hero--no-image .event-cover-abstract.event-hero__image { display: none; }

/* ── Bord à bord ──────────────────────────────────────────────────────────────────────────────────── */

/* Les en-têtes (page, fiche événement, fiche lieu) sortent de la colonne et vont d'un bord à l'autre de l'écran,
   collés sous la barre de navigation. Le texte reste aligné sur la colonne : le rembourrage latéral rattrape
   la marge (`50vw - 50%`). `overflow-x: clip` sur la racine : 100vw compte la barre de défilement sous
   Windows, sans lui on aurait 15 px de défilement horizontal. */
html { overflow-x: clip; }

html body :is(.page-hero, .event-hero) {
    width: auto;
    max-width: none;
    /* Sans ce zéro, `aspect-ratio` + `min-height` de la fiche événement imposaient une largeur minimale
       (230 px × 16/9 = 409 px) : l'en-tête dépassait de l'écran sur téléphone. */
    min-width: 0;
    margin-inline: calc(50% - 50vw);
    margin-top: 0;
    border-radius: 0;
}

html body .page-hero {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    min-height: clamp(300px, 42vh, 460px);
    padding-inline: calc(50vw - 50% + 0px);
    padding-top: clamp(1.25rem, 4vw, 2.5rem);
    padding-bottom: clamp(2rem, 5vw, 3.5rem);
}

html body .page-hero__topline { margin-bottom: auto; padding-bottom: 1.5rem; }

html body .page-hero__title {
    font-size: clamp(2.3rem, 5.4vw, 4.6rem);
    line-height: 1.02;
    max-width: 18ch;
}

html body .page-hero__intro {
    font-size: clamp(1rem, 1.3vw, 1.2rem);
    max-width: 52ch;
}

html body .event-hero { padding-inline: calc(50vw - 50%); }

/* Téléphone et tablette : hauteur posée en 16/9 de la largeur d'écran plutôt que par `aspect-ratio`, qui, avec
   le `min-height` de 230 px, élargissait l'en-tête au-delà de l'écran (409 px à 390 px). Même cadrage qu'avant. */
@media (max-width: 900px) {
    html body .event-hero:not(.event-hero--no-image) {
        aspect-ratio: auto;
        height: max(230px, 56.25vw);
    }
}
html body .event-hero__content { padding-inline: 0; }

html body .event-hero__title {
    font-size: clamp(2.2rem, 5vw, 4.4rem);
    line-height: 1.02;
}

@media (min-width: 901px) {
    html body .event-hero--no-image { min-height: 400px; }
}

/* La page commence par l'en-tête : plus de marge entre la barre de navigation et la photo. */
html body main:has(> .page-hero:first-child, > .event-hero:first-child, > .home-hero:first-child) { padding-top: 0; margin-top: 0; }

/* Mon compte, espace Pro : la bannière de la carte d'identité prend la photo de la côte (sauf couverture
   personnalisée de la page Pro, posée en style en ligne). Un peu plus haute, pour qu'elle se voie. */
html body .profile-hero__cover { height: clamp(120px, 20vw, 210px); }

html body .profile-hero__cover:not([style]) {
    background:
        linear-gradient(180deg, rgba(6, 32, 50, 0.15) 0%, rgba(6, 32, 50, 0.55) 100%),
        var(--photo-cote) center 40% / cover no-repeat;
}

/* Annuaire : fiches Page Pro au même cadre que les autres (plus de fond rosé ni de liseré corail) ; « ★ Page Pro »
   devient un surtitre corail en texte, comme la catégorie des cartes d'événement. */
html body .bloc-annuaire__item--page-pro a {
    border-color: var(--c-bordure);
    box-shadow: none;
    background: var(--c-surface);
}

html body .bloc-annuaire__page-pro {
    margin-left: 0;
    padding: 0;
    border-radius: 0;
    background: none;
    color: var(--c-corail-action);
    letter-spacing: 0.08em;
}

/* ── Titres de section, onglets ──────────────────────────────────────────────────────────────────── */

/* Même titre de rubrique que l'accueil : graisse 700, interlettrage serré, sans filet de couleur à gauche
   (/lieux) ; le nombre passe en exposant discret. */
html body :is(.section-title, .section-heading__title, .home-map-section__title, .event-similar__title,
    .actualites-bloc__titre, .bloc-annuaire__titre, .partner-cell-section__title) {
    font-weight: 700;
    letter-spacing: -0.03em;
}

html body .section-title.lieu-card::before { display: none; }

html body .section-title__count {
    margin-left: 0.5rem;
    font-size: 0.5em;
    vertical-align: super;
}

/* Compteur à côté du titre : un chiffre discret, plus une pastille. */
html body .section-heading__count {
    background: none;
    padding: 0;
    margin-left: 0.5rem;
    font-size: 0.5em;
    font-weight: 600;
    letter-spacing: 0;
    vertical-align: super;
    color: var(--c-texte-doux);
}

/* Événements / Actualité commerciale : onglets soulignés, plus un interrupteur à pastilles. */
html body .filtre-actus {
    background: none;
    border: 0;
    border-bottom: 1px solid rgba(10, 61, 98, 0.14);
    border-radius: 0;
    box-shadow: none;
    padding: 0;
    gap: 1.5rem;
}

html body .filtre-actus__lien {
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    padding: 0.55rem 0;
    margin-bottom: -1px;
    border-bottom: 2px solid transparent;
    color: var(--c-texte-doux);
}

html body .filtre-actus__lien.is-active {
    background: none;
    box-shadow: none;
    border-color: transparent;
    border-bottom-color: var(--c-marine);
    color: var(--c-marine);
    font-weight: 700;
}

html body .filtre-actus__nb {
    background: none;
    padding: 0;
    color: inherit;
    opacity: 0.7;
}

/* ── Cartes d'événement ───────────────────────────────────────────────────────────────────────────── */

html body .event-card-link:hover .event-card__title { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.18em; }

/* Plus de liseré de couleur à gauche : un filet fin tout autour ; la catégorie garde sa couleur dans le surtitre.
   La carte « Incontournable » garde son cadre doré. */
html body .event-card:not(.event-card--featured) { border: 1px solid var(--c-bordure); }

html body .event-card__title { font-size: clamp(1.1rem, 1.25vw, 1.3rem); }

/* Tuile de date retirée : la ligne « catégorie · date » dit la même chose. */
html body .event-card__date-tile { display: none; }

/* Catégorie en surtitre, date en dessous : deux lignes partout (une ligne « catégorie · date » se coupait
   sur les périodes longues, et la coupure décalait les titres de toute la rangée). */
html body .event-card__heading-text { gap: 0.15rem; }

html body .event-card__heading-text .event-card__category {
    background: none;
    box-shadow: none;
    padding: 0;
    border-radius: 0;
    color: var(--cat-fond, var(--c-marine));
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

html body .event-card__title { letter-spacing: -0.015em; }

/* Marques de la ligne de commune : chevron inutile (toute la carte est un lien), ◐ sans pastille. */
html body .event-card__click-chevron { display: none; }

html body .event-card__own-badge {
    background: none;
    color: var(--c-texte-doux);
    box-shadow: none;
}

/* Cœur seul sur la vignette. */
html body .like-btn--card .like-btn__count { display: none; }

html body .event-card__description {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
}


/* ── Blocs de contenu (fiche événement, fiche lieu, à propos, newsletter, pages légales) ──────────── */

/* Titre de bloc en surtitre, comme « À la une » du prospectus : petites capitales espacées, sans barre corail. */
html body :is(.event-panel__title, .about-card h2, .bento-card h2, .bento-card h3) {
    display: block;
    padding-left: 0;
    border-left: 0;
    font-family: var(--font-body, inherit);
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--c-marine);
}

html body .event-panel__title::before { display: none; }

/* Blocs de texte : ce ne sont pas des liens, ils ne se soulèvent plus au survol. */
html body :is(.about-card, .bento-card):hover { transform: none; }

/* ── Listes (ville, catégorie, arrondissement, accueil) : l'événement à la une en affiche ─────────── */

/* La grande tuile de tête (2/3 de la largeur) gardait une photo de 400 px au-dessus d'un petit bloc de texte. Elle
   devient une affiche, comme la une d'un guide de sorties : la photo occupe toute la tuile, la catégorie, la date,
   le titre en grand et la commune sont posés dessus, en bas, sur un voile. La photo reste recadrée (cover), jamais
   étirée. Ordinateur et tablette ; sur téléphone, la carte normale reste plus lisible. */
@media (min-width: 768px) {
    html body :is(.events-grid--bento > .event-card-link:first-child:has(.event-card__media img), .lieux-grille:not(.lieux-grille--liste) > .event-card-link:first-child) { display: block; height: 100%; }

    html body :is(.events-grid--bento > .event-card-link:first-child:has(.event-card__media img), .lieux-grille:not(.lieux-grille--liste) > .event-card-link:first-child) > .event-card {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: minmax(24rem, 1fr) auto auto auto auto;
        height: 100%;
        padding: 0;
        overflow: hidden;
    }

    html body :is(.events-grid--bento > .event-card-link:first-child:has(.event-card__media img), .lieux-grille:not(.lieux-grille--liste) > .event-card-link:first-child) .event-card__media {
        grid-row: 1 / -1;
        grid-column: 1;
        height: 100%;
        margin: 0;
        aspect-ratio: auto;
        border-radius: inherit;
    }

    html body :is(.events-grid--bento > .event-card-link:first-child:has(.event-card__media img), .lieux-grille:not(.lieux-grille--liste) > .event-card-link:first-child) .event-card__media img { width: 100%; height: 100%; object-fit: cover; }

    html body :is(.events-grid--bento > .event-card-link:first-child:has(.event-card__media img), .lieux-grille:not(.lieux-grille--liste) > .event-card-link:first-child) .event-card__media::after {
        content: "";
        position: absolute;
        inset: 35% 0 0;
        background: linear-gradient(to top, rgba(6, 30, 48, 0.88), rgba(6, 30, 48, 0.4) 55%, transparent);
        pointer-events: none;
    }

    html body :is(.events-grid--bento > .event-card-link:first-child:has(.event-card__media img), .lieux-grille:not(.lieux-grille--liste) > .event-card-link:first-child) .event-card > :not(.event-card__media, .event-card__featured-badge, .quick-edit) {
        position: relative;
        z-index: 1;
        grid-column: 1;
        margin-inline: 0;
        padding-inline: clamp(1.25rem, 2.5vw, 2.25rem);
        color: #fff;
    }

    html body :is(.events-grid--bento > .event-card-link:first-child:has(.event-card__media img), .lieux-grille:not(.lieux-grille--liste) > .event-card-link:first-child) .event-card__header { grid-row: 2; }
    /* Classe doublée : bento-shared (« .taxonomy-page .events-grid > … :first-child … ») est plus spécifique. */
    html body :is(.events-grid--bento > .event-card-link:first-child:has(.event-card__media img), .lieux-grille:not(.lieux-grille--liste) > .event-card-link:first-child) .event-card .event-card__title.event-card__title { grid-row: 3; font-size: clamp(1.8rem, 3.2vw, 3rem); line-height: 1.05; letter-spacing: -0.03em; color: #fff; }
    html body :is(.events-grid--bento > .event-card-link:first-child:has(.event-card__media img), .lieux-grille:not(.lieux-grille--liste) > .event-card-link:first-child) .event-card__ville { grid-row: 4; }
    html body :is(.events-grid--bento > .event-card-link:first-child:has(.event-card__media img), .lieux-grille:not(.lieux-grille--liste) > .event-card-link:first-child) .event-card__ville :is(svg, span) { color: inherit; }
    html body :is(.events-grid--bento > .event-card-link:first-child:has(.event-card__media img), .lieux-grille:not(.lieux-grille--liste) > .event-card-link:first-child) .event-card__heading-text .event-card__category,
    html body :is(.events-grid--bento > .event-card-link:first-child:has(.event-card__media img), .lieux-grille:not(.lieux-grille--liste) > .event-card-link:first-child) .event-card__date { color: rgba(255, 255, 255, 0.9); }

    html body :is(.events-grid--bento > .event-card-link:first-child:has(.event-card__media img), .lieux-grille:not(.lieux-grille--liste) > .event-card-link:first-child) .event-card__description {
        grid-row: 5;
        max-width: 60ch;
        margin-bottom: clamp(1.25rem, 2.5vw, 2.25rem);
        color: rgba(255, 255, 255, 0.88);
    }
}

/* ── Fiche événement (et fiche lieu, mêmes blocs) ──────────────────────────────────────────────────────────────────────────────── */

/* Colonne principale en article, comme un magazine : la description et le partage sortent de leur boîte,
   le texte grandit. La carte (plan) et la colonne « Infos pratiques » gardent leur cadre : ce sont des outils. */
html body :is(.event-main, .event-detail__main) > .event-card-panel:not(.event-map-panel) {
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    padding: 0;
}

html body :is(.event-main, .event-detail__main) > .event-card-panel:not(.event-map-panel) + .event-card-panel:not(.event-map-panel) {
    padding-top: var(--space-md);
    border-top: 1px solid var(--c-bordure);
}

html body :is(.event-description, .lieu-description) {
    font-size: clamp(1.05rem, 1.2vw, 1.2rem);
    line-height: 1.7;
    max-width: 62ch;
}

/* Infos pratiques toujours visibles au défilement (ordinateur), sous la barre de navigation collante. */
@media (min-width: 901px) {
    html body .event-sidebar { top: 5.5rem; }
}

/* « Voir plus de Musique », « Tous les événements à Calais » : grands liens de fin d'article, sans émoji ni boîte. */
html body .event-context-nav__link {
    background: none;
    border: 0;
    border-top: 1px solid var(--c-bordure);
    border-radius: 0;
    box-shadow: none;
    padding: 1.1rem 0;
}

html body .event-context-nav__icon { display: none; }

html body .event-context-nav__text strong {
    font-family: var(--font-display);
    font-size: clamp(1.4rem, 2.4vw, 2rem);
    letter-spacing: -0.03em;
}

html body .event-context-nav__text strong::after { content: " →"; }

html body .event-context-nav__link:hover strong,
html body .event-context-nav__link:focus-visible strong { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 0.15em; }

/* ── À propos, mentions légales, confidentialité ─────────────────────────────────────────────────── */

/* Plus de mosaïque de boîtes : une suite de rubriques numérotées, titre à gauche et texte à droite, séparées par
   un filet, comme les pages « à propos » des magazines. La newsletter (qui contient un formulaire) garde ses
   deux cartes. */
html body :is(.about-bento, main.bento-page:not(:has(form)) .bento-grid) {
    display: block;
    counter-reset: rubrique;
    max-width: 68rem;
    margin-inline: auto;
}

html body :is(.about-bento .about-card, main.bento-page:not(:has(form)) .bento-card) {
    display: grid;
    grid-template-columns: 1fr;
    column-gap: clamp(1.5rem, 4vw, 4rem);
    margin: 0;
    padding: clamp(1.4rem, 3vw, 2.2rem) 0;
    background: none;
    border: 0;
    border-top: 1px solid var(--c-bordure);
    border-radius: 0;
    box-shadow: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    counter-increment: rubrique;
}

html body :is(.about-bento .about-card, main.bento-page:not(:has(form)) .bento-card) > :not(h2) {
    grid-column: 1;
    /* En em, pas en ch : le « 0 » d'Instrument Sans est large, 62ch laissaient passer 93 caractères. */
    max-width: 32em;
    font-size: 1.05rem;
    column-count: auto;
}

html body :is(.about-bento .about-card, main.bento-page:not(:has(form)) .bento-card) > h2::before {
    content: counter(rubrique, decimal-leading-zero);
    display: block;
    margin-bottom: 0.35rem;
    font-family: var(--font-display);
    font-size: 2.2rem;
    font-weight: 700;
    letter-spacing: -0.03em;
    color: var(--c-corail-action);
}

@media (min-width: 900px) {
    html body :is(.about-bento .about-card, main.bento-page:not(:has(form)) .bento-card) {
        grid-template-columns: 15rem minmax(0, 1fr);
    }

    html body :is(.about-bento .about-card, main.bento-page:not(:has(form)) .bento-card) > h2 {
        grid-column: 1;
        grid-row: 1 / span 20;
        align-self: start;
    }

    /* ergonomie-2026 mettait la mission sur deux colonnes et la dernière carte en 12rem / 2fr. */
    html body .about-bento > .about-card--feature:first-child ~ .about-card:last-child:nth-child(even),
    html body .about-bento > .about-card.about-card--feature {
        grid-template-columns: 15rem minmax(0, 1fr);
        column-gap: clamp(1.5rem, 4vw, 4rem);
        align-items: start;
    }

    html body .about-bento > .about-card--feature > p + p { margin-top: 1rem; }

    html body :is(.about-bento .about-card, main.bento-page:not(:has(form)) .bento-card) > :not(h2) { grid-column: 2; }
}

/* Rubrique sans titre (page 404) : une seule colonne, sans filet. */
html body main.bento-page:not(:has(form)) .bento-card:not(:has(> h2)) {
    display: block;
    border-top: 0;
}

/* Newsletter : l'argumentaire sort de sa boîte (texte plus grand, sur le fond de page), le formulaire reste une
   carte : c'est lui qu'on doit voir. */
html body main.bento-page:has(form) .bento-grid > .bento-card:not(:has(form)) {
    background: none;
    border: 0;
    box-shadow: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    padding-inline: 0;
}

html body main.bento-page:has(form) .bento-grid > .bento-card:not(:has(form)) > p {
    font-size: clamp(1.05rem, 1.3vw, 1.2rem);
}

html body main.bento-page:has(form) .bento-grid > .bento-card:has(form) {
    box-shadow: 0 24px 60px -30px rgba(10, 61, 98, 0.45);
    border-top: 4px solid var(--c-corail-action);
}

/* Mission : en chapô, plus grand. */
html body .about-bento > .about-card--feature > p:first-of-type {
    font-family: var(--font-display);
    font-size: clamp(1.3rem, 2vw, 1.65rem);
    line-height: 1.4;
    letter-spacing: -0.015em;
    color: var(--c-marine);
}

/* ── /lieux : barre de recherche dans l'en-tête photo ─────────────────────────────────────────────── */

/* Une seule barre blanche, segmentée comme les moteurs des sites de voyage : « Rechercher | Catégorie | Commune |
   Trier | Autour de moi | Filtrer ». Petits libellés au-dessus des valeurs, champs sans cadre. Sous 900 px, la barre
   devient une carte : le champ texte sur toute la largeur, puis commune et tri côte à côte, puis les boutons. */
html body .page-hero .lieu-search {
    --barre-fond: #fff;
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 72rem;
    margin: clamp(1.25rem, 3vw, 2rem) 0 0;
    padding: 0.5rem;
    background: var(--barre-fond);
    border: 0;
    border-radius: 22px;
    box-shadow: 0 18px 44px -18px rgba(6, 32, 50, 0.6);
    color: var(--c-texte);
}

:root[data-theme="dark"] body .page-hero .lieu-search { --barre-fond: #15232f; }

html body .page-hero .lieu-search__row { gap: 0; align-items: stretch; }

html body .page-hero .lieu-search__field {
    gap: 0.1rem;
    padding: 0.45rem 1rem;
    border-radius: 16px;
}


html body .page-hero .lieu-search__field label {
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--c-marine);
}

html body .page-hero .lieu-search :is(input[type="search"], select) {
    min-height: 32px;
    padding-block: 0;
    padding-left: 0;
    /* Opaque (pas transparent) : Chrome peint le panneau déroulant d'un select avec ce fond. */
    background-color: var(--barre-fond);
    border: 0;
    border-radius: 0;
    box-shadow: none;
    font-size: 1rem;
}

html body .page-hero .lieu-search input[type="search"] { padding-left: 1.6rem; }
html body .page-hero .lieu-search__icon { left: 0; }

html body .page-hero .lieu-search__actions {
    gap: 0.4rem;
    padding: 0.25rem;
}

html body .page-hero .lieu-search__actions .btn { min-height: 48px; border-radius: 999px; padding-inline: 1.3rem; }

@media (min-width: 900px) {
    html body .page-hero .lieu-search { border-radius: 999px; }
    html body .page-hero .lieu-search__row { flex-wrap: nowrap; }
    html body .page-hero .lieu-search__field { flex: 1 1 12rem; border-radius: 0; }
    html body .page-hero .lieu-search__field--text { flex: 2 1 16rem; padding-left: 1.4rem; }
    html body .page-hero .lieu-search__field:has(#lieu-ville) { flex: 1.4 1 13rem; }
    html body .page-hero .lieu-search__field + .lieu-search__field { border-left: 1px solid var(--c-bordure); }
}

@media (max-width: 899.98px) {
    html body .page-hero .lieu-search__field--text { flex-basis: 100%; border-bottom: 1px solid var(--c-bordure); border-radius: 16px 16px 0 0; }
    html body .page-hero .lieu-search__field:not(.lieu-search__field--text) { flex: 1 1 40%; }
    html body .page-hero .lieu-search__actions { flex: 1 1 100%; justify-content: flex-end; border-top: 1px solid var(--c-bordure); padding-top: 0.5rem; }
}

/* ── /lieux : grille de lieux seuls ───────────────────────────────────────────────────────────────── */

html body .lieux-grille {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-md);
}

@media (min-width: 600px) {
    html body .lieux-grille { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
    html body .lieux-grille { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    /* Affiche sur deux colonnes seulement ici : sur deux colonnes (tablette), six fiches font trois rangées pleines. */
    html body .lieux-grille:not(.lieux-grille--liste) > .event-card-link:first-child { grid-column: span 2; }
}

/* Colonne à droite de l'affiche : les deux fiches suivantes empilées (ordinateur). En dessous de 1024 px, elle
   s'efface (`display: contents`) et ses fiches rejoignent la grille. */
html body .lieux-grille > .lead-aside { display: contents; }

@media (min-width: 1024px) {
    html body .lieux-grille:not(.lieux-grille--liste) > .lead-aside {
        display: flex;
        flex-direction: column;
        gap: var(--space-md);
        min-width: 0;
    }

    html body .lieux-grille > .lead-aside > .event-card-link { flex: 1 1 auto; display: flex; }
    html body .lieux-grille > .lead-aside > .event-card-link > .event-card { flex: 1 1 auto; }

    /* Une seule fiche à côté de l'affiche : elle garde sa hauteur, sans grand blanc étiré sous son texte. */
    html body .lieux-grille > .lead-aside > .event-card-link:only-child { flex: 0 0 auto; }
}

/* ── « Votre photo ici ? » : choix du lieu (lieu/photo_choisir) ──────────────────────────────────── */

html body .lphoto-choix { max-width: 44rem; margin-inline: auto; }
html body .lphoto-choix .form-row { display: grid; grid-template-columns: 1fr; gap: 0.45rem; }
html body .lphoto-choix .form-row label { font-size: 1.05rem; font-weight: 700; color: var(--c-marine); }
html body .lphoto-choix select { min-height: 52px; font-size: 1rem; }

/* ── /lieux par commune : index en colonnes, lieux en liste compacte ──────────────────────────────── */

html body .lieux-communes {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr));
    align-items: start;
    gap: var(--space-lg) var(--space-md);
}

html body .lieux-communes > .events-section { margin: 0; padding: 0; }

html body .lieux-communes .section-title {
    margin-bottom: 0.6rem;
    padding-bottom: 0.4rem;
    border-bottom: 1px solid var(--c-bordure);
    font-size: clamp(1.25rem, 1.6vw, 1.5rem);
}

html body .lieux-communes .lieux-grille { display: flex; flex-direction: column; gap: 0.5rem; }

html body .lieux-communes .lieu-card {
    display: grid;
    grid-template-columns: 4.5rem minmax(0, 1fr);
    grid-template-rows: auto auto;
    align-items: center;
    column-gap: 0.85rem;
    min-height: 0;
    height: auto;
    padding: 0.45rem;
    border-radius: 14px;
}

html body .lieux-communes .lieu-card .event-card__media {
    grid-row: 1 / span 2;
    width: 4.5rem;
    height: 4.5rem;
    margin: 0;
    aspect-ratio: 1;
    border-radius: 10px;
    overflow: hidden;
}

html body .lieux-communes .lieu-card .event-card__media img { width: 100%; height: 100%; object-fit: cover; }

html body .lieux-communes .lieu-card :is(.event-card__description, .event-card__ville, .lieu-card__credit, .lieu-card__glyphe, .lieu-card__badge) { display: none; }

html body .lieux-communes .lieu-card .event-card__title { grid-column: 2; grid-row: 1 / span 2; align-self: center; margin: 0; padding: 0; font-size: 1rem; line-height: 1.25; }

/* ── /lieux : « Voir les 22 lieux → » sous chaque catégorie en vue d'ensemble ─────────────────────── */

html body .lieux-voir-tout { margin: var(--space-sm) 0 0; text-align: right; }

html body .lieux-voir-tout a {
    font-family: var(--font-display);
    font-size: clamp(1.1rem, 1.6vw, 1.35rem);
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--c-marine);
    text-decoration: none;
}

html body .lieux-voir-tout a:hover { text-decoration: underline; text-underline-offset: 0.15em; }

/* ── Formulaire « Proposer » : sommaire des étapes (form-submission/steps.js) ─────────────────────── */

html body .submission-steps {
    margin-bottom: var(--space-md);
    padding: var(--space-md);
    background: var(--c-surface);
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-lg);
}

html body .submission-steps__titre {
    margin: 0 0 0.6rem;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--c-marine);
}

html body .submission-steps__barre {
    height: 6px;
    overflow: hidden;
    background: color-mix(in srgb, var(--c-marine) 10%, transparent);
    border-radius: 999px;
}

html body .submission-steps__barre > span {
    display: block;
    width: 0;
    height: 100%;
    background: var(--c-corail-action);
    border-radius: inherit;
    transition: width 0.3s ease;
}

html body .submission-steps__compte {
    margin: 0.45rem 0 0.75rem;
    font-size: 0.85rem;
    color: var(--c-texte-doux);
}

html body .submission-steps__liste {
    display: grid;
    gap: 0.15rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

html body .submission-steps__item a {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    min-height: 44px;
    padding: 0.35rem 0.5rem;
    border-radius: var(--radius-md);
    color: var(--c-texte);
    text-decoration: none;
}

html body .submission-steps__item a:hover { background: color-mix(in srgb, var(--c-marine) 6%, transparent); }

html body .submission-steps__num {
    display: grid;
    place-items: center;
    flex: none;
    width: 1.75rem;
    height: 1.75rem;
    border: 1.5px solid var(--c-bordure-champ, var(--c-bordure));
    border-radius: 50%;
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--c-texte-doux);
}

html body .submission-steps__libelle small { color: var(--c-texte-doux); font-size: 0.78rem; }

html body .submission-steps__item.is-current a { background: color-mix(in srgb, var(--c-marine) 8%, transparent); font-weight: 700; color: var(--c-marine); }
html body .submission-steps__item.is-current .submission-steps__num { border-color: var(--c-marine); color: var(--c-marine); }

/* Étape remplie : la pastille passe au vert avec une coche (le numéro reste lu par les lecteurs d'écran). */
html body .submission-steps__item.is-done .submission-steps__num {
    background: #2e8a55;
    border-color: #2e8a55;
    color: transparent;
    position: relative;
}

html body .submission-steps__item.is-done .submission-steps__num::after {
    content: "✓";
    position: absolute;
    color: #fff;
    font-size: 0.95rem;
}

/* Téléphone et tablette : le sommaire complet tombe dans l'aperçu replié ; une barre compacte suit le défilement. */
html body .submission-steps-mobile { display: none; }

@media (max-width: 959.98px) {
    html body .event-preview .submission-steps { display: none; }

    html body .submission-steps-mobile {
        display: block;
        position: sticky;
        top: 62px;
        z-index: 5;
        grid-column: 1 / -1;
        margin: 0 calc(-1 * var(--space-sm)) var(--space-sm);
        padding: 0.6rem var(--space-sm) 0.7rem;
        background: color-mix(in srgb, var(--c-sable-clair) 92%, transparent);
        -webkit-backdrop-filter: blur(8px);
        backdrop-filter: blur(8px);
        border-bottom: 1px solid var(--c-bordure);
    }

    html body .submission-steps-mobile__texte {
        margin: 0 0 0.4rem;
        font-size: 0.85rem;
        font-weight: 700;
        color: var(--c-marine);
    }
}

/* ── Mode sombre ──────────────────────────────────────────────────────────────────────────────────── */

:root[data-theme="dark"] body .event-card__heading-text .event-card__category { color: var(--c-marine); }
:root[data-theme="dark"] body .filtre-actus { border-bottom-color: rgba(160, 196, 224, 0.16); }

/* Crédit de la photo des en-têtes (licence CC BY-SA 4.0), dans la ligne du copyright. */
html body .site-footer__credit a { color: inherit; text-decoration: underline; text-underline-offset: 0.15em; }

/* ── /ou : arrondissements en cartes photo ────────────────────────────────────────────────────────── */

/* Comme les pages « destinations » des sites de voyage : grande photo, nom posé dessus, compteurs en surtitre. La
   photo est celle de l'arrondissement (admin « Images »), sinon la couverture d'un de ses événements, sinon la
   côte (`--photo-cote`). `object-fit: cover` : jamais déformée. 3 + 2 cartes, la rangée de 2 en plus large. */
html body .zone-tuiles { gap: var(--space-md); }
html body .zone-tuiles > li { flex: 1 1 320px; }

html body .zone-tuile {
    display: flex;
    align-items: flex-end;
    gap: var(--space-sm);
    min-height: clamp(15rem, 26vw, 20rem);
    padding: clamp(1.1rem, 2vw, 1.6rem);
    overflow: hidden;
    isolation: isolate;
    border: 0;
    border-radius: var(--radius-lg);
    background: #0b2c44 var(--photo-cote) center 45% / cover no-repeat;
    color: #fff;
}

html body .zone-tuile::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(180deg, rgba(6, 32, 50, 0.05) 25%, rgba(6, 32, 50, 0.82) 100%);
}

html body .zone-tuile__photo {
    position: absolute;
    inset: 0;
    z-index: -2;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.6s var(--ease-out);
}

html body .zone-tuile__texte { display: grid; gap: 0.3rem; flex: 1 1 auto; min-width: 0; }
html body .zone-tuile__texte > * { grid-area: auto; }

html body .zone-tuile__compte {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.86);
}

html body .zone-tuile__nom {
    font-size: clamp(1.6rem, 2.6vw, 2.2rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.05;
    color: #fff;
}

html body .zone-tuile__villes {
    margin: 0;
    padding: 0;
    border: 0;
    color: rgba(255, 255, 255, 0.86);
}

html body .zone-tuile__fleche { flex: 0 0 auto; background: #fff; color: #0b2c44; }

@media (hover: hover) {
    html body .zone-tuile:hover .zone-tuile__photo { transform: scale(1.04); }
}

/* ── Pages de confirmation : « Et maintenant ? » ─────────────────────────────────────────────────── */

/* En-tête photo commun, coche dans le titre ; dessous, la suite en trois étapes numérotées (la première cochée),
   reliées par un filet, puis les boutons. Sur téléphone, les étapes s'empilent et le filet devient vertical. */
html body .confirmation__coche {
    display: inline-grid;
    place-items: center;
    width: 0.9em;
    height: 0.9em;
    margin-right: 0.15em;
    vertical-align: -0.08em;
    border-radius: 50%;
    background: #3f8f5a;
    color: #fff;
}

html body .confirmation__coche svg { width: 0.55em; height: 0.55em; }

html body .confirmation__corps {
    max-width: 62rem;
    margin: clamp(2rem, 5vw, 3.5rem) 0 var(--space-2xl, 4rem);
}

html body .etapes-suite__titre {
    margin: 0 0 1.5rem;
    font-size: clamp(1.5rem, 2.6vw, 2.1rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    color: var(--c-marine);
}

html body .etapes-suite__liste {
    display: grid;
    gap: 1.25rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

html body .etapes-suite__etape {
    position: relative;
    display: grid;
    grid-template-columns: 2.5rem minmax(0, 1fr);
    align-content: start;
    column-gap: 1rem;
    row-gap: 0.2rem;
}

html body .etapes-suite__num {
    grid-row: span 2;
    display: grid;
    place-items: center;
    width: 2.5rem;
    height: 2.5rem;
    border: 2px solid var(--c-marine);
    border-radius: 50%;
    background: var(--c-fond, var(--c-surface));
    font-weight: 800;
    color: var(--c-marine);
}

html body .etapes-suite__etape.is-done .etapes-suite__num { border-color: #3f8f5a; background: #3f8f5a; color: #fff; }
html body .etapes-suite__num svg { width: 1.2rem; height: 1.2rem; }

html body .etapes-suite__nom { margin: 0.45rem 0 0; font-weight: 800; font-size: 1.05rem; color: var(--c-texte); }
html body .etapes-suite__texte { margin: 0; max-width: 32em; line-height: 1.55; color: var(--c-texte-doux); }

/* Filet entre les étapes : vertical sur téléphone, horizontal dès 768 px. */
html body .etapes-suite__etape:not(:last-child)::after {
    content: "";
    position: absolute;
    left: calc(1.25rem - 1px);
    top: 2.75rem;
    bottom: -1rem;
    width: 2px;
    background: var(--c-bordure);
}

@media (min-width: 768px) {
    html body .etapes-suite__liste { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2rem; }
    html body .etapes-suite__etape { grid-template-columns: minmax(0, 1fr); }
    html body .etapes-suite__num { grid-row: auto; margin-bottom: 0.5rem; }
    html body .etapes-suite__etape:not(:last-child)::after { left: 3.25rem; right: -1.25rem; top: calc(1.25rem - 1px); bottom: auto; width: auto; height: 2px; }
}

html body .confirmation__encart {
    margin-top: 2.25rem;
    padding: 1.25rem 1.5rem;
    border: 1px solid var(--c-bordure);
    border-radius: var(--radius-lg);
    background: var(--c-surface);
    text-align: left;
}

html body .confirmation__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
    margin-top: 2.25rem;
}

/* ── /annuaire : recherche dans l'en-tête, répertoire en fiches-lignes ────────────────────────────── */

/* Barre de /lieux : Nom ou activité | Secteur | Ville | Filtrer. */
html body .page-hero .annuaire-recherche .lieu-search__field:has(#annuaire-page-theme) { flex: 1.3 1 13rem; }

/* Répertoire façon annuaire imprimé, modernisé : plus de petites boîtes sur 5 colonnes, des lignes séparées par un
   filet fin sur 1 à 3 colonnes, initiale en grand rond, nom bien lisible, puis activité et ville. Les fiches avec
   une page Pro gardent leur initiale pleine et le surtitre « ★ Page Pro ». */
html body .annuaire-fiches {
    grid-template-columns: minmax(0, 1fr);
    gap: 0 clamp(1.5rem, 3vw, 2.5rem);
    margin-top: clamp(1.5rem, 4vw, 2.5rem);
}

@media (min-width: 700px) { html body .annuaire-fiches { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { html body .annuaire-fiches { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

html body .annuaire-fiches .bloc-annuaire__item a,
html body .annuaire-fiches .bloc-annuaire__item--page-pro a,
html body .annuaire-fiches .bloc-annuaire__item--premium a {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 5.5rem;
    padding: 1rem 0.5rem 1rem 4.25rem;
    background: none;
    border: 0;
    border-top: 1px solid var(--c-bordure);
    border-radius: 0;
    box-shadow: none;
}

html body .annuaire-fiches .bloc-annuaire__mono {
    top: 50%;
    left: 0.25rem;
    width: 3.1rem;
    height: 3.1rem;
    border-radius: 50%;
    font-size: 1.3rem;
    transform: translateY(-50%);
}

html body .annuaire-fiches .bloc-annuaire__nom {
    order: 1;
    font-size: 1.05rem;
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: -0.01em;
}

html body .annuaire-fiches .bloc-annuaire__page-pro { order: 0; margin: 0 0 0.15rem; font-size: 0.68rem; }
html body .annuaire-fiches .bloc-annuaire__soustitre { order: 2; margin-top: 0.1rem; font-size: 0.88rem; line-height: 1.4; }
html body .annuaire-fiches .bloc-annuaire__ville {
    order: 3;
    margin-top: 0.2rem;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

@media (hover: hover) {
    html body .annuaire-fiches .bloc-annuaire__item a:hover { background: color-mix(in srgb, var(--c-mer) 5%, transparent); }
    html body .annuaire-fiches .bloc-annuaire__item a:hover .bloc-annuaire__nom { text-decoration: underline; text-underline-offset: 0.18em; }
}

/* Téléphone : le secteur prend toute la largeur (ses libellés sont longs), la ville et « Filtrer » partagent la
   dernière ligne. */
@media (max-width: 899.98px) {
    html body .page-hero .annuaire-recherche .lieu-search__field:has(#annuaire-page-theme) { flex-basis: 100%; border-bottom: 1px solid var(--c-bordure); }
    html body .page-hero .annuaire-recherche .lieu-search__field:has(#annuaire-page-ville) { flex: 1 1 0; min-width: 0; }
    html body .page-hero .annuaire-recherche .lieu-search__actions { flex: 0 0 auto; align-self: center; border-top: 0; padding-top: 0.25rem; }
}

/* Bandeau « Il manque une adresse ? » intercalé dans la liste, une fois par page : toute la largeur de la grille,
   fond marine, gros titre et bouton corail, pour qu'on le voie sans chercher (demande d'Ellie, 29/10/2026). */
html body .annuaire-fiches > .annuaire-proposer {
    grid-column: 1 / -1;
    position: relative;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem clamp(1.5rem, 4vw, 3rem);
    margin: 1.25rem 0;
    padding: clamp(1.4rem, 3vw, 2.2rem) clamp(1.25rem, 4vw, 2.75rem);
    overflow: hidden;
    border-radius: var(--radius-lg);
    background: linear-gradient(120deg, #0b2c44 0%, #0a3d62 60%, #11557f 100%);
    color: #fff;
}

html body .annuaire-proposer__icone {
    position: absolute;
    right: clamp(-2rem, -1vw, 0rem);
    bottom: -2.5rem;
    width: 11rem;
    height: 11rem;
    color: rgba(255, 255, 255, 0.08);
    pointer-events: none;
}

html body .annuaire-proposer__texte { flex: 1 1 22rem; min-width: 0; position: relative; }
html body .annuaire-proposer__texte p { margin: 0; }

html body .annuaire-proposer__surtitre {
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #f3d9a4;
}

html body .annuaire-proposer__titre {
    margin-top: 0.3rem !important;
    font-family: var(--font-display);
    font-size: clamp(1.35rem, 2.4vw, 1.9rem);
    font-weight: 800;
    line-height: 1.15;
    letter-spacing: -0.02em;
}

html body .annuaire-proposer__sous { margin-top: 0.45rem !important; max-width: 40em; color: rgba(255, 255, 255, 0.85); }

html body .annuaire-proposer__btn {
    position: relative;
    flex: 0 0 auto;
    min-height: 48px;
    padding-inline: 1.4rem;
    border: 0;
    border-radius: 999px;
    background: var(--c-corail-action);
    color: #fff;
    font-weight: 800;
}

html body .annuaire-proposer__btn:hover,
html body .annuaire-proposer__btn:focus-visible { background: var(--c-corail-action-fonce); color: #fff; }

@media (max-width: 599.98px) {
    html body .annuaire-proposer__btn { flex: 1 1 100%; justify-content: center; }
}

/* ── Jetons de l'ancienne DA côté public ─────────────────────────────────────────────────────────── */

/* Quelques blocs publics repris de l'ancienne DA (page « Personnaliser » de l'espace Pro, pastille « en cours »
   de la fiche événement) parlent encore en `--da-*`, jetons définis seulement dans le back-office : côté site,
   ils tombaient à vide (texte clair sur fond blanc, fonds transparents). Alias vers la palette actuelle. */
html body:not(.admin-body) {
    --da-encre: var(--c-marine);
    --da-creme: #fff;
    --da-carte: var(--c-surface);
    --da-trait: var(--c-bordure);
    --da-jaune: #f3d9a4;
    --da-corail: var(--c-corail-action);
    --da-outremer: var(--c-mer);
    --da-ombre-s: none;
}

:root[data-theme="dark"] body:not(.admin-body) {
    --da-encre: #e8eef3;
    --da-creme: #0c1620;
    --da-jaune: rgba(243, 217, 164, 0.22);
}

/* Annuaire : le logo du pro à la place de l'initiale — rond, fond blanc, logo entier (jamais déformé). */
html body .bloc-annuaire__item .bloc-annuaire__mono--logo,
html body .bloc-annuaire__item--page-pro .bloc-annuaire__mono--logo {
    object-fit: contain;
    padding: 4px;
    background: #fff;
    border: 1px solid var(--c-bordure);
    border-radius: 50%;
}

/* ── Encarts « nos partenaires » (fiche événement, pages ville) ──────────────────────────────────── */

/* Carte blanche à filet fin comme les autres cartes du site (plus de dégradé bleu pâle) ; niveau de présence en
   surtitre texte au lieu d'une pastille jaune. */
html body .partner-cell,
:root[data-theme="dark"] body .partner-cell {
    background: var(--c-surface);
    border: 1px solid var(--c-bordure);
    border-radius: 14px;
}

html body .partner-cell__tag,
html body .partner-cell__tag--premium {
    padding: 0;
    background: none;
    border-radius: 0;
    font-size: 0.66rem;
    font-weight: 800;
    letter-spacing: 0.1em;
    color: var(--c-corail-texte);
}

html body .partner-cell__theme { color: var(--c-texte-doux); }
html body .partner-cell__link:not(.partner-cell__link--static):hover { background: color-mix(in srgb, var(--c-mer) 5%, transparent); }

/* Quatre partenaires : deux rangées de deux, plutôt que trois puis un seul étiré sur toute la largeur. */
@media (min-width: 700px) {
    html body .partner-cell-grid:has(> :nth-child(4):last-child) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}


/* EN DERNIER, volontairement : cette règle relève la taille des champs de saisie sous le
   seuil de zoom automatique d'iOS, elle doit donc passer après tous les composants qui fixent
   leur propre taille. Voir base/ios-zoom.css. */
/*
ios-zoom.css

QUOI : Garantit qu'aucun champ de saisie ne descend sous 16 px sur mobile.

COMMENT : Safari iOS zoome automatiquement sur un champ dont la taille de police est INFÉRIEURE à
          16 px au moment où il reçoit le focus — et ne dézoome jamais quand le clavier se referme.
          Le visiteur reste coincé sur une page agrandie et décalée. Ce n'est pas un réglage
          d'utilisateur ni une préférence : c'est un seuil codé en dur dans le navigateur.

          `max(16px, 1em)` et non `16px` sec — mais sans se raconter d'histoire sur ce que ça fait :
          `1em` vaut la taille HÉRITÉE du parent, pas celle du champ. Concrètement, sur mobile tous les
          champs s'alignent donc à 16 px, sauf ceux placés dans un contexte typographique délibérément
          plus grand, qui le suivent. Les écarts réellement observés sont de l'ordre du demi-pixel
          (16,32 px → 16 px sur la recherche d'accueil) : la lisibilité mobile y gagne, le dessin n'y
          perd rien.

          `!important` est ici délibéré, et n'est pas un raccourci pour éviter de comprendre la
          cascade. La règle n'exprime pas une préférence de design mais une CONTRAINTE de plateforme,
          et elle doit gagner contre des dizaines de sélecteurs de composants qui fixent chacun leur
          propre taille, avec des spécificités variées (`.discovery .search-input`,
          `.submission-form input[type="text"]`, `.poi-field input[type="email"]`…) et répartis dans
          trois bundles distincts. Un audit du 2026-09-09 en dénombrait 29 sous le seuil. Les reprendre
          un par un aurait laissé le prochain champ écrit retomber dans le même piège — c'est le genre
          de règle qui doit tenir par construction, pas par vigilance.

          Cases à cocher, boutons radio, curseurs et sélecteurs de fichier sont exclus : ils
          n'ouvrent pas de clavier, ne déclenchent donc pas le zoom, et leur taille de police pilote
          l'apparence de leur libellé.

OÙ : importé par les TROIS manifestes (`app.imports.css`, `nav.imports.css`, `admin.imports.css`) —
     on saisit du texte sur le site public, dans l'en-tête et dans le back-office.

POURQUOI : signalé en production le 2026-09-09 sur le champ de l'assistant, puis retrouvé sur 28
           autres champs. Corriger le champ signalé seul aurait déplacé le problème d'un formulaire à
           l'autre sans jamais le clore.
*/

@media (max-width: 600px) {
    input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]),
    textarea,
    select {
        font-size: max(16px, 1em) !important;
    }
}

