/* ============================================
   STARCruiser CLICKER - SPACE THEME STYLES
   Version 2.0.0
   ============================================ */
:root {
    /* Largeur maximale du jeu : sur ultrawide, la grille est bornee et
       centree ; les modales plein panneau utilisent la meme borne. */
    --game-max-width: 1720px;
    --primary: #1e3a8a;
    --primary-dark: #1e40af;
    --primary-light: #3b82f6;
    /* Bleu clair unifie de la DA (Progression Spatiale, case Prochaine
       destination, tuiles primaires, barre de destination) : un poil plus
       clair que --primary-light, MAIS le meme partout. */
    --blue-soft: #60a5fa;
    --blue-soft-glow: rgba(96, 165, 250, 0.55);
    --secondary: #0f172a;
    --secondary-light: #1e293b;
    --accent: #f59e0b;
    --accent-light: #fbbf24;
    --text: #f8fafc;
    --text-light: #94a3b8;
    --text-dark: #64748b;
    --border: #334155;
    --border-light: #475569;
    --bg: #0a0a0a;
    --bg-light: #0f172a;
    --bg-panel: #1e293b;
    --shadow: 0 1px 3px rgba(0,0,0,0.3);
    --shadow-lg: 0 4px 12px rgba(0,0,0,0.4);
    --glow: 0 0 10px rgba(30, 58, 138, 0.5);
    --radius: 8px;
    --top-height: clamp(60px, 10vh, 80px);
    --font-body: 'Space Grotesk', 'Inter', sans-serif;
    --font-display: 'Orbitron', 'Space Grotesk', sans-serif;
}
*, *::before, *::after {
    margin: 0; padding: 0; box-sizing: border-box;
}
/* Masquer toutes les barres de dfilement (scroll reste fonctionnel) */
* {
    scrollbar-width: none;
    -ms-overflow-style: none;
}
*::-webkit-scrollbar {
    display: none;
}
html {
    /* Echelle UI globale, pilotee par applyUiScale() dans script.js.
       Toute la typographie du jeu est en rem : un seul facteur fait
       evoluer textes, boutons, pop-ups et espacements proportionnellement. */
    font-size: calc(16px * var(--ui-scale, 1));
}
html, body {
    /* Desactive le double-tap zoom sur mobile (pas de zoom au double clic) */
    touch-action: manipulation;

    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    -webkit-user-drag: none;
    -webkit-touch-callout: none;
}
img {
    -webkit-user-drag: none;
    user-select: none;
    pointer-events: auto;
}
body {
    font-family: 'Space Grotesk', 'Inter', sans-serif;
    background: var(--bg);
    color: var(--text);
    min-height: 100vh;
    line-height: 1.5;
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
}
/* TOP BAR */
.top-bar {
    position: fixed;
    top: 0; left: 0; right: 0;
    height: var(--top-height);
    min-height: 60px; max-height: 80px;
    background: linear-gradient(135deg, var(--secondary-light), var(--secondary));
    /* Espace de 4 px avec le contenu : bande sombre discrete au lieu
       d'une ligne dure. */
    border-bottom: 4px solid #0a0f1e;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 0 16px;
    z-index: 1000;
    box-shadow: var(--shadow);
}
/* Sur ultrawide, le contenu de la barre reste aligne au jeu (borne et centre),
   pas colle aux bords physiques de l'ecran. */
.top-bar-logo, .top-bar-controls {
    min-width: 0;
}

/* Topbar alignee sur le panneau central : au-dela de 1920px, la bar est
   bornee a la meme largeur que la grille du jeu et centree -- le fond
   degrade ne depasse plus les bords du jeu sur ultrawide. */
@media (min-width: 1921px) {
    .top-bar {
        max-width: var(--game-max-width);
        left: 50%;
        right: auto;
        transform: translateX(-50%);
    }
}
.top-bar-controls .stardust-display {
    flex-shrink: 1;
    overflow: hidden;
    text-overflow: ellipsis;
}
.top-bar-logo {
    display: flex;
    align-items: center;
    gap: 10px;
}
.top-logo-img {
    height: 52px;
    width: auto;
    object-fit: contain;
}
.top-logo-text-img {
    /* Remplit la top bar : ~6 px de marge haut/bas seulement (barre
       max 80 px) -- le logo domine la barre. */
    height: 68px;
    width: auto;
    object-fit: contain;
}
.top-bar-title {
    color: var(--accent-light);
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.3rem;
    letter-spacing: 0.5px;
}
/* UPGRADES BAR (in center) */
.upgrade-icon {
    min-width: 38px;
    height: 38px;
    border-radius: var(--radius);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font-size: 1.3rem;
    transition: all 0.2s;
    position: relative;
    border: 2px solid var(--border-light);
    background: var(--bg-panel);
    color: var(--text);
    z-index: 3000;
    box-shadow: var(--shadow);
    overflow: hidden;
}
.upgrade-icon:hover {
    transform: scale(1.15);
    box-shadow: var(--shadow-lg);
    background: var(--secondary-light);
}
.upgrade-img {
    width: 26px;
    height: 26px;
    object-fit: contain;
    pointer-events: none;
    filter: drop-shadow(0 0 2px rgba(0,0,0,0.5));
}
.upgrade-level {
    position: absolute;
    bottom: -1px;
    right: -1px;
    min-width: 14px;
    height: 14px;
    padding: 0 3px;
    font-size: 0.6rem;
    font-weight: bold;
    line-height: 14px;
    text-align: center;
    color: #fff;
    background: rgba(0, 0, 0, 0.75);
    border-radius: 4px 0 0 0;
    text-shadow: none;
}
/* Pop \u00d72 flottant : confirme visuellement l'achat d'une amelioration
   au-dessus de la case cliquee (montee + fondu, 0.9 s). Vit dans le body
   en position fixed (coordonnees viewport capturees avant le re-render) :
   la case achetee est detruite par renderUpgrades et clippee par
   .upgrade-icon { overflow: hidden }, le pop y serait invisible. */
.upgrade-bought-pop {
    position: fixed;
    font-size: 1.1rem;
    font-weight: 800;
    padding: 2px 7px;
    border-radius: 8px;
    background: rgba(0, 0, 0, 0.75);
    border: 1px solid currentColor;
    pointer-events: none;
    white-space: nowrap;
    z-index: 12000;
    animation: upgrade-bought-pop-rise 0.9s ease-out forwards;
}
/* Variante batiment : deux fois plus gros, ancree a GAUCHE de la case du
   batiment (translate -100 % place le bord droit du pop sur le bord
   gauche de la case), animee sur place en grossissant puis en fondu. */
.upgrade-bought-pop-xl {
    font-size: 2.2rem;
    padding: 4px 14px;
    border-radius: 12px;
    animation-name: upgrade-bought-pop-xl-in;
}
@keyframes upgrade-bought-pop-xl-in {
    0%   { opacity: 0; transform: translate(-100%, -50%) scale(0.5); }
    25%  { opacity: 1; transform: translate(-100%, -50%) scale(1.2); }
    60%  { opacity: 1; transform: translate(-100%, -50%) scale(1); }
    100% { opacity: 0; transform: translate(-100%, -60%) scale(1); }
}
@keyframes upgrade-bought-pop-rise {
    0%   { opacity: 0; transform: translate(-50%, 4px) scale(0.6); }
    25%  { opacity: 1; transform: translate(-50%, -14px) scale(1.15); }
    100% { opacity: 0; transform: translate(-50%, -34px) scale(1); }
}
/* Tooltip for upgrades */
.upgrade-tooltip .tooltip-line {
    display: block;
    /* En ecran etroit : la ligne passe a la ligne suivante au lieu de
       deborder du popup (le bloc est borde par max-width). */
    white-space: normal;
    overflow-wrap: break-word;
}

.upgrade-tooltip {
    position: fixed;
    background: linear-gradient(135deg, rgba(15, 23, 42, 0.97), rgba(30, 41, 59, 0.97));
    border: 1px solid rgba(59, 130, 246, 0.45);
    border-left: 3px solid var(--primary-light);
    border-radius: 10px;
    padding: 10px 14px;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--text);
    box-shadow: 0 0 15px rgba(59, 130, 246, 0.25), 0 4px 12px rgba(0, 0, 0, 0.5);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s, visibility 0.2s;
    z-index: 9999;
    pointer-events: none;
    white-space: pre-line;
    /* Largeur fluide bornee : les lignes etant insecables, le bloc s'elargit
       au contenu sans jamais deborder de l'ecran. */
    max-width: min(88vw, 480px);
    line-height: 1.5;
    text-align: left;
    transform: translate(-50%, -120%);
    top: 0;
    left: 0;
}
.upgrade-tooltip.visible {
    opacity: 1;
    visibility: visible;
}
/* Chronometre depuis le dernier lancement (haut droit) */
.launch-timer {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 6px 12px;
    background: rgba(59, 130, 246, 0.15);
    border: 1px solid var(--border-light);
    border-radius: var(--radius);
    color: var(--text-light);
    font-size: 0.85rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: default;
}
.launch-timer.has-launch {
    color: var(--accent-light);
}

.top-bar-controls {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 4px;
    padding: 4px 8px;
    height: 100%;
    justify-content: center;
}
.stardust-display {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    background: rgba(167, 139, 250, 0.18);
    border: 1px solid #a78bfa;
    border-radius: var(--radius);
    color: #e9d5ff;
    font-weight: 700;
    font-size: 0.95rem;
    white-space: nowrap;
}
.stardust-display span {
    color: #c4b5fd;
    min-width: 1ch;
}
.control-button {
    width: 40px; height: 40px;
    border: none;
    border-radius: var(--radius);
    background: var(--primary);
    color: white;
    font-size: calc(1rem * var(--ui-scale, 1));
    cursor: pointer;
    transition: all 0.2s;
    box-shadow: var(--shadow);
}
.control-button:hover {
    background: var(--primary-light);
    transform: scale(1.1);
    box-shadow: var(--shadow-lg), var(--glow);
}
/* ===== Nouveau batiment : reveal plein ecran ===== */
.new-building-modal.active {
    animation: nbModalIn 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes nbModalIn {
    from { transform: translate(-50%, -50%) scale(0.7); opacity: 0; }
    to   { transform: translate(-50%, -50%) scale(1); opacity: 1; }
}
@keyframes nbModalInMobile {
    from { transform: translate(-50%, -50%) scale(0.7); opacity: 0; }
    to   { transform: translate(-50%, -50%) scale(1); opacity: 1; }
}
.new-building-body {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 20px 16px 24px;
}
.nb-reveal {
    position: relative;
    width: 13.125rem;
    height: 13.125rem;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 10px;
}
.nb-reveal::before {
    content: '';
    position: absolute;
    inset: -1.125rem;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(136, 201, 238, 0.35) 0%, rgba(136, 201, 238, 0.12) 45%, transparent 70%);
    animation: nbGlow 1.6s ease-in-out infinite alternate;
}
@keyframes nbGlow {
    from { transform: scale(0.92); opacity: 0.7; }
    to   { transform: scale(1.08); opacity: 1; }
}
.nb-reveal img {
    position: relative;
    width: 100%;
    height: 100%;
    object-fit: contain;
    filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.45));
    animation: nbPop 0.55s cubic-bezier(0.34, 1.56, 0.64, 1);
    -webkit-user-drag: none;
}
@keyframes nbPop {
    0%   { transform: scale(0.2) rotate(-8deg); opacity: 0; }
    60%  { transform: scale(1.15) rotate(2deg); opacity: 1; }
    100% { transform: scale(1) rotate(0deg); opacity: 1; }
}
.new-building-body h3 {
    margin: 4px 0 2px;
    font-size: 1.35rem;
    color: var(--text-dark);
}
.new-building-body p {
    margin: 0 0 14px;
    font-size: 0.9rem;
    color: var(--text-light);
    font-style: italic;
}
.nb-stats {
    display: flex;
    gap: 10px;
    width: 100%;
}
.nb-stat {
    flex: 1;
    background: var(--bg-panel);
    border: 1px solid var(--border-light);
    border-radius: var(--radius);
    padding: 8px 10px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.nb-stat-label {
    font-size: 0.72rem;
    color: var(--text-light);
}
.nb-stat-value {
    font-size: 1rem;
    font-weight: 700;
    color: var(--accent-light);
}

/* Bon retour : PLEIN ECRAN bloquant -- voile noir opaque total, la carte
   centre flotte au milieu, SEUL le bouton Continuer permet de jouer.
   Rien d'autre n'est cliquable ni visible en dessous. */
.welcome-back-modal {
    top: 0 !important;
    left: 0 !important;
    transform: none !important;
    width: 100vw !important;
    max-width: 100vw !important;
    height: 100dvh !important;
    max-height: 100dvh !important;
    background: rgba(2, 6, 23, 0.96) !important;
    display: none;
    align-items: center;
    justify-content: center;
    border: none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    z-index: 20000 !important;
}
.welcome-back-modal.active {
    display: flex;
}
.welcome-back-modal .modal-content {
    /* CARRE de reference ~450x450 sur grand ecran PC : plus compacte et
       equilibree qu'une carte etiree. Hauteur bornee a 450px, la carte
       reste carree quand le contenu le permet. */
    width: min(92vw, 450px);
    height: auto;
    max-height: 450px;
    min-height: 0;
    overflow-y: auto;
    background: linear-gradient(160deg, rgba(15, 23, 42, 0.98), rgba(2, 6, 23, 0.98));
    border: 1px solid rgba(59, 130, 246, 0.55);
    border-radius: 16px;
    box-shadow: 0 0 40px rgba(59, 130, 246, 0.35), 0 20px 60px rgba(0, 0, 0, 0.8);
    animation: wb-pop-in 0.35s cubic-bezier(0.22, 1.2, 0.36, 1);
}
@keyframes wb-pop-in {
    from { opacity: 0; transform: scale(0.85) translateY(14px); }
    to { opacity: 1; transform: scale(1) translateY(0); }
}
.wb-body {
    align-items: center;
    text-align: center;
    justify-content: center;
    padding: 18px 22px 18px !important;
}
/* Hauteur classique PC : le cercle de revelation herite du pop-up nouveau
   batiment (210px) et rendait la fenetre "Bon retour" enorme. Version
   discrete pour ce resume de gains. Mobile non touche (regle propre). */
@media not all and ((max-width: 1024px) and (pointer: coarse)) {
    .wb-body .nb-reveal {
        width: 4.5rem;
        height: 4.5rem;
        margin-bottom: 8px;
    }
}
.wb-heading {
    font-family: var(--font-display);
    font-size: 1.6rem;
    letter-spacing: 0.04em;
    background: linear-gradient(90deg, #7dd3fc, #a78bfa, #fbbf24);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    margin: 4px 0 2px;
}
.wb-continue-btn {
    margin-top: 18px;
    width: 100%;
    padding: 13px 20px;
    font-size: 1.05rem;
    font-weight: 800;
    font-family: var(--font-display);
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: #fff;
    background: linear-gradient(135deg, var(--primary), #7c3aed);
    border: 1px solid rgba(147, 197, 253, 0.7);
    border-radius: 12px;
    cursor: pointer;
    box-shadow: 0 0 18px rgba(99, 102, 241, 0.5);
    transition: transform 0.15s, box-shadow 0.15s, filter 0.15s;
    animation: wb-btn-pulse 2s ease-in-out infinite;
}
.wb-continue-btn:hover {
    transform: scale(1.03);
    filter: brightness(1.15);
    box-shadow: 0 0 26px rgba(129, 140, 248, 0.7);
}
@keyframes wb-btn-pulse {
    0%, 100% { box-shadow: 0 0 14px rgba(99, 102, 241, 0.45); }
    50% { box-shadow: 0 0 24px rgba(129, 140, 248, 0.75); }
}
.wb-capped {
    margin: 12px 0 0;
    font-size: 0.8rem;
    color: var(--text-light);
    font-style: italic;
}

/* MODALS */
.modal {
    position: fixed;
    top: var(--top-height); left: 50%;
    transform: translateX(-50%);
    width: 50%; max-width: 780px;
    height: calc(100vh - var(--top-height));
    height: calc(100dvh - var(--top-height));
    max-height: calc(100vh - var(--top-height));
    max-height: calc(100dvh - var(--top-height));
    background: var(--bg-panel);
    border-radius: var(--radius);
    box-shadow: 0 4px 20px rgba(0,0,0,0.5);
    z-index: 1000;
    display: none;
    overflow: hidden;
    border: 1px solid var(--border-light);
}
.modal.active {
    display: flex;
    flex-direction: column;
}
/* Nouveau batiment : apres .modal pour surcharger le plein panneau,
   petite fenetre centree carree/rectangulaire. */
.new-building-modal {
    width: 92%;
    max-width: 420px;
    z-index: 1100;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    height: auto;
    max-height: 80vh;
}
.modal.active > .modal-content {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1;
}
.modal-header {
    background: linear-gradient(135deg, var(--primary), var(--primary-dark));
    color: white;
    padding: 16px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 1px solid var(--border-light);
}

/* Modale des contrats : pleine largeur du panneau central (50%) */
#contracts-modal.modal {
    width: 50%;
    max-width: 50%;
}
/* Cartes / Contrats (PC) : titre et compteur sur une seule ligne, en-tete compact */
#card-collection-modal .modal-header,
/* Hauteur de la modale contrats : hauteur auto -- elle s'arrete juste
   apres le 3e contrat (padding du body = marge). Si l'ecran est trop
   petit, max-height la plafonne jusqu'en bas et le body devient
   scrollable (overflow-y auto deja present sur .contracts-modal
   .modal-body). */
#contracts-modal.modal {
    height: auto;
    max-height: calc(100dvh - var(--top-height));
}
#contracts-modal .modal-body {
    overflow-y: auto;
}
/* Hauteur des modales Stats et Parametres : auto -- elles s'arretent
   juste apres leur contenu au lieu d'aller jusqu'en bas de l'ecran. */
#stats-modal.modal,
#settings-modal.modal {
    height: auto;
    max-height: calc(100dvh - var(--top-height));
}
#stats-modal .modal-body,
#settings-modal .modal-body {
    overflow-y: auto;
    max-height: 70dvh;
}

#contracts-modal .modal-header {
    flex-wrap: nowrap;
    padding-top: 8px;
    padding-bottom: 8px;
}
#card-collection-modal .modal-header h2,
#contracts-modal .modal-header h2 {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
#card-collection-modal .modal-parts-counter,
#contracts-modal .modal-parts-counter {
    margin: 0;
    align-self: center;
    white-space: nowrap;
}
/* Empilement titre/compteur : UNIQUEMENT mobile */
@media (max-width: 1024px) and (pointer: coarse) {
    #card-collection-modal .modal-header,
    #contracts-modal .modal-header {
        flex-wrap: wrap;
        row-gap: 4px;
        padding-top: 10px;
        padding-bottom: 10px;
    }
    #card-collection-modal .modal-header h2,
    #contracts-modal .modal-header h2 {
        white-space: normal;
    }
    #card-collection-modal .modal-parts-counter,
    #contracts-modal .modal-parts-counter {
        margin: 0 auto;
    }
}
.modal-header h2 {
    font-family: var(--font-display);
    font-size: 1.3rem;
}
.modal-header h2 .modal-title-icon {
    height: 1.3em;
    width: auto;
    vertical-align: -0.25em;
    filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.5));
}
.modal-parts-counter {
    margin: 0 auto;
    padding: 6px 14px;
    background: rgba(0, 0, 0, 0.35);
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: var(--radius);
    color: white;
    font-size: 0.95rem;
    font-weight: 600;
    white-space: nowrap;
    pointer-events: none;
}
.modal-parts-counter .modal-parts-value {
    color: var(--accent-light);
}
.modal-parts-counter .modal-parts-gain {
    color: var(--accent-light);
}
.close-button {
    font-size: calc(1.25rem * var(--ui-scale, 1));
    line-height: 1;
    cursor: pointer;
    color: white;
    min-width: 34px;
    min-height: 34px;
    align-self: center;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 2px solid rgba(255, 255, 255, 0.45);
    border-radius: 8px;
    padding: 4px;
    flex-shrink: 0;
    background: rgba(0, 0, 0, 0.25);
    transition: background 0.15s ease, border-color 0.15s ease;
}
.close-button:hover {
    opacity: 0.8;
    background: rgba(255, 255, 255, 0.15);
    border-color: rgba(255, 255, 255, 0.8);
}
.modal-body {
    padding: 16px;
    overflow-y: auto;
    flex: 1;
    min-height: 0;
    background: var(--bg-panel);
    color: var(--text);
}
.modal-button {
    width: 100%;
    padding: 12px;
    border: none;
    border-radius: var(--radius);
    background: var(--primary);
    color: white;
    font-size: 1rem;
    cursor: pointer;
    margin-bottom: 8px;
    transition: all 0.2s;
}
/* Reglages : boutons de langue en grille fixe — aucun reaffichage quand
   la langue change (les libelles FR/EN/ES... ont la meme largeur). */
#settings-modal .language-selector .modal-button { margin-bottom: 0; white-space: nowrap; }
.modal-button:hover {
    background: var(--primary-light);
    box-shadow: var(--glow);
}
.modal-button.delete {
    background: #ef4444;
}
.modal-button.delete:hover {
    background: #dc2626;
}
#import-textarea {
    width: 100%;
    min-height: 100px;
    padding: 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    font-family: monospace;
    font-size: 0.9rem;
    resize: none;
    margin-bottom: 8px;
    background: var(--secondary);
    color: var(--text);
}
/* MAIN GRID */
.main-grid {
    display: grid;
    grid-template-columns: 25% 50% 25%;
    height: calc(100vh - var(--top-height));
    height: calc(100dvh - var(--top-height));
    position: fixed;
    top: var(--top-height);
    left: 0;
    right: 0;
    gap: 1px;
    background: var(--border);
    overflow: visible;
}
/* Au-dessus de 1920px seulement : le jeu garde sa composition 1920x1080,
   l'espace supplementaire reste du fond. En dessous, l'UI occupe tout
   l'ecran (pas de bandes noires). */
@media (min-width: 1921px) {
    .main-grid {
        max-width: var(--game-max-width);
        margin: 0 auto;
    }
}
/* LEFT PANEL */
/* Titres de sections : DA commune - texte simple + barre separateur dessous */
.left-panel h3,
.right-panel h3,
.space-section-title {
    font-family: var(--font-display);
    color: var(--text);
    margin: 0 0 10px 0;
    font-size: 1.1rem;
    font-weight: 700;
    text-align: center;
    border-bottom: 2px solid var(--primary-light);
    padding-bottom: 10px;
    line-height: 1.3;
}
.buildings-header h3 {
    margin: 0;
    border-bottom: none;
    padding-bottom: 0;
    white-space: nowrap;
}
.left-panel p {
    color: var(--text-dark);
    font-size: 0.9rem;
}
/* CENTER PANEL */
.center-panel-content-wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex-grow: 1;
    width: 100%;
}
.center-panel {
    background: var(--bg-panel);
    display: flex;
    flex-direction: column;
    align-items: center;
    height: 100%;
    position: relative;
    z-index: 1;
    container-type: inline-size;
}
/* Pluie de pieces en arriere-plan du panneau central.
   Au-dessus du ciel de la scene (qui masquerait la pluie) mais sous
   les elements interactifs (bouton Lancer z-100, modals, HUD). */
.parts-rain {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    z-index: 4;
}
.parts-rain .rain-canvas {
    width: 100%;
    height: 100%;
    display: block;
}
@keyframes pulse {
    0%, 100% { opacity: 0.85; }
    50% { opacity: 1; }
}
.counter span {
    color: var(--accent-light);
    font-weight: 600;
    text-shadow: var(--glow);
}
/* Chiffres du compteur : deroulement type machine a sous.
   Les colonnes .cch n'ont pas de texte inline : leur baseline flex est
   synthetisee au bord BAS, align-items: baseline les poussait donc vers
   le bas et les chiffres descendaient sous la ligne du texte "Parts".
   Centrage vertical : les chiffres remontent exactement sur la baseline
   du texte adjacent (meme police, meme font-size). */
#score-value,
.stat-value,
.modal-parts-value,
.modal-parts-gain,
#stardust-value,
#stardust-value-2 {
    display: inline-flex;
    align-items: center;
    align-self: center;
}
.cch-group {
    display: inline-flex;
}
.cch-sep {
    white-space: pre;
}
/* Ruban vertical (odometre) : une colonne = un chiffre, le ruban des 10
   chiffres glisse verticalement avec une transition douce. */
/* Hauteur de colonne snappee sur un nombre entier de px via --cch-h :
   une hauteur fractionnaire (19.91px) fait reposer chaque ruban sur un
   sous-pixel different selon le chiffre affiche, si bien que le rendu de
   la police (antialiasing) varie d'une ligne a l'autre et donne
   l'impression que les chiffres ne sont pas tout a fait au meme niveau. */
#score-value .cch,
.stat-value .cch,
#travel-distance-value .cch,
.modal-parts-value .cch,
.modal-parts-gain .cch,
#stardust-value .cch,
#stardust-value-2 .cch {
    display: inline-flex;
    align-items: flex-start;
    overflow: hidden;
    /* Taille de base 0.62em (valeur d'origine du jeu) pour TOUS les
       compteurs. Les compteurs PE en Space Grotesk grasse ont leur
       propre regle ciblee a 1em juste en dessous. */
    width: 0.62em;
    height: var(--cch-h, 1.5em);
    line-height: var(--cch-h, 1.5em);
    vertical-align: bottom;
}
/* Compteurs de Poussiere d'Etoiles (PE) : police Space Grotesk GRASSE,
   plus large que celle des autres compteurs -- colonne dediee a 1em,
   le "0" y dispose de toute sa place sans elargir les autres chiffres. */
#stardust-value .cch,
#stardust-value-2 .cch {
    width: 1em;
}
.cch-reel {
    display: flex;
    flex-direction: column;
    transition: transform 0.24s cubic-bezier(0.25, 0.9, 0.3, 1);
    will-change: transform;
}
.cch-reel .digit {
    display: block;
    height: var(--cch-h, 1.5em);
    line-height: var(--cch-h, 1.5em);
    text-align: center;
}

/* Pulse d'attention : attire l'oeil quand une action devient disponible
   (batiment abordable, nouveaux contrats, piece de fusee achetable).
   Le JS retire la classe apres 10 s si le joueur n'a pas agi. */
.pulse-hint {
    position: relative;
}
.pulse-hint::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    z-index: 0;
    box-shadow: 0 0 26px 6px rgba(251, 191, 36, 0.95), 0 0 60px 14px rgba(251, 191, 36, 0.45);
    opacity: 0;
    animation: pulse-hint-glow 1.6s ease-in-out infinite;
    will-change: opacity;
}
@keyframes pulse-hint-glow {
    0%, 100% { opacity: 0; }
    50% { opacity: 1; }
}

/* Bonus actif : le compteur devient arc-en-ciel et pulse */
.counters.bonus-active {
    position: relative;
    background: rgba(0, 0, 0, 0.5);
}
.counters.bonus-active .counter > span {
    /* Enfants directs UNIQUEMENT : la couleur animee est heritee par les
       colonnes odometre (.cch/.digit, recreees a chaque changement de
       forme du nombre). Si elles matchaient aussi ce selecteur, chaque
       colonne nouvelle repartait a la phase 0 de l'animation -- des
       chiffres arc-en-ciel PAS dans la meme couleur au meme moment. */
    animation: rainbow-colors 1.5s linear infinite;
    text-shadow: 0 0 8px rgba(255, 255, 255, 0.35);
}
/* La regle generique ".counter span" force la couleur ambre sur TOUS les
   span descendants, y compris les colonnes odometre .cch/.digit : leur
   propre couleur statique empechait l'heritage de la couleur arc-en-ciel
   animee du parent -- les chiffres du compteur restaient ambre pendant
   tout le bonus. On neutralise leur couleur pendant le bonus : sans
   couleur propre, elles heritent de l'animation du parent. */
.counters.bonus-active .counter .cch,
.counters.bonus-active .counter .cch-reel,
.counters.bonus-active .counter .digit,
.counters.bonus-active .counter .cch-sep,
.counters.bonus-active .counter .cch-group {
    color: inherit;
}
/* Le nombre de Parts/s (#gain-value) est un span IMBRIQUE dans .gain-wrap :
   la regle generique ".counter span" lui forcait aussi la couleur ambre et il
   restait fige pendant les bonus. Comme les colonnes odometre, il herite
   desormais la couleur animee de son parent. */
.counters.bonus-active .counter .gain-wrap span {
    color: inherit;
}

@keyframes rainbow-slide {
    0% { background-position: 0% 50%; }
    100% { background-position: 200% 50%; }
}
/* Couleurs arc-en-ciel par keyframes de color (pas de background-clip) :
   le gradient clippé cassait le rendu des colonnes odomètre (.cch) quand
   leur transform translateY animait les chiffres pendant un bonus. */
@keyframes rainbow-colors {
    0%   { color: #ff0080; }
    17%  { color: #ff8c00; }
    33%  { color: #ffee00; }
    50%  { color: #00e676; }
    67%  { color: #00b0ff; }
    83%  { color: #b388ff; }
    100% { color: #ff0080; }
}
/* Boost actif sur la tuile Vitesse : EXACTEMENT le meme effet que le
   compteur principal — meme pulse, meme gradient arc-en-ciel coulissant.
   Le gradient est appliquE a la valeur ET a ses descendants (.cch) :
   le clip de fond ne descendait pas dans les colonnes odomEtre et
   rendait les chiffres noirs quand il n'Etait que sur .stat-value. */
.stat-tile.bonus-active {
    position: relative;
    border-color: rgba(255, 255, 255, 0.35);
}
.stat-tile.bonus-active .stat-value {
    /* Seule la valeur anime : les colonnes odometre heritent de la couleur
       (meme phase partout, meme quand elles sont recreees). */
    animation: rainbow-colors 1.5s linear infinite;
    text-shadow: 0 0 8px rgba(255, 255, 255, 0.35);
}
@keyframes bonus-rainbow-pulse {
    0%, 100% { opacity: 0; }
    50% { opacity: 1; }
}
.counters.bonus-active::after,
.stat-tile.bonus-active::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    border: 2px solid rgba(255, 255, 255, 0.55);
    box-shadow: 0 0 22px 4px rgba(255, 255, 255, 0.55), 0 0 44px 10px rgba(255, 255, 255, 0.25);
    opacity: 0;
    animation: bonus-rainbow-pulse 1.5s ease-in-out infinite;
    will-change: opacity;
    z-index: 1;
}
.bonus-timer {
    position: static;
    flex: 0 0 auto;
    font-size: 1rem;
    color: var(--accent-light);
    font-weight: 600;
    background: rgba(245, 158, 11, 0.2);
    padding: 4px 12px;
    border-radius: var(--radius);
    display: none;
    border: 1px solid var(--accent);
    max-width: 40%;
    overflow: hidden;
    text-overflow: ellipsis;
    /* nowrap : le libelle est court ("x5 - 12 s"), le wrap le rendait
       illisible en vertical quand la largeur manquait. */
    white-space: nowrap;
}
/* ===== ECRAN DE CHARGEMENT ===== */
/* Overlay opaque au-dessus de tout : couvre le temps de chargement des
   scripts, des images et de l'init du jeu. Masque via .hidden (opacity +
   pointer-events) pour une transition douce. */
#loading-screen {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 24px;
    background: linear-gradient(180deg, #0b1030 0%, #1e3a6e 100%);
    transition: opacity 0.4s ease;
}
#loading-screen.hidden {
    opacity: 0;
    pointer-events: none;
}
.loading-logo {
    width: min(320px, 70vw);
    height: auto;
    animation: loading-pulse 1.6s ease-in-out infinite;
}
.loading-spinner {
    width: 42px;
    height: 42px;
    border-radius: 50%;
    border: 4px solid rgba(255, 255, 255, 0.15);
    border-top-color: var(--accent-light);
    animation: loading-spin 0.9s linear infinite;
}
.loading-text {
    color: #cbd5e1;
    font-family: 'Space Grotesk', sans-serif;
    font-size: 1rem;
    letter-spacing: 1px;
}
@keyframes loading-spin {
    to { transform: rotate(360deg); }
}
@keyframes loading-pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50% { opacity: 0.75; transform: scale(1.03); }
}
@media (prefers-reduced-motion: reduce) {
    .loading-logo, .loading-spinner { animation: none; }
}

/* Panneau flottant de contrat actif : objectif + progression + chrono,
   affiche sous le compteur tant que le contrat de 30 s est en cours. */
.contract-hud {
    order: 3;
    /* Le badge de bonus en position basse (bonus-below) est absolu sous
       le compteur : decaler le HUD de contrat sous cet espace reserve
       pour eviter toute superposition. */
    margin-top: 8px;
    flex: 0 0 auto;
    min-width: min(280px, 40cqw);
    max-width: 60%;
    background: rgba(2, 6, 23, 0.92);
    border: 2px solid var(--accent);
    border-radius: var(--radius);
    padding: 6px 12px 8px 12px;
    font-size: 0.9rem;
    color: var(--text);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}
.hud-top-row:has(.bonus-timer.bonus-below) .contract-hud {
    margin-top: 44px;
}
.contract-hud-text {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.contract-hud-label {
    color: var(--accent-light);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
}
.contract-hud-progress { font-weight: 700; }
.contract-hud-time { color: var(--accent-light); font-variant-numeric: tabular-nums; }
.contract-hud-bar {
    margin-top: 5px;
    height: 6px;
    background: rgba(255, 255, 255, 0.12);
    border-radius: 3px;
    overflow: hidden;
}
.contract-hud-bar-fill {
    height: 100%;
    width: 0%;
    background: linear-gradient(90deg, var(--accent), var(--accent-light));
    border-radius: 3px;
    transition: width 0.45s linear;
}

/* RIGHT PANEL */
.right-panel {
    background: var(--bg-panel);
    border-left: 1px solid var(--border);
    padding: 15px 16px 16px 16px;
    /* Le panel ne scrolle plus : le header (titre + multiplicateurs) reste
       figé et SEULE la liste des batiments defile (voir .buildings-list). */
    display: flex;
    flex-direction: column;
    overflow: hidden;
    height: 100%;
    color: var(--text);
}

.buildings-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 8px;
    /* SEULE la liste defile : le header au-dessus est hors de ce
       conteneur et reste fige, aucune case visible au-dessus du titre. */
    /* container-type OBLIGATOIRE : les proprietes cqw de la case ELLE-MEME
       (padding, min/max-height et surtout grid-template-columns 28.6cqw
       33.6cqw 1fr) se resolvent contre le plus proche ancetre conteneur
       de requete -- c'est CETTE liste. Sans lui, les cqw retombent sur
       le viewport : 28.6cqw = 28.6vw soit des cases geantes ou l'on ne
       voit que l'image (colonnes texte et bouton chassees hors ecran).
       Les .building-item ont AUSSI leur propre container-type, mais il
       ne couvre que leurs descendants, pas leurs propres proprietes. */
    container-type: inline-size;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior-y: contain;
}
/* Building items */
/* Case auto-contenue : toutes ses tailles internes sont exprimees en cqw
   (pourcentage de la largeur de la case), calibrees sur le rendu de
   reference 1920x1080. Quand l'ecran se retractit, la case et tout ce
   qu'elle contient suivent un ratio homothetique unique. */
.building-item {
    container-type: inline-size;
    background: var(--secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 2.7cqw;
    display: grid;
    /* Colonnes du rendu 1920x1080 : 92px / 150px / 129px sur 447px */
    /* 1fr final : le bouton s'etire jusqu'au bord droit, aucun espace mort
       (les proportions des autres colonnes restent calibrees 1920x1080). */
    /* PC : bouton d'achat reduit de ~20% — l'espace rendu va au texte a
       gauche (colonne 1 elargie), ce qui decale l'image vers la droite. */
    grid-template-columns: minmax(0, 28.6cqw) 33.6cqw minmax(0, 1fr);
    align-items: center;
    cursor: pointer;
    transition: all 0.2s;
    min-height: 18.5cqw;
    max-height: 26cqw;
    flex: 0 0 auto;
    overflow: hidden;
    position: relative;
}
.building-item:hover {
    background: var(--secondary-light);
    border-color: var(--primary-light);
    box-shadow: var(--shadow-lg);
}
.building-left {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
    max-width: 100%;
}
.building-right {
    display: flex;
    flex-direction: column;
    gap: 4px;
    align-items: flex-end;
    min-width: 0;
    max-width: 100%;
}
.building-center {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    overflow: hidden;
    min-width: 0;
}
.building-name-icon {
    display: flex;
    align-items: center;
    gap: 12px;
}
.building-name {
    font-size: 3.94cqw;
    font-weight: 500;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.building-image {
    /* RETOUR a la regle d'origine qui rendait l'image a la largeur de sa
       colonne : le width:100% force cassait la grille de la case (les
       colonnes texte et bouton etaient ecrasees selon le ratio du sprite).
       width auto + max-width 100% + max-height 17cqw : l'image prend
       naturellement toute la largeur disponible sans deborder. */
    height: auto;
    width: auto;
    max-width: 100%;
    max-height: 17cqw;
    object-fit: contain;
    margin: 0 auto;
    opacity: 1;
    pointer-events: none;
    display: block;
    filter: none;
    flex-shrink: 1;
}
.building-center {
    align-self: stretch;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 0;
}

/* Styles spécifiques pour les images des bâtiments */
.building-item.nozzles .building-image,
.building-item.workshop .building-image,
.building-item.engines .building-image,
.building-item.fuel-tank .building-image,
.building-item.cockpit .building-image,
.building-item.shield .building-image,
.building-item.launch-pad .building-image,
.building-item.astronaut .building-image {
    margin-left: -3.35cqw;
}

.building-item.nozzles .building-image {
    height: 50%;
    width: auto;
    max-height: 7.8cqw;
}

.building-item.workshop .building-image {
    height: auto;
    width: auto;
    max-width: 100%;
    max-height: 17cqw;
    margin: 0 auto;
}

.building-item.rocket-body .building-image,
.building-item.boosters-left .building-image,
.building-item.boosters-right .building-image {
    transform: rotate(65deg);
    transform-origin: center;
    height: 100%;
    max-height: 11.7cqw;
    opacity: 0.7;
    margin-left: -1.1cqw;
}

.building-ownership {
    font-size: 3.58cqw;
    color: var(--text-dark);
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}
/* Enfants de la grille : min-width 0 pour que les colonnes puissent
   resserer sous la taille de leur contenu sans deborder de la case. */
.building-item > .building-left,
.building-item > .building-center,
.building-item > .building-right { min-width: 0; }
.building-production {
    font-size: 3.58cqw;
    color: var(--accent-light);
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}
.building-item button {
    width: 100%;
    background: var(--primary);
    color: white;
    border: none;
    border-radius: var(--radius);
    padding: 1.9cqw 2.7cqw;
    font-size: 3.58cqw;
    cursor: pointer;
    transition: all 0.2s;
    min-width: 0;
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.building-item button:hover:not(:disabled) {
    background: var(--primary-light);
    box-shadow: var(--glow);
}
.building-item button:disabled {
    background: var(--border);
    cursor: not-allowed;
    opacity: 0.5;
}
/* Buy multipliers */
.buildings-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    min-height: 1.3em;
    margin: 0;
    padding: 0 0 10px 0;
    border-bottom: 2px solid var(--primary-light);
    box-sizing: border-box;
    /* Header hors du flux scrollable : il ne bouge jamais, aucune case
       ne peut apparaitre derriere ou au-dessus du titre. */
    flex: 0 0 auto;
    margin-bottom: 10px;
}

.multiplier-buttons {
    display: flex;
    gap: 4px;
}
.multiplier-btn {
    padding: 4px 8px;
    border: 1px solid var(--border-light);
    border-radius: var(--radius);
    background: var(--secondary);
    color: var(--text);
    font-size: 0.85rem;
    cursor: pointer;
    transition: all 0.2s;
}
.multiplier-btn:hover {
    background: var(--secondary-light);
    border-color: var(--primary-light);
}
.multiplier-btn.active {
    background: var(--primary);
    color: white;
    border-color: var(--primary);
    box-shadow: var(--glow);
}
/* TOOLTIP */
.building-item::after {
    content: attr(data-tooltip);
    position: absolute;
    top: 100%; left: 0;
    background: var(--bg-panel);
    border: 1px solid var(--border-light);
    border-radius: var(--radius);
    padding: 12px;
    font-size: 0.85rem;
    color: var(--text);
    box-shadow: var(--shadow-lg);
    opacity: 0;
    visibility: hidden;
    transition: all 0.2s;
    z-index: 1000;
    pointer-events: none;
    white-space: pre-line;
    width: 85%;
    line-height: 1.5;
}
.building-item:hover::after {
    opacity: 1;
    visibility: visible;
    transform: translateY(8px);
}
/* VISUAL EFFECTS */
.bonuses-container,
.click-effects {
    position: fixed;
    top: var(--top-height);
    left: 0; right: 0; bottom: 0;
    pointer-events: none;
    z-index: 50;
}
/* Les comètes passent DEVANT tout le reste (modals, nav, lightbox),
   même pendant l'animation de voyage : elles restent cliquables. */
.bonuses-container {
    z-index: 10000;
}
/* Les pop-ups de bonus ("+X Parts", "x5") passent devant les comètes elles-mêmes
   pour rester lisibles au moment de la récompense. */
#click-effects {
    z-index: 10001;
}

/* Pieces qui tombent depuis le point clique
   - wrapper .falling-coin : positionne ; la trajectoire balistique
     (saut puis chute gravitationnelle) est pilotee en JS via WAAPI
   - img : apparition pop + tournoiement tres lent */
.falling-coins {
    position: fixed;
    top: var(--top-height);
    left: 0; right: 0; bottom: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 50;
}
.falling-coin {
    position: absolute;
    transform: translate(-50%, -50%);
    pointer-events: none;
    user-select: none;
}
.falling-coin img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
    pointer-events: none;
    animation:
        coin-pop-in 0.22s ease-out both,
        coin-tumble var(--fall-duration) var(--fall-delay, 0s) linear both;
    filter: drop-shadow(0 3px 4px rgba(0, 0, 0, 0.35));
}
/* Tournoiement regulier : 1 tour / 12 s (vitesse definie en JS) */
@keyframes coin-tumble {
    from { rotate: 0deg; }
    to   { rotate: var(--fall-spin); }
}
/* Apparition sur place avec un leger tournoiement (transform: rotate
   compose avec la propriete `rotate` du tournoiement lent) */
@keyframes coin-pop-in {
    from { transform: rotate(-35deg); scale: 0.4; opacity: 0; }
    to   { transform: rotate(0deg); scale: 1; opacity: 1; }
}
.random-bonus {
    position: absolute;
    width: 180px; height: 180px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    pointer-events: all;
    z-index: 60;
}
.random-bonus.comet {
    transition: none;
    /* Position REELLE du noyau dans le conteneur (le sprite comète.png
       est horizontal, noyau a ~85% de la largeur, queue integree ;
       rendu contain + rotation 45deg place le noyau ici, pas au centre
       du canvas). Tous les effets s'ancrent sur ces coordonnees. */
    /* Noyau en POURCENTAGE du conteneur : suit la taille de la comete
       (180px desktop, 130px mobile, 120px pluie) sans decalage */
    --nx: 67.16%;
    --ny: 80.51%;
}
.random-bonus.comet.reverse {
    --comet-rot: 120deg;
}
.comet-img {
    width: 180px;
    height: 180px;
    object-fit: contain;
    transform: rotate(var(--comet-rot, 60deg));
    pointer-events: none;
}
.random-bonus.comet.reverse .comet-img {
    transform: rotate(var(--comet-rot, 120deg));
}
/* Chevelure (coma) : halo diffus bleute-cyan autour du noyau, anime */
.comet-coma {
    position: absolute;
    left: var(--nx);
    top: var(--ny);
    width: 127.78%;
    height: 127.78%;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background:
        radial-gradient(circle at 50% 50%, rgba(200, 235, 255, 0.55) 0%, rgba(150, 200, 255, 0.28) 34%, rgba(110, 170, 250, 0.1) 58%, rgba(110, 170, 250, 0) 78%);
    filter: blur(4px);
    pointer-events: none;
    animation: cometComa 0.8s ease-in-out infinite alternate;
}
@keyframes cometComa {
    from { transform: translate(-50%, -50%) scale(0.92); opacity: 0.8; }
    to   { transform: translate(-50%, -50%) scale(1.06); opacity: 1; }
}
/* Queue de plasma : panache continu attache derriere le noyau, oriente
   dans l'axe oppose au vol (45 deg vers le haut-arriere), degrade
   blanc-bleu qui s'affine, leger ondulement */
.comet-tail-plasma {
    position: absolute;
    left: calc(var(--nx) - 177.78%);
    top: calc(var(--ny) - 12.78%);
    width: 177.78%;
    height: 25.56%;
    transform-origin: 100% 50%;
    transform: rotate(var(--comet-rot, 60deg));
    border-radius: 50% 40% 40% 50% / 60% 45% 45% 60%;
    background: linear-gradient(270deg,
        rgba(255, 255, 255, 0.9) 0%,
        rgba(190, 225, 255, 0.5) 22%,
        rgba(140, 190, 255, 0.26) 50%,
        rgba(100, 160, 250, 0.1) 74%,
        rgba(100, 160, 250, 0) 100%);
    filter: blur(3px);
    pointer-events: none;
    animation: cometPlasma 0.6s ease-in-out infinite alternate;
}
.random-bonus.comet.reverse .comet-tail-plasma {
    transform: rotate(var(--comet-rot, 120deg));
}
@keyframes cometPlasma {
    from { opacity: 0.75; }
    to   { opacity: 1; }
}
/* Queue de poussiere : panache plus large, teinte dorée. Alignee sur le
   MEME axe que la queue de plasma (l'ancien decalage -15deg etait lu
   comme un defaut d'alignement avec la direction du vol). */
.comet-tail-dust {
    position: absolute;
    left: calc(var(--nx) - 144.44%);
    top: calc(var(--ny) - 18.33%);
    width: 144.44%;
    height: 36.67%;
    transform-origin: 100% 50%;
    transform: rotate(var(--comet-rot, 60deg));
    border-radius: 50% 45% 45% 50% / 65% 50% 50% 65%;
    background: linear-gradient(270deg,
        rgba(255, 235, 190, 0.42) 0%,
        rgba(250, 210, 150, 0.22) 34%,
        rgba(230, 180, 120, 0.1) 62%,
        rgba(230, 180, 120, 0) 100%);
    filter: blur(5px);
    pointer-events: none;
    animation: cometDust 0.7s ease-in-out infinite alternate;
}
.random-bonus.comet.reverse .comet-tail-dust {
    transform: rotate(var(--comet-rot, 120deg));
}
@keyframes cometDust {
    from { opacity: 0.7; }
    to   { opacity: 0.95; }
}
/* Particules de queue : coeur brillant et poussiere, vie longue,
   derive vers l'arriere pilotee en JS */
.comet-trail {
    position: fixed;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    pointer-events: none;
    /* Comme les cometes : devant les modals et la nav */
    z-index: 9999;
    transform: translate(-50%, -50%);
    transition: opacity 900ms linear, transform 900ms ease-out;
}
.comet-trail.core {
    width: 20px;
    height: 20px;
    background: radial-gradient(circle, rgba(255,255,255,0.95) 0%, rgba(200,230,255,0.45) 45%, transparent 75%);
}
.comet-trail.dust {
    width: 11px;
    height: 11px;
    background: radial-gradient(circle, rgba(255,225,180,0.7) 0%, rgba(240,190,130,0.28) 55%, transparent 80%);
}
/* Missile d'interception : sprite PNG du joueur, bande centrale horizontale
   (nez a gauche, flamme a droite). Le conteneur est oriente par le JS selon
   l'angle de vol ; l'image est retournee de 180° pour aligner le nez sur
   l'axe +x du conteneur, donc sur la direction du vol. */
.comet-missile {
    position: fixed;
    /* Taille adaptative : ratio 4:3 du sprite conserve, mobile via --mscale */
    width: clamp(calc(84px * var(--mscale, 1)), 11vw, 150px);
    height: clamp(calc(63px * var(--mscale, 1)), calc(8.25vw), 112px);
    /* Comme les cometes (z-index 10000) : le missile passe devant les
       modals, la nav et la lightbox. */
    z-index: 10001;
    pointer-events: none;
    will-change: left, top, transform;
}
.comet-missile img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    transform: rotate(180deg);
    filter: drop-shadow(0 3px 8px rgba(0, 0, 0, 0.5));
    user-select: none;
    -webkit-user-drag: none;
}
/* ===== Explosion de la comète : flash, boule de feu, ondes, étincelles, fumée ===== */
.comet-explosion {
    position: fixed;
    width: 0;
    height: 0;
    /* L'explosion passe devant tout, au-dessus du missile */
    z-index: 10002;
    pointer-events: none;
}
/* Lueur globale : éclat doux qui éclaire la zone puis retombe */
.exp-light {
    position: absolute;
    width: calc(340px * var(--es, 1));
    height: calc(340px * var(--es, 1));
    border-radius: 50%;
    transform: translate(-50%, -50%);
    background: radial-gradient(circle, rgba(255, 244, 214, 0.95) 0%, rgba(255, 190, 90, 0.55) 30%, rgba(255, 150, 50, 0) 68%);
    animation: expLight 0.55s ease-out forwards;
}
@keyframes expLight {
    0%   { transform: translate(-50%, -50%) scale(0.25); opacity: 1; }
    55%  { opacity: 0.85; }
    100% { transform: translate(-50%, -50%) scale(1.15); opacity: 0; }
}
/* Coeur blanc : flash suraigu au point d'impact */
.exp-core {
    position: absolute;
    width: calc(44px * var(--es, 1));
    height: calc(44px * var(--es, 1));
    border-radius: 50%;
    transform: translate(-50%, -50%);
    background: radial-gradient(circle, #ffffff 0%, #fff4c8 55%, rgba(255, 235, 160, 0) 75%);
    animation: expCore 0.4s cubic-bezier(0.2, 0.8, 0.4, 1) forwards;
}
@keyframes expCore {
    0%   { transform: translate(-50%, -50%) scale(0.15); opacity: 1; }
    70%  { opacity: 1; }
    100% { transform: translate(-50%, -50%) scale(3); opacity: 0; }
}
/* Boule de feu : orange vif, grossit en s'éteignant */
.exp-fireball {
    position: absolute;
    width: calc(90px * var(--es, 1));
    height: calc(90px * var(--es, 1));
    border-radius: 50%;
    transform: translate(-50%, -50%);
    background: radial-gradient(circle, #fff7d6 0%, #ffd23f 28%, #ff8a00 58%, rgba(255, 61, 0, 0.85) 82%, rgba(255, 61, 0, 0) 100%);
    filter: blur(2px);
    animation: expFireball 0.6s cubic-bezier(0.2, 0.75, 0.35, 1) forwards;
}
@keyframes expFireball {
    0%   { transform: translate(-50%, -50%) scale(0.2) rotate(0deg); opacity: 1; }
    45%  { opacity: 1; }
    100% { transform: translate(-50%, -50%) scale(2.1) rotate(18deg); opacity: 0; }
}
/* Ondes de choc : deux anneaux qui se propagent, le second en retard */
.exp-ring {
    position: absolute;
    width: calc(14px * var(--es, 1));
    height: calc(14px * var(--es, 1));
    border-radius: 50%;
    border: 3px solid rgba(255, 236, 180, 0.95);
    box-shadow: 0 0 14px rgba(255, 200, 100, 0.55), inset 0 0 10px rgba(255, 220, 140, 0.4);
    transform: translate(-50%, -50%);
    animation: expRing 0.62s cubic-bezier(0.15, 0.8, 0.3, 1) forwards;
}
@keyframes expRing {
    0%   { transform: translate(-50%, -50%) scale(0.3); opacity: 0.95; border-width: 4px; }
    100% { transform: translate(-50%, -50%) scale(11); opacity: 0; border-width: 1px; }
}
/* Étincelles : traits incandescents projetés dans toutes les directions */
.exp-spark {
    position: absolute;
    left: 0;
    top: 0;
    width: var(--ssize, 4px);
    height: var(--ssize, 4px);
    border-radius: 50%;
    background: radial-gradient(circle, #ffffff 0%, #ffe38a 45%, #ff9b2f 100%);
    box-shadow: 0 0 6px 1px rgba(255, 170, 60, 0.85);
    transform: translate(-50%, -50%);
    animation: expSpark var(--sd, 0.6s) cubic-bezier(0.15, 0.85, 0.45, 1) forwards;
}
@keyframes expSpark {
    0%   { transform: translate(-50%, -50%) rotate(0deg) scale(1.1); opacity: 1; }
    60%  { opacity: 1; }
    100% { transform: translate(calc(-50% + var(--sx)), calc(-50% + var(--sy))) rotate(var(--sr, 0deg)) scale(0.25); opacity: 0; }
}
/* Fumée : bouffées gris-bleu qui s'étendent en s'élevant doucement */
.exp-smoke {
    position: absolute;
    left: 0;
    top: 0;
    width: calc(56px * var(--es, 1));
    height: calc(56px * var(--es, 1));
    border-radius: 50%;
    background: radial-gradient(circle, rgba(186, 192, 204, 0.5) 0%, rgba(140, 146, 160, 0.32) 45%, rgba(120, 126, 140, 0) 72%);
    filter: blur(5px);
    transform: translate(-50%, -50%);
    animation: expSmoke 0.95s ease-out forwards;
    animation-delay: var(--sdelay, 0s);
    opacity: 0;
}
@keyframes expSmoke {
    0%   { transform: translate(-50%, -50%) scale(calc(0.35 * var(--sscale, 1))); opacity: 0; }
    18%  { opacity: 0.85; }
    100% { transform: translate(calc(-50% + var(--sx)), calc(-50% + var(--sy))) scale(calc(1.5 * var(--sscale, 1))); opacity: 0; }
}
/* Comètes de la pluie d'événement : plus petites, teinte dorée */
.random-bonus.shower {
    width: 120px;
    height: 120px;
}
.random-bonus.shower .comet-img {
    width: 120px;
    height: 120px;
    filter: sepia(0.5) saturate(1.6) hue-rotate(-12deg) brightness(1.15);
    animation: showerGlow 0.5s ease-in-out infinite alternate;
}
@keyframes showerGlow {
    from { opacity: 0.85; }
    to   { opacity: 1; }
}
.random-bonus.clicked {
    opacity: 0;
    transform: scale(0.5);
    transition: all 0.5s;
    pointer-events: none;
}
/* +X du clic : part du point de clique vers une direction aleatoire
   (--ce-dx/--ce-dy), avec une legere rotation, a vitesse lisible. */
@keyframes clickBurst {
    0% { opacity: 0; transform: translate(-50%, -50%) scale(0.5); }
    12% { opacity: 1; transform: translate(calc(-50% + var(--ce-dx, 0px) * 0.25), calc(-50% + var(--ce-dy, 0px) * 0.25)) scale(1.2); }
    100% { opacity: 0; transform: translate(calc(-50% + var(--ce-dx, 0px)), calc(-50% + var(--ce-dy, 0px))) rotate(var(--ce-rot, 0deg)) scale(0.95); }
}
/* Feedback d'achat : popup flottant au-dessus de la carte du batiment.
   Deux lignes : cout en rouge (montee rapide), gain de production en vert
   (apparition decalee). Position absolue dans la carte, sans decaler la mise
   en page. */
/* Cout et gain partent du meme ancrage mais s'ecartent en V : le cout
   file vers la gauche, le gain vers la droite -- plus aucune
   superposition pendant la montee. */
@keyframes buyFeedbackInCost {
    0% { opacity: 0; transform: translate(-50%, 8px) scale(0.7); }
    14% { opacity: 1; transform: translate(-108%, -8px) scale(1.08); }
    75% { opacity: 1; transform: translate(-115%, -28px) scale(1); }
    100% { opacity: 0; transform: translate(-122%, -48px) scale(0.92); }
}
@keyframes buyFeedbackInGain {
    0% { opacity: 0; transform: translate(-50%, 8px) scale(0.7); }
    14% { opacity: 1; transform: translate(8%, -14px) scale(1.08); }
    75% { opacity: 1; transform: translate(15%, -34px) scale(1); }
    100% { opacity: 0; transform: translate(22%, -54px) scale(0.92); }
}
.buy-feedback {
    position: fixed;
    font-size: 1.37rem;
    font-weight: 800;
    white-space: nowrap;
    pointer-events: none;
    z-index: 13000;
    animation-duration: 2.2s;
    animation-timing-function: ease-out;
    animation-fill-mode: forwards;
    opacity: 0;
    text-shadow: 0 1px 4px rgba(0, 0, 0, 0.95), 0 0 10px rgba(0, 0, 0, 0.5);
}
.buy-feedback-cost { color: #ff6b6b; animation-name: buyFeedbackInCost; animation-delay: 0s; }
.buy-feedback-gain { color: #7CFC98; animation-name: buyFeedbackInGain; animation-delay: 0.45s; }
/* Flash de la carte "Prochaine etape" quand une piece est construite */
@keyframes partBuiltFlash {
    0% { box-shadow: 0 0 0 0 rgba(255, 215, 0, 0); }
    25% { box-shadow: 0 0 22px 6px rgba(255, 215, 0, 0.65); }
    100% { box-shadow: 0 0 0 0 rgba(255, 215, 0, 0); }
}
.rocket-part-frame.part-built-flash { animation: partBuiltFlash 1.2s ease-out; }
/* Gros popup central de reussite du lancement : distance en grand */
@keyframes launchRewardIn {
    0% { opacity: 0; transform: translate(-50%, -50%) scale(0.4); }
    14% { opacity: 1; transform: translate(-50%, -50%) scale(1.15); }
    22% { transform: translate(-50%, -50%) scale(1); }
    78% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
    100% { opacity: 0; transform: translate(-50%, -50%) scale(1.25); }
}
.launch-reward {
    position: fixed;
    left: 50%;
    top: 42%;
    transform: translate(-50%, -50%);
    text-align: center;
    pointer-events: none;
    z-index: 12000;
    opacity: 0;
    animation: launchRewardIn 2.8s ease-out forwards;
}
.launch-reward-emoji {
    display: block;
    font-size: 4rem;
    line-height: 1;
    margin-bottom: 6px;
}
.launch-reward-distance {
    display: block;
    font-size: 2.6rem;
    font-weight: 900;
    color: var(--accent-light);
    text-shadow: 0 0 18px rgba(255, 215, 0, 0.6), 0 2px 6px rgba(0, 0, 0, 0.9);
    white-space: nowrap;
}
.launch-reward-label {
    display: block;
    font-size: 1.1rem;
    font-weight: 700;
    color: #fff;
    text-shadow: 0 1px 4px rgba(0, 0, 0, 0.9);
    margin-top: 4px;
}

.click-effect {
    position: absolute;
    color: var(--accent-light);
    font-size: 1.9rem;
    font-weight: 800;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9), 0 0 14px rgba(255, 215, 0, 0.45);
    background: rgba(30, 58, 138, 0.82);
    border: 1px solid rgba(255, 215, 0, 0.55);
    padding: 4px 12px;
    border-radius: 8px;
    animation: clickBurst 1.4s ease-out forwards;
    opacity: 0;
    z-index: 1000;
    white-space: nowrap;
    pointer-events: none;
}

/* Coup CRITIQUE (x3) : le "+X" devient or eclatant, plus gros, avec
   un eclat lumineux -- immediatement reconnaissable au clic. */
.click-effect.crit {
    color: #fde047;
    font-size: 2.4rem;
    background: linear-gradient(135deg, rgba(120, 53, 15, 0.92), rgba(146, 64, 14, 0.92));
    border: 1px solid #fbbf24;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9), 0 0 20px rgba(251, 191, 36, 0.9);
    box-shadow: 0 0 22px rgba(251, 191, 36, 0.55);
    animation: clickBurstCrit 1.4s ease-out forwards;
}
@keyframes clickBurstCrit {
    0% { opacity: 0; transform: scale(0.4); }
    12% { opacity: 1; transform: scale(1.35); }
    22% { transform: scale(1.05); }
    100% { opacity: 0; transform: translateY(-70px) scale(1); }
}
/* Gros popup de bonus (+X Parts / Production x5) au centre de l'ecran,
   position et angle aleatoires. */
.bonus-pop {
    position: absolute;
    font-size: clamp(2rem, 4.5vw, 3.4rem);
    font-weight: 900;
    white-space: nowrap;
    transform: translate(-50%, -50%) rotate(var(--bpop-rot, 0deg));
    pointer-events: none;
    z-index: 1200;
    animation: bonusPop 1.9s cubic-bezier(0.22, 1.2, 0.36, 1) forwards;
    text-shadow: 0 3px 14px rgba(0, 0, 0, 0.85), 0 0 30px rgba(0, 0, 0, 0.5);
}
.bonus-pop-instant {
    color: var(--accent-light);
    filter: drop-shadow(0 0 18px rgba(255, 190, 40, 0.55));
}
.bonus-pop-mult {
    background: linear-gradient(90deg, #ff0080, #ff8c00, #ffee00, #00e676, #00b0ff, #b388ff, #ff0080);
    background-size: 200% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: bonusPop 1.9s cubic-bezier(0.22, 1.2, 0.36, 1) forwards,
               rainbow-slide 1.5s linear infinite;
}
@keyframes bonusPop {
    0% { opacity: 0; scale: 0.3; }
    14% { opacity: 1; scale: 1.15; }
    24% { scale: 1; }
    70% { opacity: 1; }
    100% { opacity: 0; scale: 0.92; }
}
#toast-container {
    position: fixed;
    bottom: 20px; left: 50%;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column-reverse;
    /* Toutes les notifications ont exactement la meme largeur */
    align-items: stretch;
    gap: 8px;
    z-index: 11000;
    pointer-events: none;
    /* Largeur commune a toutes les toasts, identique sur tous supports */
    width: min(94vw, 480px);
    max-width: 94vw;
}
.toast {
    position: relative;
    /* Cliquable : le tap ferme la notification ET absorbe le clic -- il ne
       doit PLUS passer au bouton situe derriere (ex. Lancer la fusee). */
    pointer-events: auto;
    cursor: pointer;
    background: var(--secondary-light);
    color: var(--text);
    padding: clamp(6px, 1vh, 10px) clamp(12px, 1.4vw, 20px);
    border-radius: var(--radius);
    font-size: clamp(0.85rem, 1vw + 0.35rem, 1.05rem);
    z-index: 11000;
    opacity: 0;
    transform: translateY(20px);
    transition: all 0.3s;
    box-shadow: var(--shadow-lg);
    border: 1px solid var(--border-light);
    box-sizing: border-box;
    width: 100%;
    justify-content: center;
    text-align: center;
}
.toast.active {
    transform: translateY(0);
    opacity: 1;
    cursor: pointer;
}
/* Toast d'ECHEC de contrat : rouge sombre, secousse a l'apparition —
   impossible a confondre avec une notification normale. */
/* Notification de trophee debloque : fond dore distingue des toasts
   neutres -- meme pattern que .failure mais en or de recompense. */
.toast.trophy {
    background: linear-gradient(135deg, #78350f, #92400e);
    border: 1px solid #fbbf24;
    color: #fef3c7;
    font-weight: 700;
    box-shadow: 0 4px 18px rgba(251, 191, 36, 0.35), var(--shadow-lg);
}
.toast.trophy .toast-icon { color: #fbbf24; }
.toast.trophy.active { animation: toast-trophy-glow 0.6s ease-out; }
@keyframes toast-trophy-glow {
    0%   { box-shadow: 0 0 0 rgba(251, 191, 36, 0); }
    50%  { box-shadow: 0 0 26px rgba(251, 191, 36, 0.6); }
    100% { box-shadow: 0 4px 18px rgba(251, 191, 36, 0.35); }
}
.toast.failure {
    background: linear-gradient(135deg, #7f1d1d, #991b1b);
    border: 1px solid #f87171;
    color: #fecaca;
    font-weight: 700;
}
.toast.failure .toast-icon {
    color: #f87171;
}
.toast.failure.active {
    animation: toast-shake 0.4s ease-out;
}
@keyframes toast-shake {
    0%   { transform: translateX(0); }
    20%  { transform: translateX(-8px); }
    40%  { transform: translateX(7px); }
    60%  { transform: translateX(-5px); }
    80%  { transform: translateX(3px); }
    100% { transform: translateX(0); }
}
.coin-icon {
    display: inline-block;
    width: 18px;
    height: 18px;
    object-fit: contain;
    vertical-align: -3px;
    margin-right: 2px;
}
.toast-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    margin-right: 13px;
    vertical-align: middle;
    flex-shrink: 0;
}
.toast-icon img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}
/* Building blur effect for not purchased buildings */
.building-item.not-purchased .building-left,
.building-item.not-purchased .building-center {
    opacity: 0.45;
    filter: blur(5px);
}
/* Styles for random bonuses */
/* TROPHIES */
.trophy-icon {
    width: 50px;
    height: 50px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem;
    cursor: pointer;
    position: relative;
    transition: all 0.2s;
    border: 2px solid var(--border-light);
    background: var(--secondary);
    color: var(--text);
}
.trophy-icon:hover {
    transform: scale(1.1);
    box-shadow: var(--shadow-lg);
}
.trophy-icon.unlocked {
    background: linear-gradient(135deg, var(--primary), var(--primary-dark));
    border-color: var(--primary-light);
    opacity: 1;
}
.trophy-icon.locked {
    opacity: 0.4;
    filter: grayscale(100%);
}
/* RESPONSIVE */
@media (max-width: 992px) and (pointer: coarse) {
    .top-bar-controls { flex-direction: row; gap: calc(8px * var(--mscale, 1)); }
    .control-button { width: calc(40px * var(--mscale, 1)); height: calc(40px * var(--mscale, 1)); font-size: calc(16px * var(--mscale, 1)); }
}
@media (max-width: 768px) and (pointer: coarse) {
    .galactic-shop-btn { font-size: 0.85rem; padding: calc(6px * var(--mscale, 1)) calc(8px * var(--mscale, 1)); }
}
@media (max-width: 480px) and (pointer: coarse) {
    .medal { width: calc(90px * var(--mscale, 1)); height: calc(90px * var(--mscale, 1)); }
}
/* ============================================
   ROCKET LAUNCH SYSTEM
   ============================================ */
/* Launch Button */
.launch-button:hover {
    /* translateX(-50%) conserve : le bouton est ancre left:50%, sans lui il
       saute a droite (visible surtout au tap mobile, ou :hover est collant). */
    transform: translateX(-50%) translateY(-3px);
    box-shadow: var(--shadow-lg), 0 0 30px rgba(239, 68, 68, 0.6);
    background: linear-gradient(135deg, #f87171, #ef4444);
}
.launch-button:active {
    transform: translateX(-50%) translateY(1px);
    background: linear-gradient(135deg, #dc2626, #b91c1c);
}
.launch-button.ready {
    display: flex;
    animation: launch-btn-appear 0.45s cubic-bezier(0.22, 1.2, 0.36, 1);
}
@keyframes launch-btn-appear {
    from { opacity: 0; transform: translateX(-50%) translateY(18px) scale(0.9); }
    to { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
}
.launch-button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    /* Conserve le centrage translateX(-50%) : le bouton est ancre left:50% ;
       sans lui, il saute a droite pendant l'etat disabled du lancement. */
    transform: translateX(-50%);
}
/* Launch Results Modal */
.launch-modal {
    background: linear-gradient(135deg, var(--bg-panel), var(--secondary-light));
    border: 2px solid var(--primary-light);
    box-shadow: 0 0 30px rgba(30, 58, 138, 0.3);
    width: 100%;
    height: auto;
    max-height: 80vh;
}
#launch-results-modal {
    top: 50%;
    transform: translate(-50%, -50%);
    width: 92%;
    max-width: 460px;
    height: auto;
    max-height: 80vh;
}
.launch-modal .modal-header {
    background: linear-gradient(135deg, var(--primary), var(--primary-dark));
    border-bottom: 2px solid var(--primary-light);
}
.launch-modal .modal-header h2 {
    color: white;
}
.launch-result-item {
    display: flex;
    justify-content: space-between;
    padding: 15px 20px;
    margin: 10px 0;
    background: rgba(30, 58, 138, 0.1);
    border-radius: var(--radius);
    border-left: 4px solid var(--primary-light);
}
.launch-label {
    font-weight: 600;
    color: var(--text-light);
}
.launch-value {
    font-weight: 700;
    color: var(--accent-light);
    font-size: 1.2rem;
}
.launch-info {
    background: rgba(245, 158, 11, 0.1);
    border: 1px solid var(--accent);
    border-radius: var(--radius);
    padding: 15px;
    margin-top: 20px;
    text-align: center;
}
.launch-info p {
    color: var(--accent-light);
    font-style: italic;
}
/* Destination atteinte : ligne mise en avant au-dessus des autres resultats */
.launch-destination-line {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 12px;
    margin-bottom: 10px;
    background: rgba(16, 185, 129, 0.12);
    border: 1px solid rgba(16, 185, 129, 0.5);
    border-radius: var(--radius);
}
.launch-destination-line .launch-value {
    color: #34d399;
}
/* Bouton NOUVELLE EXPEDITION de la modale de resultats : meme style que
   le bouton Continuer de l'atelier (vert d'action, pulse discret). */
.launch-new-expedition-btn {
    display: block;
    width: 100%;
    margin-top: 18px;
    background: linear-gradient(135deg, #10b981, #059669);
    color: white;
    border: none;
    border-radius: var(--radius);
    padding: 14px 36px;
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    cursor: pointer;
    transition: all 0.3s ease;
    box-shadow: var(--shadow-lg);
}
.launch-new-expedition-btn:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg), 0 0 24px rgba(16, 185, 129, 0.5);
}
/* Note "Chaque expedition part de la Terre" dans le resume de l'atelier */
.pts-expedition-note {
    margin-top: 10px;
    font-size: 0.85rem;
    font-style: italic;
    color: var(--text-muted, #94a3b8);
    text-align: center;
}
/* ============================================
   SEQUENCE DE LANCEMENT (décollage cinématique)
   ============================================ */
.launch-overlay {
    position: absolute;
    inset: 0;
    z-index: 50;
    pointer-events: none;
}
.launch-countdown {
    position: absolute;
    top: 12%;
    left: 50%;
    transform: translateX(-50%);
    font-size: 3.2rem;
    font-weight: 800;
    color: #fff;
    text-shadow: 0 0 24px rgba(59, 130, 246, 0.9), 0 2px 6px rgba(0, 0, 0, 0.8);
    font-variant-numeric: tabular-nums;
    transition: opacity 0.4s ease;
}
.launch-countdown.pulsing {
    animation: launchCountdownPulse 0.7s ease-in-out infinite;
}
.launch-countdown.fading {
    animation: launchCountdownFade 0.5s ease forwards;
}
@keyframes launchCountdownPulse {
    0% { transform: translateX(-50%) scale(1); }
    50% { transform: translateX(-50%) scale(1.25); }
    100% { transform: translateX(-50%) scale(1); }
}
@keyframes launchCountdownFade {
    to { opacity: 0; transform: translateX(-50%) scale(1.6); }
}
/* Tremblement pré-lancement : SEULE la fusée vibre (pas le pas de tir
   ni l'astronaute). Le wrapper porte le transform de base du container :
   le shake en margin-left évite d'écraser ce transform. */
.launch-rocket-wrap {
    position: relative;
    width: 100%;
}
/* Tremblement d'ENSEMBLE : la propriete translate est composited, le
   calque du wrapper bouge d'un bloc (moteurs, reservoir, boosters et
   tuyeres restent soudes, aucun interstice ne s'ouvre entre eux). */
.launch-rocket-wrap.launch-shaking {
    animation: launchShake 0.12s linear infinite;
}
@keyframes launchShake {
    0% { translate: 0 0; }
    25% { translate: -1.5px 0.4px; }
    50% { translate: 1.5px -0.4px; }
    75% { translate: -1px 0.3px; }
    100% { translate: 0 0; }
}
/* Décollage : accélération réaliste (lente au départ, rapide ensuite) */
.launch-rocket-wrap.lift-off {
    animation: launchLiftOff 1.9s cubic-bezier(0.55, 0, 0.85, 0.4) forwards;
}
@keyframes launchLiftOff {
    0% { opacity: 1; }
    8% { transform: translate3d(0, 0, 0) scale(1); }
    100% { transform: translate3d(0, -110vh, 0) scale(1.05); opacity: 0; }
}
/* Astronaute : place a GAUCHE du pas de tir ; des le clic sur Lancer,
   il effectue un SALTO ARRIERE complet pour entrer dans le cockpit de
   la fusée (monde 1024px) : petite flexion d'anticipation vers l'arriere,
   impulsion, rotation 360 degres sur l'apex de l'arc de saut, puis
   reception dans le cockpit (x=50%, y~314) et disparition douce.
   Uniquement transform + opacity : anime sur le compositeur GPU. */
.astronaut-jumping {
    animation: astronautBackflipToCockpit 1.4s cubic-bezier(0.33, 0, 0.25, 1) forwards !important;
    will-change: transform, opacity;
}
@keyframes astronautBackflipToCockpit {
    0%   { transform: translate(-50%, 0) rotate(0deg) scale(1); opacity: 1; }
    8%   { transform: translate(calc(-50% - 8px), 14px) rotate(6deg) scale(0.96, 1.04); opacity: 1; }
    16%  { transform: translate(calc(-50% + 14px), -46px) rotate(-30deg) scale(1); opacity: 1; }
    38%  { transform: translate(calc(-50% + 58px), -168px) rotate(-175deg) scale(1); opacity: 1; }
    58%  { transform: translate(calc(-50% + 88px), -252px) rotate(-300deg) scale(1); opacity: 1; }
    74%  { transform: translate(calc(-50% + 100px), -300px) rotate(-360deg) scale(1); opacity: 1; }
    86%  { transform: translate(calc(-50% + 104px), -312px) rotate(-360deg) scale(1); opacity: 0.9; }
    100% { transform: translate(calc(-50% + 106px), -318px) rotate(-360deg) scale(1); opacity: 0; }
}
/* Flammes sous les moteurs : jets coniques orangés vacillants.
   Ancrées au bas des tuyères (y=666) : le HAUT des jets affleure les
   tuyères (top:0 dans le conteneur posé à top:666px), elles suivent
   la fusée pendant tout le vol. */
/* Conteneur PLEINE LARGEUR (repere monde) : les jets sont places en %
   depuis ROCKET_PARTS (x=50% moteurs, x=45.8%/54.2% boosters), le % doit
   s'appliquer sur toute la largeur de la fusee, pas sur une boite de 120px. */
.launch-flames {
    position: absolute;
    top: 666px;
    left: 0;
    width: 100%;
    height: 140px;
    pointer-events: none;
    z-index: 2;
}
/* Flammes moteur style jeu video 2D : coeur incandescent + double halo
   (orange puis rouge) + pointes dynamiques, pulsation rapide. */
/* Flamme moteur REALISTE, couchee comme une vraie flamme de fusee :
   - base BLEUE juste sous la tuyere (combustion incomplete)
   - coeur BLANC-JAUNE compact et stable (le plus chaud, pres moteur)
   - colonne ORANGE translucide qui s'affine
   - panache ROUGE FUMEUX en pointe, consume
   Oscillation douce en LARGEUR uniquement, pas de va-et-vient en longueur. */
.launch-flame-jet {
    position: absolute;
    top: 0;
    width: 28px;
    height: 86px;
    background:
        /* panache rouge fumeux en pointe */
        linear-gradient(180deg, rgba(255, 110, 20, 0) 62%, rgba(255, 80, 0, 0.35) 78%, rgba(200, 40, 0, 0.12) 92%, rgba(160, 30, 0, 0) 100%),
        /* colonne orange translucide */
        linear-gradient(180deg, rgba(255, 200, 80, 0.95) 18%, rgba(255, 160, 40, 0.75) 45%, rgba(255, 110, 20, 0.4) 65%, rgba(255, 90, 10, 0) 88%),
        /* coeur blanc-jaune compact */
        radial-gradient(ellipse 55% 26% at 50% 10%, rgba(255, 255, 255, 0.98) 0%, rgba(255, 245, 190, 0.9) 45%, rgba(255, 230, 120, 0) 80%);
    border-radius: 46% 54% 50% 50% / 58% 62% 42% 38%;
    filter: blur(1.4px) drop-shadow(0 0 10px rgba(255, 170, 60, 0.55)) drop-shadow(0 0 22px rgba(255, 90, 10, 0.3));
    transform-origin: 50% 0;
    animation: launchFlameJet 0.22s ease-in-out infinite alternate;
}
/* Base BLEUE de la flamme : anneau de combustion incomplete colle a la tuyere */
.launch-flame-jet::before {
    content: '';
    position: absolute;
    top: 0;
    left: 50%;
    width: 100%;
    height: 34%;
    transform: translateX(-50%);
    background: radial-gradient(ellipse 62% 72% at 50% 18%, rgba(120, 180, 255, 0.85) 0%, rgba(80, 140, 255, 0.5) 45%, rgba(60, 110, 240, 0) 78%);
    filter: blur(1.8px);
    animation: launchFlameBase 0.18s ease-in-out infinite alternate;
}
/* Pointe : leger frisson de consume, amplitude faible */
.launch-flame-jet::after {
    content: '';
    position: absolute;
    top: 52%;
    left: 50%;
    width: 48%;
    height: 52%;
    transform: translateX(-50%);
    background: linear-gradient(180deg, rgba(255, 130, 30, 0.5) 0%, rgba(230, 70, 0, 0.3) 50%, rgba(180, 40, 0, 0) 100%);
    border-radius: 50% 50% 46% 54% / 42% 42% 62% 58%;
    filter: blur(2.4px);
    animation: launchFlameTip 0.19s ease-in-out infinite alternate;
}
@keyframes launchFlameBase {
    from { transform: translateX(-50%) scaleX(0.94); opacity: 0.8; }
    to { transform: translateX(-50%) scaleX(1.08); opacity: 1; }
}
@keyframes launchFlameTip {
    from { transform: translateX(-50%) scaleY(0.85) scaleX(1.08); opacity: 0.75; }
    to { transform: translateX(-50%) scaleY(1.12) scaleX(0.9); opacity: 1; }
}
/* Positions des jets calculees en JS depuis ROCKET_PARTS (left en %).
   Jets desynchronises, oscillation en LARGEUR seulement (realiste). */
.launch-flame-jet:nth-child(2) { animation-name: launchFlameJet2; animation-duration: 0.19s; }
.launch-flame-jet:nth-child(3) { animation-name: launchFlameJet3; animation-duration: 0.25s; }
@keyframes launchFlameJet {
    from { transform: scaleX(0.94); opacity: 0.94; }
    to { transform: scaleX(1.06); opacity: 1; }
}
@keyframes launchFlameJet2 {
    from { transform: scaleX(1.05); opacity: 1; }
    to { transform: scaleX(0.93); opacity: 0.92; }
}
@keyframes launchFlameJet3 {
    from { transform: scaleX(0.97); opacity: 0.96; }
    to { transform: scaleX(1.04); opacity: 1; }
}
/* Fumée au sol qui déborde du pas de tir (reste au sol pendant le vol) */
.launch-smoke {
    position: absolute;
    /* Repere monde (1024x744) : la base de la fusée est à y=636 (remontée
       de 50px), on pose la fumée juste dessous, sur la ligne de sol */
    bottom: 96px;
    left: 50%;
    width: 420px;
    height: 210px;
    transform: translateX(-50%);
    background:
        radial-gradient(ellipse 42% 30% at 50% 92%, rgba(240, 243, 248, 0.98) 0%, rgba(210, 215, 224, 0.6) 50%, rgba(190, 195, 205, 0) 78%),
        radial-gradient(ellipse 65% 40% at 50% 96%, rgba(215, 220, 230, 0.9) 0%, rgba(175, 180, 192, 0.55) 55%, rgba(160, 165, 178, 0) 80%),
        radial-gradient(ellipse 90% 34% at 50% 100%, rgba(195, 200, 212, 0.65) 0%, rgba(170, 175, 188, 0) 75%),
        radial-gradient(ellipse 30% 22% at 42% 88%, rgba(245, 247, 251, 0.9) 0%, rgba(205, 210, 220, 0.4) 60%, rgba(190, 195, 205, 0) 80%),
        radial-gradient(ellipse 28% 20% at 60% 90%, rgba(245, 247, 251, 0.85) 0%, rgba(205, 210, 220, 0.4) 60%, rgba(190, 195, 205, 0) 80%);
    border-radius: 50%;
    filter: blur(12px);
    pointer-events: none;
    z-index: 4;
    animation: launchSmokeSpread 3.4s ease-out forwards;
}
/* Jaillissements lateraux : deux jets de vapeur qui debordent du pas de tir */
.launch-smoke::before,
.launch-smoke::after {
    content: '';
    position: absolute;
    bottom: 6%;
    width: 75%;
    height: 78%;
    background: radial-gradient(ellipse at center, rgba(225, 228, 236, 0.9) 0%, rgba(200, 205, 215, 0.55) 50%, rgba(190, 195, 208, 0) 75%);
    border-radius: 50%;
    filter: blur(8px);
}
.launch-smoke::before { left: -22%; animation: launchSmokeBurstL 3.4s ease-out forwards; }
.launch-smoke::after { right: -22%; animation: launchSmokeBurstR 3.4s ease-out forwards; }
@keyframes launchSmokeBurstL {
    0% { transform: translateX(0) scale(0.2); opacity: 0; }
    18% { opacity: 1; }
    100% { transform: translateX(-70%) scale(1.35); opacity: 0; }
}
@keyframes launchSmokeBurstR {
    0% { transform: translateX(0) scale(0.2); opacity: 0; }
    18% { opacity: 1; }
    100% { transform: translateX(70%) scale(1.35); opacity: 0; }
}
@keyframes launchSmokeSpread {
    0% { transform: translateX(-50%) scale(0.3); opacity: 0; }
    15% { opacity: 1; }
    55% { opacity: 0.85; }
    100% { transform: translateX(-50%) scale(2.8); opacity: 0; }
}
/* ============================================
   ANIMATION DE VOYAGE (plein ecran, verticale, mobile-first)
   ============================================ */
.travel-overlay {
    position: fixed;
    inset: 0;
    z-index: 9000;
    background: linear-gradient(180deg, #02030f 0%, #0b1030 55%, #1a2a5e 100%);
    display: none;
    overflow: hidden;
    pointer-events: none;
}
.travel-overlay.active {
    display: block;
    pointer-events: auto;
}
/* Fond lointain : nebuleuses + poussiere d'etoiles statique. Couche la
   plus profonde, derriere les etoiles parallaxe. */
.travel-deepfield {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
}
.travel-nebula {
    position: absolute;
    width: 70vmin;
    height: 70vmin;
    border-radius: 50%;
    background: radial-gradient(circle at 40% 40%,
        rgba(88, 60, 180, 0.22) 0%,
        rgba(58, 40, 130, 0.14) 38%,
        rgba(30, 25, 80, 0.07) 62%,
        transparent 78%);
    filter: blur(6px);
    transform: translate(-50%, -50%);
    animation: nebulaDrift 26s ease-in-out infinite alternate;
}
.travel-nebula.nebula-b {
    width: 90vmin;
    height: 90vmin;
    background: radial-gradient(circle at 55% 55%,
        rgba(20, 110, 150, 0.16) 0%,
        rgba(18, 70, 120, 0.10) 40%,
        transparent 72%);
    animation-duration: 34s;
    animation-delay: -12s;
}
@keyframes nebulaDrift {
    from { transform: translate(-50%, -50%) scale(1); opacity: 0.85; }
    to   { transform: translate(-46%, -54%) scale(1.18); opacity: 1; }
}
.travel-dust {
    position: absolute;
    border-radius: 50%;
    background: #cdd8ff;
    opacity: 0.4;
    animation: travelStarTwinkle 2.6s ease-in-out infinite alternate;
}
/* Champ d'etoiles en parallaxe : positions pilotees en JS selon la
   profondeur propre a chaque etoile (le fond defile avec le voyage). */
.travel-stars {
    position: absolute;
    inset: 0;
    overflow: hidden;
}
.travel-star {
    position: absolute;
    border-radius: 50%;
    background: #fff;
    opacity: 0.8;
}
.travel-star.twinkle {
    animation: travelStarTwinkle 1.6s ease-in-out infinite alternate;
}
@keyframes travelStarTwinkle {
    from { opacity: 0.25; }
    to { opacity: 0.9; }
}
/* Trainees de vitesse : traits verticaux semi-transparents qui
   apparaissent avec la vitesse camera. z-index 0 : TOUJOURS derriere
   le calque des planetes (#travel-deep, z-index 1). */
.travel-streaks {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    z-index: 0;
}
.travel-streak {
    position: absolute;
    width: 2px;
    border-radius: 2px;
    background: linear-gradient(to bottom, transparent, rgba(255, 255, 255, 0.75), transparent);
    pointer-events: none;
    will-change: transform, opacity;
}
/* Fusee : vole vers le HAUT, meme image que la scene de construction.
   L'image body.webp pointe vers le haut, aucune rotation necessaire. */
/* Voile lumineux de la plongee galactique : quand la destination est le
   Centre Voie lactee, Andromede ou l'Amas de Virgo, la camera traverse le
   corps -- un voile radial chaud enveloppe l'ecran (pilote en JS).
   z-index 2 : AU-DESSUS des planetes (#travel-deep, z-index 1),
   SOUS la fusee (z-index 3) et le HUD. */
.travel-through-veil {
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0;
    z-index: 2;
    background:
        radial-gradient(ellipse 140% 100% at 50% 55%,
            rgba(255, 248, 227, 0.95) 0%,
            rgba(253, 224, 160, 0.75) 30%,
            rgba(190, 170, 255, 0.45) 62%,
            rgba(10, 8, 40, 0.2) 100%);
    transition: opacity 0.12s linear;
}

/* ---- Ecran de fin : premiere arrivee a l'Amas de Virgo ---- */
.game-ending-overlay {
    position: fixed;
    inset: 0;
    z-index: 13000;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: radial-gradient(ellipse at 50% 40%, rgba(30, 20, 80, 0.96) 0%, rgba(2, 4, 18, 0.99) 70%);
    overflow: hidden;
}
.game-ending-overlay.active { display: flex; }
.game-ending-fireworks {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
}
.game-ending-fireworks span {
    position: absolute;
    color: var(--accent, #fbbf24);
    opacity: 0;
    animation: endingSparkle 3s ease-in-out infinite;
    text-shadow: 0 0 12px rgba(251, 191, 36, 0.8);
}
@keyframes endingSparkle {
    0%, 100% { opacity: 0; transform: scale(0.5); }
    50% { opacity: 0.95; transform: scale(1.15); }
}
.game-ending-content {
    position: relative;
    max-width: 640px;
    width: 100%;
    text-align: center;
    background: linear-gradient(160deg, rgba(15, 15, 45, 0.92), rgba(5, 8, 30, 0.95));
    border: 2px solid var(--accent, #fbbf24);
    border-radius: 24px;
    padding: 40px 28px 32px;
    box-shadow: 0 0 60px rgba(251, 191, 36, 0.35), inset 0 0 40px rgba(120, 90, 255, 0.12);
    animation: endingPop 0.9s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes endingPop {
    from { opacity: 0; transform: scale(0.85) translateY(30px); }
    to { opacity: 1; transform: none; }
}
.game-ending-emoji {
    font-size: 64px;
    line-height: 1;
    margin-bottom: 12px;
    animation: endingFloat 3.5s ease-in-out infinite;
}
@keyframes endingFloat {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-8px); }
}
.game-ending-title {
    font-size: clamp(26px, 5vw, 40px);
    letter-spacing: 2px;
    color: #fff;
    margin: 0 0 10px;
    background: linear-gradient(90deg, #fff, var(--accent, #fbbf24), #c4b5fd);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}
.game-ending-planet {
    font-size: 18px;
    color: #e2e8f0;
    margin-bottom: 6px;
}
.game-ending-distance {
    font-size: 15px;
    color: #94a3b8;
    margin-bottom: 18px;
}
.game-ending-distance span { color: var(--accent, #fbbf24); font-weight: 700; }
.game-ending-divider {
    height: 1px;
    margin: 0 auto 18px;
    width: 70%;
    background: linear-gradient(90deg, transparent, rgba(251, 191, 36, 0.6), transparent);
}
.game-ending-infinite {
    background: linear-gradient(135deg, rgba(88, 28, 135, 0.35), rgba(30, 20, 80, 0.35));
    border: 1px solid rgba(196, 181, 253, 0.4);
    border-radius: 14px;
    padding: 14px 16px;
    margin-bottom: 22px;
}
.gei-title { font-size: 17px; font-weight: 700; color: #e9d5ff; margin-bottom: 6px; }
.gei-desc { font-size: 14px; color: #cbd5e1; line-height: 1.5; }
.gei-desc strong { color: var(--accent, #fbbf24); }
.game-ending-btn {
    font-family: inherit;
    font-size: 16px;
    font-weight: 800;
    letter-spacing: 1.5px;
    color: #1a1200;
    background: linear-gradient(135deg, #fbbf24, #f59e0b);
    border: none;
    border-radius: 14px;
    padding: 15px 34px;
    cursor: pointer;
    box-shadow: 0 6px 24px rgba(251, 191, 36, 0.45);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.game-ending-btn:hover {
    transform: translateY(-2px) scale(1.03);
    box-shadow: 0 10px 32px rgba(251, 191, 36, 0.6);
}

.travel-rocket {
    position: absolute;
    /* left/top/transform + dimensions pilotes en JS : la fusee complete
       (tuyeres -> bouclier) est reconstruite dedans a la bonne echelle. */
    z-index: 3;
}
.travel-rocket > div {
    position: absolute;
    inset: 0;
}
.travel-rocket img {
    pointer-events: none;
    filter: drop-shadow(0 0 10px rgba(0, 0, 0, 0.5));
}
/* Flammes des TROIS moteurs pendant le voyage : structure dediee
   injectee en JS (buildTravelRocketInto), proportionnelle au conteneur
   fusee. Chaque .travel-jet est ancre au centre d'une tuyere (20.8%,
   50.3%, 79.8% de la largeur -- mesures sur Fusee-travel.webp, sortie
   des tuyeres a ~86% de la hauteur). Chaque jet contient :
   .travel-flame-glow = lueur externe large et diffuse,
   .travel-flame-core = flamme principale (coeur blanc-jaune + colonne
   orange), .travel-flame-blue = base bleue de combustion incomplete,
   .travel-flame-tip = pointe fumeuse rouge. Jets desynchronises via
   animation-delay, oscillation surtout en largeur. */
.travel-rocket > .travel-flames {
    position: absolute;
    top: 86%;
    left: 0;
    right: auto;
    bottom: auto;
    width: 100%;
    height: 80%;
    pointer-events: none;
    --jet-w: 28%;
    --jet-h: 68%;
}
.travel-jet {
    position: absolute;
    top: 0;
    left: var(--jet-left, 50%);
    width: var(--jet-w);
    height: var(--jet-h);
    transform: translateX(-50%) scale(var(--jet-scale, 1));
    transform-origin: 50% 0;
    pointer-events: none;
    --jet-delay: 0s;
}
.travel-jet > .travel-flame-glow { animation-delay: var(--jet-delay); }
.travel-jet > .travel-flame-core { animation-delay: var(--jet-delay); }
.travel-jet > .travel-flame-tip { animation-delay: var(--jet-delay); }
.travel-jet div {
    position: absolute;
    transform-origin: 50% 0;
    pointer-events: none;
}
.travel-flame-glow {
    top: -6%;
    left: 50%;
    width: 190%;
    height: 78%;
    transform: translateX(-50%);
    background:
        radial-gradient(ellipse 55% 60% at 50% 14%, rgba(255, 190, 90, 0.42) 0%, rgba(255, 130, 40, 0.22) 45%, rgba(255, 90, 20, 0) 75%);
    border-radius: 50% 50% 45% 55% / 55% 60% 45% 40%;
    filter: blur(7px);
    animation: travelFlameGlow 0.31s ease-in-out infinite alternate;
}
.travel-flame-core {
    top: 0;
    left: 50%;
    width: 54%;
    height: 90%;
    transform: translateX(-50%);
    background:
        /* colonne orange translucide */
        linear-gradient(180deg, rgba(255, 200, 80, 0.95) 14%, rgba(255, 160, 40, 0.72) 42%, rgba(255, 110, 20, 0.38) 64%, rgba(255, 90, 10, 0) 88%),
        /* coeur blanc-jaune compact */
        radial-gradient(ellipse 55% 24% at 50% 9%, rgba(255, 255, 255, 0.98) 0%, rgba(255, 245, 190, 0.9) 45%, rgba(255, 230, 120, 0) 80%);
    border-radius: 46% 54% 50% 50% / 58% 62% 42% 38%;
    filter: blur(1.2px) drop-shadow(0 0 10px rgba(255, 170, 60, 0.6));
    animation: travelFlame 0.21s ease-in-out infinite alternate;
}
.travel-flame-blue {
    top: 0;
    left: 50%;
    width: 100%;
    height: 28%;
    transform: translateX(-50%);
    background:
        radial-gradient(ellipse 62% 74% at 50% 18%, rgba(130, 185, 255, 0.72) 0%, rgba(85, 145, 250, 0.4) 50%, rgba(60, 110, 240, 0) 82%);
    border-radius: 50%;
    filter: blur(1.6px);
}
.travel-flame-tip {
    top: 40%;
    left: 50%;
    width: 58%;
    height: 58%;
    transform: translateX(-50%);
    background:
        linear-gradient(180deg, rgba(255, 110, 20, 0) 0%, rgba(255, 80, 0, 0.32) 40%, rgba(200, 40, 0, 0.14) 72%, rgba(160, 30, 0, 0) 100%);
    border-radius: 50% 50% 46% 54% / 42% 42% 62% 58%;
    filter: blur(2.2px);
    animation: travelFlameTip 0.18s ease-in-out infinite alternate;
}
@keyframes travelFlameGlow {
    from { transform: translateX(-50%) scaleY(0.88) scaleX(0.95); opacity: 0.75; }
    to { transform: translateX(-50%) scaleY(1.12) scaleX(1.06); opacity: 1; }
}
@keyframes travelFlame {
    from { transform: translateX(-50%) scaleY(0.98) scaleX(0.94); opacity: 0.93; }
    to { transform: translateX(-50%) scaleY(1.02) scaleX(1.07); opacity: 1; }
}
@keyframes travelFlameTip {
    from { transform: translateX(-50%) scaleX(0.92); opacity: 0.7; }
    to { transform: translateX(-50%) scaleX(1.08); opacity: 1; }
}
/* Planetes d'arrivee : Terre en bas, Lune en haut (visible une fois proche) */
.travel-planet {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    pointer-events: none;
}
.travel-planet img {
    width: 100%;
    height: auto;
    display: block;
}
/* Calque des astres en profondeur : chaque planete est un div genere en
   JS (id travel-deep), place par la projection perspective. La largeur
   de reference est fixee en JS selon l'ecran ; ici on ne gere que le
   positionnement: left/top calcules + transform scale. */
#travel-deep {
    position: absolute;
    inset: 0;
    z-index: 1;            /* calque derriere la fusee (z-index 3) */
    pointer-events: none;
}
/* ---- Nuage d'Oort : champ volumetrique aux 5 images dediees ----
   Chaque objet est un div contenant l'une des 5 images utilisateur
   (images/effects/) : noyau glace, noyau de comete, fragment glace-roche,
   asteroide sombre, gros corps rare. --streak pilote le motion blur
   radial des fly-by. */
.travel-oort {
    position: absolute;
    will-change: transform, opacity;
    pointer-events: none;
    filter: blur(0.3px);
    --streak: 0;
}
.travel-oort img {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: contain;
    pointer-events: none;
    user-select: none;
    -webkit-user-drag: none;
}
.travel-body {
    position: absolute;
    width: 300px;
    max-width: none;
    will-change: transform, opacity;
}
.travel-body img {
    width: 100%;
    height: auto;
    display: block;
    border-radius: 50%;
    filter: drop-shadow(0 0 18px rgba(120, 160, 255, 0.25));
}
/* HUD : compteur de km en haut, bouton Passer en dessous */
.travel-hud {
    position: absolute;
    top: 4vh;
    left: 0;
    right: 0;
    z-index: 5;
    text-align: center;
}
.travel-distance {
    font-size: clamp(2rem, 9vw, 3.4rem);
    font-weight: 800;
    color: #fff;
    font-variant-numeric: tabular-nums;
    text-shadow: 0 0 24px rgba(59, 130, 246, 0.9), 0 2px 6px rgba(0, 0, 0, 0.8);
}
.travel-distance span {
    color: var(--blue-soft);
}
.travel-distance #travel-distance-value {
    display: inline-flex;
    align-items: baseline;
}
.travel-distance #travel-distance-value .cch,
.travel-distance #travel-distance-value .cch-sep {
    color: #fff;
}
.travel-skip {
    margin-top: 10px;
    padding: 8px 22px;
    background: rgba(0, 0, 0, 0.4);
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 999px;
    color: #fff;
    font-size: 0.95rem;
    cursor: pointer;
}
.travel-skip:active {
    transform: scale(0.96);
}
/* Sur petits ecans : fusee et planetes un peu plus petites */
/* (planetes et fusee de voyage dimensionnees en JS selon l'ecran) */
/* ============================================
   SPACE MAP STYLES
   ============================================ */
/* Space Connection Lines */
.space-connection {
    position: absolute;
    top: 50%;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--border-light), transparent);
    transform: translateY(-50%);
    z-index: 1;
}
.space-connection.active {
    background: linear-gradient(90deg, transparent, var(--primary-light), transparent);
}
/* Space Planets */
.space-planet {
    position: absolute;
    top: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    z-index: 2;
    transition: all 0.3s ease;
}
.space-planet .planet-emoji {
    font-size: 2rem;
    text-shadow: 0 0 10px var(--text);
}
.space-planet .planet-image {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    object-fit: cover;
    filter: drop-shadow(0 0 5px var(--planet-color));
}
.space-planet .planet-name {
    font-size: 0.8rem;
    color: var(--text-light);
    font-weight: 600;
}
.space-planet .planet-distance {
    font-size: 0.7rem;
    color: var(--text-dark);
}
.space-planet.unlocked .planet-emoji {
    text-shadow: 0 0 20px var(--planet-color);
    filter: drop-shadow(0 0 5px var(--planet-color));
}
.space-planet.unlocked .planet-name {
    color: var(--planet-color);
}
.space-planet.current .planet-emoji {
    animation: pulse 2s infinite;
}
.space-planet.current .planet-name {
    color: var(--accent-light);
}
.space-planet.origin .planet-name {
    color: #ffffff;
}
.space-planet.hidden .planet-unknown {
    border-radius: 50%;
    background: #000;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2.5rem;
    font-weight: bold;
    border: 2px solid var(--border);
    box-sizing: border-box;
}
.space-planet.hidden .planet-name,
.space-planet.hidden .planet-distance {
    color: var(--text-dark);
}
@keyframes pulse {
    0%, 100% { transform: translate(-50%, -50%) scale(1); }
    50% { transform: translate(-50%, -50%) scale(1.2); }
}
/* Spaceship */
.spaceship {
    position: absolute;
    top: 45%;
    transform: translateX(-50%);
    font-size: 1.5rem;
    z-index: 3;
    animation: fly 3s ease-in-out infinite;
}
@keyframes fly {
    0%, 100% { transform: translate(-50%, -50%) translateY(0) rotate(0deg); }
    50% { transform: translate(-50%, -50%) translateY(-5px) rotate(5deg); }
}
/* ============================================
   SPACE PROGRESS SIDEBAR
   ============================================ */
.left-panel {
    background: linear-gradient(180deg, var(--bg-panel), var(--secondary-light));
    border-right: 1px solid var(--border);
    padding: 15px;
    /* Le panel ne scrolle plus : le titre "Progression Spatiale" reste
       figé et SEUL le contenu en dessous defile (voir .left-panel-scroll). */
    display: flex;
    flex-direction: column;
    overflow: hidden;
    height: 100%;
    color: var(--text);
}
.left-panel-scroll {
    display: flex;
    flex-direction: column;
    gap: 15px;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior-y: contain;
}
/* Titre "Progression Spatiale" hors du flux scrollable : il ne bouge
   jamais, aucun contenu ne peut apparaitre derriere ou au-dessus de lui. */
.left-panel > h3 {
    flex: 0 0 auto;
}

/* Police display (Orbitron) : alignee sur les autres titres/boutons
   structurants du jeu (modales, en-tetes) -- avant, le bouton heritait
   de la police body (Space Grotesk), incoherent avec le reste. */
.galactic-shop-btn {
    font-family: var(--font-display);
    flex: 1 1 100%;
    min-width: 0;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 2px 6px;
    font-size: 0.9rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 10px 6px;
    background: rgba(167, 139, 250, 0.06);
    color: #c4b5fd;
    border: 1px solid rgba(167, 139, 250, 0.55);
    border-radius: 6px;
    cursor: pointer;
    text-align: center;
    transition: all 0.2s;
    flex-wrap: wrap;
    white-space: normal;
    overflow: hidden;
}
.galactic-shop-btn:hover {
    background: rgba(167, 139, 250, 0.25);
    box-shadow: 0 0 12px rgba(167, 139, 250, 0.4);
}
.galactic-shop-label {
    font-size: 0.9rem;
    font-weight: 700;
    min-width: 0;
    white-space: nowrap;
}
.galactic-shop-stardust {
    font-size: 0.9rem;
    font-weight: 600;
    color: #e9d5ff;
    /* Flex-shrink 0 : le compteur de poussiere d'etoiles ne se fait plus
       couper par le badge preview a droite -- si la place manque, c'est
       le preview (informatif, secondaire) qui cede. */
    flex: 0 0 auto;
    white-space: nowrap;
}
.galactic-shop-stardust span {
    color: #c4b5fd;
}
/* Largeur FIXE : le preview ne change plus de taille selon la
   longueur du nombre de PE affiche dedans -- le bouton Atelier
   Galactique ne "respire" plus a chaque tick de compteur. */
.galactic-shop-preview {
    position: relative;
    font-size: 0.85rem;
    font-weight: 700;
    color: #a5f3fc;
    padding: 1px 8px;
    border-radius: 6px;
    overflow: hidden;
    flex: 0 0 auto;
    width: 7.5rem;
    text-align: center;
    white-space: nowrap;
    text-align: center;
    background: rgba(34, 211, 238, 0.08);
    border: 1px solid rgba(34, 211, 238, 0.3);
}
.galactic-shop-preview-bar {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 0%;
    background: linear-gradient(90deg, rgba(34, 211, 238, 0.35), rgba(167, 139, 250, 0.45));
    z-index: 0;
    transition: width 0.3s ease;
}
.galactic-shop-preview-text {
    position: relative;
    z-index: 1;
}
.space-progress-container {
    display: flex;
    flex-direction: column;
    gap: 15px;
}
.space-progress-footer {
    display: flex;
    width: 100%;
}
.space-progress-footer .galactic-shop-btn {
    width: 100%;
}
.space-progress-header {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    gap: 8px;
}
/* Barre de progression EN FOND de la case jaune : remplit la case sous le
   texte du nom de planete (effet "jauge de niveau" du bouton). */
/* Teinte --planet-tint posee par le JS (couleur de la planete visee) :
   translucide pour ne jamais masquer le texte ; bord d'arrivee lumineux,
   reflet anime, dans le style des jauges du jeu. */
/* Case Prochaine destination : version moderne et minimaliste.
   Fond sobre, fine barre de progression discrete en bas de case,
   teintee de la couleur de la planete visee -- pas d'effet flashy. */
/* Case Prochaine destination : coloree et lisible, barre de progression
   visible avec une petite animation (pouls lumineux doux). Couleur UNIQUE
   pour toutes les planetes : l'or/ambre du theme. */
.current-planet-display {
    position: relative;
    display: block;
    width: 100%;
    box-sizing: border-box;
    overflow: hidden;
    font-size: 0.95rem;
    font-weight: 700;
    /* Refonte bleu clair : la case est un « objectif » -- un bleu clair
       lumineux la fait ressortir sans l'agressivite de l'ambre, et
       l'unite visuelle avec les tuiles primaires est conservee. */
    color: #bfdbfe;
    background: linear-gradient(160deg, rgba(96, 165, 250, 0.14), rgba(59, 130, 246, 0.18));
    padding: 7px 12px 14px;
    border-radius: 10px;
    border: 1px solid var(--blue-soft-glow);
    text-align: center;
    box-shadow: inset 0 0 18px rgba(96, 165, 250, 0.10);
}
.current-planet-display #current-planet-text {
    position: relative;
    z-index: 1;
    letter-spacing: 0.02em;
    white-space: nowrap;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}
/* Rail discret toujours visible : sans lui la barre est invisible a 0 %
   et le joueur ne devine pas ou elle apparaitra. */
.current-planet-display::after {
    content: '';
    /* Rail EXACTEMENT aux dimensions de la barre reelle (header-planet-fill :
    left 0, bottom 0, height 11px) : la piste devinee correspond au remplissage
    qui viendra par-dessus, au pixel pres. */
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 11px;
    border-radius: 0 0 10px 10px;
    background: rgba(0, 0, 0, 0.4);
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.55);
    pointer-events: none;
}
.current-planet-display .header-planet-fill {
    --planet-tint: 96, 165, 250;
    position: absolute;
    left: 0;
    bottom: 0;
    height: 11px;
    width: 0%;
    background: linear-gradient(90deg, var(--blue-soft), #bfdbfe);
    border-radius: 0 3px 3px 0;
    transition: width 0.4s ease;
    pointer-events: none;
    box-shadow: 0 0 8px rgba(96, 165, 250, 0.7);
    overflow: hidden;
}
.current-planet-display .header-planet-fill::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: -45%;
    width: 40%;
    background: linear-gradient(105deg, transparent 0%, rgba(255, 255, 255, 0.45) 50%, transparent 100%);
    animation: dest-fill-shine 2.4s ease-in-out infinite;
    will-change: transform;
}
@keyframes dest-fill-shine {
    0% { transform: translateX(0); }
    60%, 100% { transform: translateX(400%); }
}

/* Mini Space Map */
/* Minimap : hauteur FLEXIBLE -- elle partage la colonne avec les
   stats et les mini-jeux, reduit quand l'ecran perd de la hauteur ou
   de la largeur, exactement comme les blocs du centre. */
.mini-space-map {
    height: clamp(90px, 16vh, 158px);
    flex: 0 1 auto;
    min-height: 72px;
    background: radial-gradient(ellipse at center, #0a0a2a 0%, #000000 100%);
    border-radius: var(--radius);
    border: 1px solid var(--border);
    position: relative;
    overflow: hidden;
}
.mini-space-map .space-connection {
    position: absolute;
    top: 50%;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--border-light), transparent);
    transform: translateY(-50%);
}
.mini-space-map .space-connection.active {
    background: linear-gradient(90deg, transparent, var(--primary-light), transparent);
}
.mini-space-map .space-planet {
    position: absolute;
    top: 10%;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    z-index: 2;
}
.mini-space-map .space-planet .planet-emoji {
    font-size: 1.2rem;
    text-shadow: 0 0 5px var(--text);
}
.mini-space-map .space-planet.unlocked .planet-emoji {
    text-shadow: 0 0 10px var(--planet-color);
    filter: drop-shadow(0 0 3px var(--planet-color));
}

@keyframes spaceshipBounce {
    0%, 100% { transform: translateY(-50%) translateX(-50%) rotate(90deg) translateY(0); }
    50% { transform: translateY(-50%) translateX(-50%) rotate(90deg) translateY(-5px); }
}

.mini-space-map .spaceship {
    animation: spaceshipBounce 2s ease-in-out infinite;
    position: absolute;
    top: 28%;
    transform: translateY(-50%) translateX(-50%) rotate(90deg);
    width: 23px;
    height: 43px;
    z-index: 3;
    /* Deplacement fluide : la position est recalculee toutes les 500 ms,
       la transition interpole entre chaque mise a jour (pas d'a-coups). */
    transition: left 0.55s linear;
}
.mini-space-map .spaceship .spaceship-img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    filter: drop-shadow(0 0 4px var(--blue-soft-glow));
}

/* Halo autour de la fusee : double drop-shadow diffise + pulse lumineux
   doux, la fusee se repere d'un coup d'oeil sur la mini map. */
@keyframes spaceshipHalo {
    0%, 100% { filter: drop-shadow(0 0 4px var(--blue-soft-glow)) drop-shadow(0 0 9px rgba(96, 165, 250, 0.5)); }
    50% { filter: drop-shadow(0 0 5px var(--blue-soft-glow)) drop-shadow(0 0 14px rgba(147, 197, 253, 0.75)); }
}
.mini-space-map .spaceship .spaceship-img {
    animation: spaceshipHalo 2.4s ease-in-out infinite;
}

/* Planet images in mini map */
.mini-space-map .planet-image {
    width: 72px;
    height: 72px;
    border-radius: 50%;
    object-fit: cover;
    filter: drop-shadow(0 0 3px var(--planet-color));
}
/* Elements proportionnels a la LARGEUR de la mini map (cqw, la hauteur
   reste un plancher cqh) : quand le panneau lateral se retrecit, planetes,
   titres et distances reduisent avec lui au lieu d'etre coupees par le bord. */
@supports (width: 1cqw) {
    .mini-space-map { container-type: inline-size; }
    .mini-space-map .planet-image { width: max(min(55cqh, 18cqw), 26px); height: max(min(55cqh, 18cqw), 26px); }


    .mini-space-map .planet-name { font-size: max(min(9.5cqh, 3.1cqw), 0.44rem); }
    .mini-space-map .planet-distance { font-size: max(min(8.5cqh, 2.8cqw), 0.40rem); }
    .mini-space-map .spaceship { width: max(min(17cqh, 5.5cqw), 12px); height: max(min(32cqh, 10.5cqw), 22px); }
    /* Les planetes des extremites (15% / 85%) restent entierement visibles :
       leur bloc est recentre vers l'interieur au lieu d'etre coupe. */
    .mini-space-map .space-planet { max-width: 30cqw; }
}

/* MOBILE : planetes de la minimap ancrees sur la LARGEUR (cqw) avec minimum
   plus haut -- la hauteur reduite de la minimap ne les rapetisse plus. */
@media (max-width: 1024px) and (pointer: coarse) {
    @supports (width: 1cqw) {
        .mini-space-map .planet-image { width: max(min(16cqw, 46px), 30px); height: max(min(16cqw, 46px), 30px); }
    }
}

/* Planet names in mini map */
.mini-space-map .planet-name {
    font-size: 0.78rem;
    color: var(--text);
    text-align: center;
    margin-top: 5px;
    white-space: nowrap;
    text-shadow: 0 0 2px var(--text);
}
.mini-space-map .planet-distance {
    font-size: 0.66rem;
    color: var(--text-light);
    text-align: center;
    white-space: nowrap;
    opacity: 0.8;
}
/* Space Stats */
/* Stats spatiales : grille gaming 2x2 — un rectangle divise en 4 tuiles.
   Titre en haut de chaque tuile, valeur centree en dessous, lisible. */


/* Bulle d'information au clic sur une case de la Progression Spatiale */
.stat-tile {
    position: relative;
    cursor: pointer;
}
/* Position FIXED posee par le JS (dans le body, coordonnees viewport) :
   la bulle n'est plus clippee par .left-panel (overflow hidden) qui la
   rognait aux bords du panneau gauche -- elle s'affiche entiere, centree
   sous la tuile et clampee a l'ecran. */
.stat-tile-info {
    position: fixed;
    z-index: 1500;
    min-width: min(220px, calc(100vw - 16px));
    max-width: 300px;
    /* Petits ecrans : la bulle ne doit JAMAIS sortir de l'ecran. */
    max-width: min(300px, calc(100vw - 16px));
    background: linear-gradient(160deg, rgba(15, 23, 42, 0.98), rgba(2, 6, 23, 0.98));
    border: 1px solid rgba(245, 158, 11, 0.55);
    border-radius: 10px;
    padding: 12px 14px;
    box-shadow: 0 8px 28px rgba(0, 0, 0, 0.55), 0 0 18px rgba(251, 191, 36, 0.12);
    font-size: 0.82rem;
    line-height: 1.5;
    color: var(--text);
    pointer-events: auto;
    animation: sti-pop 0.18s ease-out;
}
@keyframes sti-pop {
    from { opacity: 0; transform: translateY(-4px); }
    to { opacity: 1; transform: translateY(0); }
}
.sti-title {
    font-weight: 800;
    font-size: 0.9rem;
    color: var(--accent, #fbbf24);
    margin-bottom: 6px;
    letter-spacing: 0.03em;
}
.sti-line {
    color: #cbd5e1;
    margin-bottom: 3px;
}
.sti-line:last-of-type { margin-bottom: 0; }
.sti-close {
    position: absolute;
    top: 4px;
    right: 8px;
    font-size: 1rem;
    font-weight: 700;
    color: #94a3b8;
    cursor: pointer;
    line-height: 1;
}
.sti-close:hover { color: #fff; }

.space-stats {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4px;
    padding: 4px;
    background: rgba(30, 58, 138, 0.05);
    border-radius: var(--radius);
    border: 1px solid var(--border-light);
}
.stat-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    gap: 1px;
    padding: 2px 6px;
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(71, 85, 105, 0.4);
    border-radius: 6px;
    min-width: 0;
}
/* Tuile Vitesse : libelle et valeur sur la MEME LIGNE (la tuile prend
   toute la largeur de la colonne, il y a la place -- empiles c'etait
   une perte de hauteur). Doit venir APRES .stat-tile pour l'emporter. */
.stat-tile.stat-tile-speed .stat-label {
    /* Sur la meme ligne que la valeur : pas de coupe ni de ellipse, sinon
       le libelle est tronque au profit de la valeur et parait decalle. */
    overflow: visible;
    text-overflow: clip;
    max-width: none;
    flex-shrink: 0;
    /* Meme style exact que la valeur : meme taille, meme graisse,
       meme couleur -- deux fragments d'un seul texte sur la ligne. */
    font-size: 1.05rem;
    font-weight: 800;
    color: #dbeafe;
    text-transform: none;
    letter-spacing: 0;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
    font-variant-numeric: tabular-nums;
}
.stat-tile.stat-tile-speed .stat-value {
    flex-shrink: 1;
    overflow: hidden;
}
.stat-tile.stat-tile-speed {
    grid-column: 1 / -1;
    flex-direction: row;
    justify-content: center;
    align-items: baseline;
    /* Espace net entre le libelle et la valeur : la tuile prend toute la
       largeur, on peut se permettre une vraie separation visuelle. */
    gap: 14px;
    /* Un peu plus de hauteur que les autres tuiles : libelle et valeur
       sur une seule ligne, la tuile paraissait ecrasee. */
    padding: 11px 6px;
}
/* Hierarchie : Portee actuelle et Distance a parcourir (stats de l'expedition
   en cours) legerement mises en avant par rapport aux stats secondaires --
   meme famille bleu clair que la case Prochaine destination. */
.stat-tile.stat-tile-primary {
    border-color: var(--blue-soft-glow);
    background: rgba(96, 165, 250, 0.10);
}
/* Toutes les autres tuiles de stats de la progression spatiale (Vitesse,
   Distance record, Bonus planetes) : meme famille bleu clair unifiee que
   les tuiles primaires -- meme bord, meme fond, DA homogene. */
.stat-tile:not(.stat-tile-primary) {
    border-color: var(--blue-soft-glow);
    background: rgba(96, 165, 250, 0.06);
}
.stat-label {
    font-size: 0.64rem;
    color: #cbd5e1;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}
.stat-value {
    font-size: 1.05rem;
    color: #dbeafe;
    font-weight: 800;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
/* Sigle infini (mode suite infinie) : plus grand que la police des valeurs
   et en orange accentue -- il remplace la valeur numerique de la case
   Distance a parcourir et doit se distinguer d'un simple chiffre.
   La classe .stat-value-infinite est posee par le JS uniquement quand la
   valeur affichee est le sigle. */
.stat-value-infinite .cch-sep {
    font-size: 1.6rem;
    color: var(--accent, #fbbf24);
    text-shadow: 0 0 10px rgba(251, 191, 36, 0.55);
    line-height: 1;
    font-weight: 800;
}
/* Tuile "Prochaine planete" : nom + barre + % + teaser de l'etape d'apres.
   La barre est le coeur de la motivation : le joueur voit OU il va et
   QU'EST-CE QU'IL Y A APRÈS. */
.planet-progress-tile {
    gap: 3px;
}
.planet-progress-name {
    font-size: 0.95rem;
    color: var(--accent-light);
}
.planet-progress-bar {
    position: relative;
    width: 100%;
    height: 14px;
    background: rgba(0, 0, 0, 0.45);
    border: 1px solid rgba(71, 85, 105, 0.6);
    border-radius: 7px;
    overflow: hidden;
    margin-top: 1px;
}
.planet-progress-fill {
    height: 100%;
    width: 0%;
    background: var(--accent);
    border-radius: 7px;
    transition: width 0.4s;
}
.planet-progress-pct {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.58rem;
    font-weight: 800;
    color: #fff;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9);
}
.planet-progress-next {
    font-size: 0.6rem;
    color: #94a3b8;
    font-style: italic;
    min-height: 0.9em;
}
/* Responsive for sidebar */

/* ============================================
   MINI-GAMES SECTION STYLES
   ============================================ */
.mini-games-section {
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px solid var(--border);
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    /* Hauteur naturelle : c'est le panneau gauche entier qui scrolle */
    min-height: 0;
}
.mini-games-section h4 {
    color: var(--text);
    font-family: var(--font-display);
    font-size: 1rem;
    margin-bottom: 10px;
    text-align: center;
}
.mini-games-container {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 8px;
    background: rgba(255, 255, 255, 0.02);
    border-radius: var(--radius);
    border: 1px dashed var(--border-light);
    flex: 1;
    min-height: 0;
}
.mini-games-placeholder {
    color: var(--text-dark);
    font-style: italic;
    text-align: center;
    padding: 20px;
    font-size: 0.85rem;
}
/* Mini-game card */
.mini-game-card {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 12px;
    padding: 12px;
    background: var(--bg-panel);
    border: 1px solid var(--border-light);
    border-radius: var(--radius);
    cursor: pointer;
    transition: all 0.3s ease;
    flex: 1;
    /* Hauteur minimale preservee quand l'ecran perd de la hauteur (PC/tablette) */
    min-height: 96px;
}
.mini-game-card .game-icon {
    font-size: 2.4rem;
    flex: 0 0 auto;
    line-height: 1;
    align-self: center;
    filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.5));
}
.mini-game-card .game-icon {
    width: 52px;
}
.mini-game-card .game-icon img {
    height: auto;
    width: 100%;
    object-fit: contain;
    filter: drop-shadow(0 3px 8px rgba(0, 0, 0, 0.5));
    display: block;
}
.mini-game-card .game-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 3px;
    text-align: left;
}
.mini-game-card .game-cost {
    flex: 0 0 auto;
    font-size: 0.7rem;
    color: var(--accent-light);
    font-weight: 600;
    border-top: 1px solid var(--border);
    padding-top: 5px;
    margin-top: 2px;
}
.mini-game-card:hover {
    background: var(--secondary-light);
    border-color: var(--primary-light);
    transform: translateY(-2px);
    box-shadow: var(--shadow);
}
.mini-game-card .game-name {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text);
    text-align: left;
}
.mini-game-card .game-description {
    font-size: 0.7rem;
    color: var(--text-dark);
    text-align: left;
    line-height: 1.2;
}
.mini-game-card .game-status {
    display: none;
    font-size: 0.68rem;
    text-align: left;
    line-height: 1.3;
    margin-top: 2px;
}
.mini-game-card /* Icone de contrat (image du jeu) dans le statut de la case mini-jeu. */
.status-contract-icon {
    width: 16px;
    height: 16px;
    object-fit: contain;
    vertical-align: middle;
}
.game-status.visible {
    display: block;
}
.mini-game-card .game-status .status-bar {
    display: block;
    height: 4px;
    width: 100%;
    background: rgba(255, 255, 255, 0.1);
    border-radius: 2px;
    overflow: hidden;
    margin-top: 4px;
}
.mini-game-card .game-status .status-bar > div {
    height: 100%;
    background: linear-gradient(90deg, var(--primary-light), var(--accent-light));
    border-radius: 2px;
}
.mini-game-card .game-status .status-timer {
    color: var(--accent-light);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.mini-game-card .game-status .status-offers {
    color: var(--primary-light);
    font-weight: 600;
}
/* ============================================
   CONTRATS DE FABRICATION
   ============================================ */
#contracts-modal.modal {
    max-width: 780px;
}

.contracts-modal {
    width: 100%;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

#contracts-modal .modal-header {
    border-bottom: 2px solid var(--primary-light);
}

.contracts-modal .modal-body {
    overflow-y: auto;
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.contracts-intro {
    font-size: 0.82rem;
    color: #94a3b8;
    margin: 0;
    padding: 10px 12px;
    line-height: 1.45;
    background: rgba(59, 130, 246, 0.08);
    border: 1px solid rgba(59, 130, 246, 0.2);
    border-left: 3px solid var(--primary-light);
    border-radius: 6px;
}

.contract-card {
    background: linear-gradient(180deg, rgba(30, 41, 59, 0.9), rgba(15, 23, 42, 0.9));
    border: 1px solid rgba(148, 163, 184, 0.2);
    border-radius: 12px;
    padding: 14px 16px;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
    transition: border-color 0.2s, box-shadow 0.2s;
}

.contract-card:hover {
    border-color: rgba(59, 130, 246, 0.5);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
}

.contract-card.active {
    border-color: rgba(34, 197, 94, 0.5);
    box-shadow: 0 0 10px rgba(34, 197, 94, 0.15);
}

.contract-head {
    display: flex;
    align-items: center;
    gap: 12px;
}

.contract-head img,
.contract-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    object-fit: contain;
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.06);
    padding: 4px;
}

.contract-title {
    font-weight: 600;
    font-size: 0.95rem;
}

/* Labels de difficulte des contrats */
.diff-easy { color: #34d399; font-weight: 700; }
.diff-normal { color: var(--blue-soft); font-weight: 700; }
.diff-hard { color: #f87171; font-weight: 700; }
.contract-sub {
    font-size: 0.78rem;
    color: #94a3b8;
    line-height: 1.3;
}

.contract-reward {
    font-size: 1.05rem;
    font-weight: 700;
    color: #22c55e;
    text-shadow: 0 0 12px rgba(34, 197, 94, 0.35);
}

.contract-progress {
    height: 10px;
    background: rgba(255, 255, 255, 0.08);
    border-radius: 6px;
    overflow: hidden;
}

.contract-progress div {
    height: 100%;
    background: linear-gradient(90deg, #10b981, #34d399);
    border-radius: 6px;
    transition: width 0.3s;
}

.contract-meta {
    display: flex;
    justify-content: space-between;
    font-size: 0.8rem;
    color: #cbd5e1;
}

.contract-timer {
    font-variant-numeric: tabular-nums;
    color: #fbbf24;
}

.contract-buy-btn {
    background: linear-gradient(135deg, #2563eb, #3b82f6);
    border: none;
    border-radius: 8px;
    color: white;
    font-weight: 600;
    font-size: 0.85rem;
    padding: 8px 14px;
    cursor: pointer;
    transition: all 0.2s;
    align-self: flex-start;
}

.contract-buy-btn:hover:not(:disabled) {
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(37, 99, 235, 0.4);
}

.contract-buy-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

.contract-rotation {
    font-size: 0.8rem;
    color: #cbd5e1;
    text-align: right;
    margin: 0;
    font-variant-numeric: tabular-nums;
}

.contract-empty {
    text-align: center;
    color: #94a3b8;
    font-size: 0.85rem;
    padding: 24px 0;
}


/* ===== SYSTEME DE GRID 100x100 ===== */
.center-content {
    position: relative;
    width: 100%;
    flex: 1;
    min-height: 0;
    overflow: hidden;
}
.construction-scene-100x100 {
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
    /* Ciel de remplissage : meme couleur que le haut du fond, la jonction
       est invisible quand le monde 1024x744 ne remplit pas tout l'ecran */
    background: linear-gradient(180deg, #2e5f96 0%, #3b81c7 100%);
}
/* Monde a taille fixe : repere unique pour le fond ET la fusée.
   Dimensions natives de l'image (1024x744). Le JS applique un
   transform scale() uniforme : jamais de recadrage ni de decalage. */
/* Decale de 50 px vers la gauche : le monde reste ancre en bas, le
   transform translateX(-50%) d'applySceneScale s'applique par-dessus. */
.scene-world {
    position: absolute;
    /* Réaligné sur le nouveau fond (cover, ancré bas) : le calque de
       fond a glissé de ~5 px vers le bas en passant de top:5px/étendu
       à top:0/bottom:0 -- le monde suit pour que la fusée repose sur
       la même ligne de sol qu'avant. */
    left: calc(50% + 100px);
    bottom: 10px;
    width: 1024px;
    height: 744px;
    transform-origin: 50% 100%;
    z-index: 0;
}
/* Prolongation du sol : remplissage aux couleurs du terrain du decor,
   ancre en bas de scene. Visible uniquement quand le monde 1024x744
   ne couvre pas toute la largeur (ecrans larges et bas). La hauteur
   est pilotee par JS (applySceneScale) pour suivre la ligne de sol. */
.scene-ground-fill {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 0;
    background: linear-gradient(180deg, #4c542f 0%, #3c3e26 100%);
    pointer-events: none;
}
.scene-background {
    position: absolute;
    /* Ancré au BAS de la scène (jusqu'à sa limite), décalé à GAUCHE
       de 150 px. background-size: cover : l'image garde son ratio natif
       SANS étirement -- l'ancien 100% 100% l'écrasait sur ~150 px de
       large d'où la perte de qualité ; le débordement est clippé. */
    bottom: -30px;
    left: -150px;
    right: -12px;
    top: 0;
    background-image: url('images/backgrounds/valley-day.webp');
    background-size: cover;
    background-position: center bottom;
    background-repeat: no-repeat;
    z-index: 0;
}
/* Fond de nuit : le joueur explore de nuit (20h-6h heure locale).
   Meme composition que le jour (meme recalage de la dalle), le ciel
   et l'eclairage passent en version nocturne. */
/* Transition jour <-> nuit : la version nocturne vit dans un calque
   ::after superpose, dont l'opacite passe de 0 a 1 en 3 s -- un vrai
   fondu croise au lieu d'un changement brutal d'image. */
body.night-mode .scene-background {
    background-image: url('images/backgrounds/valley-day.webp');
}
.scene-background::after {
    content: '';
    position: absolute;
    inset: 0;
    background-image: url('images/backgrounds/valley-night.webp');
    background-size: cover;
    background-position: center bottom;
    background-repeat: no-repeat;
    opacity: 0;
    transition: opacity 3s ease-in-out;
    pointer-events: none;
}
body.night-mode .scene-background::after {
    opacity: 1;
}
/* Grille 100x100 (optionnelle) */
.grid-100x100 {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 1;
    display: none; /* Masquée par défaut */
}
.grid-100x100.show {
    display: block;
}
.grid-line {
    position: absolute;
    background: rgba(255, 255, 255, 0.2);
    pointer-events: none;
}
.grid-line.h {
    width: 100%;
    height: 1px;
    top: calc(var(--pos) * 1%);
    left: 0;
}
.grid-line.v {
    width: 1px;
    height: 100%;
    top: 0;
    left: calc(var(--pos) * 1%);
}
/* Conteneur des pièces de fusée */
.rocket-parts-100x100 {
    position: absolute;
    top: -50px; /* Fusée remontée de 50px par rapport au bas du monde */
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 2;
}
/* Pièces de fusée sur grille 100x100 */
/* Positionnement géré en JS via left/top + transform: translate(-50%, 0) (ancrage haut-centre) */
.rocket-piece {
    position: absolute;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: auto; /* Largeur définie par JavaScript */
    height: auto; /* Hauteur définie par JavaScript */
    font-size: 2rem;
    color: white;
    text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8);
    pointer-events: none;
    z-index: 3;
}

/* Ombre portee de l'astronaute : le soleil de la vallee vient de la
   droite, l'ombre tombe donc a GAUCHE, au sol. Ellipse aplatie
   (perspective rasante du sol), leger rotation, flou doux, ancree a
   la base de l'astronaute (il "flotte" legerement au-dessus : l'ombre
   est plus petite et plus diffuse = distance de rendition). Le z-index
   2 le garde SOUS l'astronaute (z-index 3) mais au-dessus du sol. */
.rocket-piece.astronaut::before {
    content: '';
    position: absolute;
    /* Ancree DIRECTEMENT sous les pieds : centree sur l'astronaute,
       juste decalee de quelques px vers la gauche (lumiere de la vallee
       venant de la droite, legere inclinaison pour la perspective). */
    bottom: 2px;
    left: -6px;
    right: 0;
    margin: auto;
    width: 90%;
    height: 14px;
    background: rgba(0, 0, 0, 0.45);
    border-radius: 50%;
    filter: blur(4px);
    transform: rotate(-2deg) scaleY(0.9);
    z-index: -1;
    pointer-events: none;
}
.rocket-piece img {
    max-width: 100%; /* Ne dépasse pas la largeur du conteneur */
    max-height: 100%; /* Ne dépasse pas la hauteur du conteneur */
    width: auto;
    height: auto;
    object-fit: contain; /* Garde les proportions sans déformation */
}

/* Ombres portees directement sur les images (drop-shadow suit l'alpha
   reel du PNG : impossible a rogner par la boite de la piece). Tuyeres
   principales ET tuyeres des boosters, ombre plus marquee et plus
   decalee vers le bas pour asseoir la fusee sur son pas de tir. */
.rocket-piece.nozzles img,
.rocket-piece.boosters-left img,
.rocket-piece.boosters-right img {
    filter: drop-shadow(0 13px 10px rgba(0, 0, 0, 0.9));
}
/* Animation de chute pour les pièces nouvelles */
@keyframes fallFromTop {
    0% { 
        transform: translate(-50%, -200px) scale(0.8); 
        opacity: 0;
    }
    100% { 
        transform: translate(-50%, 0) scale(1); 
        opacity: 1;
    }
}

.rocket-piece.new {
    animation: fallFromTop 0.6s ease-out forwards;
}

.rocket-piece.unlocked {
    pointer-events: auto;
    cursor: pointer;
}

/* Effet de poussiere de construction : particules jaillissant au point
   de contact quand une piece atterrit sur une autre. */
.build-dust {
    position: absolute;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: radial-gradient(circle, #d8c7a0 0%, #b8a37a 60%, transparent 70%);
    pointer-events: none;
    z-index: 8;
    transform: translate(-50%, -50%);
    animation: buildDust 0.8s ease-out forwards;
}
@keyframes buildDust {
    0% {
        opacity: 0.95;
        transform: translate(-50%, -50%) scale(1);
    }
    100% {
        opacity: 0;
        transform: translate(calc(-50% + var(--dx, 0px)), calc(-50% + var(--dy, -30px))) scale(0.2);
    }
}

/* Label de l'atelier */
.workshop-label {
    position: absolute;
    bottom: -20px;
    left: 50%;
    transform: translateX(-50%);
    color: white;
    font-size: 0.7rem;
    text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
    background: rgba(0, 0, 0, 0.5);
    padding: 2px 8px;
    border-radius: 4px;
    white-space: nowrap;
}

/* Bouton cliquable principal - Pièce */
/* 3 couches indépendantes pour composer les échelles sans conflit :
   .medal (conteneur) : survol / clic → scale du conteneur
   .medal-anim (wrapper) : taille de base de la pièce + squash & stretch du clic
   .medal-img (image) : rotation d'inertie du clic */
.medal {
    position: absolute;
    /* Inversion demandee : la piece passe a GAUCHE du panneau central. */
    left: calc(10% - 10px);
    right: auto;
    top: calc(25% + 50px);
    /* Agrandie : la zone cliquable principale du jeu doit etre
       generreuse. Le right: 10% garde une distance similaire au bord
       droit, proportionnellement conservee. */
    width: 293px;
    height: 293px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
    z-index: 100;
    transform: translateY(-50%);
}
.medal:hover {
    transform: translateY(-50%) scale(1.08);
}
.medal:hover .medal-img {
    filter: drop-shadow(0 0 18px rgba(120, 180, 255, 0.85));
}
.medal:active {
    transform: translateY(-50%) scale(0.96);
}
/* Medaille adaptative : proportionnelle a la hauteur du panneau central,
   memes proportions que la version PC (204px pour ~978px  soit 21cqh). */
@supports (width: 1cqh) {
    .center-content { container-type: size; }
    .medal {
        width: 31.35cqh;
        height: 31.35cqh;
        min-width: 165px;
        min-height: 165px;
        max-width: 355px;
        max-height: 355px;
    }
}
/* Wrapper : agrandissement de la pièce + squash & stretch au clic.
   Le scale de base (1.05) : la nouvelle image de la piece est quasi carree et remplie. */
.medal-anim {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    transform: scale(1.05);
}
.medal {
    --click-nx: 0;
    --click-ny: 0;
}
.medal.bounce .medal-anim {
    animation: coin-pop 0.45s cubic-bezier(0.22, 1.2, 0.36, 1);
}
.medal.bounce .medal-img {
    animation: coin-spin 0.55s cubic-bezier(0.3, 0.8, 0.4, 1);
}
/* Squash & stretch directionnel : la piece se tord vers le point clique.
   --click-nx/--click-ny : direction normalisee du clic (definie en JS). */
@keyframes coin-pop {
    0%   { transform: translate(0px, 0px) scale(1.05) scale(1); }
    25%  { transform: translate(calc(var(--click-nx) * -9px), calc(var(--click-ny) * -9px)) scale(1.05) scale(0.9, 1.08); }
    55%  { transform: translate(calc(var(--click-nx) * 14px), calc(var(--click-ny) * 14px)) scale(1.05) scale(1.08, 0.95); }
    75%  { transform: translate(calc(var(--click-nx) * -5px), calc(var(--click-ny) * -5px)) scale(1.05) scale(0.98, 1.01); }
    100% { transform: translate(0px, 0px) scale(1.05) scale(1); }
}
/* Rotation d'inertie directionnelle : tord la piece vers l'angle du clic */
@keyframes coin-spin {
    0%   { transform: rotate(0deg) skewX(calc(var(--click-nx) * -5deg)) skewY(calc(var(--click-ny) * -4deg)); }
    35%  { transform: rotate(calc(var(--click-nx) * -7deg)) skewX(calc(var(--click-nx) * -7deg)) skewY(calc(var(--click-ny) * -5deg)); }
    70%  { transform: rotate(calc(var(--click-nx) * 3deg)) skewX(calc(var(--click-nx) * 3deg)) skewY(calc(var(--click-ny) * 2deg)); }
    100% { transform: rotate(0deg) skewX(0deg) skewY(0deg); }
}
.medal-img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    border-radius: 50%;
    pointer-events: none;
    user-select: none;
    -webkit-user-drag: none;
    filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.35));
}
/* Flash de lumière au clic */
.medal::after {
    content: '';
    position: absolute;
    inset: 12%;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(255, 255, 255, 0.9) 0%, rgba(160, 210, 255, 0.5) 45%, transparent 70%);
    opacity: 0;
    pointer-events: none;
    z-index: -1;
}
.medal.bounce::after {
    animation: coin-flash 0.4s ease-out;
}
@keyframes coin-flash {
    0%   { opacity: 0.9; transform: scale(0.85); }
    100% { opacity: 0; transform: scale(1.45); }
}
/* ===== Reflet speculaire balayant (permanant, GPU) ===== */
/* Voile lumineux qui traverse la piece en diagonale toutes les ~6 s :
   la piece parait "vivante", metal precieux exposE sous un eclairage. */
.medal-shine {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    overflow: hidden;
    pointer-events: none;
    z-index: 2;
}
.medal-shine::before {
    content: '';
    position: absolute;
    top: -20%;
    left: -60%;
    width: 45%;
    height: 140%;
    background: linear-gradient(105deg,
        transparent 0%,
        rgba(255, 255, 255, 0.06) 35%,
        rgba(255, 255, 255, 0.35) 50%,
        rgba(255, 255, 255, 0.06) 65%,
        transparent 100%);
    transform: skewX(-18deg);
    animation: medal-shine-sweep 5.5s ease-in-out infinite;
    filter: blur(1px);
    will-change: transform;
}
@keyframes medal-shine-sweep {
    0%, 55%  { transform: skewX(-18deg) translateX(0); }   /* longue pause hors piece : balayage ponctuel, pas un stroboscope */
    85%, 100% { transform: skewX(-18deg) translateX(425%); }
}


/* ===== Halo pulsant autour de la piece ===== */
/* Lueur blanche diffuse qui respire lentement : attire l'oeil vers la piece
   sans crier. Aucun bord net, juste un voile lumineux qui s'evanouit
   progressivement vers l'exterieur. */
.medal-halo {
    position: absolute;
    inset: -22%;
    border-radius: 50%;
    pointer-events: none;
    z-index: 0;
    will-change: opacity;
    background:
        radial-gradient(circle,
            rgba(255, 255, 255, 0.38) 48%,
            rgba(255, 255, 255, 0.20) 58%,
            rgba(255, 255, 255, 0.08) 70%,
            transparent 88%);
    filter: blur(14px);
    animation: medal-halo-breathe 2.6s ease-in-out infinite;
    opacity: 0.9;
}

/* Voile blanc legerement dephase qui renforce la profondeur du flou */
.medal-halo::before {
    content: '';
    position: absolute;
    inset: 4%;
    border-radius: 50%;
    background:
        radial-gradient(circle,
            rgba(255, 255, 255, 0.22) 50%,
            transparent 78%);
    filter: blur(10px);
    animation: medal-halo-breathe 2.6s ease-in-out infinite reverse;
}

/* Renflement de lueur tres diffus qui tourne lentement : effet "vivant" */
.medal-halo::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: conic-gradient(from 0deg,
        rgba(255, 255, 255, 0.14) 0deg,
        transparent 70deg,
        transparent 290deg,
        rgba(255, 255, 255, 0.14) 360deg);
    filter: blur(18px);
    animation: medal-halo-spin 9s linear infinite;
}

@keyframes medal-halo-breathe {
    0%, 100% { opacity: 0.7; }
    50%      { opacity: 1; }
}

@keyframes medal-halo-spin {
    to { transform: rotate(360deg); }
}

/* Le halo s'efface quand la piece n'est pas utilisable (lancement en cours) */
.medal.disabled .medal-halo,
.medal:disabled .medal-halo {
    opacity: 0;
    transition: opacity 0.4s ease;
}

@media (prefers-reduced-motion: reduce) {
    .medal-halo, .medal-halo::before, .medal-halo::after {
        animation: none;
        opacity: 0.6;
    }
    /* P4 : sequence de lancement sans tremblement, avec un decollage
       court et sans acceleration -- le JS attend 500 ms dans ce mode. */
    .launch-rocket-wrap.launch-shaking,
    .launch-rocket-wrap.launch-shaking * { animation: none !important; }
    .astronaut-jumping { animation: none !important; opacity: 0 !important; }
    .launch-flame-jet { animation: none !important; }
    .launch-rocket-wrap.lift-off {
        animation: launchLiftOffReduced 0.45s ease-out forwards;
    }
}
@keyframes launchLiftOffReduced {
    0% { opacity: 1; }
    100% { transform: translate3d(0, -110vh, 0) scale(1); opacity: 0; }
}

/* ===== Ondes de choc au point d'impact ===== */
/* 2 anneaux emIS au point EXACT du clic, 60 ms d'ecart, s'etendent en
   s'estompant : sensation de frapper la piece, pas de la survoler. */
.shockwave {
    position: absolute;
    /* Taille et marges definies en JS (adaptatives, proportionnelles a
       la piece) : ici seulement le style. */
    border-radius: 50%;
    border: 3px solid rgba(190, 225, 255, 0.95);
    box-shadow: 0 0 14px rgba(160, 210, 255, 0.7), 0 0 28px rgba(160, 210, 255, 0.35);
    pointer-events: none;
    opacity: 1;
    animation: shockwave-expand 0.55s cubic-bezier(0.16, 1, 0.3, 1) forwards;
    z-index: 2;
}
.shockwave.small {
    border-width: 2px;
    animation-delay: 0.07s;
}
@keyframes shockwave-expand {
    0%   { transform: scale(0.25); opacity: 1; }
    70%  { opacity: 0.6; }
    100% { transform: scale(2.6); opacity: 0; }
}
/* Bouton de lancement : cache tant que la fusee est incomplete (la case
   d'achat des pieces occupe le bas du panneau central a sa place). La
   classe .ready, posee par updateLaunchButtonVisibility(), le fait
   reapparaitre. Un SEUL display dans ce bloc : le display:flex vit dans
   .launch-button.ready, sinon il ecraserait le none. */
.launch-button {
    display: none;
    position: absolute;
    bottom: 10px;
    left: 50%;
    transform: translateX(-50%);
    /* Fusee complete : le bouton est la SEULE action du bas du panneau,
       il la remplace largement (agrandi vs la case d'achat). Padding
       lateral modeste (plus de 90px morts qui bloquaient la largeur
       utile) + TOUJOURS une seule ligne, meme en ecran etroit : le
       texte est insecable et la police se ressert avec la largeur. */
    padding: 18px 24px;
    background: linear-gradient(135deg, #ef4444, #dc2626);
    border: none;
    border-radius: 18px;
    color: white;
    font-size: clamp(0.95rem, 4.5vw, 1.35rem);
    font-family: var(--font-display);
    letter-spacing: 0.06em;
    font-weight: bold;
    cursor: pointer;
    box-shadow: 0 4px 15px rgba(255, 68, 68, 0.4);
    transition: all 0.2s ease;
    z-index: 100;
    align-items: center;
    gap: 8px;
    white-space: nowrap;
    max-width: calc(100% - 16px);
    overflow: hidden;
}
.launch-button:hover {
    transform: translateX(-50%) translateY(-2px);
    box-shadow: 0 6px 20px rgba(255, 68, 68, 0.6);
}
.launch-button:active {
    transform: translateX(-50%) translateY(0);
}
.launch-button:disabled {
    background: #666;
    cursor: not-allowed;
    box-shadow: none;
}
/* Cadre unique de la prochaine pièce de fusée à acheter */
/* Case d'achat des pieces : BARRE HORIZONTALE EN BAS du panneau central
   (pleine largeur), a la place du bouton de lancement tant que la fusee
   est incomplete. Sur petit ecran PC comme en mobile, la carte a enfin
   la place de s'etaler en largeur au lieu d'etre etroite et empilee. */
.rocket-parts-shop {
    position: absolute;
    bottom: 5px;
    left: 50%;
    transform: translateX(-50%);
    width: min(96%, 458px);
    display: flex;
    flex-direction: column;
    padding: 4px 6px;
    z-index: 90;
}
/* Fusee complete : la boutique disparait TOTALEMENT (plus de carte
   "Pieces completes") -- seul le bouton LANCER, agrandi, reste en bas. */
.rocket-parts-shop.shop-done { display: none; }
/* Case piece de fusee : DEUX parties, comme les cases batiments --
   DA du jeu : fond var(--secondary), bordure var(--border), hover
   var(--secondary-light) + glow primaire. A gauche l'image, a droite
   les informations. Carte entiere cliquable. */
.rocket-parts-shop .rocket-part-frame {
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    gap: 1rem;
    padding: 0.6rem 0.9rem;
    cursor: pointer;
    background: var(--secondary);
    border: 1px solid var(--border);
    box-shadow: var(--shadow);
    transition: all 0.2s;
}
.rocket-parts-shop .rocket-part-frame:hover:not(.locked) {
    background: var(--secondary-light);
    border-color: var(--primary-light);
    box-shadow: var(--shadow-lg), 0 0 12px var(--blue-soft-glow);
}
.rocket-parts-shop .rocket-part-frame.locked { cursor: not-allowed; opacity: 0.75; }
/* Partie gauche : l'image de la piece */
.rocket-parts-shop .rocket-part-img {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 4rem;
    height: 4rem;
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 0.3rem;
}
.rocket-parts-shop .rocket-part-img .rocket-part-icon,
.rocket-parts-shop .rocket-part-img .rocket-part-icon-placeholder { width: 100%; height: 100%; opacity: 0.95; }
/* Partie droite : les informations. La ligne titre+bonus et la barre de
   cout partagent exactement la meme largeur (align-items: stretch). */
.rocket-parts-shop .rocket-part-info {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    text-align: left;
    flex: 1 1 auto;
    min-width: 0;
    gap: 0.3rem;
}
/* Titre et bonus sur la MEME ligne : nom a gauche, bonus pousse a droite. */
.rocket-parts-shop .rocket-part-headline {
    display: flex;
    flex-direction: row;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
    width: 100%;
    min-width: 0;
}
.rocket-parts-shop .rocket-part-name { font-size: 1.05rem; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rocket-parts-shop .rocket-part-mult { font-size: 0.85rem; font-weight: 600; color: #86efac; white-space: nowrap; }
.rocket-parts-shop .rocket-part-progress { width: 100%; height: 26px; margin-top: 0; }
.rocket-parts-shop .rocket-part-progress { width: 100%; height: 26px; margin-top: 0.25rem; }
.rocket-parts-shop .rocket-part-progress-label { font-size: 0.88rem; font-weight: 700; text-shadow: 0 1px 3px rgba(0,0,0,0.8); }
.rocket-parts-shop .rocket-part-frame.complete { flex-direction: row; }    }
    .rocket-part-frame {
        gap: 0.7rem;
        padding: 1rem 1rem;
    }
    .rocket-part-frame-title {
        font-size: 1.05rem;
    }
    .rocket-part-left {
        width: 6rem;
        height: 6rem;
    }
    .rocket-part-icon {
        width: 5.25rem;
        height: 5.25rem;
    }
    .rocket-part-icon-placeholder {
        width: 5.25rem;
        height: 5.25rem;
    }
    .rocket-part-name {
        font-size: 1.35rem;
    }
    .rocket-part-cost {
        font-size: 1.15rem;
    }
    .rocket-part-progress {
        height: 22px;
    }
    .rocket-part-progress-label {
        font-size: 1rem;
    }
    .rocket-part-btn {
        padding: 0.65rem 0.9rem;
        font-size: 1rem;
    }
}
/* Base HORS shop (modales etc.) : colonne centree. Dans la barre du bas,
   les regles .rocket-parts-shop .rocket-part-frame plus specifiques
   imposent le layout horizontal -- mais celle-ci arrive APRES dans le
   source, on la borne donc pour ne jamais s'appliquer a la barre. */
.rocket-parts-shop .rocket-part-frame {
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    background: var(--secondary);
    border: 1px solid var(--border);
    box-shadow: var(--shadow);
}
.rocket-part-frame {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.55rem;
    padding: 0.8rem 0.7rem;
    background: var(--secondary-light);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    transition: all 0.2s;
}
.rocket-part-frame.locked {
    opacity: 0.7;
}
.rocket-part-frame.complete {
    border-color: #10b981;
    background: var(--secondary-light);
    box-shadow: inset 0 0 0 100px rgba(16, 185, 129, 0.15);
}
.rocket-part-frame-title {
    font-size: 0.92rem;
    font-weight: 700;
    color: var(--accent-light);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.rocket-part-frame-complete {
    font-size: 0.9rem;
    font-weight: 600;
    color: #34d399;
    text-align: center;
    padding: 10px 0;
}
.rocket-part-left {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3.75rem;
    height: 3.75rem;
}
.rocket-part-icon {
    width: 3.5rem;
    height: 3.5rem;
    object-fit: contain;
    opacity: 0.85;
    pointer-events: none;
    display: block;
}
.rocket-part-icon-placeholder {
    display: block;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--radius);
    background: var(--secondary);
}
.rocket-part-info {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.1875rem;
    text-align: center;
}
.rocket-part-name {
    font-size: 1.08rem;
    font-weight: 600;
    color: var(--text);
}
.rocket-part-cost {
    font-size: 0.92rem;
    color: var(--accent-light);
}
.rocket-part-mult {
    font-size: 0.88rem;
    font-weight: 700;
    color: #86efac;
}
/* Barre de progression vers la prochaine piece (183/250 Parts, 73 %) */
.rocket-part-progress {
    position: relative;
    width: 100%;
    height: 22px;
    background: rgba(0, 0, 0, 0.45);
    border: 1px solid var(--border);
    border-radius: 9px;
    overflow: hidden;
}
.rocket-part-progress-fill {
    height: 100%;
    width: 0%;
    background: linear-gradient(90deg, var(--primary), var(--accent));
    transition: width 0.3s;
}
.rocket-part-progress-label {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.9rem;
    font-weight: 700;
    color: #fff;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
    /* Une seule ligne, TOUJOURS : le JS (fitRocketPartProgressLabels)
       reduit la police si le texte depasse -- plus de retour a la ligne
       qui cassait la hauteur de la case sur mobile. */
    white-space: nowrap;
    overflow: hidden;
}
.rocket-part-btn {
    width: 100%;
    padding: 0.75rem 0.7rem;
    background: var(--primary);
    color: white;
    border: none;
    border-radius: var(--radius);
    cursor: pointer;
    font-size: 1.05rem;
    font-weight: 700;
    transition: all 0.2s;
}
.rocket-part-btn:hover:not(:disabled) {
    background: var(--primary-light);
}
.rocket-part-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}
.rocket-part-status {
    font-size: 0.65rem;
    color: #10b981;
    font-weight: 600;
}
.rocket-part-btn {
    margin-top: 2px;
    padding: 7px 8px;
    border: none;
    border-radius: 6px;
    background: var(--primary);
    color: white;
    font-size: 0.95rem;
    font-weight: 700;
    cursor: pointer;
    /* Plus de nowrap : sur petit ecran "Construire — 250 Parts"
       debordait du cadre. Le texte passe a la ligne dans la largeur
       du cadre, bouton toujours pleine largeur. */
    white-space: normal;
    overflow-wrap: break-word;
    text-align: center;
    transition: background 0.2s;
}
.rocket-part-btn:hover:not(:disabled) {
    background: var(--primary-light);
}
.rocket-part-btn:disabled {
    background: #475569;
    cursor: not-allowed;
}.launch-button-text {
    font-size: 1em;
    letter-spacing: 1px;
    white-space: nowrap;
}
/* Compteurs */
.hud-top-row {
    position: absolute;
    top: 48px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    /* 24cqw de marge au lieu de 28 : aligne la zone HUD sur la boutique   de pieces de fusée (24cqw), le badge de bonus a cote du compteur   reste dans la zone visible sur tablette paysage (panneau etroit). */    max-width: calc(100cqw - 24cqw);
    z-index: 100;
}

/* Le badge de bonus est en position absolue a droite du compteur : le
   compteur garde exactement la meme position avec ou sans bonus actif,
   le badge n'occupe aucune place dans le flux. Si l'espace a droite (ou a
   gauche) manque, la classe .bonus-below ajoutee en JS le repasse en
   statique sous le compteur : il reste entier et visible sans deborder
   du panneau central ni chevaucher les voisins. */
.hud-counters-row {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    max-width: 100%;
}

.hud-counters-row .bonus-timer {
    position: absolute;
    left: calc(100% + 8px);
    top: 50%;
    transform: translateY(-50%);
    max-width: 220px;
}

.hud-counters-row .bonus-timer.bonus-below {
    /* Absolu sous le compteur, centre : le badge n'occupe aucune place
       dans le flux, le conteneur central ne bouge pas d'un pixel quand
       un bonus temporaire apparait ou disparait. */
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    margin-top: 4px;
    max-width: 100%;
    white-space: nowrap;
}
.counters {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: clamp(8px, 1.2vw, 24px);
    /* Largeur fluide bornee : le min depend du panneau central (cqw) pour
       que le compteur se comprime plutot que chevaucher la boutique. */
    width: clamp(min(340px, 52cqw), 30vw, 500px);
    height: clamp(50px, 6.5vh, 66px);
    flex: 0 1 auto;
    min-width: 0;
    background: rgba(0, 0, 0, 0.8);
    padding: 6px clamp(8px, 1vw, 16px);
    border-radius: 10px;
}
.counter {
    color: white;
    font-size: 1.6rem;
    font-weight: bold;
    text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
    /* Largeur FIXE et egale pour les deux compteurs : en 0 1 auto, le
       compteur Parts grossissait a chaque chiffre ajoute et poussait le
       compteur /s -- le cadre entier semblait respirer. Chaque compteur
       occupe exactement la moitie du cadre, le nombre grandit vers la
       gauche sans jamais deplacer l'autre compteur. */
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    align-items: baseline;
    justify-content: center;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: 0 8px;
    /* Container flex : les espaces du HTML entre number et "Parts" ou
       entre les chiffres et "/s" sont IGNORES (anonymous flex items),
       d'ou le "1.5M" colle au "Parts" et le "/s" fusionne avec le nombre.
       Le gap flex restitue un espacement vivant, proportionnel a l'ecran. */
    gap: clamp(3px, 0.7vw, 9px);
}
.counter .gain-wrap {
    display: inline-flex;
    align-items: baseline;
    white-space: nowrap;
}
.counter .unit {
    display: inline-flex;
    align-items: baseline;
    white-space: nowrap;
}
.counter > span[data-i18n="Parts"], .counter .unit {
    align-self: baseline;
    white-space: nowrap;
}
/* Detection d'overflow fiable : si les enfants pouvaient retrecir
   (flex-shrink, min-width: 0), le contenu se rognerait silencieusement
   sans jamais faire grandir scrollWidth, et l'auto-ajustement de police
   (fitCounterFontSize) ne se declencherait jamais. En interdisant le
   shrink, le contenu deborde reellement, scrollWidth > clientWidth
   devient detectable, et JS reduit la police jusqu'a ce que tout
   rentre (chiffres + "Parts" / "/s" bien separes). */
.counter > * {
    flex-shrink: 0;
}
#score-value {
    justify-content: flex-end;
}
.counter span {
    color: var(--accent-light);
    display: inline-block;
    min-width: 1ch;
}

/* Tres petites largeurs (<1150px) : une seule rangee ne peut pas tenir entre
   la boutique de pieces et le bord du panneau central sans rogner "Parts".
   On empile les deux compteurs et on borne la boite a l'espace libre reel. */
/* Tablettes paysage (layout PC, panneau central etroit) : la boutique de   pieces fait 24cqw, on borne la boite de compteurs a l'espace reellement   libre entre elle et le bord du panneau. */
@media (max-width: 1150px) {
    .counters {
        flex-direction: column;
        gap: 2px;
        height: auto;
        padding: 4px 10px;
        width: min(clamp(min(280px, 60cqw), 42vw, 440px), calc(100cqw - 24cqw - 40px));
    }
    .counter {
        padding: 0 2px;
        width: 100%;
        flex: 0 1 auto;
        min-height: 1.6rem;
    }
}
/* Barre des upgrades */
.upgrades-bar {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 48px;
    background: var(--bg-panel);
    z-index: 1000;
    display: flex;
    align-items: center;
    padding: 0 10px;
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow);
    overflow: visible;
}
.buy-all-upgrades-btn {
    margin-left: 10px;
    padding: 6px 14px;
    background: linear-gradient(135deg, #2563eb, #1d4ed8);
    color: #fff;
    font-size: 0.85rem;
    font-weight: 700;
    border: 1px solid #60a5fa;
    border-radius: var(--radius);
    cursor: pointer;
    white-space: nowrap;
    flex-shrink: 0;
    transition: filter 0.15s ease, box-shadow 0.15s ease;
}
.buy-all-upgrades-btn:hover:not(:disabled) {
    filter: brightness(1.2);
    box-shadow: 0 0 10px rgba(96, 165, 250, 0.6);
}
.buy-all-upgrades-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}
.upgrades-title {
    color: white;
    font-family: var(--font-display);
    font-size: 1.1rem;
    font-weight: 700;
    margin-right: 12px;
    white-space: nowrap;
    flex-shrink: 0;
    text-shadow: var(--glow);
}
.upgrades-container-center {
    display: flex;
    gap: 10px;
    margin-left: 20px;
    height: 100%;
    align-items: center;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 0 0 0 10px;
    flex: 1;
    min-width: 0;
    -ms-overflow-style: none;
    scrollbar-width: none;
}
/* CARD COLLECTION MODAL */
#card-collection-modal {
    max-width: 750px;
    width: 90vw;
    max-height: 85vh;
    height: 85vh;
}
#card-collection-modal.modal {
    /* Largeur du panneau central +5px : le bord droit reste colle au
       bord, le bord gauche deborde de 5px pour masquer le fond. */
    width: calc(50% + 5px);
    max-width: calc(50% + 5px);
    top: var(--top-height);
    left: 50%;
    /* Bord droit inchangé (colle au bord du panneau), bord gauche
       decale de 5px vers la gauche pour masquer le fond visible. */
    transform: translateX(calc(-50% + 2.5px));
    height: calc(100vh - var(--top-height));
    height: calc(100dvh - var(--top-height));
    max-height: calc(100vh - var(--top-height));
    max-height: calc(100dvh - var(--top-height));
}
.card-collection-modal {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
}
.card-collection-modal .modal-body {
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    flex: 1;
    padding: 16px;
    max-height: none;
}
.card-collection-stats {
    display: flex;
    justify-content: space-around;
    margin-bottom: 16px;
    padding: 10px;
    background: rgba(59, 130, 246, 0.1);
    border-radius: var(--radius);
}
.card-stat {
    font-size: 0.9rem;
    color: var(--text);
    font-weight: 600;
}
.card-stat span {
    color: var(--accent-light);
}
.cc-intro {
    text-align: center;
    color: var(--text-light);
    margin-bottom: 18px;
    font-size: 0.9rem;
    line-height: 1.4;
}
.cc-booster-options {
    display: flex;
    gap: 12px;
    justify-content: center;
    align-items: stretch;
    flex-wrap: wrap;
    margin-bottom: 18px;
}
/* Badge informatif collection dans la case du mini-jeu : cartes
   obtenues / 20 + bonus actuel, a droite sur la ligne "Boosters payants". */
.game-cost {
    display: flex;
    align-items: center;
    gap: 6px;
}
.game-cost .cc-collection-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    justify-content: flex-end;
    margin-left: auto;
    padding: 2px 8px;
    background: rgba(59, 130, 246, 0.12);
    border: 1px solid rgba(59, 130, 246, 0.35);
    border-radius: 999px;
    font-weight: 700;
    white-space: normal;
    /* Adaptable : le badge peut retrer quand la case rapetisse, sa police
       suit la largeur disponible (clamp) au lieu de deborder. */
    flex-shrink: 1;
    min-width: 0;
    overflow: hidden;
    font-size: clamp(0.62rem, 1.6vw, 0.78rem);
}
.ccb-count {
    font-size: 1em;
    color: var(--accent-light);
    font-variant-numeric: tabular-nums;
}
.ccb-sep {
    color: var(--text-light);
    margin: 0 1px;
}
.ccb-divider {
    width: 1px;
    height: 12px;
    background: rgba(59, 130, 246, 0.4);
}

/* Badge collection sur 2 lignes : quand la largeur manque, le multiplicateur
   repasse sous le compteur de cartes au lieu de disparaitre hors du badge. */
.game-cost .cc-collection-badge .ccb-divider {
    display: none;
}
.ccb-mult {
    font-size: 1em;
    color: var(--accent-light);
    font-variant-numeric: tabular-nums;
}
.cc-booster-btn {
    flex: 1;
    min-width: 0;
    max-width: 260px;
    display: flex;
    flex-direction: column;
    align-items: center;
    background: linear-gradient(135deg, #1e3a8a, #1e1b4b);
    border: 2px solid var(--primary-light);
    border-radius: var(--radius);
    padding: 14px;
    cursor: pointer;
    color: var(--text);
    text-align: center;
    transition: transform 0.2s, box-shadow 0.2s, border-color 0.2s;
}
.cc-booster-btn:hover {
    transform: translateY(-4px);
    box-shadow: 0 6px 16px rgba(59, 130, 246, 0.3);
    border-color: var(--accent);
}
.cc-booster-btn:active {
    transform: translateY(-2px);
}
.cc-booster-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    transform: none;
}
.cc-booster-btn:disabled .cc-booster-img {
    filter: grayscale(0.8);
}
.cc-booster-img {
    width: 100%;
    max-width: 192px;
    height: auto;
    aspect-ratio: 540 / 920;
    object-fit: contain;
    border-radius: calc(var(--radius) - 4px);
    margin-bottom: 10px;
    pointer-events: none;
}
.cc-booster-name {
    font-size: 1.1rem;
    font-weight: 700;
    margin-bottom: 6px;
}
.cc-booster-info {
    font-size: 0.75rem;
    color: var(--text-light);
    margin-bottom: 8px;
    line-height: 1.3;
}
.cc-booster-cost {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--accent-light);
}
.cc-view-album-btn {
    display: block;
    margin: 0 auto;
    padding: 13px 32px;
    background: rgba(167, 139, 250, 0.15);
    border: 1px solid #a78bfa;
    border-radius: var(--radius);
    color: var(--text);
    cursor: pointer;
    font-weight: 600;
    font-size: 1.35rem;
    transition: background 0.2s;
}
.cc-view-album-btn:hover {
    background: rgba(167, 139, 250, 0.25);
}
.cc-reveal-intro {
    text-align: center;
    color: var(--accent-light);
    font-weight: 600;
    margin-bottom: 16px;
    font-size: 1rem;
}
.cc-reveal-cards {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 14px;
    flex-wrap: nowrap;
    margin-bottom: 16px;
    flex: 1 1 auto;
    width: 100%;
    container-type: size;
}
#cc-reveal-screen {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex: 1 1 auto;
    min-height: 0;
}
.cc-reveal-card {
    width: min(
        calc((100cqw - (var(--card-count, 3) - 1) * 14px) / var(--card-count, 3)),
        240px,
        calc(50cqh)
    );
    max-width: 100%;
    height: auto;
    aspect-ratio: 2 / 3;
    border-radius: clamp(10px, 7.5%, 26px);
    padding: 0;
    box-sizing: border-box;
    position: relative;
    opacity: 0;
    perspective: 1000px;
    cursor: pointer;
    animation: cc-reveal 0.5s ease forwards;
    transition: transform 0.2s;
}
/* Paquet sequential : une seule carte a la fois, bien plus grande.
   Plafond releve a 520px et proportionnel a la hauteur (68cqh) : sur
   grand ecran la carte exploite enfin la place, sur petit ecran elle
   se ressert automatiquement. */
.cc-reveal-card.pack {
    width: min(78cqw, 520px, 68cqh);
}
/* Titre du recap de booster : AU-DESSUS des cartes, celles-ci centrees
   en dessous dans .cc-reveal-cards (le titre vit hors du conteneur flex,
   insere juste avant par le JS). */
.cc-reveal-summary-title {
    flex: 0 0 auto;
    margin-bottom: 0.4rem;
    width: 100%;
    text-align: center;
    font-family: var(--font-display);
    font-size: clamp(0.9rem, 3.2vh, 1.2rem);
    font-weight: 700;
    color: var(--accent-light);
    letter-spacing: 0.05em;
    text-transform: uppercase;
    margin-bottom: 0.6rem;
}
/* Recap final : toutes les cartes retournees cote a cote, bien plus
   grandes -- avec 1 carte par booster le recap est la derniere chose
   que le joueur voit, elle doit etre lisible. Meme base que le paquet
   sequential (78cqw / 420px), mais le plafond de HAUTEUR est 55cqh :
   la carte est en aspect-ratio 2/3 (hauteur = 1,5 x largeur), le
   cap 72cqh du paquet laissait la hauteur deborder du conteneur. */
.cc-reveal-card.summary {
    width: min(
        calc((78cqw - (var(--card-count, 1) - 1) * 14px) / var(--card-count, 1)),
        520px,
        55cqh
    );
    cursor: default;
}
/* Sortie de carte : envol vers le haut avec fondu */
.cc-reveal-card.pack-out {
    animation: cc-pack-out 0.32s ease-in forwards;
    pointer-events: none;
}
@keyframes cc-pack-out {
    from { transform: translateY(0) scale(1); opacity: 1; }
    to   { transform: translateY(-60px) scale(0.7); opacity: 0; }
}
.cc-reveal-card:hover:not(.flipped) {
    transform: translateY(-6px) scale(1.04);
}
@keyframes cc-reveal {
    from { opacity: 0; transform: scale(0.5); }
    to   { opacity: 1; transform: scale(1); }
}
.cc-reveal-inner {
    width: 100%;
    height: 100%;
    position: relative;
    transition: transform 0.6s ease;
    transform-style: preserve-3d;
}
.cc-reveal-card.flipped .cc-reveal-inner,
.cc-reveal-inner.flipped {
    transform: rotateY(180deg);
}
.cc-reveal-front,
.cc-reveal-back {
    position: absolute;
    width: 100%;
    height: 100%;
    border-radius: clamp(10px, 7.5%, 26px);
    overflow: hidden;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}
.cc-reveal-front {
    box-shadow: var(--shadow);
}
.cc-reveal-back {
    transform: rotateY(180deg);
    box-sizing: border-box;
}

/* Glow par rareté — uniquement sur la face avant (reveal back / album) */
.cc-card-rarity {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    opacity: 0.8;
}
.cc-card-icon {
    font-size: 2.4rem;
    line-height: 1;
}
.cc-card-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: clamp(10px, 7.5%, 26px);
    display: block;
}
.cc-card-name {
    font-size: 0.8rem;
    font-weight: 600;
    text-align: center;
}
/* Badge NOUVELLE ! proportionnel a la carte : 5cqh suit la taille de
   la carte (petit ecran -> petit badge, grand ecran -> badge lisible),
   plancher 0.7rem pour rester visible sur les plus petits ecrans. */
.cc-card-new {
    position: absolute;
    top: -2cqh;
    left: 50%;
    transform: translateX(-50%);
    font-size: max(5cqh, 0.7rem);
    color: #fbbf24;
    font-weight: 700;
    background: rgba(0, 0, 0, 0.7);
    padding: 0.4em 0.9em;
    border-radius: 4px;
    z-index: 2;
    white-space: nowrap;
}
.cc-card-bonus {
    font-size: 0.7rem;
    color: var(--accent-light);
    font-weight: 600;
}
.cc-reveal-actions {
    display: flex;
    justify-content: center;
    gap: 12px;
}
.cc-action-btn {
    padding: 15px 30px;
    background: rgba(59, 130, 246, 0.15);
    border: 1px solid var(--primary-light);
    border-radius: var(--radius);
    color: var(--text);
    cursor: pointer;
    font-weight: 600;
    font-size: 1.2rem;
    transition: background 0.2s;
}
.cc-action-btn:hover {
    background: rgba(59, 130, 246, 0.3);
}
.cc-album-grid {
    display: grid;
    /* Colonnes fluides : 192px ideal, compressibles jusqu'a 150px et
       repondantes a la largeur disponible (tablettes, fenetres etroites). */
    grid-template-columns: repeat(auto-fill, minmax(min(192px, 100%), 1fr));
    gap: 14px;
    justify-content: center;
}
.cc-album-card {
    width: 192px;
    height: 288px;
    border-radius: clamp(10px, 7.5%, 26px);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    position: relative;
    overflow: hidden;
    background: transparent;
}
.cc-album-card.locked {
    background: rgba(15, 23, 42, 0.5);
    opacity: 0.6;
}
.cc-album-card.locked .cc-card-icon {
    color: #334155;
}
.cc-card-count {
    position: absolute;
    bottom: 8px;
    right: 8px;
    font-size: 0.75rem;
    color: #f1f5f9;
    font-weight: 700;
    background: rgba(0, 0, 0, 0.7);
    padding: 2px 8px;
    border-radius: 10px;
    z-index: 2;
}
.cc-set-complete {
    grid-column: 1 / -1;
    text-align: center;
    padding: 10px;
    background: rgba(251, 191, 36, 0.15);
    border: 1px solid #fbbf24;
    border-radius: var(--radius);
    color: #fbbf24;
    font-weight: 700;
    margin-bottom: 4px;
}
.cc-back-btn {
    margin-right: 14px;
    align-self: center;
    padding: 6px 14px;
    background: rgba(59, 130, 246, 0.25);
    border: 1px solid var(--primary-light);
    border-radius: var(--radius);
    color: white;
    cursor: pointer;
    font-weight: 600;
    font-size: 0.9rem;
    white-space: nowrap;
    transition: background 0.2s;
}
.cc-back-btn:hover {
    background: rgba(59, 130, 246, 0.4);
}

/* ATELIER GALACTIQUE - Arbre d'améliorations */
#galactic-shop-modal.modal {
    /* Largeur du panneau central +5px : le bord droit reste colle au
       bord, le bord gauche deborde de 5px pour masquer le fond. */
    width: calc(50% + 5px);
    max-width: calc(50% + 5px);
    top: var(--top-height);
    left: 50%;
    /* Bord droit inchangé (colle au bord du panneau), bord gauche
       decale de 5px vers la gauche pour masquer le fond visible. */
    transform: translateX(calc(-50% + 2.5px));
    height: calc(100vh - var(--top-height));
    height: calc(100dvh - var(--top-height));
    max-height: calc(100vh - var(--top-height));
    max-height: calc(100dvh - var(--top-height));
}
#galactic-shop-modal .modal-content {
    /* Referent du badge record en position absolute (haut-gauche). */
    position: relative;
    background: linear-gradient(135deg, var(--bg-panel), var(--secondary-light));
    border: 2px solid #a78bfa;
    box-shadow: 0 0 30px rgba(167, 139, 250, 0.3);
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
}
#galactic-shop-modal .modal-header {
    background: linear-gradient(135deg, #a78bfa, #581c87);
    border-bottom: 2px solid #a78bfa;
}
/* Fondu de transition fin de lancement -> atelier galactique : voile noir
   qui s'opacifie, l'atelier s'ouvre dessus, puis le voile se dissipe. */
.post-travel-veil {
    position: fixed;
    inset: 0;
    background: #000;
    opacity: 0;
    transition: opacity 0.4s ease;
    pointer-events: none;
    z-index: 11500;
}
.post-travel-veil.visible {
    opacity: 1;
}
/* Badge record de distance : HAUT-GAUCHE de l'atelier post-lancement,
   toujours visible, lisible sur le degrade violet (fond sombre dedie). */
.post-travel-record {
    position: absolute;
    top: 10px;
    left: 10px;
    z-index: 5;
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 6px 12px;
    background: rgba(2, 6, 23, 0.85);
    border: 1px solid var(--accent-light);
    border-radius: var(--radius);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
    pointer-events: none;
}
.post-travel-record .ptr-label {
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #cbd5e1;
}
.post-travel-record .ptr-value {
    font-size: 1.05rem;
    font-weight: 800;
    color: var(--accent-light);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
/* Petits ecrans : le badge se resserre sans jamais recouvrir le titre. */
@media (max-width: 640px) {
    .post-travel-record {
        padding: 4px 8px;
        max-width: 46vw;
    }
    .post-travel-record .ptr-label { font-size: 0.6rem; }
    .post-travel-record .ptr-value {
        font-size: 0.85rem;
        overflow: hidden;
        text-overflow: ellipsis;
    }
}
/* ===== Atelier galactique post-voyage : plein ecran, non fermable ===== */
#galactic-shop-modal.modal.post-travel {
    width: 100vw !important;
    max-width: 100vw !important;
    top: 0 !important;
    left: 0 !important;
    transform: none !important;
    height: 100dvh !important;
    max-height: 100dvh !important;
    z-index: 1200;
}
#galactic-shop-modal.modal.post-travel .close-button {
    display: none;
}
/* Le badge record occupe le haut-gauche : le titre laisse la place. */
#galactic-shop-modal.modal.post-travel .modal-header {
    padding-left: 155px;
}
@media (max-width: 640px) {
    #galactic-shop-modal.modal.post-travel .modal-header {
        padding-left: 130px;
    }
}
.post-travel-summary {
    flex-shrink: 0;
    margin-bottom: 12px;
    padding: 12px 16px;
    background: rgba(16, 185, 129, 0.10);
    border: 1px solid rgba(16, 185, 129, 0.45);
    border-radius: var(--radius);
    text-align: center;
}
.pts-line {
    font-size: 0.95rem;
    color: var(--text);
    padding: 3px 0;
}
.pts-line strong {
    color: var(--accent-light);
}
.pts-unlocks {
    margin-top: 8px;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    justify-content: center;
}
.pts-planet {
    font-size: 0.8rem;
    font-weight: 700;
    padding: 3px 10px;
    border: 1px solid;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.06);
}
.post-travel-actions {
    flex-shrink: 0;
    padding: 14px 16px 16px;
    display: flex;
    justify-content: center;
    background: linear-gradient(to top, var(--bg-panel) 60%, transparent);
}
.post-travel-continue {
    background: linear-gradient(135deg, #10b981, #059669);
    color: white;
    border: none;
    border-radius: var(--radius);
    padding: 14px 36px;
    font-size: 1.05rem;
    font-weight: 700;
    cursor: pointer;
    transition: all 0.3s ease;
    box-shadow: var(--shadow-lg);
    position: relative;
}
.post-travel-continue::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.55);
    opacity: 1;
    animation: ptsPulse 1.6s ease-in-out infinite;
    will-change: opacity;
}
@keyframes ptsPulse {
    0%, 100% { opacity: 0; }
    50%      { opacity: 1; }
}
.post-travel-continue:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg), 0 0 24px rgba(16, 185, 129, 0.5);
}

#galactic-shop-modal .modal-body {
    flex: 1;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    max-height: none;
}
.galactic-intro {
    text-align: center;
    color: var(--text-light);
    font-size: 0.9rem;
    margin-bottom: 16px;
    padding: 10px;
    background: rgba(167, 139, 250, 0.08);
    border-radius: var(--radius);
    flex-shrink: 0;
}
/* Gros bouton Suite infinie de l'atelier galactique :
   convertit toutes les PE disponibles en +1% de production chacune. */
.infinite-buy-button-wrap {
    margin: 0 0 14px;
}
.infinite-buy-button {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    width: 100%;
    font-family: inherit;
    padding: 16px 18px;
    cursor: pointer;
    border: 2px solid var(--accent, #fbbf24);
    border-radius: 16px;
    background: linear-gradient(135deg, rgba(88, 28, 135, 0.45), rgba(30, 20, 80, 0.45));
    box-shadow: 0 0 24px rgba(251, 191, 36, 0.25), inset 0 0 24px rgba(196, 181, 253, 0.12);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.infinite-buy-button:hover:not(:disabled) {
    transform: translateY(-2px);
    box-shadow: 0 6px 30px rgba(251, 191, 36, 0.45);
}
.infinite-buy-button:disabled {
    opacity: 0.55;
    cursor: default;
}
.ibb-icon { font-size: 22px; }
.ibb-title {
    font-size: 1.15rem;
    font-weight: 800;
    letter-spacing: 0.5px;
    color: #fff;
}
.ibb-desc { font-size: 0.85rem; color: #cbd5e1; }
.ibb-cta {
    margin-top: 6px;
    font-size: 1rem;
    font-weight: 800;
    color: #1a1200;
    background: linear-gradient(135deg, #fbbf24, #f59e0b);
    border-radius: 10px;
    padding: 8px 18px;
}
.ibb-cta.disabled { filter: grayscale(0.6); opacity: 0.6; }

.galactic-shop-list {
    display: flex;
    flex-direction: column;
    gap: 18px;
    flex: 1;
}
.galactic-branch {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.galactic-branch-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    background: rgba(255,255,255,0.05);
    border-radius: var(--radius);
    border-left: 4px solid var(--branch-color);
    flex-shrink: 0;
}
.galactic-branch-icon {
    font-size: 1.2rem;
}
.galactic-branch-name {
    font-size: 1rem;
    font-weight: 700;
    color: var(--branch-color);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.galactic-tree {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 10px;
}
.galactic-node {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 12px;
    background: rgba(15, 23, 42, 0.7);
    border: 1px solid var(--border-light);
    border-radius: var(--radius);
    border-left: 3px solid var(--branch-color);
    transition: all 0.2s;
}
.galactic-node:hover:not(.locked) {
    background: rgba(30, 41, 59, 0.9);
    border-color: var(--branch-color);
    box-shadow: 0 0 10px rgba(167, 139, 250, 0.2);
}
.galactic-node.maxed {
    border-color: #fbbf24;
    background: rgba(251, 191, 36, 0.1);
}
.galactic-node.locked {
    opacity: 0.45;
    filter: grayscale(0.5);
}
.galactic-node.too-expensive {
    opacity: 0.7;
}
.galactic-node-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}
.galactic-node-name {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text);
}
.galactic-node-max {
    font-size: 0.8rem;
    font-weight: 800;
    color: #fbbf24;
    background: rgba(251, 191, 36, 0.2);
    padding: 2px 8px;
    border-radius: 10px;
}
.galactic-node-desc {
    font-size: 0.9rem;
    color: var(--text-light);
    line-height: 1.4;
    min-height: 2.4em;
}
.galactic-node-bottom {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
}
.galactic-node-level {
    font-size: 0.78rem;
    color: #a78bfa;
    font-weight: 600;
    white-space: nowrap;
}
.galactic-req {
    font-size: 0.72rem;
    color: var(--text-dark);
    font-style: italic;
    text-align: right;
}
.galactic-btn {
    padding: 6px 12px;
    border: none;
    border-radius: var(--radius);
    background: #a78bfa;
    color: white;
    font-weight: 700;
    font-size: 0.85rem;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.2s;
}
.galactic-btn:hover:not(:disabled) {
    background: #a78bfa;
    transform: scale(1.05);
}
.galactic-btn:disabled {
    background: #475569;
    cursor: not-allowed;
    opacity: 0.6;
}

/* ============================================
   MOBILE / RESPONSIVE (max-width: 1024px)
   ============================================ */

/* Breakpoint principal : en dessous de 1024px on passe en vue "mobile"
   avec navigation par onglets en bas d'écran. */
@media (max-width: 1024px) and (pointer: coarse) {

    :root { --mobile-nav-height: calc(56px * var(--mscale, 1)); --top-height: calc(56px * var(--mscale, 1)); }

    html, body { overflow: hidden; }

    /* --- Grille : une seule vue visible à la fois --- */
    .main-grid {
        grid-template-columns: 1fr;
        grid-template-rows: 100%;
        height: calc(100vh - var(--top-height));
        height: calc(100svh - var(--top-height));
    }

    /* --- Nav bas d'écran --- */
    .mobile-nav {
        display: flex;
        position: fixed;
        bottom: 0; left: 0; right: 0;
        height: calc(var(--mobile-nav-height) + env(safe-area-inset-bottom, 0px));
        padding-bottom: env(safe-area-inset-bottom, 0px);
        background: linear-gradient(135deg, var(--secondary-light), var(--secondary));
        border-top: calc(1px * var(--mscale, 1)) solid var(--border);
        box-shadow: 0 -calc(4px * var(--mscale, 1)) calc(12px * var(--mscale, 1)) rgba(0,0,0,0.5);
        /* Au-dessus des modals (1200) : la nav reste visible et cliquable
           meme dans Collection / Contrats / Atelier. */
        z-index: 1350;
    }
    .mobile-nav button {
        flex: 1;
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
        gap: calc(6px * var(--mscale, 1));
        background: none;
        border: none;
        color: var(--text-light);
        font-family: 'Space Grotesk', 'Inter', sans-serif;
        font-size: 0.85rem;
        font-weight: 600;
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }
    .mobile-nav button + button {
        border-left: calc(1px * var(--mscale, 1)) solid var(--border);
    }
    .mobile-nav button .nav-icon { font-size: 1.3rem; line-height: 1; display: flex; align-items: center; }
    .mobile-nav button .nav-icon .nav-img {
        width: calc(24px * var(--mscale, 1));
        height: calc(24px * var(--mscale, 1));
        object-fit: contain;
        display: block;
        margin: 0;
    }
    .mobile-nav button .nav-icon .nav-img.nav-rocket {
        width: calc(16px * var(--mscale, 1));
        height: calc(26px * var(--mscale, 1));
        transform: rotate(60deg);
        margin-left: 0;
        margin-right: 0;
    }
    .mobile-nav button.active { color: var(--accent-light); }

    /* Les panneaux occupent tout l'écran; seule la vue active est affichée */
    .main-grid > .left-panel,
    .main-grid > .center-panel,
    .main-grid > .right-panel {
        grid-area: 1 / 1;
        height: 100%;
        display: none;
        border: none !important;
        padding-bottom: calc(var(--mobile-nav-height) + env(safe-area-inset-bottom, 0px));
    }
    .main-grid.mobile-view-left  > .left-panel  { display: flex; overflow: hidden; }
    .main-grid.mobile-view-left > .left-panel > .left-panel-scroll { -webkit-overflow-scrolling: touch; }
    .main-grid.mobile-view-center > .center-panel { display: flex; }
    .main-grid.mobile-view-right > .right-panel { display: flex; flex-direction: column; overflow: hidden; }
    .main-grid.mobile-view-right > .right-panel > .buildings-list { -webkit-overflow-scrolling: touch; overflow-anchor: none; }

    /* --- Barre du haut compacte --- */
    .top-bar { height: calc(54px * var(--mscale, 1)) !important; min-height: calc(54px * var(--mscale, 1)); max-height: calc(54px * var(--mscale, 1)); padding: 0 calc(10px * var(--mscale, 1)); }
    .top-logo-img { height: calc(34px * var(--mscale, 1)); }
    .top-logo-text-img { height: calc(30px * var(--mscale, 1)); }
    .top-bar-controls { flex-direction: row; gap: calc(4px * var(--mscale, 1)); padding: 0 calc(4px * var(--mscale, 1)); }
    /* Taille d'origine preservEe : 40px fixes (pas de --mscale qui
       rapetissait a ~34px), cappEe seulement si la barre compacte
       n'a physiquement pas la place. */
    .control-button { width: min(40px, calc(48px * var(--mscale, 1))); height: min(40px, calc(48px * var(--mscale, 1))); font-size: min(17px, calc(20px * var(--mscale, 1))); }

    /* --- Compteurs --- */
    /* Mobile : la boutique est en bas, le HUD revient centre normalement.
       La ligne compteur+bonus repasse en colonne : la largeur est trop
       etroite pour les cote a cote sans faire deborder les chiffres. */
    .hud-top-row { top: calc(56px * var(--mscale, 1)); flex-wrap: nowrap; max-width: calc(100% - calc(24px * var(--mscale, 1))); transform: translateX(-50%); }
    .hud-counters-row { flex-direction: column; gap: 4px; width: 100%; }
    .hud-counters-row .bonus-timer { position: static; transform: none; max-width: 100%; }
    /* Compteur mobile : largeur equilibree -- ni la boite etroite d'origine
       (rognait les grands nombres), ni la boite 50vw trop massive. Le
       contenu garde l'auto-ajustement de police de fitCounterFontSize. */
    .counters {
        width: auto;
        max-width: 100%;
        min-width: 34vw;
        box-sizing: border-box;
    }
    .counter { font-size: 1.9rem; padding: 0 4px; }
    .hud-top-row { width: 100%; }
    .hud-counters-row { width: 100%; align-items: stretch; }
    .counters { width: auto; max-width: calc(100% - 16px); flex-wrap: nowrap; gap: clamp(calc(6px * var(--mscale, 1)), calc(0.8vw * var(--mscale, 1)), calc(10px * var(--mscale, 1))); padding: calc(6px * var(--mscale, 1)) clamp(calc(8px * var(--mscale, 1)), calc(1vw * var(--mscale, 1)), calc(12px * var(--mscale, 1))); }
    .counters { flex-direction: row !important; }
    .counter { font-size: 0.95rem; min-width: 0; }
    .bonus-timer { max-width: 100%; }

    /* --- Barre d'upgrades (horizontale, déjà scrollable) --- */
    .upgrades-bar { height: calc(57px * var(--mscale, 1)); }
    .upgrades-title { display: none; }
    .upgrades-container-center { margin-left: 0; gap: calc(8px * var(--mscale, 1)); }
    .upgrade-icon { min-width: calc(52px * var(--mscale, 1)); height: calc(52px * var(--mscale, 1)); }
    .upgrade-img { width: calc(31px * var(--mscale, 1)); height: calc(31px * var(--mscale, 1)); }

    /* --- Scène de construction : zoom adaptatif --- */
    .center-content { height: calc(100% - calc(44px * var(--mscale, 1))) !important; }
    .construction-scene-100x100 { min-height: 0; }
    /* Fusee et decor : la case d'achat vit desormais en bas (barre pleine
       largeur), plus besoin de degager la colonne droite. Avant : left
       calc(50% + 300px) poussait la fusee HORS du cadre a droite sur
       petit ecran. Ancrage centre/gauche : translateX(-50%) de
       applySceneScale la recentre, legerement a gauche pour laisser la
       place a la barre des pieces. */
    /* Decalage cumule de ~20% de la largeur ecran vers la gauche demande. */
    .scene-world { left: calc(30% - 10px) !important; }
    .rocket-parts-shop {
        position: fixed;
        bottom: calc(var(--mobile-nav-height) + env(safe-area-inset-bottom, 0px) + 5px);
        left: calc(8px * var(--mscale, 1));
        right: calc(8px * var(--mscale, 1));
        transform: none;
        width: auto;
        max-height: calc(46vh - var(--mobile-nav-height));
        overflow-y: auto;
        z-index: 58;
}
    .rocket-part-left { width: calc(44px * var(--mscale, 1)); height: calc(44px * var(--mscale, 1)); }
    .rocket-part-icon, .rocket-part-icon-placeholder { width: calc(40px * var(--mscale, 1)); height: calc(40px * var(--mscale, 1)); }

    /* Médaille cliquable plus grosse et plus accessible */
    .medal {
        /* !important : la medaille porte un style inline (right/top) dans index.html */
        /* Collee au bord droit puis etendue de 10px vers la gauche
           (demande explicite). */
        right: 10px !important; left: auto !important;
        top: 24% !important;
        transform: translateY(-50%);
        /* -44% cumule du desktop (293px -> 164px -> 148px). */
        width: 148px !important;
        height: 148px !important;
    }
    .medal:hover { transform: translateY(-50%) scale(1.05); }
    .medal:active { transform: translateY(-50%) scale(0.95); }

    /* Paysage : espace vertical trop serre ; la medaille reste a droite, sous les compteurs */
    @media (max-width: 1024px) and (pointer: coarse) and (orientation: landscape) {
        .medal { top: 55% !important; }
    }

    /* --- Bouton lancement : pilule rouge collee a la barre de navigation, ancree au viewport --- */
    .launch-button {
        position: fixed;
        bottom: calc(var(--mobile-nav-height) + env(safe-area-inset-bottom, 0px) + calc(9px * var(--mscale, 1)));
        left: 50%;
        right: auto;
        transform: translateX(-50%);
        padding: calc(12px * var(--mscale, 1)) calc(18px * var(--mscale, 1));
        width: auto; height: auto;
        border-radius: calc(999px * var(--mscale, 1));
        justify-content: center;
        font-size: 0.85rem;
    }
    .launch-button:hover { transform: translateX(-50%) translateY(-calc(2px * var(--mscale, 1))); }
    .launch-button:active { transform: translateX(-50%) translateY(0); }
    /* Securite anti-decalage : le tap mobile declenche :hover/:active collants
       puis l'etat disabled pendant le lancement -- TOUS les etats conservent
       le centrage translateX(-50%), le bouton ne saute plus a droite. */
    .launch-button:disabled,
    .launch-button.ready,
    .launch-button.pulsing { transform: translateX(-50%) !important; }
    .launch-button.ready:active,
    .launch-button.ready:hover { transform: translateX(-50%) translateY(0) !important; }
    .launch-button-text { display: block; font-size: 0.85rem; letter-spacing: calc(0.5px * var(--mscale, 1)); }
    /* Compte a rebours DECOLLAGE : 3.2rem desktop debordait sur petit
       ecran -- taille mobile bornee + largeur contrainte. */
    .launch-countdown {
        font-size: clamp(1.6rem, calc(2.2rem * var(--mscale, 1)), 2.4rem);
        white-space: nowrap;
        max-width: 94%;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* --- Panneau gauche (Espace) --- */
    .left-panel { padding: calc(12px * var(--mscale, 1)); }
    /* Titre jamais ecrase : il garde sa hauteur dans le flex-column */
    .left-panel h3 { flex-shrink: 0; }
    /* Hauteur REDUITE : la minimap mangeait ~1/4 de l'ecran mobile.
       Les planetes ne suivent pas la baisse : leur taille est recalculee
       ci-dessous en cqw (largeur) au lieu de cqh (hauteur). */
    .mini-space-map { height: clamp(calc(96px * var(--mscale, 1)), calc(14vh * var(--mscale, 1)), calc(130px * var(--mscale, 1))); flex-shrink: 0; }

    .mini-space-map .space-planet .planet-emoji { font-size: 0.95rem; }
    /* Cartes mini-jeux empilees verticalement : plus propre a lire,
       l'utilisateur scrolle si necessaire. */
    .mini-games-container { flex-direction: column; }
    .mini-game-card { flex: 0 0 auto; }
    .mini-game-card .game-cost { font-size: 0.65rem; }
    .mini-games-section { display: flex !important; flex: 0 0 auto; }

    /* --- Panneau droit (Bâtiments) --- */
    .right-panel { padding: 0 calc(6px * var(--mscale, 1)) calc(var(--mobile-nav-height) + env(safe-area-inset-bottom, 0px) + calc(12px * var(--mscale, 1))); }
    .buildings-header {
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: calc(6px * var(--mscale, 1));
        height: calc(44px * var(--mscale, 1));
        padding: 0 calc(4px * var(--mscale, 1));
    }
    .buildings-header h3 { font-size: 0.9rem; margin: 0; white-space: nowrap; }
    .multiplier-buttons { gap: calc(3px * var(--mscale, 1)); }
    .multiplier-btn { padding: calc(4px * var(--mscale, 1)) calc(9px * var(--mscale, 1)); font-size: 0.75rem; }
    .buildings-list { gap: calc(6px * var(--mscale, 1)); margin-top: calc(2px * var(--mscale, 1)); }
    /* Cases batiments mobile : l'image occupe AU MINIMUM 25% de la largeur,
       et tous les textes (nom, possedes, production) tiennent sur UNE SEULE
       LIGNE au-dessus du bouton acheter. */
    .building-item {
        grid-template-columns: minmax(25%, calc(96px * var(--mscale, 1))) 1fr;
        grid-template-areas:
            "icon info"
            "icon buy";
        grid-template-rows: auto auto;
        row-gap: calc(6px * var(--mscale, 1));
        column-gap: calc(10px * var(--mscale, 1));
        min-height: 0;
        max-height: none;
        overflow: hidden;
        padding: calc(10px * var(--mscale, 1));
        align-items: center;
    }
    .building-left { grid-area: info; display: flex; flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: calc(8px * var(--mscale, 1)); min-width: 0; }
    .building-name { font-size: 1rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; flex: 0 1 auto; }
    .building-ownership { font-size: 0.85rem; flex-shrink: 0; }
    .building-production { font-size: 0.85rem; flex-shrink: 0; color: var(--accent-light); }
    .building-center { grid-area: icon; align-self: stretch; display: flex; align-items: center; justify-content: center; min-height: 0; }
    .building-image { height: auto; width: auto; max-width: 100%; min-width: 0; max-height: calc(72px * var(--mscale, 1)); object-fit: contain; filter: none; }
    /* Reequilibre : neutralise les marges negatives desktop */
    .building-item.nozzles .building-image, .building-item.workshop .building-image, .building-item.engines .building-image, .building-item.fuel-tank .building-image, .building-item.cockpit .building-image, .building-item.shield .building-image, .building-item.launch-pad .building-image, .building-item.astronaut .building-image { margin-left: 0; }
    .building-item.nozzles .building-image { height: auto; max-height: calc(72px * var(--mscale, 1)); }
    .building-item.rocket-body .building-image, .building-item.boosters-left .building-image, .building-item.boosters-right .building-image { max-height: calc(72px * var(--mscale, 1)); margin-left: 0; }
    .building-right { grid-area: buy; display: flex; flex-direction: row; align-items: center; justify-content: flex-end; gap: calc(8px * var(--mscale, 1)); min-width: 0; }
    .building-item button {
        flex: 1;
        width: auto; height: auto; min-height: calc(32px * var(--mscale, 1));
        display: flex; flex-direction: column; align-items: center; justify-content: center;
        padding: calc(4px * var(--mscale, 1)) calc(6px * var(--mscale, 1));
        font-size: 0.95rem;
        line-height: 1.15;
        border-radius: var(--radius);
        box-sizing: border-box;
        text-align: center;
        white-space: nowrap;
    }
    /* Texte Parts/s trop long (gros nombres) : sur DEUX lignes plutot que
       deborder de la case. Le flex-shrink: 0 (ligne d'origine) ET le
       white-space: nowrap herite du parent (.building-left) empechaient
       TOUT repli -- il faut les deux annules + une largeur contrainte
       pour que le retour a la ligne s'active reellement. */
    .building-left .building-production {
        font-size: 0.87rem;
        margin-left: 0;
        color: var(--accent-light);
        flex: 0 1 auto;
        flex-shrink: 1;
        min-width: 0;
        max-width: 100%;
        white-space: normal;
        overflow-wrap: anywhere;
        word-break: break-word;
        text-align: right;
    }

    /* --- Modales : plein écran --- */
    /* Exception : la modale Expédition terminée garde sa fenêtre centrée
       compacte -- le plein écran générique cassait son centrage (top 50%
       + translate) et la rendait démesurée pour 5 lignes de résultats. */
    #launch-results-modal.modal {
        position: fixed !important;
        top: 50% !important;
        left: 50% !important;
        transform: translate(-50%, -50%) !important;
        width: calc(100vw - 24px) !important;
        max-width: 460px !important;
        height: auto !important;
        max-height: calc(100dvh - 24px) !important;
        border-radius: var(--radius) !important;
        z-index: 13000 !important;
    }
    .modal {
        width: 100vw !important; max-width: 100vw !important;
        height: 100dvh; max-height: 100dvh !important;
        top: 0; left: 0;
        transform: none !important;
        border-radius: 0;
        border: none;
        z-index: 1200;
        /* La nav basse reste visible et cliquable : le modal cede la place. */
        padding-bottom: calc(var(--mobile-nav-height) + env(safe-area-inset-bottom, 0px));
        box-sizing: border-box;
    }
    .modal-content {
        width: 100% !important; max-width: 100% !important;
        height: 100% !important; max-height: 100% !important;
        border-radius: 0 !important;
        display: flex; flex-direction: column;
    }
    .modal-header { flex-shrink: 0; padding: calc(10px * var(--mscale, 1)) calc(12px * var(--mscale, 1)); gap: calc(8px * var(--mscale, 1)); }
    .modal-header h2 { font-size: 1.05rem; }
    .modal-parts-counter { font-size: 0.8rem; padding: calc(4px * var(--mscale, 1)) calc(10px * var(--mscale, 1)); }
    .modal-body {
        flex: 1;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        max-height: none !important;
        padding: calc(12px * var(--mscale, 1));
        padding-bottom: calc(calc(12px * var(--mscale, 1)) + env(safe-area-inset-bottom, 0px));
    }
    .modal-button { padding: calc(14px * var(--mscale, 1)); font-size: 1rem; }
    /* Reveal nouveau batiment : animation sans translate (modal plein ecran,
       le translate des keyframes desktop le faisait flasher en haut a gauche) */
    .new-building-modal.active { animation: nbModalInMobile 0.35s cubic-bezier(0.34, 1.56, 0.64, 1); }
    /* Pop-up nouveau batiment : petite fenetre centree comme sur PC,
       mais proportionnellement plus grande ; hauteur auto (max 80dvh). */
    .new-building-modal {
        width: 90vw !important; max-width: calc(480px * var(--mscale, 1)) !important;
        height: auto !important; max-height: 80dvh !important;
        top: 50% !important; left: 50% !important;
        transform: translate(-50%, -50%) !important;
        border-radius: var(--radius);
        border: calc(1px * var(--mscale, 1)) solid var(--border-light);
        padding-bottom: 0;
    }
    .nb-reveal { width: 40dvh; height: 40dvh; max-width: calc(300px * var(--mscale, 1)); max-height: calc(300px * var(--mscale, 1)); margin-bottom: calc(8px * var(--mscale, 1)); }
    .modal-body.new-building-body { justify-content: center; }


    /* Atelier galactique / Contrats / Collection : plein écran */
    #galactic-shop-modal.modal,
    #contracts-modal.modal,
    #card-collection-modal.modal {
        width: 100vw !important; max-width: 100vw !important;
        top: 0 !important; left: 0 !important; transform: none !important;
        height: 100dvh !important; max-height: 100dvh !important;
    }
    .galactic-tree { grid-template-columns: 1fr; }
    .galactic-node-desc { min-height: 0; }
    /* Bouton d'achat des ameliorations galactiques : plus grand en mobile,
       il occupe la largeur disponible du noeud. */
    .galactic-node-bottom { display: flex; }
    .galactic-btn {
        flex: 1;
        width: 100%;
        padding: calc(12px * var(--mscale, 1)) calc(10px * var(--mscale, 1));
        font-size: 1rem;
        border-radius: calc(10px * var(--mscale, 1));
    }


    /* Collection de cartes */
    .cc-booster-options { flex-direction: column; align-items: stretch; }
    .cc-booster-btn { min-width: 0; max-width: none; }
    .cc-booster-img { max-width: calc(140px * var(--mscale, 1)); }
    .cc-album-grid { grid-template-columns: repeat(3, 1fr); gap: calc(8px * var(--mscale, 1)); }
    .cc-album-card { width: 100%; height: auto; aspect-ratio: 2 / 3; }
    .cc-reveal-cards { gap: calc(8px * var(--mscale, 1)); }
    .cc-reveal-card { width: min(calc((100cqw - (var(--card-count, 3) - 1) * calc(8px * var(--mscale, 1))) / var(--card-count, 3)), calc(40cqh)); height: auto; }
    /* Carte seule : largeur limitee pour rester lisible, pas plein ecran */
    .cc-reveal-cards:has(> .cc-reveal-card.pack:only-child) { max-width: none; }
    .cc-reveal-card.pack { width: min(63cqw, 41vh); max-width: 67vw; }
    /* 3 cartes : grille 2 colonnes (2 en haut, 1 centree en bas) */

    /* Toast au-dessus de la nav */
    #toast-container { bottom: calc(var(--mobile-nav-height) + env(safe-area-inset-bottom, 0px) + calc(12px * var(--mscale, 1))); }
    .toast { font-size: clamp(0.95rem, 1.3vw + 0.6rem, 1.2rem); padding: clamp(calc(6px * var(--mscale, 1)), calc(1vw * var(--mscale, 1)), calc(9px * var(--mscale, 1))) clamp(calc(10px * var(--mscale, 1)), calc(1.6vw * var(--mscale, 1)), calc(16px * var(--mscale, 1))); display: flex; align-items: center; justify-content: center; text-align: center; }
    .toast .toast-icon { width: clamp(calc(18px * var(--mscale, 1)), calc(2.6vw * var(--mscale, 1)), calc(26px * var(--mscale, 1))); height: clamp(calc(18px * var(--mscale, 1)), calc(2.6vw * var(--mscale, 1)), calc(26px * var(--mscale, 1))); margin-right: calc(8px * var(--mscale, 1)); }
    .toast-text {
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
        line-height: 1.25;
        min-width: 0;
        flex: 1;
        width: auto;
        width: 100%;
    }

    /* Comètes un peu plus petites */
    .random-bonus { width: clamp(calc(96px * var(--mscale, 1)), calc(15vw * var(--mscale, 1)), calc(150px * var(--mscale, 1))); height: clamp(calc(96px * var(--mscale, 1)), calc(15vw * var(--mscale, 1)), calc(150px * var(--mscale, 1))); }
    .comet-img { width: clamp(calc(96px * var(--mscale, 1)), calc(15vw * var(--mscale, 1)), calc(150px * var(--mscale, 1))); height: clamp(calc(96px * var(--mscale, 1)), calc(15vw * var(--mscale, 1)), calc(150px * var(--mscale, 1))); }

    /* Tooltip : plus lisible au doigt, reste au-dessus du clavier virtuel */
    .upgrade-tooltip .tooltip-line {
    display: block;
    white-space: normal;    overflow-wrap: break-word;
}

.upgrade-tooltip { font-size: 0.8rem; max-width: 88vw; white-space: pre-line; border-left-width: calc(3px * var(--mscale, 1)); }

    /* Sur mobile, pas de tooltip CSS au survol (pas de hover) */
    .building-item:hover::after { opacity: 0; visibility: hidden; }

    /* --- Corrections ergonomie mobile --- */
    /* Titres de sections : jamais plus larges que l'ecran */
    .left-panel h3, .right-panel h3, .center-panel h3 {
        max-width: 100%;
        box-sizing: border-box;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        margin-left: 0;
        margin-right: 0;
    }
    /* Cibles tactiles >= calc(44px * var(--mscale, 1)) (recommandation Apple/Google) */
    .multiplier-btn { min-height: calc(40px * var(--mscale, 1)); padding: calc(8px * var(--mscale, 1)) calc(12px * var(--mscale, 1)); font-size: 0.85rem; }
    .building-item button { min-height: calc(54px * var(--mscale, 1)); padding: calc(14px * var(--mscale, 1)) calc(8px * var(--mscale, 1)); font-size: 0.9rem; }
    .rocket-part-btn { min-height: calc(36px * var(--mscale, 1)); padding: calc(8px * var(--mscale, 1)) calc(6px * var(--mscale, 1)); font-size: 0.75rem; }
    .galactic-shop-btn { min-height: calc(44px * var(--mscale, 1)); }
    .contract-buy-btn { min-height: calc(44px * var(--mscale, 1)); padding: calc(12px * var(--mscale, 1)) calc(18px * var(--mscale, 1)); font-size: 0.95rem; align-self: stretch; }
    .modal-button { min-height: calc(48px * var(--mscale, 1)); }
    .control-button { width: calc(44px * var(--mscale, 1)); height: calc(44px * var(--mscale, 1)); font-size: calc(18px * var(--mscale, 1)); }
    /* Minimap : tailles gerees par les unites conteneur (cqh) */
    /* Cartes mini-jeux : texte a taille lisible */
    .mini-game-card .game-name { font-size: 0.85rem; }
    .mini-game-card .game-cost { font-size: 0.75rem; }
    /* Compteurs : chiffres legèrement plus grands */
    .counter { font-size: 1rem; }
    .counter-label { font-size: 0.7rem; }
    /* Boutons de fermeture de modals plus faciles a toucher */
    .close-button { min-width: calc(34px * var(--mscale, 1)); min-height: calc(34px * var(--mscale, 1)); display: inline-flex; align-items: center; justify-content: center; border: calc(2px * var(--mscale, 1)) solid rgba(255, 255, 255, 0.45); border-radius: calc(8px * var(--mscale, 1)); padding: calc(4px * var(--mscale, 1)); flex-shrink: 0; background: rgba(0, 0, 0, 0.25); }
    /* Boutons langue et params */
    .lang-btn {
        min-height: calc(48px * var(--mscale, 1));
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: 0.5rem;
        font-size: 1.05rem;
        white-space: nowrap;
    }
    .lang-btn .lang-code { font-size: 1rem; font-weight: 600; letter-spacing: calc(0.5px * var(--mscale, 1)); }
    /* Titres de modals : cedent la place au bouton fermer, jamais de debordement */
    .modal-header h2 { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .close-button { flex-shrink: 0; }
    /* Cartes mini-jeux : jamais plus larges que l'ecran */
    .mini-games-container { max-width: 100%; box-sizing: border-box; }
    .mini-game-card { min-width: 0; }
    .game-info { min-width: 0; overflow: hidden; }
    /* km de la minimap : taille adaptative via cqh */
}

/* Petits écrans (<calc(480px * var(--mscale, 1))) : resserrage supplémentaire */
@media (max-width: 480px) and (pointer: coarse) {
    .medal { top: 30% !important; }
    .rocket-parts-shop { width: auto; }
    /* Cartes album plus grandes : une seule colonne pleine largeur sur petits ecrans */
    .cc-album-grid { grid-template-columns: repeat(3, 1fr); }
    .cc-album-card { width: 100%; max-width: calc(340px * var(--mscale, 1)); margin: 0 auto; }
    .building-item { grid-template-columns: minmax(25%, calc(96px * var(--mscale, 1))) 1fr; grid-template-areas: "icon info" "icon buy"; }
    .building-item button { width: auto; min-height: calc(32px * var(--mscale, 1)); height: auto; font-size: 0.95rem; }
    .building-image { max-height: calc(88px * var(--mscale, 1)); min-width: 0; }
    .building-name { font-size: 0.95rem; }
    .multiplier-btn { padding: calc(5px * var(--mscale, 1)) calc(10px * var(--mscale, 1)); }
    .counters { width: auto; max-width: calc(100vw - 20px); flex-wrap: nowrap; }
    .counter { font-size: calc(1.2rem * var(--mscale, 1)); white-space: nowrap; }
}
/* Tres petits ecrans : la medaille adaptive se reduit via son clamp cqh */

/* Ecrans desktop etroits : memes proportions que le layout de base
   (22.5% / 55% / 22.5%). Plus aucun remaniement : l'UI reste identique
   a toutes les tailles desktop, seul le rendu deltaire s'adapte. */
@media (min-width: 1025px) and (max-width: 1520px) {
    .building-name { white-space: normal; line-height: 1.15; }
    .building-item { max-height: none; }
    .building-left { overflow: visible; }
}

/* Desktop : la case d'achat vit desormais en bas du panneau central. */
@media (min-width: 1025px) {
    .rocket-parts-shop { bottom: 25px; }
}

/* Écrans larges (>=1920px) : la carte d'ouverture de booster exploite
   enfin la place -- l'ancienne regle la RAPETISSAIT a 378px sur les
   grands ecrans, c'etait l'inverse du but. Plafond releve a 520px. */
@media (min-width: 1920px) {
    .cc-reveal-card.pack { width: min(70.2cqw, 520px, 68cqh); }
}

/* Desktop : image du reveal doublee (mobile : 210px).
   Bornée à 30dvh pour laisser la place aux textes du bas dans le cadre. */
@media (min-width: 1025px) {
    .new-building-modal { width: 92%; max-width: 35rem; }
    .nb-reveal { width: 26.25rem; height: 26.25rem; max-width: 100%; max-height: min(30dvh, 26.25rem); }
    .new-building-body h3 { font-size: 1.6rem; }
    .new-building-body p { font-size: 1rem; }
    .nb-stat-label { font-size: 0.8rem; }
    .nb-stat-value { font-size: 1.15rem; }
}

/* Grands ecrans (>1520) : grandes images conservees ; les noms longs
   se replient sur 2 lignes plutot que de couper ou de reduire les images */
@media (min-width: 1521px) {
    .building-name { white-space: normal; line-height: 1.15; }
    .building-item { max-height: none; }
    .building-left { overflow: visible; }
}

/* Desktop : nav mobile masquée sauf sur écrans tactiles étroits.
   Pointeur absent (headless) ou fin = layout PC. */
@media not all and ((max-width: 1024px) and (pointer: coarse)) {
    .mobile-nav { display: none; }
}

/* ============================================
   CARDS LIGHTBOX (vue agrandie, album uniquement)
   ============================================ */

.cc-lightbox {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 1300;
}

.cc-lightbox.open {
    display: flex;
    align-items: center;
    justify-content: center;
}

.cc-lightbox-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(2, 6, 23, 0.85);
    backdrop-filter: blur(4px);
}

.cc-lightbox-body {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    max-width: min(92vw, 480px);
    animation: cc-lightbox-in 0.25s ease;
}

@keyframes cc-lightbox-in {
    from { opacity: 0; transform: scale(0.85); }
    to   { opacity: 1; transform: scale(1); }
}

.cc-lightbox-img {
    width: 100%;
    max-height: 72vh;
    object-fit: contain;
    border-radius: clamp(10px, 7.5%, 26px);
    box-shadow: 0 0 40px rgba(59, 130, 246, 0.35);
    cursor: pointer;
}

.cc-lightbox-info {
    text-align: center;
}

.cc-lightbox-name {
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--text);
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.8);
}

.cc-lightbox-sub {
    font-size: 0.95rem;
    color: var(--accent-light);
    font-weight: 600;
    margin-top: 4px;
}

@media (max-width: 1024px) and (pointer: coarse) {
    .cc-lightbox-body {
        max-width: 88vw;
        gap: calc(10px * var(--mscale, 1));
    }
    .cc-lightbox-img {
        max-height: 62vh;
    }
    .cc-lightbox-name {
        font-size: 1.2rem;
    }
    .cc-lightbox-sub {
        font-size: 0.85rem;
    }
}

/* ===== Grosse notification : fusée prête pour la planète suivante ===== */
.next-planet-notification {
    position: fixed;
    inset: 0;
    background: rgba(2, 6, 23, 0.85);
    backdrop-filter: blur(6px);
    display: none;
    align-items: center;
    justify-content: center;
    z-index: 1300;
    opacity: 0;
    transition: opacity 0.35s ease;
}
.next-planet-notification.active {
    display: flex;
    opacity: 1;
}
.npn-content {
    text-align: center;
    padding: 28px 30px 32px;
    max-width: 480px;
    position: relative;
    width: min(92vw, 480px);
    background: linear-gradient(160deg, var(--bg-panel), var(--secondary-light));
    border: 2px solid var(--primary-light);
    border-radius: 20px;
    box-shadow: 0 0 60px rgba(59, 130, 246, 0.45), 0 25px 50px rgba(0, 0, 0, 0.6);
    animation: npnPopIn 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes npnPopIn {
    from { transform: scale(0.6); opacity: 0; }
    to   { transform: scale(1); opacity: 1; }
}
.npn-planet-img {
    display: flex;
    justify-content: center;
    margin-bottom: 14px;
}
.npn-planet-img img {
    width: min(clamp(88px, 14vh, 128px), 22vw);
    height: min(clamp(88px, 14vh, 128px), 22vw);
    object-fit: contain;
    animation: npnPlanetSpin 14s linear infinite;
    filter: drop-shadow(0 8px 30px rgba(59, 130, 246, 0.55));
}
@keyframes npnPlanetSpin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}
.npn-title {
    margin: 0 0 6px;
    font-size: 1.9rem;
    font-weight: 800;
    color: var(--accent-light);
    text-shadow: 0 0 18px rgba(59, 130, 246, 0.8);
}
.npn-subtitle {
    margin: 0 0 4px;
    font-size: 1.15rem;
    color: var(--text);
}
.npn-planet-name {
    margin: 2px 0 4px;
    font-size: 2.1rem;
    font-weight: 800;
    color: var(--primary-light);
}
.npn-distance {
    font-size: 1rem;
    color: var(--text-dark, #94a3b8);
    margin-bottom: 18px;
}
.npn-launch-btn {
    padding: 14px 34px;
    font-size: 1.2rem;
    font-weight: bold;
    color: white;
    background: linear-gradient(135deg, #ef4444, #dc2626);
    border: none;
    border-radius: 30px;
    cursor: pointer;
    box-shadow: 0 4px 20px rgba(255, 68, 68, 0.5);
    transition: all 0.2s ease;
}
.npn-launch-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 28px rgba(255, 68, 68, 0.7);
}
.npn-close-btn {
    position: absolute;
    top: 10px;
    right: 12px;
    width: 36px;
    height: 36px;
    border: 1px solid var(--border-light);
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.35);
    color: var(--text);
    font-size: 1.3rem;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s, transform 0.2s;
}
.npn-close-btn:hover {
    background: rgba(0, 0, 0, 0.6);
    transform: scale(1.08);
}
@media (max-width: 480px) and (pointer: coarse) {
    .npn-title { font-size: 1.5rem; }
    .npn-subtitle { font-size: 1rem; }
    .npn-planet-name { font-size: 1.7rem; }
    .npn-planet-img img { width: min(calc(86px * var(--mscale, 1)), 24vw); height: min(calc(86px * var(--mscale, 1)), 24vw); }
    .npn-launch-btn { padding: calc(12px * var(--mscale, 1)) calc(26px * var(--mscale, 1)); font-size: 1.05rem; }
}

/* ============================================ */
/* TUTORIEL DEBUT DE PARTIE */
/* ============================================ */
/* Ecran d'accueil plein ecran (premiere visite) : les 5 etapes du jeu en
   flux horizontal de gauche a droite, image + grand titre + une phrase. */
.intro-overlay {
    position: fixed;
    inset: 0;
    z-index: 14200;
    display: none;
    align-items: center;
    justify-content: center;
    background: radial-gradient(ellipse at 50% 30%, #1a2a5e 0%, #0b1030 55%, #02030f 100%);
    padding: 16px;
}
.intro-overlay.active { display: flex; }
.intro-panel {
    width: min(96vw, 1100px);
    max-height: 94vh;
    overflow-y: auto;
    background: linear-gradient(160deg, var(--bg-panel), var(--secondary-light));
    border: 2px solid #a78bfa;
    border-radius: 20px;
    padding: clamp(18px, 3.5vw, 32px);
    box-shadow: 0 0 60px rgba(167, 139, 250, 0.4), 0 12px 40px rgba(0, 0, 0, 0.6);
    text-align: center;
}
.intro-welcome {
    font-size: clamp(0.85rem, 2vw, 1.1rem);
    font-weight: 600;
    letter-spacing: 3px;
    text-transform: uppercase;
    color: var(--blue-soft);
    margin: 0 0 6px;
    text-shadow: 0 1px 4px rgba(0, 0, 0, 0.8);
}
.intro-logo {
    width: min(70vw, 420px);
    margin: 6px auto 4px;
    display: block;
    filter: drop-shadow(0 0 24px rgba(255, 215, 0, 0.35));
}
.intro-title {
    font-size: clamp(1.5rem, 4vw, 2.4rem);
    font-weight: 900;
    letter-spacing: 2px;
    color: var(--accent-light);
    text-shadow: 0 0 20px rgba(255, 215, 0, 0.5), 0 2px 6px rgba(0, 0, 0, 0.8);
    margin: 0 0 22px;
}
/* Titre remplace par le logotype : garde le h1 pour l'accessibilite/SEO
   mais il sort du flux visuel. */
.intro-title-sr {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    margin: -1px;
}
.intro-steps {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    justify-content: center;
    gap: clamp(4px, 1vw, 14px);
    margin-bottom: 24px;
}
.intro-step {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    background: rgba(0, 0, 0, 0.3);
    border: 1px solid rgba(148, 163, 184, 0.25);
    border-radius: 14px;
    padding: 14px 10px;
}
.intro-step-img {
    width: clamp(64px, 9vw, 110px);
    height: clamp(64px, 9vw, 110px);
    object-fit: contain;
    filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.5));
}
.intro-step-title {
    font-weight: 900;
    font-size: clamp(0.95rem, 1.6vw, 1.25rem);
    color: var(--accent-light);
    text-shadow: 0 1px 4px rgba(0, 0, 0, 0.8);
}
.intro-step-text {
    font-size: clamp(0.72rem, 1vw, 0.88rem);
    color: #cbd5e1;
    line-height: 1.35;
}
.intro-arrow {
    align-self: center;
    flex: 0 0 auto;
    font-size: clamp(1.1rem, 2vw, 1.8rem);
    color: #a78bfa;
    text-shadow: 0 0 10px rgba(167, 139, 250, 0.7);
    animation: introArrowPulse 1.6s ease-in-out infinite;
}
@keyframes introArrowPulse {
    0%, 100% { opacity: 0.55; transform: translateX(0); }
    50% { opacity: 1; transform: translateX(4px); }
}
.intro-btn {
    background: linear-gradient(160deg, var(--accent-light), var(--accent));
    color: #1a1200;
    border: none;
    border-radius: 12px;
    padding: 12px 34px;
    font-size: 1.1rem;
    font-weight: 900;
    cursor: pointer;
    box-shadow: 0 0 24px rgba(255, 215, 0, 0.45);
    transition: transform 0.15s, box-shadow 0.15s;
}
.intro-btn:hover { transform: scale(1.05); box-shadow: 0 0 32px rgba(255, 215, 0, 0.65); }
/* Petit ecran : les etapes s'empilent en colonne avec fleches vers le bas */
@media (max-width: 760px) {
    .intro-steps { flex-direction: column; }
    .intro-arrow { transform: rotate(90deg); animation: none; }
}

.tutorial-coach {
    position: fixed;
    left: 50%;
    bottom: 18px;
    transform: translateX(-50%) translateY(20px);
    display: none;
    z-index: 14000;
    width: min(92vw, 420px);
    background: linear-gradient(160deg, var(--bg-panel), var(--secondary-light));
    border: 2px solid #a78bfa;
    border-radius: 16px;
    padding: 14px 40px 14px 16px;
    box-shadow: 0 0 40px rgba(167, 139, 250, 0.35), 0 12px 30px rgba(0, 0, 0, 0.55);
    transition: opacity 0.3s, transform 0.3s;
    opacity: 0;
}
.tutorial-coach.active {
    display: block;
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}
.tutorial-coach-head {
    display: flex;
    align-items: center;
    gap: 10px;
}
.tutorial-coach-visual {
    width: 42px;
    height: 42px;
    object-fit: contain;
    flex: 0 0 auto;
    filter: drop-shadow(0 4px 12px rgba(167, 139, 250, 0.45));
    animation: tutorialFloat 3.2s ease-in-out infinite;
}
.tutorial-coach-head-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.tutorial-coach-step {
    font-size: 0.7rem;
    font-weight: 700;
    color: #c4b5fd;
}
.tutorial-coach-title {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 800;
    color: var(--accent-light);
}
.tutorial-coach-text {
    margin: 8px 0 0;
    font-size: 0.85rem;
    color: var(--text);
    line-height: 1.35;
}
.tutorial-close-btn {
    position: absolute;
    top: 10px;
    right: 12px;
    width: 34px;
    height: 34px;
    border: 1px solid var(--border-light);
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.35);
    color: var(--text);
    font-size: 1.2rem;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s, transform 0.2s;
}
.tutorial-close-btn:hover {
    background: rgba(0, 0, 0, 0.6);
    transform: scale(1.08);
}
@keyframes tutorialFloat {    0%, 100% { transform: translateY(0); }    50% { transform: translateY(-10px); }}

/* Popups / bulles / coach : garanties anti-debordement sur petits ecrans */
@media (max-width: 640px) {
    .stat-tile-info { min-width: 0; width: calc(100vw - 16px); }
}
@media (max-width: 480px) and (pointer: coarse) {
    .tutorial-coach { width: calc(100vw - 20px); bottom: calc(10px + var(--mobile-nav-height, 0px)); max-height: calc(100dvh - 24px - var(--mobile-nav-height, 0px)); overflow-y: auto; }
    .tutorial-coach-title { font-size: 0.95rem; }
    .tutorial-coach-text { font-size: 0.8rem; }
    .tutorial-coach-visual { width: calc(34px * var(--mscale, 1)); height: calc(34px * var(--mscale, 1)); }
}
/* CHOIX DE LA LANGUE (premiere visite) */
.lang-picker-overlay {
    position: fixed;
    inset: 0;
    background: rgba(2, 6, 23, 0.85);
    backdrop-filter: blur(6px);
    display: none;
    align-items: center;
    justify-content: center;
    z-index: 14500;
}

.lang-picker-overlay.active {
    display: flex;
}

.lang-picker-box {
    background: var(--bg-panel, #1e293b);
    border: 1px solid var(--border-light, rgba(148, 163, 184, 0.25));
    border-radius: 1.375rem;
    padding: 2.125rem 1.875rem 1.875rem;
    width: min(88vw, 25rem);
    max-height: calc(100dvh - 2.5rem);
    overflow-y: auto;
    text-align: center;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.55);
    animation: tutorialPopIn 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.lang-picker-rocket img {
    width: 72px;
    height: auto;
    display: block;
    margin: 0 auto;
}

.lang-picker-rocket {
    font-size: 2.6rem;
    margin-bottom: 10px;
    animation: tutorialFloat 2.2s ease-in-out infinite;
}

.lang-picker-title {
    margin: 0 0 1.375rem;
    font-size: 1.4rem;
    color: var(--text-dark, #f1f5f9);
}

.lang-picker-buttons {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.lang-picker-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.625rem;
    padding: 0.875rem 1.125rem;
    font-size: 1.05rem;
    font-weight: 600;
    font-family: inherit;
    color: var(--text-dark, #f1f5f9);
    background: var(--bg-main, #0f172a);
    border: 1px solid var(--border-light, rgba(148, 163, 184, 0.25));
    border-radius: 14px;
    cursor: pointer;
    transition: transform 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}

.lang-picker-btn:hover {
    transform: translateY(-2px);
    border-color: var(--accent-light, #60a5fa);
    background: rgba(96, 165, 250, 0.12);
}

.lang-flag {
    display: inline-flex;
    line-height: 1;
}
.lang-picker-flag {
    display: inline-flex;
    line-height: 1;
}
.flag-svg {
    display: block;
    width: 1.5em;
    height: 1em;
    border-radius: 2px;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.25);
}
.lang-picker-flag .flag-svg {
    width: 1.5em;
    height: 1em;
    border-radius: 3px;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.25);
}

/* Panneau gauche pendant le tuto (avant l'étape Progression Spatiale) : le PANNEAU reste (fond, bordure -- pas de disparition brutale), seuls les éléments pas encore débloqués se fondent. La minimap et les mini-jeux restent visibles : les contrats se débloquent indépendamment du tuto. */
.left-panel.tutorial-muted .left-panel-scroll > *:not(.mini-games-container) {
    opacity: 0.15;
    filter: blur(3px);
    pointer-events: none;
    transition: opacity 0.8s ease, filter 0.8s ease;
}
.left-panel.tutorial-muted .mini-games-container,
.left-panel.tutorial-muted .mini-space-map {
    opacity: 1;
    filter: none;
    pointer-events: auto;
}

/* ===== Classement des Pilotes (record de vitesse km/s) ===== */

/* Bouton top-bar large "🏆 Classement" */
.control-button-wide {
    width: auto;
    min-width: 118px;
    padding: 0 14px;
    gap: 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    white-space: nowrap;
}

@media (max-width: 900px) {
    .control-button-wide { min-width: 0; padding: 0 10px; }
    .control-button-wide .control-button-label { display: none; }
}

/* Contenu modale : TOUS les elements occupent toute la largeur */
.leaderboard-content .modal-body {
    width: 100%;
    box-sizing: border-box;
}

.leaderboard-self {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 10px 12px;
    margin-bottom: 10px;
    background: linear-gradient(135deg, rgba(59, 130, 246, 0.18), rgba(59, 130, 246, 0.06));
    border: 1px solid rgba(59, 130, 246, 0.45);
    border-radius: 10px;
    box-sizing: border-box;
}

.leaderboard-self-name {
    color: #e2e8f0;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.leaderboard-self-speed {
    color: var(--accent, #3b82f6);
    font-weight: 700;
    white-space: nowrap;
}

.leaderboard-self-none {
    color: #64748b;
    font-size: 0.9rem;
}

.leaderboard-refresh-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    margin-bottom: 8px;
}

.leaderboard-subtitle {
    color: #64748b;
    font-size: 0.95rem;
}

.leaderboard-refresh-btn {
    border: 1px solid rgba(100, 116, 139, 0.4);
    background: transparent;
    color: #94a3b8;
    font-size: 1rem;
    padding: 4px 8px;
    border-radius: 8px;
    cursor: pointer;
    transition: all 0.2s;
    line-height: 1;
}

.leaderboard-refresh-btn:hover {
    border-color: var(--accent, #3b82f6);
    color: var(--accent, #3b82f6);
    transform: rotate(90deg);
}

.leaderboard-list {
    width: 100%;
    max-height: 48vh;
    overflow-y: auto;
    border: 1px solid rgba(100, 116, 139, 0.25);
    border-radius: 10px;
    padding: 4px 8px;
    box-sizing: border-box;
}

.leaderboard-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 6px;
    border-bottom: 1px solid rgba(100, 116, 139, 0.15);
    font-size: 1rem;
}

.leaderboard-row:last-child {
    border-bottom: none;
}

.leaderboard-row.me {
    background: rgba(59, 130, 246, 0.12);
    border-radius: 8px;
    outline: 1px solid rgba(59, 130, 246, 0.35);
}

.leaderboard-rank {
    width: 2.4em;
    text-align: center;
    color: #94a3b8;
    font-weight: 600;
    flex: 0 0 auto;
}

.leaderboard-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: #e2e8f0;
}

.leaderboard-speed {
    flex: 0 0 auto;
    color: var(--accent, #3b82f6);
    font-weight: 600;
}

.leaderboard-empty {
    text-align: center;
    color: #64748b;
    padding: 28px 12px;
    font-size: 0.95rem;
}

.leaderboard-footnote {
    margin-top: 10px;
    color: #64748b;
    font-size: 0.8rem;
    text-align: center;
}

/* ===== Modale "nom d'entreprise requis" (vieilles parties) ===== */
.company-required-modal .modal-body {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.company-required-text {
    color: #cbd5e1;
    font-size: 0.95rem;
    margin: 0;
    line-height: 1.5;
}

#company-required-input {
    width: 100%;
    box-sizing: border-box;
    padding: 10px 14px;
    border: 2px solid rgba(100, 116, 139, 0.5);
    border-radius: 10px;
    background: rgba(2, 6, 23, 0.6);
    color: #e2e8f0;
    font-size: 1rem;
    outline: none;
}

#company-required-input:focus {
    border-color: var(--accent, #3b82f6);
}

.company-required-btn {
    align-self: stretch;
    text-align: center;
}

/* Modale classement : fenetre centree (comme new-building), elements
   pleine largeur -- le panneau 50% laissait de l'espace mort a droite. */
#leaderboard-modal.modal {
    width: 92%;
    max-width: 540px;
    z-index: 1100;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    height: auto;
    max-height: 86dvh;
}
#leaderboard-modal .modal-content { width: 100%; box-sizing: border-box; }
#leaderboard-modal .modal-body { width: 100%; box-sizing: border-box; }

/* Modale "nom d'entreprise requis" : fenetre centree, non fermable */
#company-required-modal.modal {
    width: 92%;
    max-width: 460px;
    z-index: 14600;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    height: auto;
    max-height: 80dvh;
}
#company-required-modal .modal-content { width: 100%; box-sizing: border-box; }


/* ===== Pulse tuto sur la barre de navigation mobile ===== */
/* Quand une lecon concerne le panneau Progression Spatiale (gauche) ou
   Batiments (droite), l'onglet correspondant pulse pour guider le joueur. */
@keyframes navTargetPulse {
    0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(250, 204, 21, 0.0); }
    50% { transform: scale(1.08); box-shadow: 0 0 18px 4px rgba(250, 204, 21, 0.55); }
}
.mobile-nav button.nav-pulse {
    animation: navTargetPulse 1.1s ease-in-out infinite;
    border-radius: 10px;
    z-index: 1360;
}
@media (prefers-reduced-motion: reduce) {
    .mobile-nav button.nav-pulse { animation: none; outline: 3px solid rgba(250, 204, 21, 0.8); }
}

/* ===== Modale classement : responsive mobile ===== */
@media (max-width: 1024px) and (pointer: coarse) {
    /* !important : la modale doit echapper aux regles generiques .modal
       (width 50%, top sous la barre, hauteur pleine) qui la cassaient. */
    #leaderboard-modal.modal {
        position: fixed !important;
        top: 50% !important;
        left: 50% !important;
        transform: translate(-50%, -50%) !important;
        width: calc(100vw - 16px) !important;
        max-width: none !important;
        height: auto !important;
        max-height: calc(100dvh - 24px) !important;
        z-index: 13000 !important;
    }
    #leaderboard-modal .modal-body {
        width: 100% !important;
        max-width: 100% !important;
        padding: 12px !important;
    }
    #leaderboard-modal .modal-content { width: 100% !important; max-width: 100% !important; }
    .leaderboard-list { max-height: 42dvh; }
    .leaderboard-row { padding: 9px 4px; font-size: 0.95rem; gap: 6px; }
    .leaderboard-self { flex-wrap: wrap; font-size: 0.95rem; }
    .leaderboard-subtitle { font-size: 0.85rem; }
    .leaderboard-refresh-btn { padding: 6px 10px; }
}
/* Modale nom d'entreprise : responsive mobile robuste */
@media (max-width: 1024px) and (pointer: coarse) {
    #company-required-modal.modal {
        position: fixed !important;
        top: 50% !important;
        left: 50% !important;
        transform: translate(-50%, -50%) !important;
        width: calc(100vw - 24px) !important;
        max-width: 460px !important;
        height: auto !important;
        max-height: calc(100dvh - 24px) !important;
        z-index: 14600 !important;
    }
    #company-required-modal .modal-body {
        width: 100% !important;
        padding: 14px !important;
        box-sizing: border-box !important;
    }
    #company-required-input { font-size: 1rem; }
}

/* ===== Minimap MODE INFINI : fusée centrale, étoiles, logo ∞ ===== */
.mini-space-map.infinite .space-planet,
.mini-space-map.infinite .space-connection,
.mini-space-map.infinite .planet-name,
.mini-space-map.infinite .planet-distance {
    display: none !important;
}

.mini-space-map.infinite {
    background: radial-gradient(ellipse at center, #0d0d35 0%, #050515 70%, #000 100%);
}

.mini-space-map.infinite .infinite-ship {
    top: 50% !important;
    /* Horizontale, nez vers la droite (le sprite est vertical a l'origine) */
    transform: translate(-50%, -50%) rotate(90deg);
    width: max(min(34cqh, 16cqw), 64px);
    height: auto;
    animation: infiniteShipFloat 3.2s ease-in-out infinite;
}

.mini-space-map.infinite .infinite-ship .spaceship-img {
    width: 100%;
    height: auto;
    filter: drop-shadow(0 0 10px rgba(125, 211, 252, 0.65))
            drop-shadow(0 4px 12px rgba(0, 0, 0, 0.8));
}

@keyframes infiniteShipFloat {
    0%, 100% { transform: translate(-50%, -50%) rotate(90deg) translateY(0); }
    50% { transform: translate(-50%, -50%) rotate(90deg) translateY(-5px); }
}

/* Étoiles scintillantes : points blancs/bleutés, opacité pulsée.
   S'applique AUSSI au rendu classique (fond discret derrière les planètes). */
.mini-space-map .inf-star {
    position: absolute;
    border-radius: 50%;
    background: #e8f0ff;
    box-shadow: 0 0 4px rgba(190, 220, 255, 0.9);
    opacity: 0.25;
    animation: infStarTwinkle 2.4s ease-in-out infinite;
    pointer-events: none;
}

@keyframes infStarTwinkle {
    0%, 100% { opacity: 0.15; transform: scale(0.85); }
    50% { opacity: 0.95; transform: scale(1.15); }
}

@media (prefers-reduced-motion: reduce) {
    .mini-space-map.infinite .inf-star { animation: none; opacity: 0.6; }
    .mini-space-map.infinite .infinite-ship { animation: none; }
}

/* Logo infini doré, calé à droite au centre vertical */
.mini-space-map.infinite .inf-logo {
    position: absolute;
    right: 7%;
    top: 50%;
    transform: translateY(-50%);
    font-family: var(--font-display, inherit);
    font-size: max(min(30cqh, 13cqw), 30px);
    font-weight: 800;
    line-height: 1;
    background: linear-gradient(135deg, #fde68a, #f59e0b, #fbbf24);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    filter: drop-shadow(0 0 8px rgba(251, 191, 36, 0.55));
    pointer-events: none;
}


/* ===== ZONES PUBLICITAIRES (PC uniquement) ===== */
/* MODE INVISIBLE PAR DEFAUT : les slots sont vides tant qu'aucune pub
   n'est servie -- aucune zone, aucun contour, aucune trace. Le slot reste
   dans le DOM (le script du reseau doit pouvoir y ecrire) mais :empty le
   masque ; une vraie pub inseree le rend visible automatiquement. */
.ad-slot:empty { display: none; }

/* Spot topbar : centrage absolu, largeur pilotee en JS (fitTopbarAdSlot). */
.ad-slot-topbar {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    max-width: min(960px, calc(100% - 24px));
    overflow: hidden;
    pointer-events: none;
}
.ad-slot-topbar .ad-slot-ins { pointer-events: all; }

/* Mobile : jamais de spot topbar. */
@media (max-width: 1024px) and (pointer: coarse) {
    .ad-slot-topbar { display: none !important; }
}

/* Spot 300x250 au bas de la zone scrollable de la Progression Spatiale. */
.ad-slot-leftpanel {
    flex: 0 0 auto;
    display: flex;
    justify-content: center;
    padding: 10px 0 12px;
}

@media (max-width: 1024px) and (pointer: coarse) {
    .ad-slot-leftpanel { display: none !important; }
}


/* ===== Modale « Rapporter un bug » ===== */
/* Fenetre centree COMPACTE qui suit son contenu : les regles generiques
   .modal (plein panneau : width 50%, hauteur totale, flex:1 sur le
   content) et la media query mobile (!important plein ecran) creaient
   un vide enorme autour du formulaire. Tout est force ici. */
.bug-report-modal.modal {
    position: fixed !important;
    top: 50% !important;
    left: 50% !important;
    transform: translate(-50%, -50%) !important;
    width: min(480px, calc(100vw - 32px)) !important;
    max-width: min(480px, calc(100vw - 32px)) !important;
    height: auto !important;
    max-height: 86dvh !important;
    display: none;
    z-index: 13000 !important;
}
.bug-report-modal.modal.active { display: block !important; }
.bug-report-modal .modal-content {
    width: 100% !important;
    max-width: 100% !important;
    min-height: 0 !important;
    flex: none !important;
    max-height: 86dvh !important;
    overflow-y: auto;
}
.bug-report-modal .modal-body { padding: 16px 18px !important; }

/* ===== Nom de l'entreprise sur le corps de la fusée ===== */
/* Lettres verticales (haut en bas), centrées sur la pièce Corps. La
   taille s'auto-ajuste : clamp sur la hauteur du corps (200px) divisee
   par le nombre de lettres -- un nom court est grand, un nom long
   retrecit, tout reste dans la piece. */
.rocket-name-tag {
    position: absolute;
    left: 50%;
    /* ANCRAGE BAS DU RESERVOIR : le bas du nom se calque sur le bas
       du reservoir (fuel-tank y=537 h=58 -> ~595). Le tag vit dans la
       piece corps (y=337 h=200) : bottom negatif pour descendre
       jusqu'a cette reference ; le nom monte depuis la. */
    top: auto;
    bottom: -58px;
    transform: translateX(-50%);
    writing-mode: vertical-rl;
    text-orientation: upright;
    letter-spacing: 1px;
    font-family: var(--font-display);
    font-weight: 800;
    color: #0d1321;
    text-shadow: 0 0 5px rgba(255, 255, 255, 0.4);
    text-transform: uppercase;
    max-height: none;
    overflow: visible;
    white-space: nowrap;
    pointer-events: none;
    z-index: 4;
    font-size: clamp(12px, 26px, 28px);
    line-height: 1;
}
