/* La palette du château — UNE seule, pour tout le site public.

   ── Ce que la palette est aujourd'hui ──
   Des NEUTRES : blanc, gris, taupe, presque-noir. Un seul accent, l'or du
   blason. Andy, 19/08 : « 깔끔, 담백, 선명, 깨끗, 명료함 » — et la référence
   qu'il donne est www.chateaudubu.fr, pas une charte inventée ici.

   ⛔ ── La charte du massif est RETIRÉE, et sa RAISON avec elle ──
   Du 03/08 au 19/08 les couleurs étaient tirées de quatre photos du massif du
   château (k-moyennes en Lab) : lysimaque dorée, olive, feuillage sombre. La
   raison était « 난 자연의 색이 좋아 » et une proposition de Mouloud. Andy a
   tranché le 19/08 : « 물루드가 제시했던 '녹색' 걷어내. 전면적으로 수정해 ».

   Cette raison est réécrite ici EXPRÈS, retirée en même temps que la règle :
   une session qui retrouverait les photos sans savoir qu'elles ont été
   écartées en redériverait du vert, et le vert reviendrait par la porte du
   raisonnement. Le verdict porte sur la TEINTE, pas sur la méthode.

   Ce qui restait du vert et que la refonte des jetons ne pouvait pas atteindre
   — courbes SVG en `#0f2d21`, voiles `rgba(13,36,25,…)` — était écrit EN DUR
   dans les gabarits, sans lien vers ce fichier. Retiré le 19/08. *Un jeton ne
   gouverne que ce qui l'appelle.*

   ── Ce qui n'a jamais changé ──
   • L'OR DU BLASON (`--or`, `--or-pale`) : « 로고의 색상을 살리고 ». C'est le
     seul accent qui survit aux deux chartes.
   • Le BLANC. « 여백의 흰색은 언제나 환영이야. 깔끔함을 주니까. »
   • Les NOMS des jetons (`--vert…`, `--lysimaque…`). Douze pages les appellent ;
     les renommer aurait été une seconde refonte, invisible et risquée. Ils
     portent des neutres — lire le nom comme une couleur est une erreur.

   ── Contrastes ──
   Tous les couples texte/fond utilisés passent WCAG AA (≥ 4,5:1) — mesuré, pas
   supposé. Les couleurs de SURFACE ne sont jamais du texte : `--lysimaque`
   plafonne à 2,03:1 sur blanc, `--pierre` à 2,54:1, `--or` à 2,4:1. Pour du
   texte secondaire sur fond clair, `--sourdine` (6,69:1) ou `--olive` (5,66:1).

   ⚠ Ne pas redéclarer ces variables dans une page : c'est ce qui avait produit
   seize `:root` divergents. `tests/test_palette.py` échoue si l'une revient. */

/* ⚠ iOS Safari « gonfle » le texte qu'il juge trop petit quand on tourne le
   téléphone en paysage — et le laisse gonflé au retour en portrait (Andy,
   04/09, le barème de la console). Toutes les pages chargent cette feuille :
   la taille reste celle qu'on a composée. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

/* D'une page à l'autre, un fondu au lieu d'un blanc — transition entre
   documents (Chrome 126+, Safari 18.2+ ; ailleurs, rien ne change). La
   règle doit être dans la page qu'on quitte ET dans celle qui arrive :
   c'est pourquoi elle vit ici, la feuille de toutes les pages. */
@view-transition { navigation: auto; }
@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }

/* ── `hidden` doit vraiment cacher ────────────────────────────────────────
   `hidden` est un ATTRIBUT ; la feuille du navigateur lui donne `display:none`,
   mais la moindre règle d'auteur qui pose un `display` la bat. L'élément que le
   script croit avoir caché reste alors à l'écran, sans que rien ne le signale.

   Ce n'est pas une hypothèse, c'est trois fois :
   * le message de confirmation du formulaire de réception (`display:grid`),
     invisible d'un côté, poussé hors cadre de l'autre ;
   * le lecteur de la fiche photo (`dialog video{display:block}`), un cadre
     noir vide sous chaque photo et un « 00:00 / 00:00 » sous chaque vidéo
     de réserve — signalé par Andy le 06/08 ;
   * et quatre autres endroits déjà rattrapés un par un, chacun avec sa propre
     ligne (`.onglet[hidden]`, `.stats[hidden]`, `.filtres[hidden]`,
     `.barre-basse button[hidden]`).

   Quatre corrections identiques écrites séparément, c'est une classe de bogue
   qu'on soigne cas par cas. On la ferme ici, une fois. `!important` est justifié :
   la règle ne dit pas une préférence de style, elle dit ce que l'attribut
   SIGNIFIE — et rien ne doit pouvoir le contredire. Vérifié avant de l'écrire :
   aucune page ne montre un élément `hidden` par `style.display`.

   Les lignes déjà écrites au cas par cas deviennent redondantes ; elles ne
   nuisent pas et restent là où elles documentent un piège précis. */
[hidden] { display: none !important; }

:root {
  /* ---- Neutres — le blanc est roi, et cette fois littéralement ------ */
  --surface:        #ffffff;   /* cartes, panneaux                       */
  --carte:          #ffffff;   /* alias historique de --surface          */
  --fond:           #ffffff;   /* page : BLANC. L'ancien #fbfaf5 tirait
                                  vers le vert — c'est ce voile qui
                                  éteignait le texte posé dessus.        */
  --fond-tiede:     #f3f3f1;   /* sections alternées — gris neutre       */
  --parchemin:      #f0efeb;   /* aplats chauds (encadrés, citations)    */
  --encre:          #1a1a1a;   /* presque noir, SANS teinte  17,4:1 ✓    */
  --sourdine:       #5c5c5c;   /* texte secondaire, gris neutre 6,7:1 ✓  */
  --gris:           #5c5c5c;   /* alias historique de --sourdine         */
  --bord:           #e5e3dd;   /* filets, séparateurs                    */

  /* ---- L'ossature — pierre et charbon, non plus feuillage ----------- */
  /* ⚠ Les NOMS restent (`--vert…`) : douze pages les appellent, et les
     renommer aurait été une seconde refonte, invisible et risquée. Ce
     qu'ils portent, lui, a changé — ce sont désormais des neutres chauds,
     de la pierre du château plutôt que de la feuille.                   */
  --vert:           #6e665a;   /* boutons pleins, taupe moyen 5,7:1 ✓    */
  --vert-fonce:     #26241f;   /* barres, pieds de page      15,5:1 ✓    */
  --vert-doux:      #f0efe9;   /* aplats clairs                          */
  --vert-clair:     #f0efe9;   /* alias historique de --vert-doux        */
  --olive:          #6f6656;   /* petites capitales, texte  5,7:1 ✓      */

  /* ---- La famille du blason — elle remplace la lysimaque ------------ */
  /* ⚠ SURFACE uniquement. Jamais de texte.                             */
  --lysimaque:      #c9b391;
  --lysimaque-clair:#e3d6bf;
  --lysimaque-pale: #f5f0e7;

  /* ---- L'or du blason — INCHANGÉ ------------------------------------ */
  --or:             #c5a35c;
  --or-fonce:       #82682f;   /* 5,3:1 sur le blanc                     */
  --or-pale:        #ecdfc2;

  /* ---- Points de couleur — ils piquent, ils ne couvrent pas -------- */
  --campanule:      #6553a8;   /* violet                      6,3:1 ✓    */
  --campanule-pale: #ece9f6;
  --heuchere:       #a75544;   /* corail                      5,2:1 ✓    */
  --heuchere-pale:  #f7e8e2;
  --rouge:          #a75544;   /* alias historique de --heuchere         */
  --pierre:         #a8a294;   /* le muret du massif                     */
  /* ⚠ Le seul vert de la charte, et il est CONFINÉ : le bouton « ajouter
     cette chambre » du tunnel et la barre du panier qui lui répond — deux
     gestes qui doivent se distinguer de l'or du « continuer » (Andy, 02/09,
     choisi parmi cinq candidats). Ailleurs, le verdict du 19/08 tient.    */
  --tilleul:        #566d28;   /* blanc dessus                5,8:1 ✓    */
  --tilleul-fonce:  #3f5219;   /* survol                                 */
  /* Le vert clair de la prairie du château (échantillonné sur hero-chateau.jpg),
     CONFINÉ au bouton du chat public (Andy, 04/09) — encre dessus, 7,2:1 ✓ */
  --prairie:        #a0b030;
  --prairie-pale:   #eef2d9;   /* la bulle du visiteur                   */
  /* Le turquoise du fil du bracelet d'Andy (photo du 04/09), CONFINÉ au chat
     de la console : le ton DONNÉ, pas un plus dense — l'assombrir pour la
     règle du contraste rendait la fenêtre lourde (Andy). Un seul ton, du
     blanc dessus, et l'icône du bouton peinte du même. */
  --lagon:          #24979e;
  --lagon-fonce:    #1d7c82;   /* survol                                 */

  /* ---- Couleur des petites capitales ------------------------------- */
  /* Les étiquettes (`.eyebrow`, `.cat-eyebrow`…) changent de couleur
     selon ce qu'il y a DESSOUS. Une propriété personnalisée hérite : les
     conteneurs sombres la redéfinissent, et tout leur contenu suit, à
     n'importe quelle profondeur. C'est la seule façon de ne pas devoir
     y revenir — l'or sur clair donne 2,4:1, et l'erreur a été faite. */
  --etiquette:      #6f6656;   /* = --olive, sur fond clair    5,7:1 ✓  */
}

/* Tout conteneur sombre bascule ses étiquettes vers l'or pâle (11,1:1).
   La classe est posée sur les blocs qui portent un fond vert ou une
   photo assombrie ; elle se déclare une fois, jamais par étiquette. */
.sur-sombre { --etiquette: #ecdfc2; }

/* ── Le filet de sécurité de `.reveal` ───────────────────────────────────
   Les sections apparaissent au défilement : `opacity:0` au départ, `.vu`
   ajouté par un IntersectionObserver. Tant qu'on défile, tout va bien.

   Deux cas où l'on ne défile pas, et où la page reste donc VIDE :

   • À L'IMPRESSION. Le navigateur rend le document entier d'un coup ; les
     sections jamais entrées dans la fenêtre restent à `opacity:0` et sortent
     blanches. Aucune page ne s'en protégeait — la fiche de réception avait
     déjà donné cette leçon le 01/08, sur un autre écran.
   • EN MOUVEMENT RÉDUIT. Quatre pages sur six coupaient l'animation ;
     `apercu-hotel` et `histoire-detail` l'oubliaient.

   La règle vit ici parce que `.reveal` est déclaré dans six feuilles de style
   différentes, et qu'une septième arrivera. Nom de classe doublé : `palette.css`
   est chargée AVANT les `<style>` des pages, et il faut battre leur `.reveal`
   à spécificité égale. */
@media print {
  .reveal.reveal { opacity: 1 !important; transform: none !important; }
}
@media (prefers-reduced-motion: reduce) {
  .reveal.reveal { opacity: 1; transform: none; transition: none; }
}

/* ── Coupure de ligne en coréen ──────────────────────────────────────────
   Andy, 03/08 : « 가독성도 꼭 보고 […] 문장은 자연스러운지 ».

   Le coréen s'écrit sans espace à l'intérieur d'un 어절 mais AVEC des espaces
   entre eux. Par défaut, le navigateur le traite comme du chinois et coupe
   n'importe où : le titre de l'accueil donnait « 노르망디의 심 / 장에 자리한 »,
   le mot 심장 tranché en deux. C'est la faute de typographie coréenne la plus
   visible qui soit, et elle passe inaperçue quand on relit en français.

   `keep-all` coupe aux espaces, donc entre 어절. On l'applique au coréen SEUL :
   le chinois et le japonais, eux, se coupent bien caractère par caractère, et
   leur imposer `keep-all` produirait des lignes à moitié vides.

   `overflow-wrap:break-word` reste le filet : un mot plus large que sa colonne
   (une URL, un nom propre latin) cède plutôt que de déborder.
   ⚠ `anywhere` et non `break-word` : la différence a l'air nulle et ne l'est
   pas. `anywhere` entre dans le calcul de la largeur MINIMALE d'une boîte, si
   bien qu'un conteneur flexible se laisse écraser jusqu'à couper les mots
   qu'il contient. En 320 px, le sélecteur de langue affichait « K » au-dessus
   de « O ». `break-word` ne coupe que ce qui déborde vraiment. */
:lang(ko) { word-break: keep-all; overflow-wrap: break-word; }

/* ── La barre de marque sur les très petits écrans ───────────────────────
   En 320 px, `.marque` (blason + « Château du Bû » + losange doré) demande
   226 px et n'en reçoit que 159. Le conteneur est en `flex`, donc il l'écrase ;
   mais le CONTENU, lui, déborde en `overflow:visible` et passe sous le
   sélecteur de langue. Rien ne le signale — pas de barre de défilement, pas
   d'avertissement : le nom du château se retrouve simplement à moitié caché
   derrière un drapeau.

   Sous 380 px on retire le losange (pure ornementation) et on réduit blason et
   nom jusqu'à ce que l'ensemble tienne. Le nom reste ENTIER : c'est la
   première chose que lit un visiteur arrivé par un lien.

   LA CAUSE, et elle n'est pas propre au petit écran : `.marque` est un élément
   flex qui se laisse RÉTRÉCIR sous la largeur de son contenu, lequel déborde
   ensuite en `overflow:visible`. En 1280 px et en français, « Château du Bû »
   passait par-dessus le lien « Chambres » de la barre — sur la page d'accueil,
   au premier coup d'œil, depuis toujours. `flex-shrink:0` règle la cause ; la
   réduction ci-dessous ne sert plus qu'aux écrans où même la taille naturelle
   ne rentre pas.

   Nom de classe DOUBLÉ : `palette.css` se charge avant les `<style>` des pages,
   et à spécificité égale c'est la page qui gagne. La première version de ce
   bloc n'avait aucun effet — la barre débordait toujours. Même piège que pour
   les motifs. */
.marque.marque { flex: 0 0 auto; min-width: max-content; }
@media (max-width: 380px) {
  .marque.marque img { height: 32px; }
  .marque.marque span { font-size: 1rem; letter-spacing: 0; }
  .marque.marque { gap: .38rem; }
}
@media (max-width: 340px) {
  .marque.marque img { height: 27px; }
  .marque.marque span { font-size: .92rem; }
}

/* Entre le tiroir mobile (≤ 900 px) et le confort (≥ 1440 px), la barre est
   TROP CHARGÉE : blason + nom + huit liens + sélecteur de langue + bouton.
   En français à 1280 px elle réclame 1263 px pour 1178 disponibles ; en
   néerlandais, 1303. (Sous 1280 px, c'est le menu qui prend le relais —
   voir le bloc suivant.) `.marque` absorbait le déficit en débordant sur les liens,
   ce qui donnait l'illusion que tout tenait. Une fois qu'on l'en empêche, le
   dépassement se voit — c'est le même défaut, enfin visible.

   On rend la place là où elle coûte le moins : un blason plus discret et des
   liens moins espacés. Le nom du château reste entier, les huit rubriques
   restent visibles.

   La borne haute est 1699 px et non 1439 : en russe et en ukrainien, les
   libellés sont assez longs pour que le déficit revienne dès que la
   compression s'arrête (55 px en russe à 1600 px). On règle sur la langue
   la plus large, pas sur la sienne — deuxième fois dans ce fichier. */
/* ⛔ Cette compression NE TOUCHE PLUS la barre du site, et c'est voulu.
   Elle avait été écrite quand chaque page portait sa marque ; elle vise
   `.marque.marque` (0,2,1) et l'en-tête partagée pose `header.barre .marque`
   (0,2,2) — elle ne pouvait donc plus l'atteindre, et personne ne s'en était
   aperçu : le blason restait à 54 px là où on croyait l'avoir réduit à 40, et
   la barre se repliait en espagnol et en néerlandais pour dix-huit pixels.
   *Une règle écrite pour battre les PAGES perd contre le COMPOSANT arrivé
   après.* La barre gère désormais sa propre compression (`header.barre.compact`
   dans `entete.js`), qui est le seul endroit sachant ce qu'elle contient.
   Ce qui reste ici sert les pages qui ont encore leur propre marque —
   réservation, album, consoles. */
@media (min-width: 1280px) and (max-width: 1699px) {
  .marque.marque img { height: 40px; }
  .marque.marque span { font-size: 1.2rem; }
}

/* ⛔ ── Le seuil dur de repli à 1279 px a été RETIRÉ le 19/08 ─────────────
   Il posait `.liens.liens { display:none !important }` et
   `.burger.burger { display:block }`. Il avait raison quand chaque page
   écrivait sa propre barre. Depuis que `static/entete.js` porte l'en-tête, il
   fait DEUX dégâts, tous deux constatés en production :

   • Une bande SANS AUCUNE NAVIGATION entre 1000 et 1279 px, sur sept pages.
     Le `!important` cachait les liens ; le `display:block` du burger, lui,
     n'avait pas d'`!important` et perdait contre `header.barre .burger
     { display:none }`. Ni liens, ni burger. Et le repli dynamique de l'en-tête
     ne rattrapait rien : il mesurait une rangée déjà cachée, donc 0 contre 0,
     donc « ça rentre ».

   • Sur `/hotel/restaurant`, les quinze blocs `.liens` du CONTENU — téléphone
     et itinéraire de chaque table voisine — DISPARAISSAIENT sous 1280 px.
     C'est-à-dire pour à peu près tous les visiteurs. `.liens` est un nom
     générique ; la règle disait « la rangée de navigation » et frappait tout
     ce qui portait ce mot.
     ⭐ *Un sélecteur générique posé au niveau du site est une règle qu'on ne
     peut plus relire* — même famille que le `tr:first-child` écrit en pensant
     « en-tête ». Ce qui appartient à l'en-tête se nomme `header.barre …`.

   Le repli est désormais décidé au seul endroit qui sait ce que la barre
   contient : `entete.js`, qui mesure la rangée et se replie quand elle
   déborde — ou quand elle n'est pas mesurable. */

/* Le russe et l'ukrainien restent 38 px trop larges à 1280 px, une fois la
   compression générale appliquée. Plutôt que de remonter le seuil du menu pour
   TOUT LE MONDE — et de priver les portables 1280 d'une barre qui leur va très
   bien dans huit langues sur dix — on resserre ces deux-là. La règle porte la
   raison de son existence dans son sélecteur. */
/* ⛔ Le resserrement russe/ukrainien vivait ici et visait la rangée de la
   barre : il part avec le reste. L'état `compact` d'`entete.js` s'applique à
   TOUTES les langues dès que la rangée déborde — mesuré, pas deviné, donc il
   n'y a plus de liste de langues à tenir à jour. */
@media (min-width: 1280px) and (max-width: 1400px) {
  :lang(ru) .marque.marque span, :lang(uk) .marque.marque span { font-size: 1.08rem; }
}

/* ── Les fontes ───────────────────────────────────────────────────────────
   Andy, 19/08 : « '샤토에 어울리는' 폰트 다 걷어내고, 아이폰 수준의 단순
   폰트로 다 바꿔 ».

   Playfair Display et Jost partaient — deux fontes VARIABLES téléchargées sur
   chaque page — pour dire « château ». Elles le disaient bien ; elles le
   disaient à la place du texte. Ici c'est la pile du SYSTÈME : San Francisco
   sur iPhone, Segoe sur Windows, Roboto sur Android. Le lecteur ne la
   remarque pas, et c'est exactement ce qu'on lui demande.

   ⚠ Ce n'est pas une pile inventée : c'est celle des consoles
   d'exploitation, replis coréens compris. Elle couvre le cyrillique et les
   CJK sans un octet de téléchargement — et le site parle dix langues.

   ⭐ Une seule famille pour le titre ET le texte, comme sur iOS : la
   hiérarchie se dit par la TAILLE et le POIDS, jamais par un changement de
   fonte. `--f-display` reste nommé ainsi parce que quinze pages l'appellent.
   Déclaré ICI, plus dans chaque page — c'est la leçon de l'en-tête. */
:root {
  --f-display: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Noto Sans KR","Apple SD Gothic Neo","Malgun Gothic",Arial,sans-serif;
  --f-corps:   -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Noto Sans KR","Apple SD Gothic Neo","Malgun Gothic",Arial,sans-serif;
  /* ── Fonte du RÉCIT (pages d'histoire) — un jeton à part, pour une étape
     à venir. Andy a comparé nos pages d'histoire à un magazine sur son
     iPhone (24/08) : à taille et interligne égaux, le magazine se lisait
     mieux — il est en serif. ESSAI du 25/08 en serif SYSTÈME (Iowan Old
     Style / Palatino / Georgia, replis CJK et cyrillique) : REJETÉ par Andy
     le jour même — « 시스템 세리프는 영 별로 », bien en deçà du serif du
     magazine. Retour à la pile système, et une étape dédiée viendra choisir
     une VRAIE fonte de lecture (voir le mémoire `en-attente`).

     ⚠ Le jeton reste : `.chap p, .doc p` l'appellent déjà, donc le jour où
     la fonte est choisie, c'est CETTE ligne qui change et rien d'autre.
     ⚠ Le retour n'était PAS « une ligne » comme annoncé : les trois `:lang()`
     de repli auraient continué à pousser ru/uk vers Georgia et ko/zh vers un
     serif CJK. Ils sont retirés avec l'essai. */
  --f-lecture: var(--f-corps);
  /* Taille du CORPS DE LECTURE — les vrais paragraphes, pas les légendes ni
     les puces. Unifiée le 24/08 (opérateur : l'histoire et le contact
     paraissaient plus petits que l'accueil — 16 et 14,7 px contre 16,6).
     Un seul jeton, sinon chaque page dérive de nouveau. */
  --corps: 1.05rem;
  /* Colonne de lecture EMPILÉE — sous 900 px (téléphone en paysage, tablette
     en portrait), texte ET média partagent cette largeur, centrés. L'opérateur
     (24/08, captures paysage) : un paragraphe à 48ch au-dessus d'une image
     pleine largeur, les deux bords ne se répondent plus. Un seul jeton,
     géré ici — pas une largeur par section. */
  --colonne: 35rem;
}
