/*
 * Squelette du démarrage. Servi tel quel (hors Vite), avant le code du site :
 * index.html l'affiche dès le premier octet, puis BootScreen (src/app) reprend
 * avec les mêmes classes. Il ne dessine que le cadre du site de la page visée ;
 * le squelette de la page dessine ensuite son contenu. Couleurs : les
 * variables du thème (theme.css, chargé juste avant), avec les mêmes mélanges
 * que les tokens d'index.css.
 */
.mx-boot {
  /* Comme previewSurface (lib/site-theme) : blanc sur fond clair, fond à peine éclairci sur fond sombre. */
  --mx-boot-surface: #ffffff;
  --mx-boot-field: color-mix(in srgb, var(--mx-ink, #090933) 6%, var(--mx-bg, #fbfbff));
  --mx-boot-line: color-mix(in srgb, var(--mx-ink, #090933) 14%, var(--mx-bg, #fbfbff));
  position: relative;
  box-sizing: border-box;
  min-height: 100dvh;
  background: var(--mx-bg, #fbfbff);
}

@supports (color: oklch(from red l c h)) {
  .mx-boot {
    --mx-boot-surface: oklch(
      from var(--mx-bg, #fbfbff) max(calc(l + 0.06), clamp(0, calc((l - 0.6) * 1000), 1))
        calc(c * (1 - clamp(0, calc((l - 0.6) * 1000), 1))) h
    );
  }
}

.mx-boot *,
.mx-boot *::before {
  box-sizing: border-box;
}

/*
 * Le cadre du site, selon l'adresse (data-mx-shell, posé par splash.js puis
 * par BootScreen) : barre apprenant, barre latérale apprenant, rail ou barre
 * du back-office. Placés comme les vrais (LearnerLayout, BackOfficeLayout),
 * pour qu'ils les remplacent sans bouger. Le contenu, lui, est dessiné par le
 * squelette de la page.
 */
.mx-shell {
  display: none;
}

.mx-shell-top {
  position: absolute;
  inset: 0 0 auto;
  height: 58px;
  border-bottom: 1px solid var(--mx-boot-line);
  background: var(--mx-boot-surface);
}

.mx-shell-top-inner {
  display: flex;
  height: 100%;
  max-width: 1440px;
  align-items: center;
  gap: 10px;
  margin: 0 auto;
  padding: 0 12px;
}

.mx-shell-links {
  display: none;
  flex: 1;
  justify-content: center;
  gap: 28px;
}

.mx-shell-end {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

.mx-shell-aside {
  position: absolute;
  inset: 0 auto 0 0;
  display: flex;
  width: 224px;
  flex-direction: column;
  gap: 16px;
  border-right: 1px solid var(--mx-boot-line);
  background: var(--mx-boot-surface);
  padding: 12px;
}

.mx-shell-aside-head {
  position: absolute;
  inset: 0 0 auto 224px;
  display: flex;
  height: 74px;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  border-bottom: 1px solid var(--mx-boot-line);
  background: var(--mx-boot-surface);
  padding: 0 40px;
}

.mx-shell-rail {
  position: absolute;
  inset: 0 auto 0 0;
  width: 76px;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  border-right: 1px solid var(--mx-boot-line);
  background: var(--mx-boot-surface);
  padding: 16px 0;
}

[data-mx-shell='admin-pinned'] .mx-shell-rail {
  width: 264px;
  align-items: stretch;
  padding: 16px;
}

.mx-shell-rail-gap {
  height: 10px;
}

.mx-shell-rail-end {
  margin-top: auto;
}

.mx-boot .mx-shell-label {
  display: none;
}

[data-mx-shell='admin-pinned'] .mx-boot .mx-shell-label,
.mx-boot[data-mx-shell='admin-pinned'] .mx-shell-label {
  display: block;
}

/* Une entrée du rail : une icône de 22 px dans sa zone de 44 px, comme les vraies. */
.mx-shell-icon {
  display: flex;
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
}

.mx-shell-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.mx-shell-admin-bar {
  position: absolute;
  inset: 0 0 auto;
  min-height: 56px;
  align-items: center;
  gap: 8px;
  border-bottom: 1px solid var(--mx-boot-line);
  background: var(--mx-boot-surface);
  padding: 0 6px;
}

/* Sur téléphone, la barre latérale apprenant devient la barre du haut, et le rail une barre. */
[data-mx-shell='learner'] .mx-shell-learner,
[data-mx-shell='learner-side'] .mx-shell-learner {
  display: block;
}

[data-mx-shell^='admin'] .mx-shell-admin-bar {
  display: flex;
}

@media (min-width: 48rem) {
  .mx-shell-top {
    height: 74px;
  }

  .mx-shell-top-inner {
    gap: 40px;
    padding: 0 24px;
  }

  [data-mx-shell='learner-side'] .mx-shell-learner,
  [data-mx-shell^='admin'] .mx-shell-admin-bar {
    display: none;
  }

  [data-mx-shell='learner-side'] .mx-shell-side {
    display: block;
  }

  [data-mx-shell^='admin'] .mx-shell-rail {
    display: flex;
  }
}

@media (min-width: 64rem) {
  .mx-shell-top-inner {
    padding: 0 40px;
  }

  .mx-shell-links {
    display: flex;
  }
}

/*
 * Un aplat qui tient la place d'un texte ou d'une image, traversé par un reflet
 * (comme Telegram). Le dégradé est calé sur la fenêtre (background-attachment :
 * fixed) : une seule vague balaie tous les aplats de l'écran à la fois. Sert
 * aussi aux squelettes des pages (HubSkeleton) : couleurs des tokens du site
 * quand ils existent, mélanges du thème avant.
 * --mx-bone-delay recale la vague sur l'horloge de la page : d'un squelette à
 * l'autre, elle continue sans sauter.
 */
.mx-bone {
  --mx-bone-base: color-mix(in srgb, var(--mx-ink, #090933) 8%, var(--mx-bg, #fbfbff));
  --mx-bone-light: color-mix(in srgb, var(--mx-bone-base) 15%, var(--mx-boot-white, #ffffff));
  display: block;
  background: var(--mx-bone-base)
    linear-gradient(100deg, transparent 35%, var(--mx-bone-light) 50%, transparent 65%) no-repeat;
  background-attachment: fixed;
  background-size: 200vw 100%;
  animation: mx-bone-shimmer 1.4s ease-in-out infinite;
  animation-delay: var(--mx-bone-delay, 0s);
}

.mx-boot .mx-bone {
  border-radius: 99px;
}

.mx-boot .mx-bone-square {
  border-radius: 12px;
}

.mx-boot .mx-shell-icon .mx-bone-square {
  border-radius: 6px;
}


/* Écran immédiat d'index.html : un chargement rapide ne le montre jamais. */
.mx-splash {
  opacity: 0;
  animation: mx-boot-in 0.3s ease-out 0.4s forwards;
}

@keyframes mx-boot-in {
  to {
    opacity: 1;
  }
}

@keyframes mx-bone-shimmer {
  from {
    background-position: -130vw 0;
  }

  to {
    background-position: 30vw 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .mx-bone {
    animation: none;
  }
}

/*
 * Squelettes des pages (composant Skeleton) : ils n'apparaissent qu'après
 * 150 ms. Une donnée qui arrive vite (ou déjà en cache) ne fait rien clignoter.
 */
.mx-skeleton {
  animation: mx-skeleton-in 0.25s ease-out 0.15s both;
}

@keyframes mx-skeleton-in {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}
