/* ---------------------------------------------------------------------------
   FLY OR DIE — LA FEUILLE DE STYLE.
 
   Elle vivait dans index.html, entre la ligne 18 et la ligne 888 : huit cent
   soixante-dix lignes de mise en page posées juste avant dix-sept mille lignes
   de jeu. Toucher à une marge demandait de traverser tout le fichier, et les
   deux sujets n'ont rien à se dire.
 
   Elle est cachée par le service worker comme le reste : le jeu s'installe et
   se lance toujours sans réseau.
   ------------------------------------------------------------------------ */

/* ---------------------------------------------------------------------------
   LA POLICE EST DANS LE DÉPÔT.
 
   Elle venait de Google Fonts. Trois conséquences, dont une grave :
 
   — HORS RÉSEAU, LA PREMIÈRE FOIS, ELLE N'ARRIVE JAMAIS. Le jeu s'installe,
     on le rouvre dans un avion ou un train, et tout le texte tombe sur la
     police système du téléphone. Le service worker cache tout ce qui est de
     la même origine ; Google Fonts n'en est pas, et ne se mettait en cache
     qu'après un premier passage réussi. C'est exactement le cas d'usage d'un
     jeu installable, et c'était le seul endroit où il cassait.
 
   — UN JEU AU TRAIT SE LIT À SES CHIFFRES. L'échelle d'altitude, le compas, la
     jauge de structure : tout est aligné au caractère, et une police non
     monospace décale les colonnes. Le HUD se redessine à chaque image, donc
     une police tardive se rattrape — mais une police absente, non.
 
   — ET C'EST UNE REQUÊTE VERS UN TIERS, sur un jeu qui n'en fait aucune autre.
 
   Quatre fichiers, quarante-huit kilooctets, les mêmes que ceux que Google
   servait. Ils sont dans le socle du service worker : ils arrivent à
   l'installation, avec le reste.
   ------------------------------------------------------------------------ */
  @font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 400;
    /* BLOCK, ET PAS SWAP. Le fichier est à côté du jeu, sur la même origine,
       préchargé : l'attente se compte en millisecondes. « swap » afficherait
       une police système pendant ce temps-là, puis basculerait — c'est le
       clignotement qu'on voit sur la moitié des sites. Si le fichier manquait
       vraiment, le navigateur rendrait la main au bout de trois secondes. */
    font-display: block;
    src: url('vendor/plex/plex-mono-400-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
  }
  @font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 400;
    /* BLOCK, ET PAS SWAP. Le fichier est à côté du jeu, sur la même origine,
       préchargé : l'attente se compte en millisecondes. « swap » afficherait
       une police système pendant ce temps-là, puis basculerait — c'est le
       clignotement qu'on voit sur la moitié des sites. Si le fichier manquait
       vraiment, le navigateur rendrait la main au bout de trois secondes. */
    font-display: block;
    src: url('vendor/plex/plex-mono-400-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }
  @font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 500;
    /* BLOCK, ET PAS SWAP. Le fichier est à côté du jeu, sur la même origine,
       préchargé : l'attente se compte en millisecondes. « swap » afficherait
       une police système pendant ce temps-là, puis basculerait — c'est le
       clignotement qu'on voit sur la moitié des sites. Si le fichier manquait
       vraiment, le navigateur rendrait la main au bout de trois secondes. */
    font-display: block;
    src: url('vendor/plex/plex-mono-500-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
  }
  @font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 500;
    /* BLOCK, ET PAS SWAP. Le fichier est à côté du jeu, sur la même origine,
       préchargé : l'attente se compte en millisecondes. « swap » afficherait
       une police système pendant ce temps-là, puis basculerait — c'est le
       clignotement qu'on voit sur la moitié des sites. Si le fichier manquait
       vraiment, le navigateur rendrait la main au bout de trois secondes. */
    font-display: block;
    src: url('vendor/plex/plex-mono-500-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }
  :root {
    --ph-line: #46ffa0;
    --ph-text: #8ffcc4;
    --ph-dim: rgba(70, 255, 160, 0.4);
    --ph-fill: #0a1f16;
    --ph-bg: #04070a;
    --ph-chrome: #071812;
  }

  /* touch-action n'est pas une propriété héritée : la poser sur html et body
     ne protégeait rien de ce qu'il y a dedans. Les canvas gardaient donc le
     comportement par défaut, et sur iOS deux appuis rapprochés déclenchaient
     le zoom-au-double-tap — ce qui décalait toute la page et laissait une
     bande noire en bas. Exactement le geste qui sert à faire une figure. */
  * { touch-action: none; }
  /* seuls les panneaux doivent encore défiler au doigt */
  /* Et sur tout ce qu'ils contiennent. touch-action n'est pas héritée : la
     règle universelle ci-dessus la remettait à « none » sur chaque paragraphe,
     chaque vignette, chaque titre. Or c'est l'élément où le doigt SE POSE qui
     décide. Poser le doigt sur un texte du panneau bloquait donc le
     défilement, et seule la mince bande de la barre de défilement — qui, elle,
     appartient au panneau lui-même — répondait. */
  #aide, #aide *, #changelog, #changelog *, #viseurs, #viseurs *,
  #coop, #coop *, #overlay, #overlay *, #menu, #menu *, #infos, #infos *,
  #install, #install *,
  /* LA LETTRE N'Y ÉTAIT PAS. Elle défile depuis toujours — « touch-action:
     pan-y » est écrit sur sa feuille — mais la règle universelle au-dessus
     remettait « none » sur chaque paragraphe, et c'est l'élément où le doigt
     SE POSE qui décide. Poser le doigt sur le texte d'Émilie ne faisait donc
     rien, et il fallait viser la barre de défilement, à droite. On lit une
     lettre en la poussant du pouce, n'importe où sur la page. */
  #lettre, #lettre *, #carteMur, #carteMur *,
  #guitare, #guitare * { touch-action: pan-y; }
  /* ET SANS BARRE. Une barre de défilement dit « ceci est une page web ».
     Une lettre n'en a pas : elle a un bord, et on la fait glisser. */
  #lettre .feuille, #carteMur .papier, #guitare .papier { scrollbar-width: none; }
  #lettre .feuille::-webkit-scrollbar, #carteMur .papier::-webkit-scrollbar,
  #guitare .papier::-webkit-scrollbar { display: none; }
  /* LA LOUPE DE L'IPHONE. Deux appuis rapprochés sur du texte font surgir un
     ovale grossissant, celui de la sélection : il passe par-dessus le jeu au
     moment précis où l'on fait une figure. Il ne naît que là où le texte est
     sélectionnable, donc on l'interdit partout sauf dans les champs où l'on
     tape vraiment. */
  /* ET AVEC PRIORITÉ. Une règle universelle a la spécificité la plus faible
     du document : n'importe quelle règle plus précise écrite plus bas — et il
     y en a — la reprenait sur l'élément concerné, et la loupe revenait
     exactement là. Le « !important » est ici à sa place : ce n'est pas un
     réglage de mise en page, c'est une interdiction. */
  *:not(input):not(textarea) {
    -webkit-user-select: none !important;
    user-select: none !important;
    -webkit-touch-callout: none !important;
    -webkit-tap-highlight-color: transparent;
  }
  /* et la loupe se nourrit aussi du curseur de texte : aucun élément du jeu
     n'en affiche un, donc aucun ne se présente comme du texte à prendre */
  *:not(input):not(textarea) { cursor: default; }
  a, button, label, summary { cursor: pointer; }

  html, body {
    margin: 0;
    height: 100%;
    overflow: hidden;
    background: var(--ph-bg);
    color: var(--ph-text);
    touch-action: none;
    overscroll-behavior: none;
    font-family: "IBM Plex Mono", ui-monospace, monospace;
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
    -webkit-tap-highlight-color: transparent;
  }

  canvas { display: block; }

  /* la scène 3D et le calque HUD 2D occupent tous les deux tout l'écran,
     le HUD par-dessus et transparent aux doigts (les gestes sont écoutés
     sur window, pas sur un élément particulier) */
  #scene, #hud {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
  }
  #hud { z-index: 5; pointer-events: none; }

  #topbar, #bottombar {
    position: fixed;
    left: 0;
    right: 0;
    z-index: 10;
    background: var(--ph-chrome);
    color: var(--ph-text);
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 12px;
    letter-spacing: 0.08em;
    overflow: hidden;
  }
  /* sur un téléphone étroit, tout doit pouvoir rétrécir plutôt que
     pousser le bouton de version hors de l'écran */
  #topbar > *, #bottombar > * { flex-shrink: 1; min-width: 0; white-space: nowrap; }
  /* un nombre long ne doit pas passer par-dessus son voisin : chaque bloc
     coupe ce qui déborde plutôt que de mordre sur le suivant */
  #topbar > *, #bottombar > * { overflow: hidden; text-overflow: clip; }
  /* COUPER N'EST PAS TENIR. « SCORE 3110 » finissait tronqué en « SCORE 311 »
     par le bouton d'à côté : on lisait un score faux, ce qui est pire que pas
     de score du tout. Les chiffres rétrécissent donc avec la largeur de
     l'écran au lieu d'être rognés, et les boutons, dont le texte est fixe,
     ne rétrécissent plus du tout — c'est la seule manière que tout tienne
     sur un téléphone étroit sans que rien ne mente. */
  /* ET CE SONT EUX QUI PRENNENT LA PLACE. La vague et le score sont ce qu'on
     regarde ; MENU est ce qu'on touche une fois par partie. Ils avaient
     pourtant la même taille, et c'est le bouton qui s'étirait. Les chiffres
     occupent maintenant toute la gauche et grossissent avec l'écran ; le
     bouton se range à droite, petit, centré sur la hauteur de la bande. */
  #topbar .chiffre {
    font-size: clamp(13px, 4.4vw, 21px);
    letter-spacing: clamp(0.01em, 0.3vw, 0.06em);
    flex: 0 1 auto;
    line-height: 1.1;
  }
  #topbar #waveLbl { flex: 1 1 auto; }
  #topbar button { flex-shrink: 0; }
  @media (max-width: 420px) {
    #topbar { gap: 5px; padding-left: 7px; padding-right: 7px; }
  }
  #bottombar #bouclierLbl { flex-shrink: 2; }

  /* au-dessus du menu : sans ça les boutons du haut étaient couverts par
     l'écran de titre, donc inaccessibles au moment précis où l'on veut
     choisir son viseur */
  /* LES BANDEAUX NE PRENNENT PLUS LE DOIGT. Ce sont deux bandes pleine
     largeur : celle du bas ne porte que la jauge de vie, et c'est exactement
     là qu'un pouce se pose. Tout contact qui y atterrissait était rejeté
     comme un appui sur un bouton, et le manche ne démarrait pas — un
     glissement sur deux qui ne prenait pas. Seuls les boutons restent
     sensibles ; le reste laisse passer. */
  #topbar, #bottombar { pointer-events: none; }
  #topbar button { pointer-events: auto; }


  /* LA VIE EN HAUT, LES BOUTONS EN BAS. On lit une jauge du coin de l'oeil en
     haut de l'écran ; on touche un bouton avec le pouce en bas. Les deux
     bandes ont donc échangé leur place : #bottombar porte la vie et se colle
     en haut, #topbar porte le score et les boutons et descend. */
  #topbar {
    z-index: 40;
    bottom: 0;
    padding: 7px 10px calc(7px + env(safe-area-inset-bottom));
  }
  #bottombar {
    top: 0;
    padding: calc(7px + env(safe-area-inset-top)) 10px 7px;
    justify-content: flex-start;
  }

  .spacer { flex: 1; }
  .dim { color: var(--ph-dim); }

  #viseurBtn {
    background: none;
    border: 1px solid var(--ph-dim);
    border-radius: 5px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 11px;
    letter-spacing: 0.08em;
    padding: 3px 8px;
    flex-shrink: 0;
  }

  #sonBtn {
    background: none;
    border: 1px solid var(--ph-dim);
    border-radius: 5px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 11px;
    letter-spacing: 0.08em;
    padding: 3px 8px;
    flex-shrink: 0;
  }
  #sonBtn.off { opacity: 0.3; }

  #aideBtn {
    background: none;
    border: 1px solid var(--ph-dim);
    border-radius: 5px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 11px;
    padding: 3px 9px;
    flex-shrink: 0;
  }

  #versionBtn {
    background: none;
    border: 1px solid var(--ph-dim);
    border-radius: 5px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 11px;
    padding: 3px 8px;
    flex-shrink: 0;
  }

  #gauge {
    display: inline-block;
    width: 92px;
    height: 8px;
    border: 1px solid var(--ph-dim);
    vertical-align: middle;
  }
  #gaugeFill {
    display: block;
    height: 100%;
    width: 100%;
    background: var(--ph-line);
    transition: width 0.18s linear;
  }

  #aideLangue { display: flex; gap: 6px; justify-content: flex-end; margin: -2px 0 10px; }
  #timbreBtn, #langBtn {
    background: none;
    border: 1px solid var(--ph-dim);
    border-radius: 4px;
    color: var(--ph-dim);
    font-family: inherit;
    font-size: 10px;
    letter-spacing: 0.14em;
    padding: 5px 10px;
  }

  #coop textarea {
    width: 100%;
    background: #04070a;
    border: 1px solid var(--ph-dim);
    border-radius: 4px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 10px;
    padding: 6px;
    resize: none;
    margin: 0 0 8px;
  }
  #coop button {
    background: var(--ph-fill);
    border: 1px solid var(--ph-line);
    border-radius: 5px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 11px;
    letter-spacing: 0.14em;
    padding: 9px 14px;
    margin: 0 8px 10px 0;
  }
  #coopChoix { display: flex; gap: 8px; flex-wrap: wrap; }

  /* Le carnet : des chiffres, donc des chiffres alignés. */
  #carnet { border-top: 1px solid var(--ph-dim); margin-top: 14px; padding-top: 12px; }
  #carnet dl {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 3px 12px;
    margin: 0 0 10px;
    font-size: 11.5px;
  }
  #carnet dt { color: var(--ph-dim); }
  #carnet dd {
    margin: 0;
    color: var(--ph-text);
    font-variant-numeric: tabular-nums;
    text-align: right;
  }
  #carnet button {
    background: none;
    border: 1px solid var(--ph-dim);
    border-radius: 4px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 10px;
    letter-spacing: 0.14em;
    padding: 7px 12px;
    margin-right: 6px;
  }
  /* Une branche sans porte de sortie est une impasse : on avait choisi une fois
     pour toutes, et même en refermant le panneau on y revenait. */
  #coop button.retour {
    background: none;
    border: 0;
    color: var(--ph-dim);
    font-family: inherit;
    font-size: 10px;
    letter-spacing: 0.16em;
    padding: 0 0 8px;
    display: block;
  }
  #coopEtat { color: var(--ph-line); }
  #coopBtn {
    background: none;
    border: 1px solid var(--ph-dim);
    border-radius: 6px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 12px;
    letter-spacing: 0.18em;
    padding: 10px 22px;
    margin-top: 2px;
  }

  #viseurBtn, #sonBtn, #aideBtn, #versionBtn { display: none; }
  #vagueBtn {
    background: none;
    border: 1px solid var(--ph-line);
    border-radius: 5px;
    color: var(--ph-line);
    font-family: inherit;
    font-size: 10px;
    letter-spacing: 0.06em;
    padding: 3px 7px;
    flex-shrink: 0;
    margin-left: 4px;
  }
  /* LES BOUTONS OCCUPENT LA BANDE. Serrés à gauche, ils laissaient un trou à
     droite et le pouce visait des pastilles. Ils s'étirent maintenant pour se
     partager la place libre, à parts égales : la bande est remplie d'un bord
     à l'autre, sans qu'aucun texte ne rétrécisse. Grandir, oui ; rapetisser,
     jamais — c'est ce qui faisait lire « SCORE 311 » pour 3110. */
  #topbar .spacer { flex: 0 0 6px; }
  #topbar { justify-content: flex-start; }
  #topbar button {
    flex: 0 0 auto;            /* il ne s'étire plus : la place est aux chiffres */
    align-self: center;        /* et il se centre sur la hauteur de la bande */
    font-size: 11px;
    padding: 6px 13px;
  }
  /* LA JAUGE PREND TOUT LE HAUT. Elle faisait quatre-vingt-douze pixels collés
     au bord gauche, perdus dans une bande pleine largeur. Elle s'étire
     maintenant sur toute la colonne : on lit sa vie du coin de l'oeil sans
     la chercher. */
  #bottombar > span:first-child { flex: 1 1 auto; min-width: 0; }
  /* LE CADRE N'AVAIT PLUS DE TRAIT À DROITE. La jauge est en content-box :
     « width: 100% » donnait cent pour cent au CONTENU, et les deux pixels de
     cadre passaient par-dessus — donc deux pixels de trop, que le
     « overflow: hidden » de la bande rognait. C'est le trait de droite qui
     tombait. */
  #bottombar #gauge { display: block; width: 100%; box-sizing: border-box; }
  /* le ressort de fin de bande mangeait la moitié de la place : la jauge
     s'arrêtait au milieu de l'écran alors qu'elle doit le traverser */
  #bottombar .spacer { flex: 0 0 0; }
  #vagueBtn[hidden] { display: none; }
  /* À L'ACCUEIL, LES DEUX BOUTONS PRENNENT TOUTE LA LARGEUR. En bas le MENU,
     en haut le défi du jour : ce sont les deux seules choses à toucher sur cet
     écran, et un pouce ne vise pas une pastille de quarante pixels. Le corps
     porte la classe « accueil » tant que le panneau de titre est ouvert. */
  /* LE DÉFI DESCEND DANS LA BANDE. Il était en pastille au-dessus du titre,
     où il le gênait et où le pouce ne va pas. Il partage maintenant la bande
     du bas avec MENU, moitié-moitié : les deux seules choses à toucher sur
     cet écran sont côte à côte, en bas, et larges. */
  body.accueil #defiBtn, body.accueil #menuBtn { flex: 1 1 0; min-width: 0; }
  /* ET DÉCOLLER REMONTE AU-DESSUS DE L'AVION. Poussé tout en bas, il tombait
     sous la cellule et le texte de série se retrouvait coincé entre les deux.
     Il se pose maintenant un peu sous le texte, donc juste au-dessus du nez,
     et tout le reste descend au bas de l'écran. */
  /* DANS LE VIDE, PAS SUR L'AVION. Le texte d'accueil tenait trois lignes et
     poussait le bouton en plein milieu de la cellule. Il ne reste qu'une
     question, et le bouton se pose dans l'espace libre entre le record et le
     nez de l'appareil. */
  body.accueil #startBtn { margin-top: clamp(24px, 11vh, 120px); }
  body.accueil #objectif { margin-top: auto; }
  body.accueil #installBtn { margin-top: 0; }
  body.accueil #topbar { padding-left: 10px; padding-right: 10px; }
  /* les compteurs de partie n'ont rien à dire sur l'écran de titre : ils
     laissaient pourtant leurs gouttières, et le bouton débordait d'autant */
  body.accueil #topbar > span { display: none; }
  body.accueil #menuBtn {
    text-align: center; padding-top: 13px; padding-bottom: 13px; border-radius: 8px;
  }
  body.accueil #defiBtn {
    text-align: center; padding-top: 13px; padding-bottom: 13px;
    border-radius: 8px; font-size: 11px; letter-spacing: 0.14em;
  }
  #menuBtn {
    background: none;
    border: 1px solid var(--ph-dim);
    border-radius: 5px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 11px;
    letter-spacing: 0.12em;
    padding: 3px 10px;
    flex-shrink: 0;
  }
  #menu .ligne {
    display: block;
    width: 100%;
    margin: 0 0 6px;
    background: none;
    border: 1px solid var(--ph-dim);
    border-radius: 5px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 11px;
    letter-spacing: 0.12em;
    padding: 9px 10px;
    text-align: left;
  }
  #menu .ligne[hidden] { display: none; }
  /* LES TIROIRS. Un titre qui se lit comme un titre — plus large, plus
     espacé, sans cadre — et son contenu légèrement rentré, pour qu'on voie
     d'un coup d'œil ce qui appartient à quoi. Le chevron dit l'état, et il
     est le seul ornement. */
  #menu .groupe { margin: 0 0 6px; }
  #menu .groupe > summary {
    list-style: none;
    cursor: pointer;
    padding: 11px 10px;
    border: 0;
    border-bottom: 1px solid var(--ph-dim);
    color: var(--ph-line);
    font-size: 11px;
    letter-spacing: 0.24em;
    text-transform: uppercase;
  }
  #menu .groupe > summary::-webkit-details-marker { display: none; }
  #menu .groupe > summary::before { content: "+  "; color: var(--ph-dim); }
  #menu .groupe[open] > summary::before { content: "\2212  "; }
  #menu .groupe[open] > summary { color: var(--ph-text); border-bottom-color: var(--ph-line); }
  #menu .groupe > :not(summary) { margin-left: 10px; }
  #menu .groupe > .ligne { width: calc(100% - 10px); }
  #menu .groupe > :nth-child(2) { margin-top: 8px; }
  #menu .aide { color: var(--ph-dim); font-size: 10px; letter-spacing: 0.12em; margin: 10px 0 6px; }
  #menu .aide:first-child { margin-top: 0; }
  /* les panneaux tombent sous la bande du haut, qui porte maintenant la vie */
  #menu .puces { display: flex; flex-wrap: wrap; gap: 6px; }
  #menu .puces button {
    background: none;
    border: 1px solid var(--ph-dim);
    border-radius: 4px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 10px;
    letter-spacing: 0.08em;
    padding: 5px 8px;
  }
  #menu .puces button.actif { border-color: var(--ph-line); background: var(--ph-fill); }
  #menu .puces button.verrou { color: var(--ph-dim); }
  #menu .puces button i { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 5px; vertical-align: -1px; }
  /* LE DEFI MONTE DANS LA BANDE, DECOLLER DESCEND SOUS LE POUCE. Les deux
     etaient au milieu de l'ecran, l'un sous l'autre : le plus gros bouton du
     jeu se trouvait la ou la main n'est pas, et une proposition secondaire
     lui volait la place. Le defi devient une pastille en haut a gauche. */
  #defiBtn { margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    background: none; border: 1px solid var(--ph-dim); border-radius: 6px;
    color: var(--ph-text); font-family: inherit; font-size: 10px;
    letter-spacing: 0.12em; padding: 7px 11px; }
  #defiBtn[hidden] { display: none; }
  /* LE PACTE DU DÉFI. On ne lance plus un défi d'un doigt distrait : la
     fenêtre dit ce qu'il enlève, ce qu'il demande, ce qu'il rapporte, et
     attend un oui. */
  #pactDefi {
    position: fixed; z-index: 50;
    left: 50%; top: 50%; transform: translate(-50%, -50%);
    width: min(92vw, 420px);
    background: var(--ph-chrome); border: 1px solid var(--ph-line);
    border-radius: 10px; padding: 20px 20px 18px;
    display: flex; flex-direction: column; gap: 12px;
    box-shadow: 0 18px 60px rgba(0,0,0,0.65);
  }
  #pactDefi[hidden] { display: none; }
  #pactDefi h2 {
    margin: 0; font-size: 14px; letter-spacing: 0.16em;
    color: var(--ph-line); font-weight: 500; line-height: 1.5;
  }
  #pactDefi p { margin: 0; font-size: 13px; line-height: 1.75; color: var(--ph-text); }
  #pactPrime { color: var(--ph-dim) !important; font-size: 11.5px !important; letter-spacing: 0.08em; }
  #pactDefi .pactBtns { display: flex; gap: 9px; margin-top: 2px; }
  #pactDefi button {
    flex: 1; font-family: inherit; font-size: 12px; letter-spacing: 0.16em;
    padding: 13px 10px; border-radius: 6px; cursor: pointer;
    background: none; border: 1px solid var(--ph-dim); color: var(--ph-text);
  }
  #pactOui { border-color: var(--ph-line) !important; background: var(--ph-fill) !important; }

  #changelog, #aide, #viseurs, #coop, #install, #menu, #infos {
    /* et les panneaux par-dessus tout */
    position: fixed;
    top: calc(38px + env(safe-area-inset-top));
    right: 8px;
    left: 8px;
    max-width: 460px;
    /* CENTRÉS, PAS COLLÉS À DROITE. « margin-left: auto » seul poussait le
       panneau contre le bord droit : invisible sur un téléphone, où les huit
       pixels de marge font toute la largeur ; franchement bizarre dès que
       l'écran s'élargit. */
    margin-left: auto;
    margin-right: auto;
    max-height: 62vh;
    overflow-y: auto;
    z-index: 45;
    background: var(--ph-chrome);
    border: 1px solid var(--ph-dim);
    border-radius: 6px;
    padding: 12px 14px;
    font-size: 12px;
    line-height: 1.5;
  }
  #changelog[hidden], #aide[hidden], #viseurs[hidden], #coop[hidden],
  #install[hidden], #menu[hidden], #infos[hidden] { display: none; }
  /* LA CROIX DE FERMETURE. Elle flotte dans le coin du panneau, au-dessus du
     texte, et le titre lui laisse la place à droite. */
  #infos #infosX {
    position: sticky; top: 0; float: right; margin: -4px -4px 0 8px;
    background: none; border: 1px solid var(--ph-dim); border-radius: 5px;
    color: var(--ph-text); font-family: inherit; font-size: 14px; line-height: 1;
    padding: 5px 9px; cursor: pointer; z-index: 2;
  }
  #infos h3 { margin: 0 0 8px; font-size: 12px; letter-spacing: 0.14em; font-weight: 500; color: var(--ph-line); }
  #infos p { margin: 0 0 8px; color: var(--ph-text); }
  #infos .ligne, #menu .ligne.opt { display: block; width: 100%; margin: 0 0 6px; background: none; border: 1px solid var(--ph-dim); border-radius: 5px; color: var(--ph-text); font-family: inherit; font-size: 11px; letter-spacing: 0.1em; padding: 9px 10px; text-align: left; }
  #infos .ligne.actif { border-color: var(--ph-line); background: var(--ph-fill); }
  #infos input { width: 100%; box-sizing: border-box; background: none; border: 1px solid var(--ph-dim); border-radius: 5px; color: var(--ph-text); font-family: inherit; font-size: 13px; letter-spacing: 0.2em; padding: 9px 10px; text-transform: uppercase; }

  /* INSTALLATION. Trois pas numérotés, parce qu'aucun navigateur ne sait
     expliquer ça et qu'on ne peut pas le faire à la place du joueur sur iOS :
     Apple n'expose aucune interface pour le proposer. On décrit donc le geste,
     à l'endroit et au moment où il est utile. */
  #install ol { margin: 0 0 12px; padding: 0; list-style: none; counter-reset: pas; }
  #install ol li {
    display: flex; gap: 11px; align-items: flex-start;
    margin: 0 0 11px; counter-increment: pas; line-height: 1.55;
  }
  #install ol li::before {
    content: counter(pas);
    flex: 0 0 auto;
    width: 22px; height: 22px; border-radius: 50%;
    background: var(--ph-fill); border: 1px solid var(--ph-line);
    color: var(--ph-line); font-size: 11px;
    display: flex; align-items: center; justify-content: center;
  }
  #install .fin { color: var(--ph-dim); font-size: 11px; line-height: 1.6; margin: 0; }
  #install .fin b { color: var(--ph-text); font-weight: 500; }

  /* La pastille du haut : elle ne se montre qu'après une première partie, et
     une seule fois — un rappel n'est pas un harcèlement. */
  #installPastille {
    position: fixed;
    top: calc(44px + env(safe-area-inset-top));
    left: 50%;
    transform: translateX(-50%);
    z-index: 39;
    background: rgba(7, 24, 18, 0.94);
    border: 1px solid var(--ph-dim);
    border-radius: 20px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 10px;
    letter-spacing: 0.16em;
    padding: 7px 15px;
  }
  #installPastille[hidden] { display: none; }

  /* La bascule de version : le seul moment où le hors-ligne peut tromper. */
  #majPastille {
    position: fixed;
    bottom: calc(52px + env(safe-area-inset-bottom));
    left: 50%;
    transform: translateX(-50%);
    z-index: 44;
    background: var(--ph-line);
    border: 1px solid var(--ph-line);
    border-radius: 20px;
    color: #04070a;
    font-family: inherit;
    font-size: 10px;
    letter-spacing: 0.16em;
    padding: 9px 18px;
  }
  #majPastille[hidden] { display: none; }
  #coopHote[hidden], #coopInvite[hidden], #coopEtape2[hidden] { display: none; }
  #viseurs .grille {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 8px;
  }
  #viseurs .item {
    border: 1px solid var(--ph-dim);
    border-radius: 6px;
    padding: 6px 4px 5px;
    text-align: center;
  }
  #viseurs .item.actif { border-color: var(--ph-line); background: var(--ph-fill); }
  #viseurs .item canvas { display: block; margin: 0 auto 3px; }
  #viseurs .item .n { font-size: 9px; letter-spacing: 0.1em; color: var(--ph-text); }
  #viseurs .item.verrou .n { color: var(--ph-dim); }
  #viseurs .item button {
    margin-top: 4px;
    width: 100%;
    background: none;
    border: 1px solid var(--ph-dim);
    border-radius: 4px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 9px;
    letter-spacing: 0.06em;
    padding: 3px 0;
  }
  #coop .aide, #viseurs .aide { color: var(--ph-dim); font-size: 11px; margin: 0 0 10px; line-height: 1.6; }
  #changelog div, #aide p { margin: 0 0 8px; }
  /* le numéro de version est un titre, la liste est en dessous */
  #changelog .bloc { margin: 0 0 16px; }
  #changelog .bloc b { display: block; margin-bottom: 5px; letter-spacing: 0.08em; }
  #changelog .bloc ul { margin: 0; padding: 0 0 0 15px; list-style: none; }
  #changelog .bloc li { margin: 0 0 5px; position: relative; }
  #changelog .bloc li::before {
    content: '—'; position: absolute; left: -15px; opacity: 0.45;
  }
  #changelog .bloc li:last-child { margin-bottom: 0; }
  #changelog .merci { color: var(--ph-line); }
  #changelog div:last-child, #aide p:last-child { margin-bottom: 0; }
  #changelog b, #aide b { color: var(--ph-line); }
  #aide h2 {
    margin: 16px 0 7px;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.22em;
    color: var(--ph-line);
  }
  #aide h2:first-child { margin-top: 0; }
  #aide .eq {
    margin: 9px 0;
    text-align: center;
    color: var(--ph-line);
    letter-spacing: 0.06em;
  }
  #aide .src { color: var(--ph-dim); font-size: 11px; }

  #overlay {
    position: fixed;
    /* Pas « inset: 0 ». Sur iOS un élément fixe se cale sur la GRANDE fenêtre,
       celle qu'on aurait si la barre du navigateur se repliait — pas sur ce
       qu'on voit. Le menu était donc dessiné pour une hauteur qui n'existait
       pas, et sa dernière ligne se retrouvait sous la barre d'outils de
       Safari. dvh suit la fenêtre réellement visible, seconde par seconde. */
    top: 0; left: 0; right: 0;
    height: 100vh; height: 100dvh;
    box-sizing: border-box;
    z-index: 30;
    /* dégradé plutôt qu'un voile plein : le texte reste lisible en haut,
       et l'avion posé au sol se voit en bas */
    background: linear-gradient(to bottom,
      rgba(4, 7, 10, 0.96) 0%,
      rgba(4, 7, 10, 0.9) 42%,
      rgba(4, 7, 10, 0.45) 62%,
      rgba(4, 7, 10, 0.1) 80%);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    /* Sur un téléphone en 5G avec la barre du navigateur et la barre de vie,
       les cinq lignes du menu de mort ne tiennent pas dans ce qui reste :
       le dernier bouton passait sous la jauge. Les espaces suivent donc la
       hauteur disponible, et ce qui déborde encore se fait défiler. */
    gap: clamp(9px, 2vh, 18px);
    /* le bas réserve la hauteur de la barre de vie, qui passe par-dessus */
    padding: clamp(26px, 11vh, 150px) 24px
             calc(58px + env(safe-area-inset-bottom, 0px));
    text-align: center;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
  #overlay > * { flex: 0 0 auto; }
  #overlay[hidden] { display: none; }

  #overlay h1 {
    margin: 0;
    font-size: clamp(1.5rem, 8vw, 2.6rem);
    font-weight: 500;
    letter-spacing: 0.28em;
    color: var(--ph-line);
    text-shadow: 0 0 18px var(--ph-dim);
  }
  #overlayText { margin: 0; font-size: 13px; line-height: 1.7; color: var(--ph-text); max-width: 30em; }
  #overlayScore { margin: 0; font-size: 13px; color: var(--ph-dim); letter-spacing: 0.15em; line-height: 1.9; }
  #overlayScore b { color: var(--ph-line); font-weight: 500; }
  #gaugeFill.bonus { background: #ffd166; box-shadow: 0 0 8px #ffd166; }
  /* LE REPÈRE DU PLAFOND. Un trait vertical sur la jauge : à sa gauche, ce
     que les mécaniciens savent rendre ; à sa droite, ce qu'il faut aller
     chercher dans les trous. */
  #jaugeCap {
    position: absolute; top: -1px; bottom: -1px; width: 2px;
    margin-left: -1px; background: var(--ph-text); opacity: 0.55;
    pointer-events: none;
  }
  #gauge { position: relative; }
  /* LA JAUGE VIENT DE SE REMPLIR. Deux battements blancs, et c'est tout :
     on a payé la réparation, on a le droit de la voir se terminer. */
  #gaugeFill.pleine { background: #f2fff6; box-shadow: 0 0 16px #f2fff6; animation: jaugePleine 0.4s steps(1) 4; }
  @keyframes jaugePleine { 0%, 50% { opacity: 1; } 50.01%, 100% { opacity: 0.55; } }
  #objectif { margin: 0; font-size: 12px; color: var(--ph-dim); letter-spacing: 0.12em; line-height: 1.8; max-width: 30em; }
  #objectif b { color: var(--ph-line); font-weight: 500; }
  #objectif[hidden] { display: none; }
  #partageBtn[hidden], #installBtn[hidden] { display: none; }

  #videoBtn, #installBtn, #partageBtn {
    background: none;
    border: 1px solid var(--ph-dim);
    border-radius: 6px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 11px;
    letter-spacing: 0.14em;
    padding: 10px 18px;
    max-width: 90vw;
  }
  #videoBtn[disabled] { opacity: 0.35; }

  /* Le bouton de remise en l'air, posé bas et large : on y va au pouce, sans
     regarder, pendant qu'on se fait tirer dessus au sol. */
  #redecoBtn {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    bottom: calc(52px + env(safe-area-inset-bottom));
    z-index: 42;
    background: var(--ph-fill);
    border: 1px solid var(--ph-line);
    border-radius: 6px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 13px;
    letter-spacing: 0.2em;
    padding: 13px 30px;
  }
  #redecoBtn[hidden] { display: none; }
  /* LE BOUTON D'ACTION. Même place que REDÉCOLLER mais juste au-dessus : on
     n'a jamais les deux à la fois, sauf debout à côté de l'appareil, et alors
     ils se lisent l'un sous l'autre sans se marcher dessus. */
  #actionBtn {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    bottom: calc(112px + env(safe-area-inset-bottom));
    z-index: 42;
    background: var(--ph-fill);
    border: 1px solid var(--ph-line);
    border-radius: 6px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 13px;
    letter-spacing: 0.2em;
    padding: 13px 30px;
  }
  #actionBtn[hidden] { display: none; }
  /* LA LETTRE. Du papier, pas un panneau de jeu : elle est plus étroite que
     l'écran, elle respire, et son texte est le seul du jeu qui ne soit pas en
     capitales — parce que personne n'écrit une lettre en capitales. */
  #lettre {
    position: fixed; inset: 0; z-index: 70;
    /* OPAQUE, PAS PRESQUE. À 0,94 on lisait encore les boutons du jeu au
       travers du papier : READ, TAKE OFF AGAIN, la barre du bas. Une lettre
       qu'on ouvre remplace l'écran, elle ne le recouvre pas à moitié. */
    background: var(--ph-bg);
    display: flex; align-items: center; justify-content: center;
    /* LE CADRE NE TOUCHE JAMAIS LE BORD DU HAUT. Vingt-quatre pixels fixes
       depuis `inset: 0` : sur un téléphone dont la barre d'état et l'île
       mangent le haut, le trait du cadre passait dessous et la première ligne
       avec. On part de la zone sûre, et on descend encore de vingt pixels. */
    padding: max(28px, calc(env(safe-area-inset-top) + 20px)) 20px
             max(28px, calc(env(safe-area-inset-bottom) + 20px));
  }
  #lettre[hidden] { display: none; }
  body.lit #topbar, body.lit #bottombar, body.lit #hud { visibility: hidden; }
  #lettre .feuille {
    /* SANS CECI, « max-height: 100% » PLAFONNE LE CONTENU ET PAS LE CADRE.
       La feuille est en content-box : les vingt-six pixels de marge du haut,
       les dix-huit du bas et les deux traits du cadre s'ajoutaient PAR-DESSUS
       les sept cent quatre pixels autorisés, et le cadre en faisait sept cent
       cinquante — vingt-trois de trop en haut, vingt-trois en bas. Mesuré :
       le trait du haut tombait à cinq pixels du bord de l'écran au lieu de
       vingt-huit. C'est tout le défaut. */
    box-sizing: border-box;
    max-width: 30rem; width: 100%;
    border: 1px solid var(--ph-dim);
    padding: 26px 22px 18px;
    max-height: 100%; overflow-y: auto;
    touch-action: pan-y;               /* elle défile au doigt */
    -webkit-overflow-scrolling: touch;
  }
  /* CE N'EST PAS ELLE QUI PARLE. Ce qui est écrit dans les crochets décrit ce
     qui est arrivé au papier, pas ce qu'elle a écrit dessus : couleur éteinte,
     pour qu'on ne le lise pas comme une phrase d'Émilie. */
  #lettre .pluie { color: var(--ph-dim); }
  #lettre .signe[hidden], #lettre .nom[hidden] { display: none; }
  /* « Mon amour, » : la même écriture que le reste, à gauche, et un blanc
     dessous — on n'écrit pas une lettre sans commencer par appeler quelqu'un */
  #lettre .debut {
    margin: 0 0 18px; color: var(--ph-text);
    font-size: 15px; line-height: 1.85; text-transform: none;
    letter-spacing: 0.02em;
  }
  #lettre .ecrit {
    margin: 0 0 18px; color: var(--ph-text);
    font-size: 15px; line-height: 1.85; text-transform: none;
    letter-spacing: 0.02em; white-space: pre-line;
  }
  /* LA MÊME ÉCRITURE, JUSQU'AU NOM. La formule était à quinze pixels et le nom
     à dix-sept, dans une autre couleur : trois écritures dans une lettre écrite
     à la main par une seule personne. Tout est maintenant du même corps, de la
     même couleur et de la même graisse que le texte — seul l'alignement change,
     parce qu'une signature se met à droite. */
  #lettre .signe, #lettre .nom {
    margin: 0; color: var(--ph-text);
    font-size: 15px; line-height: 1.85; text-align: right; text-transform: none;
    letter-spacing: 0.02em;
  }
  #lettre .nom { margin-bottom: 24px; }
  #lettre button {
    display: block; margin: 0 auto;
    background: transparent; border: 1px solid var(--ph-dim); border-radius: 4px;
    color: var(--ph-text); font-family: inherit; font-size: 12px;
    letter-spacing: 0.22em; padding: 10px 26px;
  }

  /* LA CARTE DU MUR. Même papier que la lettre — c'est la même maison, la même
     main — mais elle porte un dessin plutôt qu'un texte, et elle se traduit :
     ce n'est pas un mot pour quelqu'un, c'est une indication pour qui vient. */
  #carteMur, #guitare {
    position: fixed; inset: 0; z-index: 70;
    background: var(--ph-bg);
    display: flex; align-items: center; justify-content: center;
    /* même zone sûre que la lettre : c'est le même papier, et il ne doit pas
       plus qu'elle passer sous la barre d'état */
    padding: max(28px, calc(env(safe-area-inset-top) + 20px)) 20px
             max(28px, calc(env(safe-area-inset-bottom) + 20px));
  }
  #carteMur[hidden], #guitare[hidden] { display: none; }
  /* « display: block » sur les boutons l'emportait sur l'attribut hidden :
     « LA REGARDER » restait affiché après qu'on avait regardé. */
  #guitare button[hidden] { display: none; }
  #guitare button { margin-bottom: 10px; }
  #guitare button:last-child { margin-bottom: 0; }
  #carteMur .papier, #guitare .papier {
    box-sizing: border-box;      /* même raison que la feuille de la lettre */
    max-width: 30rem; width: 100%;
    border: 1px solid var(--ph-dim);
    padding: 22px 20px 16px;
    max-height: 100%; overflow-y: auto;
    touch-action: pan-y;
    -webkit-overflow-scrolling: touch;
  }
  #carteMur .titre, #guitare .titre {
    margin: 0 0 16px; color: var(--ph-text);
    font-size: 12px; letter-spacing: 0.22em; text-align: center;
  }
  #carteMur svg { display: block; width: 100%; height: auto; color: var(--ph-text); }
  #carteMur .note, #guitare .note {
    margin: 16px 0 20px; color: var(--ph-text);
    font-size: 14px; line-height: 1.8; text-transform: none; letter-spacing: 0.02em;
  }
  #carteMur button, #guitare button {
    display: block; margin: 0 auto;
    background: transparent; border: 1px solid var(--ph-dim); border-radius: 4px;
    color: var(--ph-text); font-family: inherit; font-size: 12px;
    letter-spacing: 0.22em; padding: 10px 26px;
  }

  /* POSER : même place que REDÉCOLLER, un cran plus haut. Il n'apparaît que
     quand la piste est devant et lisible, et il bat quand on est sur le plan —
     c'est le seul moment où appuyer sert à quelque chose. */
  #poserBtn {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    bottom: calc(52px + env(safe-area-inset-bottom));
    z-index: 41;
    background: rgba(4, 7, 10, 0.55);
    border: 1px solid var(--ph-dim);
    border-radius: 6px;
    color: var(--ph-dim);
    font-family: inherit;
    font-size: 13px;
    letter-spacing: 0.2em;
    padding: 13px 30px;
  }
  #poserBtn[hidden] { display: none; }
  #poserBtn { background-image: linear-gradient(90deg, var(--ph-fill) 0, var(--ph-fill) calc(var(--charge, 0) * 100%), transparent calc(var(--charge, 0) * 100%)); }
  #poserBtn.pret {
    color: #04070a;
    background: var(--ph-line);
    border-color: var(--ph-line);
    animation: battementPose 0.9s ease-in-out infinite;
  }
  /* Engagé, il doit se lire autrement que prêt : plein et battant, c'est une
     invitation ; creux et vif, c'est un état. Les deux se ressemblaient trait
     pour trait et l'on ne savait plus si le pilote automatique tenait le
     manche ou non. */
  #poserBtn.actif {
    color: var(--ph-line);
    background: rgba(70, 255, 160, 0.12);
    border-color: var(--ph-line);
    animation: none;
  }
  @keyframes battementPose {
    0%, 100% { box-shadow: 0 0 0 0 rgba(70, 255, 160, 0.5); }
    55%       { box-shadow: 0 0 0 13px rgba(70, 255, 160, 0); }
  }
  @media (prefers-reduced-motion: reduce) { #poserBtn.pret { animation: none; } }

  #expliqueBtn {
    background: none;
    border: 1px solid var(--ph-dim);
    border-radius: 6px;
    color: var(--ph-dim);
    font-family: inherit;
    font-size: 11px;
    letter-spacing: 0.16em;
    padding: 9px 18px;
    margin-top: 4px;
  }
  #expliqueBtn[hidden], #plusJamais[hidden] { display: none; }
  #plusJamais {
    display: flex;
    align-items: center;
    gap: 7px;
    color: var(--ph-dim);
    font-size: 11px;
    letter-spacing: 0.06em;
    margin-top: -2px;
  }
  #plusJamais input { accent-color: var(--ph-line); margin: 0; }

  #startBtn {
    /* pousse le bouton en bas de la colonne : c'est la que le pouce arrive */
    margin-top: auto;
    background: var(--ph-fill);
    border: 1px solid var(--ph-line);
    border-radius: 6px;
    color: var(--ph-text);
    font-family: inherit;
    font-size: 15px;
    letter-spacing: 0.24em;
    padding: 16px 26px;
    width: min(92vw, 460px);
  }
  #coopBtn { display: none; }
  /* LE RAPPORT DE VOL. Dix-huit lignes de chiffres débordaient de l'écran de
     fin et passaient sous la bande du bas. Elles vivent maintenant dans leur
     propre panneau, qui défile, et l'écran de fin ne garde que ce qu'on lit
     vraiment tout de suite : le score, le record, et qui vous a eu. */
  #statsBtn {
    background: none; border: 1px solid var(--ph-dim); border-radius: 6px;
    color: var(--ph-text); font-family: inherit; font-size: 11px;
    letter-spacing: 0.16em; padding: 11px 18px;
  }
  #statsBtn[hidden] { display: none; }

  /* L'ÉCRAN DE MORT TIENT SANS DÉFILER. Mesuré : à 320×568 il débordait de
     156 px (« explications », « rapport de vol » et la case sortaient), à
     375×667 de 89 px. Sur un écran bas, tout se resserre : marges, titre,
     boutons — sans rien retirer. Demandé : tout à l'écran, sans lisser. */
  @media (max-height: 720px) {
    #overlay { gap: 6px; padding: clamp(12px, 3vh, 34px) 18px calc(50px + env(safe-area-inset-bottom, 0px)); }
    #overlay h1 { font-size: 1.25rem; letter-spacing: 0.22em; }
    #overlayText { font-size: 12px; line-height: 1.4; }
    #overlayScore { font-size: 12px; line-height: 1.45; }
    #videoBtn, #installBtn, #partageBtn, #expliqueBtn, #statsBtn { padding: 7px 14px; margin-top: 0; }
    #startBtn { padding: 11px 20px; font-size: 14px; }
    #plusJamais { margin-top: 0; }
  }
  #stats { margin: 0; font-size: 12px; color: var(--ph-dim); letter-spacing: 0.06em; line-height: 1.9; text-align: left; }
  #stats b { color: var(--ph-text); font-weight: 500; }
  #stats[hidden] { display: none; }
  /* à l'accueil et à la fin, ni vie ni chiffres : ils n'apparaissent qu'en vol */
  body.accueil #bottombar, body.accueil #topbar .chiffre { visibility: hidden; }
  /* la barre de vie, désormais en haut, laisse la place au titre */

  /* -------------------------------------------------------------------------
     UNE COLONNE, ET PAS TOUTE LA LARGEUR.
 
     Tout est réglé pour un téléphone tenu debout, quatre cent trente pixels de
     large : les deux bandes s'étirent d'un bord à l'autre et leurs boutons se
     rangent aux extrémités. C'est juste là, et faux partout ailleurs. Mesuré
     sur un pliant déplié, 2208 pixels de large : le bouton le plus éloigné se
     retrouvait à 2033 pixels du bord opposé — hors d'atteinte d'un pouce, et
     hors du regard.
 
     Le fond des bandes garde toute la largeur, parce qu'une bande coupée au
     milieu d'un écran ne ressemble à rien. Ce qu'elles CONTIENNENT tient dans
     une colonne centrée. C'est ce que fait n'importe quelle interface qui
     accepte de changer de forme, et ça ne coûte que deux marges.
     ---------------------------------------------------------------------- */
  /* LA LISTE EST LONGUE PARCE QUE LA SPÉCIFICITÉ COMPTE. `body.accueil #topbar`
     vaut (1,1,0) et l'emportait sur (1,0,0) : la colonne s'appliquait partout
     SAUF sur l'écran de titre, c'est-à-dire précisément là où l'on regarde.
     On reprend donc le même poids. */
  #topbar, #bottombar, #overlay,
  body.accueil #topbar, body.accueil #bottombar, body.accueil #overlay {
    /* LA VALEUR EST ÉCRITE EN TOUTES LETTRES. Avec `var(--colonne)` à
       l'intérieur du `max()`, Chromium laisse tomber la déclaration et
       retombe sur les dix pixels du raccourci — mesuré : 10 px depuis la
       feuille, 824 px avec la même expression posée à la main sur l'élément.
       Une variable qui ne se substitue pas est pire qu'une valeur en dur. */
    padding-left: max(10px, calc((100% - 560px) / 2));
    padding-right: max(10px, calc((100% - 560px) / 2));
  }
  /* les panneaux, l'écran de titre et les bandes partagent la même colonne */
  #overlay > *, #topbar > *, #bottombar > * { max-width: 100%; }

  /* -------------------------------------------------------------------------
     LA CHARNIÈRE.
 
     Un pliant posé en tente, ou tenu ouvert comme un livre, ne présente pas
     une surface : il en présente deux, séparées par un pli où rien ne doit se
     trouver. Le navigateur les décrit par `viewport-segment` — la proportion
     seule ne suffit pas à les deviner.
 
     Ces deux règles ne sont PAS vérifiées : aucun navigateur de ce banc
     n'expose de segments, et je n'ai pas de pliant sous la main. Elles sont
     écrites d'après la spécification, elles n'ont aucun effet sur un écran
     ordinaire — la requête ne s'applique jamais — et elles attendent d'être
     démenties par un vrai appareil.
     ---------------------------------------------------------------------- */

  /* OUVERT COMME UN LIVRE : le pli est vertical, au milieu. On range tout ce
     qui se lit dans le segment de gauche plutôt qu'à cheval sur la pliure. */
  @media (horizontal-viewport-segments: 2) {
    #changelog, #aide, #viseurs, #coop, #install, #menu, #infos,
    #lettre .feuille, #carteMur .papier, #guitare .papier {
      max-width: min(460px, env(viewport-segment-width 0 0, 460px));
      margin-left: 0;
      margin-right: auto;
    }
    #topbar, #bottombar, #overlay,
    body.accueil #topbar, body.accueil #bottombar, body.accueil #overlay {
      padding-left: 10px;
      padding-right: max(10px, calc(100% - env(viewport-segment-right 0 0, 100%) + 10px));
    }
  }

  /* POSÉ EN TENTE : le pli est horizontal. Le segment du bas devient le
     pupitre — c'est là que le pouce arrive — et le haut reste l'image. */
  @media (vertical-viewport-segments: 2) {
    #lettre .feuille, #carteMur .papier, #guitare .papier {
      max-height: env(viewport-segment-height 0 1, 62vh);
      align-self: flex-end;
    }
    #redecoBtn, #actionBtn {
      bottom: calc(env(viewport-segment-top 0 1, 0px) + 18px);
    }
  }
