/* ════════════════════════════════════════════════════════════════════════════
   type.css — les deux polices de Strive
   Chargée par TOUTES les pages, juste après le lien Google Fonts.

   Geist ....... l'interface. Grotesque neutre, très lisible en petit corps,
                 chiffres bien plantés — c'est ce qu'on lit toute la journée.
                 Remplace l'ancienne police d'interface, dont les capitales
                 larges tenaient mal dans les libellés de 9-10 px omniprésents.
   Newsreader .. le gamifié. Serif de lecture avec une vraie italique, qui
                 donne à l'Île, aux événements et aux célébrations un ton de
                 récit plutôt que de tableau de bord. Remplace les deux polices
                 d'apparat qui jouaient ce rôle chacune dans leur coin (une
                 serif pour le Pomodoro doré, une script pour la bannière
                 d'événement) : un seul univers typographique désormais.

   RÈGLE DE PARTAGE — pourquoi ce n'est pas « du serif partout sur ces pages »
   ──────────────────────────────────────────────────────────────────────────
   Newsreader habille ce qui se CONTEMPLE : titres, noms propres du monde
   (bâtiments, cénacles, saisons), annonces de récompense, grands nombres de
   célébration. Geist garde tout ce qui se PARCOURT ou se compare : boutons,
   libellés, prix, compteurs, tableaux, formulaires. Un prix de boutique en
   serif se lit moins vite ; un titre d'événement en grotesque perd son âme.

   Le tout est scopé par `html[data-page="…"]`, l'attribut que js/theme.js pose
   sur <html> (§17). Aucune page n'a donc à déclarer quoi que ce soit : ajouter
   un écran gamifié = ajouter son fichier à la liste ci-dessous.
   ════════════════════════════════════════════════════════════════════════════ */

:root {
  --font-ui:      'Geist', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-display: 'Newsreader', Georgia, 'Times New Roman', serif;
}

/* Filet : les pages déclarent presque toutes leur propre font-family, mais
   celles qui l'oublient (ou les éléments injectés en JS) atterrissent ici. */
body { font-family: var(--font-ui); }

/* ⚠️ NE JAMAIS remettre de `font-size` dans les règles de cette feuille.
   Piège vécu : ces sélecteurs visent des éléments qui déclarent DÉJÀ leur taille
   en px (`.si-name{font-size:11px}`). Comme le scope `html[data-page=…]` a une
   spécificité supérieure, un `font-size:1.08em` ajouté « pour compenser l'œil
   plus petit de Newsreader » écrasait ces 11 px — et `em` se résout sur le
   PARENT, pas sur la taille qu'aurait eue l'élément. Les noms d'articles de la
   boutique sont passés de 11 px à ~15 px d'un coup.
   Ici on ne change QUE la famille ; les tailles restent celles des pages. */
.font-display,
:where(.gami-title) {
  font-family: var(--font-display);
}

/* ══════════════════════════════════════════════════════════════════════
   ÎLE — le monde du joueur
   Les titres de panneaux, les noms de bâtiments et d'objets passent en
   serif ; les prix, quantités et boutons restent en Geist (voir la règle
   de partage plus haut).
   ══════════════════════════════════════════════════════════════════════ */
html[data-page="ile.html"] :where(.isl-title, .itb-title, .do-title, .fp-title, .modal-title),
html[data-page="ile-visite.html"] :where(.isl-title, .itb-title, .do-title, .modal-title) {
  font-family: var(--font-display);
  letter-spacing: -.01em;
}
/* Noms d'articles de boutique et d'inventaire : ce sont des noms propres du
   monde (« Cabane du pêcheur »), pas des libellés d'interface. */
html[data-page="ile.html"] :where(.si-name, .inv-name, .tr-tool-name, .bs-hud-name) {
  font-family: var(--font-display);
}

/* ══════════════════════════════════════════════════════════════════════
   ÉVÉNEMENTS — la bannière et le récit
   ══════════════════════════════════════════════════════════════════════ */
html[data-page="evenement-estival-2026.html"] :where(.ev-hero-title, .ev-modal-title, .ev-confirm-title, .ev-pass-progress-lvl) {
  font-family: var(--font-display);
}
/* Le titre de bannière portait une script très marquée (Lobster). Newsreader en
   italique grasse garde l'emphase sans ouvrir un troisième univers typographique. */
html[data-page="evenement-estival-2026.html"] .ev-hero-title {
  font-style: italic;
  font-weight: 700;
  letter-spacing: -.015em;
}

/* ══════════════════════════════════════════════════════════════════════
   CÉLÉBRATIONS — popups injectés par JS sur toutes les pages
   (reward-anim, rank-popup, perfect-day, daily-rewards, succès, missions,
   récap de bataille). Ce sont les moments « spectacle » de l'app.
   ══════════════════════════════════════════════════════════════════════ */
/* ⚠️ Ces popups sont injectés en JS et nomment leurs éléments par ID autant que
   par classe — d'où le mélange. Sélecteurs vérifiés un à un contre le markup
   réel : une règle typographique qui vise une classe inexistante ne prévient
   jamais, elle ne fait juste rien. */
:where(
  #rp-rank-name,                      /* montée de rang — nom du nouveau rang */
  #pd-label, #pd-streak-num,          /* jour parfait — titre + grand nombre */
  #dr-pop-title,                      /* récompense de connexion */
  .ach-toast-title,                   /* succès débloqué */
  .recap-title, .arena-title,         /* batailles */
  .golden-reveal-title, .golden-reveal-sub
) {
  font-family: var(--font-display);
}
/* ⚠️ `#rp-rank-name` porte des dégradés découpés dans le texte (rangs Or,
   Diamant…). `:where()` garde la spécificité à 0, donc ces règles-là continuent
   de gagner : on ne change que la police, pas le remplissage. */

/* ══════════════════════════════════════════════════════════════════════
   ARBRES DE CONNAISSANCE — mêmes codes que l'Île : c'est un monde à
   parcourir, pas un tableau.
   ══════════════════════════════════════════════════════════════════════ */
html[data-page="formations.html"] :where(.tree-title, .node-title, .fcn),
html[data-page="arbres.html"] :where(.tree-title, .node-title, .fcn) {
  font-family: var(--font-display);
}

/* ══════════════════════════════════════════════════════════════════════
   POMODORO DORÉ — la séance d'exception portait déjà une serif d'apparat.
   Les !important sont ceux de la page ; on les reprend pour rester au-dessus.
   ══════════════════════════════════════════════════════════════════════ */
html[data-page="pomodoro.html"] body.golden-pomo :where(.timer-display, .timer-phase),
html[data-page="pomodoro.html"] :where(.golden-crown, .cd-golden-tag, #recap-golden) {
  font-family: var(--font-display) !important;
}

/* ══════════════════════════════════════════════════════════════════════
   SÉLECTION DE TEXTE — discrète, et réservée au TEXTE
   ──────────────────────────────────────────────────────────────────────
   Deux problèmes réglés ici, tous deux visibles seulement sur PC (à la
   souris, un glissement traverse la page bien plus facilement qu'un doigt) :

   1. Le bleu système. La sélection par défaut du navigateur est un bleu vif
      qui n'appartient à aucune palette de Strive — il jure sur le near-black
      comme sur les thèmes clairs. On le remplace par une surbrillance opaque
      teintée de l'accent du thème, qui INVERSE la clarté du texte pour rester
      lisible quelle que soit sa couleur d'origine (détail plus bas).

   2. Les zones qu'on ne sélectionne jamais volontairement. Attraper un
      bouton, une icône ou un libellé de navigation en glissant la souris ne
      sert à rien et laisse une trace bleue en travers de l'interface. Ces
      éléments passent donc en `user-select:none`.

   ⚠️ La liste ci-dessous est volontairement fermée : boutons, images et
   chrome de navigation. On ne met JAMAIS `user-select:none` sur `body` avec
   des exceptions — le contenu du membre (messages, notes, ressources,
   descriptions) doit rester copiable partout, y compris là où il vit dans un
   simple <div>. Ajouter une zone ici, c'est en interdire la copie.
   `label` en est volontairement absent pour la même raison : un libellé porte
   parfois une valeur qu'on veut recopier (un montant, un code).
   ══════════════════════════════════════════════════════════════════════ */

/* ── INVERSION HAUT CONTRASTE ─────────────────────────────────────────────
   La sélection ne teinte plus le fond : elle INVERSE le rapport de clarté.
   Sur un thème sombre la surbrillance est claire et le texte y passe en
   sombre ; sur un thème clair, exactement l'inverse. Un texte blanc devient
   donc noir et réciproquement, QUELLE QUE SOIT sa couleur d'origine — c'est
   tout l'intérêt : sous un simple voile translucide, le gris secondaire
   (--text3 = #444), l'ambre, et les textes posés sur une image restaient
   illisibles une fois sélectionnés.

   ⚠️ Ce n'est PAS un `mix-blend-mode: difference`, et il ne faut pas essayer
   d'en mettre un : les pseudo-éléments de surbrillance n'acceptent que
   color / background-color / text-shadow / text-decoration /
   -webkit-text-fill-color (css-pseudo-4) — un mode de fusion y est ignoré.
   Et une différence littérale serait PIRE ici : |violet − noir| = violet,
   donc un texte noir disparaîtrait dans sa propre surbrillance. On force
   les deux couleurs, ce qui garantit le contraste au lieu de le subir
   (≈ 15:1 en sombre, ≈ 10:1 en clair — calculés, pas estimés).

   Trois propriétés, et les trois sont nécessaires :
   · `color`                   — le texte ordinaire ;
   · `-webkit-text-fill-color` — les titres dont le remplissage est un dégradé
     découpé dans le texte (`background-clip:text` + `text-fill-color:
     transparent`, ex. #rp-rank-name, §23) seraient INVISIBLES une fois
     sélectionnés sans cette ligne, `color` n'ayant aucune prise sur eux ;
   · `text-shadow: none`       — les textes posés sur une bannière portent une
     ombre calibrée pour du foncé (§17 piège 4) qui bave sur fond clair.

   La teinte suit l'accent du thème (`--violet` : rose en Sakura, orangé en
   Forge) via color-mix, avec un repli en dur pour les moteurs qui ne le
   connaissent pas — même patron que la pastille `.chip` des batailles (§22).
   ⚠️ Les DEUX schémas vivent ici et nulle part ailleurs : `light-base.css`
   n'est chargée que par les thèmes clairs, elle ne peut pas porter le socle,
   et deux définitions concurrentes finiraient par diverger. */
::selection {
  background-color: #e5e3ff;
  color: #0b0a12;
  -webkit-text-fill-color: #0b0a12;
  text-shadow: none;
}
html[data-theme-scheme="light"] ::selection {
  background-color: #3b368c;
  color: #ffffff;
  -webkit-text-fill-color: #ffffff;
  text-shadow: none;
}
@supports (background-color: color-mix(in srgb, red 20%, white)) {
  ::selection {
    background-color: color-mix(in srgb, var(--violet, #6c63ff) 18%, #ffffff);
  }
  html[data-theme-scheme="light"] ::selection {
    background-color: color-mix(in srgb, var(--violet, #6c63ff) 55%, #000000);
  }
}

:where(
  button, [role="button"], .btn, summary,
  img, svg, canvas, video,
  input[type="checkbox"], input[type="radio"], input[type="range"],
  input[type="file"], input[type="color"], select,
  .sidebar, .mobile-nav, .dock, nav
) {
  -webkit-user-select: none;
  user-select: none;
}

/* Les champs de saisie restent sélectionnables même quand ils vivent dans une
   zone marquée `none` ci-dessus (la propriété est héritée) : sans ce
   rattrapage, impossible de sélectionner ce qu'on vient d'écrire dans un
   champ posé dans la sidebar ou dans un <label>. */
:where(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]),
       textarea, [contenteditable="true"], [contenteditable=""]) {
  -webkit-user-select: text;
  user-select: text;
}

/* Le halo bleu au tap (Android/iOS) n'a pas plus sa place que le bleu de
   sélection. css/mobile.css l'annule déjà zone par zone ; ici c'est global. */
:where(a, button, [role="button"], .btn) { -webkit-tap-highlight-color: transparent; }
