#loader { display:none; position:fixed; inset:0; z-index:9999; background:#11051d; align-items:center; justify-content:center; }
html.is-loading { overflow:hidden; scroll-behavior:auto !important; }
html.is-loading:not(.is-revealing) body > :not(#loader):not(.loader-dissolve), html.is-loading:not(.is-revealing) body > :not(#loader) * { visibility:hidden !important; }
html.is-loading #loader { display:flex; }
html.is-loading body > :not(#loader), html.is-loading body > :not(#loader) *, html.is-loading body > :not(#loader) *::before, html.is-loading body > :not(#loader) *::after { animation-play-state:paused !important; }
    /* Rail — 960px max, 4 px de haut, flex pour accueillir les pixels */
    .loader__bar {
      display:   flex;
      gap:       1px;
      width:     calc(100% - 32px);
      max-width: 960px;
      height:    8px;
    }

    /* Animation de refroidissement d'un pixel
       6 stops du chaud (orange) au froid (purple)
       box-shadow se résorbe sur les 2 premiers stops */
    @keyframes loader-cool {
      0%   { background: #ffc15b; box-shadow: 0 0 4px 0 #ffc15b; }
      20%  { background: #e48b5e; box-shadow: 0 0 0   0 #ffc15b; }
      40%  { background: #cf7b7b; }
      60%  { background: #ba6c98; }
      80%  { background: #a55cb4; }
      100% { background: #904dd1; box-shadow: none; }
    }

    /* Pixel unitaire 4×4px
       L'animation démarre dès l'insertion dans le DOM.
       L'effet dégradé vient du décalage temporel entre pixels :
       les récents sont encore chauds, les anciens ont déjà refroidi */
    .loader__px {
      width:       8px;
      height:      8px;
      flex-shrink: 0;
      animation:   loader-cool .4s ease forwards;
    }

html.is-loading.is-revealing body > :not(#loader) { visibility:visible; }
