/* ═══════════════════════════════════════════════════════════════════════
   PORTAIL DE SHANDRIS — scene composee, couche par couche
   ═══════════════════════════════════════════════════════════════════════

   LA SCENE N'EST PAS UNE IMAGE : elle est assemblee ici a partir des pieces
   extraites de la planche. C'est ce qui permet d'ecarter les plans, de faire
   respirer les braseros, d'onduler les bannieres et de choisir le format -
   l'illustration d'origine imposait son 4,1:1 et ne se decomposait pas.

   L'ORDRE DES COUCHES, DU FOND VERS L'AVANT :

       ciel  >  horizon (les deux royaumes)  >  sol  >  decor lointain
       >  bannieres  >  [ travers > vortex > arche ]  >  decor proche
       >  mages  >  canvas (faisceaux, particules, halo)  >  voile > texte

   LE VORTEX EST DERRIERE LA PIERRE. Son canvas est enfant de l'arche et
   passe sous elle : l'ouverture evidee le laisse voir, la pierre le masque.
   Les particules, elles, passent devant tout.

   AUCUNE TAILLE DE TEXTE SOUS 1rem : contrainte d'accessibilite du projet.
   ═══════════════════════════════════════════════════════════════════════ */

.portail {
  /* LA BARRE DE NAVIGATION EST FIXE et recouvrait le haut de la scene.
     Sa hauteur porte deja un nom dans la mise en page - 76 px, 70 px sur
     petit ecran - et l'ancien hero s'en servait : on reprend la variable
     plutot qu'un nombre, sans quoi les deux se desaccorderaient au
     premier changement de barre. */
  padding-top: var(--nav-h, 76px);

  --ratio: 1600 / 780;

  /* L'OUVERTURE, RELEVEE SUR L'IMAGE DE L'ARCHE. Elle sert au decoupage
     du vortex et au placement de ses couches : si l'arche change, ces
     quatre nombres doivent etre repris, sans quoi tout se decale en
     silence. Mesure par propagation depuis le centre de l'image, ce qui
     donne l'ouverture elle-meme et non une approximation. */
  --ouv-cx: 49.80%;
  --ouv-cy: 52.23%;
  --ouv-rx: 23.96%;
  --ouv-ry: 27.67%;

  /* Un ajustement OPTIQUE du vortex dans son ouverture, en pixels et non
     en pourcentage : il doit rester constant quelle que soit la taille de
     la scene. */
  --vortex-dy: 11px;

  /* Les bouts de baton, d'ou partent les faisceaux. En pourcentage de la
     scene : le script les lit ici, de sorte qu'un seul endroit commande. */
  /* Les axes que les pieces partagent avec ce qui se pose dessus. Une
     piece dimensionnee en HAUTEUR a une largeur qui depend du ratio de la
     scene : poser une flamme a cote de son brasero par un pourcentage
     fixe ne l'aurait alignee qu'a un seul format d'ecran. */
  --axe-piliers: 7.7%;
  --axe-brasero: 15.7%;
  --axe-cristal: 35.7%;


  --bleu-vif: #6fc3ff;
  --or: var(--amber, #f5a623);
  --or-clair: var(--amber-soft, #ffd97d);

  position: relative;
  width: 100%;
  margin: 0 0 28px;
  overflow: hidden;
  /* PAS DE FOND PROPRE. La scene le recouvrait entierement : il ne
     servait qu'a masquer les auras douces que .cw-page::before pose
     sur toute la page, et le portail s'en trouvait plus sombre que
     ce qui l'entoure. */
}

.portail-scene {
  position: relative;
  width: 100%;
  aspect-ratio: var(--ratio);
  /* Le plafond fait ceder la HAUTEUR, jamais la largeur : la scene reste
     pleine page et s'aplatit d'elle-meme sur un ecran bas. */
  /* La barre s'ajoute au-dessus : sans la retrancher, l'ensemble
     depasserait l'ecran de sa hauteur. */
  max-height: calc(82vh - var(--nav-h, 76px));
  min-height: 380px;
  overflow: hidden;
}

.portail-scene > * { position: absolute; }

/* ─── 1. le ciel ────────────────────────────────────────────────────── */

.portail-ciel {
  inset: 0;
  background:
    radial-gradient(90% 70% at 50% 72%, rgba(40, 80, 180, 0.35), transparent 70%),
    linear-gradient(to bottom, #060b1c 0%, #0a1430 45%, #050a18 100%);
}

/* ─── 2. l'horizon : la neige a gauche, le desert a droite ──────────── */
/*
   Les deux panoramas se rejoignent au centre, derriere l'arche. Le fondu
   evite une couture nette la ou ils se touchent.
*/
.portail-horizon { inset: 0 0 auto 0; height: 78%; }

.portail-pano {
  position: absolute;
  top: 0;
  width: 52%;
  height: 100%;
  object-fit: cover;
  opacity: 0.82;
}

.portail-pano-nord {
  left: 0;
  -webkit-mask-image: linear-gradient(to right, #000 62%, transparent 100%);
  mask-image: linear-gradient(to right, #000 62%, transparent 100%);
}

.portail-pano-sud {
  right: 0;
  -webkit-mask-image: linear-gradient(to left, #000 62%, transparent 100%);
  mask-image: linear-gradient(to left, #000 62%, transparent 100%);
}

/* ─── 3. le sol ─────────────────────────────────────────────────────── */

.portail-sol {
  inset: auto 0 0 0;
  height: 34%;
  background:
    linear-gradient(to right, rgba(120, 150, 200, 0.16), transparent 42%,
                    transparent 58%, rgba(200, 160, 90, 0.16)),
    linear-gradient(to bottom, rgba(6, 10, 24, 0) 0%, rgba(5, 8, 15, 0.9) 72%);
}

/* ─── 4. le decor ───────────────────────────────────────────────────── */

/* Les pieces se dimensionnent par leur HAUTEUR, et non leur largeur : elles
   n'ont pas les memes proportions entre elles, et raisonner en hauteur les
   pose toutes sur le meme plan, comme si elles partageaient le sol. */
.portail-piece { width: auto; pointer-events: none; }

/*
   LES PILIERS SONT POSES PAR LEUR CENTRE. Par leur bord, ils ne pouvaient
   s'aligner sur leurs bannieres qu'a un seul ratio de scene : la largeur
   d'une piece dimensionnee en hauteur vaut hauteur x ratio_image /
   ratio_scene, et les deux pieces n'ont pas le meme ratio d'image. Les
   deux colonnes non plus entre elles (0,42 au nord, 0,48 au sud).
*/
.portail-colonne-g {
  left: var(--axe-piliers);
  bottom: 25%;
  height: 46%;
  transform: translateX(-50%);
}
.portail-colonne-d {
  right: var(--axe-piliers);
  bottom: 25%;
  height: 46%;
  transform: translateX(50%);
}

.portail-cristal-g {
  left: var(--axe-cristal);
  bottom: 28%;
  height: 13%;
  transform: translateX(-50%);
}
.portail-cristal-d {
  right: var(--axe-cristal);
  bottom: 28%;
  height: 13%;
  transform: translateX(50%);
}

/*
   L'ECLAT DU CRISTAL : une etoile a quatre branches qui parait une demi-
   seconde toutes les sept, puis s'efface en grandissant. Elle se pose sur
   l'axe du monument, ou son cristal est centre a 2 % pres - mesure a
   50,2 % au nord et 51,9 % au sud.

   Les hauteurs, elles, different : le coeur lumineux tombe a 37,9 % de
   l'obelisque nord et a 56,7 % du monument sud, ce qui les place a 63,9
   et 66,4 % de la scene.
*/
.portail-eclat {
  width: 3.4%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%) scale(0.5);
  opacity: 0;
  pointer-events: none;
  mix-blend-mode: screen;
  animation: portail-scintille 3.5s ease-out infinite;
}

/* Le halo rond. */
.portail-eclat::before {
  content: '';
  position: absolute;
  inset: 26%;
  border-radius: 50%;
  background: radial-gradient(circle,
              rgba(255, 255, 255, 0.95) 0%,
              rgba(255, 255, 255, 0.4) 26%,
              rgba(255, 255, 255, 0) 65%);
}

/* Les quatre branches : deux fonds, l'un couche, l'autre debout. */
.portail-eclat::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to right,
      rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.85) 50%,
      rgba(255, 255, 255, 0) 100%) center / 100% 7% no-repeat,
    linear-gradient(to bottom,
      rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.85) 50%,
      rgba(255, 255, 255, 0) 100%) center / 7% 100% no-repeat;
}

/* Les trois pixels sont un ajustement OPTIQUE sur le cristal : ils
   doivent valoir autant a toute taille de scene, d'ou des pixels et non
   un pourcentage. */
.portail-eclat-g { left: var(--axe-cristal); top: calc(63.9% - 3px); }
.portail-eclat-d {
  left: calc(100% - var(--axe-cristal));
  top: calc(66.4% - 3px);
  /* Un autre cycle et un autre retard : deux eclats synchrones se
     liraient comme un clignotant, non comme deux reflets. */
  animation-duration: 4.3s;
  animation-delay: -1.85s;
}

@keyframes portail-scintille {
  0%, 88%  { opacity: 0; transform: translate(-50%, -50%) scale(0.45) rotate(0deg); }
  91%      { opacity: 1; transform: translate(-50%, -50%) scale(1) rotate(10deg); }
  95%      { opacity: 0.3; transform: translate(-50%, -50%) scale(1.3) rotate(18deg); }
  100%     { opacity: 0; transform: translate(-50%, -50%) scale(0.5) rotate(24deg); }
}

/* Les braseros respirent : la flamme bleue monte et retombe. */
.portail-brasero-g {
  left: var(--axe-brasero);
  bottom: 23%;
  height: 19%;
  transform: translateX(-50%);
}
.portail-brasero-d {
  right: var(--axe-brasero);
  bottom: 23%;
  height: 19%;
  transform: translateX(50%);
}

/*
   LES FLAMMES, QUATRE INSTANTS EN BANDE. La planche est haute d'une
   seule cellule et large de quatre, et chacun de ses instants est tenu
   par un calque distinct - voir plus bas pourquoi.

   En pourcentage, la position d'un fond se compte sur la difference entre
   l'image et son cadre - ici 300 % - de sorte que les quatre cellules
   tombent a 0, 33,3, 66,7 et 100 %. Ce sont ces quatre valeurs que les
   calques se partagent.

   Leur bas se pose a la levre de la coupe, soit 34 % de la hauteur de la
   scene : le brasero monte de 23 a 42 %, et sa flamme en partait.
*/
.portail-flamme {
  bottom: 34%;
  height: 9.5%;
  aspect-ratio: 1;
  transform: translateX(-50%);
  mix-blend-mode: screen;
  pointer-events: none;
}

/*
   QUATRE CALQUES, UN PAR INSTANT, et un fondu entre eux.

   `steps(4)` sautait d'une cellule a la suivante : par construction il
   n'y a rien entre deux pas, donc aucun fondu possible. Animer la
   position en continu n'aurait pas donne un fondu mais un GLISSEMENT -
   deux flammes defilant cote a cote.

   Chaque calque est donc FIGE sur son instant, et seule son opacite
   bouge : elle descend de 1 a 0 pendant le quart qui suit son tour et
   remonte pendant le quart qui le precede. Les pentes etant lineaires et
   complementaires, deux calques voisins se relaient sans creux.

   Les quatre courbes sont identiques : un simple retard negatif les
   decale. Il se calcule sur la duree, qui differe d'un cote a l'autre.

   LA PENTE RESTE LINEAIRE. Une courbe adoucie - `ease-in-out` - garde
   bien la somme des opacites a 1, puisqu'elle est symetrique autour de
   son milieu ; mais elle ralentit AUX PICS et accelere AU MILIEU, de
   sorte que chaque image serait tenue plus longtemps avant de basculer
   vite. C'est l'inverse d'un fondu etale.

   Et le fondu n'a pas de reglage propre : aucun calque ne tient de
   palier, la transition occupe donc tout le cycle, et l'allonger revient
   exactement a la ralentir.
*/
.portail-flamme i {
  position: absolute;
  inset: 0;
  background-size: 400% 100%;
  background-repeat: no-repeat;
  animation: portail-flamme var(--duree) linear infinite;
}

.portail-flamme i:nth-child(1) { background-position-x: 0%; }
.portail-flamme i:nth-child(2) {
  background-position-x: 33.333%;
  animation-delay: calc(var(--duree) * -0.75);
}
.portail-flamme i:nth-child(3) {
  background-position-x: 66.667%;
  animation-delay: calc(var(--duree) * -0.5);
}
.portail-flamme i:nth-child(4) {
  background-position-x: 100%;
  animation-delay: calc(var(--duree) * -0.25);
}

.portail-flamme-g {
  --duree: 6.8s;
  left: var(--axe-brasero);
}
.portail-flamme-g i { background-image: url('effets/flamme_nord.webp'); }

.portail-flamme-d {
  /* Une autre duree : les deux ne doivent pas battre ensemble, sinon le
     decor clignote. Sans rapport simple entre elles, les deux ne
     retombent jamais en phase. */
  --duree: 7.6s;
  left: calc(100% - var(--axe-brasero));
}
.portail-flamme-d i { background-image: url('effets/flamme_sud.webp'); }

@keyframes portail-flamme {
  0%        { opacity: 1; }
  25%, 75%  { opacity: 0; }
  100%      { opacity: 1; }
}

.portail-brasero-g,
.portail-brasero-d {
  animation: portail-souffle 4.2s ease-in-out infinite;
}
.portail-brasero-d { animation-delay: -2.1s; }

@keyframes portail-souffle {
  0%, 100% { filter: brightness(1); }
  50%      { filter: brightness(1.3); }
}

/* ─── 5. les bannieres ──────────────────────────────────────────────── */
/*
   Elles ondulent lentement, pivotant depuis leur hampe : c'est le seul
   mouvement qui trahisse un peu de vent, et il suffit a sortir la scene
   de l'image fixe.
*/
.portail-banniere { top: 21%; height: 38%; width: auto; transform-origin: 50% 0; }

/*
   LE RECENTRAGE PASSE PAR UNE VARIABLE. L'animation ci-dessous ecrit
   `transform`, donc elle ecraserait un translateX pose ici : les images
   cles reprennent `--mi`, que chaque cote decline. Le transform de base
   le porte aussi, pour le cas ou `prefers-reduced-motion` coupe
   l'animation - la banniere resterait sinon decalee d'une demi-largeur.
*/
.portail-banniere-g {
  left: var(--axe-piliers);
  --mi: -50%;
  transform: translateX(-50%);
  animation: portail-flotte 6.5s ease-in-out infinite;
}
.portail-banniere-d {
  right: var(--axe-piliers);
  --mi: 50%;
  transform: translateX(50%);
  animation: portail-flotte 6.5s ease-in-out infinite reverse;
}

@keyframes portail-flotte {
  0%, 100% { transform: translateX(var(--mi)) rotate(-1.1deg) skewX(0.8deg); }
  50%      { transform: translateX(var(--mi)) rotate(1.1deg) skewX(-0.8deg); }
}

/* ─── 6. l'arche, et ce qui vit dedans ──────────────────────────────── */

.portail-arche-boite {
  left: 50%;
  bottom: 30%;
  height: 62%;
  aspect-ratio: 1100 / 1100;   /* les pixels de l'image, recadree */
  transform: translateX(-50%);
}

.portail-arche-boite > * { position: absolute; inset: 0; width: 100%; height: 100%; }

/* Le paysage vu au travers : present des le debut, mais cache par le
   vortex. A l'ouverture, le vortex s'efface et il apparait.
   La decoupe suit l'ovale mesure, pas un cercle. */
/*
   LA CITE N'EXISTE QUE POUR LE PORTAIL OUVERT. Tant qu'il dort,
   l'ouverture reste TRANSPARENTE et laisse paraitre le decor general :
   montrer la cite par avance, c'etait reveler ce que le portail est
   cense ouvrir.
*/
.portail-travers {
  object-fit: cover;
  clip-path: ellipse(var(--ouv-rx) var(--ouv-ry) at var(--ouv-cx) var(--ouv-cy));
  opacity: 0;
  transition: opacity 2.4s ease-in;
}

.portail.est-ouvert .portail-travers { opacity: 0.92; }

.portail-arche { object-fit: contain; }

/* ─── Le vortex : des textures empilees ─────────────────────────────── */
/*
   TOUT EST COMPOSE EN « screen », et c'est pour cela que les effets sont
   livres sur fond NOIR : ce mode annule le noir et ne garde que la lumiere.
   Un detourage aurait tranche les degrades de lueur, qui font tout leur
   interet.

   TROIS COUCHES TOURNENT A DES VITESSES DIFFERENTES, dans des sens
   opposes. C'est ce decalage qui donne la profondeur : une seule image,
   meme animee, tournerait comme un disque.

   LEUR INTENSITE SUIT --p, la puissance du portail, de 0 a 1. Le script ne
   pose que cette variable ; tout le reste se calcule ici.
*/
.portail-vortex {
  pointer-events: none;
  clip-path: ellipse(var(--ouv-rx) var(--ouv-ry) at var(--ouv-cx) var(--ouv-cy));
}

.portail-vortex img {
  position: absolute;
  left: var(--ouv-cx);
  top: calc(var(--ouv-cy) - var(--vortex-dy));
  width: calc(var(--ouv-rx) * 2.16);
  height: auto;
  mix-blend-mode: screen;
  transform-origin: 50% 50%;
  will-change: transform, opacity;
}

.pv-anneau {
  opacity: calc(0.12 + var(--p, 0) * 0.88);
  animation: pv-tourne calc(26s - var(--p, 0) * 14s) linear infinite;
}

.pv-spirale {
  width: calc(var(--ouv-rx) * 2.0);
  opacity: calc(0.08 + var(--p, 0) * 0.82);
  animation: pv-tourne-envers calc(18s - var(--p, 0) * 11s) linear infinite;
}

/* Le coeur ne monte qu'a la fin : son opacite suit le CARRE de la
   puissance, si bien qu'il reste discret longtemps puis s'embrase. */
.pv-coeur {
  width: calc(var(--ouv-rx) * 1.36);
  opacity: calc(var(--p, 0) * var(--p, 0));
  animation: pv-bat calc(5s - var(--p, 0) * 2.6s) ease-in-out infinite;
}

/* Les runes debordent de l'ouverture : elles vivent hors du decoupage. */
.portail-runes {
  position: absolute;
  left: var(--ouv-cx);
  top: calc(var(--ouv-cy) - 5px);
  width: calc(var(--ouv-rx) * 2.58);
  height: auto;
  mix-blend-mode: screen;
  transform-origin: 50% 50%;
  pointer-events: none;
  opacity: calc(max(0, var(--p, 0) - 0.22) * 1.25);
  animation: pv-tourne-envers 40s linear infinite;
}

@keyframes pv-tourne {
  from { transform: translate(-50%, -50%) rotate(0deg); }
  to   { transform: translate(-50%, -50%) rotate(360deg); }
}

@keyframes pv-tourne-envers {
  from { transform: translate(-50%, -50%) rotate(360deg); }
  to   { transform: translate(-50%, -50%) rotate(0deg); }
}

@keyframes pv-bat {
  0%, 100% { transform: translate(-50%, -50%) scale(1); }
  50%      { transform: translate(-50%, -50%) scale(1.14); }
}

/*
   A L'OUVERTURE, LE VORTEX S'APAISE SANS S'ETEINDRE. Le couper net
   laissait un trou inerte, comme si le passage s'etait referme ; il
   subsiste un halo tournant, assez faible pour que la cite se lise au
   travers et assez vivant pour qu'on sache que le passage est actif.

   Les runes, elles, s'effacent tout a fait : elles annoncaient une
   ouverture a venir, elles n'ont plus rien a dire une fois ouvert.
*/
.portail.est-ouvert .portail-vortex {
  opacity: 0.26;
  transition: opacity 2.2s ease-out;
}

/* Le coeur est la seule couche assez dense pour masquer la cite. */
.portail.est-ouvert .pv-coeur { opacity: 0; }

/* Un portail qu'on vient de forcer s'apaise : il ne tourbillonne plus au
   rythme de la montee en puissance. */
.portail.est-ouvert .pv-anneau  { animation-duration: 44s; }
.portail.est-ouvert .pv-spirale { animation-duration: 31s; }

.portail.est-ouvert .portail-runes { opacity: 0; transition: opacity 1.6s ease-out; }

/* ─── 7. les mages ──────────────────────────────────────────────────── */

.portail-mage {
  bottom: 24%;
  height: 36%;
  width: auto;
  pointer-events: none;
}

.portail-mage-g { left: 17%; }
.portail-mage-d { right: 17%; }

.portail-mage-garde { opacity: 0; transition: opacity 2s ease-in; }
.portail-mage-canal { opacity: 1; transition: opacity 1.4s ease-out; }

.portail.est-ouvert .portail-mage-garde { opacity: 1; }
.portail.est-ouvert .portail-mage-canal { opacity: 0; }

/* ─── 8. le canvas d'ambiance ───────────────────────────────────────── */

.portail-canvas { inset: 0; width: 100%; height: 100%; pointer-events: none; }

/* ─── 9. les rayons de canalisation ─────────────────────────────────── */
/*
   ILS SONT TRACES AU CANEVAS, et non plus poses en image. Une planche
   porte un trait DROIT dans un rectangle : etirable, pivotable, mais pas
   courbable. Le trace par programme donne des brins qui ondulent, des
   noeuds de lumiere qui courent vers le portail et des ramifications
   breves - et il suit l'angle reel, qui varie de pres de 9 degres selon
   le ratio de la scene.

   Tout le dessin vit dans le script ; il ne reste ici que le plan et la
   montee en intensite.
*/
.portail-rayons {
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  /* LE MEME DECALAGE D'UN CRAN que dans le script : en y portant
     p' = 0,50 + 0,95 p, l'expression 0,22 + 0,78 p' devient celle-ci.
     A p = 0 elle vaut 0,61 - ce que l'accumulation valait - et elle
     sature avant l'ouverture, ce que le navigateur borne de lui-meme. */
  opacity: calc(0.61 + var(--p, 0) * 0.741);
}

/* Les mages cessent de canaliser a l'ouverture. */
.portail.est-ouvert .portail-rayons { opacity: 0; transition: opacity 1.2s ease-out; }

/* ─── 10. l'onde d'ouverture ────────────────────────────────────────── */
/*
   Elle ne joue QU'UNE FOIS, a la seconde zero, et le script la declenche
   en posant une classe. Une animation permanente la rejouerait a chaque
   passage, ce qui lui oterait tout son sens.
*/
.portail-onde {
  left: 50%;
  top: 40.8%;
  width: 34%;
  height: auto;
  mix-blend-mode: screen;
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, -50%) scale(0.2);
}

.portail.joue-ouverture .portail-onde { animation: portail-deflagration 2.8s ease-out forwards; }

@keyframes portail-deflagration {
  0%   { opacity: 0;    transform: translate(-50%, -50%) scale(0.2); }
  14%  { opacity: 1;    transform: translate(-50%, -50%) scale(0.75); }
  100% { opacity: 0;    transform: translate(-50%, -50%) scale(2.1); }
}

/* ─── 11. le logo du site ──────────────────────────────────────────── */
/*
   IL VIENT DE L'ANCIEN HERO, que le portail remplace, ET IL SE TIENT DANS
   L'ANGLE. Au centre il disputait la scene au portail, qui en est le
   sujet ; dans le coin il signe la page sans la concurrencer.

   Il n'a plus a composer avec le cristal de l'arche, ce qui permet de le
   reduire franchement : le bandeau a une proportion de 2,884, donc a
   10,5 % de largeur il n'occupe qu'environ 8 % de la hauteur.

   La banniere du Nord commence a 21 % de hauteur : le logo, qui s'arrete
   vers 11 %, passe au-dessus d'elle sans la toucher.
*/
.portail-logo {
  top: 3%;
  left: 2.5%;
  width: min(10.5%, 215px);
  min-width: 128px;
  height: auto;
  pointer-events: none;
  filter: drop-shadow(0 2px 14px rgba(2, 6, 14, 0.85))
          drop-shadow(0 0 26px rgba(111, 195, 255, 0.3));
}

/* ─── 12. le texte ──────────────────────────────────────────────────── */

.portail-voile {
  inset: auto 0 0 0;
  height: 34%;
  background: linear-gradient(to bottom,
              rgba(4, 7, 13, 0) 0%, rgba(4, 7, 13, 0.45) 34%, rgba(4, 7, 13, 0.88) 78%);
  pointer-events: none;
}

.portail-hud {
  inset: auto 0 0 0;
  padding: 0 16px 1.6%;
  text-align: center;
}

/*
   LE VOILE DU TITRE DEBORDE DE SON BANDEAU. Pose sur le bandeau lui-meme,
   il se coupait net : un degrade s'arrete au bord de son element, et
   l'ellipse valait encore une demi-opacite en y arrivant. Ici elle
   s'eteint a 82 % de son rayon, bien avant les limites du pseudo, et le
   flou fond ce qui resterait de transition.

   Son centre tombe sur la ligne du titre : le pseudo s'etendant de -38 %
   a +108 % du bandeau, un centre a 34 % de sa hauteur revient a 12 % de
   celle du bandeau.
*/
.portail-hud::before {
  content: '';
  position: absolute;
  inset: -38% -6% -8% -6%;
  background: radial-gradient(ellipse 42% 36% at 50% 34%,
              rgba(2, 6, 14, 0.66) 0%,
              rgba(2, 6, 14, 0.30) 52%,
              rgba(2, 6, 14, 0) 82%);
  filter: blur(26px);
  pointer-events: none;
}

/* Le pseudo venant avant le contenu, les enfants remontent d'un cran. Un
   z-index negatif les aurait laisses en paix, mais aurait aussi envoye le
   voile derriere le decor : rien ici ne cree de contexte d'empilement. */
.portail-hud > * { position: relative; z-index: 1; }

.portail-royaume {
  margin: 0;
  font-family: var(--font-title, 'Cinzel', Georgia, serif);
  font-size: clamp(1.6rem, 2.7vw, 2.4rem);
  font-weight: 800;
  letter-spacing: 0.17em;
  color: #fff;
  /* Le halo bleu porte l'ambiance ; les trois ombres sombres et SERREES
     qui suivent portent la lisibilite. Sur la crete enneigee, le seul
     halo laissait le titre se fondre dans le blanc. */
  text-shadow:
    0 0 24px rgba(111, 195, 255, 0.8),
    0 0 7px rgba(2, 6, 14, 0.95),
    0 2px 10px rgba(2, 6, 14, 0.95),
    0 1px 3px rgba(2, 6, 14, 1);
}

.portail-accroche {
  margin: 1px 0 9px;
  font-size: 1rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--or-clair);
  /* Un or clair sur de la neige, c'est un ton sur ton : sans ces ombres,
     la ligne disparait des que la montagne passe derriere. */
  text-shadow:
    0 0 6px rgba(2, 6, 14, 0.95),
    0 1px 3px rgba(2, 6, 14, 1),
    0 2px 9px rgba(2, 6, 14, 0.9);
}

/* ─── Le compte a rebours ───────────────────────────────────────────── */
/*
   LE CADRE EST UNE IMAGE, LE TEXTE EST DU HTML. L'habillage a ete demande
   VIDE de tout caractere, et les chiffres se posent dedans : ils restent
   ainsi traduisibles, lisibles aux lecteurs d'ecran et nets a toute taille.
   Peints dans l'image, il aurait fallu la regenerer a chaque langue.

   LES CASES SONT POSEES EN ABSOLU, ET NON REPARTIES PAR FLEX DANS UN
   REMBOURRAGE. Un pourcentage de padding se rapporte en CSS a la largeur du
   PARENT, jamais a celle de l'element : les 8,5 % d'avant valaient environ
   159 px de chaque cote et, faute de box-sizing, s'ajoutaient a la largeur.
   Le cadre mesurait 773 px pour 455 px de contenu, et les chiffres se
   resserraient au centre pendant que l'image s'etirait sur toute la largeur.

   TOUT EST RELEVE SUR L'IMAGE, Y COMPRIS LA HAUTEUR. Le cadre porte des
   ornements qui n'ont aucune raison d'etre symetriques, et ils ne le sont
   pas : la zone bleue va de y=72 a y=199 sur 236, soit un centre a
   57,42 % et non a 50 %. Centrer sur le cadre posait donc les chiffres
   7,4 points trop haut.

     bord interieur    7,2 %                     92,3 %
     separateurs              29,0 / 50,1 / 71,2 %
     centre de l'encart       57,42 % de la hauteur
*/
.portail-compte {
  position: relative;
  display: block;
  width: min(38%, 560px);
  min-width: 320px;
  margin: 0 auto;
  aspect-ratio: 900 / 236;
  background: url('ui/cadre.webp') center / 100% 100% no-repeat;
}

.portail-case {
  position: absolute;
  top: 57.42%;             /* le centre de l'encart, mesure - pas 50 % */
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  white-space: nowrap;
}

/* Abscisses relevees sur l'image du cadre, bord a bord entre separateurs. */
.portail-case:nth-of-type(1) { left: 7.2%;  width: 21.8%; }
.portail-case:nth-of-type(2) { left: 29.0%; width: 21.1%; }
.portail-case:nth-of-type(3) { left: 50.1%; width: 21.1%; }
.portail-case:nth-of-type(4) { left: 71.2%; width: 21.1%; }

.portail-nombre {
  font-size: clamp(1.4rem, 2.1vw, 1.9rem);
  font-weight: 700;
  line-height: 1.1;
  color: #fff;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 14px rgba(111, 195, 255, 0.85);
}

.portail-unite {
  font-size: 1rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--or-clair);
}

.portail-legende { margin: 8px 0 0; font-size: 1rem; color: #c3d2e6; }

/* Meme principe pour le bouton : l'habillage est une image vide, le libelle
   est du texte. Il se traduit, se selectionne, et reste net. */
.portail-bouton {
  display: none;
  align-items: center;
  justify-content: center;
  width: min(30%, 400px);
  min-width: 240px;
  margin: 8px auto 0;
  aspect-ratio: 760 / 129;
  background: url('ui/bouton.webp') center / 100% 100% no-repeat;
  font-family: var(--font-title, 'Cinzel', Georgia, serif);
  font-size: clamp(1rem, 1.5vw, 1.3rem);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-align: center;
  text-decoration: none;
  text-shadow: 0 0 14px rgba(0, 0, 0, 0.75);
  color: #fff;
  transition: transform 0.2s ease, filter 0.2s ease;
}

.portail-bouton:hover {
  transform: translateY(-2px) scale(1.02);
  filter: brightness(1.22);
  color: #fff;
}

.portail.est-ouvert .portail-compte,
.portail.est-ouvert .portail-legende { display: none; }
.portail.est-ouvert .portail-bouton { display: flex; }

/* ─── Petits ecrans ─────────────────────────────────────────────────── */
/*
   On ne recadre rien : la scene etant composee, il suffit de resserrer ses
   pieces. Le format passe au 4:3, l'arche grandit, et le decor lointain
   s'efface pour ne pas encombrer.
*/
@media (max-width: 860px) {
  .portail {
    --ratio: 4 / 3;
    /* Le format se resserre : les axes suivent. */
    --axe-cristal: 28.5%;
    --axe-brasero: 10.5%;
  }

  /* Les piliers et leurs bannieres disparaissent : ils mangeraient la
     moitie de la largeur. Les cristaux restent, au pied de l'arche. */
  .portail-colonne-g, .portail-colonne-d,
  .portail-banniere-g, .portail-banniere-d { display: none; }

  .portail-cristal-g,
  .portail-cristal-d { bottom: 33%; height: 8%; }
  .portail-eclat { width: 2.6%; }
  /* La scene passe en 4:3 : le logo garde sa part. */
  .portail-logo { top: 2%; left: 3%; width: 30%; min-width: 0; }
  .portail-eclat-g { top: calc(61% - 3px); }
  .portail-eclat-d { top: calc(62.5% - 3px); }

  .portail-arche-boite { height: 48%; bottom: 34%; }

  .portail-mage { height: 24%; bottom: 30%; }
  .portail-mage-g { left: 1%; }
  .portail-mage-d { right: 1%; }

  .portail-brasero-g,
  .portail-brasero-d { bottom: 30%; height: 14%; }
  .portail-flamme { bottom: 38%; height: 7%; }


  .portail-voile { height: 40%; }
  .portail-compte { width: 94%; min-width: 0; }
  .portail-bouton { width: 78%; min-width: 0; }
}

/* ─── Mouvement reduit ──────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .portail-banniere-g, .portail-banniere-d,
  .portail-brasero-g, .portail-brasero-d { animation: none; }
  .portail-mage-garde, .portail-mage-canal { transition: none; }
  .portail.joue-ouverture .portail-flash { animation: none; }
}
