/* =============================================================================
   game.css — Flora
   Direction « Contre-jour » : la coque est INVERSÉE. L'en-tête, la ligne
   d'objectif et la barre d'actions forment un socle graphite chaud ; les
   ressources, le comptoir et le jardin vivent sur une « planche » claire posée
   dessus, à coins supérieurs arrondis. La hiérarchie vient du renversement
   fond/figure, pas d'une ombre portée.

   Ce n'est PAS un mode sombre : un seul jeu de jetons, `color-scheme: light`.
   La couleur reste une seule source de sens — la teinte réelle de l'infusion
   de chaque plante, déclarée dans data/plants_db.json.

   Aucun dégradé décoratif, aucune ombre portée décorative. L'air et les filets
   font le travail — la seule ombre du jeu est fonctionnelle, sous la croix des
   feuilles, et elle l'empêche de percer un trou dans la carte qui défile
   dessous. Mobile-first : cibles tactiles >= 44 px, rien qui dépende du survol.
   ============================================================================= */

/* ==================== JETONS ====================
   Toute couleur du jeu passe par un jeton. Changer de direction artistique
   = réécrire ce bloc, rien d'autre.
   ========================================================================= */

:root {
    color-scheme: light;

    /* Surfaces — la planche claire posée sur le socle */
    --porcelaine:   #FAF8F2;   /* fond de PLANCHE (anciennement fond de page) */
    --surface:      #FFFFFF;   /* cartes, cases en pousse — et le blanc des mélanges (color-mix) */
    --surface-sourd:#F1EDE1;   /* creux : case vide, ligne de tableau */

    /* Encres — sur planche, et toutes sur l'axe CHAUD. Les encres d'avant
       tiraient vers le bleu-ardoise : c'était une cause directe de l'effet
       « plat », deux familles de gris qui se contrariaient sur la même page.
       Ratios sur la porcelaine, relevés par le handoff. */
    --encre:        #1F211B;   /* texte principal                 15,3 */
    --encre-2:      #4A453B;   /* texte secondaire                 8,9 */
    --encre-3:      #6B6659;   /* intitulés, mentions              5,4 */
    --encre-4:      #8B8574;   /* NON TEXTUEL                      3,5 */
    /* La règle de partage entre les deux dernières, à ne pas confondre :
       --encre-3 pour tout TEXTE qui informe, si petit soit-il — le prix sous
       « Semer », le PLANTER d'une case vide, la description d'un succès qu'on
       n'a pas encore. --encre-4 pour ce qui ne se lit pas ou ne se touche pas :
       un bouton désactivé, une icône, un filet, un aplat. 3:1 suffit à un objet
       graphique ; il ne suffit pas à une phrase de 10 px. Si un LIBELLÉ a
       vraiment besoin de cette clarté-là, le handoff donne #757060 (4,7:1). */

    /* Filets */
    --filet:        #E4DFD1;
    --filet-fort:   #CFC8B6;

    /* Accent — marque UNIQUEMENT ce qui attend le joueur, une chose à la fois */
    --accent:       #33583F;
    --accent-fonce: #274531;
    --accent-voile: #EDF4ED;
    --accent-filet: #8FB897;
    --sur-accent:   #FAF8F2;
    --accent-sur-voile:  #2E5039;   /* l'accent posé SUR son voile : bouton de barre en attente, sortie après verdict */
    --accent-voile-fort: #E2ECE3;   /* le voile d'accent un cran plus dense : cette sortie au survol */

    /* Rôles */
    --or:           #8A6220;   /* monnaie                          5,1 */
    --or-voile:     #FCF6E3;
    --alerte:       #9B4633;   /* terre cuite, jamais de rouge vif  6,0 */

    /* Rayons — un cran plus généreux : les cases ne sont plus des champs de
       formulaire. */
    --r-xs: 4px;
    --r-sm: 8px;
    --r:    12px;
    --r-lg: 18px;

    /* Typographies — piles système, aucune dépendance réseau */
    --serif: 'Iowan Old Style', 'Palatino Linotype', Palatino, 'Book Antiqua',
             Georgia, 'Times New Roman', serif;
    --sans:  -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
             'Helvetica Neue', Arial, sans-serif;
    --mono:  ui-monospace, 'Cascadia Mono', 'Segoe UI Mono', 'SF Mono',
             Consolas, monospace;

    /* Planches botaniques : la densité du lavis sous l'encre. Un jeton et non
       une valeur dans la règle, parce que la carte de partage le LIT pour
       dessiner la même planche au canvas (share.js). */
    --dessin-lavis: 0.7;

    /* Rythme */
    --touch: 44px;
    /* Réglage « Taille du texte » (§11.1). 1 = ce que le système a décidé. */
    --echelle: 1;
    /* La barre du bas grandit MOINS VITE que le texte : ses pictogrammes et ses
       marges sont en pixels, seuls les libellés suivent l'échelle. Tout mettre
       en rem sur-réservait 29 px à l'échelle 1,3, et l'écran débordait de 8 px
       pour de la place vide.
       Part fixe (DA « Contre-jour ») : 12 + 18 de padding de barre, 6 + 6 de
       padding de bouton, 21 d'icône, 4 + 4 de gouttières = 71 px. Part de
       texte : le libellé (0,625rem) et le compteur (0,5625rem). À 16 px de
       base la valeur vaut 90 px, contre 66 avant — les boutons sont devenus
       des cartes et la barre a gagné sa marge basse.
       C'est elle qui pose le bas de la planche : trop courte, une couture
       sombre apparaît entre la planche et la barre. Mesurée, pas déduite. */
    --dock-h: calc(71px + 1.1875rem);

    /* Plans — l'échelle ENTIÈRE des z-index, en un seul endroit, du plus bas au
       plus haut. Les trois premiers sont LOCAUX (dans la jauge d'infusion, dans
       une feuille) ; les autres se comparent entre eux sur la page. */
    --z-jauge-bande:  2;      /* la bande PARFAIT, au-dessus du remplissage */
    --z-jauge-repere: 3;      /* le trait du niveau, au-dessus de tout dans la jauge */
    --z-croix:        5;      /* la croix collante d'une feuille, sur ce qui défile dessous */
    --z-barre:        900;    /* la barre d'actions */
    --z-halo:         1200;   /* l'anneau de l'accompagnement */
    --z-bulle:        1201;   /* sa bulle, juste au-dessus */
    --z-feuille:      1500;   /* une feuille et son voile — le panneau d'infusion en est une, plein écran */
    --z-toasts:       2000;   /* les notifications, au-dessus des feuilles */
    --z-effets:       2400;   /* la couche d'effets, transparente aux clics */
    --z-celebration:  2500;   /* la carte de célébration */
    --z-publicite:    3000;   /* la publicité, devant tout */
}

/* Les jetons du SOCLE. Sept sont nés avec « Contre-jour » — aucun jeton
   existant ne décrivait un fond sombre — et les autres ont été relevés depuis
   des littéraux dispersés dans la feuille, à valeur strictement identique.
   C'est le socle sur lequel la planche est posée — en-tête, ligne d'objectif,
   barre d'actions, et le plein écran de l'infusion. Ils ne servent JAMAIS sur
   la planche, et les encres ne servent jamais sur eux : deux mondes, deux
   jeux de couleurs de texte. */
:root {
    /* Fonds et filets */
    --coque:             #23261F;   /* en-tête, objectif, barre d'actions */
    --coque-2:           #2E322A;   /* bouton d'action au repos */
    --coque-3:           #2A2E26;   /* bouton ÉTEINT, un cran sous le repos (barre, infusion) */
    --coque-fonce:       #1B1E18;   /* panneau d'infusion, voile derrière une modale */
    --coque-creux:       #252923;   /* le creux de la jauge d'infusion */
    --coque-piste:       #34382E;   /* la piste d'objectif, couture entre socle et planche */
    --comptoir-rond:     #3A3E33;   /* le rond derrière le visage, au comptoir */
    --coque-filet:       #3E4238;
    --coque-fonce-filet: #343830;   /* filet sur --coque-fonce : bord de la jauge, bouton éteint */
    --coque-voile:       rgba(27, 30, 24, 0.44);   /* --coque-fonce en voile, derrière une feuille */
    --coque-voile-fort:  rgba(27, 30, 24, 0.72);   /* le même, plus dense, derrière une publicité */

    /* Textes et pictos sur socle, du plus clair au plus éteint */
    --sur-coque:         #F5F2E9;   /* texte sur socle                      13,7 */
    --sur-coque-doux:    #E7E2D4;   /* un cran dessous : phrase d'objectif, gain du verdict */
    --sur-coque-presse:  #E2DED2;   /* le bouton qu'on maintient, enfoncé */
    --dock-texte:        #DCD8CB;   /* libellé et picto d'un bouton de la barre, disponible */
    --comptoir-visage:   #CFCBBE;   /* le visage posé dans son rond */
    --sur-coque-2:       #A8A395;   /* texte secondaire sur socle            6,1 */
    --sur-coque-sourd:   #948F81;   /* compteur d'un bouton de la barre, chevron du comptoir */
    --sur-coque-3:       #8A8578;   /* mentions du panneau d'infusion : chapeau, pourquoi, sortie */
    --sur-coque-inerte:  #6E6A5E;   /* texte et picto d'un bouton éteint */
    --dock-meta-inerte:  #585448;   /* compteur d'un bouton éteint */

    /* Accents sur socle */
    --accent-clair:      #8FBF99;   /* accent lisible sur socle */
    --or-clair:          #D6A64A;   /* l'or du socle — --or n'y tiendrait que 2,3:1 sur --coque-2 */
    --parfait-voile:     rgba(245, 242, 233, 0.14);   /* la bande PARFAIT : --sur-coque en voile */
    --parfait-filet:     rgba(245, 242, 233, 0.55);   /* ses deux bords */
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* 100 % et non 16px : la base est celle que le SYSTÈME a choisie. Le verrou en
   pixels annulait purement et simplement le réglage « grands caractères » du
   téléphone — mesuré, aucun effet quel que soit le réglage. `--echelle` le
   multiplie par-dessus : c'est le réglage « Taille du texte » de l'atelier. */
html {
    font-size: calc(100% * var(--echelle, 1));
    scroll-behavior: smooth;
}

/* Le fond de page est désormais le SOCLE, pas la planche : c'est le
   renversement dont toute la direction dépend. */
body {
    font-family: var(--sans);
    background: var(--coque);
    color: var(--encre);
    min-height: 100vh;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
    -webkit-tap-highlight-color: transparent;
}

/* Les chiffres qui bougent ne doivent jamais faire danser la mise en page. */
.tabulaire { font-variant-numeric: tabular-nums; }

/* Un compteur « a / b » doit se lire dans le MÊME sens dans les huit langues.
   En arabe, « 2009 / 7500 » s'affichait « 7500 / 2009 » : les espaces autour
   du séparateur coupent la chaîne en trois runs que l'algorithme bidi
   réordonne selon la direction du paragraphe. Le joueur lisait donc son
   objectif comme sa progression, et l'inverse. Mesuré en arabe avant et après
   — « 7/9 », sans espaces, ne bougeait pas, ce qui explique que le défaut
   n'ait jamais sauté aux yeux.

   La liste est NOMINATIVE et non `.tabulaire`, qui serait le crochet évident
   et serait faux : deux de ses porteurs sont des chaînes TRADUITES —
   `secret.progress` vaut « Mélanges trouvés : {a} / {b} », des mots, et leur
   imposer `direction: ltr` casserait l'arabe pour de bon. N'entrent ici que
   les éléments qui ne contiennent QUE des chiffres et leur ponctuation. */
.goal-count,
.garden-count,
.dock-meta,
.counter-count,
.collect-count,
.mastery-step-count {
    direction: ltr;
    unicode-bidi: isolate;
}

/* ==================== COQUE ==================== */

/* Colonne pleine hauteur : c'est elle qui permet à la planche de prendre
   `flex: 1` et de descendre jusqu'à la barre d'actions. Plus de padding
   d'inline ici — l'en-tête et l'objectif portent le leur, la planche a sa
   propre marge de 10 px, et le socle doit toucher les deux bords. */
/* Le dégagement du HAUT est celui du système : barre d'état, encoche. Il vit
   ici et non sur `.app-head`, pour que le socle continue de peindre SOUS la
   barre d'état — le graphite va jusqu'au bord de l'écran, seul le contenu
   descend. Sans lui, le titre passait sous l'heure et l'étiquette de rôle
   derrière la batterie : vu sur le téléphone, invisible au navigateur, où
   `env()` vaut zéro. La barre du bas a toujours eu son pendant. */
.app {
    max-width: 520px;
    margin: 0 auto;
    min-height: 100dvh;
    padding: env(safe-area-inset-top, 0px) 0 var(--dock-h);
    display: flex;
    flex-direction: column;
}

/* ==================== EN-TÊTE ==================== */

/* Sur socle : encres claires, jamais les encres de planche.
   Plus de padding vertical, et c'est la MARQUE qui le fournit : le fichier de
   56 px porte environ 19 % de marge interne — un dessin qui n'occupe que 35 %
   de son côté — et son fond #23261F se confond avec le socle. L'en-tête garde
   donc ses 56 px, la hauteur sur laquelle tout le relevé du handoff est
   calculé, et le dessin y fait une vingtaine de pixels d'encre, soit l'échelle
   de l'icône Lucide qu'il remplace.
   Le fichier de 32 px, essayé d'abord, ne rendait que 11 px d'encre à côté
   d'un titre de 19 : une tache, pas une marque. */
.app-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 0 16px;
    color: var(--sur-coque);
}

/* Gouttière de 2 px et non de 9 : la marque porte déjà sa propre marge, et
   les deux s'additionnaient en un trou d'une vingtaine de pixels entre le
   dessin et le titre. `min-width: 0` laisse le titre se rétrécir plutôt que
   pousser l'étiquette de rôle hors de l'écran. */
.brand {
    display: flex;
    align-items: center;
    gap: 2px;
    min-width: 0;
    flex: 1;
}

/* La marque du logo, servie à sa taille native. Aucune couleur ici : le SVG
   porte les siennes (#F5F2E9 pour la tasse, #8FBF99 pour la pousse), et son
   fond #23261F se confond avec le socle.

   La marge NÉGATIVE reprend la marge interne du fichier — le dessin n'occupe
   que 35 % de son côté, il y a donc une dizaine de pixels de vide de chaque
   bord. Sans elle, la marque coûtait 56 px de largeur là où l'icône Lucide en
   coûtait 21, et sur un écran de 360 px le titre n'avait plus la place de
   tenir sur une ligne. On ne redimensionne pas le fichier : on cesse de payer
   pour son vide. */
.brand-mark {
    flex: none;
    display: block;
    width: 56px;
    height: 56px;
    margin-inline: -10px;
}

/* Le titre complet est plus long que « Flora » seul, et il se traduit : il
   tient sur UNE ligne, toujours, et se coupe plutôt que de passer à deux.

   C'est l'en-tête entier qui en dépend — sa hauteur de 56 px est la base de
   tout le relevé de gabarit, et une seconde ligne la faisait passer à 84,
   poussant le reste vers le bas. Mesurer la largeur au navigateur ne suffit
   pas à s'en prémunir : aucune police de la pile serif n'existe sur Android,
   qui retombe sur Noto Serif — plus large que le Georgia d'un poste Windows.
   Le français tenait sur une ligne à 360 px chez moi et passait à deux sur le
   téléphone. `nowrap` rend la hauteur indépendante de la police. */
/* `--titre-plafond` vaut 1 jusqu'au cran par défaut et descend au-delà : le
   titre cesse alors de grandir avec le texte, pour rendre à la pastille de rôle
   la place qu'elle prend (64 → 74 → 102 px). Posé par `applyTextScale()`, avec
   un repli à 1 pour que le CSS reste juste seul — une feuille de style qui
   dépend d'un JavaScript non encore exécuté rendrait un titre à zéro. */
.wordmark {
    font-family: var(--serif);
    font-size: calc(1.1875rem * var(--titre-plafond, 1));
    font-weight: 600;
    letter-spacing: 0.005em;
    line-height: 1.15;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

/* Sous 390 px — le gabarit de référence — le titre descend d'un demi-cran.
   Mesuré dans la VRAIE police de l'appareil (Noto Serif Bold, tirée de
   /system/fonts) sur un écran de 360 : « Le jardin de Flora » demandait
   200 px pour 194 disponibles et « O jardim da Flora » 198 pour 186. La
   coupure par points de suspension est un plancher, pas une mise en page :
   couper le nom du jeu est pire que le défaut qu'elle évite.
   Un cran de `rem`, jamais de `vw` : la taille doit rester celle que le
   système a choisie, multipliée par le réglage du joueur. */
@media (max-width: 389px) {
    .wordmark { font-size: calc(1.0625rem * var(--titre-plafond, 1)); }
}

/* C'est un RÔLE (« Herboriste »), pas une phase de journée : l'or le dit
   mieux qu'une encre grise, et il ne concurrence aucun vert. */
.phase-tag {
    font-family: var(--mono);
    font-size: 0.625rem;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--or-clair);
    white-space: nowrap;
}

/* ==================== OBJECTIF ==================== */

/* La jauge d'objectif est BORD À BORD, et c'est pour cela que le padding
   d'inline descend d'un cran, de `.goal` à `.goal-line` : la phrase et le
   compteur gardent leurs 16 px, la jauge n'en a plus. */
.goal {
    display: flex;
    flex-direction: column;
    gap: 9px;
    padding: 0 0 12px;
}

.goal-line {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 0 16px;
}

.goal-label { font-size: 0.875rem; font-weight: 400; color: var(--sur-coque-doux); }

.goal-count {
    font-family: var(--mono);
    font-size: 0.75rem;
    color: var(--sur-coque-2);
}

/* Sur socle : la piste ne peut plus être un filet de planche.
   Ni marge, ni rayon, et 5 px de haut : elle traverse l'écran d'un bord à
   l'autre, juste au-dessus de la planche. Ce n'est plus une barre de
   progression posée dans une carte, c'est la COUTURE entre le socle et la
   planche — la seule ligne de l'écran qui va d'un bord à l'autre, et elle
   dit où l'un s'arrête et l'autre commence. Un rayon de 99 px l'aurait
   redétachée du bord qu'elle est censée toucher. */
.track {
    height: 5px;
    background: var(--coque-piste);
    overflow: hidden;
}

.track-fill {
    height: 100%;
    width: 0;
    background: var(--accent-clair);
    transition: width 0.6s cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* ==================== LA PLANCHE ====================
   Le fond clair posé sur le socle. `flex: 1` la fait descendre jusqu'à la
   barre d'actions ; ses coins ne sont arrondis qu'en HAUT, le bas disparaît
   sous la barre. C'est le seul ajout de structure de la refonte.
   ========================================================================= */

.planche {
    flex: 1;
    margin-inline: 10px;
    background: var(--porcelaine);
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* ==================== RESSOURCES ====================
   Ni cadre de carte, ni icône : quatre chiffres et quatre intitulés, séparés
   du jardin par un simple filet. Le chiffre passe en serif tabulaire — c'est
   ce qui le distingue d'un compteur d'interface et le rattache au grimoire.
   ========================================================================= */

.stats {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    border-bottom: 1px solid var(--filet);
}

.stat {
    padding: 12px 6px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    min-width: 0;
}

.stat-value {
    font-family: var(--serif);
    font-size: 1.375rem;
    font-weight: 400;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

/* Les pièces sont la seule ressource qu'on DÉPENSE : un cran plus grosses,
   et à l'or, qui est déjà leur couleur partout ailleurs dans le jeu. */
.stat.is-money .stat-value { font-size: 1.5rem; color: var(--or); }

/* Une ressource à zéro n'est pas une information, c'est une absence : elle
   s'efface au lieu de peser autant qu'un stock plein. --encre-4 est ici à sa
   place, un chiffre n'étant pas une phrase de 10 px.
   APRÈS `.is-money`, et à dessein : les deux règles ont la même spécificité,
   donc c'est l'ordre qui tranche — et une bourse vide doit s'éteindre elle
   aussi, sans quoi l'or resterait allumé sur un zéro. */
.stat.is-vide .stat-value { color: var(--encre-4); }

.stat-key {
    font-family: var(--mono);
    font-size: 0.5625rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--encre-3);
    line-height: 1.2;
}

/* ==================== JARDIN ==================== */

.garden {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
    padding-bottom: 14px;
}

.garden-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    padding: 13px 14px 9px;
}

/* « JARDIN » cesse d'être un titre de section serif : sur la planche, le
   serif est réservé aux CHIFFRES (ressources) et aux titres de feuille. Ici
   c'est un intitulé, donc du mono en petites capitales — le même vocabulaire
   que SAVOIR, VILLAGE ou AMÉLIORATIONS dans l'atelier. */
.garden-title {
    font-family: var(--mono);
    font-size: 0.5625rem;
    font-weight: 400;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--encre-3);
}

.garden-count { font-family: var(--mono); font-size: 0.625rem; color: var(--encre-4); }

.garden-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 9px;
    padding: 0 14px;
    align-content: start;
}

/* Le bandeau « growth_boost » est un FRÈRE de la grille, pas un enfant : il
   portait sa marge d'inline par le padding de `.app`, qui n'existe plus — le
   socle doit toucher les deux bords de l'écran. Il la porte donc lui-même,
   et se cale sur la gouttière de la grille. */
#gardenBoost:not(:empty) { padding: 12px 14px 0; }

.garden-slot {
    aspect-ratio: 1;
    border-radius: var(--r);
    border: 1px solid var(--filet);
    background: var(--surface);
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 84px;
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s, transform 0.12s;
}

.garden-slot.empty {
    background: var(--surface-sourd);
    border-style: dashed;
    border-color: var(--filet-fort);
    color: var(--encre-3);
}

.garden-slot.empty:active { transform: scale(0.97); }

.garden-slot.growing { color: var(--encre-3); }

/* La teinte de la plante est injectée en --plante par le rendu. */
.garden-slot.ready {
    background: var(--surface);
    border-color: var(--plante, var(--accent-filet));
    background: color-mix(in srgb, var(--plante, var(--accent)) 7%, var(--surface));
}

.garden-slot.ready:active { transform: scale(0.97); }

.slot-body {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
}

.slot-hint {
    font-size: 0.625rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--encre-3);
}

.slot-tag {
    position: absolute;
    top: 7px;
    inset-inline-start: 7px;
    display: inline-flex;
    opacity: 0.75;
}

.slot-progress {
    position: absolute;
    bottom: 8px;
    font-family: var(--mono);
    font-size: 0.625rem;
    color: var(--encre-3);
    font-variant-numeric: tabular-nums;
}

.slot-bar {
    position: absolute;
    left: 10px;
    right: 10px;
    bottom: 4px;
    height: 2px;
    background: var(--filet);
    border-radius: 99px;
    overflow: hidden;
}

.slot-bar-fill {
    height: 100%;
    background: var(--plante, var(--accent));
    transition: width 0.25s linear;
}

.slot-ready-mark {
    position: absolute;
    top: 7px;
    inset-inline-end: 7px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--plante, var(--accent));
}

/* Les quatre étapes de pousse coexistent, une seule est visible :
   changer d'étape ne recrée aucun SVG. */
.slot-stages .stage-icon { display: none; }
.slot-stages[data-stage="0"] .stage-icon[data-s="0"],
.slot-stages[data-stage="1"] .stage-icon[data-s="1"],
.slot-stages[data-stage="2"] .stage-icon[data-s="2"],
.slot-stages[data-stage="3"] .stage-icon[data-s="3"] { display: inline-flex; }

/* ==================== BARRE D'ACTIONS (dock) ====================
   Ancrée en bas de l'écran : les cinq commandes du jeu restent sous le pouce,
   quelle que soit la longueur de la page.
   ========================================================================= */

.dock {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: var(--z-barre);
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 4px;
    max-width: 520px;
    margin: 0 auto;
    padding: 12px 10px calc(18px + env(safe-area-inset-bottom));
    /* La barre appartient au SOCLE, comme l'en-tête : c'est ce qui referme
       la planche par le bas. Plus de filet — deux matières différentes n'ont
       pas besoin d'un trait pour se distinguer. */
    background: var(--coque);
}

/* Chaque commande devient une CARTE : elle a son fond, son rayon, et c'est le
   fond qui porte l'état. Avant, les cinq boutons étaient transparents et
   seule la couleur du texte les distinguait — sur un socle sombre, cela ne
   suffisait plus à séparer « possible » de « impossible ».
   État par défaut : DISPONIBLE. */
.dock-btn {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    min-height: var(--touch);
    padding: 6px 2px;
    border: 0;
    border-radius: var(--r);
    background: var(--coque-2);
    color: var(--dock-texte);
    font-family: inherit;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, transform 0.1s;
}

/* La taille des cinq pictogrammes vit ici et non sur chaque <i> du HTML :
   lucide.createIcons() pose un <svg width="24" height="24">, et une propriété
   CSS l'emporte sur ces attributs de présentation. */
.dock-btn > svg { flex: none; width: 19px; height: 19px; color: var(--dock-texte); }
.dock-label { font-size: 0.65625rem; letter-spacing: 0.01em; line-height: 1; }
.dock-meta {
    font-family: var(--mono);
    font-size: 0.625rem;
    line-height: 1;
    color: var(--sur-coque-sourd);
    font-variant-numeric: tabular-nums;
}

.dock-btn:not(:disabled):active { transform: scale(0.94); }

/* EN ATTENTE DU JOUEUR — un seul bouton à la fois, garanti par ui.js.
   C'est le renversement du renversement : sur le socle sombre, la chose qui
   attend est la seule CLAIRE. Elle n'a besoin d'aucun badge. */
.dock-btn.is-live {
    background: var(--accent-voile);
    color: var(--accent-sur-voile);
}
.dock-btn.is-live > svg { color: var(--accent-sur-voile); }
.dock-btn.is-live .dock-label { font-weight: 600; }
.dock-btn.is-live .dock-meta { color: var(--accent); font-weight: 500; }

/* Le rappel : l'action attend depuis 45 s et personne ne l'a touchée.
   Un anneau, pas un aplat — le bouton est DÉJÀ vert (`is-live`), et le
   remplir de couleur reviendrait à inventer un second niveau de vert. Ce
   qu'on ajoute n'est pas « c'est possible », c'est « ça attend ».

   Le battement porte le sens, pas l'anneau seul : c'est ce qui attire l'œil
   d'un joueur qui a décroché. Il s'arrête de lui-même quand le joueur touche
   quoi que ce soit, et les deux blocs de réduction des animations (§11.1)
   l'immobilisent — l'anneau, lui, reste visible. */
.dock-btn.is-rappel::after {
    content: '';
    position: absolute;
    inset: 1px;
    border: 2px solid var(--accent-clair);
    border-radius: var(--r);
    pointer-events: none;
    animation: rappel-battement 1.9s ease-in-out infinite;
}

/* Le creux ne descend PAS sous 0,4 : regardé à l'écran, un plancher à 0,25
   faisait disparaître l'anneau un tiers du cycle, et cela se lisait comme un
   clignotement — donc comme une alerte. On veut une respiration.
   Aucune valeur d'opacité hors des images-clés, et c'est voulu : quand les
   animations sont réduites (§11.1), l'animation s'achève en 0,01 ms et
   l'élément retombe sur son style de base, soit un anneau PLEIN et immobile. */
@keyframes rappel-battement {
    0%, 100% { opacity: 0.4; transform: scale(1); }
    50%      { opacity: 1;   transform: scale(1.03); }
}

/* L'anneau se pose TOUJOURS sur le bouton qui attend, donc sur la carte
   claire : --accent-clair y disparaîtrait (1,7:1 sur --accent-voile). Il
   reprend l'accent plein, qui est le vert de la planche. */
.dock-btn.is-live.is-rappel::after { border-color: var(--accent); }

/* INERTE — l'action est impossible. Le fond s'enfonce d'un cran sous celui
   d'un bouton disponible au lieu de disparaître : une commande éteinte reste
   une commande, et le joueur doit voir qu'elle existe. */
.dock-btn:disabled { background: var(--coque-3); color: var(--sur-coque-inerte); cursor: default; }
.dock-btn:disabled > svg { color: var(--sur-coque-inerte); opacity: 1; }
.dock-btn:disabled .dock-meta { color: var(--dock-meta-inerte); }

/* Le filet qui séparait Atelier des quatre autres n'a plus d'objet : la
   gouttière de 4 px et les fonds de carte le font mieux que lui. */

/* La pastille se cale désormais sur le COIN de la carte, et non plus sur le
   milieu du bouton par un `calc(50% - 17px)` : le bouton a un fond, donc un
   coin, et une pastille accrochée à un bord se lit tout de suite comme une
   marque posée dessus. L'ancien calage la mettait au-dessus de l'icône, où
   elle avait l'air d'en faire partie.

   Elle est en or et non en vert : le vert de l'écran de jeu appartient à
   l'action qui attend, et Atelier n'est jamais cette action-là. --or serait
   trop sombre sur --coque-2 (2,3:1), d'où l'or clair du socle. */
.dock-dot {
    position: absolute;
    inset-block-start: 9px;
    inset-inline-end: 16px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--or-clair);
}

/* ==================== SECTIONS DE L'ATELIER ==================== */

.sheet-section { margin-bottom: 20px; }

.sheet-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 9px;
    font-size: 0.6875rem;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--encre-3);
}

.sheet-head > svg { color: var(--encre-4); }

/* Le « i » d'une rubrique. Il reste petit à l'œil mais sa zone tactile fait
   44 px : le remplissage l'étend, les marges négatives l'empêchent de faire
   grandir l'intitulé. Sans quoi il aurait fallu choisir entre un titre gonflé
   et une cible que le pouce rate. */
.sheet-info {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* 13 px d'icône + 2 × 16 px = 45 px de cible : mesuré, 14 px de remplissage
       n'en donnaient que 41 et passaient sous la règle des 44. */
    padding: 16px;
    margin: -16px -16px -16px -3px;
    border: 0;
    background: none;
    color: var(--encre-4);
    cursor: pointer;
}

.sheet-info:hover { color: var(--accent); }
.sheet-info > svg { color: inherit; }

/* L'explication elle-même : du texte suivi, pas une étiquette. */
.section-info {
    font-size: 0.84375rem;
    line-height: 1.6;
    color: var(--encre-2);
    margin: 14px 0 18px;
}

.sheet-list { display: flex; flex-direction: column; gap: 7px; }

.link-row {
    display: flex;
    align-items: center;
    gap: 11px;
    width: 100%;
    min-height: var(--touch);
    padding: 11px;
    border: 0;
    border-radius: var(--r-sm);
    background: var(--surface-sourd);
    color: inherit;
    font-family: inherit;
    font-size: 0.8125rem;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
}

.link-row > svg:first-child { color: var(--accent); flex: none; }
.link-row .link-meta { margin-inline-start: auto; font-family: var(--mono); font-size: 0.6875rem;
                       color: var(--encre-3); font-variant-numeric: tabular-nums; }

.settings-row { display: flex; flex-wrap: wrap; gap: 6px; }

.settings-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: var(--touch);
    padding: 0 13px;
    border: 1px solid var(--filet);
    border-radius: 99px;
    background: transparent;
    color: var(--encre-2);
    font-family: inherit;
    font-size: 0.78125rem;
    cursor: pointer;
    transition: border-color 0.2s, color 0.2s;
}

.settings-btn:hover { border-color: var(--filet-fort); color: var(--encre); }
.settings-btn.is-danger:hover { border-color: var(--alerte); color: var(--alerte); }

.row-card {
    display: flex;
    flex-direction: column;
    gap: 9px;
    padding: 10px 11px;
    background: var(--surface-sourd);
    border-radius: var(--r-sm);
}

.row-top { display: flex; align-items: center; gap: 11px; }

.row-icon {
    flex: none;
    width: 34px;
    height: 34px;
    border-radius: var(--r-sm);
    background: var(--surface);
    border: 1px solid var(--filet);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--accent);
}

.row-main { flex: 1; min-width: 0; }
.row-name { font-size: 0.8125rem; font-weight: 500; }
.row-note { font-size: 0.6875rem; color: var(--encre-3); }

.buy-button {
    flex: none;
    min-height: var(--touch);
    padding: 0 14px;
    border: 1px solid var(--accent);
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--accent);
    font-family: var(--mono);
    font-size: 0.75rem;
    font-weight: 500;
    cursor: pointer;
    font-variant-numeric: tabular-nums;
    transition: background 0.2s, color 0.2s;
}

.buy-button:not(:disabled):hover { background: var(--accent); color: var(--sur-accent); }

/* Un prix : le picto de pièces remplace le symbole monétaire, qui n'aurait
   pas le même sens d'un pays à l'autre. */
/* La pièce est l'unité : c'est elle qui dit que le nombre est un prix, le jeu
   n'écrivant ni symbole ni devise. Elle était à 12 px sous 70 % d'opacité et
   se lisait comme une tache — elle porte trop de sens pour être un ornement. */
.price { display: inline-flex; align-items: center; gap: 5px; }

.buy-button:disabled {
    border-color: var(--filet-fort);
    color: var(--encre-4);
    cursor: not-allowed;
}

.row-timer { display: flex; flex-direction: column; gap: 5px; }

.row-timer-line {
    display: flex;
    justify-content: space-between;
    font-family: var(--mono);
    font-size: 0.625rem;
    color: var(--encre-3);
    font-variant-numeric: tabular-nums;
}

.mini-track { height: 2px; background: var(--filet); border-radius: 99px; overflow: hidden; }
.mini-track-fill { height: 100%; background: var(--accent); }

.panel-empty { font-size: 0.75rem; color: var(--encre-3); padding: 4px 0; }

/* ==================== NOTIFICATIONS ====================
   Juste au-dessus de la barre d'actions, jamais devant elle.
   ========================================================================= */

#notificationContainer {
    position: fixed;
    left: 12px;
    right: 12px;
    bottom: calc(var(--dock-h) + env(safe-area-inset-bottom) + 10px);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    z-index: var(--z-toasts);
    pointer-events: none;
}

.toast {
    display: flex;
    align-items: center;
    gap: 9px;
    max-width: 400px;
    padding: 10px 14px;
    background: var(--encre);
    color: var(--porcelaine);
    border-radius: 99px;
    font-size: 0.8125rem;
    animation: toast-in 0.24s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.toast > svg { flex: none; opacity: 0.85; }
.toast.is-error { background: var(--alerte); }

@keyframes toast-in {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes toast-out {
    to { opacity: 0; transform: translateY(6px); }
}

/* ==================== MODALES ==================== */

/* Le voile est celui du SOCLE (--coque-voile, dérivé de --coque-fonce), pas de
   l'encre. Les trois voiles du jeu étaient écrits en dur d'après l'ancienne
   --encre : ils n'auraient donc pas suivi la réécriture des jetons, et une
   modale se serait ouverte sur un voile brun devant un socle graphite. */
.modal-overlay {
    position: fixed;
    inset: 0;
    background: var(--coque-voile);
    z-index: var(--z-feuille);
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding: 0;
    animation: fade-in 0.2s;
}

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

.modal-content {
    background: var(--porcelaine);
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    padding: 24px 20px calc(20px + env(safe-area-inset-bottom));
    width: 100%;
    max-width: 520px;
    max-height: 88vh;
    overflow-y: auto;
    animation: sheet-up 0.26s cubic-bezier(0.22, 0.61, 0.36, 1);
}

@keyframes sheet-up {
    from { transform: translateY(24px); opacity: 0; }
    to   { transform: translateY(0); opacity: 1; }
}

@media (min-width: 560px) {
    .modal-overlay { align-items: center; padding: 20px; }
    .modal-content { border-radius: var(--r-lg); max-height: 84vh; }
}

/* ==================== LA CROIX DE FERMETURE ====================
   La barre ne fait AUCUNE hauteur : elle ne décale pas d'un pixel les vingt
   feuilles qui existaient avant elle, et la croix déborde vers le bas dans le
   coin. `sticky` parce que `.modal-content` est le conteneur de défilement —
   posée en flux, la croix serait partie au premier mouvement du doigt, et l'on
   aurait reproduit à l'autre bout le défaut qu'elle corrige.
   ========================================================================= */

.sheet-bar {
    position: sticky;
    top: 0;
    z-index: var(--z-croix);
    height: 0;
    display: flex;
    justify-content: flex-end;
}

/* Le fond opaque est OBLIGATOIRE : le contenu défile dessous, et sans lui le
   chiffre d'une ligne de tableau passerait au travers de la croix.

   Mais un simple disque de porcelaine ne suffit pas — regardé à l'écran, il
   perçait un trou blanc dans la carte, elle-même en `--surface`, et se lisait
   comme un défaut d'affichage plutôt que comme un bouton. Le filet et l'ombre
   très basse le posent AU-DESSUS de la feuille : c'est la seule chose de
   l'interface qui flotte, et il faut que cela se voie. Aucune couleur : le vert
   ne marque que ce qui attend le joueur, et rien ne l'attend dans une sortie. */
.sheet-x {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: var(--touch);
    min-height: var(--touch);
    margin: -6px -4px 0 0;
    border: 1px solid var(--filet);
    border-radius: 99px;
    background: var(--porcelaine);
    box-shadow: 0 1px 4px color-mix(in srgb, var(--encre) 10%, transparent);
    color: var(--encre-2);
    cursor: pointer;
    transition: color 0.2s, background 0.2s, border-color 0.2s;
}

[dir="rtl"] .sheet-x { margin: -6px 0 0 -4px; }

.sheet-x:hover {
    background: var(--surface-sourd);
    border-color: var(--filet-fort);
    color: var(--encre);
}

.modal-title {
    font-family: var(--serif);
    font-size: 1.375rem;
    font-weight: 400;
    display: flex;
    align-items: center;
    gap: 9px;
    margin-bottom: 4px;
    /* La croix flotte dans ce coin : un titre long lui passerait dessous. */
    padding-inline-end: 34px;
}

.modal-sub { font-size: 0.8125rem; color: var(--encre-3); margin-bottom: 18px; }
.modal-section { margin-bottom: 18px; }
.modal-section h3 { font-size: 0.8125rem; font-weight: 500; margin-bottom: 6px; }
.modal-section p, .modal-section li { font-size: 0.8125rem; color: var(--encre-2); }
.modal-section ol, .modal-section ul { padding-inline-start: 18px; display: flex; flex-direction: column; gap: 3px; }

/* Le hors-ligne n'est PAS un palier de la liste des seuils : il vit hors d'elle,
   et ce filet le dit. Il y était en dernière puce, ce qui passait tant que la
   liste était plate ; depuis que chaque seuil porte sa sous-liste, une puce de
   même rang sans sous-liste se lisait comme un cinquième palier amputé. Vu sur
   le téléphone le 17/08/2026, et invisible à toute mesure — rien ne débordait,
   rien n'était coupé, seule la hiérarchie était fausse. */
.help-offline { margin-top: 11px; padding-top: 9px; border-top: 1px solid var(--filet); }

.data-row {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 9px 0;
    border-bottom: 1px solid var(--filet);
    font-size: 0.8125rem;
}

.data-row:last-child { border-bottom: 0; }
.data-row span { color: var(--encre-2); }
.data-row b { font-family: var(--mono); font-weight: 500; font-variant-numeric: tabular-nums; }

/* Le bouton plein d'une feuille, et ses deux jumeaux : la sortie d'une
   publicité (`.ad-close`) et le geste gratuit du dépannage (`.rescue-take`).
   Même action, même habit — déclaré une fois, ici, à la place du premier. */
.modal-close,
.ad-close,
.rescue-take {
    width: 100%;
    min-height: var(--touch);
    border: 1px solid var(--accent);
    border-radius: var(--r);
    background: var(--accent);
    color: var(--sur-accent);
    font-family: inherit;
    font-size: 0.875rem;
    font-weight: 500;
    cursor: pointer;
}

.modal-close { margin-top: 8px; }

.modal-close:hover { background: var(--accent-fonce); border-color: var(--accent-fonce); }

/* Choix de plante */

.plant-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }

.plant-choice {
    position: relative;   /* la pastille de rafale s'ancre dans le coin */
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    padding: 16px 10px 13px;
    border: 1px solid var(--filet);
    border-radius: var(--r);
    background: var(--surface);
    cursor: pointer;
    font-family: inherit;
    transition: border-color 0.2s, background 0.2s;
}

.plant-choice:hover { border-color: var(--plante, var(--accent-filet)); }
.plant-choice > svg { color: var(--plante, var(--accent)); }
.plant-choice .nom { font-size: 0.8125rem; font-weight: 500; }
/* Chrono puis tasse : la ligne dit « pousse en tant de temps, rend tant ».
   Les deux pictos portent le sens, le point médian ne fait que séparer. */
.plant-choice .meta {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-family: var(--mono);
    font-size: 0.65625rem;
    color: var(--encre-3);
}
.plant-choice .meta-part { display: inline-flex; align-items: center; gap: 3px; }
.plant-choice .meta-sep  { color: var(--encre-4); }

/* À quoi sert la plante. En lettres et non en chiffres — c'est justement ce que
   les chiffres ne disaient pas. Ni gras ni couleur : le rôle informe, il ne
   recommande pas, et les deux réponses se valent selon le joueur. */
.plant-choice .role {
    font-size: 0.65625rem;
    line-height: 1.35;
    color: var(--encre-3);
    text-align: center;
    text-wrap: balance;
}

/* Prix à la graineterie, réserve à la plantation : même place, deux lectures. */
.plant-choice .choice-price,
.plant-choice .choice-stock {
    margin-top: 3px;
    font-family: var(--mono);
    font-size: 0.6875rem;
}

.plant-choice .choice-price { color: var(--or); }
.plant-choice .choice-stock { color: var(--accent); }

/* Le voile d'une carte qu'on ne peut plus payer porte sur son CONTENU, non sur
   la carte entière : la pastille de rafale y vit, et c'est justement quand la
   dernière graine vide la bourse qu'il faut pouvoir lire combien on en a pris.
   Un parent à 0,45 aurait multiplié l'opacité de la pastille par la sienne. */
.plant-choice:disabled { cursor: default; }
.plant-choice:disabled > svg,
.plant-choice:disabled > .dessin-plante,
.plant-choice:disabled .nom,
.plant-choice:disabled .meta,
.plant-choice:disabled .role,
.plant-choice:disabled .choice-price,
.plant-choice:disabled .choice-stock { opacity: 0.45; }

/* Rangée de pastilles à choix unique. Elle servait la graineterie — ×1 / ×5 /
   ×10 / Max — jusqu'au 11/08/2026, où la vente est passée à la tape ; il ne
   reste que la taille du texte (`.echelle-row`, plus bas), qui n'en veut que
   trois. Les quatre colonnes restent le défaut : c'est ce qui tient sur une
   ligne en 390 px, 44 px de haut, sans rien devoir au survol. */
.qty-row {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 6px;
    margin-bottom: 10px;
}

.qty-chip {
    min-height: 44px;
    padding: 0 4px;
    border: 1px solid var(--filet);
    border-radius: var(--r);
    background: var(--surface);
    color: var(--encre-2);
    font-family: var(--mono);
    font-size: 0.8125rem;
    cursor: pointer;
    transition: border-color 0.2s, color 0.2s, background 0.2s;
}

/* Même marquage d'état que les interrupteurs de l'atelier : filet d'accent et
   voile, jamais un aplat de couleur — une seule couleur porte du sens ici. */
.qty-chip.is-current {
    border-color: var(--accent-filet);
    background: var(--accent-voile);
    color: var(--encre);
}

/* ==================== TAILLE DU TEXTE (§11.1) ====================
   Trois « A » de tailles croissantes : le réglage se comprend sans savoir lire,
   comme la carte d'accueil. Le libellé existe quand même, pour les lecteurs
   d'écran — un « A » ne s'énonce pas.
   ========================================================================= */

.echelle-row { grid-template-columns: repeat(3, 1fr); }
.echelle-chip { font-family: var(--sans); line-height: 1; }

/* ==================== COMPTEUR DE TAPES (graineterie) ====================
   Une tape, une graine : la pastille dit combien de fois le doigt est tombé sur
   CETTE carte-ci, ×1, ×2, ×3. Elle ne dit pas un état du jeu — la réserve, deux
   lignes au-dessus, s'en charge — elle dit le GESTE.

   D'où l'encre, et ni le vert ni la teinte de la plante. Le vert ne marque que
   ce qui ATTEND le joueur, et rien ne l'attend ici : il vient d'agir. Quant à
   `--plante`, les dix teintes vont de 1,61 à 6,14 contre le blanc — le tilleul
   et la mélisse rendraient un compteur illisible. « Une action possible se
   signale par la couleur, jamais par un badge criard » : celui-ci n'annonce
   aucune action, il accuse réception.
   ========================================================================= */

.choice-taps {
    position: absolute;
    top: 6px;
    inset-inline-end: 6px;   /* l'arabe la veut dans l'autre coin */
    min-width: 24px;
    padding: 2px 6px;
    border-radius: 99px;
    background: var(--encre);
    color: var(--porcelaine);
    font-family: var(--mono);
    font-size: 0.6875rem;
    line-height: 1.45;
    font-variant-numeric: tabular-nums;
    opacity: 0;
    transition: opacity 0.3s;
    pointer-events: none;    /* elle ne doit jamais voler la tape suivante */
}

.choice-taps.is-on { opacity: 1; }

/* Un sursaut à chaque tape : c'est ce qui distingue un « ×3 » qui vient de
   monter d'un « ×3 » posé là depuis une seconde. Les deux blocs de réduction
   des animations (§11.1) l'écrasent d'eux-mêmes — il est purement décoratif,
   le chiffre, lui, s'écrit sans attendre l'image. */
.choice-taps.is-tapped { animation: tap-pop 0.22s ease-out; }

@keyframes tap-pop {
    from { transform: scale(0.55); }
    60%  { transform: scale(1.15); }
    to   { transform: scale(1); }
}

/* Succès */

.achievement-row {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 11px 0;
    border-bottom: 1px solid var(--filet);
}

.achievement-row:last-child { border-bottom: 0; }
.achievement-row > svg { flex: none; color: var(--encre-4); }
.achievement-row.is-done > svg { color: var(--accent); }
.achievement-row .nom { font-size: 0.8125rem; font-weight: 500; }
.achievement-row .desc { font-size: 0.71875rem; color: var(--encre-3); }
.achievement-row .etat { font-family: var(--mono); font-size: 0.625rem; letter-spacing: 0.06em;
                         text-transform: uppercase; color: var(--encre-3); flex: none; }
.achievement-row.is-done .etat { color: var(--accent); }
/* Un succès non acquis est en retrait, pas illisible : c'est là qu'on lit ce
   qu'il reste à faire. Le retrait se joue donc sur --encre-3 (4,6:1) et non
   sur --encre-4, qui est réservée à ce qui ne peut PAS être touché. */
.achievement-row:not(.is-done) .nom,
.achievement-row:not(.is-done) .desc { color: var(--encre-3); }

/* ==================== CÉLÉBRATION ==================== */

.celebration {
    position: fixed;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: var(--z-celebration);
    width: calc(100% - 48px);
    max-width: 300px;
    padding: 26px 22px;
    background: var(--porcelaine);
    border: 1px solid var(--filet-fort);
    border-radius: var(--r-lg);
    text-align: center;
    animation: pop 0.42s cubic-bezier(0.22, 1.2, 0.36, 1);
    /* La carte se pose au milieu de l'écran, pile sur le jardin. Elle annonce,
       elle ne demande rien : le doigt doit la traverser. Les cartes se suivant
       désormais à la file, elles occupent le centre bien plus longtemps —
       intercepter un tap n'était déjà pas souhaitable, ce serait maintenant un
       geste perdu à chaque page restaurée. */
    pointer-events: none;
}

@keyframes pop {
    from { transform: translate(-50%, -50%) scale(0.92); opacity: 0; }
    to   { transform: translate(-50%, -50%) scale(1); opacity: 1; }
}

.celebration-icon { display: flex; justify-content: center; color: var(--accent); margin-bottom: 12px; }
.celebration-kicker { font-family: var(--mono); font-size: 0.625rem; letter-spacing: 0.14em;
                      text-transform: uppercase; color: var(--encre-3); margin-bottom: 6px; }
.celebration-title { font-family: var(--serif); font-size: 1.25rem; font-weight: 400; margin-bottom: 4px; }
.celebration-note { font-size: 0.78125rem; color: var(--encre-2); }

/* ==================== EFFETS ====================
   Couche fixe, transparente aux clics, au-dessus du jeu et des feuilles
   modales. Rien de ce qui s'y joue ne peut décaler la mise en page.
   ========================================================================= */

#effectLayer {
    position: fixed;
    inset: 0;
    z-index: var(--z-effets);
    pointer-events: none;
    overflow: hidden;
}

/* La plante récoltée grossit puis s'efface. */
.fx-pop {
    position: fixed;
    display: flex;
    animation: fx-pop 220ms cubic-bezier(0.34, 1.4, 0.64, 1) forwards;
}

@keyframes fx-pop {
    0%   { transform: translate(-50%, -50%) scale(1);    opacity: 1; }
    45%  { transform: translate(-50%, -50%) scale(1.3);  opacity: 1; }
    100% { transform: translate(-50%, -50%) scale(0.72); opacity: 0; }
}

/* Feuilles qui s'échappent : la trajectoire arrive en --dx/--dy. */
.fx-particle {
    position: fixed;
    display: flex;
    opacity: 0;
    animation: fx-particle 560ms cubic-bezier(0.18, 0.72, 0.3, 1) forwards;
}

@keyframes fx-particle {
    0%   { transform: translate(-50%, -50%) scale(0.5) rotate(0deg); opacity: 0; }
    20%  { opacity: 0.95; }
    100% {
        transform: translate(-50%, -50%) translate(var(--dx), var(--dy))
                   scale(1) rotate(var(--rot));
        opacity: 0;
    }
}

/* Volutes de vapeur d'une infusion réussie : pas de contour, pas d'icône. */
.fx-steam {
    position: fixed;
    width: var(--size, 12px);
    height: var(--size, 12px);
    border-radius: 50%;
    background: var(--encre-4);
    opacity: 0;
    animation: fx-steam 900ms ease-out forwards;
}

@keyframes fx-steam {
    0%   { transform: translate(-50%, 0) scale(0.4); opacity: 0; }
    25%  { opacity: 0.34; }
    100% { transform: translate(-50%, -62px) translateX(var(--drift, 0)) scale(1.5); opacity: 0; }
}

/* Montant qui s'envole du point d'impact. Écrit nu, picto de pièces pour unité. */
.fx-gain {
    position: fixed;
    display: flex;
    align-items: center;
    gap: 4px;
    font-family: var(--mono);
    font-size: 0.9375rem;
    font-weight: 500;
    color: var(--or);
    white-space: nowrap;
    animation: fx-gain 780ms cubic-bezier(0.2, 0.72, 0.3, 1) forwards;
}

@keyframes fx-gain {
    0%   { transform: translate(-50%, 0) scale(0.85);      opacity: 0; }
    18%  { transform: translate(-50%, -12px) scale(1);     opacity: 1; }
    100% { transform: translate(-50%, -50px) scale(1);     opacity: 0; }
}

/* Graine récupérée à la récolte : discrète, elle ne vole pas la vedette. */
.fx-seed {
    position: fixed;
    display: flex;
    align-items: center;
    gap: 3px;
    font-family: var(--mono);
    font-size: 0.75rem;
    white-space: nowrap;
    animation: fx-seed 760ms cubic-bezier(0.2, 0.72, 0.3, 1) forwards;
}

@keyframes fx-seed {
    0%   { transform: translate(-50%, 0) scale(0.7);   opacity: 0; }
    22%  { transform: translate(-50%, -9px) scale(1);  opacity: 0.95; }
    100% { transform: translate(-50%, -34px) scale(1); opacity: 0; }
}

/* Pièces en cloche, du bouton Vendre vers le compteur. */
.fx-coin {
    position: fixed;
    display: flex;
    color: var(--or);
    opacity: 0;
    animation: fx-coin 640ms cubic-bezier(0.36, 0, 0.24, 1) forwards;
}

@keyframes fx-coin {
    0%  { transform: translate(-50%, -50%) scale(0.7); opacity: 0; }
    14% { opacity: 1; }
    55% {
        transform: translate(-50%, -50%)
                   translate(calc(var(--dx) * 0.55), calc(var(--dy) * 0.55 - 30px))
                   scale(1.15);
        opacity: 1;
    }
    100% {
        transform: translate(-50%, -50%) translate(var(--dx), var(--dy)) scale(0.55);
        opacity: 0;
    }
}

/* ==================== LE PANNEAU D'INFUSION ====================
   Le seul moment TENDU du jeu, et le seul qui quitte la planche : plein
   écran sur --coque-fonce. Ce n'est plus une feuille posée sur le jardin, et
   c'est voulu — pendant 1500 ms il n'y a plus rien d'autre à regarder.

   Le mini-jeu : le niveau monte tant que le doigt reste posé. La jauge dure le
   même temps pour toutes les plantes ; seule la hauteur de la zone PARFAIT
   change avec le palier. La teinte vient de la plante la plus fine du panier
   (--plante).
   ========================================================================= */

.brew-overlay {
    position: fixed;
    inset: 0;
    background: var(--coque-fonce);
    z-index: var(--z-feuille);
    display: flex;
    align-items: stretch;
    justify-content: center;
    animation: fade-in 0.16s ease;
}

.brew-panel {
    width: 100%;
    max-width: 520px;
    background: var(--coque-fonce);
    /* Le panneau est plein écran : sans la marge du haut, « Infusion » passait
       sous l'heure sur le téléphone (08/10/2026), comme l'en-tête avant `.app`. */
    padding: calc(18px + env(safe-area-inset-top, 0px)) 22px calc(30px + env(safe-area-inset-bottom));
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    animation: sheet-up 0.24s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.brew-panel.is-shaking { animation: brew-shake 0.16s linear 2; }

@keyframes brew-shake {
    0%, 100% { transform: translateX(0); }
    25%      { transform: translateX(-3px); }
    75%      { transform: translateX(3px); }
}

.brew-kicker {
    align-self: flex-start;
    font-family: var(--mono);
    font-size: 0.625rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--sur-coque-3);
}

/* L'espèce se nomme : serif pour le nom vernaculaire, comme au grimoire, et
   le binôme latin dessous — c'est le seul texte du jeu qui ne se traduit pas. */
.brew-ident {
    margin-block-start: 12px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    text-align: center;
}

.brew-name {
    font-family: var(--serif);
    font-size: 1.75rem;
    font-weight: 600;
    line-height: 1.1;
    color: var(--sur-coque);
}

.brew-latin { font-size: 0.8125rem; font-style: italic; color: var(--sur-coque-2); }

.brew-sub { font-size: 0.75rem; color: var(--sur-coque-2); text-align: center; }

/* Ce que vaut un PARFAIT sur CETTE plante. Le bonus dépend du palier : la règle
   doit être lisible avant de jouer le coup, pas déduite après (§11.2). */
.brew-worth {
    font-family: var(--mono);
    font-size: 0.75rem;
    color: var(--plante, var(--sur-coque-2));
    white-space: nowrap;
}

/* LA JAUGE. Une colonne de 96 px à bouts ronds, et non plus un rectangle de
   76 : c'est un récipient qui se remplit, pas un champ de formulaire.
   La hauteur cède avant de déborder — `min()` la borne à la place réellement
   disponible au cran de texte maximum, où les 372 px nominaux ne tiendraient
   plus sous le nom et au-dessus du bouton. */
.brew-gauge {
    position: relative;
    width: 96px;
    height: min(372px, 44vh);
    margin-block-start: 8px;
    border-radius: 48px;
    background: var(--coque-creux);
    box-shadow: inset 0 0 0 1px var(--coque-fonce-filet);
    overflow: hidden;
}

.brew-zone { position: absolute; left: 0; right: 0; }

/* La zone « bien » ne se montre plus : sur un fond sombre, deux bandes
   concentriques se lisaient comme deux cibles. Une seule est visée. */
.brew-zone.is-good { background: transparent; }

/* La bande PARFAIT — enfant absolu de la piste, en clair translucide plutôt
   qu'à la teinte de l'espèce : le remplissage MONTE à cette teinte, et deux
   objets de même couleur qui se recouvrent ne se distinguent plus au moment
   précis où il faut viser. */
.brew-zone.is-perfect {
    background: var(--parfait-voile);
    border-top: 1px solid var(--parfait-filet);
    border-bottom: 1px solid var(--parfait-filet);
    /* AU-DESSUS du remplissage, et c'est vital : la bande est déclarée avant
       lui dans le DOM (l'ordre dont brewing.js dépend), donc sans cela elle
       passe dessous. Tant que le remplissage était translucide on la voyait
       encore au travers ; devenu un dégradé OPAQUE, il effaçait la cible au
       moment précis où le liquide l'atteint — c'est-à-dire à la seule seconde
       où le joueur en a besoin. Vu à l'écran, jamais par une mesure.
       Le maquettiste avait tranché pareil, en dessinant la bande APRÈS le
       remplissage dans son cadre de verdict. */
    z-index: var(--z-jauge-bande);
}

/* Le niveau d'infusion : un remplissage en dégradé de la teinte de l'espèce,
   surmonté d'un trait net — c'est le trait que l'œil vise, pas le haut du
   remplissage. Le dégradé part clair en haut : c'est ce qui donne le liquide. */
.brew-fill {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 0;
    background: linear-gradient(
        color-mix(in srgb, var(--plante) 55%, var(--surface)),
        var(--plante, var(--accent))
    );
}

/* Au-dessus de tout : c'est LUI qu'on vise, il ne peut passer sous rien. */
.brew-level {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 2px;
    background: var(--porcelaine);
    z-index: var(--z-jauge-repere);
}

/* Le pied du panneau est poussé en bas : la jauge garde sa place quel que
   soit ce que le verdict fait grandir. */
.brew-verdict {
    margin-block-start: auto;
    min-height: 46px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    font-size: 0.8125rem;
    color: var(--sur-coque-2);
    text-align: center;
}

/* Le mot du verdict passe en SERIF 2,5rem : c'est le seul endroit du jeu où
   un mot est l'événement. En mono 0,8125rem il avait le poids d'une mention
   de bas de page, sur l'écran qui vient de juger le geste du joueur. */
.brew-verdict-word {
    font-family: var(--serif);
    font-size: 2.5rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    line-height: 1;
    text-transform: none;
    color: var(--sur-coque);
}

/* Une parfaite se dit à la teinte CLAIRE de l'espèce : c'est elle qu'on vient
   de réussir, et le vert appartient au bouton qui suit. */
.brew-verdict.is-perfect .brew-verdict-word {
    color: color-mix(in srgb, var(--plante) 45%, var(--surface));
}
.brew-verdict.is-miss .brew-verdict-word {
    color: color-mix(in srgb, var(--alerte) 55%, var(--surface));
}

.brew-verdict-gain {
    font-family: var(--mono);
    font-size: 0.75rem;
    letter-spacing: 0.1em;
    color: var(--sur-coque-doux);
}

.brew-verdict-why { font-size: 0.71875rem; color: var(--sur-coque-3); }

.brew-combo {
    font-family: var(--mono);
    font-size: 0.75rem;
    letter-spacing: 0.1em;
    color: var(--accent-clair);
    animation: pop 0.3s cubic-bezier(0.34, 1.5, 0.64, 1);
}

/* Le bouton qu'on MAINTIENT est la seule chose claire du panneau : sur un
   plein écran sombre, c'est le renversement qui désigne le geste, et il n'a
   pas besoin d'être vert pour cela. Il est aussi la cible la plus grosse du
   jeu — 64 px — parce qu'on l'attrape sans regarder, l'œil étant sur la jauge. */
.brew-hold {
    width: 100%;
    min-height: 64px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    background: var(--sur-coque);
    color: var(--encre);
    border: 1px solid var(--sur-coque);
    border-radius: 32px;
    font-family: var(--mono);
    font-size: 0.8125rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    cursor: pointer;
    /* Un appui maintenu ne doit ni sélectionner du texte, ni faire défiler la
       page, ni ouvrir le menu contextuel long-press du mobile. */
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
    touch-action: none;
    transition: transform 0.1s, background 0.15s;
}

.brew-overlay.is-holding .brew-hold {
    transform: scale(0.97);
    background: var(--sur-coque-presse);
    border-color: var(--sur-coque-presse);
}

/* Infusé : le bouton s'éteint DANS le socle au lieu de virer au gris de
   planche, qui faisait une tache claire sur le fond sombre. */
.brew-hold:disabled {
    background: var(--coque-3);
    border-color: var(--coque-fonce-filet);
    color: var(--sur-coque-inerte);
    cursor: default;
}

.brew-quit {
    background: none;
    border: 0;
    font-family: inherit;
    font-size: 0.8125rem;
    color: var(--sur-coque-3);
    padding: 6px 10px;
    min-height: var(--touch);
    cursor: pointer;
}

.brew-quit:hover { color: var(--sur-coque); }

/* Une fois le verdict tombé, « Retour au jardin » N'EST PLUS un abandon : c'est
   la seule chose qui reste à faire, donc l'action. Le vert marque ce qui attend
   le joueur, et ce qui l'attend a changé au moment du verdict.

   Pendant le mini-jeu il reste pâle, et c'est la même règle : l'action est
   alors le bouton qu'on maintient, et deux verts empilés ne diraient plus
   lequel est le geste (§3.2).

   Aucun conflit avec l'offre de doublement : la publicité est DORÉE (--or),
   jamais verte. Le panneau porte donc au plus un vert, quel que soit l'état. */
.brew-quit.is-action {
    width: 100%;
    min-height: 64px;
    border: 1px solid var(--accent-voile);
    border-radius: 32px;
    background: var(--accent-voile);
    color: var(--accent-sur-voile);
    font-family: var(--mono);
    font-size: 0.8125rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
}

.brew-quit.is-action:hover {
    background: var(--accent-voile-fort);
    border-color: var(--accent-voile-fort);
    color: var(--accent-sur-voile);
}

/* ==================== LIGNES D'OPTION ====================
   La LIGNE TACTILE : une carte pleine largeur, un picto, un texte, 44 px sous
   le pouce. Quatre lignes du jeu l'ont en commun — l'interrupteur, la lettre,
   l'entrée du quiz, l'habitant — et ne gardent chacune que ce qui les
   distingue : gouttière, remplissage, filet, rayon. `.lang-card` (grille à
   deux colonnes, 66 px, rayon --r) et `.quiz-option` (un bloc de texte, pas
   une rangée flex) n'en sont pas, malgré l'air de famille.
   Le filet et le rayon restent dans chaque règle, à leur place d'origine :
   trois des quatre sont déclarées APRÈS `:focus-visible`, qui pose un rayon à
   même spécificité, et les remonter ici changerait le bouton au clavier.
   ========================================================================= */

.toggle-row,
.letter-row,
.quiz-start,
.village-card {
    width: 100%;
    display: flex;
    align-items: center;
    min-height: var(--touch);
    background: var(--surface);
    font-family: inherit;
    text-align: start;
    cursor: pointer;
}

.toggle-row {
    gap: 11px;
    padding: 9px 11px;
    border: 1px solid var(--filet);
    border-radius: var(--r-sm);
}

.toggle-row > svg { flex: none; color: var(--encre-4); }
.toggle-row[aria-pressed="true"] { border-color: var(--accent-filet); background: var(--accent-voile); }
.toggle-row[aria-pressed="true"] > svg { color: var(--accent); }

.toggle-text { display: flex; flex-direction: column; min-width: 0; }
.toggle-name { font-size: 0.8125rem; font-weight: 500; color: var(--encre); }
.toggle-desc { font-size: 0.71875rem; color: var(--encre-3); }

/* ==================== PUBLICITÉ (mock) ==================== */

.ad-overlay {
    position: fixed;
    inset: 0;
    background: var(--coque-voile-fort);
    z-index: var(--z-publicite);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    animation: fade-in 0.2s;
}

.ad-panel {
    background: var(--porcelaine);
    border: 1px dashed var(--filet-fort);
    border-radius: var(--r-lg);
    padding: 26px 22px;
    text-align: center;
    max-width: 320px;
    width: 100%;
}

.ad-tag {
    font-family: var(--mono);
    font-size: 0.625rem;
    letter-spacing: 0.12em;
    color: var(--encre-3);
    margin-bottom: 16px;
}

.ad-icon { display: flex; justify-content: center; color: var(--encre-4); margin-bottom: 12px; }
.ad-label { font-size: 0.875rem; font-weight: 500; margin-bottom: 5px; }
.ad-hint { font-size: 0.71875rem; color: var(--encre-3); margin-bottom: 20px; }

/* `.ad-close` porte l'habit de `.modal-close` (voir MODALES). */
.ad-close:disabled {
    background: transparent;
    border-color: var(--filet-fort);
    color: var(--encre-4);
    cursor: not-allowed;
}

/* ==================== APPEL VERS UNE PUB RÉCOMPENSÉE ====================
   Il portait un liseré en POINTILLÉS sur fond transparent, en gris. Or le
   pointillé est, dans ce jeu, le signe d'une case vide (`.garden-slot.empty`) :
   le seul bouton qu'on espère voir touché disait « il n'y a rien ici ». Et une
   fois le bonus obtenu, `.boost-active` était plus habillé que l'offre qui y
   menait — l'après plus désirable que l'avant.

   Il prend donc le rôle de l'OR, celui que le jeu réserve déjà à la valeur (le
   compteur d'argent, les prix). Surtout pas le vert d'accent : il ne marque que
   ce qui ATTEND le joueur — une récolte mûre, des tisanes à vendre — et une
   publicité n'attend personne. La frontière du §7.3 se lit aussi en couleur.

   Le gain reste sur --encre pour tenir le AA à 12,5 px : l'or sur son voile ne
   monte qu'à 3,3:1, il colore le pictogramme et le liseré, jamais la phrase.
   ========================================================================= */

.ad-cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 0 15px;
    border: 1px solid color-mix(in srgb, var(--or) 40%, var(--or-voile));
    border-radius: 99px;
    background: var(--or-voile);
    color: var(--encre);
    font-family: inherit;
    font-size: 0.78125rem;
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s, transform 0.12s;
}

.ad-cta > svg { flex: none; color: var(--or); }
.ad-cta:hover:not(:disabled) { border-color: var(--or); }
.ad-cta:not(:disabled):active { transform: scale(0.98); }
.ad-cta:disabled { opacity: 0.5; cursor: not-allowed; }
.ad-cta.is-wide { width: 100%; min-height: var(--touch); margin-top: 8px; }

/* SUR UN BOUTON LARGE, LE TEXTE SE CENTRE. La boite d'un bouton etroit
   epouse son contenu : il n'y a pas de vide a repartir. Large, elle ne
   l'epouse plus, et la seconde ligne — « Publicite », courte — laissait un
   creux a sa droite. Vu a l'ecran le 19/08/2026 sur les deux visuels
   compares ; aucune mesure ne l'aurait signale, rien ne debordait. */
.ad-cta.is-wide .ad-cta-text { align-items: center; text-align: center; }

/* Le gain sur une ligne, sa contrepartie sur la suivante : le joueur voit ce
   qu'il reçoit ET ce qu'il donne avant de toucher (§11.2). La mention de la
   vidéo est en retrait de taille, jamais de lisibilité — elle reste sur
   --encre-3, au-dessus du seuil AA. */
.ad-cta-text  { display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
                text-align: start; }
/* Le gain porte le poids : c'est la promesse, pas la mention légale. */
.ad-cta-label { line-height: 1.25; font-weight: 500; }
.ad-cta-note  { font-size: 0.625rem; letter-spacing: 0.04em; color: var(--encre-3); }
/* La pastille du jardin porte maintenant deux lignes : 38 px de haut la
   faisaient tomber a 42 px mesures, sous la regle des 44 px tactiles. */
.ad-cta:not(.is-wide) { padding: 5px 15px; min-height: var(--touch); }

/* ==================== L'INVITATION DU CRÉNEAU (12/08/2026) ====================
   Quand l'attente est réelle mais que l'offre publicitaire ne peut pas
   s'afficher (§7.6, plafonds), le créneau sous le jardin porte une invitation
   du jeu vers le grimoire — une seule voix par créneau, jamais les deux.

   Même géométrie de pilule que l'offre qu'elle remplace, mais AUCUN de ses
   signaux : pas l'or (ce n'est pas une publicité), pas le vert (rien
   n'attend), pas de pointillés (signe d'une case VIDE dans ce jeu — la leçon
   du bloc ci-dessus). Un filet, l'encre des mentions : c'est une suggestion,
   elle ne réclame rien. */
.pousse-invite {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: var(--touch);
    padding: 5px 15px;
    border: 1px solid var(--filet-fort);
    border-radius: 99px;
    background: none;
    color: var(--encre-3);
    font-family: inherit;
    font-size: 0.78125rem;
    cursor: pointer;
}
.pousse-invite > svg { flex: none; }
.pousse-invite:active { transform: scale(0.98); }

/* `.boost-active` (le compte à rebours) est PARTI avec la fournée (12/08/2026) :
   l'avance est créditée d'un coup, il n'y a plus de fenêtre à décompter. */

#gardenBoost { display: flex; justify-content: center; }
#gardenBoost:empty { display: none; }

/* ==================== ACCOMPAGNEMENT DES PREMIERS PAS ====================
   Rien n'est bloqué : l'anneau et la bulle laissent passer les clics, seul le
   bouton « passer » est cliquable.
   ========================================================================= */

.coach-halo {
    position: fixed;
    z-index: var(--z-halo);
    border-radius: 14px;
    border: 2px solid var(--accent);
    pointer-events: none;
    transition: opacity 0.2s;
    animation: coach-pulse 1.8s ease-in-out infinite;
}

/* Le halo DÉRIVE de --accent au lieu de le recopier : les deux valeurs
   étaient l'ancien #3E6B4E, si bien que le trait (var(--accent)) et son onde
   portaient deux verts différents sur le même élément depuis la refonte. */
@keyframes coach-pulse {
    0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 30%, transparent); }
    50%      { box-shadow: 0 0 0 7px color-mix(in srgb, var(--accent) 0%, transparent); }
}

/* Bornée aux gouttières et centrée par la mise en page, jamais par du calcul
   en JavaScript : impossible de mordre un bord. */
.coach-bubble {
    position: fixed;
    z-index: var(--z-bulle);
    inset-inline: 12px;
    max-width: 496px;
    margin-inline: auto;
    padding: 12px 14px;
    background: var(--encre);
    color: var(--porcelaine);
    border-radius: var(--r);
    pointer-events: none;
    animation: toast-in 0.26s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.coach-bubble.is-centered { top: 50%; transform: translateY(-50%); }

.coach-text { font-size: 0.84375rem; line-height: 1.45; }

/* 44 px et non 32 : c'est le seul élément cliquable de la bulle, et il était
   le dernier bouton du jeu sous la règle des cibles tactiles — même correctif
   que `.quiz-quit` le 20/08/2026. La bulle n'a pas de hauteur fixe, et
   l'accompagnement la mesure (`offsetHeight`) avant de la poser. */
.coach-skip {
    pointer-events: auto;
    margin-top: 9px;
    min-height: var(--touch);
    padding: 0 12px;
    border: 1px solid color-mix(in srgb, var(--porcelaine) 28%, transparent);
    border-radius: 99px;
    background: transparent;
    color: var(--porcelaine);
    font-family: inherit;
    font-size: 0.71875rem;
    cursor: pointer;
}

.coach-skip:hover { border-color: var(--porcelaine); }

/* ==================== SÉLECTEUR DE LANGUE ==================== */

.lang-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
}

.lang-card {
    position: relative;
    display: flex;
    align-items: center;
    gap: 11px;
    min-height: 66px;
    padding: 12px 13px;
    border: 1px solid var(--filet);
    border-radius: var(--r);
    background: var(--surface);
    color: inherit;
    font-family: inherit;
    text-align: start;
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s;
}

.lang-card:hover { border-color: var(--filet-fort); }

.lang-card.is-current {
    border-color: var(--accent);
    background: var(--accent-voile);
}

.lang-tag {
    flex: none;
    font-family: var(--mono);
    font-size: 1.1875rem;
    letter-spacing: 0.02em;
    color: var(--encre-4);
}

.lang-card.is-current .lang-tag { color: var(--accent); }

.lang-names { display: flex; flex-direction: column; min-width: 0; }
.lang-native { font-size: 0.8125rem; font-weight: 500; }
.lang-english { font-size: 0.6875rem; color: var(--encre-3); }

.lang-check {
    position: absolute;
    top: 10px;
    inset-inline-end: 10px;
    display: inline-flex;
    color: var(--accent);
}

/* Les chevrons pointent vers la suite de la lecture, pas vers la droite. */
[dir="rtl"] .link-row > svg:last-child { transform: scaleX(-1); }

/* ==================== ERREUR FATALE ==================== */

.fatal-error {
    max-width: 520px;
    margin: 60px auto;
    padding: 26px 20px;
    font-family: var(--sans);
}

.fatal-error h1 { font-family: var(--serif); font-size: 1.375rem; font-weight: 400;
                  color: var(--alerte); margin-bottom: 12px; }
.fatal-error p { font-size: 0.875rem; color: var(--encre-2); margin-bottom: 10px; }
.fatal-error .hint { font-size: 0.8125rem; color: var(--encre-3); }
.fatal-error code { font-family: var(--mono); font-size: 0.75rem; background: var(--surface-sourd);
                    padding: 1px 5px; border-radius: var(--r-xs); }
.fatal-error pre { font-family: var(--mono); font-size: 0.78125rem; background: var(--encre);
                   color: var(--porcelaine); padding: 12px 14px; border-radius: var(--r-sm);
                   overflow-x: auto; margin-bottom: 10px; }

/* ==================== ACCESSIBILITÉ ==================== */

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--r-xs);
}

:focus:not(:focus-visible) { outline: none; }

.hidden { display: none !important; }

/* Réduction des animations (§11.1).

   Deux entrées vers le même état : le réglage du système d'exploitation, et
   l'interrupteur de l'atelier qui pose `.reduit-animations` sur <html>. La
   seconde existe parce que la première est tout ou rien et hors du jeu — un
   joueur peut vouloir Flora calme sans reconfigurer son téléphone.

   Ce bloc écrase les animations purement décoratives. Ce qui PORTE une
   information — le montant qui s'envole, la graine récupérée — est coupé côté
   JavaScript, pas ici : mieux vaut ne pas le jouer du tout que le jouer en une
   milliseconde, invisible. Voir `reducedMotion()` dans js/noyau/ui.js. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

:root.reduit-animations *,
:root.reduit-animations *::before,
:root.reduit-animations *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
}

/* ==================== PETITS ÉCRANS ==================== */

/* Le padding de `.app` n'est PAS repris ici : il porte le dégagement du bas
   (--dock-h) et celui du système, et une surcharge d'avant « Contre-jour »
   les écrasait — la planche passait sous la barre d'actions. */
@media (max-width: 359px) {
    .stat-value { font-size: 0.875rem; }
    .garden-slot { min-height: 72px; }
}

/* ==================== LES PLANCHES BOTANIQUES ====================
   Deux calques posés l'un sur l'autre, chacun un aplat découpé par son masque
   (ui.js, `dessinPlante`). Le lavis dessous, en --plante ; l'encre dessus, en
   --encre. Aucune couleur n'est écrite ici : un masque ne porte QUE la forme,
   la couleur vient des jetons — c'est ce qui permet à une planche de 1887 de
   suivre la direction artistique du jeu.

   LE COMPOSANT NE S'APPELLE PAS `.planche`, et ce n'est pas un caprice : le
   nom est pris depuis « Contre-jour » par la planche claire qui porte les
   ressources et le jardin (index.html). Au premier essai, les deux règles se
   sont additionnées — la vignette a pris le fond porcelaine et les coins
   arrondis de la planche, et la planche a perdu son `flex: 1`, ouvrant une
   couture sombre sous le jardin. Vu à la capture, invisible à toute mesure qui
   ne comparait pas les deux feuilles de style.

   Une image ne se retourne pas en arabe : aucune propriété de ce bloc ne
   dépend de la direction, et c'est voulu — une planche botanique miroitée
   serait une faute, comme un portrait retourné.
   ========================================================================= */

.dessin-plante {
    position: relative;
    display: inline-block;
    flex: none;
}

/* La planche entière, sous le titre de la page. Le format est celui de
   `sortie.format` dans tools/planches/cadrages.json : les deux vont ensemble,
   et un écart ne casse rien — le masque est posé en `contain`, il se centre. */
.dessin-plante.is-grande {
    display: block;
    width: 100%;
    aspect-ratio: 3 / 2;
    margin-bottom: 16px;
}

.dessin-plante > span {
    position: absolute;
    inset: 0;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: center;
            mask-position: center;
    -webkit-mask-size: contain;
            mask-size: contain;
}

.dessin-lavis { background: var(--plante, var(--encre-4)); opacity: var(--dessin-lavis); }
.dessin-encre { background: var(--encre); }

/* Découverte : l'encre seule. `display: none` et non une opacité nulle — le
   lavis n'est pas même téléchargé tant que la page ne l'a pas mérité. */
.dessin-plante.is-trait .dessin-lavis { display: none; }

/* Verrouillée : les deux calques dans l'encre NON TEXTUELLE, pâlis ensemble.
   L'opacité porte sur le groupe, après composition : l'encre et le lavis ne
   s'additionnent pas en une tache plus sombre là où ils se recouvrent. */
.dessin-plante.is-silhouette { opacity: 0.38; }
.dessin-plante.is-silhouette > span { background: var(--encre-4); opacity: 1; }

/* ==================== LE GRIMOIRE DE FLORA (§2.2) ====================
   Un livre, pas un tableau de bord. Le serif porte les noms et les lettres, la
   couleur ne vient que de la teinte d'infusion de la plante — et seulement sur
   les pages qui existent : une page verrouillée est une page sans couleur.
   ========================================================================= */

.book-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }

.book-card {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-height: 62px;
    padding: 9px 11px;
    background: var(--surface);
    border: 1px solid var(--filet);
    border-radius: var(--r-sm);
    font-family: inherit;
    text-align: start;
    cursor: pointer;
}

.book-card > svg { color: var(--plante, var(--encre-4)); flex: none; }
.book-name { font-size: 0.78125rem; font-weight: 500; color: var(--encre); line-height: 1.25; }

/* La marque d'état vit dans le coin haut-droit, sur la même ligne que l'icône. */
.book-card { position: relative; }

.book-mark {
    position: absolute;
    inset-block-start: 9px;
    inset-inline-end: 10px;
    display: inline-flex;
    align-items: center;
    font-family: var(--mono);
    font-size: 0.625rem;
    color: var(--encre-3);
}

.book-mark.is-done { color: var(--accent); }

/* Verrouillée : ni couleur, ni promesse. Elle reste lisible — --encre-3 pour le
   nom, qui est du texte, --encre-4 pour l'icône, qui n'en est pas. */
.book-card.is-locked { background: var(--surface-sourd); border-color: transparent; }
.book-card.is-locked > svg { color: var(--encre-4); }
.book-card.is-locked .book-name { color: var(--encre-3); font-weight: 400; }

.book-card.is-restored { border-color: var(--plante, var(--accent-filet)); }

/* Le nom latin, sous le titre de la page : il ne se traduit pas, il s'italise. */
.book-latin {
    font-family: var(--serif);
    font-style: italic;
    font-size: 0.8125rem;
    color: var(--encre-3);
    margin: -12px 0 16px;
}

/* Ce qui n'est pas encore restauré : l'encre a pâli, et on dit quoi faire. */
.book-faded {
    padding: 13px;
    background: var(--surface-sourd);
    border-radius: var(--r-sm);
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.book-faded p { font-size: 0.78125rem; color: var(--encre-2); }
.book-progress { font-family: var(--mono); font-size: 0.6875rem; color: var(--encre-3); }

/* Page jamais récoltée : le sceau, et rien d'autre. */
.book-sealed {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 11px;
    padding: 30px 18px;
    background: var(--surface-sourd);
    border-radius: var(--r-sm);
    margin-bottom: 18px;
}

.book-sealed > svg { color: var(--encre-4); }
.book-sealed p { font-size: 0.8125rem; color: var(--encre-2); text-align: center; max-width: 30ch; }

/* ==================== LES LETTRES DE FLORA ==================== */

.letter-list { display: flex; flex-direction: column; gap: 7px; }

/* Une ligne tactile (voir LIGNES D'OPTION). */
.letter-row {
    gap: 11px;
    padding: 8px 12px;
    border: 1px solid var(--filet);
    border-radius: var(--r-sm);
    font-size: 0.8125rem;
    color: var(--encre);
}

.letter-row > svg:first-child { flex: none; color: var(--accent); }
.letter-name { flex: 1; min-width: 0; }
.letter-row > svg:last-child { flex: none; color: var(--encre-4); }

.letter-row.is-locked {
    background: var(--surface-sourd);
    border-color: transparent;
    color: var(--encre-3);
    cursor: default;
}

.letter-row.is-locked > svg { color: var(--encre-4); }

/* La lettre elle-même : c'est une main qui écrit, pas une interface. */
.letter-body {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 4px 2px 18px;
}

.letter-body p {
    font-family: var(--serif);
    font-size: 0.90625rem;
    line-height: 1.65;
    color: var(--encre);
}

/* La signature : plus spécifique que `.letter-body p`, qui pose l'encre pleine
   sur chaque paragraphe — c'est la cascade qui tranche, pas un `!important`. */
.letter-body .letter-sign {
    align-self: flex-end;
    font-style: italic;
    color: var(--encre-2);
}

/* ==================== LE QUIZ (§2.3) ====================
   Trois questions, une par écran. Les propositions sont des cibles pleine
   largeur : on répond au pouce, sans viser.
   ========================================================================= */

.book-card.is-mastered { border-color: var(--accent-filet); background: var(--accent-voile); }
.book-card.is-mastered .book-mark { color: var(--accent); }

.book-mastery {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 10px;
    font-size: 0.71875rem;
    color: var(--encre-3);
}

.book-mastery > svg { color: var(--accent); flex: none; }

/* L'entrée du quiz, au pied d'une page restaurée. Une ligne tactile (voir
   LIGNES D'OPTION), la seule des quatre au filet fort. */
.quiz-start {
    gap: 11px;
    padding: 10px 13px;
    margin-bottom: 18px;
    border: 1px solid var(--filet-fort);
    border-radius: var(--r-sm);
}

.quiz-start > svg { flex: none; color: var(--accent); }
.quiz-start:hover { border-color: var(--accent-filet); background: var(--accent-voile); }
.quiz-start-text { display: flex; flex-direction: column; min-width: 0; }
.quiz-start-name { font-size: 0.8125rem; font-weight: 500; color: var(--encre); }
.quiz-start-note { font-size: 0.71875rem; color: var(--encre-3); }

/* Le sceau de maîtrise remplace l'entrée une fois le quiz réussi. */
.quiz-seal {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 11px 13px;
    margin-bottom: 18px;
    background: var(--accent-voile);
    border: 1px solid var(--accent-filet);
    border-radius: var(--r-sm);
}

.quiz-seal > svg { flex: none; color: var(--accent); }
.quiz-seal-name { font-size: 0.8125rem; font-weight: 500; color: var(--accent-fonce); }
.quiz-seal-note { font-size: 0.71875rem; color: var(--encre-2); }

/* La question : c'est elle qu'on lit, elle prend la place. */
.quiz-question {
    font-family: var(--serif);
    font-size: 1rem;
    line-height: 1.45;
    color: var(--encre);
    margin-bottom: 16px;
}

.quiz-options { display: flex; flex-direction: column; gap: 8px; }

.quiz-option {
    width: 100%;
    min-height: var(--touch);
    padding: 11px 14px;
    background: var(--surface);
    border: 1px solid var(--filet);
    border-radius: var(--r-sm);
    font-family: inherit;
    font-size: 0.84375rem;
    line-height: 1.4;
    color: var(--encre);
    text-align: start;
    cursor: pointer;
}

.quiz-option:hover { border-color: var(--accent-filet); background: var(--accent-voile); }
.quiz-option:active { transform: scale(0.99); }

/* Quitter en cours de route : le quiz est facultatif, on le dit.
   `min-height` comme `.quiz-option` et `.quiz-retry` : c'est une CIBLE, et la
   discrétion se joue sur la couleur et la graisse, jamais sur la hauteur. Il
   mesurait 36 / 38 / 41 px aux trois crans, seul bouton du jeu sous les 44 —
   trouvé le 20/08/2026 par la scène `quiz` du banc de bout en bout. */
.quiz-quit {
    display: block;
    width: 100%;
    min-height: var(--touch);
    margin-top: 16px;
    padding: 10px;
    background: none;
    border: 0;
    font-family: inherit;
    font-size: 0.75rem;
    color: var(--encre-3);
    cursor: pointer;
}

.quiz-quit:hover { color: var(--encre); }

.quiz-missed {
    margin-top: 12px;
    margin-bottom: 4px;
    font-family: var(--mono);
    font-size: 0.625rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--encre-3);
}

/* Le gain, écrit noir sur blanc au moment où il est acquis. */
.quiz-reward {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 15px;
    margin-bottom: 18px;
    background: var(--accent-voile);
    border-radius: var(--r-sm);
}

.quiz-reward > svg { flex: none; color: var(--accent); }
.quiz-reward p { font-size: 0.8125rem; color: var(--encre); }

.quiz-retry {
    width: 100%;
    min-height: var(--touch);
    margin-bottom: 9px;
    background: transparent;
    border: 1px solid var(--filet-fort);
    border-radius: var(--r);
    font-family: inherit;
    font-size: 0.84375rem;
    color: var(--encre);
    cursor: pointer;
}

.quiz-retry:hover { border-color: var(--accent); color: var(--accent); }

/* ==================== LA MAÎTRISE D'UNE PLANTE (§5.1) ====================
   Cinq lignes sous la page. Une marche franchie n'est pas mise en valeur : elle
   s'efface, et c'est ce qui reste à faire qui garde l'encre pleine.
   ========================================================================= */

.mastery-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 9px;
    margin-bottom: 7px;
}

.mastery-percent { font-size: 0.8125rem; font-weight: 500; color: var(--encre); }

.mastery-done {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 0.71875rem;
    color: var(--accent-fonce);
}

.mastery-done > svg { flex: none; }

.mastery-steps { margin-top: 11px; display: flex; flex-direction: column; gap: 2px; }

.mastery-step {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 5px 0;
    font-size: 0.78125rem;
    color: var(--encre);
}

.mastery-step > svg { flex: none; color: var(--filet-fort); }
.mastery-step-name { flex: 1; min-width: 0; }
.mastery-step-count { font-size: 0.71875rem; color: var(--encre-3); }

.mastery-step.is-done { color: var(--encre-3); }
.mastery-step.is-done > svg { color: var(--accent); }

.mastery-note { margin-top: 9px; font-size: 0.71875rem; color: var(--encre-3); }

/* ==================== LA COLLECTION DE FLORA (§5.2) ====================
   Cinq lignes, cinq portes. Le compte est à droite, en chiffres tabulaires :
   la colonne reste droite quand les nombres changent.
   ========================================================================= */

.collect-list { display: flex; flex-direction: column; gap: 2px; }

.collect-row {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 11px;
    min-height: var(--touch);
    padding: 9px 4px;
    background: none;
    border: 0;
    border-bottom: 1px solid var(--filet);
    font-family: inherit;
    text-align: start;
    cursor: pointer;
}

.collect-row:last-child { border-bottom: 0; }
.collect-row > svg { flex: none; color: var(--encre-3); }
.collect-row:hover { background: var(--accent-voile); }
.collect-row.is-full > svg:first-child { color: var(--accent); }

.collect-name { flex: 1; min-width: 0; font-size: 0.8125rem; color: var(--encre); }
.collect-count { flex: none; font-size: 0.75rem; color: var(--encre-2); }

.collect-note { margin-top: 13px; font-size: 0.71875rem; color: var(--encre-3); }

/* ==================== LA PAGE SANS NOM (§5.6) ====================
   Elle ne ressemble à aucune carte de plante : pas de teinte, pas de nom, un
   filet en pointillés. C'est une page que le grimoire n'a pas encore.
   ========================================================================= */

.secret-card {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 13px;
    background: var(--surface);
    border: 1px dashed var(--filet-fort);
    border-radius: var(--r-sm);
}

.secret-card > svg { flex: none; color: var(--encre-3); }
.secret-card.is-hinted { border-style: solid; border-color: var(--accent-filet); }
.secret-card.is-hinted > svg { color: var(--accent); }

.secret-text { flex: 1; min-width: 0; }

/* Le nom d'une page sans nom et celui d'une aventure (`.adv-name`, plus bas)
   sont le même titre de carte, en serif. */
.secret-name,
.adv-name {
    font-family: var(--serif);
    font-size: 0.9375rem;
    color: var(--encre);
    line-height: 1.25;
}

.secret-note { margin-top: 3px; font-size: 0.75rem; color: var(--encre-2); }
.secret-count { margin-top: 5px; font-size: 0.71875rem; color: var(--encre-3); }

/* ==================== LES ÉPREUVES (§5.5) ====================
   Elles ne rapportent rien, et l'écran ne doit pas faire croire le contraire :
   aucune pastille de récompense, aucun accent tant qu'elles ne sont pas
   remportées. Une manquée se dit, elle ne se gronde pas.
   ========================================================================= */

.epreuve-list { display: flex; flex-direction: column; }

.epreuve-row {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    padding: 11px 2px;
    border-bottom: 1px solid var(--filet);
}

.epreuve-row:last-child { border-bottom: 0; }
.epreuve-row > svg { flex: none; margin-top: 1px; color: var(--filet-fort); }
.epreuve-row.is-won > svg { color: var(--accent); }
.epreuve-row.is-missed > svg { color: var(--encre-3); }

.epreuve-text { flex: 1; min-width: 0; }
.epreuve-name { font-size: 0.8125rem; font-weight: 500; color: var(--encre); }
.epreuve-note { margin-top: 2px; font-size: 0.71875rem; color: var(--encre-3); }
.epreuve-missed { margin-top: 4px; font-size: 0.71875rem; color: var(--encre-2); font-style: italic; }

.epreuve-row.is-won .epreuve-name { color: var(--accent-fonce); }
.epreuve-row.is-missed .epreuve-name { color: var(--encre-2); }

.epreuve-state {
    flex: none;
    font-family: var(--mono);
    font-size: 0.59375rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--encre-3);
}

.epreuve-row.is-won .epreuve-state { color: var(--accent); }
.epreuve-hint { margin-top: 13px; font-size: 0.71875rem; color: var(--encre-3); }

/* ==================== LE BILAN DE FIN (§5.7) ====================
   Un moment, pas un tableau de bord : le titre est en serif, centré, et prend
   la place qu'il faut avant que les chiffres n'arrivent.
   ========================================================================= */

.bilan { text-align: center; padding: 6px 0 16px; }

.bilan-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 62px;
    height: 62px;
    margin-bottom: 12px;
    border-radius: 50%;
    background: var(--accent-voile);
    color: var(--accent);
}

.bilan-title {
    font-family: var(--serif);
    font-size: 1.25rem;
    line-height: 1.25;
    color: var(--encre);
}

.bilan-sub { margin-top: 6px; font-size: 0.8125rem; color: var(--encre-3); }

.bilan-suite {
    margin-top: 18px;
    font-family: var(--serif);
    font-size: 0.9375rem;
    font-style: italic;
    text-align: center;
    color: var(--accent-fonce);
}

/* ==================== LA CARTE DES AVENTURES (§5.9) ====================
   Une aventure à venir n'est pas une porte fermée : pas de cadenas, pas de
   compte à rebours. Un filet en pointillés, et une phrase qui promet.
   ========================================================================= */

.adv-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }

.adv-card {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 13px;
    background: var(--surface);
    border: 1px solid var(--filet-fort);
    border-radius: var(--r-sm);
}

.adv-card > svg { flex: none; align-self: flex-start; margin-top: 2px; color: var(--accent); }
.adv-card.is-done { background: var(--accent-voile); border-color: var(--accent-filet); }
.adv-card.is-soon { border-style: dashed; }
.adv-card.is-soon > svg { color: var(--encre-3); }

.adv-text { flex: 1; min-width: 0; }

/* `.adv-name` partage sa règle avec `.secret-name` (LA PAGE SANS NOM). */
.adv-note { margin-top: 3px; font-size: 0.71875rem; color: var(--encre-3); }

/* L'état est un chapeau au-dessus du titre : posé à droite, « Menée à son
   terme » mangeait la moitié de la carte et coupait la description. */
.adv-state {
    margin-bottom: 3px;
    font-family: var(--mono);
    font-size: 0.5625rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--encre-3);
}

.adv-card.is-done .adv-state { color: var(--accent); }

/* Où et quand (§6.2, §6.3). Une ligne de service sous la description, jamais
   un titre : le lieu situe l'aventure, il ne la nomme pas. */
.adv-where {
    display: flex;
    align-items: center;
    gap: 5px;
    margin-top: 5px;
    font-size: 0.6875rem;
    color: var(--encre-3);
}

.adv-where > svg { flex: none; }

/* Le geste de lancement (§5.8, 13/08/2026). Quand il est là, c'est l'action
   de la feuille : plein accent, comme le bouton de bas de feuille — mais à sa
   taille, pas à sa largeur : la carte n'est pas une feuille. Jamais deux à
   l'écran par construction (la courante n'en porte pas, une verrouillée non
   plus). */
.adv-start {
    margin-top: 8px;
    padding: 0 16px;
    min-height: var(--touch);
    border: 1px solid var(--accent);
    border-radius: var(--r-sm);
    background: var(--accent);
    color: var(--sur-accent);
    font-family: inherit;
    font-size: 0.78125rem;
    font-weight: 500;
    cursor: pointer;
}

.adv-hint { margin-top: 12px; font-size: 0.71875rem; color: var(--encre-3); }

/* ==================== GRADES D'EXPERTISE (§2.4) ====================
   Deuxième axe de progression : les phases disent ce que l'herboristerie
   produit, le grade ce que le joueur sait. Il vit donc en tête du grimoire,
   et nulle part ailleurs.
   ========================================================================= */

.grade-badge {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 13px;
    margin-bottom: 16px;
    background: var(--accent-voile);
    border: 1px solid var(--accent-filet);
    border-radius: var(--r-sm);
}

.grade-badge > svg { flex: none; color: var(--accent); }
.grade-text { flex: 1; min-width: 0; }

.grade-kicker {
    font-family: var(--mono);
    font-size: 0.59375rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--encre-3);
}

.grade-name {
    font-family: var(--serif);
    font-size: 1rem;
    color: var(--accent-fonce);
    line-height: 1.2;
}

/* Ce qu'il reste à faire, en retrait mais lisible : --encre-3, pas --encre-4. */
.grade-next {
    flex: none;
    max-width: 40%;
    font-size: 0.6875rem;
    line-height: 1.3;
    color: var(--encre-3);
    text-align: end;
}

/* ==================== LES MÉLANGES (§2.5) ====================
   Même famille visuelle que les lettres : une liste de choses trouvées, où le
   creux dit ce qui manque sans crier.
   ========================================================================= */

.recipe-list { display: flex; flex-direction: column; gap: 7px; }

.recipe-row {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    min-height: var(--touch);
    padding: 10px 12px;
    background: var(--surface);
    border: 1px solid var(--filet);
    border-radius: var(--r-sm);
}

.recipe-row > svg { flex: none; margin-top: 2px; color: var(--accent); }
.recipe-text { min-width: 0; }
.recipe-name { font-size: 0.8125rem; font-weight: 500; color: var(--encre); }
.recipe-plants { font-size: 0.71875rem; color: var(--accent); }
.recipe-note { font-size: 0.71875rem; line-height: 1.45; color: var(--encre-2); margin-top: 3px; }

.recipe-row.is-locked {
    align-items: center;
    background: var(--surface-sourd);
    border-color: transparent;
}

.recipe-row.is-locked > svg { margin-top: 0; color: var(--encre-4); }
.recipe-row.is-locked .recipe-name { color: var(--encre-3); font-weight: 400; }

/* La règle du jeu, écrite une fois sous la liste : sans elle, cinq paires parmi
   dix plantes se cherchent à l'aveugle. */
.recipe-hint {
    margin-top: 9px;
    font-size: 0.71875rem;
    line-height: 1.45;
    color: var(--encre-3);
}

/* ==================== LE VILLAGE (§3.1) ====================
   Trois habitants, trois arcs. Le portrait est un objet, pas un visage : le
   jeu n'a pas d'emoji, et une icône de métier dit plus qu'une silhouette.
   ========================================================================= */

/* La réputation (§5.4) reprend le bandeau du grade, mais il faut une phrase
   pour dire lequel est lequel : deux échelles à cinq barreaux, ça se confond. */
.village-repute {
    margin: -10px 0 16px;
    font-size: 0.71875rem;
    color: var(--encre-3);
}

.village-list { display: flex; flex-direction: column; gap: 8px; }

/* Une ligne tactile (voir LIGNES D'OPTION), à la gouttière de 12 px. */
.village-card {
    gap: 12px;
    padding: 10px 12px;
    border: 1px solid var(--filet);
    border-radius: var(--r-sm);
}

.village-card > svg:first-child { flex: none; color: var(--accent); }
.village-card > svg:last-child { flex: none; color: var(--encre-4); }
.village-text { flex: 1; min-width: 0; }
.village-name { font-size: 0.8125rem; font-weight: 500; color: var(--encre); }
.village-note { font-size: 0.71875rem; line-height: 1.35; color: var(--encre-3); }

.village-step {
    flex: none;
    font-family: var(--mono);
    font-size: 0.65625rem;
    color: var(--encre-3);
}

.village-card.is-done { border-color: var(--accent-filet); background: var(--accent-voile); }
.village-card.is-done .village-step { color: var(--accent); }

.village-card.is-locked {
    background: var(--surface-sourd);
    border-color: transparent;
    cursor: default;
}

.village-card.is-locked > svg { color: var(--encre-4); }
.village-card.is-locked .village-name { color: var(--encre-3); font-weight: 400; }

/* ==================== L'ARC D'UN HABITANT ==================== */

.arc-list { display: flex; flex-direction: column; gap: 9px; }

.arc-step {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 12px;
    background: var(--surface-sourd);
    border-radius: var(--r-sm);
}

.arc-step > svg { flex: none; margin-top: 2px; color: var(--encre-4); }
.arc-step.is-done > svg { color: var(--accent); }
.arc-step.is-current { background: var(--accent-voile); }
.arc-step.is-current > svg { color: var(--accent); }

/* Ce qu'il dit est en serif : c'est une voix, pas une étiquette. */
.arc-ask {
    font-family: var(--serif);
    font-size: 0.84375rem;
    line-height: 1.45;
    color: var(--encre);
}

.arc-step.is-locked .arc-ask { font-family: var(--sans); font-size: 0.75rem; color: var(--encre-3); }
.arc-vignette { font-size: 0.75rem; line-height: 1.5; color: var(--encre-2); margin-top: 5px; }
.arc-need { font-size: 0.71875rem; color: var(--accent); margin-top: 5px; }

/* Le savoir, libéré quand l'arc se termine. Il porte la teinte de sa plante. */
.client-savoir {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 13px;
    margin-bottom: 18px;
    background: var(--surface-sourd);
    border-inline-start: 2px solid var(--plante, var(--accent));
    border-radius: var(--r-sm);
}

/* « Il repassera » : la fiche dit où servir quand elle ne le permet pas. */
.village-wait {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 11px 12px;
    margin-bottom: 4px;
    background: var(--surface-sourd);
    border-radius: var(--r-sm);
    font-size: 0.75rem;
    line-height: 1.45;
    color: var(--encre-3);
}

.village-wait > svg { flex: none; color: var(--encre-4); }

.client-savoir > svg { flex: none; margin-top: 2px; color: var(--plante, var(--accent)); }
.client-savoir-name { font-size: 0.78125rem; font-weight: 500; color: var(--encre); }
.client-savoir-note { font-size: 0.78125rem; line-height: 1.5; color: var(--encre-2); margin-top: 4px; }

/* ==================== LE COMPTOIR (§3.2) ====================
   Une bande sur l'écran principal, entre la jauge d'objectif et la planche :
   ce qu'on a, pour qui, puis de quoi le faire. Elle n'apparaît QUE lorsqu'un
   habitant attend. Depuis « Contre-jour » elle vit sur le SOCLE et non sur la
   planche — un habitant qui attend vient du village, pas du jardin.

   Le vert d'accent ne marque ici que ce qui attend le joueur — la bande ne
   s'allume qu'une fois les tisanes réunies, exactement comme le bouton Vendre.
   Un comptoir vert en permanence serait un rappel, pas un signal.
   ========================================================================= */

/* `.app` n'a plus de `gap` depuis « Contre-jour » : un comptoir désert ne
   coûte donc plus les treize pixels qui justifiaient cette règle à l'origine.
   Elle reste parce qu'elle dit toujours quelque chose de vrai — un `#counter`
   vide ne doit rien occuper — et parce que `.counter` porte maintenant sa
   propre marge basse de 8 px, qui elle s'appliquerait à un conteneur vide. */
#counter:empty { display: none; }

/* Le comptoir vit sur le SOCLE, entre la jauge d'objectif et la planche : un
   habitant qui attend vient du village, pas du jardin. Ses couleurs sont donc
   celles du socle, et sa marge de 10 px est celle de la planche — les deux
   objets s'alignent sur le même bord. */
.counter {
    width: calc(100% - 20px);
    margin: 0 10px 8px;
    display: flex;
    align-items: center;
    gap: 11px;
    min-height: var(--touch);
    padding: 11px 12px;
    background: var(--coque-2);
    border: 1px solid var(--coque-filet);
    border-radius: var(--r);
    font-family: inherit;
    text-align: start;
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s, transform 0.12s;
}

.counter:active { transform: scale(0.985); }

/* Prêt à servir : sur le socle, le vert lisible est --accent-clair. */
.counter.is-ready { border-color: var(--accent-clair); }

/* Le visage est posé dans un rond, comme au cadre 2a/2 : sur un fond sombre,
   une icône seule flotte sans se rattacher à rien. */
.counter-face {
    flex: none;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    background: var(--comptoir-rond);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--comptoir-visage);
}

.counter > svg:last-child { flex: none; color: var(--sur-coque-sourd); }

.counter-text { flex: 1; min-width: 0; display: flex; flex-direction: column; }

/* Les DEUX lignes se coupent, et la première autant que la seconde.
   Elle ne l'avait pas, et c'était le seul endroit du jeu où l'écran principal
   débordait : « L'instituteur vous attend » tient sur une ligne, « The
   schoolteacher is waiting » et « O professor está esperando » passent à deux
   au cran ×1,3, et les 22 px de trop poussaient la page à 860 sur 844.
   Mesuré en huit langues — le relevé d'origine ne connaissait que le français.

   Rien n'est perdu : la bande est un BOUTON, et la feuille qu'elle ouvre porte
   le nom entier. */
.counter-name,
.counter-ask {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.counter-name { font-size: 0.8125rem; font-weight: 400; color: var(--sur-coque); }

/* La demande peut être longue (« Le mélange « Garrigue » : thym et romarin »). */
.counter-ask {
    font-size: 0.71875rem;
    line-height: 1.35;
    color: var(--sur-coque-2);
}

/* Le gain se lit en or, jamais en vert : le vert de l'écran de jeu appartient
   à UNE action à la fois, et elle est dans la barre du bas. */
.counter-count {
    flex: none;
    font-family: var(--mono);
    font-size: 0.6875rem;
    color: var(--sur-coque-2);
}

.counter.is-ready .counter-count { color: var(--or-clair); }

/* ---- La feuille du comptoir ---- */

/* Ce qu'il dit est en serif, comme dans son arc : c'est une voix. */
.counter-line {
    font-family: var(--serif);
    font-size: 0.90625rem;
    line-height: 1.5;
    color: var(--encre);
    margin: 14px 0 12px;
}

.counter-order {
    padding: 12px 13px;
    background: var(--surface-sourd);
    border-radius: var(--r-sm);
}

.counter-want { font-size: 0.8125rem; font-weight: 500; color: var(--encre); }

.counter-need {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    font-size: 0.75rem;
    color: var(--encre-3);
    margin-top: 3px;
}

.counter-have { font-family: var(--mono); font-size: 0.71875rem; color: var(--encre-3); }
.counter-have.is-ok { color: var(--accent); }

.counter-brew,
.counter-verdict,
.counter-pay,
.counter-again {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 0.75rem;
    line-height: 1.45;
    color: var(--encre-2);
}

.counter-brew { margin-top: 10px; }
.counter-brew > svg { flex: none; color: var(--encre-4); }
.counter-brew.is-ok > svg { color: var(--accent); }

.counter-verdict { font-size: 0.71875rem; color: var(--encre-3); margin-top: 2px; }

/* La ligne qui dit « ce n'est pas ce qui est demandé » avait exactement la
   couleur et la taille de celle qui dit le contraire : seuls les mots
   changeaient. Terre cuite, jamais de rouge vif — on n'a rien cassé, on a
   choisi. Voir `.counter-serve.is-mismatch` pour l'autre moitié de la règle. */
.counter-verdict.is-mismatch { color: var(--alerte); font-weight: 500; }

.counter-pay {
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--filet);
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--or);
}

.counter-pay > svg { flex: none; color: var(--or); }

.counter-serve {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    min-height: var(--touch);
    margin-top: 14px;
    padding: 12px 14px;
    background: var(--accent);
    color: var(--sur-accent);
    /* Transparente et non absente : `.is-mismatch` la rend visible, et les deux
       états doivent faire la même hauteur — sinon le bouton saute de 2 px selon
       ce qu'on vient d'infuser. */
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    font-family: inherit;
    font-size: 0.875rem;
    font-weight: 500;
    cursor: pointer;
}

/* Une commande qui ne correspond pas se sert QUAND MÊME — c'est la troisième
   sortie du §3.2, celle qui fait tenir l'« aucun blocage ». Mais elle cesse
   d'être L'action, et le vert la suit : il ne marque que ce qui attend le
   joueur, et ce qui l'attend ici est d'aller infuser ce qu'on lui demande.

   Signalé à l'œil par le propriétaire le 11/08/2026 : « l'instituteur attend
   de la sauge, je peux lui donner de la menthe et gagner ». Le jeu ne donnait
   RIEN — l'arc n'avançait pas, le bonus n'était pas versé — mais le même
   bouton vert menait aux deux issues, l'habitant repartait pareil, et le
   verdict qui l'expliquait était du même gris que celui qui félicite. Rien
   n'était faux, rien ne se voyait.

   Il reste plein contour et texte d'encre, jamais le gris de `:disabled` : ce
   n'est pas un refus, c'est un choix qu'on n'encourage pas. */
.counter-serve.is-mismatch {
    background: none;
    color: var(--encre);
    border-color: var(--filet-fort);
}

.counter-serve.is-mismatch > svg { color: var(--encre-3); }

.counter-serve:disabled { background: var(--filet-fort); color: var(--encre-3); cursor: default; }
.counter-serve:disabled.is-mismatch { border-color: transparent; color: var(--encre-3); }
.counter-serve:not(:disabled):active { transform: scale(0.985); }

.counter-missing {
    font-size: 0.71875rem;
    color: var(--encre-3);
    text-align: center;
    margin-top: 7px;
}

/* ---- Sa réponse : le fragment d'histoire que la commande libère ---- */

.counter-vignette {
    font-family: var(--serif);
    font-size: 0.875rem;
    line-height: 1.65;
    color: var(--encre);
    margin: 14px 0;
}

.counter-receipt {
    padding: 12px 13px;
    margin-bottom: 16px;
    background: var(--surface-sourd);
    border-radius: var(--r-sm);
}

.counter-pay.is-paid { margin-top: 0; padding-top: 0; border-top: 0; }
.counter-again { font-size: 0.71875rem; color: var(--encre-3); margin-top: 6px; }

/* ==================== LA CARTE D'ACCUEIL ====================
   Elle doit se comprendre sans savoir lire : quatre icônes, quatre mots, trois
   chevrons. Tout le reste est en retrait.
   ========================================================================= */

.welcome { text-align: center; }

.welcome-mark {
    display: inline-flex;
    color: var(--accent);
    margin-bottom: 10px;
}

.welcome-title {
    font-family: var(--serif);
    font-size: 1.375rem;
    font-weight: 400;
    line-height: 1.2;
    margin-bottom: 7px;
}

.welcome-sub {
    font-size: 0.8125rem;
    line-height: 1.5;
    color: var(--encre-2);
    margin-bottom: 20px;
}

/* La boucle. Les quatre gestes tiennent sur une ligne en 390 px : c'est la
   condition pour qu'on les lise d'un seul regard, et non l'un après l'autre. */
.welcome-loop {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    gap: 2px;
    padding: 16px 4px;
    background: var(--surface-sourd);
    border-radius: var(--r);
}

.welcome-step {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 7px;
    min-width: 0;
    flex: 1;
}

.welcome-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: var(--surface);
    border: 1px solid var(--filet-fort);
    color: var(--accent);
}

.welcome-word {
    font-size: 0.71875rem;
    font-weight: 500;
    line-height: 1.2;
    color: var(--encre);
}

/* Le chevron se pose à hauteur des ronds, pas des mots. */
.welcome-arrow {
    flex: none;
    display: inline-flex;
    align-items: center;
    height: 48px;
    color: var(--encre-4);
}

.welcome-again {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    margin-top: 9px;
    font-size: 0.71875rem;
    color: var(--encre-3);
}

.welcome-again > svg { flex: none; }

.welcome-book {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 16px;
    margin-bottom: 20px;
    padding: 11px 13px;
    background: var(--accent-voile);
    border-radius: var(--r-sm);
    font-size: 0.78125rem;
    line-height: 1.45;
    color: var(--encre-2);
    text-align: start;
}

.welcome-book > svg { flex: none; color: var(--accent); }

/* ==================== LE DÉPANNAGE DE FLORA ====================
   Il n'apparaît que dans l'état absorbant : plus rien nulle part. Il doit se
   voir sans crier — c'est une main tendue, pas une alerte.
   ========================================================================= */

.rescue {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px;
    margin-bottom: 18px;
    background: var(--accent-voile);
    border: 1px solid var(--accent-filet);
    border-radius: var(--r-sm);
}

.rescue-top { display: flex; align-items: flex-start; gap: 12px; }
.rescue-top > svg { flex: none; margin-top: 1px; color: var(--accent); }
.rescue-text { min-width: 0; }
.rescue-name { font-size: 0.84375rem; font-weight: 500; color: var(--encre); }
.rescue-note { font-size: 0.78125rem; line-height: 1.45; color: var(--encre-2); margin-top: 3px; }

/* Le gratuit est le bouton plein ; la vidéo reste en pointillé sous lui. Le
   §7.3 se lit dans la hiérarchie visuelle autant que dans le code. */
/* `.rescue-take` porte l'habit de `.modal-close` (voir MODALES). Le rayon est
   REDIT ici, après `:focus-visible` — qui pose `border-radius: var(--r-xs)` à
   même spécificité — pour que le bouton garde le sien au clavier, comme le
   faisait la règle d'origine, écrite à cette place. */
.rescue-take { border-radius: var(--r); }

.rescue-take:hover { background: var(--accent-fonce); border-color: var(--accent-fonce); }
.rescue .ad-cta.is-wide { margin-top: 0; }

/* ==================== L'ANNONCE D'UN LIEU ====================
   Même famille que la carte d'accueil : centrée, une icône, une phrase, et un
   bouton qui EMMÈNE plutôt qu'il ne renvoie.
   ========================================================================= */

.lieu { text-align: center; }

.lieu-mark {
    display: inline-flex;
    color: var(--accent);
    margin-bottom: 12px;
}

.lieu-title {
    font-family: var(--serif);
    font-size: 1.25rem;
    font-weight: 400;
    line-height: 1.2;
    margin-bottom: 8px;
}

.lieu-note {
    font-size: 0.8125rem;
    line-height: 1.55;
    color: var(--encre-2);
    margin-bottom: 20px;
}

/* « Plus tard » existe et se voit : une annonce qu'on ne peut pas remettre
   n'est plus une annonce, c'est une interruption. Elle reste sur --encre-3,
   au-dessus du seuil AA.

   Le comptoir emprunte le même retrait, et pour la même raison : renvoyer un
   habitant n'est pas le servir. Les deux gestes portaient le vert plein de
   `.modal-close` et pesaient donc exactement pareil — vu à l'écran, pas
   mesuré. */
.lieu-later,
.counter-later {
    width: 100%;
    min-height: var(--touch);
    margin-top: 8px;
    background: none;
    border: 0;
    font-family: inherit;
    font-size: 0.78125rem;
    color: var(--encre-3);
    cursor: pointer;
}

.lieu-later:hover,
.counter-later:hover { color: var(--encre); }

/* ==================== PARTAGE (§4.2) ====================
   Un bouton de partage n'est pas une action du jeu : il ne fait pas pousser,
   ne fait pas infuser, ne fait rien gagner. Il porte donc le contour clair des
   gestes secondaires, jamais le vert plein de `.modal-close` — le vert d'accent
   ne marque que ce qui attend le joueur.

   Il ne vit qu'à froid : le record dans la feuille des statistiques, une page
   dans le grimoire. Le panneau d'infusion n'en porte plus depuis le
   12/08/2026 — on ne sollicite pas le joueur à la seconde où il vient de
   réussir — et il n'a donc plus de voisin doré dont il faudrait le distinguer.
   ========================================================================= */

.share-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    width: 100%;
    min-height: var(--touch);
    margin-top: 8px;
    padding: 0 14px;
    border: 1px solid var(--filet-fort);
    border-radius: var(--r);
    background: transparent;
    color: var(--encre-2);
    font-family: inherit;
    font-size: 0.8125rem;
    cursor: pointer;
    transition: border-color 0.2s, color 0.2s;
}

.share-btn > svg { flex: none; color: var(--encre-3); }
.share-btn:hover { border-color: var(--accent-filet); color: var(--encre); }
.share-btn:hover > svg { color: var(--accent); }
.share-btn:active { transform: scale(0.99); }

/* Dernier recours du partage : ni feuille système, ni presse-papier. Le texte
   s'affiche, sélectionnable, et le joueur le recopie. */
.share-text {
    font-size: 0.8125rem;
    line-height: 1.6;
    color: var(--encre);
    user-select: all;
    word-break: break-word;
}

/* ==================== LE RENDEZ-VOUS DE FLORA (§4.3) ====================
   Ce qu'elle a laissé, posé au creux de la carte. Un aplat très clair plutôt
   qu'un cadre : c'est un cadeau, pas un formulaire.
   ========================================================================= */

.rdv-cadeau {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin: 14px 0 4px;
    padding: 13px 15px;
    border: 1px solid var(--accent-filet);
    border-radius: var(--r);
    background: var(--accent-voile);
    text-align: start;
}

.rdv-cadeau > svg { flex: none; margin-top: 1px; color: var(--accent); }

.rdv-cadeau p {
    font-size: 0.8125rem;
    line-height: 1.55;
    color: var(--encre);
}

.rdv-cadeau b { font-weight: 600; }
