/* ============================================================
   LCDI — TOKENS DU CHILD THEME (É4, bloc 1 · socle)
   NE PAS ÉDITER À LA MAIN. Ce fichier est le TRANSPORT de
   `design-system/tokens.css` (source de vérité, É2 close au gate 2 du 05/08).

   Ce qui change entre la source et ici, et rien d'autre :
   1. COUCHE 1 — les hex ne vivent plus dans un CSS : ils sont des presets
      `theme.json` (`settings.color.palette`, slugs `brand-*`). Les variables de
      la couche 1 deviennent donc un PONT vers ces presets. Une seule définition
      des couleurs dans tout le socle, et c'est theme.json.
   2. `--signature-motif` — chemin remappé vers les assets du child theme
      (le DS l'annonce lui-même : « chemin remappé par le child theme à l'É4 »).
   3. `--brand-alerte-encre` — cartographié sur le preset `brand-alerte` :
      le DS lui donne la MÊME valeur (« pas de 2e rouge »), donc pas de 2e preset.

   Les couches 2 et 3 (rôles sémantiques, plomberie universelle, typographie,
   formes, mouvement, contextes `data-theme`, parade AA, accessibilité,
   mouvement réduit) sont transportées VERBATIM. Toute correction de design
   se fait dans `design-system/tokens.css`, jamais ici : la sonde
   `deploy/sonde-socle.php` échoue si les deux fichiers divergent.

   Rejouer le contrôle : ./deploy/wp-local.sh eval-file deploy/sonde-socle.php
   ============================================================ */

:root {

  /* ------------------------------------------------------------
     COUCHE 1 — LE PONT VERS LES PRESETS theme.json
     Les valeurs (et leurs commentaires d'usage : interdits de contraste,
     rôles) vivent dans `design-system/tokens.css` § COUCHE 1 et dans
     `theme.json`. Ici, uniquement la correspondance.
     ------------------------------------------------------------ */
  --brand-maillot:        var(--wp--preset--color--brand-maillot);
  --brand-maillot-fonce:  var(--wp--preset--color--brand-maillot-fonce);
  --brand-maillot-encre:  var(--wp--preset--color--brand-maillot-encre);
  --brand-bitume:         var(--wp--preset--color--brand-bitume);
  --brand-beton:          var(--wp--preset--color--brand-beton);
  --brand-poussiere:      var(--wp--preset--color--brand-poussiere);
  --brand-nuit:           var(--wp--preset--color--brand-nuit);
  --brand-givre:          var(--wp--preset--color--brand-givre);
  --brand-aube:           var(--wp--preset--color--brand-aube);
  --brand-blanc:          var(--wp--preset--color--brand-blanc);
  --brand-alerte:         var(--wp--preset--color--brand-alerte);
  --brand-valide:         var(--wp--preset--color--brand-valide);
  --brand-info:           var(--wp--preset--color--brand-info);
  --brand-veille:         var(--wp--preset--color--brand-veille);
  --brand-veille-encre:   var(--wp--preset--color--brand-veille-encre);
  /* même valeur que --brand-alerte dans le DS : « pas de 2e rouge » */
  --brand-alerte-encre:   var(--wp--preset--color--brand-alerte);

  /* ------------------------------------------------------------
     SIGNATURE — « le galet et l'initiale »
     L'audace de cette DA n'est pas une couleur ni un dégradé : c'est une
     GÉOMÉTRIE et une lettre. Trois marqueurs relevés, tous propriétaires :
       1. le galet : rayon asymétrique 20/20/90 sur les photos (21 éléments
          rendus sur la seule page d'accueil) ;
       2. l'initiale colorée : le 1er caractère des titres de section en accent
          (31 occurrences en palette1, + variantes claires sur fond sombre) ;
       3. le picto vélo : seul motif de marque hors logo, en tête de pied.
     Le relevé porte 6 autres rayons asymétriques ponctuels (0/0/0/30, 30/0/0,
     50/0/0, 0/0/0/20, 0/20/0/0, 0/0/20) : le contrat « rayons rationalisés »
     les absorbe tous dans le galet et son miroir.
     ------------------------------------------------------------ */
  --signature-galet:        20px 20px 90px;   /* le geste, relevé tel quel */
  --signature-galet-miroir: 90px 20px 20px;   /* son reflet, pour les compositions alternées */
  --signature-initiale:     var(--brand-maillot);       /* sur fond clair */
  --signature-initiale-nuit: var(--brand-blanc);        /* sur fond sombre (relevé : palette9 sur nuit) */
  --signature-motif:        url("../img/picto-velo-1-2024.png");  /* chemin remappé par le child theme à l'É4 */

  /* Voile de scène du héros : la seule « signature en dégradé » du système,
     écrite en BORNES REMAPPABLES (jamais un gradient monolithique) : un
     contexte remappe une borne, tout suit.
     PLANCHER MESURÉ : alpha .55 est la valeur la plus légère qui garde le texte
     inverse à 4,5:1 dans le pire cas (pixel de photo blanc sous le voile).
     GATE 2 (05/08, verdict Julien) : .40 retenu à l'œil sur le média réel
     (vidéo de course sombre), le .62 initial jugé trop lourd. SOUS le plancher
     pire-cas : le H1 (61 px bold, seuil 3:1) tient largement ; GARDE-FOU
     D'USAGE : tout petit texte inverse posé sur un média CLAIR se vérifie à la
     maquette (batterie), et les scènes à texte dense montent à .72. */
  --scene-a:            rgba(4, 4, 30, .40);
  --scene-b:            rgba(4, 4, 30, .66);
  --signature-scene:    linear-gradient(180deg, var(--scene-a) 0%, var(--scene-b) 100%);

  /* ------------------------------------------------------------
     COUCHE 2 — TOKENS SÉMANTIQUES (les rôles, remappables par contexte)
     Noms standard du design system : NE PAS renommer.
     ------------------------------------------------------------ */
  --surface-page:     var(--brand-aube);
  --surface-warm:     var(--brand-givre);      /* surface alternée : rangée « Vous aimerez aussi », panneau de profil */
  --surface-raised:   var(--brand-blanc);      /* cartes, panneaux, modales */
  --surface-inverse:  var(--brand-bitume);     /* l'inverse du monde COURANT : il bascule avec le contexte */
  --surface-night:    var(--brand-nuit);       /* le monde sombre : héros, badges, popups */

  /* --- RÔLES NON BASCULANTS -------------------------------------------
     TROUVÉS PAR L'AUTO-CRITIQUE NAVIGATEUR DU 05/08, pas par raisonnement :
     le pied rendait BLANC SUR BLANC et le titre du héros #111111 sur #111111.
     Cause : le chrome du site (header, pied, héros) consommait `--surface-inverse`
     et `--text-inverse`, qui sont des rôles RELATIFS — dans un contexte de nuit,
     « l'inverse » bascule au clair, ce qui est juste pour le rôle et faux pour
     le chrome. Or le chrome de LCDI est sombre dans TOUS les mondes.
     D'où ces trois rôles, qui ne basculent jamais et sont re-déclarés à
     l'identique dans chaque contexte pour être immunisés. */
  --surface-structure: var(--brand-bitume);  /* le chrome permanent : header, pied, héros plein */
  --text-on-structure: var(--brand-aube);    /* texte du chrome (navigation, bouton compte) — valeur relevée #f5f8f9 */
  --text-on-night:     var(--brand-blanc);   /* texte posé sur une surface sombre permanente (pied, badge, légende sur voile) — valeur relevée #ffffff */
  /* panneau posé sur nuit + sa bordure — teintés de la lueur claire, jamais de
     blanc pur opaque. Mesuré : texte inverse sur ce panneau = 18,15:1 */
  --surface-night-raised: rgba(255, 255, 255, .06);
  --border-night:         rgba(255, 255, 255, .15);

  --text-strong:      var(--brand-bitume);     /* titres. 17,69:1 sur la page */
  --text-body:        var(--brand-beton);      /* corps. 9,13:1 sur la page */
  --text-muted:       var(--brand-gravillon);  /* [AJOUT 18/08] encre secondaire de PETIT texte : mentions, étiquettes, métadonnées de ligne. 5,38 / 5,74 / 4,69:1 sur les trois fonds clairs — AA en texte courant, contrairement à `--text-soft` */
  --text-soft:        var(--brand-poussiere);  /* mentions. 3,32:1 : GRAND TEXTE OU DÉCOR, jamais du corps */
  --text-inverse:     var(--brand-blanc);

  --accent:           var(--brand-maillot);       /* aplats, fonds, filets, icônes sur nuit */
  --accent-strong:    var(--brand-maillot-fonce); /* survols */
  --accent-ink:       var(--brand-maillot-encre); /* le teal qui a le droit de porter du texte sur clair */
  --accent-alt:       var(--brand-nuit);          /* 2e accent : le bleu nuit (badges, ombres). La DA n'a pas de 3e couleur */
  --link:             var(--accent-ink);          /* 5,30:1 — corrigé (plomberie, voir en-tête § régime 1) */
  --link-hover:       var(--brand-maillot-fonce);
  --link-inverse:     var(--brand-maillot);       /* sur nuit, le teal d'origine passe à 7,02:1 */

  --border-soft:      var(--brand-givre);      /* 1,15:1 : filet DÉCORATIF, jamais seul porteur d'information */
  --border-strong:    var(--brand-poussiere);  /* 3,54:1 : le filet qui a le droit de délimiter un contrôle */
  --border-accent:    var(--brand-maillot);

  /* LE CHAMP DE SAISIE A SES DEUX RÔLES PROPRES — [AJOUT 19/08, retouche T8].
     MOTIF DE NAISSANCE, et il vient du vécu : dans la modale d'inscription, les
     trois champs étaient INVISIBLES tant qu'on ne cliquait pas dedans. La modale
     est un voile `data-theme="nuit"` qui contient un dialogue `data-theme="jour"` ;
     `forms.css` habillait le champ de nuit par un SÉLECTEUR DESCENDANT
     (`[data-theme="nuit"] .lcdi-input`, spécificité 0,2,0), qui attrapait les
     champs À TRAVERS la frontière du thème jour — le dialogue déclarait son
     monde, la règle ne le respectait pas. Fond et filet de nuit sur panneau
     blanc : 1:1, un formulaire qui n'existe pas à l'œil.

     LA RÈGLE QUI EN SORT, et elle vaut pour toute déclinaison de thème : UNE
     DÉCLINAISON SE PORTE PAR TOKENS QUI BASCULENT À LA FRONTIÈRE DE THÈME LA
     PLUS PROCHE, JAMAIS PAR UN SÉLECTEUR QUI ÉNUMÈRE LE THÈME. Ces deux rôles
     sont redéclarés dans chaque contexte ci-dessous : l'héritage s'arrête donc
     de lui-même au `data-theme` du dialogue, sans que personne ait à y penser.
     Même famille que « le chrome dérive du contenu, jamais énuméré » et que le
     correctif « couche de page devant composant » du bloc T6b.

     POURQUOI DES RÔLES À EUX plutôt que la réutilisation de `--surface-raised`
     et `--border-strong` : un champ est un CONTRÔLE, pas un panneau. C'est lui
     que WCAG 1.4.11 vise (3:1 pour le contour d'un élément d'interface) et lui
     seul ; le jour où un contexte devra renforcer le filet d'un champ sans
     toucher aux filets décoratifs, il y a UN endroit pour le faire. */
  --field-surface:    var(--surface-raised);   /* le fond d'un champ de saisie */
  --field-border:     var(--border-strong);    /* son filet : 3,54:1 sur le blanc du panneau */

  /* Le CTA est LE geste du site (l'adhésion, la commande) : il ne change JAMAIS
     de couleur, quel que soit le contexte de page — y compris sur nuit.
     GATE 2 (05/08, verdict Julien) : GRAVÉ CONFIRMÉ en connaissance du 2,69:1.
     DÉROGATION ASSUMÉE : la couleur de marque prime sur le ratio AA ; les
     alternatives ont été vues sur pièce (parade AA 5,30:1, texte nuit 7,02:1
     rejeté à l'œil). À porter en EXCEPTION DOCUMENTÉE à l'axe accessibilité
     de la recette É5, pas en échec. La parade AA reste ci-dessous.
     RE-CONFIRMÉ le 22/08 (verdict Julien, gate mission ② de la recette É4),
     en connaissance de la mesure complète (23 boutons, survol 3,76:1, bordure
     2,69:1, carte d'appel 2,87:1) et de l'option C intermédiaire (#4d7782,
     4,60:1) vue sur pièce. Décision finale présentée au client LCDI au point
     du 25/08 (3 options), consignée au CR : le choix appartient au client. */
  --cta-bg:           var(--brand-maillot);
  --cta-bg-hover:     var(--brand-maillot-fonce);
  --cta-text:         var(--brand-aube);
  --cta-border:       var(--brand-maillot);
  --cta-border-hover: var(--brand-maillot-fonce);

  /* VOIX DE BOUTONS — les RÔLES sont standard, les valeurs viennent du relevé.
     Le site en avait CINQ écritures (rayons 4/7/8, graisses 500/600, bordure
     simulée en box-shadow) : le contrat les ramène aux DEUX voix du système.
     Voix 2 relevée : blanc, bordure 2 px accent, texte accent, inversion au survol.
     ÉTATS POSSÉDÉS : chaque voix écrit SES hover/active/focus dans le registre,
     rien n'est hérité d'un thème parent. */
  --btn-secondary-bg:         var(--brand-blanc);
  --btn-secondary-border:     var(--brand-maillot);
  --btn-secondary-text:       var(--accent-ink);        /* corrigé : le texte de la voix 2 passe de 2,87 à 5,65:1 ; la BORDURE reste au teal d'origine (le rendu voulu ne bouge pas) */
  --btn-secondary-bg-hover:   var(--brand-maillot);     /* l'inversion relevée */
  --btn-secondary-text-hover: var(--brand-blanc);

  /* ANNEAU DE FOCUS — DOUBLE, et c'est une conclusion de mesure, pas un style :
     aucun ton unique n'est visible sur les trois fonds du site.
       sombre sur aube ..... 17,69:1   sombre sur nuit ..... 1,07:1  (invisible)
       clair  sur nuit ..... 20,17:1   clair  sur aube ..... 1,07:1  (invisible)
       sombre sur CTA ....... 6,58:1   clair  sur CTA ...... 2,87:1  (insuffisant)
     Le double anneau (lueur claire à l'intérieur, encre sombre à l'extérieur)
     est donc toujours porté par au moins une de ses deux bagues. */
  --focus-ring: 0 0 0 2px var(--brand-blanc), 0 0 0 5px var(--brand-bitume);
  --focus-ring-night: 0 0 0 2px var(--brand-nuit), 0 0 0 5px var(--brand-blanc);

  /* données de preuve (registre documentaire : € du catalogue, dates de validité,
     compteurs de dons, stock) */
  --data-ink:         var(--brand-bitume);
  --data-accent:      var(--accent-ink);   /* le prix : 5,65:1 au lieu de 4,01:1 */

  /* rampe d'état, en rôles (voir composant `status.css`) */
  --state-danger:       var(--brand-alerte);
  --state-danger-text:  var(--brand-alerte);
  --state-danger-veil:  rgba(184, 33, 5, .08);
  --state-success:      var(--brand-valide);
  --state-success-veil: rgba(19, 97, 46, .10);
  --state-info:         var(--brand-info);
  --state-info-veil:    rgba(17, 89, 175, .08);
  --state-warning:      var(--brand-veille);
  --state-warning-text: var(--brand-veille-encre);
  --state-warning-veil: rgba(247, 99, 12, .12);
  --state-neutral:      var(--brand-poussiere);
  --state-neutral-veil: rgba(136, 136, 136, .12);

  /* ------------------------------------------------------------
     COUCHE 2 — PLOMBERIE UNIVERSELLE (utilitaires)
     Toutes les cases du gabarit sont remplies ; les retraits sont justifiés.
     Recette : teinte = couche 1 ; alphas ajustés au constat.
     ------------------------------------------------------------ */

  /* voiles & scrims — teintés du pôle sombre de la DA (son bleu nuit) */
  --veil-night:       rgba(4, 4, 30, .8);    /* panneau translucide sur photo : légendes, frises */
  --veil-night-solid: rgba(4, 4, 30, .97);   /* barre quasi opaque : sticky de secours, bandeaux fixes */
  --scrim-modal:      rgba(4, 4, 30, .94);   /* fond de modale et de menu mobile. NOTE : le site rend
                                                aujourd'hui un overlay de popup en accent à opacité .7
                                                (relevé § 5.3) ; le système le ramène au scrim nuit,
                                                l'accent ne sert pas de rideau */
  /* voiles teintés accent — fonds discrets d'icônes, survols, pastilles */
  --veil-accent:       rgba(104, 161, 176, .10);  /* accent sur clair */
  --veil-accent-night: rgba(104, 161, 176, .16);  /* teinte d'interaction sur nuit */
  --veil-accent-alt:   rgba(4, 4, 30, .10);       /* 2e accent (le nuit) : encarts, survols de carte */
  --veil-media:        rgba(4, 4, 30, .18);       /* le voile de survol des images, relevé tel quel (.k-zoom) */

  /* LE VERRE — AMÉLIORATION gravée au gate 1 : le header devient translucide au
     défilement (aujourd'hui il n'a aucun état scrollé : ombre du collant nulle).
     Glassmorphisme MOTIVÉ, pas décoratif : le header est transparent sur les
     héros ; au défilement il doit reprendre du corps sans masquer la scène.
     Deux leviers, réglés sur la planche et CONFIRMÉS TELS QUELS AU GATE 2
     (05/08, verdict Julien : 14 px / 72 %). */
  --glass-blur: 14px;
  --glass-tint: rgba(4, 4, 30, .72);

  /* bordures translucides */
  --border-night-strong: rgba(255, 255, 255, .28);  /* champs et contours actifs sur nuit */
  --border-accent-night: rgba(104, 161, 176, .18);  /* filets teintés sur nuit : chrome, pied */
  --border-accent-alt:   rgba(4, 4, 30, .18);       /* filets du 2e accent : encarts, sceaux */
  --border-glass:        rgba(255, 255, 255, .5);   /* liseré sur surface riche : badges, header en verre */

  /* iconographie — icônes INFORMATIVES uniquement ; une icône INTERACTIVE
     (lien social, bouton) consomme --link, jamais --icon.
     L'accent d'origine ne passe pas le seuil non-texte sur fond clair (2,69:1) :
     `--icon` prend donc l'encre du teal. Sur nuit, l'accent d'origine passe
     (7,02:1) et reste. */
  --icon:         var(--accent-ink);
  --icon-inverse: var(--brand-maillot);

  /* ------------------------------------------------------------
     TYPOGRAPHIE
     Display : Roboto Slab (gravé). Corps : ROBOTO, duel Roboto vs Hanken
     Grotesk TRANCHÉ AU GATE 2 (05/08, verdict Julien, sur planche vivante).
     Anton : RETIRÉE par le gate 1 (les popups repassent en Roboto Slab).
     Aucune police mono : le relevé n'en montre aucune, on n'en introduit pas.
     Le registre documentaire (prix, dates, compteurs) s'écrit dans la police du
     corps avec des chiffres tabulaires — voir --numeric-data.
     ------------------------------------------------------------ */
  --font-display: "Roboto Slab", Georgia, serif;
  --font-body:    "Roboto", system-ui, -apple-system, sans-serif;
  --font-data:    var(--font-body);
  --numeric-data: tabular-nums;

  --weight-body:   400;
  --weight-medium: 500;
  --weight-strong: 600;
  --weight-title:  700;

  /* Échelle de type — UNIFIÉE EN REM ET FLUIDE (contrat « corrige » : plus de
     H5/H6 en px, plus de tailles posées bloc par bloc). Les bornes reproduisent
     exactement le relevé : min = la valeur mobile 390, max = la valeur desktop.
     Les 11 tailles hors échelle relevées (24.96, 26.88, 30, 32, 35, 45, 15.2,
     14.4, 22, 17.008, 12.8 px) n'ont plus de place : elles retombent sur le cran
     le plus proche. */
  --type-hero:     clamp(2rem, 1.33rem + 2.77vw, 3.815rem);       /* H1 : 32 → 61,04 px */
  --type-display:  clamp(1.85rem, 1.63rem + 0.90vw, 2.44rem);     /* H2 : 29,6 → 39,04 px */
  --type-title:    clamp(1.125rem, 0.92rem + 0.85vw, 1.68rem);    /* H3 : 18 → 26,88 px */
  --type-subtitle: clamp(1.125rem, 0.99rem + 0.57vw, 1.5rem);     /* H4 : 18 → 24 px */
  --type-h5:       1.25rem;    /* 20 px — était déclaré en px ; absorbe aussi les 16 occurrences de 20 px de l'espace adhérent */
  --type-h6:       1.125rem;   /* 18 px — était déclaré en px */
  --type-lead:     1.25rem;    /* 20 px — le chapô monte d'un cran puisque le corps passe à 18 px, sinon il perd son rôle */
  --type-body:     1.125rem;   /* 18 px — AMÉLIORATION gravée au gate 1 (était 16 px) */
  --type-caption:  .95rem;     /* 15,2 px — la mention du relevé, en rem */
  --type-fine:     .875rem;    /* 14 px — mentions de fiche produit, bandeau cookies */
  --type-data:     1.125rem;   /* 18 px — le prix de la boutique (Roboto 18/600) */
  --type-eyebrow:  1.125rem;   /* 18 px — le surtitre, seul style interlettré du site */
  --type-badge:    .6875rem;   /* 11 px — badge « Épuisé » */

  --lh-tight:  1.2;    /* H1 (relevé : 1.2em) */
  --lh-title:  1.25;   /* H2 */
  --lh-snug:   1.3;    /* H3-H4 */
  --lh-body:   1.6;    /* corps (relevé) */
  --lh-flat:   1;      /* boutons (relevé) */

  --ls-eyebrow: .15em;  /* SIGNATURE : le seul interlettrage du site (2,7 px à 18 px) */
  --ls-badge:   .06em;
  /* Aucun autre interlettrage : le relevé donne `letter-spacing: normal` sur
     tout le thème. Ne pas en introduire (c'est un fait de DA, pas un oubli). */

  /* ------------------------------------------------------------
     FORMES, PROFONDEUR, RYTHME
     Contrat « corrige » : rayons rationalisés (système 8 / signature 20-90,
     le reste se justifie ou disparaît).
     DISPARAISSENT : 15 px, 30 px, 50 px (mosaïque ponctuelle → le galet),
     3 px (flèches de carrousel, champs Fluent Forms), 2 px (CookieYes),
     5,6 px (recherche SureCart), 7 px (bouton Fluent Forms), 0,35em (SureCart).
     ------------------------------------------------------------ */
  --radius-s:   4px;    /* JUSTIFIÉ : les petits contrôles ont besoin d'un cran sous 8 px
                           (pastilles de variante, puces, coins de champ). Absorbe 2, 3, 5.6 et 7 px */
  --radius-m:   8px;    /* LE rayon système du site : 112 déclarations, 71 rendues */
  --radius-l:   20px;   /* la borne douce du galet, pour les grands panneaux */
  --radius-arc: 999px;  /* pastilles et boutons ronds : badge « Épuisé » (100 px relevé),
                           pagination fléchée (9999 px relevé), pastilles d'état */
  --radius-round: 50%;  /* cercles pleins : puces de carrousel, avatars ronds (13 rendus) */

  /* Ombres — TEINTÉES DU BLEU NUIT de la DA, jamais du gris sale.
     RETRAIT DU GATE 1 : l'ombre portée n'est plus généralisée à tous les
     boutons ; elle est RÉSERVÉE AU CTA. Les 17 éléments qui la portaient sur
     l'accueil la perdent. */
  --shadow-cta:       0 4px 10px rgba(0, 0, 0, .12);      /* l'ombre système relevée, désormais au seul CTA */
  --shadow-cta-hover: 0 6px 14px rgba(0, 0, 0, .14);      /* son survol, relevé */
  --shadow-soft:      0 8px 20px -12px rgba(4, 4, 30, .20);   /* objets posés : panneaux, sous-menus */
  --shadow-float:     0 12px 24px -8px rgba(4, 4, 30, .18);   /* survol des cartes produit, relevé tel quel */
  --shadow-deep:      0 32px 68px -36px rgba(4, 4, 30, .30);  /* grands panneaux : modales, encarts majeurs */
  --shadow-bar:       0 6px 24px -12px rgba(4, 4, 30, .35);   /* barres fixes : header en verre (AMÉLIORATION du gate 1 ;
                                                                 le collant actuel n'a aucune ombre) */
  --shadow-text:      0 1px 4px rgba(4, 4, 30, .6);       /* lisibilité d'un texte posé sur photo ou vidéo */
  --shadow-dot:       0 2px 8px rgba(4, 4, 30, .35);      /* petits contrôles : puces de carrousel */
  --shadow-inset:     inset 0 1px 3px rgba(4, 4, 30, .12);/* creux. NON EMPLOYÉ par la DA (le relevé donne une ombre
                                                             de champ neutre) ; case remplie, teinte alignée */
  --glow-accent:      0 0 10px 1px rgba(104, 161, 176, .55); /* halo ponctuel. NON EMPLOYÉ au temps 2 : le relevé n'a
                                                                aucun point lumineux. Disponible pour l'É3 */

  --space-1: .25rem;  --space-2: .5rem;  --space-3: .75rem;
  --space-4: 1rem;    --space-5: 1.5rem; --space-6: 2rem;
  --space-7: 3rem;    --space-8: 4.5rem; --space-9: 6.5rem;

  /* Gouttières : le site tient sur 32 / 16 px (relevé § 4.4). La boutique est
     la seule à 20 px — le contrat demande de trancher. Proposition portée par
     la planche : retour au système à 16 px. Arithmétique : 4 colonnes dans
     1242 px donnent des cartes de 298,5 px à 16 px de gouttière, contre
     295,5 px aujourd'hui à 20 px — l'écart est de 3 px, invisible, et le 20 px
     disparaît du système. */
  --gap-grid:       var(--space-6);   /* 32 px */
  --gap-grid-tight: var(--space-4);   /* 16 px */
  --gap-row:        var(--space-7);   /* 48 px — le row-gap large du relevé (64 px) ramené sur l'échelle */

  /* ------------------------------------------------------------
     RYTHME VERTICAL — l'échelle des espacements DANS une section
     Ajoutée au bloc 3c de l'É4 (06/08), sur relevé mesuré du child et du live.
     Aucun matériau nouveau : trois RÔLES posés sur des crans existants.

     CE QUE LE RELEVÉ DU 06/08 A TROUVÉ (sonde `probe-3c-child.js`, accueil à
     1440 et 1600) — deux sections sœurs, deux rythmes :
       colonne de contenu des bandes ... 16 px entre TOUS les blocs, sans
                                         distinction : surtitre→titre,
                                         titre→texte, texte→grille, grille→bouton
       « Événements passés » ........... 10 px surtitre→titre, 0 px titre→
                                         carrousel, 32 px carrousel→bouton
     Le premier n'a plus de hiérarchie (tout est à égale distance), le second
     n'a plus de règle du tout. Les deux se corrigent au CRAN COMMUN.

     LA RÈGLE, en une phrase : 16 px à l'intérieur d'un groupe (un surtitre, son
     titre, le bloc qu'il introduit), 32 px entre deux groupes.

     LES BANDES PLEINES SE TOUCHENT : le relevé du live donne un écart de 0 px
     entre TOUTES ses sections, et le child aussi. Il n'existe donc AUCUN
     espacement inter-sections dans ce système — les respirations vivent
     dedans, jamais entre. `--rythme-section` est la marge intérieure haute et
     basse d'une section, pas un écart entre deux.
     Mécanique : `layout.css`, classe `.lcdi-rythme`.
     ------------------------------------------------------------ */
  --rythme-titre:   var(--space-4);   /* 16 px — dans un groupe : surtitre, titre, son bloc */
  --rythme-bloc:    var(--space-6);   /* 32 px — d'un groupe au suivant */
  --rythme-section: var(--space-8);   /* 72 px — la respiration haute et basse d'une section */

  /* ------------------------------------------------------------
     DÉGAGEMENT DE PIED — l'air que la DERNIÈRE section réserve avant le pied
     Ajouté au bloc 3c (retouche 9, verdict de gate du 06/08).

     POURQUOI IL EXISTE : le picto vélo du pied REMONTE de 110 px dans la
     section qui le précède (`--footer-crest-pull`, relevé live). Si cette
     section ne réserve pas d'air en bas, le vélo va percuter son dernier
     contenu. Constaté sur la home : le bouton « Voir tous nos événements
     passés » était chevauché de 38 px par le vélo.

     LA VALEUR EST RELEVÉE, à deux largeurs, sur le live :
       1440 → 172 px entre le dernier contenu et le bas de la section
       1920 → 231 px
     Soit une pente de 59 px pour 480 px de largeur = 12,29 % du viewport.
     D'où le fluide `12.3vw`, qui EST la règle du live, pas une approximation :
     il redonne 172 et 231 aux deux points mesurés.
       plancher 6,5 rem (= --space-9, 104 px) — il protège le TÉLÉPHONE, où la
         remontée du picto n'est plus 110 px mais 74 px et où 12 vw ne vaudrait
         que 47 px : le vélo repasserait sur le contenu.
       plafond 231 px — la valeur relevée à 1920 ; au-delà, la page cesse de
         gagner de l'air, elle n'en a plus besoin.

     CE DÉGAGEMENT N'EST PAS UNE BANDE BLANCHE : il vit DANS la dernière
     section, donc son décor (fond, photo) continue jusqu'au noir du pied. La
     retouche 4 reste entière — blanc mesuré −34 px, fond du pied transparent.
     Mécanique et exception : `footer.css` § DÉGAGEMENT DE PIED.
     ------------------------------------------------------------ */
  --footer-clearance: clamp(6.5rem, 12.3vw, 231px);

  /* ------------------------------------------------------------
     LE CALQUE DU PIED — ajouté au bloc 3c (retouche 9bis, 06/08)
     Il répond à un défaut de PEINTURE, pas de géométrie : le vélo du pied ne
     mordait pas le noir, alors que toutes les boîtes disaient qu'il le
     recouvrait de 40 px. Compté sur les pixels rendus : 37 lignes de morsure
     visible sur le live, 3 chez nous.

     LA CAUSE, mesurée des deux côtés : nos sections sont `position: relative`
     (elles portent leurs coutures) et notre pied était `static`. Or un élément
     POSITIONNÉ se peint après les blocs en flux, même s'il vient AVANT dans le
     document : la dernière section, qui descend 34 px sous le haut de la rangée
     sombre, repeignait donc son décor par-dessus le noir. Le live fait
     l'inverse — c'est SA rangée sombre qui est `position: relative` (mesuré) —
     et son noir se voit dès le haut.

     POURQUOI UN CALQUE ET PAS UNE EXCEPTION : `.lcdi-band` aussi est
     positionnée. Toute page finissant par une bande aurait eu le même défaut.
     Un calque de pied règle la classe entière, une fois.

     LA VALEUR 3, et pourquoi elle n'est pas 1 : deux composants font
     délibérément remonter un z-index au niveau de la page — le contenu d'une
     section sur ses coutures (`.lcdi-section--media > *` et
     `.lcdi-stats-section__inner`, z-index 2), parce que leurs sections ne
     ferment pas de contexte d'empilement (c'est ce qui permet au vélo des
     chiffres clés de mordre le héros, acquis du bloc 3b : ne pas y toucher).
     Le pied doit passer devant ce 2. Voisinage, pour situer : header 100,
     tiroir mobile 300, lien d'évitement 400 — écrits en clair dans
     `header.css`, ils migreront vers cette échelle quand on y retouchera.
     ------------------------------------------------------------ */
  --layer-footer: 3;

  --container:        1290px;   /* relevé (défaut Kadence non personnalisé) → theme.json layout.contentSize */
  --container-narrow: 842px;
  --container-wide:   1520px;
  --page-edge:        var(--space-5);   /* 24 px, relevé */
  --page-edge-mobile: var(--space-4);   /* 16 px, relevé */

  /* Points de rupture — pour la documentation et le JS ; une media query ne
     peut pas lire une variable CSS, les composants les écrivent en dur.
     Relevé : 767 (mobile) · 1024 (tablette) · 1025 (desktop) · 1520 (débords).

     LE SEUIL GRAND ÉCRAN (ajout du bloc 3c de l'É4, 06/08) — MESURÉ AU PIXEL,
     pas estimé : bissection sur le site live, 1499 px → 3 cartes de bureau,
     1500 px → 4. C'est le seuil où le site bascule sa mise en page large
     (config Kadence xxl=4 / xl=3), et le gate l'a retenu comme seuil COMMUN de
     deux comportements : la densité de la piste du bureau (`carousel.css`) et
     l'apparition des photos latérales de « Sponsors » (`band.css`).
     RÈGLE : les deux fichiers l'écrivent en dur sous le même commentaire nommé
     — `/* seuil grand écran commun : 1500px, relevé live 06/08 */` — pour que
     la valeur reste cherchable et modifiable d'un seul geste. Ces deux px de
     media query sont une EXCEPTION STRUCTURELLE admise du diff de conformité :
     ils se consignent au rapport, ils ne s'absorbent pas. */
  --bp-mobile:      767px;
  --bp-tablet:      1024px;
  --bp-desktop:     1025px;
  --bp-grand-ecran: 1500px;
  --bp-wide:        1520px;

  /* ------------------------------------------------------------
     MOUVEMENT — CSS d'abord (décision 9). Ici les constantes ;
     l'orchestration vit à l'étape 3.
     Durées relevées sur le site : .25 s (cartes produit), .4 s (zoom d'image).
     ------------------------------------------------------------ */
  --ease-brand: cubic-bezier(.22, .8, .36, 1);  /* l'élan du peloton : départ franc, arrivée posée */
  --t-quick: 160ms;   /* micro-interactions : survol de lien, focus */
  --t-soft:  250ms;   /* survols composés : cartes, boutons (relevé) */
  --t-scene: 400ms;   /* séquences : zoom d'image, entrée de modale (relevé) */

  /* Leviers de mouvement lus par les composants — basculés en bloc par
     `prefers-reduced-motion` (voir fin de fichier). */
  --lift-btn:        -2px;   /* AMÉLIORATION gate 1 : soulèvement des boutons au survol */
  --lift-card:       -4px;   /* lévitation de la carte produit, relevée */
  --zoom-media:      1.08;   /* zoom d'image au survol, relevé */
  --hero-media-show: block;  /* la vidéo de fond du héros ; `none` en mouvement réduit */
  --countup-duration: 2000ms;/* compteurs animés de l'accueil ; 0 en mouvement réduit */
}

/* ============================================================
   CONTEXTE « NUIT » — le monde sombre réel du site
   Le héros de l'accueil (vidéo Vimeo sur fond #111111), les héros de page,
   le pied et les popups vivent en nuit. Le contexte REMAPPE LES RÔLES ;
   les composants ne changent pas.
   RÈGLE ABSOLUE : le CTA garde sa couleur — il n'est pas remappé ici.
   Sur nuit, l'accent d'origine redevient légitime en texte (7,02:1) : c'est
   le seul endroit du système où `--link` reprend le teal du relevé.
   ============================================================ */
[data-theme="nuit"] {
  --surface-page:     var(--brand-nuit);
  --surface-warm:     var(--brand-bitume);
  --surface-raised:   var(--surface-night-raised);
  --surface-inverse:  var(--brand-blanc);      /* il bascule : c'est son rôle */

  /* les trois rôles non basculants, re-déclarés à l'identique (immunité) */
  --surface-structure: var(--brand-bitume);
  --text-on-structure: var(--brand-aube);
  --text-on-night:     var(--brand-blanc);

  --text-strong:      var(--brand-blanc);
  --text-body:        var(--brand-blanc);
  --text-muted:       rgba(255, 255, 255, .82);  /* [AJOUT 18/08] symétrie du rôle en nuit : un cran sous le corps, jamais sous le plancher de lecture */
  --text-soft:        rgba(255, 255, 255, .72);
  --text-inverse:     var(--brand-bitume);

  --link:             var(--brand-maillot);       /* 7,02:1 */
  --link-hover:       var(--brand-givre);
  --icon:             var(--brand-maillot);       /* 7,02:1 */
  --icon-inverse:     var(--accent-ink);

  --border-soft:      var(--border-night);
  --border-strong:    var(--border-night-strong);

  /* Le champ posé sur nuit : c'est CE bloc qui le décide, et il s'arrête à la
     première frontière de thème rencontrée en descendant. */
  --field-surface:    var(--surface-night-raised);
  --field-border:     var(--border-night-strong);

  --btn-secondary-bg:         rgba(255, 255, 255, .06);
  --btn-secondary-border:     rgba(255, 255, 255, .28);
  --btn-secondary-text:       var(--brand-blanc);
  --btn-secondary-bg-hover:   rgba(255, 255, 255, .14);
  --btn-secondary-text-hover: var(--brand-blanc);

  --focus-ring:       var(--focus-ring-night);

  --data-ink:         var(--brand-blanc);
  --data-accent:      var(--brand-maillot);

  --signature-initiale: var(--signature-initiale-nuit);

  /* Rampe d'état sur nuit : les rouges et verts sombres de la palette
     deviennent illisibles ; l'état s'écrit alors en pastille pleine
     (voir `status.css`, variante `.is-on-night`). */
  --state-danger-veil:  rgba(184, 33, 5, .28);
  --state-success-veil: rgba(19, 97, 46, .28);
  --state-info-veil:    rgba(17, 89, 175, .28);
  --state-warning-veil: rgba(247, 99, 12, .28);
  --state-neutral-veil: rgba(255, 255, 255, .12);
}

/* ============================================================
   CONTEXTE « JOUR » — la ré-entrée dans le clair depuis une zone nuit
   Cas réel du site : une carte blanche posée dans un héros sombre, un panneau
   de contenu à l'intérieur du pied. Sans ce bloc, la carte hériterait des
   rôles de nuit et rendrait du texte blanc sur du blanc.
   Symétrie exigée par le skill : le contexte inverse s'écrit toujours.
   ============================================================ */
[data-theme="jour"] {
  --surface-page:     var(--brand-aube);
  --surface-warm:     var(--brand-givre);
  --surface-raised:   var(--brand-blanc);
  --surface-inverse:  var(--brand-bitume);

  /* les trois rôles non basculants, re-déclarés à l'identique (immunité) */
  --surface-structure: var(--brand-bitume);
  --text-on-structure: var(--brand-aube);
  --text-on-night:     var(--brand-blanc);

  --text-strong:      var(--brand-bitume);
  --text-body:        var(--brand-beton);
  --text-muted:       var(--brand-gravillon);  /* [AJOUT 18/08] */
  --text-soft:        var(--brand-poussiere);
  --text-inverse:     var(--brand-blanc);

  --link:             var(--accent-ink);
  --link-hover:       var(--brand-maillot-fonce);
  --icon:             var(--accent-ink);
  --icon-inverse:     var(--brand-maillot);

  --border-soft:      var(--brand-givre);
  --border-strong:    var(--brand-poussiere);

  /* LE CHAMP REVIENT AU JOUR AVEC SON DIALOGUE. C'est la ligne qui répare le
     défaut du 19/08 : sans elle, un champ posé dans une carte claire au milieu
     d'un monde sombre garderait le fond et le filet de nuit. */
  --field-surface:    var(--brand-blanc);
  --field-border:     var(--brand-poussiere);

  --btn-secondary-bg:         var(--brand-blanc);
  --btn-secondary-border:     var(--brand-maillot);
  --btn-secondary-text:       var(--accent-ink);
  --btn-secondary-bg-hover:   var(--brand-maillot);
  --btn-secondary-text-hover: var(--brand-blanc);

  --focus-ring:       0 0 0 2px var(--brand-blanc), 0 0 0 5px var(--brand-bitume);

  --data-ink:         var(--brand-bitume);
  --data-accent:      var(--accent-ink);

  --signature-initiale: var(--brand-maillot);

  --state-danger-veil:  rgba(184, 33, 5, .08);
  --state-success-veil: rgba(19, 97, 46, .10);
  --state-info-veil:    rgba(17, 89, 175, .08);
  --state-warning-veil: rgba(247, 99, 12, .12);
  --state-neutral-veil: rgba(136, 136, 136, .12);
}

/* ============================================================
   PARADE AA — le bloc que le gate 2 arbitre
   Le CTA gravé au gate 1 mesure 2,69:1 (texte #f5f8f9 sur #68a1b0), très
   au-dessous du seuil AA de 4,5:1 exigé pour un texte de 18 px en graisse 600.
   Deux paradés mesurées, aucune n'est appliquée par défaut :
     A. assombrir le FOND au 3e cran du teal : #f5f8f9 sur #3c6e7c = 5,30:1.
        Le bouton reste teal, il fonce. C'est la parade la plus proche du rendu
        voulu, et celle que la planche montre par défaut quand on l'active.
     B. inverser l'ENCRE : #111111 sur #68a1b0 = 6,58:1. Le fond ne bouge pas,
        le texte devient sombre. Rendu plus contrasté, plus éloigné du site actuel.
   Activation : poser `data-aa="on"` sur <html>. La planche de style le fait par
   un interrupteur, pour trancher sur pièce vivante.
   Si le gate 2 retient une parade, elle remonte dans :root et ce bloc disparaît.
   ============================================================ */
[data-aa="on"] {
  --cta-bg:           var(--brand-maillot-encre);
  --cta-bg-hover:     #2f5a66;                  /* [AJOUT] le cran sous l'encre, pour garder un survol perceptible */
  --cta-text:         var(--brand-aube);
  --cta-border:       var(--brand-maillot-encre);
  --cta-border-hover: #2f5a66;
  --btn-secondary-border: var(--brand-maillot-encre);
}

/* ============================================================
   ACCESSIBILITÉ — plancher non négociable
   Paires validées : voir l'en-tête de ce fichier et
   `preuves/wcag-contrastes.mjs` (61 paires, rejouable).
   Plomberie : texte sur --veil-night ≥ 4,5:1 (mesuré 8,65:1 dans le pire cas) ·
   --icon sur clair et --icon-inverse sur nuit ≥ 3:1 (5,30 et 7,02) ·
   focus visible sur clair, nuit et CTA (double anneau, voir plus haut).
   ============================================================ */
:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-s);
}

/* Le focus au clavier ne doit jamais être avalé par un parent qui coupe :
   les composants qui débordent posent `isolation: isolate`, pas `overflow: hidden`
   sur un élément focusable (règle d'usage, voir la planche). */

@media (prefers-reduced-motion: reduce) {
  :root {
    --t-quick: .01ms;
    --t-soft:  .01ms;
    --t-scene: .01ms;
    --lift-btn:  0px;
    --lift-card: 0px;
    --zoom-media: 1;
    --hero-media-show: none;    /* la vidéo de fond du héros ne se joue pas : le fond
                                   d'attente #111111 et l'image de secours tiennent la scène */
    --countup-duration: 0ms;    /* les compteurs affichent directement leur valeur */
  }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}
