/* LE HUB — l'accueil communautaire, avant le bois.

   Onzieme feuille, chargee apres `brief.css`. Elle n'invente AUCUNE couleur
   ni AUCUNE police : tout vient des variables de `base.css` (le verre vert,
   l'or grave, le bois, le parchemin, Nunito Sans et Caveat). Ce qu'elle
   ajoute est de la menuiserie — la planche brune cerclee de beige des
   articles, les rangees de l'accueil, la page d'un cartographe.

   La barre du bas n'est PAS ici : c'est `.tabbar` / `.tab` de `base.css`,
   celle du joueur, telle quelle. Le hub s'y range, elle ne se refait pas
   pour lui. */

/* ------------------------------------------------------------- la coque */

/* Le titre du hub : la planche « large » (le mot coiffe de la tete), a la
   taille de l'accueil du jeu — sans ce calage elle sort du cadre. */
#screen-hub .home-hero { --home-title-h: min(17vw, 66px); margin: 6px 0 16px; }
/* DE L'AIR AU-DESSUS DU LOGO. Le titre commencait a dix-huit pixels du bord
   utile : sur un telephone, les icones du haut (heure, reseau, batterie) se
   posent juste dessus, et le bois du logo semblait les toucher. */
.hub-scroll { padding-top: calc(var(--safe-top) + 34px); }
#screen-hub .home-logo { height: var(--home-title-h); width: auto; }

/* LES DEUX COINS DU HAUT (2.70) : la roue crantee et le visage du compte,
   poses sur le decor de part et d'autre du logo. Le hero est deja cache sur
   les sous-pages, ils partent avec lui. `pointer-events: none` sur la
   ligne : entre les deux boutons, c'est le logo qu'on touche (il est la
   porte de l'accueil).

   LA MEME MARGE EN HAUT QUE SUR LES COTES (2.70.1). Le defileur laisse
   16 px de chaque cote ; le hero, lui, commence a 48 px sous la zone sure
   (34 de defileur + 14 de marge), et les coins poses a son bord semblaient
   tasses contre le logo. Ils remontent donc de 32 px : 16 px sous la zone
   sure, comme sur les cotes — et ils ne mordent plus sur le bois du titre.

   LE TITRE DESCEND DE 30 PX (2.70.3). Les coins remontes touchaient encore
   le bois du logo, surtout le visage (62 px de haut) : le hero prend 30 px
   de marge en plus (14 → 44), et les coins reculent d'autant (-32 → -62)
   pour rester a 16 px sous la zone sure. Tout le reste de l'accueil suit
   le titre.

   UNE CUVETTE SOMBRE, PAS UNE VITRE. Le verre vert laissait passer la
   foret, et l'or de la roue se perdait dans le feuillage : le fond est
   maintenant une nuit presque pleine, creusee (ombre interieure) sous un
   liseret d'or — une empreinte dans l'ecorce, ou le picto se lit. */
#screen-hub .home-hero { position: relative; }
.hub-haut {
  position: absolute; top: -24px; left: 0; right: 0; z-index: 2;
  display: flex; justify-content: flex-end; align-items: flex-start;
  pointer-events: none;
}
.hub-coin {
  pointer-events: auto; cursor: pointer;
  width: 52px; height: 52px; border-radius: 50%; padding: 0; position: relative;
  display: grid; place-items: center; color: var(--gold);
  background: radial-gradient(circle at 50% 38%, rgba(26, 44, 32, 0.92), rgba(7, 16, 12, 0.94) 72%);
  border: 1.5px solid rgba(201, 164, 104, 0.55);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.45),
              inset 0 3px 8px rgba(0, 0, 0, 0.65),
              inset 0 -1px 0 rgba(255, 255, 255, 0.06);
  transition: transform 0.12s ease;
}
.hub-coin:active { transform: scale(0.92); }
.hub-coin:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.hub-coin > svg { width: 26px; height: 26px; filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.6)); }
/* Le visage, moitie plus grand que la roue : c'est une tete, on la
   reconnait de loin ; la roue n'est qu'un outil. Les deux s'alignent par
   le haut, a la meme marge. */
.hub-coin-face { width: 46px; height: 46px; }
.hub-coin-face > svg { width: 24px; height: 24px; color: var(--parchment); }
.hub-coin-face img {
  width: 100%; height: 100%; border-radius: 50%; object-fit: cover; display: block;
}
.hub-coin-face.connecte { border-color: var(--gold); padding: 3px; }
.hub-coin-face.connecte img { box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.4); }
/* Le point vert du connecte, le « + » de celui qui ne l'est pas : le meme
   coin, bas a droite, pour que l'oeil sache ou lire l'etat. */
.hub-coin-point, .hub-coin-plus {
  position: absolute; right: 1px; bottom: 1px;
  width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid var(--ink-800); box-sizing: content-box;
}
.hub-coin-point { background: var(--moss); }
.hub-coin-plus {
  background: var(--gold); color: var(--ink-900);
  font: 800 13px/14px var(--display); text-align: center; font-style: normal;
}

/* La planche du hub — brun de bois, cadre beige plein — a demenage dans
   `base.css` (`.bois`) : les reglages la reprennent, et deux copies auraient
   fini par diverger. */

.hub-rub {
  display: flex; justify-content: space-between; align-items: baseline;
  margin: 16px 2px 8px;
  font-family: var(--display); font-weight: 800; font-size: 1.12rem;
  color: var(--parchment);
}
.hub-rub .link-btn { font-size: 0.72rem; }

/* LE « + » DU TITRE : la porte de creation, la ou l'on regarde ce qu'on a
   deja fait. Il prend le bois des boutons — jamais un brun ecrit ici, il vit
   dans `--bois-grad` (base.css) et chaque theme le repeint. */
.hub-plus {
  flex: none; align-self: center;
  width: 30px; height: 30px; border-radius: 50%;
  border: 1px solid var(--gold-deep); background: var(--bois-grad);
  color: var(--gold); font-size: 1.15rem; line-height: 1;
  display: grid; place-items: center; cursor: pointer;
}
.hub-plus:active { transform: scale(0.94); }

/* ------------------------------------------------------------ a la une */

/* LE CARROUSEL SE GLISSE AU POUCE. `pan-y` laisse le defilement vertical au
   navigateur et nous rend l'horizontal : sans cela, le geste part en
   defilement de page et le carrousel a l'air fige. La carte suit le doigt
   (transform pose en JS), puis la suivante entre du bon cote — une image qui
   se remplace sans bouger ne dit pas qu'on a avance. */
.hub-une { touch-action: pan-y; }
.hub-une.entre-d { animation: hub-entre-d 0.24s ease-out; }
.hub-une.entre-g { animation: hub-entre-g 0.24s ease-out; }
@keyframes hub-entre-d {
  from { opacity: 0.35; transform: translateX(26%); }
  to { opacity: 1; transform: none; }
}
@keyframes hub-entre-g {
  from { opacity: 0.35; transform: translateX(-26%); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .hub-une.entre-d, .hub-une.entre-g { animation: none; }
}

.hub-tag {
  display: inline-block; margin-bottom: 6px; border-radius: 4px;
  background: var(--moss-deep); color: #eaffe6;
  font-size: 0.56rem; font-weight: 800; letter-spacing: 0.08em;
  /* `letter-spacing` pose son espace APRES la derniere lettre : dans une boite
     ajustee au texte, le E final se collait au bord puis se faisait rogner par
     l'arrondi. Le retrait droit reprend cet espace fantome (8 + 0.08em), et le
     mot redevient optiquement centre. */
  padding: 4px calc(8px + 0.08em) 4px 8px;
  white-space: nowrap;
}

/* Les points du carrousel : les memes que la pile de pages du livre. */
.hub-dots { display: flex; gap: 6px; justify-content: center; padding: 8px 0 0; }
.hub-dots i { width: 6px; height: 6px; border-radius: 50%; background: rgba(238, 241, 230, 0.25); }
.hub-dots i.on { width: 16px; border-radius: 3px; background: var(--moss); }

/* La pastille d'un article : le sceau appose sur la fiche. Le meme banc que
   celui d'une balise (`assets/badges/`). */
.hub-sceau {
  position: absolute; top: 8px; right: 8px; z-index: 2;
  width: 44px; height: 44px; object-fit: contain;
  filter: drop-shadow(0 3px 7px rgba(0, 0, 0, 0.7));
}

/* La meta d'un parcours : etoile, chrono, sentier. Les silhouettes de
   `assets/pictos/`, celles de la carte — pas un jeu d'icones de plus. */
.hub-meta { display: flex; gap: 9px; list-style: none; margin: 0; padding: 0;
  font-size: 0.68rem; color: var(--parch-dim); }
.hub-meta li { display: inline-flex; align-items: center; white-space: nowrap; }
.hub-ic {
  width: 12px; height: 12px; object-fit: contain; margin-right: 4px; flex: none;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.85));
}
.hub-meta .facile { color: var(--moss); }
.hub-meta .moyen { color: var(--ember); }
.hub-meta .dur { color: var(--rot); }

/* ------------------------------------------------------- les cartographes */

.hub-face {
  width: 62px; height: 62px; border-radius: 50%; object-fit: cover;
  border: 2px solid var(--wood-1); box-shadow: var(--shadow-1); display: block; margin: 0 auto;
}
.hub-face.grande { width: 92px; height: 92px; border-width: 3px; }
.hub-face.mini { width: 24px; height: 24px; border-width: 1px; }

/* ------------------------------------------------ une ligne de parcours */

.hub-ligne {
  position: relative; display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px; margin-bottom: 8px; cursor: pointer; text-align: left;
  background: var(--bois-grad);
  border: 3px solid var(--wood-1); border-radius: var(--radius);
  box-shadow: var(--shadow-1), inset 0 1px 0 rgba(255, 255, 255, 0.07);
}
/* LA PLACE DE LA BANDE DU MODE (`.a-mode::after`, css/modes.css) : quatre
   pixels a gauche, pris sur le padding de l'item et non sur son contenu. */
.hub-ligne.a-mode { padding-left: 12px; }
.hub-mini { position: relative; width: 74px; height: 60px; flex: none; }
.hub-mini img { width: 100%; height: 100%; object-fit: cover; border-radius: 10px; display: block; }
.hub-mini .hub-sceau { width: 26px; height: 26px; top: 4px; right: 4px; }
.hub-ligne-txt { flex: 1; min-width: 0; }
.hub-ligne-txt b { display: block; margin-bottom: 4px; font-family: var(--display);
  font-size: 0.86rem; line-height: 1.15; color: var(--gold); }
/* DEPUIS QUAND ON A QUITTE, sur SA ligne : sous le nom du parcours et non a
   cote. Un « Sentier des Trolls noirs de Comboire » et « quitte il y a 12
   jours » cote a cote repliaient l'un dans l'autre sur un iPhone etroit, et
   l'on ne lisait plus ni le parcours ni le temps. Ce bloc etant le seul a
   porter deux lignes de legende, le passage a la ligne se demande ici et non
   sur `.hub-ligne-txt i`, qui sert partout ailleurs. */
.hub-ligne-txt .hub-quand { display: block; margin-top: 2px; opacity: 0.85; }
/* LA RANGEE D'ETIQUETTES : « NOUVEAU », « A LA UNE », la pastille du mode.
   Une rangee et non trois marges empilees — sur un ecran etroit, les deux
   passaient a la ligne l'une sous l'autre et la vignette s'etirait. */
.hub-tags {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-bottom: 4px;
}
.hub-tags:empty { display: none; }
.hub-tags .hub-tag, .hub-tags .hub-neuf { margin-bottom: 0; }
/* Sur la carte a la une, le texte est pose sur la photo : la pastille a
   besoin d'un fond a elle pour rester lisible sur un ciel clair. */

/* -------------------------------------------------- l'espace du cartographe

   Un brouillon ou un lieu ferme n'ouvre rien (`espaceLieuPage`, js/hub.js) :
   la ligne reste un `<div>` et non un `<button data-route>`, et le curseur
   le dit — sans quoi elle promettrait une fiche qui repond 404. */
.esp-brouillon { background: #6b3a17; color: #ffe9d1; }
.esp-figee { cursor: default; }
.esp-avis { justify-content: space-between; }
.esp-etoiles { flex: none; color: var(--gold); font-size: 0.9rem; letter-spacing: 1px; white-space: nowrap; }

/* LA BARRE DE L'ONGLET « PARCOURS » : chercher a gauche, creer a droite.

   LE CHAMP EST A 16px ET N'EN BOUGE PAS : en dessous, Safari zoome sur le
   champ des qu'on le touche et ne dezoome jamais. Meme regle que la
   recherche d'Explorer (`.monde-search input`, css/ecrans.css). */
/* LES RUBRIQUES DU CHANTIER : « Repris en dernier », « Vos lieux ». Plus
   petites que le titre de l'espace — ce sont des intercalaires dans une page
   qui en porte deja un. */
.esp-rub {
  margin: 15px 2px 8px; font-family: var(--display); font-weight: 800;
  font-size: 0.86rem; color: var(--gold);
}
.esp-rub:first-child { margin-top: 4px; }


.esp-barre { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
.esp-chercher { position: relative; flex: 1; min-width: 0; display: flex; align-items: center; }
.esp-chercher input {
  width: 100%; box-sizing: border-box; padding: 11px 12px 11px 38px; border-radius: 12px;
  font: inherit; font-size: 16px;
  background: rgba(16, 12, 7, 0.55); color: var(--parchment);
  border: 1px solid rgba(201, 164, 104, 0.28);
}
.esp-chercher input::placeholder { color: var(--parch-faint); }
/* LA CROIX QUI VIDE LE CHAMP est celle du navigateur, et elle arrive en BLEU
   systeme sur du bois dore. Redessinee en or, a sa place. */
.esp-chercher input::-webkit-search-cancel-button {
  -webkit-appearance: none; appearance: none;
  width: 15px; height: 15px; cursor: pointer; background: var(--gold-deep);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 6l12 12M18 6L6 18' stroke='%23000' stroke-width='3' stroke-linecap='round' fill='none'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 6l12 12M18 6L6 18' stroke='%23000' stroke-width='3' stroke-linecap='round' fill='none'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* La loupe est un bouton pose DANS le champ : elle ne prend pas de rangee a
   elle, et le pouce qui la vise obtient le clavier. */
.esp-loupe {
  position: absolute; left: 5px; width: 28px; height: 28px; padding: 0;
  display: grid; place-items: center; cursor: pointer;
  background: none; border: 0; color: var(--gold-deep);
}
.esp-loupe svg { width: 17px; height: 17px; }
.esp-barre .hub-plus { width: 38px; height: 38px; font-size: 1.3rem; }

/* LA POUBELLE D'UN LIEU VIDE (2.68.24).

   Elle est SOEUR de la ligne et non posee dessus : un bouton dans un bouton
   n'existe pas en HTML, et une poubelle en surimpression se toucherait en
   visant la vignette. Le rang la met au bout, hors de la cible du lieu.

   Elle ne parait que sur un lieu SANS PARCOURS (`ligneLieu`, js/hub.js) : ce
   qui porte un trace se vide d'abord, parcours par parcours. Un bois emporte
   tout son terrain, et ce garde-fou-la vaut mieux qu'un avertissement de plus.

   Elle reprend la mesure de la fleche beige (32 px, 44 px de zone tactile avec
   la marge du rang) dans le rouge des effacements. */
.esp-rang { display: flex; align-items: center; gap: 8px; }
.esp-rang .hub-ligne { flex: 1; min-width: 0; }
/* LE RANG SANS POUBELLE GARDE SA PLACE. Sans ce fantome, les lieux vides
   etaient plus courts que les autres et la colonne partait en dents de scie —
   une liste dont les bords ne s'alignent pas se lit comme une panne, pas comme
   une difference voulue. */
.esp-rang:not(.jetable)::after { content: ''; flex: none; width: 34px; }
.esp-jeter {
  flex: none; width: 34px; height: 34px; margin-bottom: 8px; padding: 0;
  border-radius: 10px; display: grid; place-items: center; cursor: pointer;
  color: #fbe9e4;
  background: linear-gradient(180deg, #a8483a, #6f2c23);
  border: 1px solid rgba(22, 17, 12, 0.45);
  box-shadow: var(--shadow-1);
}
.esp-jeter svg { width: 17px; height: 17px; }
.esp-jeter:active { transform: scale(0.94); }

/* LES SOUS-ONGLETS DE « COMMUNAUTE » : UN SEUL OBJET, PAS TROIS (2.68.4).

   Ils reprenaient les pastilles du dessus en plus petit, et le retenu etait un
   voile d'or translucide. Deux defauts, et le second tuait le premier : trois
   pastilles de meme dessin faisaient une SECONDE rangee d'onglets, ou rien ne
   disait laquelle commandait l'autre ; et posees sur une photo de sous-bois,
   le voile de l'onglet retenu se noyait dans les feuilles — on ne voyait plus
   du tout ou l'on etait.

   C'est donc une AUGE : un creux de bois sombre qui porte les trois d'un
   tenant, et le retenu est une pastille d'or PLEINE, a l'encre sombre. Le
   creux donne son fond a la rangee (la photo ne traverse plus), et l'or plein
   ne se confond avec rien. La hierarchie vient de la TAILLE et de la matiere,
   pas d'un dessin different : l'onglet du dessus commande, celui-ci trie. */
.monde-tabs.sous {
  margin: 0 0 10px; gap: 3px; padding: 3px; border-radius: 13px;
  background: rgba(12, 8, 4, 0.58);
  border: 1px solid rgba(201, 164, 104, 0.3);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.5);
}
.monde-tabs.sous .monde-tab {
  padding: 8px 4px; font-size: 0.7rem; border-radius: 10px;
  background: none; border: 0; color: var(--parch-dim);
}
.monde-tabs.sous .monde-tab.on {
  background: linear-gradient(180deg, var(--gold), var(--gold-deep));
  color: var(--wood-ink); font-weight: 800;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.45);
}

.hub-neuf {
  display: inline-block; margin-bottom: 3px; padding: 2px 6px; border-radius: 3px;
  background: var(--moss); color: #06240f;
  font-size: 0.5rem; font-weight: 900; letter-spacing: 0.07em;
}

/* LA FLECHE BEIGE. Un rond de bois clair, et un TRACE dedans : une fleche
   typographique change de dessin d'une police a l'autre et ne se centre
   jamais dans un rond. Le vert reste aux actions principales. */
.hub-fleche {
  flex: none; width: 32px; height: 32px; border-radius: 50%;
  display: grid; place-items: center; padding: 0;
  background: radial-gradient(circle at 34% 28%, #f7ecce, #d9bf8c 55%, #a3823f 100%);
  border: 3px solid #6a5330; color: var(--wood-ink);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.6);
}
.hub-fleche svg { width: 16px; height: 16px; }
/* LES OUTILS PLUTOT QUE LA FLECHE, sur ce qui mene au chantier du terrain.
   Les pictos de `assets/pictos/` sont des silhouettes BLANCHES, faites pour
   se poser sur des tuiles de sous-bois : sur le parchemin clair de la
   pastille, il faut les retourner a l'encre — c'est la couleur que la fleche
   y prend deja (`--wood-ink`). */
.hub-fleche img { width: 18px; height: 18px; object-fit: contain; display: block; }
.hub-fleche.outil img { filter: brightness(0) opacity(0.8); }
/* Dans la carte a la une, la fleche est posee dans le coin : le texte
   occupe toute la largeur sous elle. */
.hub-fleche.grande { width: 38px; height: 38px; }
.hub-fleche.grande svg { width: 19px; height: 19px; }

/* ------------------------------------------------- la page d'un createur */

.hub-couv { position: relative; height: 180px; margin: 0 -16px; }
.hub-couv img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hub-couv::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(transparent 45%, rgba(6, 18, 12, 0.96));
}
/* LA COUVERTURE FOND DANS LE DECOR (2.69.2). Sur la page d'un lieu, d'un
   parcours ou d'un cartographe, la photo s'arretait net : son voile la
   noircissait vers le bas, et sous elle le sous-bois flou de l'ecran
   reprenait en plein jour — deux images collees, une rupture a la regle, que
   le cadre de la fiche ne couvrait qu'au milieu. La photo se fond donc
   ELLE-MEME dans le decor (un masque, du plein au transparent sur son tiers
   bas) : plus de bord, quel que soit le fond. Le voile reste au milieu, pour
   asseoir le cadre, et s'efface avec la photo. Un peu plus haute, pour que
   le fondu ne mange pas ce qu'elle montre. Le profil garde sa couverture
   d'origine : son voile brun est pense pour un portrait. */
#screen-hub.sous-page:not(.onglet-profil) .hub-couv { height: 210px; }
#screen-hub.sous-page:not(.onglet-profil) .hub-couv img {
  -webkit-mask-image: linear-gradient(#000 52%, rgba(0, 0, 0, 0.55) 78%, transparent 100%);
  mask-image: linear-gradient(#000 52%, rgba(0, 0, 0, 0.55) 78%, transparent 100%);
}
#screen-hub.sous-page:not(.onglet-profil) .hub-couv::after {
  background: linear-gradient(transparent 35%, rgba(6, 18, 12, 0.55) 70%, transparent 100%);
}
/* LE VOILE DU PROFIL, LEGEREMENT BRUN (2.65.16) : les autres couvertures
   (parcours, createur) restent vertes -- celle-ci porte un portrait, pas une
   photo de bois, et un brun discret l'accorde mieux a la planche de
   `.hub-fiche` juste dessous. Classe posee par `paint()` (js/hub.js). */
#screen-hub.onglet-profil .hub-couv::after {
  background: linear-gradient(rgba(24, 16, 8, 0.22), rgba(18, 12, 6, 0.85));
}
/* LE MEME VOILE, ETENDU AU FOND DE FORET (2.65.20) : sous la couverture, le
   reste de l'onglet (le compte, les trois portes, le mot de bas de page)
   s'assoit sur `.home-bg` — le meme vert plein jour que l'accueil, qui
   jurait derriere des cartes en bois. `.home-bg` est deja `position:
   absolute` : elle sert de repere a ce voile sans rien y ajouter d'autre. */
#screen-hub.onglet-profil .home-bg::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(rgba(24, 16, 8, 0.45), rgba(18, 12, 6, 0.75));
}
.hub-fiche {
  position: relative; text-align: center; margin: -46px 0 4px; padding: 0 14px 14px;
  background: var(--bois-grad);
  border: 3px solid var(--wood-1); border-radius: var(--radius);
  box-shadow: var(--shadow-2), inset 0 1px 0 rgba(255, 255, 255, 0.07);
}
.hub-fiche .hub-face.grande { margin-top: -46px; }
.hub-fiche h2 { margin: 8px 0 2px; font-family: var(--display); font-size: 1.3rem; color: var(--gold); }
.hub-chiffres {
  display: grid; grid-template-columns: repeat(3, 1fr); margin: 12px 0 0;
  border-top: 1px solid rgba(201, 164, 104, 0.22); padding-top: 10px;
}
.hub-chiffres.quatre { grid-template-columns: repeat(4, 1fr); }
.hub-chiffres.deux { grid-template-columns: repeat(2, 1fr); }
.hub-chiffres.trois { grid-template-columns: repeat(3, 1fr); }
.hub-chiffres div { display: flex; flex-direction: column; gap: 2px; padding: 0 4px; min-width: 0; }
.hub-chiffres div + div { border-left: 1px solid rgba(201, 164, 104, 0.16); }
.hub-chiffres b {
  font-size: 1rem; color: var(--parchment);
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hub-chiffres span { font-size: 0.58rem; color: var(--parch-faint); }
.hub-bio {
  margin: 12px 4px 0; font-family: var(--hand); font-size: 1rem; line-height: 1.3;
  color: var(--gold);
}

/* -------------------------------------------------- la fiche d'un parcours

   La page qu'on lit avant de partir : couverture, titre, auteur, les trois
   puces de la marche, le mot de l'auteur, ce qui attend, et le bois. Elle
   reprend la planche et la couverture de la page d'un cartographe — deux
   sous-pages du meme hub ne doivent pas se dessiner de deux facons. */

/* Le retour, pose SUR la couverture : un bouton de plus en tete de page
   aurait pousse la photo vers le bas, et c'est elle qui dit ou l'on est. */
/* Une sous-page s'ouvre sur SA couverture : le logo du hub et sa devise
   repoussaient la photo d'un tiers d'ecran pour redire ou l'on est. Profil
   partage la regle : sa propre couverture (`.hub-couv`) tient ce role.

   LA REMONTEE DOIT ANNULER TOUT LE HAUT DE `.hub-scroll`, PAS SEULEMENT
   `--safe-top` (2.65.16) : celui-ci ajoute 34 px d'air pour le logo (plus
   haut dans cette feuille), un logo que la sous-page cache justement —
   sans ce complement la couverture restait a 34 px du bord, collee a rien. */
#screen-hub.sous-page .home-hero { display: none; }
/* L'AIR DU LOGO PART AVEC LE LOGO (2.65.30). Les 34 px du haut de
   `.hub-scroll` sont la place du titre : sur un onglet qui n'en a pas et qui
   n'a pas de couverture pour les absorber (l'espace du cartographe), ils
   restaient en vide au-dessus du premier panneau. On revient donc aux 18 px
   de tout `.scroller`, et la remontee de la couverture annule ce reste — elle
   colle au bord comme avant, seul le vide a disparu. */
#screen-hub.sous-page .hub-scroll { padding-top: calc(var(--safe-top) + 18px); }
#screen-hub.sous-page .hub-couv { margin-top: calc((var(--safe-top) + 18px) * -1); }

/* LA PHOTO PASSE SOUS L'ENCOCHE, PAS LES BOUTONS. La remontee ci-dessus colle
   la couverture au bord haut de la dalle — c'est voulu, une photo pleine
   largeur dit ou l'on est mieux qu'un cadre. Mais le retour et le sceau sont
   poses DANS cette couverture, a 10 et 12 px de son bord : sur un iPhone ils
   se retrouvaient derriere la camera, et le seul moyen de toucher le retour
   etait de viser sous l'encoche. Ils reprennent donc le retrait que la
   couverture, elle, a le droit d'ignorer. */
#screen-hub.sous-page .hub-couv .hub-retour { top: calc(var(--safe-top) + 10px); }
#screen-hub.sous-page .hub-couv .hub-sceau { top: calc(var(--safe-top) + 12px); }

.hub-retour {
  position: absolute; top: 10px; left: 14px; z-index: 3;
  width: 38px; height: 38px; padding: 0; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer;
  color: var(--parchment);
  background: rgba(24, 17, 10, 0.72);
  border: 2px solid var(--wood-1);
  box-shadow: var(--shadow-1);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.hub-retour svg { width: 19px; height: 19px; }

/* La fiche d'un parcours se lit a gauche : un titre de deux lignes et un
   paragraphe centres se relisent mal, la ou une page d'auteur — un nom, un
   portrait, trois chiffres — appelle le centre. */
/* LE SCEAU N'EST PAS LA COUVERTURE. `.hub-couv img` etire TOUTE image de la
   couverture au cadre : la pastille du parcours y devenait un hibou de
   180 px, et comme elle porte un z-index elle recouvrait le titre pose
   dessous. Elle reprend donc sa taille, ici aussi. */
.hub-couv .hub-sceau { width: 44px; height: 44px; top: 12px; right: 14px; }

/* La fiche d'un parcours remonte MOINS que celle d'un auteur : celle-la
   glisse son portrait rond dans le creux (-46 px), celle-ci n'a que son
   titre, et l'y noyer sous la photo le rendait illisible. */
.hub-fiche.gauche { text-align: left; padding: 14px; margin-top: -20px; }
.hub-fiche.gauche h2 { margin: 0 0 6px; font-size: 1.35rem; line-height: 1.1; }
.hub-par {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; margin: 0 0 10px;
  font-size: 0.72rem; color: var(--parch-dim);
}
/* `.hub-face` porte `margin: 0 auto` — il centre le portrait dans la colonne
   d'une carte de createur. Dans une LIGNE en flex, ces marges automatiques
   avalent l'espace libre et poussent le nom au milieu du cadre. */
.hub-par .hub-face { margin: 0; }
.hub-par .link-btn { font-size: 0.72rem; }
.hub-par em {
  display: inline-flex; align-items: center; font-style: normal;
  font-weight: 800; color: var(--gold);
}
.hub-par em i { font-style: normal; font-weight: 400; color: var(--parch-faint); margin-left: 4px; }
.hub-par em.faint { font-weight: 600; color: var(--parch-faint); }
/* Les puces de la marche : plus grosses que celles d'une rangee, parce que
   ce sont ELLES qu'on vient chercher — combien de temps, combien de bornes. */
.hub-meta.grande {
  gap: 8px; flex-wrap: wrap; font-size: 0.74rem; font-weight: 700; margin-bottom: 10px;
}
.hub-meta.grande li {
  padding: 5px 10px; border-radius: 9px;
  background: rgba(16, 12, 7, 0.6); border: 1px solid rgba(201, 164, 104, 0.3);
}
.hub-meta.grande .hub-ic { width: 14px; height: 14px; }
.hub-desc { margin: 0; font-size: 0.8rem; line-height: 1.5; color: var(--parch-dim); }

/* Les chiffres en planche : les memes cases que la page d'un auteur, mais
   posees sur leur propre bois — elles ne sont plus dans la fiche, elles la
   suivent. */
.hub-chiffres.planche {
  margin: 0; padding: 12px 6px; border-top: 0;
  background: var(--bois-grad);
  border: 3px solid var(--wood-1); border-radius: var(--radius);
  box-shadow: var(--shadow-1), inset 0 1px 0 rgba(255, 255, 255, 0.07);
  text-align: center;
}
.hub-chiffres.planche b { color: var(--gold); }

/* -------------------------------------------------- le carnet de marche

   CE QU'UN COMPTE A MARCHE (2.71) : sous le compte, dans Profil. Un titre
   en or avec le marcheur, la planche des trois grands chiffres (km, h,
   montee) et des quatre petits, puis les records en petites cartes de bois
   deux par rangee — la valeur en gros, le mot dessous, la date et le lieu en
   italique. Un record a zero se grise : la case existe, elle attend. */
.hub-carnet { margin-top: 14px; }
.hub-carnet h3, .hub-carnet h4 {
  display: flex; align-items: center; gap: 8px; margin: 0 2px 8px;
  font-family: var(--display); color: var(--gold); font-size: 1.05rem;
}
.hub-carnet h4 { margin-top: 14px; font-size: 0.92rem; }
.hub-carnet h3 svg { width: 20px; height: 20px; flex: none; }
.hub-carnet h3 i { margin-left: auto; font: 400 0.68rem var(--sans); color: var(--parch-faint); }
.hub-carnet-planche {
  padding: 10px 6px 12px; background: var(--bois-grad);
  border: 3px solid var(--wood-1); border-radius: var(--radius);
  box-shadow: var(--shadow-1), inset 0 1px 0 rgba(255, 255, 255, 0.07);
  text-align: center;
}
.hub-carnet-planche .hub-chiffres.planche { border: 0; box-shadow: none; background: none; padding: 2px 0 10px; }
.hub-carnet-planche .hub-chiffres.planche b { font-size: 1.45rem; letter-spacing: -0.01em; }
.hub-carnet-planche .hub-chiffres.planche b small { font-size: 0.62rem; margin-left: 2px; color: var(--parch-dim); }
.hub-carnet-planche .hub-chiffres.quatre { margin-top: 0; }
.hub-carnet-mot {
  margin: 10px 6px 0; font-family: var(--hand); font-size: 1.05rem; line-height: 1.3;
  color: var(--gold); text-align: center;
}
/* La planche est `.bois` (base.css), posee par le HTML. */
.hub-carnet-vide { padding: 12px 14px; }
.hub-carnet-vide h3 { margin-bottom: 6px; }
.hub-carnet-vide p { margin: 0; font-size: 0.74rem; line-height: 1.45; color: var(--parch-dim); }
.hub-records { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.hub-record {
  position: relative; display: flex; flex-direction: column; gap: 1px; min-width: 0;
  padding: 10px 10px 9px 12px; background: var(--bois-grad);
  border: 2px solid var(--wood-1); border-radius: var(--radius);
  box-shadow: var(--shadow-1), inset 0 1px 0 rgba(255, 255, 255, 0.07);
}
.hub-record svg {
  position: absolute; top: 9px; right: 9px; width: 18px; height: 18px;
  color: var(--gold); opacity: 0.8;
}
.hub-record b {
  font-family: var(--display); font-size: 1.35rem; line-height: 1.1; color: var(--gold);
  padding-right: 24px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hub-record b small { font-size: 0.68rem; font-weight: 700; margin-left: 3px; color: var(--parch-dim); }
.hub-record span { font-size: 0.66rem; line-height: 1.25; color: var(--parchment); }
.hub-record i { margin-top: 4px; font-size: 0.6rem; font-style: italic; color: var(--parch-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hub-record.sans { opacity: 0.55; }
.hub-record.sans b { color: var(--parch-faint); }

/* Ce qui, mal lu, gache une sortie : la carte a charger avant de partir. */
.hub-note {
  margin: 8px 2px 14px; font-size: 0.7rem; line-height: 1.45; color: var(--parch-dim);
}
.hub-note.attention {
  padding: 9px 11px; border-radius: 11px; color: var(--gold);
  background: rgba(217, 184, 80, 0.12); border: 1px solid rgba(217, 184, 80, 0.32);
}
/* LA NOTE PORTE SON BOUTON (2.101) : le sac de CE lieu, d'un geste. */
.hub-note-sac p { margin: 0 0 9px; }
.hub-note-sac .btn { gap: 8px; }
.hub-note-sac .btn-img { width: 26px; height: 26px; object-fit: contain; margin: -4px 0; }

/* LE PICTO DU SAC sur un item (2.101) : la ou le reseau manque. Il se touche,
   et remplit le sac du lieu sans code de partie. Sur la vignette d'un lieu il
   se pose dans le coin ; dans la ligne d'un parcours, a cote du mode. */
.hub-sac {
  display: inline-grid; place-items: center; flex: none; cursor: pointer;
  width: 26px; height: 26px; border-radius: 50%;
  background: rgba(22, 16, 9, 0.82); border: 1px solid rgba(217, 184, 80, 0.55);
  box-shadow: var(--shadow-1);
}
.hub-sac img { width: 20px; height: 20px; object-fit: contain; }
.hub-tags .hub-sac { width: 22px; height: 22px; margin-left: 2px; }
.hub-tags .hub-sac img { width: 17px; height: 17px; }
/* « ALLER DANS CE BOIS » EST CENTRE. La primitive `.grow` du jeu pousse le
   texte a gauche pour laisser la place a un chevron ; ce bouton-la n'en a pas,
   et son mot restait colle au bord comme s'il manquait quelque chose. */
/* LA PORTE D'UNE FICHE (lieu ou parcours) : creer l'aventure, et — pour
   celui qui l'a posee — l'outil. Le carre reste a GAUCHE du grand bouton et
   ne grandit pas avec lui : c'est le geste de l'exception, il ne doit jamais
   avoir l'air du geste principal. Sans lui, la rangee n'a qu'un enfant et
   rien ne bouge. */
.hub-lancer { display: flex; align-items: stretch; gap: 10px; }
.hub-lancer .hub-fonder { margin-bottom: 4px; }
.btn.xl.hub-fonder .grow { text-align: center; }
.hub-porte-note { margin: 10px 6px 14px; }
.btn.hub-editer {
  flex: none; width: 62px; min-height: 62px; padding: 0; margin-bottom: 4px;
  border-radius: var(--radius);
}
.btn.hub-editer img { width: 30px; height: 30px; display: block; }

/* ------------------------------------------------------------ le profil */

.hub-vide { text-align: center; padding: 22px 16px; }
.hub-vide b { display: block; font-family: var(--display); font-size: 1rem; color: var(--gold); }
.hub-vide p { margin: 6px 0 0; font-size: 0.76rem; color: var(--parch-dim); }
/* UN MOT APPUYE DANS UNE PHRASE RESTE DANS LA PHRASE. `.hub-vide b` est le
   TITRE de la planche — en bloc, en or — et un `<b>` au milieu d'un
   paragraphe heritait de cette regle : la phrase se cassait en trois, et le
   point tombait seul sur sa ligne. */
.hub-vide p b {
  display: inline; font-family: inherit; font-size: inherit;
  color: var(--parch); font-weight: 700;
}

/* ------------------------------------------------------- l'ecran etroit */

@media (max-width: 359px) {
  .hub-face { width: 54px; height: 54px; }
}

/* ------------------------------------------------- la barre du bas du hub

   C'est `.tabbar` du jeu, mot pour mot : meme fond, meme lisere, memes
   angles, meme pilule verte. Deux retouches seulement, et elles ne changent
   pas son dessin :
     - elle n'est plus dans la grille de la coque de jeu (`grid-area: nav`),
       mais amarree au bas de l'ecran du hub ;
     - le bouton du milieu sur son socle (2.65.13) : il ouvre desormais
       « Jouer » — Creer, Rejoindre, Concevoir — et non plus l'exploration,
       geste qui garde sa propre entree juste a cote.
   Cinq entrees, et les MEMES partout (2.75.6) : `#monde-tabs`, la barre de
   la selection des lieux, n'est pas une autre barre — c'est celle-ci, sur un
   autre ecran. Elle n'avait plus que trois colonnes depuis la 2.65.14 ; la
   barre fondait sous le doigt des qu'on touchait « Explorer ». */
/* LE BAS DE L'ECRAN EST UN BLOC, PAS DEUX PIECES AMARREES (2.75.7). La barre
   etait collee au bas de l'ecran ; le ruban des rubriques, qui se pose
   au-dessus d'elle, aurait demande de mesurer sa hauteur en JS a chaque
   peinture et a chaque rotation. C'est le BLOC qui est amarre, et ils
   s'empilent dedans. */
.hub-bas {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 5;
  max-width: 560px; margin-left: auto; margin-right: auto;
  pointer-events: none;                 /* le vide a cote du ruban laisse passer */
}
.hub-bas > * { pointer-events: auto; }
.hub-tabbar {
  position: relative;
  grid-area: auto;
  grid-template-columns: repeat(5, 1fr);
  margin-top: 0;
}
.hub-scroll { padding-bottom: calc(var(--nav-h, 64px) + 28px + var(--safe-bot)); }
/* ET L'ECRAN DU CODE, quand la barre s'y pose (2.76.1). Le volet de
   « Rejoindre » n'a pas d'ascenseur — il tient dans sa hauteur, boutons
   amarres en bas — donc sans cette place reservee, « Entrer sur le terrain »
   finit DERRIERE la barre : le seul geste de l'ecran, cache par la porte de
   sortie. La classe est posee par `showOnboardPane` avec la barre. */
#screen-onboard.a-barre .scroller {
  padding-bottom: calc(var(--nav-h, 64px) + 28px + var(--safe-bot));
}
/* Le ruban mange une rangee de plus : le defilement s'arrete plus haut, sinon
   la derniere planche se lit a moitie. */
#screen-hub.a-sous .hub-scroll,
#screen-monde.a-sous .monde-scroll {
  padding-bottom: calc(var(--nav-h, 64px) + 96px + var(--safe-bot));
}

/* ------------------------------------------- le ruban des rubriques (2.75.7)

   LA DEUXIEME RANGEE. Cinq onglets en bas, et derriere chacun un ecran qui
   porte tout ce que l'onglet sait faire : l'accueil empilait ses rangees
   jusqu'a ce qu'on ne sache plus ce qu'on defile. Le ruban le decoupe en
   pages — une rubrique, un ecran — sans ajouter d'onglet en bas.

   IL SORT DE SON ONGLET, ET ON DOIT LE VOIR : le PIC DE DIALOGUE se pose
   sous la planche, a l'aplomb de l'onglet ouvert (`--pic`, pose par
   `peindreSous()`). Sans lui, la rangee ressemble a une seconde barre de
   navigation posee la, et l'on ne sait plus laquelle commande l'autre.

   La planche est OPAQUE, et c'est ce qui rend le pic propre : il est dessine
   dessous (z-index), sa moitie haute disparait derriere elle, et il n'en
   reste que la pointe et ses deux aretes d'or. */
/* z-index 3 : au-dessus de la barre (2), pour que la pointe du pic morde
   dedans au lieu de se faire couper par elle. */
.sous-menu { position: relative; z-index: 3; padding: 0 10px 12px; }
.sous-menu[hidden] { display: none; }
.sm-planche {
  position: relative; z-index: 1;
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  align-items: stretch; gap: 2px;
  padding: 5px 4px;
  border-radius: 18px;
  border: 1px solid rgba(226, 201, 141, 0.48);
  background: linear-gradient(180deg, #2b1e10, #1a1209);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.07);
}
.sm-pic {
  /* AU-DESSUS DE LA PLANCHE, pas dessous (z-index 2 contre 1) : c'est ce qui
     fait une bulle et non un triangle colle dessous. Son fond est EXACTEMENT
     la couleur du bas de la planche, sa moitie haute recouvre donc le lisere
     d'or a l'endroit ou le pic sort — le trait fait le tour du pic, comme il
     ferait le tour d'une bulle de bande dessinee. Dessous, on aurait vu le
     lisere barrer le pic en travers.
     Sa pointe mord de trois pixels dans la barre : un pic qui s'arrete juste
     au-dessus flotte, et ne designe plus rien. */
  position: absolute; z-index: 2;
  left: var(--pic, 50%); bottom: 1px;
  width: 19px; height: 19px; margin-left: -9.5px;
  transform: rotate(45deg);
  background: #1a1209;
  border-right: 1px solid rgba(226, 201, 141, 0.48);
  border-bottom: 1px solid rgba(226, 201, 141, 0.48);
  border-bottom-right-radius: 4px;
  transition: left 0.22s var(--ease);
}
.sm-item {
  border: 0; background: none; color: var(--parch-faint);
  font: inherit; font-size: 0.56rem; font-weight: 700; line-height: 1.1;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  padding: 5px 1px; border-radius: 13px;
  cursor: pointer; text-align: center;
  /* Un libelle long (« En ce moment ») se serre plutot que de casser la
     rangee en deux hauteurs. */
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis; max-width: 100%;
  transition: color 0.2s, background 0.2s;
}
.sm-item svg { width: 19px; height: 19px; }
/* L'IPHONE SE, 320 points : « En ce moment » y perdait sa fin sous les points
   de suspension. Cinq cases de soixante pixels ne laissent pas le choix — on
   serre la lettre plutot que de couper le mot, qui est ce qui se lit. */
@media (max-width: 359px) {
  .sm-item { font-size: 0.5rem; letter-spacing: -0.015em; padding-left: 0; padding-right: 0; }
  .sm-item svg { width: 17px; height: 17px; }
}
.sm-item.on {
  color: var(--moss);
  background: linear-gradient(180deg, rgba(70, 150, 90, 0.30), rgba(30, 80, 48, 0.22));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.10);
}
.sm-item.on svg { filter: drop-shadow(0 0 7px rgba(110, 200, 120, 0.5)); }
/* UNE RUBRIQUE QUI SE GAGNE (2.76) : elle reste touchable — c'est en y
   allant qu'on apprend ce qu'elle porte — mais son cadenas se voit. */
.sm-item.ferme { opacity: 0.72; }
.sm-bulle.verrou {
  background: rgba(12, 9, 5, 0.92); border-color: rgba(226, 201, 141, 0.45);
  color: var(--gold);
}
.sm-bulle.verrou svg { width: 8px; height: 8px; }
/* CE QUI ATTEND DERRIERE UNE RUBRIQUE (2.75.8) : le compte des nouveautes,
   sur l'icone et non sur le mot — la meme pastille que sur les onglets de la
   barre, en plus petit. Le bouton ne peut pas etre `relative` sans casser
   l'ellipse du libelle : c'est l'icone qui la porte. */
.sm-ic { position: relative; display: inline-flex; }
.sm-bulle {
  /* Elle ne DEBORDE pas du bouton : il cache ce qui depasse, pour serrer le
     libelle en points de suspension plutot que de casser la rangee. */
  position: absolute; top: -3px; right: -8px; min-width: 15px; height: 15px;
  padding: 0 3px; border-radius: 8px; background: var(--moss-deep);
  border: 1px solid var(--moss); color: #fff; font-size: 0.5rem;
  font-style: normal; font-weight: 700; display: grid; place-items: center;
}
.sm-item:active svg { transform: scale(0.9); }

.tab.boussole { padding: 0; overflow: visible; }
.tab.boussole .rose {
  width: 54px; height: 54px; margin: -20px auto 0; border-radius: 50%;
  display: grid; place-items: center; color: #05210f;
  background: radial-gradient(circle at 35% 30%, #9ef08a, #3f9a4a 70%);
  box-shadow: 0 0 0 4px rgba(127, 208, 127, 0.18), 0 6px 16px rgba(0, 0, 0, 0.55),
              inset 0 1px 0 rgba(255, 255, 255, 0.35);
}
.tab.boussole .rose svg { width: 28px; height: 28px; }

/* Le decor du hub : le meme sous-bois que l'accueil, mais fige — il defile
   sous quatre rangees, et une image qui derive sous un defilement donne le
   mal de mer. Sans assombrissement (2.65.11) : la meme lumiere que la
   selection des lieux (screen-monde), qui partage ce decor sans en avoir
   jamais eu un. */
#screen-hub .home-bg { animation: none; }

/* La selection des lieux porte la meme barre : son defilement doit s'arreter
   au-dessus, comme celui du hub. */
#screen-monde .monde-scroll { padding-bottom: calc(var(--nav-h) + 28px + var(--safe-bot)); }

/* ============ LA FICHE D'UN PARCOURS : CE QU'ELLE MONTRE DE PLUS ============

   Elle disait le titre, l'auteur et trois chiffres. Ce qu'on veut vraiment
   savoir avant de charger la voiture, c'est : a quoi ca ressemble, ca monte
   combien, et ou est-ce que ca se passe. Trois blocs y repondent (2.61.1), et
   aucun ne franchit la frontiere des balises — trois decors d'ambiance, une
   courbe qui ne porte aucune coordonnee, et le contour du bois qui est deja
   public. */

/* Les trois vues, sous le mot de l'auteur. Une rangee egale, pas une grille
   qui se casse : trois images de la meme hauteur se lisent comme une bande de
   pellicule, et c'est ce qu'on regarde en premier sur une fiche. */
.hub-apercus {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px;
  margin: 12px 0 2px;
}
.hub-apercus img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block;
  border-radius: 10px; border: 2px solid var(--wood-2);
}

/* Le chiffre de la montee se range DANS la rubrique, a droite : une ligne de
   plus sous le titre aurait separe la courbe de ce qu'elle mesure. */
.hub-rub span {
  font-family: var(--sans); font-size: 0.7rem; font-weight: 700;
  color: var(--gold); white-space: nowrap;
}

/* La courbe de la montee, sur sa planche. `height` fixe et `viewBox` etire :
   c'est ce qui lui permet de tenir la meme hauteur a toutes les largeurs
   d'ecran sans qu'on ait a la repeindre au retournement. */
.hub-profil {
  background: var(--bois-grad);
  border: 3px solid var(--wood-1); border-radius: var(--radius);
  box-shadow: var(--shadow-1), inset 0 1px 0 rgba(255, 255, 255, 0.07);
  padding: 10px 12px 8px; margin-bottom: 10px;
}
.hub-profil svg { width: 100%; height: 96px; display: block; }
.hub-profil-ax {
  display: flex; justify-content: space-between; align-items: baseline;
  margin-top: 6px; font-size: 0.6rem; color: var(--parch-faint);
}
.hub-profil-ax span:nth-child(2) { color: var(--gold); font-weight: 700; }

/* LA CARTE DU PARCOURS. Elle se pose au-dessus de la ligne du lieu, dont elle
   est l'illustration : les deux ne font qu'une reponse a « ou cela se passe ».

   Une TOILE (les tuiles du jeu, le bois, le chemin, les deux bouts), donc une
   image : elle prend la largeur et garde son rapport tout seul, la hauteur du
   canevas etant calculee sur la forme du bois. Une hauteur fixe faisait un
   timbre-poste au milieu d'une bande vide. */
.hub-carte {
  position: relative;
  background: var(--bois-grad);
  border: 3px solid var(--wood-1); border-radius: var(--radius);
  box-shadow: var(--shadow-1), inset 0 1px 0 rgba(255, 255, 255, 0.07);
  padding: 8px 8px 9px; margin-bottom: 10px;
}
.hub-carte canvas {
  width: 100%; height: auto; display: block;
  border-radius: 10px; background: rgba(12, 8, 4, 0.35);
}
.hub-carte i {
  display: block; margin-top: 5px; text-align: center;
  font-style: normal; font-size: 0.6rem; color: var(--parch-faint);
}
/* La legende : deux pastilles et deux mots, pour que le vert et l'or se
   lisent sans avoir a deviner lequel est le depart. */
.hub-carte-lg {
  /* En HAUT de la toile, pas en bas : posee en bas elle chevauchait la phrase
     sous le cadre des que celle-ci passait sur deux lignes. */
  position: absolute; left: 16px; top: 16px;
  display: flex; align-items: center; gap: 4px;
  padding: 3px 8px; border-radius: 999px;
  background: rgba(12, 8, 4, 0.72); border: 1px solid var(--wood-2);
  font-size: 0.56rem; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--parch-dim);
}
.hub-carte-lg i {
  display: inline-block; margin: 0; width: 8px; height: 8px; border-radius: 50%;
  border: 1px solid #1b140d;
}
.hub-carte-lg i.dep { background: #7fb069; }
.hub-carte-lg i.arr { background: #d9b850; margin-left: 6px; }

/* La grande photo du cadre de presentation. La couverture du haut est coupee
   par la planche qui la chevauche et par le sceau : elle pose l'ambiance, elle
   ne MONTRE pas. Celle-ci est entiere, a la place ou l'oeil descend apres le
   mot de l'auteur. */
.hub-grande {
  width: 100%; aspect-ratio: 16 / 10; object-fit: cover; display: block;
  margin: 12px 0 0; border-radius: 12px; border: 2px solid var(--wood-1);
  box-shadow: var(--shadow-1);
}
.hub-grande + .hub-apercus { margin-top: 6px; }

/* L'AUTEUR SUR UNE RANGEE : le portrait et le pseudo, discrets. Un parcours
   est de quelqu'un — c'est ce que le hub raconte — mais le nom ne doit pas
   disputer le titre : 18 px de portrait, et le meme corps que le lieu. */
.hub-par-mini {
  display: inline-flex; align-items: center; gap: 4px;
  margin-right: 6px; vertical-align: middle;
  font-style: normal; color: var(--parch-dim);
}
.hub-par-mini img {
  width: 18px; height: 18px; border-radius: 50%; object-fit: cover;
  border: 1px solid var(--wood-2); flex: none; display: block;
}
/* Sur la photo de « A la une », le fond est sombre et libre : le nom peut
   prendre le parchemin plein sans peser. */
.hub-par-mini.clair {
  margin: 0 0 5px; font-size: 0.64rem; font-weight: 700; color: var(--parchment);
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.8);
}
/* LE SEPARATEUR ENTRE L'AUTEUR ET SON BOIS. Le portrait, le pseudo et le nom
   du lieu se suivaient sans rien entre eux : « Guillaume Bois des Vouillants »
   se lit comme un seul nom, et l'on ne sait plus ou l'un s'arrete. Un petit
   losange d'or, aligne sur la ligne de base des deux textes. */
.hub-sep {
  display: inline-block; width: 5px; height: 5px; margin: 0 7px 1px 1px;
  background: var(--gold); opacity: 0.7; transform: rotate(45deg);
  vertical-align: middle; flex: none;
}

/* LA PORTE A PLUSIEURS CLES (2.72, `Compte.porte`, js/compte.js) : la meme
   dans l'onglet Profil du hub et sur l'ecran du cartographe, d'ou base.css
   plutot qu'une feuille par ecran. Google dessine son bouton dans
   `.porte-google-btn` ; on ne fait que lui donner sa place et le centrer. */
.porte { text-align: left; }
.porte-google-btn { display: flex; justify-content: center; min-height: 44px; }
.porte-ou {
  display: flex; align-items: center; gap: 10px; margin: 12px 0 8px;
  color: var(--parch-faint); font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase;
}
.porte-ou::before, .porte-ou::after { content: ''; flex: 1; height: 1px; background: rgba(255, 255, 255, 0.14); }
.porte-form .field { margin-bottom: 10px; }
.porte-form .btn { margin-top: 4px; }
.porte-sms { margin-top: 9px; }
.porte-liens {
  display: flex; justify-content: center; gap: 10px; margin: 12px 0 0;
  font-size: 0.86rem;
}
.porte-liens a { color: var(--gold); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.porte-liens span { color: var(--parch-faint); }
.porte-msg { margin: 8px 0 0; min-height: 1em; text-align: center; }
.porte-msg.alert { color: #f0a58a; }
/* Les feuilles de la porte (inscription, code, oubli, les gestes de la fiche). */
.porte-pane { padding: 4px 2px 8px; }
.porte-pane .btn + .btn { margin-top: 8px; }
.porte-pane .porte-otp { margin: 14px 0 6px; }
.porte-pane .porte-google-btn { margin: 10px 0 14px; }

/* --------------------------------- le hub sur un ecran de bureau (2.68.12)

   Le hub est dessine pour un pouce, et rien de ce qu'il montre ne gagne a
   s'etirer : sur un moniteur, la photo de « A la une » se delayait sur toute
   la largeur du `.scroller` a densite 1, le decor de foret se tirait d'un
   bord a l'autre de la fenetre et la barre du bas courait avec lui. On rend
   donc au hub sa largeur de telephone, et le reste tombe dans le noir de la
   planche (`--ink-900`, le fond de `body`).

   DEUX ECRANS SEULEMENT — le hub et la selection des lieux, ceux qui portent
   la barre du bas. Le jeu, les reglages et le cartographe gardent la fenetre
   entiere : on y lit une carte, et une carte veut toute la place qu'on lui
   donne.

   Le seuil est a 600 px. En dessous, `.scroller` (560 px) tenait deja la
   largeur : la colonne n'y changerait rien, et un telephone ne doit croiser
   aucune de ces regles.

   `margin-inline: auto` et NON `transform: translateX(-50%)` : les deux
   centrent un bloc absolu, mais un `transform` fait de l'ecran le bloc
   conteneur de ses descendants `position: fixed` — le voile d'un tiroir
   (`.sheet-bg`, inset: 0) ne couvrirait alors plus que la colonne, et les
   messages s'ancreraient dessus au lieu de la fenetre.

   `overflow: hidden` n'est pas de la prudence : `.home-bg` deborde de 16 px
   de chaque cote (sa derive lente a besoin de cette reserve). Hors de
   l'ecran sur un telephone, ces deux bandes de foret se poseraient ici en
   plein sur le noir, de part et d'autre de la colonne. */
@media (min-width: 600px) {
  #screen-hub.active, #screen-monde.active {
    width: var(--phone-w); margin-inline: auto; overflow: hidden;
  }

  /* LE FOND GENERAL N'A PLUS RIEN A ECLAIRER. `#bg-photo`, son voile et les
     particules sont `position: fixed; inset: 0` : ils vivent HORS de la
     section et rempliraient la fenetre autour d'elle. Les deux ecrans
     portent leur propre decor (`.home-bg`, dans la section), ils ne perdent
     rien. `body:has()` est l'idiome de la maison pour « selon l'ecran
     ouvert » — voir le voile du demarrage dans `ecrans.css`. */
  body:has(#screen-hub.active) #bg-photo,
  body:has(#screen-hub.active) #bg-veil,
  body:has(#screen-hub.active) #particles,
  body:has(#screen-monde.active) #bg-photo,
  body:has(#screen-monde.active) #bg-veil,
  body:has(#screen-monde.active) #particles { display: none; }

  /* Ce qui se pose PAR-DESSUS reste dans la colonne : un tiroir tire a
     560 px deborderait de 430 de part et d'autre, et les messages courent de
     bord a bord (`left: 12px; right: 12px`). */
  body:has(#screen-hub.active) .sheet,
  body:has(#screen-monde.active) .sheet { max-width: var(--phone-w); }
  body:has(#screen-hub.active) #toasts,
  body:has(#screen-monde.active) #toasts {
    left: 50%; right: auto; transform: translateX(-50%);
    width: calc(var(--phone-w) - 24px);
  }
}

/* ------------------------------------------------- la page du lieu (2.69)

   Le lieu se presente, le parcours vient derriere. La porte de la page —
   creer une aventure, le carre d'outils du proprietaire a sa gauche — vient
   AVANT la liste, pour ne pas tomber sous le pli ; puis une ligne par
   parcours, la meme rangee que l'accueil (`.hub-ligne`), la fleche a droite
   (2.69.1). Le slide d'avant (une carte par parcours, `scroll-snap`) cachait
   les parcours au-dela du deuxieme et la porte dessous. */
.hub-parcours { margin-bottom: 4px; }
.hub-tri { margin: -2px 0 8px; }
.hub-tag.clair { background: rgba(238, 241, 230, 0.16); color: var(--parchment); }
/* ------------------------------------------ le chantier d'un lieu (2.69) */

.esp-retour {
  display: inline-flex; align-items: center; gap: 4px; margin: 0 0 8px; padding: 4px 8px 4px 2px;
  background: none; border: 0; color: var(--gold); font-size: 0.72rem; font-weight: 800;
  cursor: pointer;
}
.esp-retour .btn-ic svg { width: 16px; height: 16px; }
.esp-lieu-tete {
  display: flex; gap: 10px; align-items: center; margin: 0 0 10px; padding: 8px;
  background: var(--bois-grad); border: 3px solid var(--wood-1); border-radius: 14px;
  box-shadow: var(--shadow-1);
}
.esp-lieu-tete .hub-vign { width: 74px; height: 74px; flex: none; object-fit: cover; border-radius: 9px; }
.esp-lieu-tete b { display: block; font-family: var(--display); font-size: 1rem; line-height: 1.1; color: var(--gold); }
.esp-lieu-tete i { display: block; font-style: normal; margin: 1px 0 4px; }
.esp-lieu-tete .hub-tags { margin-bottom: 2px; }
.esp-lieu-tete .hub-meta { font-size: 0.62rem; }
.btn.esp-nouveau-lieu { margin: 0 0 10px; }
.esp-rub + .esp-nouveau-lieu { margin-top: 2px; }

/* ------------------------------------------------- conseils et FAQ (2.101)

   La rubrique : une carte par item, l'image a gauche, le titre et sa ligne a
   droite — la grammaire des lignes de parcours, pour qu'on sache d'avance
   que ca s'ouvre. L'ecran d'un item : l'image en couverture, puis des slides
   qui glissent au doigt (`scroll-snap`, aucun geste a nous), et le bouton
   de ce dont on vient de parler. */
.hub-savoir-intro { margin: 4px 2px 10px; }
.hub-savoir { display: flex; flex-direction: column; gap: 9px; }
.hub-savoir-item {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 7px 10px 7px 7px; text-align: left; cursor: pointer; font: inherit;
  background: var(--bois-grad);
  border: 3px solid var(--wood-1); border-radius: 14px;
  box-shadow: var(--shadow-1);
}
.hub-savoir-item img {
  flex: none; width: 84px; height: 56px; object-fit: cover;
  border-radius: 9px; border: 2px solid var(--wood-2);
}
.hub-savoir-item > span:not(.hub-fleche) { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.hub-savoir-item b { font-size: 0.78rem; line-height: 1.2; color: var(--gold); }
.hub-savoir-item i { font-style: normal; font-size: 0.64rem; line-height: 1.35; color: var(--parch-dim); }

.hub-savoir-page h2 { margin-bottom: 10px; }
.hub-slides {
  display: flex; gap: 12px; overflow-x: auto; scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain; scrollbar-width: none;
  margin: 0 -2px; padding: 2px;
}
.hub-slides::-webkit-scrollbar { display: none; }
.hub-slide {
  flex: 0 0 100%; scroll-snap-align: start; box-sizing: border-box;
  display: flex; flex-direction: column; gap: 7px;
  padding: 14px 15px 16px; min-height: 150px; margin: 0;
}
.hub-slide em {
  font-style: normal; font-size: 0.58rem; font-weight: 800; letter-spacing: 0.08em;
  color: var(--moss-soft);
}
.hub-slide b { font-size: 0.92rem; line-height: 1.2; color: var(--gold); }
.hub-slide p { margin: 0; font-size: 0.76rem; line-height: 1.5; color: var(--parchment); }
.hub-slides-dots { padding: 10px 0 2px; }
.hub-slides-dots i { cursor: pointer; }
.hub-savoir-act { margin-top: 14px; }

/* ------------------------------------------------ l'annonce et la pause (2.109)

   Poses dans la console (Application ▸ Accès). L'annonce est une ligne en
   tete de l'accueil, dans l'un des trois tons ; la maintenance prend la
   place de la page — la barre reste, pour reprendre une aventure en cours. */
.hub-annonce {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 12px; padding: 10px 14px; border-radius: var(--radius-sm);
  font-size: 0.86rem; font-weight: 700; line-height: 1.35;
  /* Un fond PLEIN : l'accueil pose l'annonce sur la photo du sous-bois, et
     une vitre teintee s'y lisait a peine. */
  background: linear-gradient(90deg, rgba(20, 44, 54, 0.94), rgba(18, 24, 20, 0.9));
  color: #d6eef5;
  border: 1px solid rgba(127, 182, 201, 0.55);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
}
.hub-annonce svg { flex: none; width: 20px; height: 20px; }
.hub-annonce.fete { background: linear-gradient(90deg, rgba(62, 46, 18, 0.95), rgba(28, 22, 14, 0.9)); color: #f7e6ba; border-color: rgba(226, 201, 141, 0.6); }
.hub-annonce.alerte { background: linear-gradient(90deg, rgba(70, 24, 20, 0.95), rgba(28, 18, 14, 0.9)); color: #ffd0c9; border-color: rgba(217, 105, 92, 0.6); }
.hub-maintenance {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  text-align: center; padding: 18px 18px 20px; margin-top: 8vh;
}
.hub-maintenance img { width: 100%; max-width: 300px; aspect-ratio: 3 / 2; object-fit: cover; border-radius: var(--radius-sm); }
.hub-maintenance b { font-size: 1.3rem; color: var(--gold); }
.hub-maintenance p { margin: 0; color: var(--parch-dim); }

/* ------------------------------------------------- le carnet des lieux (2.113)

   UNE FEUILLE DE PAPIER POSEE SUR LA FORET. L'accueil empilait des planches
   brunes cerclees d'or sur un sous-bois lumineux : tout avait le meme poids,
   et le texte se lisait mal au soleil. La foret ne se voit plus qu'en haut,
   derriere le logo ; tout ce qu'on lit est a l'encre sur du clair. La feuille
   deborde le defileur jusqu'aux bords de l'ecran et descend sous la barre :
   elle ne s'arrete pas en l'air au-dessus du bois. */
.hub-feuille {
  position: relative; color: var(--encre-1);
  margin: 0 -16px calc(-1 * (var(--nav-h, 64px) + 28px + var(--safe-bot)));
  padding: 22px 18px calc(var(--nav-h, 64px) + 44px + var(--safe-bot));
  min-height: 72vh;
  border-radius: 26px 26px 0 0;
  background:
    radial-gradient(120% 60% at 10% 0%, rgba(255, 250, 235, 0.7), transparent 60%),
    radial-gradient(80% 50% at 100% 40%, rgba(214, 196, 160, 0.35), transparent 70%),
    radial-gradient(60% 40% at 0% 90%, rgba(214, 196, 160, 0.3), transparent 70%),
    linear-gradient(180deg, var(--papier-1), var(--papier-2));
  box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.35);
}
/* Le croquis du coin : de l'encre sur fond transparent, dessine par Codex
   (atelier/origine/carnet/). */
.hub-feuille-croquis {
  position: absolute; right: 12px; top: 12px; width: 132px; height: auto;
  opacity: 0.6; pointer-events: none;
}
.hub-feuille-t {
  position: relative; max-width: 72%; margin: 4px 0 14px;
  font-family: var(--display); font-size: 1.95rem; font-weight: 900; line-height: 1.06;
  letter-spacing: -0.01em; color: var(--encre-1);
}
.hub-cherche {
  position: relative; display: flex; align-items: center; gap: 12px; width: 100%;
  height: 46px; padding: 0 14px; cursor: text; text-align: left;
  font: inherit; font-size: 1rem; color: var(--encre-3);
  background: rgba(255, 252, 243, 0.78); border: 1px solid rgba(120, 88, 50, 0.32); border-radius: 12px;
}
.hub-cherche svg { width: 21px; height: 21px; color: var(--encre-1); flex: none; }
.hub-code-lien, .hub-tous {
  display: block; margin: 9px 2px 14px auto; padding: 2px 0; border: 0; background: none; cursor: pointer;
  font: inherit; font-size: 0.85rem; font-weight: 800; color: var(--sapin);
}
.hub-tous { margin: 2px 2px 0 auto; }

/* La une : une photo, puis le papier. Un seul cadre d'or dans tout le carnet. */
.hub-feuille .hub-une {
  position: relative; display: block; width: 100%; padding: 0; overflow: hidden; cursor: pointer;
  text-align: left; color: var(--encre-1); font: inherit;
  background: #f6eedb; border: 1.5px solid var(--wood-1); border-radius: 14px;
  box-shadow: 0 6px 18px rgba(90, 60, 20, 0.18);
}
.hub-feuille .hub-une-bg { display: block; width: 100%; height: 136px; object-fit: cover; }
.hub-feuille .hub-une-txt { display: block; padding: 12px 64px 13px 14px; }
.hub-une-t { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.hub-une-t b { font-family: var(--display); font-size: 1.2rem; font-weight: 900; line-height: 1.15; }
.hub-feuille .hub-tag {
  margin: 0; padding: 2px 9px; border-radius: 999px; letter-spacing: 0;
  font-size: 0.7rem; font-weight: 700; color: #3c5a2e; background: #d9e3c4;
}
.hub-feuille .hub-une p {
  margin: 4px 0 6px; font-size: 0.88rem; line-height: 1.3; color: var(--encre-2);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.hub-feuille .hub-une small { display: flex; align-items: center; gap: 6px; font-size: 0.82rem; color: var(--encre-2); }
.hub-feuille .hub-une small svg { width: 15px; height: 15px; color: var(--encre-3); }
.hub-feuille .hub-une .hub-fleche {
  position: absolute; right: 12px; bottom: 14px; width: 42px; height: 42px;
  color: #fff; background: var(--sapin); border: 0; box-shadow: 0 3px 8px rgba(0, 0, 0, 0.25);
}
.hub-feuille .hub-dots i { background: rgba(90, 70, 50, 0.25); }
.hub-feuille .hub-dots i.on { background: var(--sapin); }

/* Les lignes du carnet : lieux proches, journal, reprise. Le meme
   `.hub-ligne` que partout, repeint au papier. */
.hub-rangs { display: grid; gap: 7px; margin-top: 10px; }
.hub-feuille .hub-ligne {
  gap: 12px; margin: 0; padding: 5px 12px 5px 5px; color: var(--encre-1);
  background: rgba(255, 252, 243, 0.62); border: 1px solid var(--filet-papier); border-radius: 12px;
  box-shadow: none;
}
.hub-feuille > .hub-ligne { margin: 0 0 12px; }
.hub-feuille .hub-mini { width: 74px; height: 52px; }
.hub-feuille .hub-mini img { border-radius: 8px; }
.hub-feuille .hub-ligne-txt b { margin-bottom: 2px; font-size: 0.97rem; font-weight: 800; color: var(--encre-1); }
.hub-feuille .hub-ligne-txt i {
  display: flex; align-items: center; gap: 6px; font-style: normal; font-size: 0.8rem; color: var(--encre-2);
}
.hub-feuille .hub-ligne-txt i svg { width: 14px; height: 14px; color: var(--encre-3); flex: none; }
.hub-feuille .hub-chev { width: 16px; height: 16px; color: var(--encre-3); flex: none; }
.hub-feuille .hub-ligne .hub-fleche { background: var(--sapin); color: #fff; border: 0; }
.hub-feuille .hub-ligne .hub-fleche.outil img { filter: brightness(0) invert(1); }
.hub-sans-reseau {
  display: block; margin-top: 3px; cursor: pointer;
  font-size: 0.74rem; font-weight: 800; color: #9a5a1c;
}

/* Un titre du carnet : l'icone, le mot, et un trait qui file vers la marge. */
.hub-feuille-rub {
  display: flex; align-items: center; gap: 10px; margin: 26px 2px 2px;
  font-family: var(--display); font-size: 1.2rem; font-weight: 900; color: var(--encre-1);
}
.hub-feuille-rub svg { width: 24px; height: 24px; color: var(--encre-2); flex: none; }
.hub-feuille-rub::after {
  content: ''; flex: 1; height: 1px; margin-left: 6px;
  background: linear-gradient(90deg, rgba(90, 70, 50, 0.45), transparent);
}

.hub-createurs { display: flex; gap: 8px; overflow-x: auto; margin: 10px -18px 0; padding: 0 18px 4px; }
.hub-createur {
  flex: none; display: flex; align-items: center; gap: 9px; padding: 5px 14px 5px 5px; cursor: pointer;
  text-align: left; color: var(--encre-1);
  background: rgba(255, 252, 243, 0.62); border: 1px solid var(--filet-papier); border-radius: 999px;
}
.hub-createur .hub-face { width: 36px; height: 36px; margin: 0; border-width: 1.5px; box-shadow: none; }
.hub-createur b { display: block; font-size: 0.86rem; }
.hub-createur i { display: block; font-style: normal; font-size: 0.74rem; color: var(--encre-2); }

.hub-tuiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); gap: 8px; margin-top: 10px; }
.hub-tuile {
  display: grid; justify-items: center; gap: 6px; padding: 13px 6px 11px; cursor: pointer;
  font: inherit; font-size: 0.82rem; font-weight: 800; text-align: center; color: var(--encre-1);
  background: rgba(255, 252, 243, 0.62); border: 1px solid var(--filet-papier); border-radius: 12px;
}
.hub-tuile svg { width: 24px; height: 24px; color: var(--encre-2); }

.hub-amis {
  display: flex; align-items: center; gap: 12px; width: 100%; margin-top: 18px; padding: 12px 14px;
  cursor: pointer; text-align: left; font: inherit; font-size: 0.85rem; color: var(--encre-2);
  background: none; border: 1px dashed rgba(120, 88, 50, 0.45); border-radius: 12px;
}
.hub-amis > svg { width: 22px; height: 22px; color: var(--encre-2); flex: none; }
.hub-amis b { color: var(--sapin); white-space: nowrap; }
.hub-amis-faces { display: flex; flex: none; padding-left: 8px; }
.hub-amis-faces img {
  width: 32px; height: 32px; margin-left: -8px; border-radius: 50%; object-fit: cover;
  border: 2px solid var(--papier-1);
}
.hub-feuille .hub-vide b { color: var(--encre-1); }
.hub-feuille .hub-vide p { color: var(--encre-2); }

/* La page des conseils et des questions : un titre et son retour, sans
   couverture — elle s'ouvre par sa tuile, au bas du carnet. */
.hub-savoir-tete { display: flex; align-items: center; gap: 12px; margin: 2px 0 6px; }
.hub-savoir-tete .hub-retour { position: static; flex: none; }
.hub-savoir-tete h2 { margin: 0; font-family: var(--display); font-size: 1.3rem; color: var(--gold); }

/* « Jouer » se dit sous le rond : un drapeau seul ne disait pas qu'il sert a
   entrer le code d'une aventure. */
.tab.boussole { gap: 2px; }

/* ------------------------------------------- tout le hub en papier (2.113.1)

   LE CARNET NE S'ARRETE PAS A L'ACCUEIL. Une page de lieu, une fiche de
   parcours, un cartographe, le profil, les amis, l'espace du cartographe :
   tout ce que le hub montre derriere l'accueil s'ecrit sur la meme feuille.
   La couverture reste une photo, et la feuille monte dessus avec ses coins
   ronds ; une page sans couverture commence sous une bande de foret.

   PAR LES VARIABLES, PAS PAR LES REGLES. Les planches du hub disent toutes
   `var(--bois-grad)`, `var(--wood-1)`, `var(--gold)`, `var(--parchment)` :
   on les redefinit sur la feuille, et les deux cents regles qui s'en servent
   passent au papier sans etre reecrites — le mecanisme meme des themes
   (docs/themes.md). Ne restent ici que les couleurs ecrites en dur ailleurs.
   Le jeu, lui, n'est pas sous `#screen-hub` : il reste en bois. */
#screen-hub.sous-page #hub-body, .hub-feuille {
  --bois-1: #fbf6ea; --bois-2: #f6efdf; --bois-3: #f1e8d4;
  --bois-grad: linear-gradient(180deg, rgba(255, 252, 243, 0.82), rgba(252, 246, 232, 0.7));
  --wood-1: var(--filet-papier); --wood-2: var(--filet-papier);
  --parchment: var(--encre-1); --parch: var(--encre-1);
  --parch-dim: var(--encre-2); --parch-faint: var(--encre-3);
  --gold: #5e4219; --gold-deep: #9a7a40;
  /* LE VERT DES ETATS, FONCE POUR LE PAPIER : le vert clair des pictos
     etait pense pour le bois sombre, et se perdait sur le clair. */
  --moss: #2e7a3e; --moss-soft: #2e6e38; --moss-deep: #2a6b38;
  --shadow-1: none; --shadow-2: 0 4px 14px rgba(90, 60, 20, 0.12);
  color: var(--encre-1);
}
#screen-hub.sous-page #hub-body {
  position: relative;
  margin: 0 -16px calc(-1 * (var(--nav-h, 64px) + 28px + var(--safe-bot)));
  padding: 18px 16px calc(var(--nav-h, 64px) + 44px + var(--safe-bot));
  min-height: calc(100vh - var(--safe-top) - 18px);
  border-radius: 26px 26px 0 0;
  background:
    radial-gradient(120% 40% at 10% 0%, rgba(255, 250, 235, 0.7), transparent 60%),
    linear-gradient(180deg, var(--papier-1), var(--papier-2));
  box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.35);
}
/* La couverture remonte jusqu'en haut de l'ecran : la feuille commence
   donc sous elle, et la fiche qui la chevauchait devient le haut arrondi
   de la feuille. */
#screen-hub.sous-page #hub-body:has(> .hub-couv) { padding-top: 0; }
#screen-hub.sous-page #hub-body > .hub-couv { margin-top: calc((var(--safe-top) + 18px) * -1); }
#screen-hub.sous-page #hub-body > .hub-couv + .hub-fiche {
  margin: -28px -16px 6px; padding-left: 18px; padding-right: 18px;
  border: 0; border-radius: 26px 26px 0 0; box-shadow: none;
  background: linear-gradient(180deg, var(--papier-1), var(--papier-1));
}
/* Les cadres : un filet, plus trois pixels d'or. */
#screen-hub.sous-page #hub-body .panel, #screen-hub.sous-page #hub-body .bois,
#screen-hub.sous-page #hub-body .hub-ligne { border-width: 1px; box-shadow: none; }
/* Les boutons ordinaires ont leur brun ecrit en dur (base.css) : ils
   passent au papier ici. Le bouton d'action reste vert. */
#screen-hub.sous-page #hub-body .btn:not(.primary):not(.danger) {
  background: rgba(255, 252, 243, 0.85); border-color: rgba(120, 88, 50, 0.35);
  color: var(--encre-1); box-shadow: none;
}
#screen-hub.sous-page #hub-body input:not([type="checkbox"]):not([type="radio"]),
#screen-hub.sous-page #hub-body textarea, #screen-hub.sous-page #hub-body select {
  color: var(--encre-1); background: rgba(255, 253, 247, 0.9);
  border-color: rgba(120, 88, 50, 0.32); box-shadow: inset 0 1px 3px rgba(90, 60, 20, 0.12);
}
#screen-hub.sous-page #hub-body input::placeholder { color: var(--encre-3); }
#screen-hub.sous-page #hub-body .hub-retour { color: #fff; }
#screen-hub.sous-page #hub-body .hub-fleche { border-width: 1px; box-shadow: none; }
/* La feuille, sans tache de ton : le haut est uni, la fiche qui chevauche la
   couverture est de la meme couleur. */
#screen-hub.sous-page #hub-body {
  background: linear-gradient(180deg, var(--papier-1) 0, var(--papier-1) 1100px, var(--papier-2) 100%);
}
#screen-hub.sous-page #hub-body .hub-meta.grande li {
  background: rgba(255, 252, 243, 0.85); border-color: var(--filet-papier);
}
#screen-hub.sous-page #hub-body .hub-compte {
  margin: 18px 0 0; background: rgba(255, 252, 243, 0.62); border: 1px solid var(--filet-papier);
}
/* La phrase d'un cartographe : une citation courte, pas une page manuscrite. */
.hub-bio { font-family: var(--sans); font-style: italic; font-size: 0.86rem; line-height: 1.45; color: var(--parch-dim); }
.hub-createur-n { margin: 12px 0 0; }
.hub-desc.replie { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }
.hub-lire { margin: 4px 0 2px; font-size: 0.8rem; font-weight: 800; color: var(--sapin); }
.hub-profil-neuf { margin: 4px 6px 10px; }
.hub-profil-go { margin: 0 auto 2px; }

/* ------------------------------------------------ Explorer en papier (2.113.1)

   La meme feuille que l'accueil, sous une bande de foret ; la planche qui
   trie s'efface (la feuille la porte deja), et les creux sombres de la
   recherche et des modes deviennent des champs clairs. */
.monde-feuille {
  --bois-1: #fbf6ea; --bois-2: #f6efdf; --bois-3: #f1e8d4;
  --bois-grad: linear-gradient(180deg, rgba(255, 252, 243, 0.82), rgba(252, 246, 232, 0.7));
  --wood-1: var(--filet-papier); --wood-2: var(--filet-papier);
  --parchment: var(--encre-1); --parch: var(--encre-1);
  --parch-dim: var(--encre-2); --parch-faint: var(--encre-3);
  --gold: #5e4219; --gold-deep: #9a7a40; --moss-soft: #3f7a46; --moss: #2f7a42;
  --shadow-1: none; --shadow-2: 0 4px 14px rgba(90, 60, 20, 0.12);
  position: relative; color: var(--encre-1);
  margin: 0 -16px calc(-1 * (var(--nav-h, 64px) + 28px + var(--safe-bot)));
  padding: 18px 16px calc(var(--nav-h, 64px) + 44px + var(--safe-bot));
  min-height: calc(100vh - var(--safe-top) - 18px);
  border-radius: 26px 26px 0 0;
  background: linear-gradient(180deg, var(--papier-1) 0, var(--papier-1) 1100px, var(--papier-2) 100%);
  box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.35);
}
.monde-feuille .monde-barre { padding: 0; margin: 0 0 6px; background: none; border: 0; box-shadow: none; }
.monde-feuille .monde-barre .monde-search input,
.monde-feuille .monde-barre .mode-filtre button {
  background: rgba(255, 253, 247, 0.9); color: var(--encre-1);
  border-color: rgba(120, 88, 50, 0.3); box-shadow: none;
}
.monde-feuille .monde-barre .mode-filtre button.on {
  background: color-mix(in srgb, var(--md-teinte, var(--gold)) 22%, #fffaf0);
  border-color: color-mix(in srgb, var(--md-teinte, var(--gold)) 60%, transparent);
}
.monde-feuille .monde-card, .monde-feuille .bois, .monde-feuille .panel { border-width: 1px; box-shadow: none; }
.monde-feuille .monde-tag.or { background: rgba(90, 70, 50, 0.1); }
.monde-vues {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 4px; margin: 0 0 8px; padding: 4px;
  border-radius: 14px; background: rgba(90, 70, 50, 0.08); border: 1px solid var(--filet-papier);
}
.monde-vue {
  display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 7px 2px; border: 0; border-radius: 10px;
  background: none; cursor: pointer; font: inherit; font-size: 0.68rem; font-weight: 800; color: var(--encre-2);
  white-space: nowrap;
}
.monde-vue svg { width: 19px; height: 19px; }
.monde-vue.on { background: #fffaf0; color: var(--sapin); box-shadow: 0 1px 4px rgba(90, 60, 20, 0.18); }

/* LES PICTOS DU SOCIAL SUR LE PAPIER (2.113.2). Leurs ronds etaient creuses
   de noir a 22-30 % : sur le bois, une empreinte ; sur le papier, une tache
   grise sous un picto vert, illisible. Ils deviennent des ronds clairs, filet
   vert, picto vert fonce. Les titres perdent l'ombre portee qui les
   detachait du bois et ne faisait que les brouiller ici. */
#screen-hub.sous-page #hub-body .so-rond-ic,
#screen-hub.sous-page #hub-body .so-sans-ic {
  background: #fffaf0; border-color: rgba(46, 122, 62, 0.45); color: var(--moss);
}
#screen-hub.sous-page #hub-body .so-jauge,
#screen-hub.sous-page #hub-body .so-seg,
#screen-hub.sous-page #hub-body .so-conf-onglets,
#screen-hub.sous-page #hub-body .so-cran { background: rgba(90, 70, 50, 0.1); }
#screen-hub.sous-page #hub-body .so-entete-t h2,
#screen-hub.sous-page #hub-body .so-moncode-id > b,
#screen-hub.sous-page #hub-body .so-grandcode { text-shadow: none; }

/* Les rubriques d'Amis et du Cartographe, en tete de la feuille (2.113.3) :
   la rangee d'Explorer, avec la pastille de ce qui attend et le cadenas
   d'une rubrique qui demande un rang. */
.hub-vues { margin: 0 0 12px; }
.monde-vue { position: relative; }
.hub-vue-bulle {
  position: absolute; top: 3px; right: calc(50% - 20px); min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 8px; background: var(--ember); color: #fff; font: 800 10px/16px var(--sans); font-style: normal;
}
.monde-vue.ferme { opacity: 0.55; }
/* Les quatre vues de la Communaute (Statistiques, Carnet, Avis, Popularite)
   etaient une planche sombre a pilule d'or au milieu du papier : la meme
   rangee claire que les rubriques (2.113.3). */
#screen-hub.sous-page #hub-body .monde-tabs.sous {
  padding: 4px; gap: 4px; border-radius: 14px; box-shadow: none;
  background: rgba(90, 70, 50, 0.08); border: 1px solid var(--filet-papier);
}
#screen-hub.sous-page #hub-body .monde-tabs.sous .monde-tab {
  background: none; border: 0; color: var(--encre-2); font-weight: 800; box-shadow: none;
}
#screen-hub.sous-page #hub-body .monde-tabs.sous .monde-tab.on {
  background: #fffaf0; color: var(--sapin); box-shadow: 0 1px 4px rgba(90, 60, 20, 0.18);
}
/* Les pictos de meta (etoile, boussole, sentier) sont des silhouettes
   claires a ombre portee, faites pour le bois : sur le papier, de l'encre. */
#screen-hub.sous-page #hub-body .hub-ic, .hub-feuille .hub-ic, .monde-feuille .hub-ic {
  filter: brightness(0) opacity(0.62);
}

/* Les peintures du profil (2.113.5) : une vignette par rangee, un bandeau en
   tete du carnet de marche et du compte. */
.hub-conf { padding: 8px 12px 8px 8px; font-family: var(--sans); }
.hub-conf-illu {
  flex: none; width: 84px; height: 56px; border-radius: 10px;
  background: var(--illu) center / cover no-repeat, #2b2116;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}
.hub-bandeau {
  display: block; height: 96px; margin: 0 0 10px; border-radius: 12px;
  background: var(--illu) center / cover no-repeat, #2b2116;
}
.hub-conf-txt b, .hub-conf-txt i { display: block; white-space: normal; overflow-wrap: anywhere; }
.hub-conf-txt i { line-height: 1.3; margin-top: 1px; }
/* `.hub-conf > span { flex: none }` (social.css) visait l'icone, et figeait
   aussi le texte a sa largeur : il debordait au lieu de passer a la ligne. */
.hub-conf > .hub-conf-txt { flex: 1 1 auto; min-width: 0; }
/* LE CARRE D'OUTILS GARDE SON BOIS (2.113.6). Son picto est une silhouette
   blanche : sur la feuille, le bouton passait au papier et l'outil
   disparaissait, blanc sur blanc. Il reste la piece de bois sombre du
   cartographe — sur la page d'un lieu comme sur la fiche d'un parcours. */
#screen-hub.sous-page #hub-body .btn.hub-editer:not(.primary):not(.danger) {
  background: linear-gradient(180deg, #5a4327, #35261a);
  border-color: rgba(201, 164, 104, 0.6); box-shadow: 0 2px 6px rgba(60, 40, 15, 0.3);
}
