:: StoryTitle
Hojo Tigers — Tome 1


:: StoryData
{
  "ifid": "13431f45-7bbe-4e7e-b91b-236a82d4669d",
  "format": "SugarCube",
  "format-version": "2.36.1",
  "start": "Ecran_Titre",
  "zoom": 0.6
}


:: -webkit-scrollbar {"position":"25,25","size":"100,100"}



:: -webkit-scrollbar-thumb {"position":"275,25","size":"100,100"}



:: -webkit-scrollbar-thumb:hover {"position":"400,25","size":"100,100"}
/* Menu : tous les styles sont inlinés en JS (voir StoryScript) */

/* ═══════════════════════════════════════
   MASQUER TOUS LES ÉLÉMENTS SUGARCUBE PAR DÉFAUT
   On gère notre propre menu / navigation.
   ═══════════════════════════════════════ */
#ui-bar,
#ui-bar-toggle,
#ui-bar-history,
#ui-bar-body,
#menu-story,
#menu-core,
#menu-item-saves,
#menu-item-settings,
#menu-item-restart,
#menu-item-share,
#story-caption,
#story-banner,
.passage .debug {
  display: none !important;
  visibility: hidden !important;
  width: 0 !important;
  height: 0 !important;
  overflow: hidden !important;
  position: absolute !important;
  left: -9999px !important;
}


:: -webkit-scrollbar-track {"position":"150,25","size":"100,100"}



:: Acte1_Arrivee {"position":"50,1450","size":"100,100"}
# Acte I — Sans filet

L'Académie Hojo est perchée sur les hauteurs d'Odawara, entre un bois de cryptomères et un terrain synthétique que le vent de mer a blanchi. Les bâtiments sont modestes — béton des années soixante-dix, fenêtres larges, préaux couverts. Rien de clinquant. Rien de miséreux non plus. Un endroit qui ne prétend pas être autre chose que ce qu'il est.

Le terrain de foot est derrière le gymnase. Tu l'aperçois en traversant la cour : pelouse naturelle, filets raccommodés, un petit gradin de bois couvert. Un type roux en survêtement crie quelque chose à un groupe de joueurs en plein échauffement.

Max Cerri. Tu le reconnais immédiatement. Ancien attaquant international, silhouette de sportif reconverti, gestes secs. Il t'a vu. Il termine sa phrase sans changer de ton, puis marche vers toi.

<p>— <<if $playerGender is "M">>« Le nouveau. T'es en avance. C'est bien. »<<else>>« La nouvelle. T'es en avance. C'est bien. »<</if>></p>

Il te tend une paire de crampons.

<p>— « Enfile ça. Tu regardes l'entraînement aujourd'hui. Demain, tu joues. »</p>

<<set $relations["Max"] += 5>>

Tu t'assieds sur le gradin. De là, tu vois tout.

L'équipe tourne. Les passes claquent, les appels sont précis, les automatismes visibles. C'est un groupe qui se connaît — et qui ne t'attendait pas.

Tu identifies rapidement les figures principales.

Un garçon aux cheveux bleu marine se déplace avec une économie de mouvements presque suspecte. Chaque geste est calibré. Il ne court pas plus vite que nécessaire, ne frappe pas plus fort que requis. Quand il parle, les autres écoutent. Il ne parle presque jamais.

<div class="encadre encadre-info">
<div class="encadre-titre">Audy Rayke — Capitaine</div>
Attaquant. 2ème année. Orphelin, élevé à l'académie. Carnet secret. Hypervigilant. Il t'a vu. Il n'a rien dit.
</div>

Une fille aux cheveux violets récupère un ballon et déclenche une combinaison à deux touches — élégante, rapide, limpide. Puis un centre arrive. Elle est seule devant le but. Elle... hésite. Un quart de seconde. La balle arrive sur un coéquipier moins bien placé. Personne ne commente. Tout le monde a vu.

<div class="encadre encadre-info">
<div class="encadre-titre">Saera Handa — Meneur de jeu</div>
Attaquante. 2ème année. Blessée l'an passé par un tacle de la Royal Academy. Le geste est revenu. La confiance, pas encore.
</div>

Un type aux cheveux argentés s'approche du gradin et te lance une bouteille d'eau avec un sourire.

<p>— « Bienvenue chez les Tigres. T'inquiète, Max aboie plus qu'il ne mord. Enfin... ça dépend des jours. »</p>

<<set $relations["Thomas"] += 5>>

<div class="scene-break">· · ·</div>

L'entraînement se termine. Tu es dans le vestiaire. Thomas fait les présentations. Nayn te jauge avec un regard direct — pas hostile, pas amical. Lucie te serre la main avec une énergie qui fait presque mal. Mizuki te regarde de loin, bras croisés, sans rien dire.

Et Naela — petite, cheveux noirs, yeux verts — te sourit. Simplement.

<p>— « J'espère que tu tiendras. On a besoin de monde. »</p>

<<set $relations["Naela"] += 5>>

La soirée tombe. Première nuit à Hojo. Demain, premier entraînement complet. Après-demain, un match amical contre une équipe locale. Max veut voir ce que tu vaux.

Mais ce soir, il te reste un créneau libre.

[[Aller parler à Thomas — il semble ouvert, c'est le plus accessible.|Acte1_Soiree_Thomas]]
[[Observer l'entraînement d'Audy — il est encore sur le terrain, seul, dans la nuit.|Acte1_Soiree_Audy]]
[[Rejoindre Naela et Mizuki à l'orphelinat — elles y retournent après l'entraînement.|Acte1_Soiree_Orphelinat]]


:: Acte1_Ch2_Audy_Humain {"position":"550,1950","size":"100,100"}
Un long silence. Audy te regarde comme s'il cherchait le piège.

<p>— « ... D'accord. »</p>

Vous restez dans la salle vidéo. Il ne parle pas beaucoup. Mais il ne te demande pas de partir. À un moment, il mentionne l'orphelinat — Naela, Mizuki, lui. Tous les trois ont grandi là.

<p>— « Naela m'a convaincu de rejoindre le club. Je ne voulais pas. Elle a insisté pendant trois semaines. Tous les jours. Même quand je ne lui répondais pas. »</p>

Un micro-sourire. C'est la chose la plus personnelle qu'il t'ait dite.

<<set $relations["Audy"] += 10>>

<div class="encadre encadre-relation">
<div class="encadre-titre">Lien personnel</div>
Audy t'a laissé entrer, un peu. La confiance relationnelle est plus lente — mais plus profonde.
</div>

[[Utiliser ton deuxième créneau.|Acte1_Ch2_Creneau2]]


:: Acte1_Ch2_Audy_Tactique {"position":"425,1950","size":"100,100"}
Audy te regarde. Évalue. Puis il rouvre un carnet — le tactique, cette fois — et commence à te montrer des schémas.

<p>— « Le Groupe B. Shuriken, Terria, Sunshine Academy, Collège Alpin. Shuriken est dangereux — formation dirigée par un type qui s'appelle Arno Schwartz. Je n'ai pas assez d'infos sur eux. Ça m'embête. »</p>

Il te montre des notes détaillées sur chaque équipe. C'est méthodique, exhaustif, obsessionnel. Et brillant.

<<set $relations["Audy"] += 8>>
<<set $reputation += 2>>

<div class="encadre encadre-info">
<div class="encadre-titre">Confiance tactique</div>
Audy te fait confiance sur le terrain. C'est un premier pas.
</div>

[[Utiliser ton deuxième créneau.|Acte1_Ch2_Creneau2]]


:: Acte1_Ch2_Creneau2 {"position":"1175,1950","size":"100,100"}
## Deuxième créneau

Il te reste un moment avant la fin de la journée.

<<if not $flags["match_amical_joue"]>>
[[S'entraîner.|Acte1_Ch2_Entrainement]]
<</if>>
[[Aller à l'orphelinat — voir Élise et l'ambiance du lieu.|Acte1_Ch2_Orphelinat]]
[[Se reposer — récupération et préparation mentale.|Acte1_Ch2_Repos]]
[[Parler à Saera — elle est souvent seule après les entraînements.|Acte1_Ch2_Saera2]]


:: Acte1_Ch2_Entrainement {"position":"1050,1825","size":"100,100"}
## Entraînement individuel

Tu choisis de travailler seul après la séance collective. Le terrain est libre, le soir tombe.

<<if $playerPoste is "attaquant">>
Tu travailles les enchaînements devant le but — contrôle, pivot, frappe. Encore. Encore. Le geste se cale.
<<set $technique += 3>>

<div class="encadre encadre-info">
<div class="encadre-titre">Progression</div>
Technique +3 (<<print $technique>>)
</div>

<<elseif $playerPoste is "défenseur">>
Tu fais des sprints, des changements de direction, du travail de duels contre un mur. L'intensité est brutale.
<<set $physique += 3>>

<div class="encadre encadre-info">
<div class="encadre-titre">Progression</div>
Physique +3 (<<print $physique>>)
</div>

<<else>> /* milieu */
Tu travailles la circulation de balle — passes courtes, contrôles orientés, lecture des espaces. Répétition, ajustement, précision.
<<set $technique += 3>>

<div class="encadre encadre-info">
<div class="encadre-titre">Progression</div>
Technique +3 (<<print $technique>>)
</div>
<</if>>

[[Utiliser ton deuxième créneau — relation ou exploration.|Acte1_Ch2_Creneau2]]


:: Acte1_Ch2_Explorer {"position":"800,1950","size":"100,100"}
## Explorer l'académie

Tu quittes les zones habituelles — terrain, dortoir, réfectoire — et tu marches.

L'Académie Hojo est plus grande qu'il n'y paraît. Derrière le gymnase, un sentier descend vers l'orphelinat Hatakeyama. À gauche, un vieux bâtiment administratif où Max a son bureau.

En passant devant la porte entrouverte du bureau de Max, tu entends une voix. Pas la sienne. Une voix féminine, tendue. Au téléphone — haut-parleur.

<p>— « ... et je ne changerai pas d'avis. Tu as fait ton choix, Max. Je fais le mien. La notification partira en fin de mois. »</p>

<p>— « Léa, attends — »</p>

La communication coupe. Un silence. Puis le bruit d'une main qui frappe un bureau.

Tu as entendu quelque chose que tu n'aurais probablement pas dû entendre.

<<set $flags["sponsor_connu"] to true>>

[[Partir discrètement. Tu en parleras à Thomas plus tard.|Acte1_Ch2_Explorer_Partir]]
[[Frapper à la porte. Voir comment Max réagit.|Acte1_Ch2_Explorer_Frapper]]


:: Acte1_Ch2_Explorer_Frapper {"position":"1050,1950","size":"100,100"}
Tu frappes. Silence. Puis :

<p>— « ... Entre. »</p>

Max est debout, les mains à plat sur le bureau. Il te regarde. Évalue ce que tu as pu entendre.

<p>— « Tu voulais quelque chose ? »</p>

Son ton est neutre — trop neutre.

<p>— « Je passais. La porte était ouverte. »</p>

Un temps.

<p>— « D'accord. Ferme-la en sortant. »</p>

Il ne te demande pas si tu as entendu. Il sait que tu as entendu. Et il choisit de ne rien dire.

<<set $relations["Max"] += 5>>

<div class="encadre encadre-secret">
<div class="encadre-titre">Pacte tacite</div>
Max sait que tu sais. Tu sais que Max sait que tu sais. Personne ne dit rien. Ce moment créera une dynamique unique plus tard.
</div>

[[Deuxième créneau libre.|Acte1_Ch2_Creneau2]]


:: Acte1_Ch2_Explorer_Partir {"position":"925,1950","size":"100,100"}
Tu t'éloignes sans bruit. La voix de Max résonne encore dans ta tête. « Léa. » Léa Voss. Le sponsor.

Quelque chose ne va pas. Et ça concerne tout le monde.

<<set $relations["Thomas"] += 3>>

<div class="encadre encadre-secret">
<div class="encadre-titre">Information sensible</div>
Tu sais maintenant que le sponsoring de Hojo est menacé. Léa Voss a parlé de « notification ». Max n'a pas su la retenir. Cette information pèse — et tu devras décider quoi en faire.
</div>

[[Deuxième créneau libre.|Acte1_Ch2_Creneau2]]


:: Acte1_Ch2_Orphelinat {"position":"50,2075","size":"100,100"}
L'orphelinat est calme ce soir. Élise Nakamura t'accueille avec un thé. Les enfants sont couchés. Naela est dans sa chambre. Mizuki lit un manga dans le salon, les pieds sur la table.

Élise est chaleureuse, directe, sans artifices. Elle te pose des questions sur ton adaptation — sincères, pas protocolaires.

<p>— « Max m'a dit que tu avais du potentiel. Venant de lui, c'est énorme. Il ne dit jamais ça. »</p>

Tu notes que quand elle parle de Max, quelque chose change dans sa voix. Pas de l'admiration. Pas de la distance non plus. Quelque chose de plus intime. De plus ancien.

<<set $relations["Naela"] += 3>>
<<set $relations["Mizuki"] += 3>>

[[→ Préparer le Football Frontier. L'histoire continue.|Interlude_Acte2]]


:: Acte1_Ch2_Rel_Audy {"position":"300,1950","size":"100,100"}
Tu trouves Audy dans la salle vidéo, comme d'habitude. Cette fois, il a un carnet ouvert — pas celui des tactiques. Un autre. Il le ferme en te voyant. Vite, mais pas assez vite pour que tu ne remarques pas les noms écrits à l'intérieur.

<p>— « Tu voulais quelque chose ? »</p>

[[« Je voulais parler du prochain match. Comment tu vois le tournoi ? »|Acte1_Ch2_Audy_Tactique]]
[[« Je voulais juste passer du temps. On est dans la même équipe. »|Acte1_Ch2_Audy_Humain]]


:: Acte1_Ch2_Rel_Naela {"position":"175,1950","size":"100,100"}
Tu trouves Naela dans la bibliothèque de l'académie, un cahier de maths ouvert devant elle. Elle ne fait manifestement pas de maths — elle dessine des schémas tactiques dans la marge.

<p>— « Oh, c'est toi. Tu travailles ici aussi ? Tire une chaise. »</p>

Vous discutez. De football, d'abord — elle analyse les matchs avec une intelligence qui surprend pour une première année. Puis de l'orphelinat, de Mizuki, d'Élise.

<p>— « Élise dit toujours que le talent, c'est ce que tu fais quand personne ne regarde. J'aime bien ça. »</p>

À un moment, elle masse discrètement son poignet. Un geste rapide, presque invisible. Elle voit que tu l'as vu — et change de sujet.

<<set $relations["Naela"] += 8>>

[[Utiliser ton deuxième créneau.|Acte1_Ch2_Creneau2]]


:: Acte1_Ch2_Rel_Nayn {"position":"675,1950","size":"100,100"}
Nayn est sur le terrain, tout seul, et travaille ses frappes. Des bicyclettes, encore et encore. C'est sa marque de fabrique — et il la perfectionne avec une obstination qui force le respect.

<p>— « Tu viens t'entraîner ou tu viens regarder ? »</p>

Tu t'entraînes. Quarante minutes de travail intense. Nayn ne parle pas pendant l'effort — mais après, assis sur le banc, il ouvre un peu.

<p>— « L'an passé, j'étais un emmerdeur. Le Trio Infernal, tout ça. Max m'a recadré. Pas en criant — en me montrant ce que je gâchais. Depuis, j'essaie d'être le joueur que le groupe mérite. »</p>

<<set $relations["Nayn"] += 8>>
<<set $physique += 1>>

[[Utiliser ton deuxième créneau.|Acte1_Ch2_Creneau2]]


:: Acte1_Ch2_Rel_Thomas {"position":"50,1950","size":"100,100"}
Thomas est au réfectoire, seul. Inhabituel — d'habitude, il est au centre de tout. Il te voit et fait signe de t'asseoir.

<p>— « J'ai vu un truc hier. Max était au téléphone près du gymnase. Il pensait être seul. Il avait l'air... pas bien. Pas en colère. Défait. »</p>

<<if $flags["thomas_confiance"]>>
<p>— « Tu te souviens de ce que je t'ai dit ? Sur les appels ? Je crois que c'est plus grave que je pensais. Quelque chose se passe avec le sponsor. Avec Léa Voss. »</p>

<<set $relations["Thomas"] += 8>>
<<set $flags["sponsor_connu"] to true>>
<<else>>
<p>— « C'est peut-être rien. Mais si c'est quelque chose... ça concerne tout le monde. »</p>

<<set $relations["Thomas"] += 5>>
<</if>>

[[Utiliser ton deuxième créneau.|Acte1_Ch2_Creneau2]]


:: Acte1_Ch2_Relation {"position":"1175,1825","size":"100,100"}
## Temps libre — Choisir un coéquipier

Qui veux-tu aller voir ?

[[Thomas — il semble porter quelque chose de lourd.|Acte1_Ch2_Rel_Thomas]]
[[Naela — tu veux mieux la connaître.|Acte1_Ch2_Rel_Naela]]
<<if $relations["Audy"] >= 25>>[[Audy — il ne viendra pas à toi. C'est à toi d'aller vers lui.|Acte1_Ch2_Rel_Audy]]<</if>>
[[Nayn — le compétiteur. Tu sens qu'il a besoin de quelqu'un qui tient tête.|Acte1_Ch2_Rel_Nayn]]


:: Acte1_Ch2_Repos {"position":"175,2075","size":"100,100"}
Tu te couches tôt. Sommeil profond, sans rêve.

<<set $energy to $energyMax>>

<div class="encadre encadre-info">
<div class="encadre-titre">Récupération</div>
Énergie restaurée à <<print $energyMax>>. Tu es prêt pour la suite.
</div>

[[→ Préparer le Football Frontier. L'histoire continue.|Interlude_Acte2]]


:: Acte1_Ch2_Saera2 {"position":"300,2075","size":"100,100"}
Saera est sur le terrain, assise dans l'herbe cette fois. Pas de ballon. Elle regarde le ciel.

<p>— « Tu savais que mon père vient à tous les matchs ? Il s'assied toujours au même endroit. Troisième rang, côté gauche. Il ne crie jamais. Il regarde. »</p>

Un silence.

<p>— « Il a beaucoup d'argent. Il pourrait sponsoriser dix clubs. Mais il ne le fait pas. C'est pas son monde. Il respecte ce que Max construit, mais il ne s'en mêle pas. Pas tant que personne ne lui demande. »</p>

Elle dit ça comme une information neutre. Mais tu sens que ce n'est pas anodin.

<<set $relations["Saera"] += 5>>

<div class="encadre encadre-secret">
<div class="encadre-titre">Information narrative</div>
M. Handa, le père de Saera, est un entrepreneur prospère d'Odawara. Il pourrait sponsoriser Hojo — mais il faudrait que quelqu'un le lui demande. Et ce quelqu'un, c'est Saera.
</div>

[[→ Préparer le Football Frontier. L'histoire continue.|Interlude_Acte2]]


:: Acte1_Ch2_Sponsor {"position":"925,1825","size":"100,100"}
# Acte I — Chapitre 2 : La question du sponsor

Lundi matin. La routine s'installe — cours le matin, entraînement l'après-midi. Tu commences à trouver tes repères dans les couloirs de l'Académie Hojo, à reconnaître les visages, à anticiper les habitudes de chacun.

Mais une tension diffuse flotte dans l'air. Elle ne vient pas du terrain.

Max est au téléphone entre deux séances. Souvent. Il s'éloigne du groupe, parle à voix basse, raccroche avec un geste sec. Personne ne commente — mais tout le monde a remarqué.

En salle commune, tu surprends une conversation entre Nayn et Clément :

<p>— « T'as vu que l'inscription au Football Frontier, c'est dans deux semaines ? Max a rien dit sur le sponsor. »</p>

<p>— « C'est Léa Voss qui finance, non ? La copine de Max. C'est réglé. »</p>

<p>— « Ouais. En principe. »</p>

Il n'ajoute rien. Mais le « en principe » reste en l'air.

<div class="scene-break">· · ·</div>

La semaine avance. Tu as deux créneaux libres avant le prochain entraînement intensif.

[[Entraînement individuel — travailler tes points faibles.|Acte1_Ch2_Entrainement]]
[[Passer du temps avec un coéquipier — renforcer un lien.|Acte1_Ch2_Relation]]
[[Explorer l'académie — quelque chose te dit qu'il y a des choses à découvrir.|Acte1_Ch2_Explorer]]


:: Acte1_Entrainement_J1 {"position":"550,1450","size":"100,100"}
## Premier entraînement

Le lendemain, 8h00. Terrain. Max siffle.

L'entraînement est intense — exercices techniques, jeu réduit, phases de pressing. Max crie. Beaucoup. Ses joueurs ne bronchent pas. Tu comprends vite : les cris sont du langage, pas de l'agressivité. Il ajuste, il corrige, il exige. Chaque remarque est précise.

Ton tour arrive. Jeu réduit, 5 contre 5.

<<if $playerPoste is "attaquant">>
Tu es aligné avec Thomas et Nayn face à Audy, Saera et Mizuki. Le niveau est brutal. Les espaces se ferment en une seconde. Nayn récupère, Thomas distribue — mais les passes arrivent vite, tendues, et l'erreur se paie immédiatement.

Un ballon arrive dans ta zone. Le défenseur est sur toi.
<<elseif $playerPoste is "milieu">>
Tu es au cœur du jeu, entre Thomas et Clément. Les ballons transitent par toi — ou pas, si tu ne te montres pas. Le rythme est soutenu, la circulation rapide.

Un ballon arrive dans ta zone. Deux adversaires ferment l'espace.
<<elseif $playerPoste is "défenseur">>
Tu es face à Mizuki en 1v1 sur une phase de débordement. Elle est rapide — très rapide. Et elle a un sourire qui dit qu'elle sait qu'elle est rapide.

Elle reçoit le ballon et fonce vers toi.
<<else>>
Tu es dans les cages. Nayn arme une frappe depuis vingt mètres. Le ballon arrive plus vite que prévu. Teo, sur le banc, regarde avec un mélange de curiosité et de compétition.

La balle file vers le coin gauche.
<</if>>

C'est ton premier moment de vérité. Pas un match. Un entraînement. Mais Max regarde. Audy regarde. Tout le monde regarde.

[[Jouer la sécurité — geste propre, sans risque, montrer que tu sais faire.|Acte1_Entrainement_Securite]]
[[Tenter quelque chose — le geste qui fait lever la tête, quitte à rater.|Acte1_Entrainement_Risque]]


:: Acte1_Entrainement_Risque {"position":"800,1450","size":"100,100"}
<<if $playerPoste is "attaquant">>
Tu reçois dos au but, tu sens le défenseur coller derrière toi. Au lieu de remettre, tu laisses passer le ballon entre tes jambes, tu pivotes — et tu frappes. Du gauche. Le ballon file au ras du poteau.

Raté. Mais le geste est là.
<<elseif $playerPoste is "milieu">>
Tu reçois entre les lignes, et au lieu de jouer simple, tu enchaînes contrôle orienté – crochet – passe lobée vers l'attaque. Le ballon retombe parfaitement devant Naela, qui ne s'y attendait pas. Elle le contrôle, surprise. L'action meurt — mais la passe était parfaite.
<<elseif $playerPoste is "défenseur">>
Mizuki fonce. Tu plonges — tacle glissé, pied gauche. Net. Le ballon jaillit de ses pieds. Elle trébuche, se relève, te regarde.

<p>— « Pas mal. Refais ça en match et je serai moins gentille. »</p>

<<set $relations["Mizuki"] += 5>>
<<else>>
Tu vois la frappe de Nayn arriver. Au lieu de plonger classiquement, tu sors du but — un pas — et tu coupes l'angle avec le corps. Le ballon rebondit sur ta poitrine. Récupération.

Teo, depuis le banc, lève un sourcil.

<<set $relations["Teo"] += 5>>
<</if>>

Max s'arrête une seconde. Puis :

<p>— <<if $playerGender is "M">>« Le petit a des idées. »<<else>>« La petite a des idées. »<</if>></p>

<<set $reputation += 5>>
<<set $relations["Max"] += 5>>
<<set $relations["Audy"] += 3>>

<div class="encadre encadre-info">
<div class="encadre-titre">Réputation</div>
Ton audace attire l'attention. L'équipe retient ton nom — en bien ou en attente de confirmation. Le prochain match sera le vrai test.
</div>

[[La fin de l'entraînement approche. Demain, match amical.|Acte1_Veille_Match]]


:: Acte1_Entrainement_Securite {"position":"675,1450","size":"100,100"}
<<if $playerPoste is "attaquant">>
Tu protèges le ballon, pivotes, et remets en retrait vers Thomas. Propre. Efficace. Pas spectaculaire — mais correct.
<<elseif $playerPoste is "milieu">>
Tu joues en une touche vers Clément. La passe est bonne, le timing juste. L'action continue sans toi, mais elle continue grâce à toi.
<<elseif $playerPoste is "défenseur">>
Tu recules, tu gardes l'intervalle. Mizuki tente un crochet — tu ne plonges pas. Elle passe par l'extérieur, mais son centre est contré par Sandro derrière toi. Tu as tenu ta position.
<<else>>
Tu plonges sur le bon côté, couvres l'angle. Le ballon frappe tes gants et roule en corner. Prise sûre, rien de miraculeux.
<</if>>

Thomas hoche la tête. Nayn ne dit rien. Max ne commente pas — ce qui, paradoxalement, signifie qu'il n'a rien à redire.

Audy écrit quelque chose dans son carnet, sur le banc.

<<set $reputation += 3>>
<<set $relations["Max"] += 3>>

<div class="encadre encadre-info">
<div class="encadre-titre">Réputation</div>
Ton jeu est propre. L'équipe te note comme fiable. La confiance viendra par l'accumulation, pas par l'éclat.
</div>

[[La fin de l'entraînement approche. Demain, match amical.|Acte1_Veille_Match]]


:: Acte1_Entrainement_Special {"position":"175,1825","size":"100,100"}
## Séance individuelle

Deux jours après le match, Max te convoque sur le terrain à 7h. Personne d'autre. Il a une série de cônes sous le bras et un ballon au pied.

<p>— « T'as montré des choses. Maintenant on travaille un point précis. Choisis ce que tu veux améliorer. »</p>

Il pose trois exercices devant toi.

<<if $playerPoste is "attaquant">>
<div class="creation-options">
<span class="creation-opt" data-passage="Acte1_Upgrade_Result" data-setter="$upgradeChoice to 'dribble'">
<div class="creation-opt-title">Travail de dribble</div>
<div class="creation-opt-desc">Enchaînements, crochets, feintes. Transformer ton Dribble en Crochet intérieur (F:5 → F:6).</div>
</span>

<span class="creation-opt" data-passage="Acte1_Upgrade_Result" data-setter="$upgradeChoice to 'tir_place'">
<div class="creation-opt-title">Finition pure</div>
<div class="creation-opt-desc">Face au but, encore et encore. Transformer ton Tir placé en Tir chirurgical (F:6 → F:7).</div>
</span>

<span class="creation-opt" data-passage="Acte1_Upgrade_Result" data-setter="$upgradeChoice to 'sprint'">
<div class="creation-opt-title">Explosivité</div>
<div class="creation-opt-desc">Démarrages, changements de rythme. Transformer ton Sprint en Accélération explosive (F:5 → F:6).</div>
</span>
</div>

<<elseif $playerPoste is "milieu">>
<div class="creation-options">
<span class="creation-opt" data-passage="Acte1_Upgrade_Result" data-setter="$upgradeChoice to 'passe_courte'">
<div class="creation-opt-title">Précision de passe</div>
<div class="creation-opt-desc">Circulation, tempo, placement. Transformer ta Passe courte en Passe laser (F:7 → F:8).</div>
</span>

<span class="creation-opt" data-passage="Acte1_Upgrade_Result" data-setter="$upgradeChoice to 'interception'">
<div class="creation-opt-title">Lecture du jeu</div>
<div class="creation-opt-desc">Anticiper, couper, récupérer. Transformer ton Interception en Lecture anticipée (F:6 → F:7, +phase ATT).</div>
</span>

<span class="creation-opt" data-passage="Acte1_Upgrade_Result" data-setter="$upgradeChoice to 'controle'">
<div class="creation-opt-title">Premier toucher</div>
<div class="creation-opt-desc">Contrôle sous pression, orientation. Transformer ton Contrôle orienté en Aile de pigeon (F:6 → F:7).</div>
</span>
</div>

<<else>> /* défenseur */
<div class="creation-options">
<span class="creation-opt" data-passage="Acte1_Upgrade_Result" data-setter="$upgradeChoice to 'tacle'">
<div class="creation-opt-title">Tacle parfait</div>
<div class="creation-opt-desc">Timing, engagement, propreté. Transformer ton Tacle glissé en Tacle parfait (F:6 → F:7, risque → Faible).</div>
</span>

<span class="creation-opt" data-passage="Acte1_Upgrade_Result" data-setter="$upgradeChoice to 'pressing'">
<div class="creation-opt-title">Pressing coordonné</div>
<div class="creation-opt-desc">Sortie collective, orientation. Transformer ton Pressing en Pressing coordonné (+phase ATT).</div>
</span>

<span class="creation-opt" data-passage="Acte1_Upgrade_Result" data-setter="$upgradeChoice to 'interception'">
<div class="creation-opt-title">Lecture anticipée</div>
<div class="creation-opt-desc">Lire avant la passe. Transformer ton Interception en Lecture anticipée (F:6 → F:7, +phase ATT).</div>
</span>
</div>
<</if>>


:: Acte1_Match_Amical_Intro {"position":"675,1575","size":"100,100"}
# Match amical — Hojo vs Collège d'Odawara

<<set $matchAdversaire to "Collège d'Odawara">>
<<set $matchScore to [0, 0]>>
<<set $matchMinute to 0>>
<<set $matchMoment to 0>>
<<set $energy to $energyMax>>
<<set $momentum to 0>>
<<set $danger to 0>>
<<set $lectureDefensive to 0>>
<<set $flags["match_amical_joue"] to true>>

/* --- Définition du match : moments scriptés --- */
<<set $matchMaxMoments to 5>>
<<set $matchEndPassage to "Acte1_Match_Fin">>
<<set $matchScripted to [
  {moment: 1, condition: "", passage: "Acte1_Match_Moment1"},
  {moment: 3, condition: "State.variables.danger >= 3 || State.variables.momentum >= 2", passage: "Acte1_Match_Moment2"}
]>>

Samedi, 14h00. Temps couvert. Vent modéré.

Le terrain de l'Académie Hojo est plein — enfin, « plein » pour un match amical de collège à Odawara, ce qui signifie une cinquantaine de personnes dans le petit gradin, quelques parents, et trois scouts d'équipes voisines.

Tu es sur le banc. À côté de toi, Teo regarde le terrain avec une concentration qui ne correspond pas à un simple match amical.

L'équipe entre :

<div class="scoreboard">
<div class="scoreboard-team">HOJO</div>
<div class="scoreboard-score">0 – 0</div>
<div class="scoreboard-team">ODAWARA</div>
</div>
<div class="scoreboard-minute">Coup d'envoi</div>

La première mi-temps est dominée par Hojo. Le collectif est fluide — Thomas récupère, Clément oriente, Nayn apporte de l'intensité. Saera distribue avec une vision parfaite, mais continue d'éviter les situations de finition directe. Audy est économe, précis, invisible jusqu'au moment où il apparaît exactement là où il faut.

À la 35ème, Mizuki déborde sur le flanc gauche, centre en retrait. Nayn reprend — but. 1-0.

<<set $matchScore[0] to 1>>

<div class="scoreboard">
<div class="scoreboard-team">HOJO</div>
<div class="scoreboard-score">1 – 0</div>
<div class="scoreboard-team">ODAWARA</div>
</div>
<div class="scoreboard-minute">35'</div>

Mi-temps. Max parle au groupe, ajuste des placements, puis se tourne vers toi.

<p>— <<if $reputation >= 5>>« Tu entres à la 55ème. Montre-moi que t'as compris ce que tu as vu. »<<else>>« Tu entres à la 60ème. Pas de folie. Intègre-toi au mouvement. »<</if>></p>

<<set $matchMinute to 55>>

[[Tu entres en jeu.|Match_Router]]


:: Acte1_Match_Fin {"position":"50,1825","size":"100,100"}
## Coup de sifflet final

<<set $matchMinute to 90>>

Les dernières minutes s'écoulent sans incident majeur. Hojo contrôle, gère, finit le match sans trembler.

<div class="scoreboard">
<div class="scoreboard-team">HOJO</div>
<div class="scoreboard-score"><<print $matchScore[0]>> – <<print $matchScore[1]>></div>
<div class="scoreboard-team">ODAWARA</div>
</div>
<div class="scoreboard-minute">90' — Fin du match</div>

Victoire. Le groupe est satisfait sans être euphorique — c'est un match amical, après tout. Mais les bases sont posées.

Max rassemble l'équipe au centre du terrain.

<p>— « Correct. Collectif solide. Il y a du travail sur les transitions, mais la base est là. »</p>

Puis il te regarde.

<<if $reputation >= 15>>
<p>— <<if $playerGender is "M">>« Le petit s'est bien débrouillé. Continue comme ça et on en reparle. »<<else>>« La petite s'est bien débrouillée. Continue comme ça et on en reparle. »<</if>></p>

<<set $relations["Max"] += 5>>

<div class="encadre encadre-relation">
<div class="encadre-titre">Reconnaissance</div>
Max t'a remarqué publiquement. L'équipe aussi. Tu n'es plus invisible.
</div>

<<elseif $reputation >= 8>>
<p>— « Du potentiel. Faut confirmer. »</p>

<<set $relations["Max"] += 2>>

<<else>>
Max ne te mentionne pas. Ce n'est pas un reproche — c'est un match amical, et tu es nouveau. Mais le silence a un poids.
<</if>>

<div class="scene-break">· · ·</div>

Le soir, dans le vestiaire, Thomas te tape dans le dos.

<p>— « Premier match. Pas le dernier. Bienvenue chez les Tigres, <<if $playerGender is "M">>gamin<<else>>gamine<</if>>. »</p>

Audy passe à côté de toi. Il ne dit rien. Mais son carnet est ouvert, et tu aperçois ton numéro de maillot griffonné dans la marge.

Il t'a noté.

<div class="scene-break">· · ·</div>

La saison commence. Le Football Frontier approche. Et la question que personne ne pose encore résonne en silence : est-ce que Hojo aura un sponsor pour y participer ?

<div class="encadre">
<div class="encadre-titre">Fin de l'Acte I — Chapitre 1</div>
<strong>Réputation :</strong> $reputation
</div>

<div class="relations-section">
<div class="relations-section-title">Relations clés</div>
<div class="relations-grid">
<<relCard "Audy" $relations["Audy"]>>
<<relCard "Thomas" $relations["Thomas"]>>
<<relCard "Saera" $relations["Saera"]>>
<<relCard "Naela" $relations["Naela"]>>
<<relCard "Mizuki" $relations["Mizuki"]>>
<<relCard "Max" $relations["Max"]>>
</div>
</div>

[[→ Acte I — Chapitre 2 : La question du sponsor|Acte1_Entrainement_Special]]


:: Acte1_Match_M2_Fermer {"position":"1050,1700","size":"100,100"}
<<set $energy -= 1>>
<<set $danger -= 1>>
<<set $reputation += 3>>
<<set $momentum += 1>>

Tu fermes le couloir. L'attaquant est forcé d'aller sur l'extérieur — le tir part en angle fermé. Teo capte sans problème.

<div class="encadre encadre-info">
<div class="encadre-titre">Résultat : Succès</div>
Défense intelligente. Le danger est écarté sans prendre de risque.
</div>

[[Moment suivant.|Match_Router]]


:: Acte1_Match_M2_Lateral {"position":"925,1700","size":"100,100"}
<<set $energy -= 1>>
<<set $danger += 1>>

Tu te replaces. Saera te trouve — passe latérale, propre. Tu remets en une touche vers Clément qui oriente vers Mizuki. Le jeu se construit.

<<set $reputation += 3>>
<<set $relations["Clément"] += 3>>
<<set $momentum += 1>>

<div class="encadre encadre-info">
<div class="encadre-titre">Résultat : Succès</div>
Jeu collectif. Exactement ce que Max a demandé. La séquence continue — Mizuki centre, Naela reprend de la tête. Repoussé, mais la dynamique est là.
</div>

[[Moment suivant.|Match_Router]]


:: Acte1_Match_M2_Profondeur {"position":"800,1700","size":"100,100"}
<<set $energy -= 2>>

Tu appelles. Saera hésite — une fraction de seconde. Puis elle joue. La passe est parfaite, comme toujours. Le problème n'est jamais la passe avec Saera.

Tu reçois en pleine course. Le défenseur est sur tes talons.

<<set _roll to random(1, 20)>>
<<set _score to 6 + Math.floor(($physique * 2 + $vision) / 30) + $momentum>>
<<set _total to _score + _roll>>

<<if _total >= 15>>
Tu le prends de vitesse. Face au gardien — tu ne réfléchis pas. Tu frappes.

<<set _roll2 to random(1, 20)>>
<<set _score2 to 6 + Math.floor(($technique * 2 + $vision) / 30) + 2>>
<<set _total2 to _score2 + _roll2>>

<<if _total2 >= 14>>
But. Le filet tremble. Ton <<if $matchScore[0] is 1>>deuxième<<else>>premier<</if>> but sous le maillot d'Hojo.

<<set $matchScore[0] += 1>>
<<set $momentum to 3>>
<<set $danger to 0>>
<<set $reputation += 8>>
<<set $relations["Saera"] += 5>>

<div class="scoreboard">
<div class="scoreboard-team">HOJO</div>
<div class="scoreboard-score"><<print $matchScore[0]>> – <<print $matchScore[1]>></div>
<div class="scoreboard-team">ODAWARA</div>
</div>

<div class="encadre encadre-relation">
<div class="encadre-titre">BUT !</div>
La connexion avec Saera fonctionne. Ce n'est qu'un match amical — mais ces choses-là se retiennent.
</div>

<<else>>
Le gardien arrête. Bon arrêt. Mais l'occasion était nette — et c'est toi qui l'as créée.

<<set $danger += 2>>
<<set $reputation += 4>>
<<set $relations["Saera"] += 3>>

<div class="encadre encadre-info">
<div class="encadre-titre">Résultat : Mitigé</div>
L'occasion est là. La finition manque. Mais la connexion avec Saera est prometteuse.
</div>
<</if>>

<<else>>
Le défenseur te rattrape. Le ballon est perdu.

<<set $momentum -= 1>>
<<set $reputation += 1>>

<div class="encadre encadre-danger">
<div class="encadre-titre">Résultat : Échec</div>
Trop lent. Le défenseur a lu ta course.
</div>
<</if>>

[[Moment suivant.|Match_Router]]


:: Acte1_Match_M2_Sortir {"position":"1175,1700","size":"100,100"}
<<set $energy -= 2>>

<<set _roll to random(1, 20)>>
<<set _score to 5 + Math.floor(($physique * 2 + $vision) / 30) + $momentum>>
<<set _total to _score + _roll>>

<<if _total >= 14>>
Tu sors au pressing. L'attaquant panique — mauvaise passe, Lucie intercepte. Transition Hojo.

<<set $momentum += 1>>
<<set $reputation += 5>>
<<set $relations["Lucie"] += 3>>

<div class="encadre encadre-info">
<div class="encadre-titre">Résultat : Succès</div>
Pressing gagnant ! Tu forces l'erreur et Lucie capitalise.
</div>

<<else>>
Tu sors trop tôt. L'attaquant te passe — mais Sandro est là en dernier rempart. Corner Odawara.

<<set $reputation += 1>>

<div class="encadre encadre-danger">
<div class="encadre-titre">Résultat : Échec</div>
Pressing raté. Heureusement, la couverture tient.
</div>
<</if>>

[[Moment suivant.|Match_Router]]


:: Acte1_Match_Moment1 {"position":"800,1575","size":"100,100"}
/* Moment scripté 1 — Première touche de balle */

<div class="hud"><div class="hud-inner">
<div class="hud-item"><span class="hud-label">Score</span> <span class="hud-value">1–0</span></div>
<div class="hud-item"><span class="hud-label">Min</span> <span class="hud-value">$matchMinute'</span></div>
<div class="hud-item"><span class="hud-label">Énergie</span> <span class="hud-value hud-energy"><<energyGauge>></span></div>
<div class="hud-item"><span class="hud-label">Momentum</span> <span class="hud-value"><<momentumDisplay>></span></div>
</div></div>

<div class="encadre encadre-info">
<div class="encadre-titre">Moment 1 — Première touche de balle</div>
<strong>Cadre :</strong> Pelouse correcte · Vent modéré<br>
<strong>Tactique :</strong> Circulation rapide — Hojo domine<br>
<strong>Fait de jeu :</strong> Transition après récupération<br>
<strong>État :</strong> Concentration (premier ballon en match)
</div>

Tu es sur le terrain. Le bruit du gradin — modeste, mais présent — résonne différemment quand tu joues. Thomas te cherche du regard. Le ballon circule.

Et il arrive.

<<if $playerPoste is "attaquant">>
<<set $matchPhase to "ATT">>
<<set $enemyAction to "couvre">>
Thomas lance une passe dans le couloir droit. Tu es face à un défenseur qui recule, ferme l'espace. Première touche de balle officielle en tant que Tigre d'Hojo.

<div class="encadre encadre-info">
<div class="encadre-titre">Phase : ATTAQUE</div>
<strong>Action adverse :</strong> <span class="enemy-action"><<print window.enemyActionLabel($enemyAction)>></span><br>
Le défenseur recule et couvre. Il faut trouver la faille.
</div>

<div class="card-hand">
<div class="card card-risk-low" data-passage="Match1_Controle" data-setter="$lastFamily to 'Conservation', $lastCardId to 'controle'">
<div class="card-name">Contrôle orienté</div>
<div class="card-stats"><span class="card-stat">F:6<<if $nativeFamilies.indexOf('Conservation') !== -1>> <span class="card-native-bonus">+1</span><</if>></span><span class="card-stat">TEC·PHY</span><span class="card-stat">É:1</span></div>
<div class="card-desc">Sécurise le ballon. Prolonge l'action.</div>
<div class="card-matchup"><<print window.matchupLabel('controle')>></div>
</div>

<div class="card card-risk-mid" data-passage="Match1_Dribble" data-setter="$lastFamily to 'Dribble', $lastCardId to 'dribble'">
<div class="card-name">Dribble</div>
<div class="card-stats"><span class="card-stat">F:5<<if $nativeFamilies.indexOf('Dribble') !== -1>> <span class="card-native-bonus">+1</span><</if>></span><span class="card-stat">TEC·PHY</span><span class="card-stat">É:2</span></div>
<div class="card-desc">Élimine le défenseur. +3 si 1v1.</div>
<div class="card-matchup"><<print window.matchupLabel('dribble')>></div>
</div>

<div class="card card-risk-low" data-passage="Match1_Passe" data-setter="$lastFamily to 'Passe', $lastCardId to 'passe_courte'">
<div class="card-name">Passe courte</div>
<div class="card-stats"><span class="card-stat">F:7<<if $nativeFamilies.indexOf('Passe') !== -1>> <span class="card-native-bonus">+1</span><</if>></span><span class="card-stat">TEC·VIS</span><span class="card-stat">É:0</span></div>
<div class="card-desc">Remet vers un coéquipier. Sûr, efficace.</div>
<div class="card-matchup"><<print window.matchupLabel('passe_courte')>></div>
</div>

<div class="card card-risk-high" data-passage="Match1_Tir" data-setter="$lastFamily to 'Tir', $lastCardId to 'frappe_loin'">
<div class="card-name">Frappe de loin</div>
<div class="card-stats"><span class="card-stat">F:4<<if $nativeFamilies.indexOf('Tir') !== -1>> <span class="card-native-bonus">+1</span><</if>></span><span class="card-stat">PHY·TEC</span><span class="card-stat">É:2</span></div>
<div class="card-desc">Tente sa chance de loin. Risque élevé.</div>
<div class="card-matchup"><<print window.matchupLabel('frappe_loin')>></div>
</div>
</div>

<<elseif $playerPoste is "milieu">>
<<set $matchPhase to "ATT">>
<<set $enemyAction to "presse">>
Le ballon arrive dans tes pieds. Deux adversaires ferment l'espace — ils montent sur toi, te pressent. Clément est libre à gauche, Audy appelle devant.

<div class="encadre encadre-info">
<div class="encadre-titre">Phase : ATTAQUE</div>
<strong>Action adverse :</strong> <span class="enemy-action"><<print window.enemyActionLabel($enemyAction)>></span><br>
Deux joueurs te pressent. Joue vite ou perds le ballon.
</div>

<div class="card-hand">
<div class="card card-risk-low" data-passage="Match1_Controle" data-setter="$lastFamily to 'Conservation', $lastCardId to 'controle'">
<div class="card-name">Contrôle orienté</div>
<div class="card-stats"><span class="card-stat">F:6<<if $nativeFamilies.indexOf('Conservation') !== -1>> <span class="card-native-bonus">+1</span><</if>></span><span class="card-stat">TEC·PHY</span><span class="card-stat">É:1</span></div>
<div class="card-desc">Temporise, garde le ballon.</div>
<div class="card-matchup"><<print window.matchupLabel('controle')>></div>
</div>

<div class="card card-risk-mid" data-passage="Match1_Profondeur" data-setter="$lastFamily to 'Passe', $lastCardId to 'passe_profonde'">
<div class="card-name">Passe en profondeur</div>
<div class="card-stats"><span class="card-stat">F:5<<if $nativeFamilies.indexOf('Passe') !== -1>> <span class="card-native-bonus">+1</span><</if>></span><span class="card-stat">VIS·TEC</span><span class="card-stat">É:1</span></div>
<div class="card-desc">Perce la défense vers Audy. +2 en transition.</div>
<div class="card-matchup"><<print window.matchupLabel('passe_profonde')>></div>
</div>

<div class="card card-risk-low" data-passage="Match1_Passe" data-setter="$lastFamily to 'Passe', $lastCardId to 'passe_courte'">
<div class="card-name">Passe courte</div>
<div class="card-stats"><span class="card-stat">F:7<<if $nativeFamilies.indexOf('Passe') !== -1>> <span class="card-native-bonus">+1</span><</if>></span><span class="card-stat">TEC·VIS</span><span class="card-stat">É:0</span></div>
<div class="card-desc">Sécurise vers Clément. Efficace.</div>
<div class="card-matchup"><<print window.matchupLabel('passe_courte')>></div>
</div>

<div class="card card-risk-mid" data-passage="Match1_Dribble" data-setter="$lastFamily to 'Dribble', $lastCardId to 'dribble'">
<div class="card-name">Dribble</div>
<div class="card-stats"><span class="card-stat">F:5<<if $nativeFamilies.indexOf('Dribble') !== -1>> <span class="card-native-bonus">+1</span><</if>></span><span class="card-stat">TEC·PHY</span><span class="card-stat">É:2</span></div>
<div class="card-desc">Élimine un adversaire. Ouvre le jeu.</div>
<div class="card-matchup"><<print window.matchupLabel('dribble')>></div>
</div>
</div>

<<elseif $playerPoste is "défenseur">>
<<set $matchPhase to "DEF">>
<<set $enemyAction to "dribble">>
Odawara tente une relance rapide. Leur attaquant est lancé sur ton côté, balle au pied — il fonce. Tu es le dernier rideau avant Teo.

<div class="encadre encadre-info">
<div class="encadre-titre">Phase : DÉFENSE</div>
<strong>Action adverse :</strong> <span class="enemy-action"><<print window.enemyActionLabel($enemyAction)>></span><br>
L'attaquant dribble vers toi. Il faut le stopper.
</div>

<div class="card-hand">
<div class="card card-risk-low" data-passage="Match1_Couverture" data-setter="$lastFamily to 'Positionnement', $lastCardId to 'couverture'">
<div class="card-name">Couverture</div>
<div class="card-stats"><span class="card-stat">F:7<<if $nativeFamilies.indexOf('Positionnement') !== -1>> <span class="card-native-bonus">+1</span><</if>></span><span class="card-stat">VIS·PHY</span><span class="card-stat">É:1</span></div>
<div class="card-desc">Ferme l'espace. Réduit le danger. Sûr.</div>
<div class="card-matchup"><<print window.matchupLabel('couverture')>></div>
</div>

<div class="card card-risk-mid" data-passage="Match1_Tacle" data-setter="$lastFamily to 'Duel', $lastCardId to 'tacle'">
<div class="card-name">Tacle glissé</div>
<div class="card-stats"><span class="card-stat">F:6<<if $nativeFamilies.indexOf('Duel') !== -1>> <span class="card-native-bonus">+1</span><</if>></span><span class="card-stat">PHY·VIS</span><span class="card-stat">É:2</span></div>
<div class="card-desc">Récupération nette. Risque de faute.</div>
<div class="card-matchup"><<print window.matchupLabel('tacle')>></div>
</div>

<div class="card card-risk-low" data-passage="Match1_Controle" data-setter="$lastFamily to 'Récupération', $lastCardId to 'interception'">
<div class="card-name">Interception</div>
<div class="card-stats"><span class="card-stat">F:6<<if $nativeFamilies.indexOf('Récupération') !== -1>> <span class="card-native-bonus">+1</span><</if>></span><span class="card-stat">VIS·TEC</span><span class="card-stat">É:1</span></div>
<div class="card-desc">Lecture de la passe adverse. Propre.</div>
<div class="card-matchup"><<print window.matchupLabel('interception')>></div>
</div>

<div class="card card-risk-mid" data-passage="Match1_Pressing" data-setter="$lastFamily to 'Récupération', $lastCardId to 'pressing'">
<div class="card-name">Pressing</div>
<div class="card-stats"><span class="card-stat">F:5<<if $nativeFamilies.indexOf('Récupération') !== -1>> <span class="card-native-bonus">+1</span><</if>></span><span class="card-stat">PHY·VIS</span><span class="card-stat">É:2</span></div>
<div class="card-desc">Force l'erreur. Momentum +1 si réussi.</div>
<div class="card-matchup"><<print window.matchupLabel('pressing')>></div>
</div>
</div>
<</if>>


:: Acte1_Match_Moment2 {"position":"675,1700","size":"100,100"}
/* Moment scripté — Moment décisif 67ème */
<<set $matchMinute to 67>>

<div class="hud"><div class="hud-inner">
<div class="hud-item"><span class="hud-label">Score</span> <span class="hud-value"><<print $matchScore[0]>>–<<print $matchScore[1]>></span></div>
<div class="hud-item"><span class="hud-label">Min</span> <span class="hud-value">67'</span></div>
<div class="hud-item"><span class="hud-label">Énergie</span> <span class="hud-value hud-energy"><<energyGauge>></span></div>
<div class="hud-item"><span class="hud-label">Momentum</span> <span class="hud-value"><<momentumDisplay>></span></div>
</div></div>

Le match avance. Odawara commence à pousser — ils n'ont rien à perdre. Les espaces s'ouvrent dans les deux sens.

<<if $momentum >= 1>>
Hojo garde le contrôle. Le jeu est fluide. Tu sens que l'équipe commence à t'inclure dans ses circuits — les passes arrivent plus naturellement, les appels te cherchent.
<<else>>
Le match est tendu. Odawara a retrouvé de l'énergie et Hojo peine à sortir proprement. Max crie des consignes depuis le banc.
<</if>>

À la 67ème, un moment décisif se présente.

<<if $playerPoste is "attaquant" or $playerPoste is "milieu">>
Saera récupère un ballon au milieu de terrain. Elle lève la tête — et te voit. Tu es démarqué. Le couloir est ouvert.

Mais entre toi et le but, il y a deux défenseurs et une décision à prendre.

[[Appeler le ballon et foncer — profondeur.|Acte1_Match_M2_Profondeur]]
[[Se replacer — offrir une option de passe latérale.|Acte1_Match_M2_Lateral]]

<<else>> /* défenseur */
Odawara lance une contre-attaque rapide. Deux contre deux. Tu es face à l'action.

[[Fermer le couloir central — forcer le tir de loin.|Acte1_Match_M2_Fermer]]
[[Sortir au pressing — forcer l'erreur avant la passe.|Acte1_Match_M2_Sortir]]
<</if>>


:: Acte1_Saera_Respect {"position":"425,1575","size":"100,100"}
Saera te regarde. Puis elle sourit — le premier vrai sourire, celui qui n'est pas poli.

<p>— « D'accord. Mets-toi là. Tu dégages mes tirs et on continue jusqu'à ce que Max vienne nous virer. »</p>

Vous tirez pendant vingt minutes. Elle ne reparle pas de l'hésitation. Mais à un moment, sur une frappe en pivot — situation de match simulée —, elle marque. Net. Sans hésiter.

Elle ne commente pas. Mais ses épaules se relâchent d'un cran.

<<set $relations["Saera"] += 8>>

<div class="encadre encadre-relation">
<div class="encadre-titre">Complicité naissante</div>
Tu n'as pas forcé la confidence. Tu as joué. Parfois, c'est le meilleur langage.
</div>

[[Retourner au dortoir. Le match est demain.|Acte1_Match_Amical_Intro]]


:: Acte1_Saera_Verite {"position":"300,1575","size":"100,100"}
Un silence. Saera ne te regarde pas. Elle ramasse un ballon, le fait tourner entre ses mains.

<p>— « ... Tu es <<if $playerGender is "M">>direct, le nouveau<<else>>directe, la nouvelle<</if>>. »</p>

Elle pose le ballon.

<p>— « C'est depuis le tacle. L'an passé. Mon corps est revenu. Ma tête... pas complètement. Quand je suis seule face au but et que j'entends quelqu'un arriver derrière moi, je... je diffère. Je passe. Je cherche quelqu'un d'autre. Et je déteste ça. »</p>

<<set $relations["Saera"] += 10>>

C'est la première fois qu'elle le dit à voix haute à quelqu'un qui n'est pas Audy ou Thomas.

<div class="encadre encadre-secret">
<div class="encadre-titre">Lien forgé</div>
Saera t'a confié sa fragilité. Ce moment comptera plus tard — quand il sera question de confiance, de sponsor, et de choix qui ne t'appartiennent pas.
</div>

[[Retourner te préparer. Tu as entendu quelque chose d'important.|Acte1_Match_Amical_Intro]]


:: Acte1_Soiree_Audy {"position":"300,1450","size":"100,100"}
Le terrain est éclairé par les lampadaires de la cour. Audy est seul, un ballon aux pieds, et enchaîne des gestes d'une simplicité trompeuse — contrôle, passe dans le mur, réception, repositionnement. Chaque mouvement est identique au précédent, au centimètre près.

Tu t'assieds dans le gradin sans dire un mot. Il t'a vu. Il ne s'arrête pas.

Cinq minutes passent. Dix. Le rythme ne change pas. Puis, sans lever les yeux :

<p>— « Tu joues $playerPoste. Max me l'a dit. »</p>

Silence. Le ballon frappe le mur. Revient.

<p>— « Le match amical est après-demain. Si tu veux jouer, montre quelque chose. Pas à moi. À l'équipe. »</p>

C'est tout. Il ne te regarde pas. Mais il t'a parlé. Thomas te dira plus tard que c'est déjà beaucoup.

<<set $relations["Audy"] += 5>>
<<set $flags["acte1_voie_performance"] to true>>

[[Retourner dans ta chambre. Le message est reçu.|Acte1_Entrainement_J1]]


:: Acte1_Soiree_Orphelinat {"position":"425,1450","size":"100,100"}
L'orphelinat Hatakeyama est à cinq minutes de l'académie, au bout d'un chemin bordé de cerisiers. Le bâtiment est petit, chaleureux — lumières allumées, odeur de soupe.

Naela et Mizuki marchent devant toi. Mizuki ne s'est pas retournée quand tu les as suivies. Naela, si.

<p>— « Tu viens voir où on habite ? C'est pas l'Hilton, mais Élise fait les meilleurs onigiri de la préfecture. »</p>

Élise Nakamura t'accueille à la porte — jeune femme brune, traits doux, sourire fatigué. La directrice de l'orphelinat. Elle te serre la main.

<p>— « Max m'a parlé de toi. Bienvenue. Tu restes manger ? »</p>

Le dîner est simple, bruyant — des enfants plus jeunes courent entre les tables, Naela les calme avec une autorité douce, Mizuki mange en silence avec un regard qui décourage les conversations. Mais à un moment, entre deux bouchées, Mizuki te fixe.

<p>— « T'es <<if $playerPoste is "attaquant">>attaquant<<elseif $playerPoste is "milieu">>milieu<<else>>défenseur<</if>>, c'est ça ? »</p>

<<if $playerPoste is "attaquant">>
<p>— « Un de plus devant. Comme si on manquait pas de défenseurs. »</p>
<<else>>
<p>— « On verra si t'es utile. »</p>
<</if>>

Naela lui donne un coup de coude. Mizuki hausse les épaules. Pas hostile — directe. Tu notes aussi quelque chose : à un moment, Naela porte la main à son épaule gauche, grimace furtivement, et Mizuki lui lance un regard précis. Un geste d'habitude. Un langage que tu ne comprends pas encore.

<<set $relations["Naela"] += 10>>
<<set $relations["Mizuki"] += 5>>
<<set $flags["acte1_voie_relations"] to true>>

[[Retourner à l'académie. Tu as beaucoup à digérer.|Acte1_Entrainement_J1]]


:: Acte1_Soiree_Thomas {"position":"175,1450","size":"100,100"}
Tu trouves Thomas dans la salle commune, un manga ouvert sur les genoux qu'il ne lit manifestement pas. Il lève la tête.

<p>— « Ah, <<if $playerGender is "M">>le nouveau<<else>>la nouvelle<</if>>. Assieds-toi. Tu veux que je te fasse le topo sur tout le monde ? »</p>

Il ne te laisse pas répondre. En vingt minutes, Thomas te dresse un portrait de chaque membre de l'équipe — avec une précision et une bienveillance qui tranchent sur sa décontraction de surface. Tu apprends que Nayn, Sheun et Sandro formaient le « Trio Infernal » l'an passé — des francs-tireurs que Max a ramenés dans le rang. Que Clément est le joueur le plus sous-estimé de l'effectif. Que Lucie est une bombe à énergie pure qu'il faut canaliser. Que Teo, le frère de Saera, est arrivé cette année comme gardien après avoir quitté l'athlétisme.

<p>— « Et Audy... Audy, c'est compliqué. C'est mon meilleur ami. Mais il faut du temps. Il observe, il note tout dans ses carnets. Si tu veux sa confiance, faudra la mériter. Et pas en parlant. En jouant. »</p>

<<set $relations["Thomas"] += 10>>

Un silence. Puis Thomas ajoute, plus bas :

<p>— « Max a l'air solide, mais ces dernières semaines... Je sais pas. Il décroche parfois. Des appels qu'il prend loin du terrain. C'est peut-être rien. »</p>

Il hausse les épaules. Mais tu sens qu'il n'a pas dit ça par hasard.

<<set $flags["thomas_confiance"] to true>>

[[Retourner dans ta chambre. Demain, premier entraînement.|Acte1_Entrainement_J1]]


:: Acte1_Upgrade_Result {"position":"300,1825","size":"100,100"}
<<run window.upgradeCard($upgradeChoice)>>

<<set _upg to $upgrades[$upgradeChoice]>>

La séance dure deux heures. Max ne parle presque pas — il corrige d'un geste, d'un regard. Quand tu réussis, il hoche la tête. Quand tu rates, il replace le cône et te fait recommencer.

À la fin, tu es trempé. Mais quelque chose a changé. Le geste est plus sûr, plus fluide. Inscrit dans le corps.

<div class="encadre encadre-info">
<div class="encadre-titre">★ Carte améliorée</div>
<strong><<print _upg.name>></strong> — Force <<print _upg.force>> · <<print _upg.stat.substring(0,3).toUpperCase()>>·<<print _upg.stat2.substring(0,3).toUpperCase()>> · Phases : <<print _upg.phases.join("·")>><br>
<<print _upg.desc>>
</div>

Max range les cônes.

<p>— « C'est mieux. Maintenant, fais-le quand ça compte. »</p>

[[→ Acte I — Chapitre 2 : La question du sponsor|Acte1_Ch2_Sponsor]]
[[→ Consulter ton profil et ton deck|Profil_Joueur]]


:: Acte1_Veille_Audy {"position":"550,1575","size":"100,100"}
Tu trouves Audy dans la salle vidéo — un projecteur allumé, des images de l'équipe adverse de demain qui défilent. Il ne lève pas la tête quand tu entres.

<p>— « Leur latéral droit monte trop haut. Ça laisse un couloir si on contre vite. »</p>

Tu ne sais pas s'il te parle ou s'il pense à voix haute. Tu t'assieds.

Cinq minutes de silence. Puis :

<p>— <<if $playerPoste is "attaquant">>« Si tu entres demain, cherche la profondeur côté droit. Nayn peut te trouver. »<<elseif $playerPoste is "milieu">>« Si tu entres, distribue vite. Pas plus de deux touches. On joue en circulation. »<<elseif $playerPoste is "défenseur">>« Si tu entres, couvre Sandro. Il prend trop de risques sur les sorties de balle. »<<else>>« Teo sera titulaire demain. Mais regarde bien leur buteur. C'est lui que tu affronteras si tu joues après. »<</if>></p>

Un conseil. Précis. Gratuit. C'est sa façon de dire qu'il te voit.

<<set $relations["Audy"] += 8>>
<<set $reputation += 2>>

[[Retourner au dortoir. Le message est clair.|Acte1_Match_Amical_Intro]]


:: Acte1_Veille_Match {"position":"925,1450","size":"100,100"}
## Veille de match

Le soir, le groupe est réuni dans la salle commune. Max fait le point sur le match amical de demain — un collège local, pas un adversaire majeur. Mais Max le prend au sérieux.

<p>— « Je veux voir du collectif. Pas de la performance individuelle. Pas de héros. Du mouvement, de la circulation, de l'intensité. C'est le premier match de la saison. C'est là qu'on installe les repères. »</p>

Il regarde dans ta direction.

<p>— <<if $reputation >= 5>>« Tu es sur le banc. Je te ferai entrer en deuxième mi-temps. Montre-moi ce que t'as. »<<else>>« Tu es sur le banc. Observe. On verra pour la deuxième mi-temps. »<</if>></p>

La soirée continue. Tu as un moment libre.

<<if $flags["thomas_confiance"]>>
[[Retrouver Thomas — il avait l'air de vouloir te dire quelque chose de plus.|Acte1_Veille_Thomas]]
<</if>>
[[Aller voir Saera s'entraîner seule aux tirs — elle est encore sur le terrain.|Acte1_Veille_Saera]]
[[Demander conseil à Audy sur le match de demain.|Acte1_Veille_Audy]]
[[Aller te coucher tôt. Demain, ça compte.|Acte1_Match_Amical_Intro]]


:: Acte1_Veille_Saera {"position":"175,1575","size":"100,100"}
Le terrain est dans la semi-obscurité. Saera est devant le but vide, un sac de ballons à ses pieds. Elle tire. Place. Le ballon file dans le coin. Parfait.

Elle en prend un autre. Même geste. Même résultat. Techniquement, c'est impeccable.

Puis elle recule de cinq mètres. Se met en situation — contrôle, pivot, frappe. Le ballon part... à côté. Elle ne frappe pas mal. Elle frappe en retard. Un quart de seconde d'hésitation. Le corps sait. La tête freine.

Elle te voit. Un instant de gêne — tu es témoin de quelque chose qu'elle ne montre à personne.

<p>— « C'est pas ce que tu crois. Je travaille juste les angles. »</p>

Vous savez tous les deux que ce n'est pas ça.

[[Dire la vérité : « C'est l'hésitation. Je l'ai vue aussi à l'entraînement. »|Acte1_Saera_Verite]]
[[Respecter le mensonge : « C'est un bon exercice. Tu veux que je te fasse le mur ? »|Acte1_Saera_Respect]]


:: Acte1_Veille_Thomas {"position":"50,1575","size":"100,100"}
Thomas est sur les marches du dortoir, téléphone éteint, regard dans le vide. Il te voit et sourit — mais le sourire est un peu forcé.

<p>— « Tu te souviens de ce que j'ai dit hier ? Sur Max ? Les appels, la tension... Je sais que c'est pas mes affaires. Mais c'est notre coach. Et si quelque chose le bouffe, ça va finir par toucher l'équipe. »</p>

Il se tait un moment.

<p>— « J'ai rien de concret. Juste une intuition. Mais si jamais tu vois quelque chose de ton côté... dis-le moi, d'accord ? »</p>

<<set $relations["Thomas"] += 5>>

Tu hoches la tête. Un pacte silencieux.

[[Retourner te préparer. Le match est demain.|Acte1_Match_Amical_Intro]]


:: Acte2_Intro_FF {"position":"425,2075","size":"100,100"}
# Acte II — Entrée dans le Football Frontier

<<set $acte to 2>>
<<set $semaine += 2>>

Deux semaines passent. L'entraînement s'intensifie. Max affine ses schémas, ajuste les automatismes, pousse le groupe. La cohésion progresse — et toi avec.

L'inscription au Football Frontier est confirmée. Sponsor officiel : Léa Voss, à titre personnel. Max n'a rien dit de plus. Thomas te lance un regard quand l'annonce est faite. Tu sais tous les deux que ce financement a une date d'expiration.

Le tirage au sort tombe.

<div class="encadre encadre-info">
<div class="encadre-titre">Football Frontier — Phase de groupes</div>
<strong>Groupe A :</strong> Inakuni Raimon · Royal Academy · Zeus · Kirkwood · Cloître Sacré<br>
<strong>Groupe B :</strong> <em>Hojo</em> · Shuriken · Terria · Sunshine Academy · Collège Alpin
</div>

Max analyse le groupe sans émotion visible.

<p>— « Shuriken est notre premier vrai test. Formation dirigée par un certain Arno Schwartz — je n'ai pas beaucoup d'infos. Terria et Sunshine sont solides. Le Collège Alpin est une inconnue. »</p>

<p>— « La Royal Academy est dans l'autre groupe. »</p>

Un silence. Tout le monde a compris ce que ça signifie : si Hojo veut sa revanche, il faudra passer les poules, puis les quarts, puis les demi-finales. Un long chemin.

Saera regarde le tableau. Son visage ne trahit rien — mais sa main serre le pendentif à son cou.

<div class="scene-break">· · ·</div>

<div class="encadre">
<div class="encadre-titre">À suivre...</div>
L'Acte II développera les matchs de poule du Football Frontier, l'approfondissement des relations, et la montée progressive de la tension autour du subplot sponsor.<br><br>
<em>Merci d'avoir joué la démo de l'Acte I. Le Tome 1 complet couvrira les 5 actes du scénario — des poules à la demi-finale contre la Royal Academy.</em>
</div>

[[← Retour au profil|Profil_Joueur]]
[[← Recommencer l'histoire|Ecran_Titre]]


:: Changelog {"position":"900,25","size":"100,100"}
<div class="preface">

## Changelog

<div class="encadre">
<div class="encadre-titre">v1.6 — 17 février 2026</div>
Paramètres dans le menu : taille de police (3 niveaux), police (serif/sans/mono), thème (Cahier/Nuit/Parchemin/Terrain). Persistance via localStorage. 4 thèmes complets avec override des CSS variables.
</div>

<div class="encadre">
<div class="encadre-titre">v1.5 — 17 février 2026</div>
Moteur de match semi-aléatoire. Routeur scripté/généré. Phase pondérée par poste et contexte. Main avec 1 favorable + 1 défavorable garanties. Résolution universelle. Banques de textes (30+ variantes contexte, 20+ résolution). Moments scriptés conditionnels.
</div>

<div class="encadre">
<div class="encadre-titre">v1.4 — 16 février 2026</div>
Système de matchup tactique. Tables DEF/ATT/FINITION : l'action adverse est annoncée, le joueur choisit sa réponse. Favorable (+2), neutre (0), défavorable (-2). Indicateurs visibles sur les cartes avant le choix.
</div>

<div class="encadre">
<div class="encadre-titre">v1.3 — 16 février 2026</div>
Système de maîtrise : compteur 0-3 par carte, +1 Force permanent à 3 utilisations réussies. Upgrades de cartes via entraînement (8 variantes). Passage séance individuelle avec Max.
</div>

<div class="encadre">
<div class="encadre-titre">v1.2 — 16 février 2026</div>
Pool universel de 26 cartes remplaçant les decks verrouillés par poste. Familles natives par position (+1 Force). Phases de jeu (DEF/TRANS/ATT/FINITION) filtrant les cartes disponibles. 2 signatures exclusives par poste.
</div>

<div class="encadre">
<div class="encadre-titre">v1.1 — 16 février 2026</div>
Passage de 4 à 3 statistiques (Technique, Physique, Vision). Système dual-stat : chaque carte utilise une stat principale (×2) et une secondaire. Rebalancement complet des formules de résolution.
</div>

<div class="encadre">
<div class="encadre-titre">v1.0 — 16 février 2026</div>
Création initiale. Système de résolution, ressources (Stamina, Momentum, Danger), statistiques, cartes par poste, progression, relations, match amical scripté, prologue et Acte I complet.
</div>

</div>

[[← Retour à l'écran titre|Ecran_Titre]]


:: Chapitre 1.1 {"position":"1550,800","size":"100,100"}



:: Creation_Deck {"position":"150,500","size":"100,100"}
/* --- Stats, familles natives et signatures selon le poste --- */

<<if $playerPoste is "défenseur">>
  <<set $physique += 15>>
  <<set $vision += 5>>
  <<set $nativeFamilies to ["Duel", "Positionnement", "Urgence", "Organisation"]>>
  <<set $signatures to [
    {id: "mur_acier", name: "Mur d'acier", force: 9, stat: "physique", stat2: "vision", cost: 3, risk: "Faible", family: "Signature", phases: ["DEF"], desc: "Défense totale. Rien ne passe. Une fois par mi-temps."},
    {id: "relance_decisive", name: "Relance décisive", force: 7, stat: "technique", stat2: "vision", cost: 2, risk: "Moyen", family: "Signature", phases: ["TRANS"], desc: "Longue passe chirurgicale vers l'attaque. Danger +2."}
  ]>>

<<elseif $playerPoste is "milieu">>
  <<set $technique += 10>>
  <<set $vision += 10>>
  <<set $nativeFamilies to ["Passe", "Conservation", "Récupération"]>>
  <<set $signatures to [
    {id: "metronome", name: "Métronome", force: 8, stat: "vision", stat2: "physique", cost: 2, risk: "Faible", family: "Signature", phases: ["TRANS","ATT"], desc: "Dicte le tempo du match. Momentum +2, Lecture défensive -1."},
    {id: "passe_decisive", name: "Passe décisive", force: 7, stat: "vision", stat2: "technique", cost: 2, risk: "Moyen", family: "Signature", phases: ["ATT"], desc: "Passe de génie. Crée une occasion nette directe."}
  ]>>

<<else>> /* attaquant */
  <<set $technique += 15>>
  <<set $physique += 5>>
  <<set $nativeFamilies to ["Tir", "Dribble", "Course"]>>
  <<set $signatures to [
    {id: "instinct", name: "Instinct de buteur", force: 9, stat: "technique", stat2: "physique", cost: 3, risk: "Moyen", family: "Signature", phases: ["FINITION"], desc: "Le geste que personne n'attend. Une fois par mi-temps."},
    {id: "fantome", name: "Appel fantôme", force: 8, stat: "vision", stat2: "physique", cost: 2, risk: "Faible", family: "Signature", phases: ["ATT"], desc: "Disparaît du marquage. Crée une occasion nette."}
  ]>>
<</if>>

## Récapitulatif

<div class="encadre encadre-info">
<div class="encadre-titre">Fiche Joueur</div>
<<if $playerGender is "M">>Joueur<<else>>Joueuse<</if>> · <<print $playerPoste.toUpperCase()>>
</div>

<div class="profil-grid">
<div class="profil-stat"><div class="profil-stat-label">Technique</div><div class="profil-stat-value">$technique</div></div>
<div class="profil-stat"><div class="profil-stat-label">Physique</div><div class="profil-stat-value">$physique</div></div>
<div class="profil-stat"><div class="profil-stat-label">Vision</div><div class="profil-stat-value">$vision</div></div>
</div>

<div class="encadre encadre-info">
<div class="encadre-titre">Familles natives (+1 Force)</div>
<<for _i to 0; _i < $nativeFamilies.length; _i++>>
<span class="deck-card-badge deck-card-badge-native"><<print window.familyIcon($nativeFamilies[_i])>> <<print $nativeFamilies[_i]>></span>
<</for>>
</div>

<div class="deck-section">
<div class="deck-section-title">Signatures <span class="deck-count">(<<print $signatures.length>>)</span></div>
<div class="deck-grid">
<<for _i to 0; _i < $signatures.length; _i++>>
<div class="deck-card-signature">
<div class="deck-card-head">
<div class="deck-card-family"><<print $signatures[_i].family>></div>
<div class="deck-card-force"><<print $signatures[_i].force>></div>
</div>
<div class="deck-card-body">
<div class="deck-card-watermark"><<print window.familyIcon($signatures[_i].family)>></div>
<div class="deck-card-name"><<print $signatures[_i].name>></div>
<div class="deck-card-stats">
<span class="deck-card-badge deck-card-badge-stat"><<print $signatures[_i].stat.substring(0,3).toUpperCase()>></span>
<span class="deck-card-badge deck-card-badge-stat2"><<print $signatures[_i].stat2.substring(0,3).toUpperCase()>></span>
<span class="deck-card-badge deck-card-badge-cost">É:<<print $signatures[_i].cost>></span>
<span class="deck-card-badge deck-card-badge-phase"><<print $signatures[_i].phases.join("·")>></span>
</div>
<div class="deck-card-sep"></div>
<div class="deck-card-desc"><<print $signatures[_i].desc>></div>
</div>
</div>
<</for>>
</div>
</div>

<div class="encadre encadre-info">
<div class="encadre-titre">Pool de cartes</div>
<<print $pool.length>> actions universelles. En match, seules les cartes adaptées à la situation te seront proposées. Tes familles natives bénéficient d'un bonus de +1 Force.
</div>

[[C'est parti. Direction l'Académie Hojo. →|Interlude_Acte1]]


:: Creation_Genre {"position":"1150,375","size":"100,100"}
## Qui es-tu ?

Le formulaire d'inscription de l'Académie Hojo est posé devant toi. Stylo en main.

<div class="creation-options">
<span class="creation-opt" data-passage="Creation_Poste" data-setter="$playerGender to 'M'">
<div class="creation-opt-title">Masculin</div>
<div class="creation-opt-desc">Tu t'inscris en tant que garçon.</div>
</span>

<span class="creation-opt" data-passage="Creation_Poste" data-setter="$playerGender to 'F'">
<div class="creation-opt-title">Féminin</div>
<div class="creation-opt-desc">Tu t'inscris en tant que fille.</div>
</span>
</div>


:: Creation_Poste {"position":"25,500","size":"100,100"}
## Quel poste ?

Max Cerri a vu tes relevés sportifs. Il te pose la question directement, sans préambule.

<p>— « Tu joues où ? Et pas "un peu partout". Un poste. Un seul. »</p>

<div class="creation-options">
<span class="creation-opt" data-passage="Creation_Deck" data-setter="$playerPoste to 'défenseur'">
<div class="creation-opt-title">Défenseur</div>
<div class="creation-opt-desc">Tacles, duels, couverture. Tu sécurises ce que les autres construisent. Sandro, Sheun et Lucie tiennent la ligne.</div>
</span>

<span class="creation-opt" data-passage="Creation_Deck" data-setter="$playerPoste to 'milieu'">
<div class="creation-opt-title">Milieu</div>
<div class="creation-opt-desc">Tu lies le jeu, tu récupères, tu distribues. Thomas, Clément et Nayn contrôlent l'entrejeu.</div>
</span>

<span class="creation-opt" data-passage="Creation_Deck" data-setter="$playerPoste to 'attaquant'">
<div class="creation-opt-title">Attaquant</div>
<div class="creation-opt-desc">Tu finis. Tu crées le danger, tu cherches la faille. Audy, Saera et Naela occupent déjà le front.</div>
</span>
</div>


:: Credits {"position":"875,550","size":"100,100"}
<<audio ":all" stop>>
<<nobr>>
<div class="interlude" style="position:relative; min-height:100vh;">
<div class="interlude__line-top"></div>
<div class="interlude__line-bot"></div>

<div class="interlude__acte">Hojo Tigers · Tome 1</div>

<div class="interlude__titre" style="margin-bottom:2.5rem;">Crédits</div>

<div style="text-align:center; max-width:400px; line-height:2.2; font-family:'Barlow Semi Condensed',sans-serif; color:rgba(240,236,228,0.7); font-size:0.8rem; letter-spacing:0.04em;">

<div style="color:rgba(232,117,42,0.8); font-size:0.6rem; font-weight:700; letter-spacing:0.4em; text-transform:uppercase; margin-bottom:0.3rem;">Écriture · Game design · Développement</div>
<div style="color:#f0ece4; font-size:1rem; font-weight:600; margin-bottom:1.5rem;">Martheon22</div>

<div style="color:rgba(232,117,42,0.8); font-size:0.6rem; font-weight:700; letter-spacing:0.4em; text-transform:uppercase; margin-bottom:0.3rem;">Univers original</div>
<div style="margin-bottom:1.5rem;">Inazuma Eleven · Arès no Tenbin<br><span style="font-size:0.7rem; color:rgba(240,236,228,0.4);">© Level-5 Inc.</span></div>

<div style="color:rgba(232,117,42,0.8); font-size:0.6rem; font-weight:700; letter-spacing:0.4em; text-transform:uppercase; margin-bottom:0.3rem;">Musiques</div>

<div style="color:rgba(232,117,42,0.8); font-size:0.5rem; font-weight:700; letter-spacing:0.4em; text-transform:uppercase; margin-bottom:0.3rem;">Morita Koichi / Maoudamashii</div>

<div style="margin-bottom:1.5rem;">
<div>Burning Heart</div> 
</div>

<div style="margin-bottom:1.5rem;">
<div>Neolock 31</div>
<div>Neolock 33</div>
<div>Neolock 39</div>
<div>Neolock 49</div>
<div>Neolock 54</div>
<div>Neolock 82 : The End of the World You Saw</div>
</div>

<div style="margin-bottom:1.5rem;">
<div>Orchestra 11</div>
<div>Orchestra 20</div>
</div>

<div style="margin-bottom:1.5rem;">
<div>Acoustic 12</div>
<div>Acoustic 25 : Afternoon in the Sunlight</div>
<div>Acoustic 50 : The Gap of Bliss</div>
</div>

<div style="margin-bottom:1.5rem;">
<div>Piano 24 : Once Upon a Time in the Autumn Sky</div>
<div>Piano 27 : Cocktail Rays</div>
<div>Piano 29 : End of the day</div>
<div>Piano 31 : To tomorrow</div>
</div>

<div style="margin-bottom:1.5rem;">
<div>Piano 32 : Pulsation</div>
<div>Piano 27 : Cocktail Rays</div>
</div>

<div style="color:rgba(232,117,42,0.8); font-size:0.5rem; font-weight:700; letter-spacing:0.4em; text-transform:uppercase; margin-bottom:0.3rem;">Kevin MacLeod</div>
<div style="margin-bottom:1.5rem;">"Rynos Theme","Feral Chase","Interloper","Nerves","Mistake the Getaway","Malicious","Full On","Exciting Trailer","Mistake the Getaway"</div>





<div style="color:rgba(232,117,42,0.8); font-size:0.6rem; font-weight:700; letter-spacing:0.4em; text-transform:uppercase; margin-bottom:0.3rem;">Moteur</div>
<div style="margin-bottom:1.5rem;">Twine · SugarCube 2</div>

<div style="color:rgba(232,117,42,0.8); font-size:0.6rem; font-weight:700; letter-spacing:0.4em; text-transform:uppercase; margin-bottom:0.3rem;">Remerciements</div>
<div style="margin-bottom:2rem;">[Bêta-testeurs, amis, communauté...]</div>

<div style="font-size:0.6rem; color:rgba(240,236,228,0.25); font-style:italic; margin-top:1rem;">
Ce jeu est une œuvre de fan-fiction. Il n'est ni affilié à Level-5 Inc. ni commercialisé.
</div>

</div>

<div style="margin-top:2rem;">
<<link '<span class="interlude__continuer" style="opacity:1;">← Retour</span>' "Ecran_Titre">><</link>>
</div>

</div>
<</nobr>>


:: Ecran_Titre {"position":"650,25","size":"100,100"}
<<audio ":all" stop>>
<<audio "theme_titre" volume 0.4 loop play>>
<div class="titre-screen">
<div class="titre-logo">HOJO TIGERS</div>
<div class="titre-sub">Livre Dont Vous Êtes le Héros — Tome 1</div>
<div class="titre-timeline">Timeline Inazuma Eleven · Arès no Tenbin</div>

<div id="titre-continuer" style="display:none;">
  <a class="titre-start" id="btn-continuer">Continuer</a>
  <div id="continuer-info" style="font-size:0.75rem; color:var(--ink-ghost); margin-top:0.3rem; font-style:italic;"></div>
</div>

<a class="titre-start" style="background: var(--pitch); margin-top: 0.8rem;" data-passage="Preface">Nouvelle partie</a>

<a class="titre-start" style="background: var(--ink-light); margin-top: 0.8rem;" data-passage="Menu_Sauvegarde">Mes sauvegardes</a>

<div class="titre-mention">Un récit interactif · Football · Choix · Cartes<br>Jouable sur mobile et PC</div>

<a class="titre-changelog" data-passage="Changelog">Changelog · v1.6</a>
</div>

<<script>>
$(document).one(':passageend', function() {
  /* Vérifier si une sauvegarde locale existe */
  if (!Save.autosave.has()) return;
  
  $('#titre-continuer').show();
  
  /* Afficher le résumé si disponible dans la sauvegarde */
  var saveInfo = Save.autosave.get();
  if (saveInfo && saveInfo.state && saveInfo.state.history && saveInfo.state.history.length > 0) {
    var lastState = saveInfo.state.history[saveInfo.state.history.length - 1];
    if (lastState.variables && lastState.variables.resume) {
      $('#continuer-info').text(lastState.variables.resume).show();
    }
  }
  
  $('#btn-continuer').on('click', function() {
    $(this).text('Chargement...');
    Save.autosave.load();
  });
});
<</script>>


:: Interlude_Acte1 {"position":"325,950","size":"100,100"}
<<run window.playInterlude("Acte I", "Sans filet", "jingle_acte1", "Acte1_Arrivee")>>


:: Interlude_Acte2 {"position":"425,2050","size":"100,100"}
<<run window.playInterlude("Acte II", "Le Football Frontier", "jingle_acte2", "Acte2_Intro_FF")>>


:: Introduction {"position":"1000,425","size":"100,100"}
<<silently>>
<<audio "ambiance_match" volume 0.5 loop play>>   /* lancer en boucle */
<<audio "ambiance_match" fadeout>>                 /* fade out */
<<audio "ambiance_match" stop>>                    /* stop sec */
<<audio ":all" stop>>                              /* tout couper */
<</silently>>

<h4><span class="japonais"><span class="ecole">北条学園</span><span class="stade">競技場</span></span><span class="francais">Stade de l'Académie Hojo</span></h4>

<p>Les gradins vibrent sous les pas de centaines de spectateurs. L'ambiance du stade est chargée, remplie d'un mélange d'espoir et de crainte, un tourbillon d'émotions planant au-dessus du terrain tel un nuage invisible et imprévisible. Avec un terrain extérieur modeste, la pelouse avait été rénovée récemment afin de faire un honneur aux invités du jour : les adversaires estimés au maillot couleur vert impérial. Pour les joueurs de l'Académie Hojo, chaque respiration est lourde – non seulement à cause de l'effort physique, mais aussi parce qu'ils portent sur leurs épaules le poids de la confrontation. S'ils gagnent ce match, l'avant-dernier de la phase éliminatoire, les plus orgueilleux pourront dire qu'ils ont gagné le tournoi avant l'heure. A vrai dire, c'est déjà ce que se disaient le principal et le corps dirigeant avant le match. Pour la première fois depuis une dizaine d'années, l'Académie Hojo était dotée d'une équipe étant capable de rayonner l'institution dans le monde du sport.</p>

<p>Pourtant, alors que le match se jouait, les esprits étaient bien moins prétentieux. Les spectateurs avaient encouragé les Tigres d'Hojo sur le terrain pendant trente minutes mais depuis l'ouverture du score par David Samford au retour des vestiaires, le silence s'était abattu sur le modeste complexe sportif.</p>

<span style="text-align: center; font-family: 'Kanit'; font-style: normal; font-weight:800; zoom:1.5">1 - 0</span>

<p>C'est le score du match, actuellement mené par la Royal Academy. Il ne reste que six minutes de jeu. La passion des supporters n’a jamais été aussi intense pour un match des éliminatoires. La Royal Academy, championne en titre depuis quarante ans, n’avait jamais été autant mise en difficulté. Pas depuis dix ans, lorsque les Tigres d’Hojo ont presque réussi l'exploit de les vaincre. Dix ans plus tard, les protagonistes ont changé mais l'histoire se répète. Enfin presque. Il y a dix ans, la Royal était menée au score. Aujourd'hui, c'est Hojo qui est à la traîne.</p>
<p>[[Plus que 5 minutes->Introduction2]]</p>


:: Introduction2 {"position":"1000,550","size":"100,100"}
<p>Le milieu de terrain de Hojo, une fille aux cheveux violet byzantium, passe le ballon à l'attaquant de l'équipe. Celui-ci s'apprête à avancer avec le ballon lorsque soudain, un adversaire surgit devant lui. L'attaquant bouillonne intérieurement : <div class="pensees">"Quand va-t-il enfin me lâcher, celui-là ?"</div>. Jude Sharp, le capitaine de l'équipe adverse, le suit de près depuis le début du match. Il est évident que l'attaquant est considéré comme une menace majeure pour justifier une telle surveillance. À tel point qu'il n'a même pas pu s'approcher de la zone de but adverse. </p>
<p>Dans un mouvement brusque, il essaie de dribbler le capitaine de la Royal, mais échoue. Jude anticipe son mouvement et lui subtilise le ballon, qu'il dégage ensuite au loin. Le joueur au maillot vert impérial et short vert rouillé s'essuie le front trempé de sueur.</p>

<p class="dialogue">Fatigué, Sharp ? Tu vas peut-être enfin me laisser passer. </p>

<p>Un sourire narquois apparaît sur les lèvres de Jude, qui répond sans lâcher l’attaquant d’Hojo d’une semelle.</p>

<p class="dialogue">Ne rêves pas trop, Rayke. Je sais de quoi tu es capable. Je ne te laisserai pas approcher nos cages.</p>
<p class="dialogue">Un pressing comme au bon vieux temps. C’est King qui va être heureux, bougonne le buteur. </p>

<p>Il revient un peu plus bas sur le terrain pour discuter avec la fille qui lui avait envoyé la passe plus tôt.</p>

<p class="dialogue">Saera, essaye de monter au dribble. Jude Sharp me colle comme une sangsue. Je ne me libérerais jamais, mais je peux l’attirer loin de la défense et vous faire de la place.</p>

<p class="dialogue">Ça va être compliqué, Audy. Le reste de la Royal forme un bloc défensif en béton… Et si j’abandonne mes tâches défensives, nous risquons d’encaisser un autre but.</p>

<p class="dialogue">Tant pis. On n’a pas vraiment le choix. Il ne nous reste que quatre minutes pour égaliser.</p>

<p>En dehors du terrain, l'écran géant de télévision diffusait un ralenti de l'action précédente avant d'afficher le temps réglementaire accompagné du score du match. </p>

<h4>2e période : 26e min</h4>
<h4>Royal Ac. 1 - 0 Ac. Hojo</h4>

<p>Saera acquiesce avec un hochement de tête. <div class="dialogue">"Je vais informer le reste de l'équipe de la stratégie à suivre."</div> Elle s'éloigne rapidement, laissant Audy seul. Enfin, jamais réellement seul, puisque toujours sous la surveillance attentive de Jude. Ce dernier s'approche de l'attaquant :</p>

<p class="dialogue">Tu n’as pas peur de parler de votre tactique de jeu devant moi ? À moins que tu ne m’aies laissé entendre la conversation que pour faire une meilleure diversion ?</p>

<p class="dialogue">Qu’est-ce que ça changerait ? Si tu décides de ne plus me marquer, je disparais de ta vue en un clin d’œil. Et dans le cas contraire, tu dois faire confiance en tes coéquipiers pour retenir nos dribbleurs. Dans tous les cas, tu es perdant. </p>
<p class="dialogue">Perdant ? Eh ben. Ta confiance en tes coéquipiers me surprend. Tu n’as jamais eu autant confiance en nous quand tu jouais pour la Royal Academy. </p>
<p class="dialogue">Vous jouez pour Ray Dark, cracha Audy. Evidemment que vous n'êtes pas dignes de confiance. Mais je connais Nae’ et Saera, et je ne peux que croire qu’elles vont vous dribbler sans problème. Ce n’est pas votre petite formation qui va y changer quelque chose.</p>


<p>D’autant plus que désormais, toutes les conditions sont réunies. Le match touche à sa fin, et les deux équipes sont fatiguées, sauf Saera et Naela, les deux milieux de terrain centraux de l'équipe Hojo. En général, elles gèrent le jeu de l'équipe, ce qui leur permet de conserver leur énergie pour faire la différence dans les moments clés. Mais à ce moment précis du match, elles sont les seules capables de faire les différences sur le terrain.</p>
 
[[Il est temps de retourner la situation->Introduction3]]


:: Introduction3 {"position":"1000,675","size":"100,100"}
<<audio "introMusic" volume 0.5 fadeoverto 5 0>><<audio "introMusic" stop>><<audio "introMusic2" volume 0.5 play loop>>
<p>Un ailier passe à Naela qui, avec un contrôle précis, dépasse Derek Swing. Elle envoie une passe millimétrée à Saera qui à son tour, d'un geste rapide, élimine deux défenseurs adverses. Le déséquilibre est créé. Une ouverture se dessine dans la défense. </p>

<p>Pourtant, le but est encore loin et Joe King, le gardien, est trop expérimenté pour être pris au dépourvu à l'entrée de la surface. Saera s'avance donc avec le ballon. En urgence, Peter Drent, le dernier défenseur de la Royal, tente de l'atteindre. L'espace est là. Un ailier est libre de tout marquage. Saera saisit l'occasion pour effectuer une passe décisive. Drent, le géant, n'aura pas le temps de revenir à sa position. Ce sera un face-à-face avec le gardien. </p>

<p>Devant les cages de la Royal Academy, le deuxième attaquant d'Hojo prépare sa frappe et tire avec désespoir. Le tir est cadré, mais Joe King est trop proche et dispose d'excellents réflexes. Il repousse le tir avec ses gants. La balle rebondit et atterrit aux pieds de Saera. Avec un sourire en coin, il semble qu'elle ait tout prévu. Tout anticipé, pour ce moment d'espoir et de libération, cette égalisation tant attendue. Il ne reste plus qu'à tirer pour obtenir les prolongations pour les Tigres d'Hojo. Le stade célèbre déjà le but dans un vacarme assourdissant.</p>

[[Après la fin du match->Introduction3bis]]


:: Introduction3bis {"position":"1000,800","size":"100,100"}
<<audio "introMusic2" volume 0.5 fadeoverto 3 0>>
<<silently>><<audio "introMusic2" stop>><</silently>>

<p style="text-indent:0; margin-top:0">…Un son brutal et sourd résonne dans le stade.</p>

<p style="text-indent:0; margin-top:0">…</p>

<p style="text-indent:0; margin-top:0">… Ce n'est pas le bruit d'un ballon en cuir frappé à pleine vitesse. </p>

<p style="text-indent:0; margin-top:0">Ce n'est pas l'écho des crampons glissant sur l'herbe. </p>

<p style="text-indent:0; margin-top:0">C'est un bruit sec, suivi d'un cri de douleur. </p>

<p>Elle a été taclée par derrière, fauchée, tout comme les rêves des joueurs d'Hojo cet après-midi. Saera s'effondre sur le terrain, tenant son genou en gémissant de douleur. Ce jour-là, à seize heures, il n'y a eu qu'un seul coup de sifflet. Ce n'était ni pour siffler un but ni pour annoncer la fin du match, mais pour prévenir la bagarre imminente.</p>

[[Après la fin du match->Introduction4]]


:: Introduction4 {"position":"1000,925","size":"100,100"}
<<audio "introMusic3" volume 0.5 play loop>>

<p>Le vestiaire est silencieux, comme si un voile de plomb s'était abattu sur les joueurs d'Hojo. L'ambiance festive qui aurait dû régner après un tel match s'est transformée en un mélange de colère et de désespoir. Audy, assis sur un banc, fixe le sol, ses poings marqués d'ecchymoses, serrés jusqu'à ce que ses articulations blanchissent. À côté de lui, Naela respire difficilement, encore secouée par l'image de Saera s'effondrant sur le terrain.</p>

<p class="dialogue">Comment va-t-elle ? Demande finalement un défenseur, brisant le silence pesant.</p>

<p class="dialogue">Les ambulanciers ont évacué Saera très vite du terrain, répond Emaël Lorima, l’entraîneur d’Hojo. Nous saurons assez vite la réponse.</p>


<p>Son visage, habituellement rayonnant, est marqué par l'inquiétude. Il a assisté à la scène de loin, mais il a souvent vu ce genre de blessures. Une rupture des ligaments croisés probablement. Une blessure lourde, surtout à un si jeune age. Il est souvent dur de rebondir sportivement après ce genre de blessures.</p>

<p>Assis sur sa chaise, Audy relève brusquement la tête, l’air déterminé.</p>

<p class="dialogue">Je dois aller la voir.</p>

<p class="dialogue">Pas maintenant, Audy, intervient le coach. Les médecins s'occupent d'elle. Tu ne pourras rien faire de plus.</p>

<p>Le regard d'Audy se durcit, mais il reste assis, conscient de la vérité dans ces paroles.</p>

<p class="dialogue">Ce n'était pas un tacle accidentel, gronde-t-il. C'était délibéré. La Royal Academy savait qu'elle était notre dernière chance de marquer.</p>

<p>Une jeune fille aux cheveux cramoisis s'approche de l'attaquant et pose délicatement sa main sur son bras, où se trouvait encore le brassard de capitaine.</p>

<p class="dialogue">Ça ne changera rien maintenant, Audy. Nous avons perdu. Le tournoi est terminé pour nous.</p>

<p>Ces mots résonnent douloureusement dans le vestiaire. Chaque joueur revit mentalement les moments importants du match, les occasions manquées, les erreurs commises. La réalité de leur défaite s'impose brutalement.</p>

<p>Le coach Lorima s'avance au centre du vestiaire, attirant l'attention de tous. Sa silhouette athlétique, souvent inspirante, semble aujourd’hui porter le poids de cette défaite sur ses épaules.</p>

<p class="dialogue">Je sais que ce n'est pas le moment que vous espériez pour des adieux, commence-t-il. Mais comme vous le savez, c'était mon dernier match avec vous.</p>


<p>Un murmure parcourt l'équipe. Bien sûr, ils étaient au courant de son départ imminent pour la France, mais personne n'avait voulu y penser avant la fin du tournoi. Un tournoi qui s'achevait maintenant, bien plus tôt que prévu.</p>

<p class="dialogue">Vous avez joué avec beaucoup de courage, avec détermination, poursuit-il. La Royal Academy a peut-être gagné, mais ils savent qu'ils ont affronté une véritable équipe aujourd'hui. Vous pouvez être fiers de vous.</p>

<p class="dialogue">À quoi ça sert la fierté quand Saera est à l'hôpital ? Lance Audy, la voix tremblante de colère.</p>

<p>L’entraineur répond du tac au tac avec une assurance marquée.</p>

<p class="dialogue">Ça sert à se relever, et à revenir plus fort. Ce n'est pas la fin, c'est juste une pause dans votre parcours. Cette année, vous m’avez montré ce que vous valez en tant qu’équipe. Et vous vous êtes bien battus. Finir demi-finaliste des éliminatoires, ce n’est pas rien, surtout après n’avoir encaissé qu’un but ! Personne n‘a fait ça depuis… Depuis vos aînés, il y a dix ans. Vous êtes la réincarnation… Non. Vous êtes le renouveau des Tigres d’Hojo, et je n’ai aucun doute quant à votre capacité de remporter le tournoi l’an prochain.</p>

<p class="dialogue">...Reculer pour mieux sauter, conclut un défenseur.</p>

<p>Emaël Lorima approuve d’un signe de tête. Puis, il sort de son sac une enveloppe qu'il tend à chacun des joueurs. L’entraîneur français sourit faiblement.</p>

<p class="dialogue">Je suivrai vos résultats. Et qui sait, peut-être que nos chemins se recroiseront un jour.</p>


<p>Il se dirige vers la porte, puis se retourne une dernière fois, le temps de s’imprégner une dernière fois de cette image, issue d’une défaite certes, toutefois si parlante du chemin qu’ils ont parcouru ensemble. </p>

<p class="pensees">“Je sais que vous y arriverez.”</p>


<<silently>> [[Quelques mois plus tard...->Introduction5]] <</silently>>
<<silently>> [[Quelques mois plus tard...->Chapitre 1.1]] <</silently>>
<div class="br"></div>

[[Fin de la démo.->TransitionSceneFin]]


:: Introduction5 {"position":"1425,800","size":"100,100"}
<<audio "introMusic3" volume 0.5 fadeoverto 3 0>>
<<audio "introMusic3" stop>>
<<audio "introMusic4" volume 0.5 play loop>>


Le bruit des pas résonne entre les bâtiments, balayant la cour d’entrée de l’Académie Hojo d’un écho qui sonne un peu trop solennel pour un jeudi matin. Les mains enfouies dans les poches de ta veste, tu hésites à franchir le portail principal. Tu as déjà vu plus accueillant qu’une muraille de béton couverte de lianes rouges et d’inscriptions calligraphiées, mais aujourd’hui, la façade est tachetée de banderoles bleu nuit et or, tendues comme des blessures mal cicatrisées. Des  Les restes du match d’hier ? Certainement. Les drapeaux des Tigres d’Hojo pendent encore aux balcons, affaissés, battus par le vent sec de janvier.

Il y a un monde fou devant l’entrée. Des élèves se bousculent, certains affalés sur les marches, d’autres debout en petits groupes à disséquer l’actualité fraîche. Il perçoit des regards en coin, curieux, parfois méfiants, mais la plupart s’en fichent, trop occupés à refaire l’histoire du match ou à balancer des rumeurs sur les réseaux du lycée. Lui, il préfère raser les murs, histoire de ne pas attirer l’attention. Il serre un peu plus son sac contre lui et marmonne dans sa barbe invisible, en s’imaginant passer la journée incognito.

Raté.

À peine a-t-il posé un pied sur le bitume que deux silhouettes déboulent devant lui, stoppant net sa trajectoire. L’une d’elles sourit à pleines dents, l’autre a l’air de scruter jusqu’à la moelle de ses os. Il ne lui faut pas plus de deux secondes pour comprendre que la fille devant lui – cheveux châtain glacé, yeux gris-bleus pétillants – n’est autre que Naela Powell. Le visage lui est familier ; il a vu des affiches avec son nom placardées dans le hall, parfois même des mèmes douteux sur le groupe LINE de sa classe.

[[Fin de la démo.->SceneFinUpdate]]



:: Match1_Controle {"position":"925,1575","size":"100,100"}
<<set $energy -= 1>>
<<set $danger += 1>>
<<set $momentum += 1>>
<<run window.addMastery($lastCardId)>>

Le geste est propre. Sans fioritures. Le ballon obéit. L'action continue.

<<if $playerPoste is "attaquant">>
Tu contrôles, tu pivotes, tu remets vers Thomas qui relance immédiatement. L'action se prolonge — Saera reçoit dans la zone, temporise, passe vers Nayn qui frappe. Au-dessus.

Mais la séquence était bonne. Fluide. Tu t'es intégré au mouvement sans le casser.
<<elseif $playerPoste is "milieu">>
Tu temporises, tu gardes, et quand l'espace se crée, tu glisses le ballon vers le flanc. Mizuki récupère et fonce. L'action meurt sur un centre trop long — mais le milieu de terrain a tenu.
<<elseif $playerPoste is "défenseur">>
Tu lis la passe, tu coupes la trajectoire. Récupération nette. Relance immédiate vers Thomas. L'équipe reprend le contrôle.
<</if>>

<<set $reputation += 3>>
<<set $relations["Max"] += 2>>

<div class="encadre encadre-info">
<div class="encadre-titre">Résultat : Succès</div>
Énergie -1 · Momentum +1 · Danger +1<br>
Un premier ballon maîtrisé. L'équipe commence à t'intégrer dans ses circuits.
</div>

[[Moment suivant.|Match_Router]]


:: Match1_Couverture {"position":"175,1700","size":"100,100"}
<<set $energy -= 1>>
<<set $danger -= 1>>
<<run window.addMastery($lastCardId)>>

Tu fermes l'espace. Le couloir se réduit. L'attaquant adverse est forcé de ralentir — et Sandro vient doubler derrière toi. Récupération collective.

<<set $reputation += 3>>
<<set $relations["Sandro"] += 3>>
<<set $momentum += 1>>

<div class="encadre encadre-info">
<div class="encadre-titre">Résultat : Succès</div>
Énergie -1 · Momentum +1 · Danger -1<br>
Défense propre. Sandro hoche la tête. C'est son langage.
</div>

[[Moment suivant.|Match_Router]]


:: Match1_Dribble {"position":"1050,1575","size":"100,100"}
<<set $energy -= 2>>

Tu reçois le ballon et tu fonces. Le défenseur recule — tu accélères, tu crochètes.

<<set _native to ($nativeFamilies.indexOf($lastFamily) !== -1) ? 1 : 0>>
<<set _mast to window.masteryBonus($lastCardId)>>
<<set _matchup to window.getMatchup($lastCardId)>>
<<set _roll to random(1, 20)>>
<<set _score to 5 + _native + _mast + _matchup + Math.floor(($technique * 2 + $physique) / 30) + $momentum + 3>>
<<set _total to _score + _roll>>

<<if _total >= 16>>
Le défenseur est éliminé. Tu débouches dans l'espace — Audy est devant toi, démarqué. Tu passes. Audy contrôle, frappe. Le gardien détourne en corner.

<<run window.addMastery($lastCardId)>>

<<set $momentum += 1>>
<<set $danger += 2>>
<<set $reputation += 5>>
<<set $relations["Audy"] += 3>>

<div class="encadre encadre-info">
<div class="encadre-titre">Résultat : Succès</div>
Énergie -2 · Momentum +1 · Danger +2<br>
Belle action. L'équipe sait que tu peux créer du danger.
</div>

<<else>>
Le crochet est lu. Le défenseur te prend le ballon proprement. Perte de balle. Odawara relance.

<<set $momentum -= 1>>
<<set $reputation += 1>>

<div class="encadre encadre-danger">
<div class="encadre-titre">Résultat : Échec</div>
Énergie -2 · Momentum -1<br>
Le geste était là, pas le timing. Tu sens le regard de Max dans ton dos.
</div>
<</if>>

[[Moment suivant.|Match_Router]]


:: Match1_Passe {"position":"1175,1575","size":"100,100"}
<<set $danger += 1>>
<<run window.addMastery($lastCardId)>>

Passe courte, un touche. Simple. Efficace. Le ballon repart vers Clément qui oriente le jeu. L'action continue sans toi — mais elle continue parce que tu n'as pas cassé le rythme.

<<set $reputation += 2>>

<div class="encadre encadre-info">
<div class="encadre-titre">Résultat : Succès (automatique)</div>
Énergie inchangée · Danger +1<br>
Invisible, mais juste. Exactement ce que Max a demandé.
</div>

[[Moment suivant.|Match_Router]]


:: Match1_Pressing {"position":"425,1700","size":"100,100"}
<<set $energy -= 2>>

<<set _native to ($nativeFamilies.indexOf($lastFamily) !== -1) ? 1 : 0>>
<<set _mast to window.masteryBonus($lastCardId)>>
<<set _matchup to window.getMatchup($lastCardId)>>
<<set _roll to random(1, 20)>>
<<set _score to 5 + _native + _mast + _matchup + Math.floor(($physique * 2 + $vision) / 30) + $momentum>>
<<set _total to _score + _roll>>

<<if _total >= 14>>
Tu forces l'erreur. L'adversaire panique, sa passe est molle — Thomas intercepte et lance le contre.

<<run window.addMastery($lastCardId)>>

<<set $momentum += 1>>
<<set $reputation += 4>>
<<set $relations["Thomas"] += 2>>

<div class="encadre encadre-info">
<div class="encadre-titre">Résultat : Succès</div>
Énergie -2 · Momentum +1<br>
Pressing gagnant. Tu montres de l'intensité.
</div>

<<else>>
L'adversaire te passe. Ton pressing trop haut laisse un espace — heureusement, Sandro couvre.

<<set $reputation += 1>>

<div class="encadre encadre-danger">
<div class="encadre-titre">Résultat : Échec</div>
Énergie -2<br>
Trop enthousiaste. Le pressing était désordonné.
</div>
<</if>>

[[Moment suivant.|Match_Router]]


:: Match1_Profondeur {"position":"550,1700","size":"100,100"}
<<set $energy -= 1>>

<<set _native to ($nativeFamilies.indexOf($lastFamily) !== -1) ? 1 : 0>>
<<set _mast to window.masteryBonus($lastCardId)>>
<<set _matchup to window.getMatchup($lastCardId)>>
<<set _roll to random(1, 20)>>
<<set _score to 5 + _native + _mast + _matchup + Math.floor(($vision * 2 + $technique) / 30) + $momentum + 2>>
<<set _total to _score + _roll>>

<<if _total >= 15>>
La passe perce la défense. Audy contrôle en pleine course — face au gardien. Il temporise, décale Saera... qui hésite. Le ballon revient vers Nayn qui frappe. Repoussé.

Mais la passe était parfaite.

<<run window.addMastery($lastCardId)>>

<<set $danger += 3>>
<<set $momentum += 1>>
<<set $reputation += 5>>
<<set $relations["Audy"] += 3>>

<div class="encadre encadre-info">
<div class="encadre-titre">Résultat : Succès</div>
Énergie -1 · Momentum +1 · Danger +3<br>
Passe décisive en puissance. L'occasion est créée, même si la finition n'a pas suivi.
</div>

<<else>>
La passe est interceptée. Trop ambitieux — le timing n'y était pas.

<<set $momentum -= 1>>
<<set $reputation += 1>>

<div class="encadre encadre-danger">
<div class="encadre-titre">Résultat : Échec</div>
Énergie -1 · Momentum -1<br>
L'intention était bonne, l'exécution non. Clément récupère derrière.
</div>
<</if>>

[[Moment suivant.|Match_Router]]


:: Match1_Tacle {"position":"300,1700","size":"100,100"}
<<set $energy -= 2>>

<<set _native to ($nativeFamilies.indexOf($lastFamily) !== -1) ? 1 : 0>>
<<set _mast to window.masteryBonus($lastCardId)>>
<<set _matchup to window.getMatchup($lastCardId)>>
<<set _roll to random(1, 20)>>
<<set _score to 6 + _native + _mast + _matchup + Math.floor(($physique * 2 + $vision) / 30) + $momentum>>
<<set _total to _score + _roll>>

<<if _total >= 14>>
Tacle glissé. Net. Le ballon jaillit et Lucie le récupère. Propre, engagé, sans faute.

<<run window.addMastery($lastCardId)>>

<<set $momentum += 1>>
<<set $reputation += 5>>
<<set $relations["Lucie"] += 3>>
<<set $danger -= 1>>

<div class="encadre encadre-info">
<div class="encadre-titre">Résultat : Succès</div>
Énergie -2 · Momentum +1 · Danger -1<br>
Un tacle qui dit « je suis là ». Lucie te tape dans le dos en passant.
</div>

<<else>>
Tu plonges. L'attaquant te passe. L'arbitre hésite — pas de faute, mais tu es au sol. Teo doit intervenir derrière.

<<set $reputation += 1>>
<<set $momentum -= 1>>

<div class="encadre encadre-danger">
<div class="encadre-titre">Résultat : Échec</div>
Énergie -2 · Momentum -1<br>
Engagé, mais battu. Le timing était décalé.
</div>
<</if>>

[[Moment suivant.|Match_Router]]


:: Match1_Tir {"position":"50,1700","size":"100,100"}
<<set $energy -= 2>>

Tu reçois à vingt-cinq mètres, tu te retournes — et tu frappes. Du pied droit, en force. Le ballon part en flèche.

<<set _native to ($nativeFamilies.indexOf($lastFamily) !== -1) ? 1 : 0>>
<<set _mast to window.masteryBonus($lastCardId)>>
<<set _matchup to window.getMatchup($lastCardId)>>
<<set _roll to random(1, 20)>>
<<set _score to 4 + _native + _mast + _matchup + Math.floor(($physique * 2 + $technique) / 30) + $momentum>>
<<set _total to _score + _roll>>

<<if _total >= 18>>
Le gardien plonge — trop tard. Le ballon se loge dans le coin droit. Tu restes immobile une seconde. Puis Nayn te saute dessus.

<<run window.addMastery($lastCardId)>>

<<set $matchScore[0] += 1>>
<<set $momentum += 2>>
<<set $danger to 0>>
<<set $reputation += 8>>
<<set $relations["Max"] += 5>>
<<set $relations["Nayn"] += 5>>

<div class="scoreboard">
<div class="scoreboard-team">HOJO</div>
<div class="scoreboard-score"><<print $matchScore[0]>> – <<print $matchScore[1]>></div>
<div class="scoreboard-team">ODAWARA</div>
</div>
<div class="scoreboard-minute">57'</div>

<div class="encadre encadre-relation">
<div class="encadre-titre">BUT !</div>
Ton premier but sous le maillot des Tigres. L'équipe te regarde différemment.
</div>

<<elseif _total >= 12>>
Le tir est cadré — le gardien repousse en corner. Pas de but, mais la frappe a fait lever le gradin.

<<run window.addMastery($lastCardId)>>
<<set $danger += 2>>
<<set $momentum += 1>>
<<set $reputation += 4>>

<div class="encadre encadre-info">
<div class="encadre-titre">Résultat : Mitigé</div>
Énergie -2 · Momentum +1 · Danger +2<br>
Pas de but, mais de l'audace. Max note.
</div>

<<else>>
Le ballon part en tribunes. Silence gêné. Nayn te lance un regard. Max ne dit rien — ce qui est pire.

<<set $momentum -= 1>>
<<set $reputation -= 1>>

<div class="encadre encadre-danger">
<div class="encadre-titre">Résultat : Échec</div>
Énergie -2 · Momentum -1<br>
Trop loin, trop tôt. Le message de Max était « collectif ». Tu as choisi « individuel ».
</div>
<</if>>

[[Moment suivant.|Match_Router]]


:: Match_GenResolution {"position":"675,1825","size":"100,100"}
/* === RÉSOLUTION GÉNÉRIQUE === */
<<set _res to window.matchEngine.resolve($lastCardId)>>

<<if _res.result is "succes">>
<<if _res.goal>>
<div class="scoreboard">
<div class="scoreboard-team">HOJO</div>
<div class="scoreboard-score"><<print $matchScore[0]>> – <<print $matchScore[1]>></div>
<div class="scoreboard-team"><<print $matchAdversaire>></div>
</div>
<div class="scoreboard-minute"><<print $matchMinute>>' — BUT !</div>

<<print _res.text>>

<div class="encadre encadre-relation">
<div class="encadre-titre">★ BUT !</div>
<<print _res.card.name>> · Force <<print _res.card.force>> + jet <<print _res.roll>> = <<print _res.total>><br>
Le filet tremble. L'équipe te saute dessus.
</div>

<<else>>
<<print _res.text>>

<div class="encadre encadre-info">
<div class="encadre-titre">Résultat : Succès</div>
<<print _res.card.name>> · Force <<print _res.card.force>> + jet <<print _res.roll>> = <<print _res.total>><br>
<<if _res.matchup > 0>>Matchup favorable (+2) · <</if>><<if _res.native > 0>>Famille native (+1) · <</if>><<if _res.mastered > 0>>Maîtrisée (+1) · <</if>>
Momentum +1 · Danger +2 · Réputation +5
</div>
<</if>>

<<elseif _res.result is "mitige">>
<<print _res.text>>

<div class="encadre encadre-info">
<div class="encadre-titre">Résultat : Mitigé</div>
<<print _res.card.name>> · Force <<print _res.card.force>> + jet <<print _res.roll>> = <<print _res.total>><br>
<<if _res.matchup < 0>>Matchup défavorable (-2) · <</if>>
Danger +1 · Réputation +2
</div>

<<else>>
<<print _res.text>>

<div class="encadre encadre-danger">
<div class="encadre-titre">Résultat : Échec</div>
<<print _res.card.name>> · Force <<print _res.card.force>> + jet <<print _res.roll>> = <<print _res.total>><br>
<<if _res.matchup < 0>>Matchup défavorable (-2) · <</if>><<if _res.penalty > 0>>Pénalité fatigue (-<<print _res.penalty>>) · <</if>>
Momentum -1
</div>
<</if>>

<<if $matchMoment >= $matchMaxMoments>>
<<link "Fin du match." $matchEndPassage>><</link>>
<<else>>
[[Moment suivant.|Match_Router]]
<</if>>


:: Match_Generated {"position":"550,1825","size":"100,100"}
/* === MOMENT GÉNÉRÉ (semi-aléatoire) === */

<div class="hud"><div class="hud-inner">
<div class="hud-item"><span class="hud-label">Score</span> <span class="hud-value"><<print $matchScore[0]>>–<<print $matchScore[1]>></span></div>
<div class="hud-item"><span class="hud-label">Min</span> <span class="hud-value"><<print $matchMinute>>'</span></div>
<div class="hud-item"><span class="hud-label">Énergie</span> <span class="hud-value hud-energy"><<energyGauge>></span></div>
<div class="hud-item"><span class="hud-label">Momentum</span> <span class="hud-value"><<momentumDisplay>></span></div>
</div></div>

<div class="encadre encadre-info">
<div class="encadre-titre">Moment <<print $matchMoment>> — <<print $matchMinute>>'</div>
<strong>Phase :</strong> <<print $matchPhase>><br>
<strong>Action adverse :</strong> <span class="enemy-action"><<print window.enemyActionLabel($enemyAction)>></span>
</div>

<<print $genFlavor>>

<div class="card-hand">
<<for _i to 0; _i < $genHand.length; _i++>>
<<set _c to $genHand[_i]>>
<<set _risk to (_c.risk is "Élevé") ? "high" : ((_c.risk is "Moyen") ? "mid" : "low")>>
<div class="card card-risk-<<print _risk>>" data-passage="Match_GenResolution" data-setter="$lastCardId to '<<print _c.id>>', $lastFamily to '<<print _c.family>>'">
<div class="card-name"><<print _c.name>></div>
<div class="card-stats"><span class="card-stat">F:<<print _c.force>><<if $nativeFamilies.indexOf(_c.family) !== -1>> <span class="card-native-bonus">+1</span><</if>><<if window.masteryBonus(_c.id) > 0>> <span class="card-native-bonus" style="color:#ff8f00">+1</span><</if>></span><span class="card-stat"><<print _c.stat.substring(0,3).toUpperCase()>>·<<print _c.stat2.substring(0,3).toUpperCase()>></span><span class="card-stat">É:<<print _c.cost>></span></div>
<div class="card-desc"><<print _c.desc>></div>
<div class="card-matchup"><<print window.matchupLabel(_c.id)>></div>
<<if window.getMastery(_c.id) > 0>><div class="card-matchup" style="color:#ff8f00;font-size:0.55rem"><<print window.masteryDots(_c.id)>></div><</if>>
</div>
<</for>>
</div>


:: Match_Router {"position":"425,1825","size":"100,100"}
/* === ROUTEUR DE MATCH ===
   Incrémente le moment, vérifie fin, cherche scripté, sinon génère.
*/

<<set $matchMoment += 1>>

<<if $matchMoment > $matchMaxMoments>>
  <<goto $matchEndPassage>>
<</if>>

/* Vérifier les moments scriptés */
<<set _found to false>>
<<for _i to 0; _i < $matchScripted.length; _i++>>
  <<if $matchScripted[_i].moment is $matchMoment and not _found>>
    <<set _entry to $matchScripted[_i]>>
    <<if _entry.condition is "">>
      <<set _found to true>>
      <<goto _entry.passage>>
    <<elseif eval(_entry.condition)>>
      <<set _found to true>>
      <<goto _entry.passage>>
    <</if>>
  <</if>>
<</for>>

/* Pas de moment scripté → générer */
<<if not _found>>
  <<run window.matchEngine.generate()>>
  <<goto "Match_Generated">>
<</if>>


:: Menu_Sauvegarde {"position":"775,25","size":"100,100"}
<div class="preface">
<h2>Sauvegardes en ligne</h2>

<div id="auth-status"></div>

<div id="auth-forms">
  <!-- Formulaire de connexion -->
  <div id="form-login">
    <h3>Connexion</h3>
    <input type="text" id="login-input" placeholder="Email ou pseudo" style="width:100%; padding:0.5rem; margin-bottom:0.5rem; border:1px solid var(--ink-ghost); border-radius:4px;">
    <input type="password" id="pass-input" placeholder="Mot de passe" style="width:100%; padding:0.5rem; margin-bottom:0.5rem; border:1px solid var(--ink-ghost); border-radius:4px;">
    <button id="btn-login" class="titre-start" style="width:100%; margin-bottom:0.5rem;">Se connecter</button>
    <p style="text-align:center; font-size:0.8rem;"><a href="#" id="show-register">Pas de compte ? S'inscrire</a></p>
    <p id="msg-login" style="color:#c44; font-size:0.8rem; text-align:center;"></p>
  </div>

  <!-- Formulaire d'inscription -->
  <div id="form-register" style="display:none;">
    <h3>Créer un compte</h3>
    <input type="email" id="reg-email" placeholder="Email" style="width:100%; padding:0.5rem; margin-bottom:0.5rem; border:1px solid var(--ink-ghost); border-radius:4px;">
    <input type="text" id="reg-username" placeholder="Pseudo" style="width:100%; padding:0.5rem; margin-bottom:0.5rem; border:1px solid var(--ink-ghost); border-radius:4px;">
    <input type="password" id="reg-pass" placeholder="Mot de passe (8 car. min)" style="width:100%; padding:0.5rem; margin-bottom:0.5rem; border:1px solid var(--ink-ghost); border-radius:4px;">
    <button id="btn-register" class="titre-start" style="width:100%; margin-bottom:0.5rem;">Créer mon compte</button>
    <p style="text-align:center; font-size:0.8rem;"><a href="#" id="show-login">Déjà un compte ? Se connecter</a></p>
    <p id="msg-register" style="color:#c44; font-size:0.8rem; text-align:center;"></p>
  </div>
</div>

<!-- Zone connecté -->
<div id="saves-zone" style="display:none;">
  <p style="margin-bottom:1rem;">Connecté : <strong id="username-display"></strong> · <a href="#" id="btn-logout">Déconnexion</a></p>
  
  <h3>Nouvelle sauvegarde</h3>
  <input type="text" id="new-slot-name" placeholder="Nom de la sauvegarde" style="width:70%; padding:0.5rem; border:1px solid var(--ink-ghost); border-radius:4px;">
  <button id="btn-new-save" class="titre-start" style="padding:0.5rem 1rem; margin-left:0.5rem;">💾</button>
  <p id="msg-save" style="color:var(--pitch); font-size:0.8rem; margin-top:0.5rem;"></p>
  
  <h3 style="margin-top:1.5rem;">Mes sauvegardes</h3>
  <div id="saves-list"><p>Chargement...</p></div>
</div>

<p style="margin-top:2rem; text-align:center;">
<<if $_returnPassage>>
<<link "← Retour au jeu">><<run Engine.play(State.variables._returnPassage)>><</link>>
<<else>>
[[← Retour à l'écran titre|Ecran_Titre]]
<</if>>
</p>
</div>

<<script>>
$(document).one(':passageend', function() {
  var $status = $('#auth-status');
  var $forms = $('#auth-forms');
  var $savesZone = $('#saves-zone');
  var $savesList = $('#saves-list');
  
  function updateUI() {
    if (HojoAPI.isLoggedIn()) {
      $forms.hide();
      $savesZone.show();
      $('#username-display').text(HojoAPI.user.username);
      loadSaves();
    } else {
      $forms.show();
      $savesZone.hide();
    }
  }
  
  function loadSaves() {
    $savesList.html('<p>Chargement...</p>');
    HojoAPI.listSaves().then(function(result) {
      if (result.saves.length === 0) {
        $savesList.html('<p style="color:var(--ink-ghost);">Aucune sauvegarde.</p>');
        return;
      }
      var html = '<ul style="list-style:none; padding:0;">';
      result.saves.forEach(function(save) {
        html += '<li style="padding:0.6rem; margin-bottom:0.5rem; background:var(--paper-alt); border-radius:4px; display:flex; justify-content:space-between; align-items:center;">';
        html += '<div><strong>' + save.slot_name + '</strong><br><small style="color:var(--ink-ghost);">' + (save.chapter || 'Début') + ' · ' + save.playtime_formatted + '</small></div>';
        html += '<div>';
        html += '<button class="btn-load" data-slot="' + save.slot_name + '" style="padding:0.3rem 0.6rem; margin-right:0.3rem; cursor:pointer;">▶ Charger</button>';
        html += '<button class="btn-delete" data-slot="' + save.slot_name + '" style="padding:0.3rem 0.6rem; cursor:pointer; color:#c44;">✕</button>';
        html += '</div></li>';
      });
      html += '</ul>';
      $savesList.html(html);
      
      // Event listeners pour charger
      $savesList.find('.btn-load').on('click', function() {
        var slot = $(this).data('slot');
        $(this).text('...');
        HojoAPI.loadGame(slot).then(function(result) {
          window.notify('Partie chargée !');
          Engine.play(result.save.chapter || 'Ecran_Titre');
        }).catch(function(e) {
          window.notify('Erreur: ' + e.message);
        });
      });
      
      // Event listeners pour supprimer
      $savesList.find('.btn-delete').on('click', function() {
        var slot = $(this).data('slot');
        if (confirm('Supprimer "' + slot + '" ?')) {
          HojoAPI.deleteSave(slot).then(function() {
            window.notify('Sauvegarde supprimée');
            loadSaves();
          }).catch(function(e) {
            window.notify('Erreur: ' + e.message);
          });
        }
      });
    }).catch(function(e) {
      $savesList.html('<p style="color:#c44;">Erreur: ' + e.message + '</p>');
    });
  }
  
  // Toggle formulaires
  $('#show-register').on('click', function(e) {
    e.preventDefault();
    $('#form-login').hide();
    $('#form-register').show();
  });
  $('#show-login').on('click', function(e) {
    e.preventDefault();
    $('#form-register').hide();
    $('#form-login').show();
  });
  
  // Connexion
  $('#btn-login').on('click', function() {
    var login = $('#login-input').val();
    var pass = $('#pass-input').val();
    $(this).text('...');
    HojoAPI.login(login, pass).then(function() {
      window.notify('Connecté !');
      updateUI();
    }).catch(function(e) {
      $('#msg-login').text(e.message);
      $('#btn-login').text('Se connecter');
    });
  });
  
  // Inscription
  $('#btn-register').on('click', function() {
    var email = $('#reg-email').val();
    var username = $('#reg-username').val();
    var pass = $('#reg-pass').val();
    $(this).text('...');
    HojoAPI.register(email, username, pass).then(function() {
      window.notify('Compte créé !');
      updateUI();
    }).catch(function(e) {
      $('#msg-register').text(e.message);
      $('#btn-register').text('Créer mon compte');
    });
  });
  
  // Déconnexion
  $('#btn-logout').on('click', function(e) {
    e.preventDefault();
    HojoAPI.logout();
    window.notify('Déconnecté');
    updateUI();
  });
  
  // Nouvelle sauvegarde
  $('#btn-new-save').on('click', function() {
    var slotName = $('#new-slot-name').val().trim();
    if (!slotName) {
      $('#msg-save').text('Entre un nom pour la sauvegarde').css('color', '#c44');
      return;
    }
    var returnPassage = State.variables._returnPassage || 'Ecran_Titre';
    $(this).text('...');
    HojoAPI.saveGame(slotName, returnPassage).then(function() {
      $('#msg-save').text('Sauvegardé !').css('color', 'var(--pitch)');
      $('#new-slot-name').val('');
      $('#btn-new-save').text('💾');
      loadSaves();
    }).catch(function(e) {
      $('#msg-save').text(e.message).css('color', '#c44');
      $('#btn-new-save').text('💾');
    });
  });
  
  // Init
  updateUI();
});
<</script>>


:: Preface {"position":"775,25","size":"100,100"}
<<audio "theme_titre" fadeout>>
<div class="preface">

## Avant-propos

Ce livre est un **LDVELH** — un Livre Dont Vous Êtes le Héros.

Tu incarnes un(e) jeune footballeur(se) qui intègre l'Académie Hojo, un club dont la gloire passée s'est ternie. L'équipe — les **Tigres** — prépare le Football Frontier, le tournoi national. Tu arrives comme douzième joueur. Tout est à prouver.

<div class="scene-break">· · ·</div>

### Comment jouer

**Hors du terrain**, tu fais des choix narratifs. Chaque décision affecte ta réputation, tes relations avec les membres de l'équipe, et la suite de l'histoire. Il n'y a pas de mauvais choix — seulement des chemins différents.

**Sur le terrain**, le jeu passe en mode tactique. Tu reçois une **main de cartes** tirée de ton pool. Chaque carte a une Force, deux statistiques, un coût en énergie, et une famille. Le système de **matchup** t'indique quelle carte est la meilleure réponse à l'action adverse :

<div class="encadre encadre-info">
<div class="encadre-titre">Matchup</div>
<span class="matchup-fav">▲ Favorable +2</span> — Bonne réponse tactique<br>
<span class="matchup-neu">— Neutre</span> — Ni bon ni mauvais<br>
<span class="matchup-def">▼ Défavorable -2</span> — Mauvais choix tactique
</div>

Tes cartes progressent avec toi. Joue-les souvent pour les **maîtriser** (●●● = +1 Force permanent). Entraîne-toi pour les **améliorer** (versions supérieures).

<div class="scene-break">· · ·</div>

### Ton poste, ton identité

Le poste que tu choisis détermine tes **familles natives** — les types de cartes où tu excelles naturellement (+1 Force). Un attaquant brille en dribble et en tir. Un défenseur domine en duel et en positionnement. Un milieu contrôle la passe et la récupération.

Mais toutes les cartes du pool sont jouables par tous. Ton poste est un avantage, pas une prison.

<div class="scene-break">· · ·</div>

### Quelques conseils

Lis l'action adverse avant de choisir ta carte. Le matchup fait la différence entre un succès et un échec. Gère ton énergie — les cartes puissantes coûtent cher, et tu ne récupères pas en match. Et surtout : les relations comptent. Tes coéquipiers se souviennent de tout.

</div>

[[Commencer →|Prologue_Intro]]


:: Profil_Joueur {"position":"800,1825","size":"100,100"}
## Profil

<div class="encadre encadre-info">
<div class="encadre-titre">Identité</div>
<<if $playerGender is "M">>Joueur<<else>>Joueuse<</if>> · <<print $playerPoste.toUpperCase()>><br>
Réputation : <strong>$reputation</strong> · <<if $titulaire>>Titulaire<<else>>Remplaçant<</if>>
</div>

<div class="profil-grid">
<div class="profil-stat"><div class="profil-stat-label">Technique</div><div class="profil-stat-value">$technique</div></div>
<div class="profil-stat"><div class="profil-stat-label">Physique</div><div class="profil-stat-value">$physique</div></div>
<div class="profil-stat"><div class="profil-stat-label">Vision</div><div class="profil-stat-value">$vision</div></div>
</div>

### Relations
<div class="relations-section">
<div class="relations-section-title">Vestiaire</div>
<div class="relations-grid">
<<for _name, _val range $relations>>
<<relCard _name _val>>
<</for>>
</div>
</div>

### Pool de cartes (<<print $pool.length>> actions)

<div class="encadre encadre-info">
<div class="encadre-titre">Familles natives (+1 Force)</div>
<<for _i to 0; _i < $nativeFamilies.length; _i++>>
<span class="deck-card-badge deck-card-badge-native"><<print window.familyIcon($nativeFamilies[_i])>> <<print $nativeFamilies[_i]>></span>
<</for>>
</div>

<div class="deck-section">
<div class="deck-section-title">Cartes universelles <span class="deck-count">(<<print $pool.length>>)</span></div>
<div class="deck-grid">
<<for _i to 0; _i < $pool.length; _i++>>
<div class="deck-card<<if $nativeFamilies.indexOf($pool[_i].family) !== -1>> deck-card-native<</if>><<if window.getMastery($pool[_i].id) >= 3>> deck-card-mastered<</if>>" data-risk="<<print $pool[_i].risk>>">
<div class="deck-card-head">
<div class="deck-card-family"><<print $pool[_i].family>><<if $nativeFamilies.indexOf($pool[_i].family) !== -1>> ★<</if>></div>
<div class="deck-card-force"><<print $pool[_i].force>></div>
</div>
<div class="deck-card-body">
<div class="deck-card-watermark"><<print window.familyIcon($pool[_i].family)>></div>
<div class="deck-card-name"><<print $pool[_i].name>></div>
<div class="deck-card-stats">
<span class="deck-card-badge deck-card-badge-stat"><<print $pool[_i].stat.substring(0,3).toUpperCase()>></span>
<span class="deck-card-badge deck-card-badge-stat2"><<print $pool[_i].stat2.substring(0,3).toUpperCase()>></span>
<span class="deck-card-badge deck-card-badge-cost">É:<<print $pool[_i].cost>></span>
<span class="deck-card-badge deck-card-badge-phase"><<print $pool[_i].phases.join("·")>></span>
<<if window.getMastery($pool[_i].id) > 0>><span class="deck-card-mastery"><<print window.masteryDots($pool[_i].id)>></span><</if>>
</div>
<div class="deck-card-sep"></div>
<div class="deck-card-desc"><<print $pool[_i].desc>></div>
</div>
</div>
<</for>>
</div>
</div>

<div class="deck-section">
<div class="deck-section-title">Signatures <span class="deck-count">(<<print $signatures.length>>)</span></div>
<div class="deck-grid">
<<for _i to 0; _i < $signatures.length; _i++>>
<div class="deck-card-signature">
<div class="deck-card-head">
<div class="deck-card-family"><<print $signatures[_i].family>></div>
<div class="deck-card-force"><<print $signatures[_i].force>></div>
</div>
<div class="deck-card-body">
<div class="deck-card-watermark"><<print window.familyIcon($signatures[_i].family)>></div>
<div class="deck-card-name"><<print $signatures[_i].name>></div>
<div class="deck-card-stats">
<span class="deck-card-badge deck-card-badge-stat"><<print $signatures[_i].stat.substring(0,3).toUpperCase()>></span>
<span class="deck-card-badge deck-card-badge-stat2"><<print $signatures[_i].stat2.substring(0,3).toUpperCase()>></span>
<span class="deck-card-badge deck-card-badge-cost">É:<<print $signatures[_i].cost>></span>
<span class="deck-card-badge deck-card-badge-phase"><<print $signatures[_i].phases.join("·")>></span>
</div>
<div class="deck-card-sep"></div>
<div class="deck-card-desc"><<print $signatures[_i].desc>></div>
</div>
</div>
<</for>>
</div>
</div>

<<if $_returnPassage>><<link "← Retour">><<run Engine.play(State.variables._returnPassage)>><</link>><<else>><<back "← Retour">><</if>>


:: Prologue_Intro {"position":"1025,25","size":"100,100"}
Le train entre en gare d'Odawara à 7h38, avec deux minutes de retard.

Tu regardes par la vitre. La ville s'étale entre la mer et les collines — des toits bas, des rues étroites, une lumière de début de saison qui blanchit tout. Rien à voir avec ce que tu as quitté. C'est précisément pour ça que tu es là.

Dans ta poche, la lettre de transfert est pliée en quatre. Académie Hojo. Club de football. Les Tigres. Tu en sais assez pour savoir que c'est un nom qui a compté, autrefois. Tu en sais assez pour savoir que la saison dernière s'est mal terminée — une défaite au Football Frontier, une joueuse blessée, un silence qui dure encore.

Max Cerri, l'entraîneur, t'a accepté au téléphone en une phrase : « Viens. On verra sur le terrain. »

Pas de promesse. Pas de place réservée. L'équipe est complète — onze titulaires, un groupe soudé, une alchimie construite sans toi.

Tu es le douzième.

<div class="scene-break">· · ·</div>

Avant d'aller plus loin, quelques choix s'imposent.

[[Définir ton personnage →|Creation_Genre]]


:: SceneFinUpdate {"position":"1425,925","size":"100,100"}
<i>Votre aventure s'arrête ici… pour l’instant. D'autres chapitres attendent encore d’être révélés.</i>
<i>De nouveaux adversaires se préparent. D’autres épreuves t’attendent.</i>
<i>Ton histoire est loin d’être terminée…</i>
<div class="br"></div>
Merci d’avoir joué à cette version du jeu.  
La suite de ton aventure sera disponible dans une prochaine mise à jour.
<div class="br"></div>
*Total mots lus : $wc_total 
*Mots uniques lus : $wc_unique



<<silently>>
Entrée du MC à Hojo en fin d'année
Recherche de l'entraineur

<</silently>>


:: StoryInit {"position":"525,25","size":"100,100"}
/* ═══════════════════════════════════════════════
   CACHE AUDIO — Pré-chargement des musiques
   Fichiers dans /musiques/ à la racine du site.
   ═══════════════════════════════════════════════ */

/* Écran titre */
<<cacheaudio "theme_titre" "musiques/theme_titre.mp3">>

/* Jingles d'interlude */
<<cacheaudio "jingle_acte" "musiques/jingle/nouveau chapitre.mp3">>
<<cacheaudio "jingle_fin" "musiques/jingle/fin_de_demo.mp3">>

/* Ambiances de match */
<<cacheaudio "ambiance_match" "musiques/ambiance_match.mp3">>
<<cacheaudio "ambiance_match_tension" "musiques/ambiance_match_tension.mp3">>

/* Ambiances narratives */
<<cacheaudio "ambiance_entrainement" "musiques/ambiance_entrainement.mp3">>
<<cacheaudio "ambiance_soiree" "musiques/ambiance_soiree.mp3">>
<<cacheaudio "ambiance_calme" "musiques/ambiance_calme.mp3">>
<<cacheaudio "ambiance_tension" "musiques/ambiance_tension.mp3">>

/* ═══════════════════════════════════════════════
   INITIALISATION DES VARIABLES
   ═══════════════════════════════════════════════ */

/* --- Identité du joueur --- */
<<set $playerName to "—">>
<<set $playerGender to "">>
<<set $playerPoste to "">>

/* --- Statistiques de base --- */
<<set $technique to 50>>
<<set $physique to 50>>
<<set $vision to 50>>

/* --- Ressources de match --- */
<<set $energy to 10>>
<<set $energyMax to 10>>
<<set $momentum to 0>>
<<set $lectureDefensive to 0>>
<<set $danger to 0>>

/* --- Progression --- */
<<set $reputation to 0>>
<<set $titulaire to false>>
<<set $acte to 1>>
<<set $semaine to 1>>

/* --- Relations (0–100) --- */
<<set $relations to {
  "Audy": 20,
  "Thomas": 35,
  "Saera": 25,
  "Naela": 30,
  "Mizuki": 15,
  "Nayn": 20,
  "Teo": 25,
  "Max": 30,
  "Lucie": 25,
  "Clément": 20,
  "Sheun": 20,
  "Sandro": 20
}>>

/* --- Drapeaux narratifs --- */
<<set $flags to {
  "voie": "",
  "thomas_confiance": false,
  "sponsor_connu": false,
  "sponsor_parle_saera": false,
  "naela_secret_connu": false,
  "naela_secret_dit_mizuki": false,
  "naela_secret_dit_max": false,
  "naela_secret_garde": false,
  "lettre_emael": false,
  "outei_remarque": false,
  "handa_sponsor": false,
  "match_amical_joue": false,
  "acte1_voie_performance": false,
  "acte1_voie_relations": false
}>>

/* --- Pool de cartes universel --- */
<<set $pool to [
  {id: "tacle", name: "Tacle glissé", force: 6, stat: "physique", stat2: "vision", cost: 2, risk: "Moyen", family: "Duel", phases: ["DEF"], desc: "Récupération engagée. Le timing fait tout. Risque de faute."},
  {id: "duel_aerien", name: "Duel aérien", force: 6, stat: "physique", stat2: "technique", cost: 2, risk: "Moyen", family: "Duel", phases: ["DEF","FINITION"], desc: "Domination dans les airs. +2 sur Corner."},
  {id: "contre_tir", name: "Contre au tir", force: 4, stat: "physique", stat2: "vision", cost: 2, risk: "Élevé", family: "Duel", phases: ["DEF"], desc: "Sacrifice corporel. Dangereux mais héroïque."},
  {id: "couverture", name: "Couverture", force: 7, stat: "vision", stat2: "physique", cost: 1, risk: "Faible", family: "Positionnement", phases: ["DEF"], desc: "Comble l'espace. Réduit le Danger."},
  {id: "marquage", name: "Marquage serré", force: 7, stat: "vision", stat2: "physique", cost: 1, risk: "Faible", family: "Positionnement", phases: ["DEF"], desc: "Colle l'attaquant. Neutralise la menace directe."},
  {id: "degagement", name: "Dégagement", force: 8, stat: "physique", stat2: "technique", cost: 1, risk: "Faible", family: "Urgence", phases: ["DEF"], desc: "Éloigne le danger. Simple mais sûr."},
  {id: "interception", name: "Interception", force: 6, stat: "vision", stat2: "technique", cost: 1, risk: "Moyen", family: "Récupération", phases: ["DEF","TRANS"], desc: "Lecture de la passe adverse. Propre."},
  {id: "pressing", name: "Pressing", force: 5, stat: "physique", stat2: "vision", cost: 2, risk: "Moyen", family: "Récupération", phases: ["DEF","TRANS"], desc: "Récupération haute. Momentum +1 si réussi."},
  {id: "communication", name: "Communication", force: 6, stat: "vision", stat2: "physique", cost: 1, risk: "Faible", family: "Organisation", phases: ["DEF"], desc: "Replace la ligne. Réduit le risque collectif."},
  {id: "protection", name: "Protection de balle", force: 5, stat: "physique", stat2: "technique", cost: 1, risk: "Faible", family: "Conservation", phases: ["DEF","TRANS"], desc: "Temporise sous pression. Protège la possession."},
  {id: "controle", name: "Contrôle orienté", force: 6, stat: "technique", stat2: "physique", cost: 1, risk: "Faible", family: "Conservation", phases: ["TRANS","ATT"], desc: "Premier toucher propre. Oriente le jeu."},
  {id: "passe_courte", name: "Passe courte", force: 7, stat: "technique", stat2: "vision", cost: 0, risk: "Faible", family: "Passe", phases: ["TRANS","ATT"], desc: "Sûre, stabilise le jeu. Circule."},
  {id: "relance", name: "Relance longue", force: 5, stat: "technique", stat2: "vision", cost: 1, risk: "Moyen", family: "Passe", phases: ["TRANS"], desc: "Transition rapide vers l'attaque."},
  {id: "sprint", name: "Sprint", force: 5, stat: "physique", stat2: "technique", cost: 3, risk: "Moyen", family: "Course", phases: ["TRANS","ATT"], desc: "Accélération pure. +2 sur Contre-attaque."},
  {id: "temporisation", name: "Temporisation", force: 7, stat: "vision", stat2: "technique", cost: 0, risk: "Faible", family: "Conservation", phases: ["TRANS","ATT"], desc: "Réduit Lecture défensive. Gère le tempo."},
  {id: "passe_profonde", name: "Passe en profondeur", force: 5, stat: "vision", stat2: "technique", cost: 1, risk: "Moyen", family: "Passe", phases: ["ATT"], desc: "Perce la défense. +2 sur Contre-attaque."},
  {id: "centre", name: "Centre", force: 5, stat: "technique", stat2: "physique", cost: 1, risk: "Moyen", family: "Passe", phases: ["ATT"], desc: "Vers la surface. Crée une situation."},
  {id: "dribble", name: "Dribble", force: 5, stat: "technique", stat2: "physique", cost: 2, risk: "Moyen", family: "Dribble", phases: ["TRANS","ATT"], desc: "Élimine un adversaire. +3 contre Tacle."},
  {id: "feinte", name: "Feinte de corps", force: 4, stat: "technique", stat2: "vision", cost: 2, risk: "Moyen", family: "Dribble", phases: ["ATT","FINITION"], desc: "Lit le défenseur, crée l'espace."},
  {id: "appel", name: "Appel dans le dos", force: 6, stat: "physique", stat2: "vision", cost: 2, risk: "Moyen", family: "Course", phases: ["ATT"], desc: "Perce la ligne. Peut créer un face-à-face."},
  {id: "pivot", name: "Jeu en pivot", force: 6, stat: "physique", stat2: "technique", cost: 1, risk: "Faible", family: "Conservation", phases: ["ATT"], desc: "Dos au but, fixe un défenseur. Ouvre le jeu."},
  {id: "espace", name: "Prise d'espace", force: 5, stat: "vision", stat2: "physique", cost: 1, risk: "Faible", family: "Course", phases: ["ATT"], desc: "Décrochage intelligent. Crée une option."},
  {id: "tir_place", name: "Tir placé", force: 6, stat: "technique", stat2: "vision", cost: 1, risk: "Moyen", family: "Tir", phases: ["FINITION"], desc: "Précision chirurgicale. +2 en 1v1 gardien."},
  {id: "tir_puissant", name: "Tir puissant", force: 7, stat: "physique", stat2: "technique", cost: 2, risk: "Élevé", family: "Tir", phases: ["FINITION"], desc: "Frappe lourde. -2 si surface encombrée."},
  {id: "tete", name: "Tête", force: 5, stat: "physique", stat2: "vision", cost: 1, risk: "Moyen", family: "Tir", phases: ["FINITION"], desc: "Jeu aérien. +2 sur Corner ou Centre."},
  {id: "frappe_loin", name: "Frappe de loin", force: 4, stat: "physique", stat2: "technique", cost: 2, risk: "Élevé", family: "Tir", phases: ["ATT","FINITION"], desc: "Tente sa chance de loin. Danger +2 si cadré."}
]>>
<<set $signatures to []>>
<<set $nativeFamilies to []>>
<<set $lastFamily to "">>
<<set $lastCardId to "">>

/* --- Maîtrise des cartes (id → 0-3) --- */
<<set $mastery to {}>>

/* --- Upgrades disponibles (catalogue) --- */
<<set $upgrades to {
  "tir_place":    {id: "tir_chirurgical", name: "Tir chirurgical", force: 7, stat: "technique", stat2: "vision", cost: 1, risk: "Moyen", family: "Tir", phases: ["FINITION"], desc: "Frappe millimétrée. +2 en 1v1 gardien. Précision létale."},
  "pressing":     {id: "pressing_coord", name: "Pressing coordonné", force: 5, stat: "physique", stat2: "vision", cost: 2, risk: "Moyen", family: "Récupération", phases: ["DEF","TRANS","ATT"], desc: "Pressing collectif. Momentum +1 si réussi. Couvre plus de phases."},
  "interception": {id: "lecture_anti", name: "Lecture anticipée", force: 7, stat: "vision", stat2: "technique", cost: 1, risk: "Faible", family: "Récupération", phases: ["DEF","TRANS","ATT"], desc: "Tu lis le jeu avant la passe. Coupe tout."},
  "dribble":      {id: "crochet_int", name: "Crochet intérieur", force: 6, stat: "technique", stat2: "physique", cost: 2, risk: "Moyen", family: "Dribble", phases: ["TRANS","ATT"], desc: "Geste signature. +3 contre Tacle. Élimine proprement."},
  "passe_courte": {id: "passe_laser", name: "Passe laser", force: 8, stat: "technique", stat2: "vision", cost: 0, risk: "Faible", family: "Passe", phases: ["TRANS","ATT"], desc: "Précision absolue. Stabilise et oriente."},
  "tacle":        {id: "tacle_parfait", name: "Tacle parfait", force: 7, stat: "physique", stat2: "vision", cost: 2, risk: "Faible", family: "Duel", phases: ["DEF"], desc: "Timing impeccable. Récupération nette, jamais de faute."},
  "sprint":       {id: "acceleration", name: "Accélération explosive", force: 6, stat: "physique", stat2: "technique", cost: 3, risk: "Moyen", family: "Course", phases: ["TRANS","ATT"], desc: "Démarrage dévastateur. +2 sur Contre-attaque. Inarrêtable."},
  "controle":     {id: "aile_de_pigeon", name: "Aile de pigeon", force: 7, stat: "technique", stat2: "physique", cost: 1, risk: "Faible", family: "Conservation", phases: ["TRANS","ATT"], desc: "Contrôle de génie. Élimine la pression en un touche."}
}>>
/* --- État du match en cours --- */
<<set $matchScore to [0, 0]>>
<<set $matchMinute to 0>>
<<set $matchAdversaire to "">>
<<set $matchMoment to 0>>
<<set $upgradeChoice to "">>
<<set $enemyAction to "">>
<<set $matchPhase to "">>
<<set $genHand to []>>
<<set $genFlavor to "">>
<<set $matchMaxMoments to 5>>
<<set $nextPassage to "">>
<<set $matchScripted to []>>
<<set $matchEndPassage to "">>


:: TransitionSceneFin {"position":"1675,800","size":"100,100"}
<<run window.playInterlude("Fin de la démo...", "", "jingle_acte1", "SceneFinUpdate")>>


:: StoryScript [script]
/* ═══════════════════════════════════════════════
   HOJO TIGERS — MOTEUR DE JEU (SugarCube 2)
   ═══════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════
   CONFIGURATION SUGARCUBE
   ═══════════════════════════════════════════════ */
Config.saves.autosave = function() {
  var ignoredPassages = ['Ecran_Titre', 'Menu_Sauvegarde', 'Profil_Joueur', 'Changelog', 'StoryInit', 'Interlude_Acte1', 'Interlude_Acte2'];
  var passage = State.passage || '';
  
  if (ignoredPassages.indexOf(passage) !== -1) return false;
  
  var currentTags = tags() || [];
  if (currentTags.indexOf('nosave') !== -1) return false;
  
  return true;
};

/* ═══════════════════════════════════════════════
   API SAUVEGARDE EN LIGNE
   ═══════════════════════════════════════════════ */
window.HojoAPI = {
  baseUrl: 'https://vilamonte.fr/api',  // URL de l'API
  token: null,
  user: null,

  init: function() {
    this.token = localStorage.getItem('hojo_token');
    var userData = localStorage.getItem('hojo_user');
    if (userData) {
      try { this.user = JSON.parse(userData); } catch(e) { this.user = null; }
    }
  },

  isLoggedIn: function() {
    return this.token !== null && this.user !== null;
  },

  async request(endpoint, method, data) {
    method = method || 'GET';
    var url = this.baseUrl + '/' + endpoint;
    var options = {
      method: method,
      headers: { 'Content-Type': 'application/json' },
      credentials: 'include'
    };
    if (this.token) {
      options.headers['Authorization'] = 'Bearer ' + this.token;
    }
    if (data && (method === 'POST' || method === 'PUT')) {
      options.body = JSON.stringify(data);
    }
    var response = await fetch(url, options);
    var result = await response.json();
    if (!result.success) {
      throw new Error(result.error || 'Erreur inconnue');
    }
    return result;
  },

  async register(email, username, password) {
    var result = await this.request('register.php', 'POST', {
      email: email, username: username, password: password
    });
    this.token = result.token;
    this.user = result.user;
    localStorage.setItem('hojo_token', this.token);
    localStorage.setItem('hojo_user', JSON.stringify(this.user));
    return result;
  },

  async login(login, password) {
    var result = await this.request('login.php', 'POST', {
      login: login, password: password
    });
    this.token = result.token;
    this.user = result.user;
    localStorage.setItem('hojo_token', this.token);
    localStorage.setItem('hojo_user', JSON.stringify(this.user));
    return result;
  },

  logout: function() {
    this.token = null;
    this.user = null;
    localStorage.removeItem('hojo_token');
    localStorage.removeItem('hojo_user');
  },

  async saveGame(slotName, chapter) {
    if (!this.isLoggedIn()) throw new Error('Connexion requise');
    var gameState = clone(State.variables);
    var playtime = State.variables.playtime || 0;
    return await this.request('save.php', 'POST', {
      slot_name: slotName,
      game_state: gameState,
      chapter: chapter || State.variables.currentChapter || State.passage,
      playtime_seconds: playtime
    });
  },

  async loadGame(slotName) {
    if (!this.isLoggedIn()) throw new Error('Connexion requise');
    var result = await this.request('load.php?slot=' + encodeURIComponent(slotName));
    var savedState = result.save.game_state;
    Object.keys(State.variables).forEach(function(key) {
      delete State.variables[key];
    });
    Object.assign(State.variables, savedState);
    return result;
  },

  async listSaves() {
    if (!this.isLoggedIn()) throw new Error('Connexion requise');
    return await this.request('list-saves.php');
  },

  async deleteSave(slotName) {
    if (!this.isLoggedIn()) throw new Error('Connexion requise');
    return await this.request('delete-save.php?slot=' + encodeURIComponent(slotName), 'DELETE');
  }
};

/* Initialiser l'API au chargement */
$(document).one(':storyready', function() {
  HojoAPI.init();
});

/* Sauvegarde en ligne automatique (en plus de l'autosave local SugarCube) */
$(document).on(':passageend', function() {
  /* Même règles que Config.saves.autosave */
  var ignoredPassages = ['Ecran_Titre', 'Menu_Sauvegarde', 'Profil_Joueur', 'Changelog', 'StoryInit', 'Interlude_Acte1', 'Interlude_Acte2'];
  var passage = State.passage || '';
  
  if (ignoredPassages.indexOf(passage) !== -1) return;
  
  var currentTags = tags() || [];
  if (currentTags.indexOf('nosave') !== -1) return;
  
  /* Sauvegarde en ligne (si connecté) */
  if (HojoAPI.isLoggedIn()) {
    HojoAPI.saveGame('Sauvegarde auto', passage).catch(function(e) {
      console.log('Autosave cloud failed:', e.message);
    });
  }
});

/* --- Supprimer la barre d'interface SugarCube --- */
$(document).one(':storyready', function() {
  /* Méthode officielle SugarCube : cacher + verrouiller la sidebar */
  if (typeof UIBar !== 'undefined') {
    UIBar.destroy();
  }

  /* Nettoyage supplémentaire : retirer les éléments résiduels */
  ['ui-bar','ui-bar-toggle','ui-bar-body','menu-story','menu-core','story-caption','story-banner'].forEach(function(id) {
    var el = document.getElementById(id);
    if (el) el.remove();
  });

  /* Supprimer le padding-left que SugarCube ajoute au body pour la sidebar */
  document.documentElement.style.marginLeft = '0';
  document.body.style.marginLeft = '0';
  var story = document.getElementById('story');
  if (story) story.style.marginLeft = 'auto';
});

/* --- Calibration des lignes du cahier ---
   Mesure la vraie position de la baseline du texte
   et ajuste background-position de #story pour
   que les traits du cahier tombent pile dessous. */
(function() {
  var CSS_LINE_POS = 19; /* position de la ligne dans le gradient CSS (px) */
  var LINE_GAP = 31;

  function measureBaseline() {
    /* Créer un conteneur mono-ligne avec la même typo */
    var probe = document.createElement('div');
    probe.style.cssText = 'position:absolute;left:-9999px;top:0;' +
      'font:17px/' + LINE_GAP + 'px Lora,Georgia,serif;white-space:nowrap;';
    /* Un span inline-block de hauteur 0, aligné baseline :
       son bord haut TOUCHE la baseline. */
    probe.innerHTML = 'Hg\u200B<span style="display:inline-block;width:0;height:0;vertical-align:baseline;"></span>';
    document.body.appendChild(probe);
    var blSpan = probe.querySelector('span');
    var baselineY = blSpan.getBoundingClientRect().top - probe.getBoundingClientRect().top;
    document.body.removeChild(probe);
    return Math.round(baselineY);
  }

  function calibrate() {
    var story = document.getElementById('story');
    if (!story) return;
    var baseline = measureBaseline();
    var padTop = parseInt(window.getComputedStyle(story).paddingTop) || 31;
    /* Décalage = padding-top + (baseline réelle − position de la ligne CSS) */
    var offset = padTop + (baseline - CSS_LINE_POS);
    story.style.backgroundPosition = '0 ' + offset + 'px';
  }

  /* Calibrer après chargement des polices */
  if (document.fonts && document.fonts.ready) {
    document.fonts.ready.then(function() { setTimeout(calibrate, 30); });
  } else {
    $(window).on('load', calibrate);
  }

  /* Re-calibrer à chaque passage (le padding peut changer) */
  $(document).on(':passagerender', function() {
    setTimeout(calibrate, 20);
  });
})();

/* --- Système de notification --- */
window.notify = function(msg, duration) {
  duration = duration || 2500;
  var el = document.getElementById('game-notif');
  if (!el) {
    el = document.createElement('div');
    el.id = 'game-notif';
    el.className = 'notif';
    document.body.appendChild(el);
  }
  el.textContent = msg;
  el.classList.add('show');
  setTimeout(function() { el.classList.remove('show'); }, duration);
};

/* --- Widget : Fiche relation --- */
Macro.add('relCard', {
  handler: function() {
    var name = this.args[0];
    var val = this.args[1] || 0;
    var role = window.relRole(name);
    var status = window.relStatus(val);
    var label = window.relStatusLabel(val);

    var html = '<div class="rel-card" data-status="' + status + '">' +
      '<div class="rel-card-header">' +
        '<span class="rel-card-role" data-pos="' + role.tag + '">' + role.tag + '</span>' +
        '<span class="rel-card-name">' + name + '</span>' +
      '</div>' +
      '<div class="rel-gauge-container">' +
        '<div class="rel-gauge"><div class="rel-gauge-fill" data-status="' + status + '" style="width:' + val + '%"></div></div>' +
        '<span class="rel-value">' + val + '</span>' +
      '</div>' +
      '<span class="rel-status" data-status="' + status + '">' + label + '</span>' +
    '</div>';

    $(this.output).wiki(html);
  }
});

/* --- Widget : Jauge d'énergie HTML --- */
Macro.add('energyGauge', {
  handler: function() {
    var max = State.variables.energyMax || 10;
    var cur = State.variables.energy || 0;
    var html = '<span class="gauge">';
    for (var i = 0; i < max; i++) {
      if (i < cur) {
        html += '<span class="gauge-pip ' + (cur <= 3 ? 'danger' : 'filled') + '"></span>';
      } else {
        html += '<span class="gauge-pip"></span>';
      }
    }
    html += '</span>';
    $(this.output).wiki(html);
  }
});

/* --- Widget : Jauge de momentum HTML --- */
Macro.add('momentumDisplay', {
  handler: function() {
    var m = State.variables.momentum || 0;
    var cls = m > 0 ? 'hud-momentum-pos' : (m < 0 ? 'hud-momentum-neg' : 'hud-momentum-zero');
    var sign = m > 0 ? '+' : '';
    $(this.output).wiki('<span class="' + cls + '">' + sign + m + '</span>');
  }
});

/* --- Fonction : Résolution d'action de match --- */
window.resolveAction = function(cardForce, stat1Name, stat2Name, family, cardId, momentumBonus, situationBonus, readPenalty, energyCost) {
  var sv = State.variables;
  var s1 = sv[stat1Name] || 50;
  var s2 = sv[stat2Name] || 50;
  var dualScore = Math.floor((s1 * 2 + s2) / 30);
  var native = (sv.nativeFamilies.indexOf(family) !== -1) ? 1 : 0;
  var mastered = window.masteryBonus(cardId);
  var matchup = window.getMatchup(cardId);
  var score = cardForce + native + mastered + matchup + dualScore + momentumBonus + situationBonus - readPenalty;
  sv.energy = Math.max(0, sv.energy - energyCost);

  /* Tirage aléatoire pondéré */
  var roll = Math.floor(Math.random() * 20) + 1;
  var total = score + roll;

  if (total >= 22) return 'critique';
  if (total >= 16) return 'succes';
  if (total >= 11) return 'mitige';
  if (total >= 6)  return 'echec';
  return 'critique_echec';
};

/* --- Helpers pour les relations --- */
window.relStatus = function(val) {
  if (val >= 80) return 'lien';
  if (val >= 65) return 'allié';
  if (val >= 50) return 'confiance';
  if (val >= 35) return 'cordial';
  if (val >= 20) return 'neutre';
  if (val >= 10) return 'froid';
  return 'hostile';
};

window.relStatusLabel = function(val) {
  if (val >= 80) return 'Lien fort';
  if (val >= 65) return 'Allié';
  if (val >= 50) return 'Confiance';
  if (val >= 35) return 'Cordial';
  if (val >= 20) return 'Neutre';
  if (val >= 10) return 'Froid';
  return 'Hostile';
};

window.relRole = function(name) {
  var roles = {
    'Audy':    { tag: 'ATT', full: 'Capitaine' },
    'Thomas':  { tag: 'MIL', full: 'Récupérateur' },
    'Saera':   { tag: 'ATT', full: 'Meneuse' },
    'Naela':   { tag: 'ATT', full: 'Attaquante' },
    'Mizuki':  { tag: 'MIL', full: 'Ailière' },
    'Nayn':    { tag: 'MIL', full: 'Box-to-box' },
    'Teo':     { tag: 'GAR', full: 'Gardien' },
    'Max':     { tag: 'COA', full: 'Coach' },
    'Lucie':   { tag: 'DEF', full: 'Latérale' },
    'Clément': { tag: 'MIL', full: 'Organisateur' },
    'Sheun':   { tag: 'DEF', full: 'Latéral' },
    'Sandro':  { tag: 'DEF', full: 'Central' }
  };
  return roles[name] || { tag: 'EQU', full: 'Équipier' };
};

/* --- Icône de famille pour les cartes --- */
window.familyIcon = function(family) {
  var icons = {
    'Arrêt':          '🧤',
    'Sortie':         '↗',
    'Posture':        '👁',
    'Relance':        '↑',
    'Communication':  '📣',
    'Organisation':   '📋',
    'Duel':           '⚔',
    'Positionnement': '🛡',
    'Urgence':        '⚡',
    'Récupération':   '↻',
    'Conservation':   '🛡',
    'Passe':          '➜',
    'Tir':            '◎',
    'Dribble':        '⚡',
    'Course':         '💨',
    'Défense':        '🛡',
    'Signature':      '★'
  };
  return icons[family] || '◆';
};

/* --- Fonction : Carte du pool par ID --- */
window.getCard = function(id) {
  var pool = State.variables.pool;
  for (var i = 0; i < pool.length; i++) {
    if (pool[i].id === id) return pool[i];
  }
  return null;
};

/* --- Fonction : La famille est-elle native au poste ? --- */
window.isNative = function(family) {
  var natives = State.variables.nativeFamilies;
  return natives.indexOf(family) !== -1;
};

/* --- Fonction : Score de stat dual --- */
window.dualStatScore = function(card) {
  var v = State.variables;
  var s1 = v[card.stat] || 50;
  var s2 = v[card.stat2] || 50;
  return Math.floor((s1 * 2 + s2) / 30);
};

/* --- Fonction : Maîtrise d'une carte (0-3) --- */
window.getMastery = function(cardId) {
  var m = State.variables.mastery;
  return m[cardId] || 0;
};

/* --- Fonction : Incrémenter la maîtrise (max 3) --- */
window.addMastery = function(cardId) {
  var m = State.variables.mastery;
  var cur = m[cardId] || 0;
  if (cur < 3) {
    m[cardId] = cur + 1;
    if (cur + 1 === 3) {
      window.notify('★ ' + cardId + ' maîtrisée ! (+1 Force)');
    }
  }
};

/* --- Fonction : Bonus de maîtrise (0 ou 1) --- */
window.masteryBonus = function(cardId) {
  return (window.getMastery(cardId) >= 3) ? 1 : 0;
};

/* --- Fonction : Force totale effective (base + natif + maîtrise) --- */
window.effectiveForce = function(card) {
  var native = window.isNative(card.family) ? 1 : 0;
  var mastered = window.masteryBonus(card.id) || 0;
  return card.force + native + mastered;
};

/* --- Fonction : Affichage maîtrise (●●○) --- */
window.masteryDots = function(cardId) {
  var m = window.getMastery(cardId);
  var dots = '';
  for (var i = 0; i < 3; i++) {
    dots += (i < m) ? '●' : '○';
  }
  return dots;
};

/* --- Fonction : Appliquer un upgrade à une carte du pool --- */
window.upgradeCard = function(baseId) {
  var sv = State.variables;
  var upg = sv.upgrades[baseId];
  if (!upg) return false;
  for (var i = 0; i < sv.pool.length; i++) {
    if (sv.pool[i].id === baseId) {
      sv.pool[i] = clone(upg);
      /* Transférer la maîtrise */
      var oldMastery = sv.mastery[baseId] || 0;
      if (oldMastery > 0) sv.mastery[upg.id] = oldMastery;
      delete sv.mastery[baseId];
      return true;
    }
  }
  return false;
};

/* ═══════════════════════════════════════════════
   SYSTÈME DE MATCHUP
   ═══════════════════════════════════════════════ */

/* Tables de matchup : action adverse → { favorable: [...ids], défavorable: [...ids] }
   Tout ce qui n'est ni favorable ni défavorable = neutre (0) */

window.matchupDEF = {
  'dribble':    { fav: ['tacle','marquage','duel_aerien'], def: ['interception','pressing','communication'] },
  'passe':      { fav: ['interception','communication','pressing'], def: ['tacle','couverture','degagement'] },
  'tir':        { fav: ['contre_tir','couverture','duel_aerien'], def: ['pressing','marquage'] },
  'temporise':  { fav: ['pressing','protection'], def: ['couverture','degagement'] }
};

window.matchupATT = {
  'tacle':   { fav: ['dribble','feinte','sprint'], def: ['controle','temporisation','pivot'] },
  'couvre':  { fav: ['passe_courte','centre','passe_profonde','relance'], def: ['dribble','sprint','appel'] },
  'presse':  { fav: ['sprint','passe_profonde','appel','relance'], def: ['tir_place','tir_puissant','controle','temporisation'] },
  'bloque':  { fav: ['tir_puissant','frappe_loin','tir_place'], def: ['appel','espace','pivot'] }
};

window.matchupFIN = {
  'sort':    { fav: ['feinte','tete','frappe_loin'], def: ['tir_puissant'] },
  'attend':  { fav: ['tir_place','tir_puissant'], def: ['feinte'] },
  'couvre':  { fav: ['duel_aerien','frappe_loin','tir_place'], def: ['appel','espace'] }
};

/* Fonction : obtenir le bonus de matchup pour une carte */
window.getMatchup = function(cardId) {
  var sv = State.variables;
  var action = sv.enemyAction || '';
  var phase = sv.matchPhase || 'DEF';
  var table;

  if (phase === 'DEF') table = window.matchupDEF;
  else if (phase === 'FINITION' || phase === 'FIN') table = window.matchupFIN;
  else table = window.matchupATT;

  var entry = table[action];
  if (!entry) return 0;
  if (entry.fav.indexOf(cardId) !== -1) return 2;
  if (entry.def.indexOf(cardId) !== -1) return -2;
  return 0;
};

/* Fonction : label du matchup */
window.matchupLabel = function(cardId) {
  var m = window.getMatchup(cardId);
  if (m > 0) return '<span class="matchup-fav">▲ Favorable +2</span>';
  if (m < 0) return '<span class="matchup-def">▼ Défavorable -2</span>';
  return '<span class="matchup-neu">— Neutre</span>';
};

/* Fonction : label de l'action adverse */
window.enemyActionLabel = function(action) {
  var labels = {
    'dribble': '🏃 Dribble',
    'passe': '➜ Passe',
    'tir': '◎ Tir',
    'temporise': '⏳ Temporise',
    'tacle': '⚔ Tacle',
    'couvre': '🛡 Couverture',
    'presse': '💨 Pressing',
    'bloque': '✋ Bloc',
    'sort': '↗ Sortie gardien',
    'attend': '👁 Gardien attend',
  };
  return labels[action] || action;
};

/* --- Fonction : Modifier une relation --- */
window.modRelation = function(name, delta) {
  var rel = State.variables.relations;
  if (rel[name] !== undefined) {
    rel[name] = Math.max(0, Math.min(100, rel[name] + delta));
    var verb = delta > 0 ? '▲' : '▼';
    notify(name + ' ' + verb + ' ' + Math.abs(delta));
  }
};

/* ═══════════════════════════════════════════════
   MOTEUR DE MATCH SEMI-ALÉATOIRE
   ═══════════════════════════════════════════════ */

window.matchEngine = {

  /* --- Tables de probabilité de phase par poste ---
     Modifiées dynamiquement selon le score */
  phaseWeights: {
    'attaquant':  { DEF: 10, TRANS: 20, ATT: 45, FINITION: 25 },
    'milieu':     { DEF: 20, TRANS: 30, ATT: 35, FINITION: 15 },
    'défenseur':  { DEF: 40, TRANS: 30, ATT: 20, FINITION: 10 },
    'gardien':    { DEF: 60, TRANS: 20, ATT: 10, FINITION: 10 }
  },

  /* --- Actions adverses par phase --- */
  enemyActions: {
    'DEF':      ['dribble', 'passe', 'tir', 'temporise'],
    'TRANS':    ['presse', 'tacle', 'couvre'],
    'ATT':      ['tacle', 'couvre', 'presse', 'bloque'],
    'FINITION': ['sort', 'attend', 'couvre']
  },

  /* --- Textes de contexte : [phase][poste] → tableau de variantes --- */
  flavorTexts: {
    DEF: {
      'attaquant': [
        "Odawara relance vite. Tu replonges pour aider — le ballon arrive dans ta zone.",
        "Perte de balle. L'adversaire contre — tu es le premier sur la trajectoire.",
        "Leur milieu lance une longue transversale. Tu te retrouves en position défensive."
      ],
      'milieu': [
        "Le milieu adverse porte le ballon. Tu es face à lui, il faut couper.",
        "Odawara circule vite. Le ballon arrive dans ta zone — à toi de récupérer.",
        "Transition adverse rapide. Tu es le dernier verrou au milieu."
      ],
      'défenseur': [
        "Leur attaquant reçoit entre les lignes. Tu es le dernier rideau.",
        "Contre-attaque rapide. L'adversaire fonce vers ton côté.",
        "Centre en retrait — l'attaquant contrôle face à toi. Duel."
      ],
      'gardien': [
        "Frappe de l'extérieur de la surface. Le ballon arrive vite.",
        "Tête plongeante sur corner. Tu dois réagir."
      ]
    },
    TRANS: {
      'attaquant': [
        "Thomas récupère et cherche la transition. Tu te démarques.",
        "Récupération au milieu — le jeu s'ouvre devant toi.",
        "Le ballon repart vers l'avant. Tu appelles dans le couloir."
      ],
      'milieu': [
        "Interception de Clément — il te remet. C'est toi qui orientes.",
        "Récupération basse. Le jeu est devant toi, tout est à construire.",
        "Le ballon arrive. Deux options devant, pression derrière."
      ],
      'défenseur': [
        "Tu récupères proprement et tu lèves la tête. Relance.",
        "Interception nette. Tu as le ballon — il faut lancer la transition.",
        "Dégagement de Teo, tu contrôles. L'équipe remonte."
      ],
      'gardien': [
        "Relance au pied. Le pressing adverse monte sur toi."
      ]
    },
    ATT: {
      'attaquant': [
        "Le ballon arrive dans ta zone. Défenseur face à toi.",
        "Saera te trouve d'une passe en retrait. Tu es à trente mètres.",
        "Nayn décale vers toi. L'espace est étroit mais il existe."
      ],
      'milieu': [
        "Tu reçois entre les lignes. L'espace se ferme vite.",
        "Passe de Thomas — tu es face au bloc adverse. Il faut créer.",
        "Le ballon te cherche. Deux adversaires convergent."
      ],
      'défenseur': [
        "Montée offensive. Tu te retrouves en surnombre devant.",
        "Corner pour Hojo — tu montes. Le ballon revient vers toi.",
        "Tu as suivi l'action jusqu'en zone adverse. Le ballon t'arrive."
      ],
      'gardien': [
        "Relance longue — personne ne s'y attend. L'attaque est lancée."
      ]
    },
    FINITION: {
      'attaquant': [
        "Tu es face au gardien. C'est maintenant.",
        "Le ballon rebondit dans la surface. Tu es le mieux placé.",
        "Centre parfait de Mizuki — tu es à six mètres."
      ],
      'milieu': [
        "L'action t'a porté jusqu'à la surface. Tu es en position de frappe.",
        "Déviation dans la surface — le ballon arrive sur toi.",
        "Débordement de Mizuki, centre en retrait — tu arrives lancé."
      ],
      'défenseur': [
        "Corner pour Hojo. Tu montes — tu es grand, tu sautes bien.",
        "Le ballon traîne dans la surface après un cafouillage. Tu es là.",
        "Coup franc. Tu es au deuxième poteau."
      ],
      'gardien': [
        "Dernière minute. Tu montes sur corner. Tout le monde te regarde."
      ]
    }
  },

  /* --- Textes de résolution génériques --- */
  resolutionTexts: {
    succes: {
      DEF: [
        "Récupération nette. Le ballon est à Hojo.",
        "Tu coupes l'action. L'adversaire est stoppé. Propre.",
        "Le geste est parfait. L'équipe reprend le contrôle."
      ],
      ATT: [
        "Le défenseur est battu. L'action continue vers l'avant.",
        "Tu débouches dans l'espace. L'équipe avance.",
        "Le geste fait la différence. L'action se prolonge."
      ],
      TRANS: [
        "La transition est lancée. Le ballon file vers l'avant.",
        "Tu orientes le jeu parfaitement. L'équipe accélère.",
        "Relance propre. Hojo pousse."
      ],
      FINITION: [
        "Le filet tremble. BUT.",
        "Le gardien est battu. Le gradin se lève.",
        "Au fond. Le ballon franchit la ligne."
      ]
    },
    mitige: {
      DEF: [
        "Le geste est à moitié — l'adversaire perd le ballon mais la récupération n'est pas nette.",
        "Tu ralentis l'action sans la couper. L'équipe se replace."
      ],
      ATT: [
        "Le geste crée du danger mais ne débouche pas. Proche.",
        "Tu forces une situation — pas idéale, mais le mouvement est là."
      ],
      TRANS: [
        "La relance est imprécise mais un coéquipier récupère.",
        "Ça passe, mais de justesse. Le rythme est cassé."
      ],
      FINITION: [
        "Le tir est cadré — le gardien repousse. Corner.",
        "La frappe est déviée. Presque."
      ]
    },
    echec: {
      DEF: [
        "Tu es battu. L'adversaire passe. Heureusement, la couverture tient.",
        "Le geste arrive trop tard. L'action adverse continue."
      ],
      ATT: [
        "Perte de balle. L'adversaire récupère et relance.",
        "Le geste est lu. Pas de danger créé. L'action meurt."
      ],
      TRANS: [
        "La passe est interceptée. Transition ratée.",
        "Tu perds le ballon sous la pression. Récupération adverse."
      ],
      FINITION: [
        "Le tir part à côté. Occasion gaspillée.",
        "Le gardien capte sans trembler. Relance adverse."
      ]
    }
  },

  /* === FONCTIONS PRINCIPALES === */

  /* Tirage pondéré dans un objet {clé: poids} */
  weightedPick: function(weights) {
    var total = 0;
    var keys = Object.keys(weights);
    for (var i = 0; i < keys.length; i++) total += weights[keys[i]];
    var r = Math.random() * total;
    var acc = 0;
    for (var i = 0; i < keys.length; i++) {
      acc += weights[keys[i]];
      if (r <= acc) return keys[i];
    }
    return keys[keys.length - 1];
  },

  /* Ajuste les poids de phase selon le score */
  adjustedPhaseWeights: function() {
    var sv = State.variables;
    var base = clone(this.phaseWeights[sv.playerPoste] || this.phaseWeights['milieu']);
    var diff = sv.matchScore[0] - sv.matchScore[1];

    /* Si on est menés → plus de DEF */
    if (diff < 0) {
      base.DEF += 15;
      base.ATT -= 10;
      base.FINITION -= 5;
    }
    /* Si on domine → plus d'ATT */
    if (diff > 0) {
      base.ATT += 10;
      base.FINITION += 5;
      base.DEF -= 10;
    }
    /* Fin de match → plus de FINITION et DEF */
    if (sv.matchMinute >= 80) {
      base.FINITION += 10;
      base.DEF += 5;
    }
    /* Momentum haut → plus d'ATT */
    if (sv.momentum >= 2) {
      base.ATT += 10;
      base.FINITION += 5;
    }

    /* Plancher à 5 pour chaque */
    var keys = Object.keys(base);
    for (var i = 0; i < keys.length; i++) {
      if (base[keys[i]] < 5) base[keys[i]] = 5;
    }
    return base;
  },

  /* Pioche aléatoire dans un tableau */
  randomFrom: function(arr) {
    return arr[Math.floor(Math.random() * arr.length)];
  },

  /* Filtre les cartes du pool par phase */
  filterByPhase: function(phase) {
    var sv = State.variables;
    var filtered = [];
    for (var i = 0; i < sv.pool.length; i++) {
      if (sv.pool[i].phases.indexOf(phase) !== -1) {
        filtered.push(sv.pool[i]);
      }
    }
    return filtered;
  },

  /* Sélectionne la main : 1-2 contextuelles + 2-3 aléatoires = 4 cartes */
  selectHand: function(phase, enemyAction) {
    var available = this.filterByPhase(phase);
    var hand = [];
    var usedIds = {};

    /* 1. Piocher 1 carte favorable (si possible) */
    var favIds = this.getFavorableIds(phase, enemyAction);
    var shuffled = available.slice().sort(function() { return Math.random() - 0.5; });
    for (var i = 0; i < shuffled.length; i++) {
      if (favIds.indexOf(shuffled[i].id) !== -1 && !usedIds[shuffled[i].id]) {
        hand.push(shuffled[i]);
        usedIds[shuffled[i].id] = true;
        break;
      }
    }

    /* 2. Piocher 1 carte défavorable (pour le choix tactique) */
    var defIds = this.getUnfavorableIds(phase, enemyAction);
    for (var i = 0; i < shuffled.length; i++) {
      if (defIds.indexOf(shuffled[i].id) !== -1 && !usedIds[shuffled[i].id]) {
        hand.push(shuffled[i]);
        usedIds[shuffled[i].id] = true;
        break;
      }
    }

    /* 3. Compléter avec des cartes aléatoires pour atteindre 4 */
    for (var i = 0; i < shuffled.length && hand.length < 4; i++) {
      if (!usedIds[shuffled[i].id]) {
        hand.push(shuffled[i]);
        usedIds[shuffled[i].id] = true;
      }
    }

    /* Mélanger la main finale */
    hand.sort(function() { return Math.random() - 0.5; });
    return hand;
  },

  /* Récupère les IDs favorables pour une phase/action */
  getFavorableIds: function(phase, action) {
    var table;
    if (phase === 'DEF') table = window.matchupDEF;
    else if (phase === 'FINITION') table = window.matchupFIN;
    else table = window.matchupATT;
    var entry = table[action];
    return entry ? entry.fav : [];
  },

  /* Récupère les IDs défavorables pour une phase/action */
  getUnfavorableIds: function(phase, action) {
    var table;
    if (phase === 'DEF') table = window.matchupDEF;
    else if (phase === 'FINITION') table = window.matchupFIN;
    else table = window.matchupATT;
    var entry = table[action];
    return entry ? entry.def : [];
  },

  /* === GÉNÉRATION D'UN MOMENT COMPLET === */
  generate: function() {
    var sv = State.variables;

    /* Phase */
    var weights = this.adjustedPhaseWeights();
    var phase = this.weightedPick(weights);

    /* Action adverse */
    var actions = this.enemyActions[phase] || this.enemyActions['ATT'];
    var enemy = this.randomFrom(actions);

    /* Texte de contexte */
    var poste = sv.playerPoste || 'milieu';
    var texts = this.flavorTexts[phase] && this.flavorTexts[phase][poste];
    var flavor = texts ? this.randomFrom(texts) : "Le ballon arrive.";

    /* Main de cartes */
    var hand = this.selectHand(phase, enemy);

    /* Avancer la minute */
    sv.matchMinute += Math.floor(Math.random() * 8) + 4;
    if (sv.matchMinute > 90) sv.matchMinute = 90;

    /* Stocker le moment généré */
    sv.matchPhase = phase;
    sv.enemyAction = enemy;
    sv.genHand = hand;
    sv.genFlavor = flavor;

    return { phase: phase, enemy: enemy, hand: hand, flavor: flavor };
  },

  /* === RÉSOLUTION GÉNÉRIQUE D'UNE CARTE === */
  resolve: function(cardId) {
    var sv = State.variables;
    var card = window.getCard(cardId);
    if (!card) return { result: 'echec', text: 'Carte introuvable.' };

    /* Calcul */
    var s1 = sv[card.stat] || 50;
    var s2 = sv[card.stat2] || 50;
    var dualScore = Math.floor((s1 * 2 + s2) / 30);
    var native = window.isNative(card.family) ? 1 : 0;
    var mastered = window.masteryBonus(card.id);
    var matchup = window.getMatchup(card.id);
    var base = card.force + native + mastered + matchup + dualScore + sv.momentum;

    /* Coût énergie */
    sv.energy = Math.max(0, sv.energy - card.cost);

    /* Pénalité énergie basse */
    var penalty = 0;
    if (sv.energy <= 2) penalty = 2;
    else if (sv.energy <= 4) penalty = 1;
    base -= penalty;

    /* Jet */
    var roll = Math.floor(Math.random() * 20) + 1;
    var total = base + roll;

    /* Seuils adaptés par phase */
    var result;
    if (sv.matchPhase === 'FINITION') {
      if (total >= 20) result = 'succes';
      else if (total >= 14) result = 'mitige';
      else result = 'echec';
    } else {
      if (total >= 16) result = 'succes';
      else if (total >= 11) result = 'mitige';
      else result = 'echec';
    }

    /* Maîtrise sur succès ou mitigé */
    if (result === 'succes' || result === 'mitige') {
      window.addMastery(card.id);
    }

    /* Effets mécaniques */
    if (result === 'succes') {
      sv.momentum = Math.min(3, sv.momentum + 1);
      sv.danger += 2;
      sv.reputation += 5;
    } else if (result === 'mitige') {
      sv.danger += 1;
      sv.reputation += 2;
    } else {
      sv.momentum = Math.max(-3, sv.momentum - 1);
      sv.reputation += 0;
    }

    /* But sur succès en FINITION */
    var goal = false;
    if (result === 'succes' && sv.matchPhase === 'FINITION') {
      sv.matchScore[0] += 1;
      sv.danger = 0;
      sv.momentum = 3;
      sv.reputation += 3;
      goal = true;
    }

    /* Texte */
    var phase = sv.matchPhase || 'ATT';
    var txts = this.resolutionTexts[result] && this.resolutionTexts[result][phase];
    var text = txts ? this.randomFrom(txts) : "L'action se conclut.";

    return {
      result: result,
      text: text,
      total: total,
      base: base,
      roll: roll,
      card: card,
      matchup: matchup,
      native: native,
      mastered: mastered,
      goal: goal,
      penalty: penalty
    };
  }
};

/* --- Fonction : Vérifier seuil de relation --- */
window.relCheck = function(name, threshold) {
  return (State.variables.relations[name] || 0) >= threshold;
};

/* --- Menu — onglet marque-page du cahier ---
   Les styles sont dans le CSS (classes hojo-*).
   Le JS ne fait que créer le DOM et toggler des classes. */
(function() {
  var menuOpen = false;
  var settingsOpen = false;

  function createMenu() {
    if (document.getElementById('hojo-menu-toggle')) return;

    /* ── Overlay ── */
    var overlay = document.createElement('div');
    overlay.id = 'hojo-menu-overlay';
    document.body.appendChild(overlay);

    /* ── Panneau ── */
    var panel = document.createElement('div');
    panel.id = 'hojo-menu-panel';
    document.body.appendChild(panel);

    /* En-tête */
    var header = document.createElement('div');
    header.id = 'hojo-menu-header';
    header.textContent = 'Carnet du joueur';
    panel.appendChild(header);

    /* Items */
    var items = [
      { label: 'Fiche & deck',           action: 'profil',    danger: false },
      { label: 'R\u00e9glages du cahier',     action: 'settings',  danger: false },
      { label: 'Sauvegardes en ligne',    action: 'cloud',     danger: false },
      { label: 'Relire depuis le d\u00e9but',  action: 'restart',   danger: true  }
    ];

    items.forEach(function(item, i) {
      var btn = document.createElement('div');
      btn.className = 'hojo-menu-item' + (item.danger ? ' hojo-menu-item--danger' : '');
      btn.setAttribute('data-action', item.action);
      btn.setAttribute('role', 'button');
      btn.setAttribute('tabindex', '0');
      btn.innerHTML = '<span class="hojo-menu-item__num">\u00a7' + (i+1) + '</span>' + item.label;
      panel.appendChild(btn);
    });

    /* ── Panneau R\u00e9glages ── */
    var settingsPanel = document.createElement('div');
    settingsPanel.id = 'hojo-settings';

    function makeSettingsGroup(label, groupId, options, currentVal) {
      var group = document.createElement('div');
      group.className = 'hojo-settings-group';

      var lbl = document.createElement('div');
      lbl.className = 'hojo-settings-label';
      lbl.textContent = label;
      group.appendChild(lbl);

      var row = document.createElement('div');
      row.className = 'hojo-settings-row';
      row.setAttribute('data-group', groupId);

      options.forEach(function(opt) {
        var b = document.createElement('button');
        b.className = 'hojo-settings-btn' + (opt.value === currentVal ? ' is-active' : '');
        b.textContent = opt.label;
        b.setAttribute('data-val', opt.value);

        b.addEventListener('click', function(e) {
          e.stopPropagation();
          var siblings = row.querySelectorAll('.hojo-settings-btn');
          for (var j = 0; j < siblings.length; j++) {
            siblings[j].classList.remove('is-active');
          }
          b.classList.add('is-active');
          window.applySettings(groupId, opt.value);
        });

        row.appendChild(b);
      });

      group.appendChild(row);
      return group;
    }

    var prefs = {
      fontSize: localStorage.getItem('hojo-fontSize') || 'medium',
      fontFamily: localStorage.getItem('hojo-fontFamily') || 'serif',
      theme: localStorage.getItem('hojo-theme') || 'cahier'
    };

    settingsPanel.appendChild(makeSettingsGroup('Taille du texte', 'fontSize', [
      { label: 'Petit', value: 'small' },
      { label: 'Moyen', value: 'medium' },
      { label: 'Grand', value: 'large' }
    ], prefs.fontSize));

    settingsPanel.appendChild(makeSettingsGroup('Police', 'fontFamily', [
      { label: 'Serif', value: 'serif' },
      { label: 'Sans-serif', value: 'sans' },
      { label: 'Mono', value: 'mono' }
    ], prefs.fontFamily));

    settingsPanel.appendChild(makeSettingsGroup('Th\u00e8me', 'theme', [
      { label: '\uD83D\uDCD3 Cahier', value: 'cahier' },
      { label: '\uD83C\uDF19 Nuit', value: 'nuit' },
      { label: '\uD83D\uDCDC Parchemin', value: 'parchemin' },
      { label: '\uD83C\uDFDF Terrain', value: 'terrain' }
    ], prefs.theme));

    /* Ins\u00e9rer apr\u00e8s le 2\u00e8me item */
    var allItems = panel.querySelectorAll('[data-action]');
    if (allItems.length >= 2) {
      allItems[1].after(settingsPanel);
    } else {
      panel.appendChild(settingsPanel);
    }

    /* ── applySettings — CSS vars + classes uniquement ── */
    window.applySettings = function(key, value) {
      localStorage.setItem('hojo-' + key, value);
      var root = document.documentElement;

      if (key === 'fontSize') {
        var sizes = { small: '14px', medium: '16px', large: '19px' };
        root.style.setProperty('--body-size', sizes[value] || '16px');
      }

      if (key === 'fontFamily') {
        var fonts = {
          serif: "'Lora', Georgia, serif",
          sans: "'Barlow', 'Segoe UI', sans-serif",
          mono: "'Courier New', Courier, monospace"
        };
        root.style.setProperty('--font-body', fonts[value] || fonts.serif);
      }

      if (key === 'theme') {
        document.body.classList.remove('theme-cahier','theme-nuit','theme-parchemin','theme-terrain');
        document.body.classList.add('theme-' + value);
      }
    };

    /* Spacer */
    var spacer = document.createElement('div');
    spacer.className = 'hojo-menu-spacer';
    panel.appendChild(spacer);

    /* ── Onglet ── */
    var tab = document.createElement('div');
    tab.id = 'hojo-menu-toggle';
    tab.setAttribute('role', 'button');
    tab.setAttribute('tabindex', '0');
    tab.setAttribute('aria-label', 'Menu');
    tab.innerHTML = '\u26BD MENU';
    document.body.appendChild(tab);

    /* Appliquer les prefs au d\u00e9marrage */
    window.applySettings('fontSize', prefs.fontSize);
    window.applySettings('fontFamily', prefs.fontFamily);
    window.applySettings('theme', prefs.theme);

    /* ── Position dynamique (calcul JS n\u00e9cessaire) ── */
    function positionPanel() {
      var storyEl = document.getElementById('story');
      if (!storyEl || window.innerWidth <= 480) return;
      var rect = storyEl.getBoundingClientRect();
      var panelRight = (window.innerWidth - rect.right) + 20;
      if (panelRight < 10) panelRight = 10;
      panel.style.right = panelRight + 'px';
      var tabRight = window.innerWidth - rect.right - 18;
      if (tabRight < 0) tabRight = 0;
      tab.style.right = tabRight + 'px';
    }

    positionPanel();
    window.addEventListener('resize', positionPanel);

    /* ── Vérifier si sauvegarde désactivée ── */
    function isSaveDisabled() {
      var manualDisable = State.variables.saveDisabled || false;
      /* Vérifier le tag "nosave" sur le passage actuel */
      var currentTags = tags() || [];
      var hasNoSaveTag = currentTags.indexOf('nosave') !== -1;
      return manualDisable || hasNoSaveTag;
    }

    function updateCloudItemState() {
      var cloudItem = panel.querySelector('[data-action="cloud"]');
      if (!cloudItem) return;
      if (isSaveDisabled()) {
        cloudItem.classList.add('is-disabled');
        cloudItem.setAttribute('title', 'Sauvegarde impossible pendant un match');
      } else {
        cloudItem.classList.remove('is-disabled');
        cloudItem.removeAttribute('title');
      }
    }

    /* ── Toggle ── */
    function openMenu() {
      menuOpen = true;
      tab.classList.add('is-open');
      tab.innerHTML = '\u2715';
      panel.classList.add('is-open');
      overlay.classList.add('is-open');
      updateCloudItemState();
    }

    function closeMenuFn() {
      menuOpen = false;
      settingsOpen = false;
      settingsPanel.classList.remove('is-open');
      tab.classList.remove('is-open');
      tab.innerHTML = '\u26BD MENU';
      panel.classList.remove('is-open');
      overlay.classList.remove('is-open');
    }

    tab.addEventListener('click', function(e) {
      e.stopPropagation();
      if (menuOpen) closeMenuFn(); else openMenu();
    });

    overlay.addEventListener('click', closeMenuFn);

    document.addEventListener('keydown', function(e) {
      if (e.key === 'Escape' && menuOpen) closeMenuFn();
    });

    /* ── Actions ── */
    panel.addEventListener('click', function(e) {
      var target = e.target.closest('[data-action]');
      if (!target) return;
      var action = target.getAttribute('data-action');

      /* Bloquer si désactivé */
      if (target.classList.contains('is-disabled')) {
        notify('Sauvegarde impossible ici');
        return;
      }

      if (action === 'settings') {
        settingsOpen = !settingsOpen;
        settingsPanel.classList.toggle('is-open', settingsOpen);
        return;
      }

      closeMenuFn();
      switch(action) {
        case 'profil':
          State.variables._returnPassage = State.passage;
          Engine.play('Profil_Joueur');
          break;
        case 'cloud':
          State.variables._returnPassage = State.passage;
          Engine.play('Menu_Sauvegarde');
          break;
        case 'restart':
          /* Popup de confirmation */
          var popupOverlay = document.createElement('div');
          popupOverlay.className = 'hojo-popup-overlay';

          var popup = document.createElement('div');
          popup.className = 'hojo-popup';
          popup.innerHTML =
            '<div class="hojo-popup__titre">Relire depuis le début</div>' +
            '<div class="hojo-popup__texte">Ta sauvegarde automatique sera <strong>supprimée</strong>. Tu devras recommencer l\'histoire depuis le début.<br><br>Tes sauvegardes en ligne ne seront pas affectées.</div>' +
            '<div class="hojo-popup__actions">' +
              '<button class="hojo-popup__btn hojo-popup__btn--annuler">Annuler</button>' +
              '<button class="hojo-popup__btn hojo-popup__btn--danger">Supprimer et relire</button>' +
            '</div>';

          popupOverlay.appendChild(popup);
          document.body.appendChild(popupOverlay);

          /* Forcer reflow puis afficher */
          popup.offsetHeight;
          popupOverlay.classList.add('is-visible');

          popupOverlay.querySelector('.hojo-popup__btn--annuler').addEventListener('click', function() {
            popupOverlay.classList.remove('is-visible');
            setTimeout(function() { popupOverlay.remove(); }, 300);
          });
          popupOverlay.querySelector('.hojo-popup__btn--danger').addEventListener('click', function() {
            Save.autosave.delete();
            popupOverlay.remove();
            Engine.restart();
          });
          popupOverlay.addEventListener('click', function(ev) {
            if (ev.target === popupOverlay) {
              popupOverlay.classList.remove('is-visible');
              setTimeout(function() { popupOverlay.remove(); }, 300);
            }
          });
          break;
      }
    });
  }

  $(document).one(':storyready', function() {
    createMenu();
  });
})();

/* --- Interlude entre les actes ---
   Usage : <<run window.playInterlude("Acte I", "Sans filet", "jingle_acte1", "Acte1_Arrivee")>>
   Le 3ème param est l'ID <<cacheaudio>> (pas un fichier). */
window.playInterlude = function(acteLabel, titre, audioId, nextPassage) {
  /* Stopper toute musique en cours */
  SimpleAudio.stop();

  /* Masquer le cahier */
  var story = document.getElementById('story');
  if (story) story.style.visibility = 'hidden';

  /* Masquer le menu */
  var menuTab = document.getElementById('hojo-menu-toggle');
  if (menuTab) menuTab.style.display = 'none';

  /* Supprimer un éventuel interlude précédent */
  var old = document.getElementById('hojo-interlude');
  if (old) old.remove();

  /* Créer l'interlude */
  var el = document.createElement('div');
  el.id = 'hojo-interlude';
  el.className = 'interlude';
  el.innerHTML =
    '<div class="interlude__line-top"></div>' +
    '<div class="interlude__line-bot"></div>' +
    '<div class="interlude__acte">' + acteLabel + '</div>' +
    '<div class="interlude__titre">' + titre + '</div>' +
    '<div class="interlude__sous-titre">Hojo Tigers · Tome 1</div>' +
    '<button class="interlude__continuer">Continuer →</button>';

  document.body.appendChild(el);

  /* Jouer le jingle via SugarCube */
  var track = null;
  if (audioId) {
    try {
      track = SimpleAudio.tracks.get(audioId);
      track.volume(0.6);
      track.play();
    } catch(e) { track = null; }
  }

  /* Bouton continuer */
  var btn = el.querySelector('.interlude__continuer');
  btn.addEventListener('click', function() {
    /* Fade out visuel */
    el.style.transition = 'opacity 0.6s ease';
    el.style.opacity = '0';

    /* Fade out audio */
    if (track) {
      track.fade(0.6, 0);
    }

    setTimeout(function() {
      el.remove();
      if (story) story.style.visibility = '';
      if (menuTab) menuTab.style.display = '';
      if (track) track.stop();
      Engine.play(nextPassage);
    }, 650);
  });
};

/* Nettoyer l'interlude si on change de passage autrement (back, etc.) */
$(document).on(':passagestart', function() {
  var interlude = document.getElementById('hojo-interlude');
  if (interlude) {
    interlude.remove();
    var story = document.getElementById('story');
    if (story) story.style.visibility = '';
    var menuTab = document.getElementById('hojo-menu-toggle');
    if (menuTab) menuTab.style.display = '';
  }
});

/* --- Réappliquer les paramètres à chaque passage --- */
$(document).on(':passagerender', function(ev) {
  var root = document.documentElement;

  /* Taille de police */
  var fs = localStorage.getItem('hojo-fontSize') || 'medium';
  var sizes = { small: '14px', medium: '16px', large: '19px' };
  root.style.setProperty('--body-size', sizes[fs] || '16px');

  /* Police */
  var ff = localStorage.getItem('hojo-fontFamily') || 'serif';
  var fonts = {
    serif: "'Lora', Georgia, serif",
    sans: "'Barlow', 'Segoe UI', sans-serif",
    mono: "'Courier New', Courier, monospace"
  };
  root.style.setProperty('--font-body', fonts[ff] || fonts.serif);

  /* Thème */
  var th = localStorage.getItem('hojo-theme') || 'cahier';
  document.body.classList.remove('theme-cahier','theme-nuit','theme-parchemin','theme-terrain');
  document.body.classList.add('theme-' + th);
});

:: StoryStylesheet [stylesheet]
/* ═══════════════════════════════════════════════
   HOJO TIGERS — LDVELH  ·  Tome 1
   Thème « Cahier de collégien × terrain de foot × gamebook »
   Mobile-first · responsive
   ═══════════════════════════════════════════════ */

@import url('https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,600;0,700;1,400&family=Barlow+Semi+Condensed:wght@500;600;700;800&family=Barlow:wght@400;500;600&display=swap');

:root {
  /* ── Papier de cahier ── */
  --page: #faf6ef;
  --page-ruled: #d5cec0;
  --page-margin: #c9525b;
  --page-shadow: #ece6da;

  /* ── Encre & texte ── */
  --ink: #1e1a14;
  --ink-light: #4a4238;
  --ink-faded: #7d7368;
  --ink-ghost: #a69e92;

  /* ── Terrain & sport ── */
  --pitch: #1b6e33;
  --pitch-dark: #145226;
  --pitch-light: #3a9a50;
  --pitch-pale: #dff0d8;
  --chalk: #ffffff;
  --chalk-line: rgba(255,255,255,0.35);

  /* ── Maillot / école ── */
  --jersey-orange: #e8752a;
  --jersey-dark: #c45e1a;
  --navy: #1c2e4a;
  --navy-light: #2c4670;

  /* ── Gamebook accents ── */
  --amber: #c08b15;
  --amber-light: #d9a832;
  --danger-red: #a12b2b;
  --bruise: #6b4c8a;

  /* ── Structure ── */
  --border: #d5cfc3;
  --border-strong: #b8b0a2;
  --shadow-sm: 0 1px 3px rgba(30,26,20,0.08);
  --shadow-md: 0 3px 10px rgba(30,26,20,0.12);
  --radius: 2px;
  --transition: 0.2s ease;
  --accent: var(--pitch);

  /* ── Rythme vertical du cahier ──
     TOUT le rythme vertical est basé sur --line-gap.
     17px font × 1.82 line-height ≈ 31px.
     On fixe 31px partout pour que lignes CSS = lignes de texte. */
  --line-gap: 31px;

  /* ── Paramètres personnalisables ── */
  --body-size: 16px;
  --font-body: 'Lora', 'Georgia', 'Times New Roman', serif;
  --font-head: 'Barlow Semi Condensed', 'Arial Narrow', sans-serif;
}

* { box-sizing: border-box; }

html {
  font-size: var(--body-size);
  scroll-behavior: smooth;
}

body {
  background: #d6d0c4;
  color: var(--ink);
  font-family: var(--font-body);
  line-height: var(--line-gap);
  margin: 0;
  padding: 0;
  -webkit-font-smoothing: antialiased;
}

/* ═══════════════════════════════════════
   THÈMES
   ═══════════════════════════════════════ */

/* Cahier — thème par défaut (les variables :root suffisent) */
body.theme-cahier {
  background: #d6d0c4;
}

/* Nuit */
body.theme-nuit {
  background: #0f0f23;
  --page: #1a1a2e;
  --page-ruled: #2a2a4e;
  --page-margin: #4a3060;
  --page-shadow: #12122a;
  --ink: #e0ddd5;
  --ink-light: #b0aaa0;
  --ink-faded: #706a60;
  --ink-ghost: #504a40;
  --pitch: #4a90d9;
  --pitch-dark: #2a60a0;
  --pitch-light: #6ab0f0;
  --pitch-pale: #1a2a40;
  --chalk: #e0ddd5;
  --jersey-orange: #e8952a;
  --navy: #2a4070;
  --amber: #d0a020;
  --danger-red: #d04040;
  --border: #333355;
  --border-strong: #444466;
}
body.theme-nuit #story {
  box-shadow: 0 2px 20px rgba(0,0,0,0.5);
}

/* Parchemin */
body.theme-parchemin {
  background: #c4a070;
  --page: #f5e6c8;
  --page-ruled: #d4c4a0;
  --page-margin: #8b4513;
  --page-shadow: #e8d4b0;
  --ink: #2c1810;
  --ink-light: #4a3020;
  --ink-faded: #7a6050;
  --ink-ghost: #a09080;
  --pitch: #8b4513;
  --pitch-dark: #6b3010;
  --pitch-light: #b06030;
  --pitch-pale: #f0e0c0;
  --jersey-orange: #c06020;
  --amber: #a07010;
  --border: #c4a882;
  --border-strong: #a08060;
}

/* Terrain */
body.theme-terrain {
  background: #4a7a4a;
  --page: #e8f0e4;
  --page-ruled: #c0d8b8;
  --page-margin: #2d6a2d;
  --page-shadow: #d0e0c8;
  --ink: #1a2e1a;
  --ink-light: #2a4a2a;
  --ink-faded: #5a7a5a;
  --ink-ghost: #8aaa8a;
  --pitch: #2d6a2d;
  --pitch-dark: #1a4a1a;
  --pitch-light: #4a9a4a;
  --pitch-pale: #d0eac0;
  --jersey-orange: #d07020;
  --amber: #a09010;
  --border: #a8c8a8;
  --border-strong: #88a888;
}

/* ═══════════════════════════════════════
   MENU — Carnet du joueur
   Tous les styles du menu sont ici.
   Les couleurs héritent des variables du thème actif.
   ═══════════════════════════════════════ */

/* Overlay */
#hojo-menu-overlay {
  position: fixed;
  inset: 0;
  background: rgba(30,26,20,0.35);
  z-index: 9000;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
}
#hojo-menu-overlay.is-open {
  opacity: 1;
  pointer-events: auto;
}

/* Panel — page arrachée du cahier */
#hojo-menu-panel {
  position: fixed;
  top: 50%;
  z-index: 9001;
  width: 280px;
  padding: 0;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-50%) translateX(20px);
  transition: all 0.3s cubic-bezier(0.4,0,0.2,1);
  overflow: hidden;
  background-color: var(--page);
  background-image:
    linear-gradient(90deg, transparent 27px, var(--page-margin) 27px, var(--page-margin) 29px, transparent 29px),
    repeating-linear-gradient(180deg, transparent 0px, transparent 30px, var(--page-ruled) 30px, var(--page-ruled) 31px);
  background-size: 100% 31px;
  background-position: 0 0;
  border: none;
  border-top: 3px dashed var(--border-strong);
  box-shadow: 3px 4px 14px rgba(30,26,20,0.25), -1px -1px 0 rgba(30,26,20,0.05);
}
#hojo-menu-panel.is-open {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(-50%) translateX(0);
}

/* En-tête */
#hojo-menu-header {
  background: transparent;
  color: var(--pitch-dark);
  padding: 10px 16px 2px 36px;
  font-family: Lora, Georgia, serif;
  font-weight: 700;
  font-size: 15px;
  font-style: italic;
  text-align: left;
  line-height: 31px;
  border-bottom: 1.5px solid var(--pitch);
  margin-bottom: 0;
}

/* Items du menu */
.hojo-menu-item {
  display: block;
  height: 31px;
  line-height: 31px;
  padding: 0 16px 0 46px;
  font-family: Lora, Georgia, serif;
  font-size: 14px;
  color: var(--ink-light);
  cursor: pointer;
  background: transparent;
  border: none;
  text-align: left;
  width: 100%;
  position: relative;
  transition: background 0.15s ease;
  box-sizing: border-box;
  text-decoration: none;
  outline: none;
}
.hojo-menu-item:hover {
  background: rgba(27,110,51,0.06);
}
.hojo-menu-item__num {
  position: absolute;
  left: 32px;
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 11px;
  font-weight: 700;
  color: var(--pitch);
}
.hojo-menu-item:hover .hojo-menu-item__num {
  color: var(--jersey-orange);
}
.hojo-menu-item--danger {
  color: var(--danger-red);
}
.hojo-menu-item--danger:hover {
  background: rgba(161,43,43,0.06);
}
.hojo-menu-item--danger .hojo-menu-item__num {
  color: var(--danger-red);
}
.hojo-menu-item--danger:hover .hojo-menu-item__num {
  color: var(--danger-red);
}

/* Item désactivé (ex: sauvegarde pendant un match) */
.hojo-menu-item.is-disabled {
  color: var(--ink-ghost);
  cursor: not-allowed;
  opacity: 0.5;
}
.hojo-menu-item.is-disabled:hover {
  background: transparent;
}
.hojo-menu-item.is-disabled .hojo-menu-item__num {
  color: var(--ink-ghost);
}

/* Panneau réglages */
#hojo-settings {
  display: none;
  padding: 10px 16px 14px 36px;
  border-top: 1px dashed var(--border);
  border-bottom: 1px dashed var(--border);
  background: rgba(27,110,51,0.03);
}
#hojo-settings.is-open {
  display: block;
}
.hojo-settings-group {
  margin-bottom: 10px;
}
.hojo-settings-group:last-child {
  margin-bottom: 0;
}
.hojo-settings-label {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 10px;
  font-weight: 700;
  color: var(--pitch);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 5px;
}
.hojo-settings-row {
  display: flex;
  gap: 5px;
  flex-wrap: wrap;
}
.hojo-settings-btn {
  padding: 4px 10px;
  font-family: Barlow, sans-serif;
  font-size: 11px;
  font-weight: 500;
  border: 1.5px solid var(--border);
  border-radius: 3px;
  cursor: pointer;
  transition: all 0.15s;
  background: transparent;
  color: var(--ink-light);
}
.hojo-settings-btn:hover {
  border-color: var(--pitch);
  color: var(--pitch);
}
.hojo-settings-btn.is-active {
  background: var(--pitch);
  color: var(--chalk);
  border-color: var(--pitch);
  font-weight: 700;
}

/* Espacement bas */
.hojo-menu-spacer {
  height: 16px;
}

/* Onglet — marque-page */
#hojo-menu-toggle {
  position: fixed;
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  z-index: 9002;
  width: 36px;
  height: 110px;
  border: none;
  border-radius: 4px 0 0 4px;
  background: var(--pitch);
  color: var(--chalk);
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: -2px 2px 6px rgba(30,26,20,0.2);
  transition: background 0.2s ease;
  writing-mode: vertical-rl;
  text-orientation: mixed;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  line-height: 1;
  padding: 0;
  margin: 0;
}
#hojo-menu-toggle:hover {
  background: var(--pitch-light);
}
#hojo-menu-toggle.is-open {
  background: var(--jersey-orange);
}
#hojo-menu-toggle.is-open:hover {
  background: var(--jersey-orange);
}

/* Mobile */
@media (max-width: 480px) {
  #hojo-menu-toggle {
    bottom: 0;
    right: 0;
    top: auto !important;
    left: auto;
    transform: none;
    width: auto;
    height: 36px;
    border-radius: 6px 0 0 0;
    box-shadow: -2px -2px 6px rgba(30,26,20,0.2);
    writing-mode: horizontal-tb;
    text-orientation: initial;
    gap: 6px;
    padding: 0 14px;
    letter-spacing: 0.1em;
  }
  #hojo-menu-panel {
    top: auto;
    bottom: 36px;
    right: 0 !important;
    left: 0;
    width: 100%;
    max-height: 60vh;
    overflow-y: auto;
    border-radius: 0;
    transform: translateY(100%);
  }
  #hojo-menu-panel.is-open {
    transform: translateY(0);
  }
  .hojo-menu-item {
    height: 48px;
    line-height: 48px;
    font-size: 15px;
    padding-left: 50px;
    border-bottom: 1px solid var(--border);
  }
}

/* ═══════════════════════════════════════
   PAGE — effet « cahier ouvert »
   - Marge rouge à gauche (cahier Seyes)
   - Lignes horizontales subtiles
   - Ombre de reliure
   ═══════════════════════════════════════ */
#ui-bar, #ui-bar-body, #ui-bar-toggle { display: none !important; }

/* Empêcher SugarCube de pousser le contenu pour la sidebar */
html[data-init="loading"] body,
body {
  margin-left: 0 !important;
}

#story {
  max-width: 660px;
  margin: 1.2rem auto !important;
  /* padding-top en px pour synchroniser avec la grille */
  padding: 31px 2rem calc(var(--line-gap) * 4) 2.8rem;
  background-color: var(--page);

  /* ── Lignes du cahier ──
     La ligne est tracée à ~20px dans chaque cycle de 31px,
     ce qui correspond à la baseline de Lora 17px.
     background-position-y = padding-top pour que le cycle
     démarre exactement là où commence le texte. */
  background-image:
    repeating-linear-gradient(
      180deg,
      transparent 0px,
      transparent 19px,
      var(--page-ruled) 19px,
      var(--page-ruled) 20px,
      transparent 20px,
      transparent 31px
    );
  background-size: 100% var(--line-gap);
  background-position: 0 31px;
  background-attachment: local;

  min-height: 100vh;
  position: relative;
  border: 1px solid var(--border);
  box-shadow:
    -6px 0 12px rgba(30,26,20,0.05),
    6px 0 12px rgba(30,26,20,0.05),
    inset 3px 0 6px rgba(30,26,20,0.04);
}

/* Marge rouge — cahier d'écolier */
#story::before {
  content: '';
  position: absolute;
  left: 2rem;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--page-margin);
  opacity: 0.45;
  z-index: 1;
}

/* Reliure gauche */
#story::after {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 6px;
  background: linear-gradient(90deg, var(--page-shadow) 0%, transparent 100%);
}

.passage {
  animation: pageIn 0.35s ease-out;
  position: relative;
  z-index: 2;
}

@keyframes pageIn {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ═══════════════════════════════════════
   TYPOGRAPHIE — esprit roman jeunesse / LDVELH
   ═══════════════════════════════════════ */
h1, h2, h3, h4 {
  font-family: var(--font-head);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

/* Titre de chapitre — bande de terrain */
h1 {
  font-size: 1.45rem;
  text-align: center;
  /* 62px = 2 × line-gap au-dessus, 31px = 1 × line-gap en-dessous */
  margin: 62px -2rem 31px -2.8rem;
  padding: 0.65rem 2.8rem;
  background: var(--pitch);
  color: var(--chalk);
  position: relative;
  border: none;
  letter-spacing: 0.06em;
  line-height: var(--line-gap);
}

/* Petite ligne de craie décorative */
h1::after {
  content: '';
  display: block;
  width: 40px;
  height: 2px;
  background: var(--chalk-line);
  margin: 0.35rem auto 0;
  border-radius: 1px;
}

/* Sous-titre — soulignement terrain */
h2 {
  font-size: 1.1rem;
  font-weight: 700;
  margin: 62px 0 0;
  padding-bottom: 4px;
  border-bottom: 2px solid var(--pitch);
  color: var(--pitch-dark);
  line-height: var(--line-gap);
}

h3 {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--ink-light);
  margin: 31px 0 0;
  letter-spacing: 0.02em;
  text-transform: none;
  line-height: var(--line-gap);
}

p {
  /* Pas de marge verticale entre paragraphes : le text-indent suffit.
     Ça préserve le rythme vertical du cahier. */
  margin: 0;
  padding: 0;
  text-align: justify;
  hyphens: auto;
  text-indent: 1.5em;
}

/* Pas d'indentation après certains éléments */
h1 + p, h2 + p, h3 + p,
.encadre + p, .card-hand + p,
.scene-break + p, .scoreboard + p,
hr + p, .hud + p,
.choices + p {
  text-indent: 0;
}

em { font-style: italic; }
strong {
  font-weight: 700;
  color: var(--ink);
}

/* Séparateur — ligne de touche */
hr {
  border: none;
  margin: 31px 0;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--border-strong) 15%,
    var(--border-strong) 42%,
    transparent 45%,
    transparent 55%,
    var(--border-strong) 58%,
    var(--border-strong) 85%,
    transparent 100%
  );
  position: relative;
}
hr::after {
  content: '⚽';
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  background: var(--page);
  padding: 0 0.6rem;
  font-size: 0.7rem;
  color: var(--ink-ghost);
}

/* ═══════════════════════════════════════
   LIENS / CHOIX — style LDVELH classique
   « Rendez-vous au paragraphe… »
   ═══════════════════════════════════════ */
.passage a[class*="link"],
.passage a:not(.card-btn):not(.btn):not(.hud-link) {
  display: block;
  background: transparent;
  border: none;
  border-left: 3px solid var(--jersey-orange);
  color: var(--ink);
  text-decoration: none;
  padding: 0.6rem 0.8rem 0.6rem 1rem;
  margin: 0.35rem 0;
  font-family: 'Barlow', 'Helvetica Neue', sans-serif;
  font-size: 0.88rem;
  font-weight: 600;
  line-height: 1.5;
  transition: all var(--transition);
  cursor: pointer;
  position: relative;
}

.passage a:not(.card-btn):not(.btn):not(.hud-link)::before {
  content: '▸';
  position: absolute;
  left: -0.2rem;
  color: var(--jersey-orange);
  font-size: 0.7rem;
  top: 50%;
  transform: translateY(-50%);
  opacity: 0;
  transition: opacity var(--transition);
}

.passage a:not(.card-btn):not(.btn):not(.hud-link):hover {
  background: rgba(232,117,42,0.06);
  border-left-color: var(--jersey-dark);
  padding-left: 1.3rem;
}

.passage a:not(.card-btn):not(.btn):not(.hud-link):hover::before {
  opacity: 1;
}

/* ═══════════════════════════════════════
   HUD — Barre d'état « tableau de bord du coach »
   ═══════════════════════════════════════ */
.hud {
  position: sticky;
  top: 0;
  z-index: 100;
  background: linear-gradient(180deg, var(--page) 0%, var(--page) 85%, transparent 100%);
  padding: 0 0 0;
  margin-bottom: 31px;
  margin-left: -0.8rem;
  font-family: 'Barlow', sans-serif;
}

.hud-inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  background: var(--navy);
  border-radius: var(--radius);
  padding: 0.45rem 0.8rem;
  font-size: 0.75rem;
  color: var(--chalk);
  border-bottom: 2px solid var(--jersey-orange);
}

.hud-item {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  white-space: nowrap;
}

.hud-label {
  opacity: 0.55;
  text-transform: uppercase;
  font-size: 0.58rem;
  letter-spacing: 0.07em;
  font-weight: 600;
}

.hud-value {
  font-weight: 700;
  font-size: 0.82rem;
}

.hud-energy { color: #7ddb8a; }
.hud-momentum-pos { color: #7ec8f0; }
.hud-momentum-neg { color: #f09090; }
.hud-momentum-zero { color: rgba(255,255,255,0.5); }

/* Jauge visuelle — pips */
.gauge {
  display: inline-flex;
  gap: 2px;
  vertical-align: middle;
  margin-left: 3px;
}

.gauge-pip {
  width: 7px;
  height: 10px;
  border-radius: 1px;
  background: rgba(255,255,255,0.15);
  transition: background var(--transition);
}

.gauge-pip.filled { background: #7ddb8a; }
.gauge-pip.danger { background: #f09090; }

/* ═══════════════════════════════════════
   CARTES DE JEU — style « fiche d'entraînement »
   Évoque un plan tactique sur ardoise de coach
   ═══════════════════════════════════════ */
/* ═══════════════════════════════════════
   MAIN DE CARTES — disposition en éventail
   ═══════════════════════════════════════ */
.card-hand {
  display: flex;
  justify-content: center;
  align-items: flex-end;
  margin: 62px 0 31px;
  padding: 2.5rem 0.5rem 1rem;
  background: var(--pitch-dark);
  border-radius: var(--radius);
  position: relative;
  min-height: 200px;
  overflow: visible;
  perspective: 800px;
}

/* Lignes de craie décoratives sur le fond terrain */
.card-hand::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 5%;
  right: 5%;
  height: 1px;
  background: var(--chalk-line);
}

.card-hand::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 8%;
  bottom: 8%;
  width: 1px;
  background: var(--chalk-line);
}

/* ── Carte individuelle ── */
.card {
  background: var(--chalk);
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  padding: 0.7rem;
  cursor: pointer;
  position: relative;
  z-index: 1;
  /* Taille fixe pour un éventail régulier */
  width: 135px;
  min-width: 135px;
  flex-shrink: 0;
  /* Chevauchement */
  margin-left: -20px;
  /* Origine de rotation = bas centre (le poignet) */
  transform-origin: 50% 95%;
  transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1),
              box-shadow 0.25s ease,
              z-index 0s;
}

/* Premier enfant : pas de marge négative */
.card:first-child {
  margin-left: 0;
}

/* ── Rotations en éventail (4 cartes) ── */
.card:nth-child(1) { transform: rotate(-9deg) translateY(-4px); z-index: 1; }
.card:nth-child(2) { transform: rotate(-3deg) translateY(-1px); z-index: 2; }
.card:nth-child(3) { transform: rotate(3deg)  translateY(-1px); z-index: 3; }
.card:nth-child(4) { transform: rotate(9deg)  translateY(-4px); z-index: 4; }

/* ── Support 3 cartes ── */
.card:nth-child(3):last-child { transform: rotate(0deg) translateY(0); }
.card:nth-child(2):nth-last-child(2) { transform: rotate(-6deg) translateY(-2px); }
.card:nth-child(3):nth-last-child(1):not(:nth-child(4)) { transform: rotate(6deg) translateY(-2px); }

/* ── Support 5 cartes ── */
.card:first-child:nth-last-child(5)                      { transform: rotate(-12deg) translateY(-8px); z-index: 1; }
.card:first-child:nth-last-child(5) ~ .card:nth-child(2) { transform: rotate(-6deg)  translateY(-3px); z-index: 2; }
.card:first-child:nth-last-child(5) ~ .card:nth-child(3) { transform: rotate(0deg)   translateY(0);    z-index: 3; }
.card:first-child:nth-last-child(5) ~ .card:nth-child(4) { transform: rotate(6deg)   translateY(-3px); z-index: 4; }
.card:first-child:nth-last-child(5) ~ .card:nth-child(5) { transform: rotate(12deg)  translateY(-8px); z-index: 5; }

/* Bande de risque en haut */
.card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  border-radius: 4px 4px 0 0;
}

.card-risk-low::before  { background: var(--pitch-light); }
.card-risk-mid::before  { background: var(--amber); }
.card-risk-high::before { background: var(--danger-red); }

/* ── Hover : la carte « sort » de la main ── */
.card:hover {
  transform: rotate(0deg) translateY(-35px) scale(1.05) !important;
  z-index: 50 !important;
  box-shadow: 0 8px 24px rgba(30,26,20,0.3);
}

.card-name {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-weight: 700;
  font-size: 0.88rem;
  color: var(--ink);
  margin-bottom: 0.25rem;
  text-transform: uppercase;
  letter-spacing: 0.01em;
}

.card-stats {
  display: flex;
  gap: 0.35rem;
  font-family: 'Barlow', sans-serif;
  font-size: 0.66rem;
  font-weight: 600;
  color: var(--ink-light);
  margin-bottom: 0.25rem;
}

.card-stat {
  padding: 1px 5px;
  background: var(--pitch-pale);
  border: 1px solid #c3d9be;
  border-radius: 2px;
}

.card-desc {
  font-family: var(--font-body);
  font-size: 0.76rem;
  color: var(--ink-faded);
  line-height: 1.4;
}

.card-disabled {
  opacity: 0.3;
  pointer-events: none;
}

/* ═══════════════════════════════════════
   DECK VISUEL — cartes posées sur le cahier
   (utilisé dans Profil_Joueur)
   ═══════════════════════════════════════ */
.deck-section {
  margin: 31px 0;
}

.deck-section-title {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-weight: 800;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--pitch-dark);
  margin: 0 0 8px 0;
  padding: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  line-height: 31px;
}

.deck-section-title::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--pitch);
  opacity: 0.3;
}

.deck-count {
  font-weight: 500;
  font-size: 0.72rem;
  color: var(--ink-faded);
  letter-spacing: 0;
  text-transform: none;
}

/* Grille de cartes — posées à plat */
.deck-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 10px;
  margin: 0;
  padding: 0;
}

/* ═══════════════════════════════════════
   MINI-CARTE DU DECK — style trading card
   ═══════════════════════════════════════ */
.deck-card {
  background: #e8f0e6;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  padding: 0;
  position: relative;
  overflow: hidden;
  transition: transform 0.25s cubic-bezier(0.34, 1.2, 0.64, 1), box-shadow 0.2s ease;
  box-shadow: 0 1px 3px rgba(30,26,20,0.1), inset 0 0 0 1px rgba(255,255,255,0.5);
}

.deck-card:hover {
  transform: translateY(-4px) rotate(-0.5deg);
  box-shadow: 0 6px 16px rgba(30,26,20,0.18), inset 0 0 0 1px rgba(255,255,255,0.5);
  z-index: 2;
}

/* ── Header : bande colorée par risque avec force ── */
.deck-card-head {
  display: flex !important;
  align-items: center !important;
  justify-content: space-between !important;
  padding: 6px 10px 5px 8px !important;
  min-height: 30px !important;
  position: relative !important;
}

/* Motif subtil sur le header — hachures diagonales */
.deck-card-head::after {
  content: '' !important;
  position: absolute !important;
  inset: 0 !important;
  background: repeating-linear-gradient(
    -45deg,
    transparent,
    transparent 4px,
    rgba(255,255,255,0.07) 4px,
    rgba(255,255,255,0.07) 5px
  ) !important;
  pointer-events: none !important;
}

/* Couleur du header selon le risque */
.deck-card[data-risk="Faible"] .deck-card-head {
  background: linear-gradient(135deg, var(--pitch-dark) 0%, var(--pitch) 100%) !important;
}
.deck-card[data-risk="Moyen"] .deck-card-head {
  background: linear-gradient(135deg, #7a5a08 0%, var(--amber) 100%) !important;
}
.deck-card[data-risk="Élevé"] .deck-card-head {
  background: linear-gradient(135deg, #5a1212 0%, var(--danger-red) 100%) !important;
}

/* Famille dans le header */
.deck-card-family {
  font-family: 'Barlow', sans-serif !important;
  font-size: 0.54rem !important;
  font-weight: 700 !important;
  text-transform: uppercase !important;
  letter-spacing: 0.1em !important;
  color: rgba(255,255,255,0.9) !important;
  line-height: 1 !important;
  display: inline-block !important;
  padding: 0 !important;
  margin: 0 !important;
  background: none !important;
  border-radius: 0 !important;
  border: none !important;
  position: relative !important;
  z-index: 1;
}

/* Gros chiffre de force */
.deck-card-force {
  font-family: 'Barlow Semi Condensed', sans-serif !important;
  font-weight: 800 !important;
  font-size: 1.2rem !important;
  color: var(--chalk) !important;
  line-height: 1 !important;
  text-shadow: 0 1px 3px rgba(0,0,0,0.25);
  position: relative !important;
  z-index: 1;
}

/* ── Corps de la carte ── */
.deck-card-body {
  padding: 7px 10px 8px;
  position: relative;
  min-height: 72px;
  /* Cadre intérieur subtil */
  border: 1px solid rgba(0,0,0,0.04);
  margin: 0 3px 3px;
  border-radius: 0 0 2px 2px;
}

/* Teinte du corps selon le risque — fond coloré léger */
.deck-card[data-risk="Faible"] .deck-card-body {
  background:
    linear-gradient(160deg, rgba(27,110,51,0.06) 0%, rgba(58,154,80,0.03) 50%, rgba(255,255,255,0) 100%);
}
.deck-card[data-risk="Moyen"] .deck-card-body {
  background:
    linear-gradient(160deg, rgba(192,139,21,0.07) 0%, rgba(192,139,21,0.03) 50%, rgba(255,255,255,0) 100%);
}
.deck-card[data-risk="Élevé"] .deck-card-body {
  background:
    linear-gradient(160deg, rgba(161,43,43,0.06) 0%, rgba(161,43,43,0.03) 50%, rgba(255,255,255,0) 100%);
}

/* ── Icône filigrane de famille — VISIBLE ── */
.deck-card-watermark {
  position: absolute;
  bottom: 2px;
  right: 4px;
  font-size: 2.6rem;
  line-height: 1;
  pointer-events: none;
  z-index: 0;
}

/* Couleur du watermark selon le risque */
.deck-card[data-risk="Faible"] .deck-card-watermark {
  color: var(--pitch);
  opacity: 0.1;
}
.deck-card[data-risk="Moyen"] .deck-card-watermark {
  color: var(--amber);
  opacity: 0.12;
}
.deck-card[data-risk="Élevé"] .deck-card-watermark {
  color: var(--danger-red);
  opacity: 0.1;
}

.deck-card:hover .deck-card-watermark {
  opacity: 0.2;
  transition: opacity 0.3s ease;
}

/* Nom */
.deck-card-name {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-weight: 700;
  font-size: 0.84rem;
  color: var(--ink);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1.2;
  margin-bottom: 5px;
  position: relative;
  z-index: 1;
}

/* Ligne de stats — badges */
.deck-card-stats {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  margin-bottom: 6px;
  align-items: center;
  position: relative;
  z-index: 1;
}

.deck-card-badge {
  font-family: 'Barlow', sans-serif;
  font-size: 0.58rem;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: 2px;
  line-height: 1.5;
}

.deck-card-badge-stat {
  background: var(--pitch-pale);
  color: var(--pitch-dark);
  border: 1px solid #b4cfac;
}

.deck-card-badge-stat2 {
  background: #eef2ed;
  color: #6a8a60;
  border: 1px solid #c8dcc2;
  font-size: 0.52rem;
  opacity: 0.85;
}

.deck-card-badge-native {
  background: #e8f5e9;
  color: #2e7d32;
  border: 1px solid #a5d6a7;
  padding: 0.15rem 0.5rem;
  border-radius: 3px;
  font-size: 0.65rem;
  font-weight: 600;
  display: inline-block;
  margin: 0.15rem 0.2rem;
}

.deck-card-badge-phase {
  background: #e3f2fd;
  color: #1565c0;
  border: 1px solid #90caf9;
  font-size: 0.48rem;
  letter-spacing: 0.5px;
}

.card-native-bonus {
  color: #2e7d32;
  font-weight: 700;
  font-size: 0.6rem;
}

.deck-card-native {
  border-left: 3px solid #4caf50;
}

.deck-card-native .deck-card-force::after {
  content: "+1";
  font-size: 0.5rem;
  color: #2e7d32;
  vertical-align: super;
}

.deck-card-mastery {
  display: inline-block;
  font-size: 0.55rem;
  color: #ff8f00;
  letter-spacing: 1px;
  margin-left: 0.3rem;
}

.deck-card-mastered {
  border-left: 3px solid #ff8f00 !important;
}

.deck-card-mastered .deck-card-force::after {
  content: "+1";
  font-size: 0.5rem;
  color: #ff8f00;
  vertical-align: super;
}

/* --- Matchup indicators --- */
.matchup-fav {
  color: #2e7d32;
  font-weight: 700;
  font-size: 0.6rem;
}

.matchup-def {
  color: #c62828;
  font-weight: 700;
  font-size: 0.6rem;
}

.matchup-neu {
  color: #757575;
  font-size: 0.55rem;
}

.card-matchup {
  text-align: center;
  padding: 0.2rem 0;
  border-top: 1px solid rgba(0,0,0,0.08);
  margin-top: 0.2rem;
}

.enemy-action {
  display: inline-block;
  background: #fff3e0;
  color: #e65100;
  border: 1px solid #ffcc80;
  padding: 0.2rem 0.6rem;
  border-radius: 4px;
  font-weight: 700;
  font-size: 0.7rem;
  letter-spacing: 0.5px;
}

.deck-card-badge-cost {
  background: #f0e5c8;
  color: #7a5e10;
  border: 1px solid #d8c890;
}

/* Indicateur de risque — icônes ▲ */
.deck-card-risk {
  font-family: 'Barlow', sans-serif;
  font-size: 0.52rem;
  font-weight: 600;
  letter-spacing: 1px;
  margin-left: auto;
  padding: 1px 4px;
  border-radius: 2px;
}

.deck-card-risk[data-risk="Faible"] {
  color: var(--pitch);
  background: rgba(27,110,51,0.08);
}
.deck-card-risk[data-risk="Moyen"] {
  color: var(--amber);
  background: rgba(192,139,21,0.08);
}
.deck-card-risk[data-risk="Élevé"] {
  color: var(--danger-red);
  background: rgba(161,43,43,0.08);
}

/* Séparateur fin avant description */
.deck-card-sep {
  height: 1px;
  background: var(--border-strong);
  margin: 0 0 5px 0;
  position: relative;
  z-index: 1;
  opacity: 0.6;
}

/* Description */
.deck-card-desc {
  font-family: var(--font-body);
  font-size: 0.7rem;
  font-style: italic;
  color: var(--ink-light);
  line-height: 1.4;
  position: relative;
  z-index: 1;
}

/* ═══════════════════════════════════════
   SIGNATURES — cartes dorées premium
   ═══════════════════════════════════════ */
.deck-card-signature {
  background: linear-gradient(155deg, #fdf6e3 0%, #f5ecd5 50%, #f0e4c8 100%);
  border: 1.5px solid var(--amber);
  border-radius: 4px;
  padding: 0;
  position: relative;
  overflow: hidden;
  transition: transform 0.25s cubic-bezier(0.34, 1.2, 0.64, 1), box-shadow 0.2s ease;
  box-shadow: 0 1px 3px rgba(192,139,21,0.12), inset 0 0 0 1px rgba(255,255,255,0.4);
}

/* Bande dorée en haut */
.deck-card-signature .deck-card-head {
  background: linear-gradient(135deg, #6a4e08 0%, var(--amber) 50%, var(--amber-light) 100%) !important;
}

/* Motif de filigrane diagonal — rayures dorées */
.deck-card-signature::after {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    -45deg,
    transparent,
    transparent 8px,
    rgba(192,139,21,0.04) 8px,
    rgba(192,139,21,0.04) 9px
  );
  pointer-events: none;
  z-index: 0;
}

.deck-card-signature .deck-card-head,
.deck-card-signature .deck-card-body {
  position: relative;
  z-index: 1;
}

/* Étoile devant la force */
.deck-card-signature .deck-card-force::before {
  content: '★ ';
  font-size: 0.65rem;
  vertical-align: middle;
  opacity: 0.8;
}

.deck-card-signature:hover {
  transform: translateY(-4px) rotate(0.5deg);
  box-shadow: 0 6px 18px rgba(192,139,21,0.25), inset 0 0 0 1px rgba(255,255,255,0.4);
}

.deck-card-signature .deck-card-family {
  color: rgba(255,255,255,0.95) !important;
}

.deck-card-signature .deck-card-body {
  background:
    linear-gradient(160deg, rgba(192,139,21,0.08) 0%, rgba(192,139,21,0.03) 50%, rgba(255,255,255,0) 100%);
  min-height: 72px;
  border: 1px solid rgba(192,139,21,0.1);
  margin: 0 3px 3px;
  border-radius: 0 0 2px 2px;
}

.deck-card-signature .deck-card-watermark {
  color: var(--amber);
  opacity: 0.15;
  font-size: 2.6rem;
  filter: none;
}

.deck-card-signature:hover .deck-card-watermark {
  opacity: 0.25;
}

.deck-card-signature .deck-card-badge-stat {
  background: #f5ecd5;
  color: #6a5010;
  border-color: #e0d0a0;
}

.deck-card-signature .deck-card-badge-stat2 {
  background: #faf5e8;
  color: #8a7030;
  border-color: #e8dab0;
  font-size: 0.52rem;
  opacity: 0.85;
}

.deck-card-signature .deck-card-badge-cost {
  background: rgba(255,255,255,0.5);
  color: #7a5e10;
  border-color: #d0c090;
}

.deck-card-signature .deck-card-sep {
  background: var(--amber);
  opacity: 0.25;
}

/* ── RESPONSIVE deck ── */
@media (max-width: 480px) {
  .deck-grid {
    grid-template-columns: repeat(auto-fill, minmax(115px, 1fr));
    gap: 7px;
  }
  .deck-card-name { font-size: 0.72rem; }
  .deck-card-badge { font-size: 0.52rem; }
  .deck-card-desc { font-size: 0.6rem; }
  .deck-card-family { font-size: 0.48rem; }
  .deck-card-force { font-size: 0.85rem; }
  .deck-card-body { padding: 5px 6px 6px; }
  .deck-card-head { padding: 3px 6px 2px 5px; }
}

/* ═══════════════════════════════════════
   ENCADRÉS — style « note dans la marge du cahier »
   ═══════════════════════════════════════ */
.encadre {
  background: var(--chalk);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
  margin: 31px 0;
  font-size: 0.86rem;
  line-height: 1.55;
  position: relative;
}

.encadre p { text-indent: 0; }

.encadre-titre {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-weight: 700;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 0.35rem;
}

.encadre-info {
  border-left: 3px solid var(--pitch);
  background: linear-gradient(90deg, var(--pitch-pale) 0%, var(--chalk) 100%);
}
.encadre-info .encadre-titre { color: var(--pitch-dark); }

.encadre-danger {
  border-left: 3px solid var(--danger-red);
  background: linear-gradient(90deg, #fce8e8 0%, var(--chalk) 100%);
}
.encadre-danger .encadre-titre { color: var(--danger-red); }

.encadre-secret {
  border-left: 3px solid var(--bruise);
  background: linear-gradient(90deg, #f0e8f5 0%, var(--chalk) 100%);
}
.encadre-secret .encadre-titre { color: var(--bruise); }

.encadre-relation {
  border-left: 3px solid var(--jersey-orange);
  background: linear-gradient(90deg, #fef0e4 0%, var(--chalk) 100%);
}
.encadre-relation .encadre-titre { color: var(--jersey-dark); }

/* ═══════════════════════════════════════
   NOTIFICATIONS — carton jaune / info flash
   ═══════════════════════════════════════ */
.notif {
  position: fixed;
  bottom: 1.5rem;
  left: 50%;
  transform: translateX(-50%) translateY(80px);
  background: var(--navy);
  color: var(--chalk);
  border-radius: var(--radius);
  border-left: 3px solid var(--jersey-orange);
  padding: 0.6rem 1.2rem;
  font-family: 'Barlow', sans-serif;
  font-size: 0.8rem;
  font-weight: 600;
  box-shadow: var(--shadow-md);
  z-index: 1000;
  opacity: 0;
  transition: all 0.35s ease;
  pointer-events: none;
}

.notif.show {
  transform: translateX(-50%) translateY(0);
  opacity: 1;
}

/* ═══════════════════════════════════════
   PROFIL DU JOUEUR — fiche de licence sportive
   ═══════════════════════════════════════ */
.profil-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.5rem;
  margin: 31px 0;
}

.profil-stat {
  background: var(--chalk);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.5rem 0.7rem;
  text-align: center;
  border-top: 2px solid var(--pitch);
}

.profil-stat-label {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 0.62rem;
  text-transform: uppercase;
  color: var(--ink-faded);
  letter-spacing: 0.07em;
  font-weight: 600;
}

.profil-stat-value {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 1.5rem;
  font-weight: 800;
  color: var(--pitch-dark);
}

/* ═══════════════════════════════════════
   CHOIX DE CRÉATION — style questionnaire de rentrée
   ═══════════════════════════════════════ */
.creation-options {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.45rem;
  margin: 31px 0;
}

.creation-opt {
  display: block;
  background: var(--chalk);
  border: 1px solid var(--border);
  border-left: 3px solid var(--jersey-orange);
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
  text-decoration: none;
  color: var(--ink);
  transition: all var(--transition);
  cursor: pointer;
}

.creation-opt:hover {
  background: #fef6ef;
  border-left-color: var(--jersey-dark);
  transform: translateX(3px);
}

.creation-opt-title {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-weight: 700;
  font-size: 0.95rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  margin-bottom: 0.15rem;
  color: var(--navy);
}

.creation-opt-desc {
  font-family: var(--font-body);
  font-size: 0.82rem;
  color: var(--ink-light);
  line-height: 1.45;
}

/* ═══════════════════════════════════════
   SCOREBOARD — tableau d'affichage de gymnase scolaire
   Panneau sombre, score lumineux, ligne orange
   ═══════════════════════════════════════ */
.scoreboard {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 1.2rem;
  background: var(--navy);
  border-radius: var(--radius);
  padding: 0.85rem 1.5rem;
  margin: 31px 0;
  font-family: 'Barlow Semi Condensed', sans-serif;
  color: var(--chalk);
  border-bottom: 3px solid var(--jersey-orange);
}

.scoreboard-team {
  text-align: center;
  font-weight: 700;
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.scoreboard-score {
  font-size: 2.2rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  color: var(--jersey-orange);
}

.scoreboard-minute {
  font-family: 'Barlow', sans-serif;
  font-size: 0.72rem;
  color: var(--ink-ghost);
  text-align: center;
  margin-top: 0.2rem;
}

/* ═══════════════════════════════════════
   RELATIONS — fiches de vestiaire
   Style « notes du coach dans son carnet »
   ═══════════════════════════════════════ */

/* Conteneur section */
.relations-section {
  margin: 31px 0;
}

.relations-section-title {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-weight: 800;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--pitch-dark);
  margin: 0 0 8px 0;
  display: flex;
  align-items: center;
  gap: 8px;
  line-height: 31px;
}

.relations-section-title::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--pitch);
  opacity: 0.3;
}

/* Grille de fiches */
.relations-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(155px, 1fr));
  gap: 6px;
}

/* Fiche individuelle */
.rel-card {
  background: var(--chalk);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 7px 9px 8px;
  position: relative;
  overflow: hidden;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.rel-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 3px 10px rgba(30,26,20,0.12);
}

/* Bande latérale gauche — couleur selon le statut */
.rel-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 3px;
  height: 100%;
}

.rel-card[data-status="hostile"]::before  { background: var(--danger-red); }
.rel-card[data-status="froid"]::before    { background: #d48a4e; }
.rel-card[data-status="neutre"]::before   { background: var(--border-strong); }
.rel-card[data-status="cordial"]::before  { background: var(--amber); }
.rel-card[data-status="confiance"]::before { background: var(--pitch-light); }
.rel-card[data-status="allié"]::before    { background: var(--pitch); }
.rel-card[data-status="lien"]::before     { background: var(--jersey-orange); }

/* Ligne 1 : tag poste + nom */
.rel-card-header {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 4px;
}

.rel-card-role {
  font-family: 'Barlow', sans-serif;
  font-size: 0.5rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--chalk);
  background: var(--navy);
  display: inline-block;
  padding: 0px 4px;
  border-radius: 2px;
  line-height: 1.6;
  flex-shrink: 0;
}

.rel-card-role[data-pos="GAR"] { background: #6b4c8a; }
.rel-card-role[data-pos="DEF"] { background: var(--navy); }
.rel-card-role[data-pos="MIL"] { background: var(--pitch-dark); }
.rel-card-role[data-pos="ATT"] { background: var(--danger-red); }
.rel-card-role[data-pos="COA"] { background: var(--ink-light); }

.rel-card-name {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-weight: 700;
  font-size: 0.8rem;
  color: var(--ink);
  letter-spacing: 0.01em;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Jauge — barre large avec fond terrain */
.rel-gauge-container {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 2px;
}

.rel-gauge {
  flex: 1;
  height: 8px;
  background: var(--border);
  border-radius: 4px;
  overflow: hidden;
  position: relative;
}

/* Graduations sur la jauge */
.rel-gauge::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg,
      transparent 24.9%, rgba(255,255,255,0.4) 25%, rgba(255,255,255,0.4) 25.3%, transparent 25.4%,
      transparent 49.9%, rgba(255,255,255,0.4) 50%, rgba(255,255,255,0.4) 50.3%, transparent 50.4%,
      transparent 74.9%, rgba(255,255,255,0.4) 75%, rgba(255,255,255,0.4) 75.3%, transparent 75.4%
    );
  z-index: 1;
  pointer-events: none;
}

.rel-gauge-fill {
  height: 100%;
  border-radius: 4px;
  transition: width 0.5s ease;
  position: relative;
}

/* Dégradé selon le niveau */
.rel-gauge-fill[data-status="hostile"]  { background: linear-gradient(90deg, #8a2020, var(--danger-red)); }
.rel-gauge-fill[data-status="froid"]    { background: linear-gradient(90deg, #b06830, #d48a4e); }
.rel-gauge-fill[data-status="neutre"]   { background: linear-gradient(90deg, var(--border-strong), var(--ink-ghost)); }
.rel-gauge-fill[data-status="cordial"]  { background: linear-gradient(90deg, #a07510, var(--amber)); }
.rel-gauge-fill[data-status="confiance"] { background: linear-gradient(90deg, var(--pitch-dark), var(--pitch-light)); }
.rel-gauge-fill[data-status="allié"]    { background: linear-gradient(90deg, var(--pitch), var(--pitch-light)); }
.rel-gauge-fill[data-status="lien"]     { background: linear-gradient(90deg, var(--jersey-dark), var(--jersey-orange)); }

.rel-value {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-weight: 700;
  font-size: 0.68rem;
  color: var(--ink-faded);
  min-width: 18px;
  text-align: right;
  line-height: 1;
}

/* Label de statut */
.rel-status {
  font-family: var(--font-body);
  font-size: 0.6rem;
  font-style: italic;
  line-height: 1;
}

.rel-status[data-status="hostile"]  { color: var(--danger-red); }
.rel-status[data-status="froid"]    { color: #d48a4e; }
.rel-status[data-status="neutre"]   { color: var(--ink-ghost); }
.rel-status[data-status="cordial"]  { color: var(--amber); }
.rel-status[data-status="confiance"] { color: var(--pitch-light); }
.rel-status[data-status="allié"]    { color: var(--pitch); }
.rel-status[data-status="lien"]     { color: var(--jersey-orange); }

/* ── RESPONSIVE relations ── */
@media (max-width: 480px) {
  .relations-grid {
    grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
    gap: 5px;
  }
  .rel-card { padding: 6px 7px 6px; }
  .rel-card-name { font-size: 0.74rem; }
  .rel-card-role { font-size: 0.46rem; }
  .rel-gauge { height: 6px; }
  .rel-value { font-size: 0.62rem; }
}

/* ═══════════════════════════════════════
   ÉCRAN TITRE — couverture de LDVELH
   ═══════════════════════════════════════ */
.titre-screen {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 80vh;
  text-align: center;
  padding: 2rem 0;
}

/* Bande verte terrain en fond du logo */
.titre-logo {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 2.6rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--chalk);
  background: var(--pitch);
  padding: 0.5rem 1.8rem;
  margin: 0 -2.8rem;
  width: calc(100% + 5.6rem);
  position: relative;
}

/* Lignes de craie sur la bande titre */
.titre-logo::before,
.titre-logo::after {
  content: '';
  position: absolute;
  left: 8%;
  right: 8%;
  height: 1px;
  background: var(--chalk-line);
}
.titre-logo::before { top: 6px; }
.titre-logo::after { bottom: 6px; }

.titre-sub {
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--ink-light);
  font-style: italic;
  margin: 0.8rem 0 0.3rem;
}

.titre-timeline {
  font-family: 'Barlow', sans-serif;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--ink-ghost);
  margin-bottom: 2.5rem;
}

.titre-start {
  display: inline-block;
  background: var(--jersey-orange);
  color: var(--chalk);
  padding: 0.7rem 2.4rem;
  border-radius: var(--radius);
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-weight: 700;
  font-size: 1rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  text-decoration: none;
  transition: all var(--transition);
  border: none;
  cursor: pointer;
}

.titre-start:hover {
  background: var(--jersey-dark);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.titre-mention {
  margin-top: 2rem;
  font-size: 0.68rem;
  color: var(--ink-ghost);
  font-family: 'Barlow', sans-serif;
}

.titre-changelog {
  display: inline-block;
  margin-top: 1.2rem;
  font-size: 0.6rem;
  color: var(--ink-ghost);
  font-family: 'Barlow', sans-serif;
  letter-spacing: 0.5px;
  text-decoration: none;
  border-bottom: 1px dotted var(--ink-ghost);
  padding-bottom: 1px;
  cursor: pointer;
  transition: color 0.2s;
}

.titre-changelog:hover {
  color: var(--accent);
}

/* ═══════════════════════════════════════
   INTERLUDE — écran entre les actes
   ═══════════════════════════════════════ */
.interlude {
  position: fixed;
  inset: 0;
  z-index: 8000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: #0a0a0f;
  text-align: center;
  overflow: hidden;
}

.interlude__line-top,
.interlude__line-bot {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(232,117,42,0.5), transparent);
  animation: interlude-line 2s 0.6s ease-out forwards;
}
.interlude__line-top { top: 36%; }
.interlude__line-bot { bottom: 36%; }

.interlude__acte {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.45em;
  text-transform: uppercase;
  color: rgba(232,117,42,0.8);
  opacity: 0;
  transform: translateY(10px);
  animation: interlude-fade 1.2s 0.8s ease-out forwards;
  margin-bottom: 0.7rem;
}

.interlude__titre {
  font-family: Lora, Georgia, serif;
  font-size: clamp(1.5rem, 5vw, 2.5rem);
  font-weight: 700;
  font-style: italic;
  color: #f0ece4;
  line-height: 1.3;
  opacity: 0;
  transform: translateY(15px);
  animation: interlude-fade 1.4s 1.2s ease-out forwards;
  margin-bottom: 1.2rem;
  padding: 0 2rem;
  max-width: 600px;
}

.interlude__sous-titre {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 0.6rem;
  font-weight: 500;
  letter-spacing: 0.15em;
  color: rgba(240,236,228,0.3);
  opacity: 0;
  animation: interlude-fade 1s 2.4s ease-out forwards;
  margin-bottom: 2.5rem;
}

.interlude__continuer {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(240,236,228,0.45);
  text-decoration: none;
  cursor: pointer;
  opacity: 0;
  animation: interlude-fade 1s 3.2s ease-out forwards;
  transition: color 0.3s, border-color 0.3s;
  padding: 0.55rem 1.6rem;
  border: 1px solid rgba(240,236,228,0.12);
  border-radius: 2px;
  background: transparent;
}
.interlude__continuer:hover {
  color: #e8752a;
  border-color: rgba(232,117,42,0.4);
}

@keyframes interlude-line {
  to { width: min(480px, 75vw); }
}
@keyframes interlude-fade {
  to { opacity: 1; transform: translateY(0); }
}

/* ═══════════════════════════════════════
   POPUP DE CONFIRMATION
   ═══════════════════════════════════════ */
.hojo-popup-overlay {
  position: fixed;
  inset: 0;
  z-index: 9500;
  background: rgba(30,26,20,0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.25s ease;
  padding: 1rem;
}
.hojo-popup-overlay.is-visible {
  opacity: 1;
}
.hojo-popup {
  background: var(--page);
  border: none;
  border-top: 3px solid var(--danger-red, #a12b2b);
  box-shadow: 0 8px 32px rgba(30,26,20,0.35);
  max-width: 380px;
  width: 100%;
  padding: 1.4rem 1.6rem 1.2rem;
  transform: translateY(10px) scale(0.97);
  transition: transform 0.25s ease;
}
.hojo-popup-overlay.is-visible .hojo-popup {
  transform: translateY(0) scale(1);
}
.hojo-popup__titre {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--danger-red, #a12b2b);
  margin-bottom: 0.7rem;
}
.hojo-popup__texte {
  font-family: Lora, Georgia, serif;
  font-size: 0.82rem;
  line-height: 1.6;
  color: var(--ink);
  margin-bottom: 1.2rem;
}
.hojo-popup__texte strong {
  color: var(--danger-red, #a12b2b);
}
.hojo-popup__actions {
  display: flex;
  gap: 0.6rem;
  justify-content: flex-end;
}
.hojo-popup__btn {
  font-family: 'Barlow Semi Condensed', sans-serif;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.45rem 1rem;
  border-radius: 2px;
  cursor: pointer;
  transition: all 0.15s;
  border: 1px solid var(--border);
}
.hojo-popup__btn--annuler {
  background: transparent;
  color: var(--ink-light);
}
.hojo-popup__btn--annuler:hover {
  background: var(--pitch-pale);
  border-color: var(--pitch);
  color: var(--pitch);
}
.hojo-popup__btn--danger {
  background: var(--danger-red, #a12b2b);
  color: #fff;
  border-color: var(--danger-red, #a12b2b);
}
.hojo-popup__btn--danger:hover {
  background: #8a2020;
  border-color: #8a2020;
}

/* ═══════════════════════════════════════
   PRÉFACE
   ═══════════════════════════════════════ */
.preface {
  max-width: 600px;
  margin: 0 auto;
  font-size: 0.85rem;
  line-height: 1.7;
}

.preface h2 {
  font-family: var(--font-head);
  font-size: 1.3rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 1.5rem;
}

.preface h3 {
  font-family: var(--font-head);
  font-size: 0.9rem;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--ink);
  margin-top: 1.5rem;
  margin-bottom: 0.5rem;
}

/* ═══════════════════════════════════════
   SÉPARATEUR DE SCÈNE — coup de sifflet
   ═══════════════════════════════════════ */
.scene-break {
  text-align: center;
  margin: 62px 0;
  color: var(--ink-ghost);
  font-size: 0.75rem;
  letter-spacing: 0.5em;
  font-family: 'Barlow', sans-serif;
  line-height: var(--line-gap);
}

/* ═══════════════════════════════════════
   RESPONSIVE
   ═══════════════════════════════════════ */
@media (max-width: 480px) {
  html { font-size: 16px; }
  /* line-height reste 31px (via body), le ratio passe à ~1.94 — OK */

  #story {
    margin: 0;
    /* padding-top = 31px pour rester calé sur la grille */
    padding: 31px 1rem 3rem 1.6rem;
    border-radius: 0;
    border: none;
    box-shadow: none;
    background-position: 0 31px;
  }

  /* Marge rouge toujours visible mais adaptée */
  #story::before { left: 1rem; }
  #story::after { display: none; }

  .titre-logo {
    font-size: 1.9rem;
    margin: 0 -1.6rem;
    width: calc(100% + 3.2rem);
  }

  h1 { font-size: 1.2rem; margin-left: -1.6rem; margin-right: -1rem; padding: 0.55rem 1.6rem; }

  .card-hand {
    padding: 2rem 0.3rem 0.8rem;
    min-height: 170px;
    margin: 31px -0.6rem;
  }

  .card {
    width: 105px;
    min-width: 105px;
    margin-left: -25px;
    padding: 0.5rem;
  }

  .card:first-child { margin-left: 0; }

  .card:hover {
    transform: rotate(0deg) translateY(-25px) scale(1.08) !important;
  }

  .card-name { font-size: 0.72rem; margin-bottom: 0.15rem; }
  .card-stats { font-size: 0.58rem; gap: 0.2rem; margin-bottom: 0.15rem; }
  .card-stat { padding: 0 3px; }
  .card-desc { font-size: 0.64rem; line-height: 1.3; }

  .hud-inner {
    padding: 0.35rem 0.5rem;
    gap: 0.3rem;
    font-size: 0.68rem;
  }

  .hud { margin-left: -0.6rem; }

  .scoreboard { gap: 0.8rem; padding: 0.6rem 0.9rem; }
  .scoreboard-score { font-size: 1.6rem; }

  h2 { font-size: 1rem; }
}

@media (min-width: 481px) and (max-width: 768px) {
  html { font-size: 16.5px; }
  #story {
    margin: 0.8rem auto;
    padding: 31px 1.6rem 3.5rem 2.4rem;
    background-position: 0 31px;
  }
  #story::before { left: 1.6rem; }
  .card { width: 125px; min-width: 125px; margin-left: -18px; }
  .card:first-child { margin-left: 0; }
  h1 { margin-left: -2.4rem; margin-right: -1.6rem; padding-left: 2.4rem; padding-right: 1.6rem; }
}

@media (min-width: 769px) {
  /* Desktop : éventail pleine taille, pas besoin d'override */
}

/* ═══════════════════════════════════════
   SCROLLBAR
   ═══════════════════════════════════════ */