/* LE CORBEAU QUI SUIT LA LECTURE.
 *
 * Sur les trois pages autres que la bibliothèque, il y en avait DEUX : un au
 * milieu d'une section et un dans le pied, à quelques centimètres l'un de
 * l'autre. Deux fois le même oiseau sur un écran, ce n'est plus une mascotte,
 * c'est un motif de papier peint.
 *
 * Il n'en reste qu'un, et il accompagne : posé en bas à droite, il commente la
 * section qu'on est en train de lire. Le corbeau devient alors ce qu'il aurait
 * dû être dès le début — quelqu'un qui lit la page avec vous — au lieu d'une
 * décoration posée deux fois.
 *
 * Quatre choses que cette feuille prend au sérieux :
 *
 *   1. IL NE BLOQUE RIEN. Le conteneur ne reçoit pas les clics ; seuls
 *      l'oiseau et sa bulle les reçoivent. Un compagnon qui avale le clic d'un
 *      bouton qu'il recouvre est une nuisance, pas une présence.
 *   2. IL S'EFFACE DEVANT LE PIED DE PAGE. Sinon il se retrouve par-dessus le
 *      corbeau du pied — le problème qu'on vient de corriger, revenu par la
 *      fenêtre.
 *   3. IL SE RANGE DU BON CÔTÉ EN ARABE. `inset-inline-end` et non `right` :
 *      en lecture de droite à gauche, la marge libre est à gauche.
 *   4. IL SE TAIT SI ON LUI DEMANDE DU CALME. `prefers-reduced-motion` coupe
 *      les fondus ; le texte, lui, change quand même.
 */

.compagnon {
  position: fixed;
  inset-block-end: clamp(14px, 3vh, 26px);
  inset-inline-end: clamp(14px, 3vw, 34px);
  z-index: 40;
  /* L'ECART TIENT COMPTE DE LA POINTE. Elle deborde de la bulle de sept
     pixels-charte - vingt et un a l'ecran - donc un ecart de dix la faisait
     entrer dans le corps de l'oiseau. Trente laisse la pointe le designer sans
     le toucher. */
  display: flex; align-items: flex-end; gap: 30px;
  /* Le conteneur laisse passer les clics ; ses enfants les reprennent. */
  pointer-events: none;
  opacity: 0; transform: translateY(10px);
  transition: opacity .45s ease, transform .45s cubic-bezier(.22, .8, .3, 1);
}
.compagnon.la { opacity: 1; transform: none; }

/* La bulle est DEVANT l'oiseau, du côté d'où vient la lecture : à sa gauche en
   français, à sa droite en arabe. Posée de l'autre côté elle sortirait de
   l'écran. */
.compagnon .bulle {
  pointer-events: auto;
  max-inline-size: min(30ch, 52vw);
  margin-block-end: 6px;
  transition: opacity .28s ease;
}
.compagnon.change .bulle { opacity: 0; }

/* LA POINTE DOIT VISER L'OISEAU. Dans le pied de page l'oiseau est du cote du
   debut et la bulle apres lui : la pointe par defaut, accrochee au bord de
   debut, le vise juste. Ici l'ordre est inverse - la bulle d'abord, l'oiseau
   ensuite - donc elle restait accrochee du mauvais cote, a designer le vide a
   gauche pendant que l'oiseau attendait a droite.

   Elle passe au bord de fin et se retourne. En arabe elle se retourne une
   seconde fois : la regle generale mirroite deja toutes les pointes, or
   celle-ci est desormais du bon cote. Deux retournements valent une position
   juste. */
.compagnon .bulle-queue {
  inset-inline-start: auto;
  inset-inline-end: calc(var(--px) * -7);
  transform: scaleX(-1);
}
[dir="rtl"] .compagnon .bulle-queue { transform: none; }

/* Deux lignes de monospace serrees se lisent mal a la volee, et cette bulle se
   lit toujours a la volee : on regarde ailleurs pendant qu'elle parle. */
.compagnon .bulle-boite {
  padding: .62rem .82rem;
  line-height: 1.75;
}

.compagnon .cw {
  pointer-events: auto;
  inline-size: auto; block-size: 4.1rem;
  cursor: pointer; overflow: visible;
  /* Une ombre très basse : elle pose l'oiseau sur la page au lieu de le
     laisser flotter devant elle. */
  filter: drop-shadow(0 10px 14px rgba(33, 29, 25, .22));
}
:root[data-theme="dark"] .compagnon .cw,
:root:not([data-theme="light"]) .compagnon .cw {
  filter: drop-shadow(0 10px 16px rgba(0, 0, 0, .5));
}

/* LE CORBEAU DU PIED S'EN VA, sur ces pages-là seulement. C'est le même
   oiseau : le garder en bas ET en flottant, c'est reproduire exactement le
   doublon qu'on enlève. */
.a-compagnon .foot .perchoir { display: none; }

/* Sur un téléphone, une bulle de trente caractères à côté d'un oiseau de
   quatre rem prend la moitié de la largeur. On réduit les deux, et la bulle
   passe AU-DESSUS : côte à côte, il ne resterait rien pour le texte. */
/* SUR UN TELEPHONE AUSSI, COTE A COTE. La premiere version empilait la bulle
   au-dessus de l'oiseau pour gagner de la largeur ; la pointe se retrouvait
   alors a designer le vide a cote d'elle, et elle debordait de l'ecran par la
   droite. Reduits, les deux tiennent en rangee : a 375 px il reste plus de
   deux cents pixels pour le texte, soit largement les vingt-six caracteres
   qu'on lui accorde. */
@media (max-width: 34rem) {
  .compagnon { gap: 22px; }
  .compagnon .bulle { max-inline-size: min(24ch, 52vw); }
  .compagnon .bulle-boite { font-size: .6875rem; padding: .5rem .65rem; }
  .compagnon .cw { block-size: 3rem; }
}

/* Écran très bas — un téléphone couché — : l'oiseau mangerait le tiers de ce
   qu'on essaie de lire. */
@media (max-height: 26rem) {
  .compagnon { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .compagnon, .compagnon .bulle { transition: none; }
}

/* ── D'UNE PARTIE A L'AUTRE ────────────────────────────────────
   Le defilement se pose sur le debut d'une section au lieu de s'arreter
   n'importe ou. Trois decisions, et la premiere est la seule qui compte :

   `proximity`, PAS `mandatory`. Avec `mandatory` le navigateur DOIT finir sur
   un point d'accroche : sur une section de quinze cents pixels - celle des
   demonstrations en fait mille cent - on ne peut plus s'arreter au milieu pour
   lire, la page vous tire au prochain titre a chaque geste. `proximity` ne se
   manifeste que si on s'est deja arrete pres d'un debut de section : elle range
   le defilement au lieu de le conduire.

   Le decalage haut est celui de la barre collante. Sans lui, la section sur
   laquelle on se pose commence SOUS la barre et son titre est cache - le seul
   mot qu'on voulait voir.

   Rien de tout cela sur la bibliotheque : elle n'a pas de sections, elle a une
   etagere, et s'accrocher au milieu d'une grille de couvertures n'aurait aucun
   sens. C'est pour cela que cette feuille n'est chargee que par les trois
   autres pages. */
@media (min-height: 34rem) {
  html {
    scroll-snap-type: y proximity;
    scroll-padding-block-start: 5.6rem;
  }
  main > section { scroll-snap-align: start; }
}
/* Le glissement, lui, EST du mouvement : un saut d'ancre qui traverse trois
   ecrans en glissant est exactement ce qu'un reglage de confort demande de ne
   pas faire. L'accroche reste - elle ne bouge rien, elle range. */
@media (min-height: 34rem) and (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* L'ARRIVEE D'UNE SECTION. Elle monte de quelques pixels et se revele, une fois,
   pendant qu'elle entre dans la fenetre.

   `animation-timeline: view()` attache l'animation au DEFILEMENT lui-meme et
   non a une horloge : la section se revele a la vitesse ou on la decouvre, elle
   se re-voile si on remonte, et il n'y a pas une ligne de JavaScript ni une
   seule image calculee quand la page est immobile. Derriere @supports parce
   qu'un navigateur qui ne connait pas la regle doit montrer la page, pas une
   page a moitie transparente. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) and (min-height: 34rem) {
    main > section {
      animation: arrivee-section linear both;
      animation-timeline: view();
      /* Fini bien avant le milieu de l'ecran : on lit une section qui est
         arrivee, pas une section qui finit d'arriver. */
      animation-range: entry 0% entry 38%;
    }
    @keyframes arrivee-section {
      from { opacity: .35; transform: translateY(22px); }
      to   { opacity: 1;   transform: none; }
    }
  }
}
