/* style.css — Mise en page pour l'interface complète du jeu : écrans superposés au
   canvas, HUD en cours de partie, canvas centré et responsive. Habillage cyberpunk
   (phase 4A) : fond bleu-nuit assorti à Config.COULEURS.fond (carte.js), touches de
   lueur néon (text-shadow / box-shadow) sur les éléments actifs ou sélectionnés —
   jamais en remplacement des distinctions déjà en place (fond + liseré, jamais la
   couleur seule), seulement en renfort visuel. */

* {
    box-sizing: border-box;
}

/* `display: flex` sur .ecran-superpose et .barre-hud (styles d'auteur) prime sinon
   sur le `display: none` que le navigateur applique par défaut à [hidden] (style
   agent utilisateur) : sans cette règle, un écran ou le HUD masqués via
   `element.hidden = true` resteraient visibles en même temps que les autres. */
[hidden] {
    display: none !important;
}

body {
    margin: 0;
    padding: 16px;
    background: #0b0b14;
    color: #e8e8ec;
    font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}

/* Décor d'arrière-plan en parallaxe (phase 7C, decor.js) : un second canvas
   indépendant du canvas de jeu, épinglé derrière tout le reste de la page. `position:
   fixed` + `inset: 0` le fait couvrir tout le viewport ; `width`/`height: 100%` sont
   nécessaires en plus (un <canvas> est un élément remplacé, `inset` seul ne suffit pas
   à l'étirer comme il le ferait pour une boîte ordinaire à dimensions automatiques).
   `z-index: -1` suffit à le faire passer derrière tout le reste du contenu de `body`
   (aucun de ses autres enfants directs — <h1>, #bouton-son, .conteneur-canvas, etc. —
   n'a de z-index propre ni de position qui créerait un contexte d'empilement séparé,
   donc ce z-index négatif s'applique bien dans le contexte d'empilement racine de la
   page entière, pas seulement localement). Le canvas de jeu, lui, garde son fond
   opaque habituel (depuis la phase 1A, renforcé en 4A) : ce décor n'est donc visible
   que dans les marges qui entourent .conteneur-canvas — plus larges sur desktop, quasi
   absentes sous 900px de large où .conteneur-canvas occupe déjà toute la largeur
   disponible. Redimensionné indépendamment du canvas de jeu par Decor.redimensionner()
   (voir decor.js), sur son propre écouteur resize. */
#canvas-decor {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: -1;
    display: block;
}

/* Image de fond fixe (phase 7C bis) : positionnée exactement comme #canvas-decor
   ci-dessus (`position: fixed; inset: 0`, plutôt que `position: absolute` — pour
   couvrir tout le viewport, y compris pendant un défilement de page, exactement comme
   le canvas de décor qu'elle recouvre), un niveau au-dessus de lui et en dessous de
   `.conteneur-canvas` : même `z-index: -1`, l'ordre entre les deux vient alors de leur
   ordre dans le DOM (canvas d'abord, image ensuite, voir index.html), pas d'un
   `z-index` distinct. `object-fit: cover` pour remplir la zone sans déformer l'image
   quel que soit son ratio d'origine. Masquée par défaut (`opacity: 0`) : le skyline
   procédural en dessous reste seul visible tant que l'image ne s'est pas chargée avec
   succès (voir Decor.initialiserImageFond, decor.js, qui ajoute `.image-decor--visible`
   sur l'événement `load`) — la transition ne fait qu'adoucir cette apparition, jamais
   utilisée pour masquer une erreur de chargement. `pointer-events: none` : purement
   décorative, ne doit jamais intercepter un clic destiné au jeu en dessous. */
.image-decor {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0;
    transition: opacity 0.6s ease;
    pointer-events: none;
    z-index: -1;
}

.image-decor--visible {
    opacity: 1;
}

/* Voile sombre entre l'image de fond et le plateau de jeu (phase 7C bis) : une photo
   réaliste en pleine luminosité nuirait au contraste de l'interface néon posée
   par-dessus (même principe qu'en phase 4A : la lisibilité du jeu passe avant
   l'esthétique du décor). Même teinte que Config.COULEURS.fond (#0b0b14 = rgb(11, 11,
   20)) à 50 % d'opacité, plutôt qu'un nouvel objet Config.PALETTE qui n'existe pas
   dans ce dépôt (voir l'écart documenté dans ARCHITECTURE.md). Toujours présent, pas
   seulement quand l'image est visible : sans effet perceptible tant que
   .image-decor reste à opacity 0 (il assombrit alors uniquement le skyline
   procédural, d'une teinte déjà proche de la sienne), donc rien à conditionner ici. */
.voile-decor {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    background: rgba(11, 11, 20, 0.5);
    pointer-events: none;
    z-index: -1;
}

h1 {
    /* Seul titre de la page (l'écran d'accueil n'en a plus de doublon, voir
       index.html) : sensiblement plus grand que les <h2> des écrans superposés
       (Victoire/Défaite) pour bien se lire comme LE titre, pas un sous-titre. */
    font-size: 2rem;
    margin: 0;
    text-align: center;
    letter-spacing: 0.02em;
    color: #00e5ff;
    text-shadow: 0 0 8px rgba(0, 229, 255, 0.6);
}

h2 {
    font-size: 1.4rem;
    margin: 0;
    color: #00e5ff;
    text-shadow: 0 0 6px rgba(0, 229, 255, 0.5);
}

.info-graine {
    font-size: 0.9rem;
    color: #a0a0aa;
}

/* Barre du HUD en cours de partie : mêmes contraintes que les autres barres, avec
   les boutons Lancer la vague / Pause / Vitesse. */
.barre-hud {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 12px;
    width: 100%;
    max-width: 900px;
    font-size: 0.9rem;
}

#bouton-lancer-vague,
#bouton-pause,
#bouton-vitesse,
#bouton-son {
    min-height: 44px;
    padding: 0 16px;
    font-size: 0.95rem;
    background: #00e5ff;
    color: #10120f;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    font-weight: 600;
    box-shadow: 0 0 8px rgba(0, 229, 255, 0.4);
}

#bouton-lancer-vague:disabled {
    background: #3a3a42;
    color: #7a7a84;
    cursor: not-allowed;
}

#bouton-pause,
#bouton-vitesse {
    background: #f1c40f;
}

.message-jeu {
    color: #e74c3c;
    font-weight: 600;
}

/* Barre de sélection du type de tour à construire (phase 2A), affichée sous le HUD.
   Même principe de mise en évidence que .choix-duree : fond ET liseré distincts pour
   le type actif, jamais une teinte seule (lisibilité aux personnes daltoniennes). */
.barre-types-tours {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px;
    width: 100%;
    max-width: 900px;
}

.barre-types-tours button {
    min-height: 44px;
    padding: 0 16px;
    font-size: 0.9rem;
    background: #2a2a30;
    color: #e8e8ec;
    border: 2px solid transparent;
    border-radius: 6px;
    cursor: pointer;
    font-weight: 600;
}

.barre-types-tours button.selectionne {
    background: #2f4a5a;
    border-color: #00e5ff;
    box-shadow: 0 0 10px rgba(0, 229, 255, 0.5);
}

.barre-types-tours button:disabled {
    background: #3a3a42;
    color: #7a7a84;
    cursor: not-allowed;
}

/* Le conteneur porte la largeur maximale et sert d'ancrage de positionnement aux
   écrans superposés (accueil, victoire, défaite). Le canvas prend 100% de sa largeur
   en CSS mais ses attributs width/height (fixés en JS) définissent la vraie
   résolution de dessin, pour éviter tout flou dû à un étirement. */
.conteneur-canvas {
    position: relative;
    width: 100%;
    max-width: 900px;
}

/* Sous env. 480 px de large, le canvas (ratio fixe 20:12) devient si bas que le
   contenu de l'écran d'accueil — le plus dense des trois écrans superposés — déborderait
   de sa boîte et chevaucherait ce qui se trouve juste au-dessus dans le flux normal de
   la page (le <h1>, et le bouton Son depuis la phase 4B) : les écrans superposés sont
   centrés verticalement par flexbox dans une boîte `inset: 0` calée sur la hauteur du
   canvas, et un contenu plus haut que cette boîte déborde de façon symétrique, aussi
   bien en haut qu'en bas, sans qu'`overflow` ne le limite.
   Cette valeur (initialement 420px, phase 1D) a été mesurée insuffisante : l'écran
   d'accueil a grossi depuis (niveau/XP et liste des cinq paliers de bonus permanents,
   phases 3A/3B) sans que cette hauteur minimale n'ait été révisée en conséquence —
   c'est ce qui produisait, en pratique, le chevauchement du bouton Son observé sur
   mobile (à tort attribué à un positionnement propre au bouton : il n'a jamais eu de
   `position: fixed`/`absolute`, voir son style partagé avec les autres boutons du HUD
   plus haut). Mesuré à nouveau à 360px et 320px (son contenu ne dépend pas de la
   largeur à ces deux tailles, les mêmes quatre boutons de durée y passent déjà sur
   deux lignes) : 461px de contenu réel, d'où cette marge. */
@media (max-width: 480px) {
    .conteneur-canvas {
        min-height: 500px;
    }
}

#canvas-jeu {
    display: block;
    width: 100%;
    height: auto;
    /* Empêche le geste de défilement tactile de « voler » les interactions avec la
       grille (pose de tours au tap). */
    touch-action: none;
    border-radius: 4px;
}

/* Panneau d'amélioration/vente d'une tour sélectionnée (phase 2B). Positionné dans un
   coin fixe du plateau (le conteneur du canvas est déjà en position: relative) plutôt
   que de suivre la tour cliquée, comme demandé : plus simple et tout aussi lisible. */
.panneau-amelioration {
    position: absolute;
    top: 8px;
    right: 8px;
    max-width: 220px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px 12px;
    background: rgba(11, 11, 20, 0.92);
    border: 2px solid #00e5ff;
    border-radius: 6px;
    box-shadow: 0 0 12px rgba(0, 229, 255, 0.35);
    text-align: left;
    font-size: 0.85rem;
}

.panneau-amelioration h3 {
    margin: 0;
    font-size: 1rem;
}

.panneau-amelioration p {
    margin: 0;
}

.panneau-amelioration button {
    min-height: 40px;
    padding: 0 12px;
    font-size: 0.85rem;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    font-weight: 600;
}

#bouton-ameliorer {
    background: #00e5ff;
    color: #10120f;
}

#bouton-ameliorer:disabled {
    background: #3a3a42;
    color: #7a7a84;
    cursor: not-allowed;
}

#panneau-niveau-max {
    color: #f1c40f;
    font-weight: 600;
}

#bouton-vendre {
    background: #e74c3c;
    color: #10120f;
}

/* Écrans superposés au canvas (accueil, victoire, défaite) : un seul à la fois est
   visible, les autres portent l'attribut `hidden` (basculé par
   Interface.mettreAJourEcrans). */
.ecran-superpose {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 16px;
    padding: 16px;
    background: rgba(16, 16, 18, 0.92);
    border-radius: 4px;
    text-align: center;
}

.choix-duree {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px;
    max-width: 100%;
}

.choix-duree button {
    min-height: 44px;
    padding: 0 16px;
    font-size: 0.95rem;
    background: #2a2a30;
    color: #e8e8ec;
    /* Bordure transparente par défaut plutôt qu'absente, pour que le passage à
       .selectionne ne fasse pas sauter la taille du bouton. */
    border: 2px solid transparent;
    border-radius: 6px;
    cursor: pointer;
    font-weight: 600;
}

/* Le bouton actif se distingue par un fond ET un liseré coloré (pas seulement une
   teinte différente), pour rester lisible aux personnes daltoniennes. */
.choix-duree button.selectionne {
    background: #2f4a5a;
    border-color: #00e5ff;
    box-shadow: 0 0 10px rgba(0, 229, 255, 0.5);
}

/* Niveau et barre d'XP du joueur (phase 3A), affichés sur l'écran d'accueil. */
.progression-joueur {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    width: 100%;
    max-width: 260px;
}

.niveau-joueur {
    margin: 0;
    font-weight: 600;
}

.barre-xp-conteneur {
    width: 100%;
    height: 10px;
    background: #2a2a30;
    border-radius: 5px;
    overflow: hidden;
}

.barre-xp-remplissage {
    height: 100%;
    background: #00e5ff;
    box-shadow: 0 0 6px rgba(0, 229, 255, 0.6);
    /* La largeur (pourcentage de xpActuelle / seuil du niveau) est fixée en JS par
       Interface.mettreAJourProgressionAccueil. */
    width: 0%;
}

.texte-niveau-max-joueur {
    margin: 0;
    font-size: 0.85rem;
    color: #f1c40f;
    font-weight: 600;
}

/* Liste des paliers de bonus permanents (phase 3B), sous la barre d'XP. Débloqué vs
   verrouillé se distingue par la couleur ET par le symbole (✓ contre 🔒) — jamais la
   couleur seule, même principe que partout ailleurs dans l'interface. */
.liste-paliers-bonus {
    list-style: none;
    margin: 4px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
    width: 100%;
    font-size: 0.78rem;
    text-align: left;
}

.liste-paliers-bonus li {
    padding: 4px 8px;
    border-radius: 4px;
    background: #1a1a1e;
}

.liste-paliers-bonus li.palier-debloque {
    color: #2ecc71;
    font-weight: 600;
}

.liste-paliers-bonus li.palier-verrouille {
    color: #7a7a84;
}

/* Mention de passage de niveau sur les écrans de victoire/défaite : suffisamment
   visible pour ne pas passer inaperçue, sans pour autant bloquer la lecture du reste
   de l'écran (même principe de mise en évidence que .vague-atteinte.score-sansfin). */
.niveau-superieur {
    margin: 0;
    font-weight: 700;
    color: #f1c40f;
}

.description-duree {
    color: #a0a0aa;
    font-size: 0.9rem;
    margin: 0;
    min-height: 1.2em;
}

.bouton-principal,
.bouton-secondaire {
    min-height: 44px;
    padding: 0 24px;
    font-size: 1rem;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    font-weight: 600;
}

.bouton-principal {
    background: #39ff88;
    color: #10120f;
    box-shadow: 0 0 10px rgba(57, 255, 136, 0.5);
}

.bouton-principal:hover {
    background: #29e070;
}

.bouton-secondaire {
    background: #3a3a42;
    color: #e8e8ec;
}

.boutons-fin-partie {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px;
}

/* Met en évidence la vague atteinte à l'écran de défaite quand elle constitue le
   score final du joueur (mode Sans fin) plutôt qu'une simple statistique parmi
   d'autres. */
.vague-atteinte.score-sansfin {
    font-size: 1.5rem;
    font-weight: 700;
    color: #f1c40f;
}

/* Mode paysage mobile (contenu additionnel post-lancement) : la mise en page
   habituelle empile tout verticalement (titre, bouton Son, canvas, HUD, barre de
   tours), pensée pour un écran plus haut que large. En paysage sur téléphone, c'est
   l'inverse (large mais bas) : le canvas, dimensionné jusqu'ici sur la seule largeur
   disponible (voir Jeu.redimensionner, jeu.js), déborderait largement de la hauteur
   réelle de l'écran, forçant à faire défiler la page pendant la partie — inconfortable
   sur un jeu qui demande des taps rapides et précis sur la grille.
   Cible seulement les téléphones (hauteur de viewport réduite), pas les tablettes ou
   ordinateurs en paysage qui ont déjà assez de place verticale avec la mise en page
   habituelle : `max-height: 500px` couvre les téléphones actuels en paysage (320 à
   ~430px de hauteur utile selon le modèle) sans capturer une tablette (768px et plus).
   Voir Jeu.MEDIA_PAYSAGE_MOBILE (jeu.js), la même requête, dupliquée côté JS pour que
   Jeu.redimensionner() sache quand plafonner aussi la hauteur du canvas (indispensable
   ici : une grille en CSS donne enfin à .conteneur-canvas une vraie hauteur mesurable
   (voir plus bas), mais sans ce plafond JS le canvas continuerait de ne considérer
   que la largeur et déborderait quand même de cette hauteur).
   Grid plutôt que flex : permet de placer titre/bouton Son/HUD/barre de tours dans une
   colonne à droite malgré leur ordre entrecoupé dans le DOM (le canvas est entre les
   deux dans index.html) sans avoir à les envelopper dans un nouvel élément — chaque
   règle ci-dessous ne fait que leur assigner une cellule de la grille par nom de ligne,
   peu importe leur position dans le HTML. */
@media (orientation: landscape) and (max-height: 500px) {
    body {
        display: grid;
        grid-template-columns: 1fr 200px;
        grid-template-rows: auto auto 1fr auto;
        min-height: 100dvh;
        padding: 8px;
        gap: 8px;
    }

    h1 {
        grid-column: 2;
        grid-row: 1;
        font-size: 1.15rem;
    }

    #bouton-son {
        grid-column: 2;
        grid-row: 2;
    }

    /* S'étire sur toutes les lignes de la grille (peu importe qu'elle en compte trois
       ou davantage) : c'est ce qui donne enfin à ce conteneur une vraie hauteur
       mesurable par Jeu.redimensionner() (`conteneur.clientHeight`), au lieu de la
       laisser dériver du canvas lui-même comme en mise en page habituelle (portrait).
       `display: flex` + centrage : le canvas, dimensionné en JS à la taille exacte qui
       tient dans cet espace en conservant son ratio (voir Jeu.redimensionner), ne
       remplit pas forcément à la fois toute la largeur et toute la hauteur de cette
       cellule — le centrer évite qu'il ne colle contre un bord plutôt que l'autre.
       `max-height` + `position: sticky` : sur le plus petit des téléphones visés par
       cette media query, la colonne de droite (titre, bouton Son, HUD, barre de tours)
       peut rester plus haute que l'écran malgré sa mise en page compacte — dans ce cas,
       la grille grandit au-delà de 100dvh et la page devient globalement défilable
       (aucun `overflow: hidden` forcé ici, qui aurait simplement rendu le bas de cette
       colonne inaccessible). Sans `max-height`, ce conteneur grandirait alors lui aussi
       au-delà de la hauteur de l'écran (il s'étire sur la même grille), et une partie du
       plateau resterait invisible sous le bord inférieur de l'écran ; `max-height`
       l'empêche de dépasser la hauteur réelle du viewport, et `position: sticky` le
       garde alors visible et jouable pendant que le reste de la page défile autour de
       lui, plutôt que de le laisser défiler hors champ avec le reste. */
    .conteneur-canvas {
        grid-column: 1;
        grid-row: 1 / -1;
        max-width: none;
        height: 100%;
        max-height: calc(100dvh - 16px);
        position: sticky;
        top: 8px;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    /* Sans ces deux propriétés, le canvas garderait son étirement habituel (width:
       100%; height: auto, voir plus bas) et couvrirait toute la largeur de
       .conteneur-canvas en déformant son ratio au lieu de respecter la taille exacte
       fixée par Jeu.redimensionner() sur ses attributs width/height. */
    #canvas-jeu {
        width: auto;
        height: auto;
        max-width: 100%;
        max-height: 100%;
    }

    /* Colonne de droite : au lieu du centrage habituel sur toute la largeur de l'écran
       (pensé pour une bande étroite en portrait), les items s'accumulent verticalement
       du haut de leur cellule plutôt qu'au centre, plus lisible dans une colonne
       étroite (200px) qu'un centrage qui les ferait flotter au milieu d'un espace
       vertical généreux. */
    .barre-hud,
    .barre-types-tours {
        grid-column: 2;
        max-width: none;
        justify-content: flex-start;
        font-size: 0.82rem;
        gap: 6px;
    }

    .barre-hud {
        grid-row: 3;
    }

    .barre-types-tours {
        grid-row: 4;
    }

    /* Filet de sécurité : sur le plus petit des téléphones visés par cette media
       query, le contenu de l'écran d'accueil (le plus dense des trois écrans
       superposés — niveau/XP, cinq paliers de bonus, boutons de durée) peut rester
       plus haut que l'espace disponible malgré la hauteur généreuse que le canvas
       reçoit désormais dans cette mise en page. Un défilement interne à l'écran
       superposé (plutôt qu'un défilement de la page entière, qui décalerait aussi le
       canvas et le reste de l'interface) garde tout le reste du jeu stable. */
    .ecran-superpose {
        overflow-y: auto;
    }
}
