/* ============================================================================
 * web-edition-a11y.css — surcouche pour mecultiver.com
 * ----------------------------------------------------------------------------
 * Se charge APRÈS public/assets/css/web-edition.css. Ne le remplace pas, ne le
 * réécrit pas. Conserve tes noms de variables (--bg, --text, --muted, --accent,
 * --gold, --line, --line-strong, --surface, --shell, --radius) et tes classes
 * (.site-shell, .site-header, .brand, .primary-nav, .hero, .feature-card…).
 *
 * Tout ce qui suit est justifié par une mesure, pas par un goût. Les ratios
 * sont calculés selon la formule de luminance relative WCAG 2.1 et vérifiables
 * avec verifier-contrastes.py.
 *
 * CE QUI VA DÉJÀ BIEN DANS web-edition.css, et que cette feuille ne touche pas :
 *   - les 7 tokens de texte passent AAA sur les 4 fonds (de 7,79:1 à 15,92:1) ;
 *   - prefers-reduced-motion est traité (ligne 870) ;
 *   - forced-colors est traité (ligne 885) ;
 *   - @media print est traité ;
 *   - les cibles sont généreuses : nav 44 px, .button 48 px, .btn 46 px,
 *     .text-link 44 px — bien au-dessus des 24 px de WCAG 2.2 §2.5.8.
 * ==========================================================================*/


/* ============================================================================
 * 1. LE SEUL VRAI DÉFAUT MESURÉ — bordures de contrôles
 * ----------------------------------------------------------------------------
 * --line-strong vaut rgba(170,196,221,.38), soit #45515f sur --bg : 2,44:1.
 * WCAG 1.4.11 exige 3:1 pour tout élément non textuel nécessaire à identifier
 * un contrôle. Or --line-strong ne sert QUE deux fois, et les deux sont
 * exactement ça :
 *     web-edition.css:296  .button-secondary { border-color: var(--line-strong) }
 *     web-edition.css:636  input, select, textarea { border: 1px solid ... }
 *
 * Le champ de saisie et le bouton secondaire sont donc actuellement bordés
 * en dessous du seuil : sur un écran mal calibré ou en plein soleil, on ne
 * voit plus où commence le champ.
 *
 * Correctif : alpha .38 → .46, soit #52606f, 3,06:1. Aucune autre couleur ne
 * bouge, et l'écart visuel est à peine perceptible sur un bon écran.
 *
 * --line reste inchangé. Ses 14 usages sont des séparateurs décoratifs —
 * bas de header, arêtes de cartes — que WCAG n'assujettit à aucun seuil.
 * Les remonter tous durcirait l'interface sans rien apporter.
 * ==========================================================================*/
:root {
  --line-strong: rgba(170, 196, 221, 0.46);   /* 3,06:1 sur --bg */
}


/* ============================================================================
 * 2. LE SEUL prefers-* MANQUANT — contraste renforcé
 * ----------------------------------------------------------------------------
 * web-edition.css gère prefers-reduced-motion et forced-colors, mais pas
 * prefers-contrast. Sur macOS « Augmenter le contraste » et Windows, le
 * réglage est donc ignoré côté CMS — alors que interface/shell/a11y.css le
 * respecte déjà côté WebGPU. On aligne les deux coques.
 *
 * Même convention data-* que ta feuille a11y.css existante, pour que le
 * panneau Préférences pilote les deux de la même façon.
 * ==========================================================================*/
@media (prefers-contrast: more) {
  :root:not([data-contrast]) {
    --line:        rgba(170, 196, 221, 0.42);
    --line-strong: rgba(170, 196, 221, 0.72);
    --muted:       #d5dee6;                    /* 12,4:1 au lieu de 8,58:1 */
    --surface:     #0f1723;                    /* opaque : plus de verre */
  }
}

:root[data-contrast="aaa"] {
  --bg: #000000;
  --bg-elevated: #000000;
  --surface: #000000;
  --surface-strong: #000000;
  --text: #ffffff;
  --muted: #f0f0f0;
  --line: rgba(255, 255, 255, 0.55);
  --line-strong: #ffffff;
  --accent: #8fe9ff;
  --shadow: none;
}
:root[data-contrast="aaa"] body { background-image: none; }
:root[data-contrast="aaa"] .site-header,
:root[data-contrast="aaa"] .hero,
:root[data-contrast="aaa"] .feature-card,
:root[data-contrast="aaa"] .webgpu-callout,
:root[data-contrast="aaa"] .source-card {
  border-width: 2px;
  background-image: none;
  backdrop-filter: none;
}


/* ============================================================================
 * 3. LE VERRE DÉPOLI — enrichissement, pas dépendance
 * ----------------------------------------------------------------------------
 * backdrop-filter est déclaré deux fois sans garde (lignes 99 et 760). Le repli
 * est correct — le fond rgba(7,11,18,.82) reste lisible sans flou — donc ce
 * n'est pas un bug. Mais le flou coûte cher en GPU sur les appareils d'entrée
 * de gamme, précisément le parc des visiteurs les plus contraints.
 *
 * On le rend donc conditionnel : présent quand tout va bien, coupé dès que
 * l'utilisateur ou le navigateur signale une contrainte.
 * ==========================================================================*/
@media (prefers-reduced-transparency: reduce) {
  .site-header { backdrop-filter: none; }
}
:root[data-save-data="on"] .site-header { backdrop-filter: none; }
:root[data-save-data="on"] body { background-image: none; }

/* Les fonds correspondants sont rendus opaques en section 10 : ils doivent être
   déclarés APRÈS les thèmes pour ne pas se faire recouvrir par eux. */


/* ============================================================================
 * 4. POLICE — lever une incohérence silencieuse
 * ----------------------------------------------------------------------------
 * web-edition.css:19 demande `Inter`. Or fonts.css ne déclare que Raleway, et
 * app.php ne charge même pas fonts.css : seul web-edition.css est lié. `Inter`
 * n'est donc jamais servie et retombe sur ui-sans-serif / system-ui.
 *
 * Ce n'est pas un problème d'affichage — la pile système est excellente et
 * coûte zéro octet, ce qui sert directement les connexions comptées. Mais le
 * nom trompe le lecteur du code. On l'assume explicitement.
 *
 * Deux options de lecture optionnelles, dans la convention data-font de ton
 * a11y.css. Aucune police n'est téléchargée tant que l'utilisateur ne choisit
 * pas : une webfont coûte 15 à 80 Ko et un aller-retour de plus.
 * ==========================================================================*/
:root {
  --font-ui: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
             "Segoe UI", Roboto, "Noto Sans", sans-serif;
  --font-read: ui-serif, Georgia, "Times New Roman", "Noto Serif", serif;
}
:root { font-family: var(--font-ui); }

:root[data-font="lecture"] { --font-ui: var(--font-read); }
:root[data-font="lecture"] .articles-show,
:root[data-font="lecture"] .legal-page { line-height: 1.8; }

:root[data-font="dyslexie"] {
  letter-spacing: 0.01em;
  word-spacing: 0.06em;
}
:root[data-font="dyslexie"] .articles-show p,
:root[data-font="dyslexie"] .legal-page p { line-height: 1.85; }


/* ============================================================================
 * 5. LONGUEUR DE LIGNE
 * ----------------------------------------------------------------------------
 * --shell vaut 1180px, ce qui est juste pour une grille. Mais sur les pages de
 * lecture — un article, une page légale — le texte s'étale sur toute la largeur.
 * Au-delà d'environ 70 signes, le retour à la ligne devient coûteux pour les
 * lecteurs dyslexiques et les basses visions : l'œil perd la ligne suivante.
 * ==========================================================================*/
.articles-show p,
.articles-show li,
.legal-page p,
.legal-page li,
.legal-lead,
.hero-intro {
  max-width: 68ch;
}


/* ============================================================================
 * 6. THÈME CLAIR — proposition, désactivée par défaut
 * ----------------------------------------------------------------------------
 * web-edition.css verrouille `color-scheme: dark`. C'est cohérent avec
 * l'identité, et je ne le change pas.
 *
 * Mais le mode sombre pénalise l'astigmatisme et une partie des basses
 * visions, et un fond clair reste lisible sur un écran bon marché mal calibré
 * — ce qui n'est pas le cas d'un dégradé sombre. Un site de lecture et
 * d'impression gagne à offrir le choix.
 *
 * Rien ne s'active tant que <html data-theme="clair"> n'est pas posé. Les
 * sept tokens de texte tiennent tous AA sur les quatre fonds, --muted à
 * 6,67:1 étant le pire cas.
 * ==========================================================================*/
:root[data-theme="clair"] {
  color-scheme: light;

  --bg:             #fbfaf7;
  --bg-elevated:    #ffffff;
  --surface:        #f3f1ec;
  --surface-strong: #ffffff;

  --text:   #14181f;   /* 15,76:1 pire cas */
  --muted:  #4d5561;   /*  6,67:1 */

  --accent:        #0a5f7a;   /* 6,35:1 */
  --accent-strong: #084b61;   /* 8,50:1 */
  --gold:          #7a5410;   /* 6,00:1 */
  --danger:        #a02030;   /* 6,78:1 */
  --success:       #1b6642;   /* 6,15:1 */

  --line:        rgba(20, 24, 31, 0.14);
  --line-strong: rgba(20, 24, 31, 0.48);   /* 3,10:1 pire cas */
  --shadow: 0 18px 44px rgba(20, 24, 31, 0.10);
}
:root[data-theme="clair"] body { background-image: none; background: var(--bg); }
:root[data-theme="clair"] .site-header { background: rgba(251, 250, 247, 0.85); }
:root[data-theme="clair"] .source-card,
:root[data-theme="clair"] .feature-card { background: var(--bg-elevated); }
:root[data-theme="clair"] .button-primary { color: #ffffff; }
:root[data-theme="clair"] :focus-visible { outline-color: var(--accent-strong); }


/* ============================================================================
 * 7. IMPRESSION — compléter l'existant
 * ----------------------------------------------------------------------------
 * @media print masque déjà header, footer, hero-actions et webgpu-callout.
 * On ajoute ce qui manque à une sortie papier utilisable : fond blanc, encre
 * noire, et l'adresse des liens en note — sans quoi une page imprimée perd
 * toutes ses références.
 * ==========================================================================*/
@media print {
  :root {
    --bg: #ffffff; --bg-elevated: #ffffff;
    --surface: #ffffff; --surface-strong: #ffffff;
    --text: #000000; --muted: #333333;
    --line: #999999; --line-strong: #666666;
    --shadow: none;
  }
  body { background: #fff !important; background-image: none !important; color: #000; }
  .articles-show p, .legal-page p { max-width: none; }
  a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 0.85em;
    word-break: break-all;
  }
  .source-card, .feature-card, .legal-table { break-inside: avoid; }
}


/* ============================================================================
 * 8. LES COULEURS ÉCRITES EN DUR — les rendre pilotables
 * ----------------------------------------------------------------------------
 * Ajouté lors de l'intégration au CMS (août 2026).
 *
 * La section 6 propose un thème clair, mais elle ne pouvait pas être complète :
 * sept couleurs de web-edition.css sont écrites en dur, hors de tout token, et
 * restent donc sombres quel que soit le thème. Sur fond clair, cela donne un
 * champ de saisie noir dans un formulaire blanc, et un pied de page qui reste
 * une bande nuit.
 *
 *   web-edition.css:98   .site-header       background rgba(7,11,18,.82)
 *   web-edition.css:168  .primary-nav a     fond de survol rgba(115,229,255,.09)
 *   web-edition.css:219  .hero              deux dégradés nuit
 *   web-edition.css:262  .hero-intro        #d6dee7
 *   web-edition.css:287  .button-primary    encre #061019
 *   web-edition.css:297  .button-secondary  voile rgba(255,255,255,.025)
 *   web-edition.css:384  .site-footer       rgba(4,7,12,.55)
 *   web-edition.css:638  input/select/…     #09111d
 *
 * On ne modifie pas web-edition.css. On introduit ici les tokens manquants,
 * initialisés aux valeurs actuelles — donc à ce stade, strictement rien ne
 * change à l'écran — puis on réapplique ces tokens aux mêmes sélecteurs. Chaque
 * thème n'a plus qu'à redéfinir huit variables au lieu de dupliquer des règles.
 * ==========================================================================*/
:root {
  --header-bg:     rgba(7, 11, 18, 0.82);
  --footer-bg:     rgba(4, 7, 12, 0.55);
  --input-bg:      #09111d;
  --on-accent:     #061019;
  --nav-hover-bg:  rgba(115, 229, 255, 0.09);
  --veil:          rgba(255, 255, 255, 0.025);
  --text-soft:     #d6dee7;
  --hero-bg:
    linear-gradient(125deg, rgba(18, 28, 43, 0.98), rgba(7, 11, 18, 0.72)),
    radial-gradient(circle at 85% 20%, rgba(115, 229, 255, 0.2), transparent 22rem);
}

.site-header { background: var(--header-bg); }
.site-footer { background: var(--footer-bg); }
.hero { background: var(--hero-bg); }
.hero-intro { color: var(--text-soft); }
.primary-nav a:hover,
.primary-nav a[aria-current="page"] { background: var(--nav-hover-bg); }
.button-secondary,
.source-card { background: var(--veil); }
.button-primary,
.btn,
button[type="submit"] { color: var(--on-accent); }
input, select, textarea { background: var(--input-bg); }

/* Le thème clair de la section 6 hérite des huit tokens. */
:root[data-theme="clair"] {
  --header-bg:    rgba(251, 250, 247, 0.85);
  --footer-bg:    #f0ede7;
  --input-bg:     #ffffff;
  --on-accent:    #ffffff;
  --nav-hover-bg: rgba(10, 95, 122, 0.10);
  --veil:         rgba(20, 24, 31, 0.03);
  --text-soft:    #2b323c;   /* 11,4:1 sur --bg */
  --hero-bg:
    linear-gradient(125deg, #ffffff, #f3f1ec 72%),
    radial-gradient(circle at 85% 20%, rgba(10, 95, 122, 0.10), transparent 22rem);
}


/* ============================================================================
 * 9. THÈME AUTOMATIQUE — suivre le réglage du système
 * ----------------------------------------------------------------------------
 * La section 6 n'expose le thème clair que sur choix explicite ; il manquait le
 * cas du visiteur qui n'a rien choisi mais a réglé son système en clair. Le
 * bloc est répété plutôt que factorisé : CSS ne permet pas de placer une
 * condition de media dans une liste de sélecteurs, et @import coûterait un
 * aller-retour de plus — précisément ce qu'on cherche à éviter.
 *
 * `data-theme="auto"` est la valeur posée quand aucun cookie n'existe sur les
 * versions Standard, Texte et Oculaire. Premium pose `sombre`.
 * ==========================================================================*/
@media (prefers-color-scheme: light) {
  :root[data-theme="auto"] {
    color-scheme: light;

    --bg:             #fbfaf7;
    --bg-elevated:    #ffffff;
    --surface:        #f3f1ec;
    --surface-strong: #ffffff;

    --text:   #14181f;   /* 15,76:1 pire cas */
    --muted:  #4d5561;   /*  6,67:1 */

    --accent:        #0a5f7a;
    --accent-strong: #084b61;
    --gold:          #7a5410;
    --danger:        #a02030;
    --success:       #1b6642;

    --line:        rgba(20, 24, 31, 0.14);
    --line-strong: rgba(20, 24, 31, 0.48);
    --shadow: 0 18px 44px rgba(20, 24, 31, 0.10);

    --header-bg:    rgba(251, 250, 247, 0.85);
    --footer-bg:    #f0ede7;
    --input-bg:     #ffffff;
    --on-accent:    #ffffff;
    --nav-hover-bg: rgba(10, 95, 122, 0.10);
    --veil:         rgba(20, 24, 31, 0.03);
    --text-soft:    #2b323c;
    --hero-bg:
      linear-gradient(125deg, #ffffff, #f3f1ec 72%),
      radial-gradient(circle at 85% 20%, rgba(10, 95, 122, 0.10), transparent 22rem);
  }
  :root[data-theme="auto"] body { background-image: none; background: var(--bg); }
  :root[data-theme="auto"] .source-card,
  :root[data-theme="auto"] .feature-card { background: var(--bg-elevated); }
  :root[data-theme="auto"] :focus-visible { outline-color: var(--accent-strong); }
}


/* ============================================================================
 * 10. CONTRASTE RENFORCÉ SUR FOND CLAIR
 * ----------------------------------------------------------------------------
 * La section 2 traite `data-contrast="aaa"` en blanc sur noir. Il manquait son
 * pendant noir sur blanc : forcer un fond sombre à quelqu'un qui a demandé du
 * contraste renforcé se retourne contre les basses visions photophobes
 * inverses et contre l'astigmatisme. Le choix du fond reste au visiteur.
 * ==========================================================================*/
:root[data-theme="clair"][data-contrast="aaa"],
:root[data-theme="auto"][data-contrast="aaa"] {
  --bg: #ffffff;
  --bg-elevated: #ffffff;
  --surface: #ffffff;
  --surface-strong: #ffffff;
  --text: #000000;
  --muted: #1a1a1a;
  --line: rgba(0, 0, 0, 0.55);
  --line-strong: #000000;
  --accent: #00435c;
  --accent-strong: #003143;
  --gold: #5c3d00;
  --shadow: none;
}
:root[data-theme="clair"][data-contrast="aaa"] .button-primary,
:root[data-theme="auto"][data-contrast="aaa"] .button-primary {
  color: #ffffff;
}


/* ============================================================================
 * 11. LE SÉLECTEUR D'AFFICHAGE
 * ----------------------------------------------------------------------------
 * Deux surfaces pour le même formulaire : le panneau repliable du pied de page
 * (`.display-picker`) et la page dédiée (`.display-page`).
 *
 * `<details>` natif plutôt qu'un panneau piloté en JavaScript : l'état ouvert
 * ou fermé est géré par le navigateur, annoncé correctement aux lecteurs
 * d'écran, et la recherche dans la page (Ctrl+F) ouvre le panneau d'elle-même
 * sur les navigateurs récents. Zéro octet de script.
 * ==========================================================================*/
.footer-display {
  padding-bottom: 1.5rem;
}

.display-picker {
  border: 1px solid var(--line);
  border-radius: 0.65rem;
  background: var(--veil);
}

.display-picker > summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 44px;
  padding: 0.6rem 0.9rem;
  cursor: pointer;
  font-weight: 700;
  /* Le marqueur par défaut est conservé : il indique l'état ouvert/fermé et
     rien ici ne le remplace. */
}

.display-picker__current {
  color: var(--muted);
  font-weight: 400;
}

.display-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.9rem;
  padding: 0 0.9rem 0.9rem;
}

.display-field {
  display: grid;
  gap: 0.25rem;
  margin: 0;
  /* 11rem : assez pour « Selon le système » sans césure, assez peu pour que
     quatre champs tiennent sur une ligne à partir d'environ 900px. */
  flex: 1 1 11rem;
}

.display-field label {
  font-size: 0.85rem;
  color: var(--muted);
}

.display-form select {
  min-height: 44px;
}

.display-help {
  flex: 1 0 100%;
  margin: 0;
  font-size: 0.9rem;
}

/* --- La page dédiée ------------------------------------------------------- */
.display-group {
  margin: 0 0 2rem;
  padding: 1rem 1.15rem;
  border: 1px solid var(--line);
  border-radius: 0.75rem;
}

.display-group legend {
  padding-inline: 0.4rem;
  font-weight: 800;
}

.display-group__intro {
  margin-top: 0;
  color: var(--muted);
  max-width: 68ch;
}

/* La grille place le bouton radio en gouttière et aligne l'intitulé et sa
   description sur une même colonne : la description reste rattachée
   visuellement à son option, ce que `aria-describedby` fait déjà pour les
   lecteurs d'écran. */
.display-option {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.15rem 0.7rem;
  padding-block: 0.6rem;
  border-top: 1px solid var(--line);
}

.display-option:first-of-type {
  border-top: 0;
}

.display-option input[type="radio"] {
  width: 1.25rem;
  height: 1.25rem;
  min-height: 0;
  margin-top: 0.25rem;
  grid-row: 1 / 3;
}

.display-option label {
  font-weight: 700;
  /* La cible cliquable couvre l'intitulé entier, pas seulement le rond. */
  min-height: 24px;
  cursor: pointer;
}

.display-option__note {
  grid-column: 2;
  color: var(--muted);
  font-size: 0.95rem;
  max-width: 68ch;
}

@media (max-width: 540px) {
  .display-form {
    flex-direction: column;
    align-items: stretch;
  }
  .display-field {
    flex: 1 1 auto;
  }
}


/* ============================================================================
 * 12. OPACITÉ FORCÉE — dernier mot du cascade
 * ----------------------------------------------------------------------------
 * Ces règles closent volontairement le fichier — plus aucune redéfinition de
 * token ne vient après. Un thème explicite
 * (`[data-theme="clair"]`, spécificité 0-2-0) l'emporterait sur un `:root`
 * (0-1-0) écrit plus haut, quel que soit son emplacement. En reprenant ici la
 * même spécificité avec `[data-theme]` et en étant les dernières déclarées, ces
 * règles ont le dernier mot : une contrainte annoncée par l'utilisateur ou par
 * le navigateur ne peut pas être annulée par un choix de thème.
 *
 * Ce que ça coupe : la translucidité du header, les dégradés du hero et du fond
 * de page. Rien qui porte d'information.
 *
 * Note sur `data-save-data` : c'est un point d'accroche, pas un réglage servi.
 * Aucun code ne le pose aujourd'hui. Il est destiné à un script client lisant
 * navigator.connection.saveData, et volontairement PAS à une déduction de
 * l'en-tête Save-Data côté serveur : cela ferait varier le HTML sur un en-tête
 * absent de `Vary` et empoisonnerait les caches partagés.
 * ==========================================================================*/
@media (prefers-reduced-transparency: reduce) {
  :root,
  :root[data-theme] {
    --header-bg: var(--bg);
    --hero-bg: var(--surface-strong);
  }
  body { background-image: none; }
}

:root[data-save-data="on"],
:root[data-theme][data-save-data="on"] {
  --header-bg: var(--bg);
  --hero-bg: var(--surface-strong);
}

:root[data-contrast="aaa"],
:root[data-theme][data-contrast="aaa"] {
  --header-bg: var(--bg);
  --hero-bg: var(--bg);
  --footer-bg: var(--bg);
  --veil: transparent;
}

@media print {
  :root,
  :root[data-theme] {
    --header-bg: #ffffff;
    --footer-bg: #ffffff;
    --input-bg: #ffffff;
    --on-accent: #000000;
    --veil: transparent;
    --text-soft: #000000;
    --hero-bg: none;
  }
}
