/* Identité et socle partagés — chargée par TOUTES les pages via
   {{template "brand_head"}} (templates/_brand.html), avant les feuilles
   propres à chaque page.
   Contenu : jetons de couleur (clair + sombre), police des titres, barre de
   navigation, lien d'évitement, focus clavier, pied de page. */

/* ══ Jetons ═══════════════════════════════════════════════════════════════
   Le site avait trois palettes qui s'ignoraient : manual.css en dur,
   teacher.css en variables (seule à connaître le mode sombre), et des copies
   en ligne dans index.html, _auth_style.html, editeur.html et trois pages
   enseignant. D'où un manuel toujours clair à côté d'un bac à sable sombre.
   Tout part d'ici désormais ; les feuilles de page ne posent plus de #hex.

   Les valeurs claires reprennent celles qui existaient. Quelques nuances
   voisines ont fusionné (#777 et #666, #999 et #888, #555 et #444) : à chaque
   fois vers la plus foncée, donc vers un meilleur contraste. */
/* Auto tant qu'aucun thème n'est forcé : les contrôles natifs (cases, boutons
   radio, flèches des champs numériques) suivent l'OS. Quand la bascule force
   un thème, color-scheme doit suivre AUSSI, sinon ces contrôles restent
   rendus dans le schéma de l'OS. */
:root { color-scheme: light dark; }

/* .print-part est un îlot clair : l'aperçu A4 de l'éditeur de partie est une
   feuille de papier, elle ne suit pas le thème sombre. Elle partage la liste
   des valeurs claires au lieu d'en garder une copie — sans quoi le contenu de
   la partie s'afficherait en encre claire sur une feuille blanche. La feuille
   d'impression, elle, force déjà data-theme="light" sur tout le document. */
.print-part { color-scheme: light; }

:root,
.print-part {
  /* Fonds et structure */
  --bg:            #f4f4f0;
  --surface:       #ffffff;
  --surface-alt:   #f8f8fc;
  --surface-hi:    #fafafa;
  --surface-soft:  #fafaff;  /* cartes teintées du manuel */
  --row-hover:     #f4f4fa;
  --code-bg:       #f0eef4;
  --track:         #f0f0f6;
  --divider:       #f0f0f4;
  --border-soft:   #eeeeee;
  --border:        #e4e4e8;
  --border-input:  #dddddd;
  --border-strong: #d4d4dc;
  --border-dash:   #c4c4d4;
  --faint:         #b0b0c4;  /* repères d'édition (saut de page, serrer) */

  /* Texte */
  --text:      #1a1a1a;
  --text-soft: #444444;
  /* #888 était la teinte des mentions discrètes : 3,2:1 sur le fond de page,
     sous le seuil AA de 4,5:1 pour du petit texte. Les deux gris ont été
     assombris d'un cran — la hiérarchie tient toujours, les deux passent. */
  --muted:     #5a5a5a;
  --muted-2:   #6f6f6f;
  --title:     #022825;  /* titres de page et de section */

  /* Marque */
  /* Deux rôles, deux jetons. Un accent lisible EN TEXTE sur le fond de page
     et un aplat sous du texte blanc ne peuvent pas être la même couleur en
     thème sombre : la première doit être claire, la seconde foncée. Le clair
     s'en tirait avec une seule valeur, pas le sombre — le blanc sur l'indigo
     clair ne donnait que 4,17:1, sous le seuil AA. */
  --brand:           #134e4a;  /* liens et texte d'accent */
  --brand-fill:      #0f766e;  /* aplat, toujours sous du blanc */
  --brand-fill-hover:#115e59;
  --brand-alt:       #14b8a6;  /* dégradé de la zone de frappe */
  --brand-tint:      #d9f5f0;
  --brand-soft:      #e6faf6;
  --brand-edge:      #57c9bb;
  --brand-edge-soft: #b8e6df;
  --brand-ink:       #3a736c;  /* intertitres discrets */
  --brand-deep:      #0b3d38;

  /* Bandeau */
  --header-bg:   #0f3b37;
  --header-link: #7fd6c7;

  /* Une gravure LilyPond, un schéma LaTeX ou une portée déposée par un
     enseignant sont de l'encre noire sur transparent. En thème sombre on
     INVERSE l'image plutôt que de lui glisser une feuille blanche dessous :
     la transparence est conservée, le fond de la carte reste visible au
     travers, et la page n'est plus trouée de dalles blanches.
     hue-rotate rattrape les teintes d'une image en couleur, que l'inversion
     seule rendrait complémentaires ; sur du noir pur elle ne change rien.
     Le jeton évite de répéter la liste des sélecteurs dans les trois blocs
     de thème. */
  --ink-invert: none;

  /* --score-bg reste pour les surfaces qui sont vraiment du papier : la
     toile de l'éditeur de partition et l'aperçu A4. Là, on n'inverse pas —
     on regarde une feuille. Son encre est --score-ink, toujours foncée. */
  --score-bg:  #ffffff;
  --score-ink: #1a1a1a;

  /* Portée (bac à sable) */
  --staff-active:      #4a6fa5;
  --staff-active-edge: #3a5f95;

  /* Sémantique */
  --ok:         #2c8c4a;
  --ok-strong:  #226f3a;
  --ok-fg:      #1b5e20;
  --ok-bg:      #e0f5e0;
  --ok-edge:    #66bb6a;
  --err-fg:     #b71c1c;
  --err-fg-deep:#7a1010;
  --err-bg:     #fff5f5;
  --err-bg-hi:  #ffe0e0;
  --err-edge:   #fca5a5;
  --err-edge-hi:#e57373;
  --err-strong: #e53935;
  --warn-bg:    #fff8e1;
  --warn-edge:  #ffe0a3;
  --warn-edge-hi:#e0b050;
  --warn-fg:    #7a5c00;
  --info-fg:    #1e3a8a;
  --info-bg:    #e3ecff;
  --info-edge:  #93b4f5;
  --hint-bg:    #eafaf7;
  --hint-edge:  #c2e8e1;

  /* Ombres et rayons */
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.04), 0 1px 3px rgba(30,32,64,0.05);
  --shadow-md: 0 1px 4px rgba(0,0,0,0.06);
  --shadow-lg: 0 4px 12px rgba(0,0,0,0.12);
  --radius-sm:   5px;
  --radius:      7px;
  --radius-lg:  10px;
  --radius-pill:20px;

  /* Contour de focus, identique partout (cf. plus bas). */
  --focus: #0d9488;
}

/* Jetons sombres — appliqués quand (a) le système préfère le sombre et
   qu'aucun choix explicite ne dit le contraire, ou (b) la bascule a posé
   data-theme="dark". Les deux blocs sont jumeaux : CSS ne sait pas partager
   une liste de déclarations entre deux sélecteurs. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:            #14151c;
    --surface:       #1c1e28;
    --surface-alt:   #222430;
    --surface-hi:    #262837;
    --surface-soft:  #1f2130;
    --row-hover:     #22242f;
    --code-bg:       #22242f;
    --track:         #1f2130;
    --divider:       #262838;
    --border-soft:   #2a2c3a;
    --border:        #2c2e3d;
    --border-input:  #3a3d52;
    --border-strong: #3a3d52;
    --border-dash:   #454962;
    --faint:         #565a70;
    --text:      #e8e8ee;
    --text-soft: #c2c2ce;
    --muted:     #9a9aab;
    --muted-2:   #8a90a4;
    --title:     #a5e5da;
    --brand:           #2dd4bf;
    --brand-fill:      #115e59;
    --brand-fill-hover:#0f766e;
    --brand-alt:       #0f766e;
    --brand-tint:      #133f3b;
    --brand-soft:      #10332f;
    --brand-edge:      #1b6b62;
    --brand-edge-soft: #16514b;
    --brand-ink:       #7fbdb3;
    --brand-deep:      #a8e6db;
    --header-bg:   #0b1513;
    --header-link: #7fd6c7;
    --ink-invert: invert(1) hue-rotate(180deg);
    --score-bg:  #f4f4f0;
    --score-ink: #1a1a1a;
    --staff-active:      #4a6fa5;
    --staff-active-edge: #5a78c0;
    --ok:         #4fbe72;
    --ok-strong:  #3da05c;
    --ok-fg:      #9fe0ae;
    --ok-bg:      #1b3524;
    --ok-edge:    #3d7a50;
    --err-fg:     #ff8b80;
    --err-fg-deep:#ffb0a8;
    --err-bg:     #3a1818;
    --err-bg-hi:  #4a1e1e;
    --err-edge:   #8a3030;
    --err-edge-hi:#a04040;
    --err-strong: #ef5350;
    --warn-bg:    #3a3018;
    --warn-edge:  #6a5820;
    --warn-edge-hi:#8a7030;
    --warn-fg:    #f0d080;
    --info-fg:    #b8ccff;
    --info-bg:    #1c2a4a;
    --info-edge:  #3a5a9a;
    --hint-bg:    #0f3b37;
    --hint-edge:  #1b5750;
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.4);
    --shadow-md: 0 1px 4px rgba(0,0,0,0.4);
    --shadow-lg: 0 4px 12px rgba(0,0,0,0.5);
    --focus: #2dd4bf;
  }
}
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg:            #14151c;
  --surface:       #1c1e28;
  --surface-alt:   #222430;
  --surface-hi:    #262837;
  --surface-soft:  #1f2130;
  --row-hover:     #22242f;
  --code-bg:       #22242f;
  --track:         #1f2130;
  --divider:       #262838;
  --border-soft:   #2a2c3a;
  --border:        #2c2e3d;
  --border-input:  #3a3d52;
  --border-strong: #3a3d52;
  --border-dash:   #454962;
  --faint:         #565a70;
  --text:      #e8e8ee;
  --text-soft: #c2c2ce;
  --muted:     #9a9aab;
  --muted-2:   #8a90a4;
  --title:     #a5e5da;
  --brand:           #2dd4bf;
  --brand-fill:      #115e59;
  --brand-fill-hover:#0f766e;
  --brand-alt:       #0f766e;
  --brand-tint:      #133f3b;
  --brand-soft:      #10332f;
  --brand-edge:      #1b6b62;
  --brand-edge-soft: #16514b;
  --brand-ink:       #7fbdb3;
  --brand-deep:      #a8e6db;
  --header-bg:   #0b1513;
  --header-link: #7fd6c7;
  --ink-invert: invert(1) hue-rotate(180deg);
  --score-bg:  #f4f4f0;
  --score-ink: #1a1a1a;
  --staff-active:      #4a6fa5;
  --staff-active-edge: #5a78c0;
  --ok:         #4fbe72;
  --ok-strong:  #3da05c;
  --ok-fg:      #9fe0ae;
  --ok-bg:      #1b3524;
  --ok-edge:    #3d7a50;
  --err-fg:     #ff8b80;
  --err-fg-deep:#ffb0a8;
  --err-bg:     #3a1818;
  --err-bg-hi:  #4a1e1e;
  --err-edge:   #8a3030;
  --err-edge-hi:#a04040;
  --err-strong: #ef5350;
  --warn-bg:    #3a3018;
  --warn-edge:  #6a5820;
  --warn-edge-hi:#8a7030;
  --warn-fg:    #f0d080;
  --info-fg:    #b8ccff;
  --info-bg:    #1c2a4a;
  --info-edge:  #3a5a9a;
  --hint-bg:    #0f3b37;
  --hint-edge:  #1b5750;
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.4);
  --shadow-md: 0 1px 4px rgba(0,0,0,0.4);
  --shadow-lg: 0 4px 12px rgba(0,0,0,0.5);
  --focus: #2dd4bf;
}

/* ══ Police des titres ════════════════════════════════════════════════════ */
@font-face {
  font-family: 'OPTIFormula-One';
  src: url('/static/font/OPTIFormula-One.woff2') format('woff2'),
       url('/static/font/OPTIFormula-One.woff') format('woff'),
       url('/static/font/OPTIFormula-One.ttf') format('truetype');
  font-display: swap;
}

:root { --font-titre: 'OPTIFormula-One', Georgia, serif; }

/* Les titres, comme sur dumiste : le nom du site dans le bandeau, les titres
   de page et ceux du contenu d'une partie. Le chrome (formulaires, panneaux,
   étiquettes) reste en system-ui. */
header h1,
h2.page-title,
.card h3,
.lesson-content h1,
.lesson-content h2,
.lesson-content h3 {
  font-family: var(--font-titre);
}

/* Les menus de navigation : les <nav> (bandeau de liens de chaque page, et le
   passe-partie en bas d'une partie) et les liens isolés d'un bandeau sans nav
   (« ← Retour », « ← Connexion »). Les boutons d'action d'une barre haute
   (Exporter, Aide, Paramètres) ne sont pas de la navigation et restent en
   system-ui. */
nav,
nav a,
header a {
  font-family: var(--font-titre);
}

/* ── Papier ──────────────────────────────────────────────────────────────
   Les versions papier d'un cours gardent system-ui : la police d'affichage
   est pour l'écran. Deux rendus à couvrir, et ils partagent .print-part —
   la feuille de /chapitre/…?impression et l'aperçu A4 de l'éditeur de partie.
   Le titre de la feuille (.print-head h1) n'a jamais reçu la police : il
   n'existe que sur papier. `inherit` fait retomber sur la font-family du
   corps sans toucher aux blocs de code, qui ont la leur. */
.print-part .lesson-content h1,
.print-part .lesson-content h2,
.print-part .lesson-content h3 {
  font-family: inherit;
}

/* Et quand c'est une page d'écran ordinaire qu'on envoie à l'imprimante. */
@media print {
  header h1,
  h2.page-title,
  .card h3,
  .lesson-content h1,
  .lesson-content h2,
  .lesson-content h3,
  nav,
  nav a,
  header a {
    font-family: inherit;
  }
}

/* ══ Encre sur transparent ════════════════════════════════════════════════
   Une seule règle pour tout ce qui est « noir sur transparent » : gravures du
   pipeline, schémas LaTeX, aperçu du bac à sable, et les SVG qu'un enseignant
   dépose dans une partie — dans une leçon, un SVG est une portée ou un
   schéma, jamais une photo. Les png/jpg/webp ne sont PAS touchés : inverser
   une photographie serait un désastre, et c'est la raison pour laquelle la
   règle ne peut pas viser toutes les images.

   Le filtre ne porte que sur des <img>. Les <svg> en ligne (éditeur, relevé,
   puzzle) se peignent en currentColor et suivent déjà le thème : les
   inverser les repeindrait à l'envers.

   Le curseur de lecture est un frère de l'image, pas un enfant : il garde sa
   couleur. */
.score-embed .score-wrap img,
.exercise-widget .exw-wrap img,
.score-card img,
.preview-score img,
.latex-embed img,
.lesson-content img[src$=".svg"],
.lesson-content img[src$=".SVG"] {
  filter: var(--ink-invert);
}
/* Sur papier, jamais. */
@media print {
  .score-embed .score-wrap img,
  .exercise-widget .exw-wrap img,
  .score-card img,
  .preview-score img,
  .latex-embed img,
  .lesson-content img { filter: none; }
}

/* ══ Lien d'évitement ═════════════════════════════════════════════════════
   Première cible tabulable de chaque page : elle saute le bandeau et ses neuf
   liens pour aller au contenu. Invisible tant qu'elle n'a pas le focus.
   La cible est id="contenu", posée sur le <main> de chaque gabarit. */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--brand-fill); color: #fff;
  padding: 0.7rem 1.1rem; border-radius: 0 0 var(--radius) 0;
  text-decoration: none; font-weight: 600;
}
.skip-link:focus { left: 0; }

/* Texte réservé aux lecteurs d'écran : retiré de la page sans être masqué
   (display:none et visibility:hidden le rendraient muet pour eux aussi).
   Sert aux régions live qui annoncent un changement purement visuel. */
.sr-only {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
  margin: -1px; padding: 0; border: 0;
}

/* ══ Focus clavier ════════════════════════════════════════════════════════
   Un seul contour pour tout le site. Il n'existait que sur les boutons
   d'exercice et dans teacher.css : ailleurs, la tabulation était invisible —
   et manual.css allait jusqu'à `outline: none` sur les champs de formulaire.
   :focus-visible ne se déclenche qu'au clavier, la souris ne voit rien. */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 3px;
}
/* Sur le bandeau sombre, le violet de marque ne ressort pas. */
header :focus-visible { outline-color: #fff; }

/* ══ Bandeau et navigation ════════════════════════════════════════════════
   Le balisage vient du partial « nav » (templates/_nav.html) ; les couleurs
   restent à la charge de chaque feuille de page, qui posent déjà
   `header nav a`. Seule la disposition est ici. */

/* Le nom du site est un lien vers l'accueil (partial « brand_home »). La
   classe pèse plus lourd que les `header a { color: … }` des feuilles de
   page, qui le peindraient de la couleur des liens de navigation. */
.brand-home { color: inherit; text-decoration: none; }

/* Le titre pousse : le bandeau porte jusqu'à quatre blocs (titre, commandes
   de l'outil, navigation, bascule de thème) et `space-between` les
   éparpillerait. */
/* min-width: 0 laisse le titre se replier sur deux lignes plutôt que de
   pousser « Menu » et la bascule de thème sur une rangée à part. */
header h1 { margin-right: auto; min-width: 0; }

header nav {
  display: flex; flex-wrap: wrap;
  align-items: center; justify-content: flex-end;
  gap: 0.15rem 0.4rem;
}
/* Le padding sert de cible tactile : sans lui les liens ne faisaient que la
   hauteur du texte (~19 px), sous le minimum de 24×24 du WCAG 2.5.8. */
header nav a {
  padding: 0.45rem 0.55rem;
  border-radius: var(--radius-sm);
  display: inline-block;
}
header nav a[aria-current="page"] { color: inherit; }
header nav .nav-sep {
  width: 1px; align-self: stretch; min-height: 1.4em;
  background: currentColor; opacity: 0.25; margin: 0 0.25rem;
}
/* Les actions propres à la page (« Modifier », « Voir la partie ») ouvrent
   la barre : ce sont des liens vers ce qu'on regarde, pas vers le site. */
header nav a.nav-action { color: inherit; }

/* Bascule clair / sombre — dernière de la barre, après le séparateur. */
.theme-btn {
  background: none; border: 0; cursor: pointer;
  padding: 0.45rem 0.55rem; border-radius: var(--radius-sm);
  color: var(--header-link); font: inherit; font-size: 1rem; line-height: 1;
}
.theme-btn:hover { color: #fff; }
/* L'icône montre le thème vers lequel on bascule : en clair, la lune. */
.theme-btn .ic-sun  { display: none; }
.theme-btn .ic-moon { display: inline; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-btn .ic-sun  { display: inline; }
  :root:not([data-theme="light"]) .theme-btn .ic-moon { display: none; }
}
:root[data-theme="dark"]  .theme-btn .ic-sun  { display: inline; }
:root[data-theme="dark"]  .theme-btn .ic-moon { display: none; }
:root[data-theme="light"] .theme-btn .ic-sun  { display: none; }
:root[data-theme="light"] .theme-btn .ic-moon { display: inline; }

/* ── Repli sur mobile ─────────────────────────────────────────────────────
   Neuf destinations pour un enseignant modérateur : dépliées sur un
   téléphone, elles font trois rangées de bandeau avant le premier mot de
   contenu. Sous 760 px la barre passe donc derrière un bouton « Menu ».
   C'est un <details>/<summary> : pas une ligne de JS, l'état est natif et le
   clavier le pilote tout seul. Au-dessus de 760 px le <details> est neutralisé
   (summary caché, contenu toujours affiché) — un seul balisage, pas deux
   navigations à tenir synchronisées comme sur dumiste. */
.nav-toggle {
  display: none;
  cursor: pointer; list-style: none;
  padding: 0.45rem 0.7rem; border-radius: var(--radius-sm);
  border: 1px solid currentColor; font-size: 0.85rem;
}
.nav-toggle::-webkit-details-marker { display: none; }
/* `display: contents` fait du <summary> et du <nav> des enfants directs du
   bandeau : le <details> est purement structurel, il ne crée ni boîte ni
   rangée.

   Le repli est piloté par l'attribut `open`, que theme.js retire sous 760 px
   (cf. static/theme.js) : un <details> fermé masque son contenu par une règle
   du navigateur qu'aucune feuille de style ne défait proprement — impossible
   donc de le laisser fermé et d'afficher la barre en CSS sur grand écran.
   Le balisage part ouvert : sans JavaScript, la barre reste entièrement
   dépliée, c'est-à-dire le comportement d'avant le repli. */
.nav-menu { display: contents; }
@media (max-width: 760px) {
  .nav-toggle { display: inline-block; }
  .nav-menu:not([open]) nav { display: none; }
  .nav-menu[open] nav {
    width: 100%; justify-content: flex-start; padding-top: 0.5rem;
  }
  /* Empilé, un séparateur vertical ne veut plus rien dire. */
  header nav .nav-sep { display: none; }
  header nav a { padding: 0.5rem 0.6rem; }
}

/* ══ Pied de page légal ═══════════════════════════════════════════════════ */
footer.legal {
  padding: 1.4rem 1rem; text-align: center;
  font-size: 0.8rem; color: var(--muted);
}
footer.legal a { color: var(--muted); text-decoration: none; }
footer.legal a:hover { text-decoration: underline; }
@media print { footer.legal, .skip-link { display: none; } }
