/* mu-shell.css -- la MISE EN PAGE que le kit n'a pas.

   Docs/ui-kit.html est une galerie de composants : il dit a quoi ressemble un
   bouton, pas comment une application s'organise a l'ecran. Tout ce qui tient
   de la coquille -- barre de titre, tiroir retractable, colonnes separees par
   une poignee, points de rupture -- vit donc ici, et NON dans mu-ui.css qui
   est une copie verbatim du kit (voir son en-tete).

   Regle de partage : mu-ui.css ne se modifie jamais a la main, mu-shell.css se
   modifie librement. C'est ce qui permet de recopier le kit sans rien perdre.

   Les quatre produits (A player, B catalogue, C-1 outil, C-2 rapport) prennent
   ici leur squelette et ne redefinissent que ce qui leur est propre.

   POINTS DE RUPTURE -- une seule serie, partagee, reprise dans MuUI.BP (mu-ui.js)
   parce qu'une media query ne sait pas lire une variable CSS :
     < 720 px   telephone  -- une seule chose a l'ecran a la fois
     720-1179   tablette   -- scene fixe en haut, contenu dessous, tiroir flottant
     >= 1180    grand      -- les colonnes cote a cote
*/

/* ═══════════════════════════════════════════════════════════════════
   COQUILLE -- trois zones : titre, corps, pied optionnel
   ═══════════════════════════════════════════════════════════════════ */
/* Flex et NON grille a rangees fixes : une page ajoute des bandeaux a la volee
   (portee des donnees, avertissement de session), et une grille en `auto 1fr
   auto` attribue alors son 1fr au mauvais enfant -- vu a l'ecran le 2026-09-24,
   l'en-tete devenait haut et le corps plat. Avec flex, seul `.shell__body`
   porte `flex:1` : peu importe combien de bandeaux s'ajoutent. */
.shell {
  display: flex; flex-direction: column;
  height: 100dvh;            /* dvh : la barre d'URL mobile ne coupe plus le bas */
  overflow: hidden;          /* le defilement appartient aux zones, pas a la page */
}
.shell__body {
  flex: 1; min-height: 0;    /* min-height:0 -- sans lui, un enfant defilant ne
                                retrecit jamais sous sa hauteur de contenu */
  display: flex;
  position: relative;        /* repere du tiroir flottant et de son voile */
}

/* Barre de titre : identite a gauche, actions a droite. */
.shell__bar {
  display: flex; align-items: center; gap: var(--s3);
  height: 52px; padding: 0 var(--s4);
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
}
.shell__bar .spacer { flex: 1; }
.shell__brand { display: flex; align-items: center; gap: var(--s2);
                font-weight: 700; font-size: var(--fs-lg); white-space: nowrap; }
.shell__brand .dot { width: 11px; height: 11px; border-radius: var(--r-pill);
                     background: var(--accent); flex: none; }
.shell__title { font-size: var(--fs-md); color: var(--ink-2);
                overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ═══════════════════════════════════════════════════════════════════
   TIROIR -- le panneau de navigation retractable, a gauche
   ═══════════════════════════════════════════════════════════════════ */
/* Geste unique aux quatre produits (Docs/interactions.md) : un bouton replie le
   tiroir, une languette le rappelle. L'etat est memorise PAR PAGE (mu-ui.js),
   jamais partage entre produits -- replier la nav du catalogue ne doit pas
   replier celle du rapport. */
.drawer {
  flex: none; width: var(--drawer-w, 264px);
  display: flex; flex-direction: column; min-height: 0;
  background: var(--bg-surface); border-right: 1px solid var(--border);
  transition: width var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.drawer__head {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s3) var(--s3) var(--s3) var(--s4); flex: none;
  border-bottom: 1px solid var(--border-soft);
}
.drawer__head h2 { font-size: var(--fs-md); font-weight: 600; flex: 1;
                   overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drawer__body { flex: 1; min-height: 0; overflow: auto; padding: var(--s3); }
.drawer.is-collapsed { width: 0; border-right-color: transparent; overflow: hidden; }

/* ═══════════════════════════════════════════════════════════════════
   RAIL DE BORD -- une colonne de boutons au bord gauche
   ═══════════════════════════════════════════════════════════════════ */
/* Tout ce qui se replie (la barre du haut, le tiroir, une scene epinglee)
   laisse ici son bouton de retour, de haut en bas dans l'ordre ou les zones se
   rencontrent a l'ecran. Un seul endroit ou regarder pour retrouver ce qu'on a
   range -- plutot qu'un bouton flottant par zone, chacun dans son coin.
   La page reserve la gouttiere (padding-left) : le rail ne mord jamais sur le
   contenu, et rien ne se decale quand un bouton apparait. */
.edge-rail {
  position: absolute; left: var(--s2); top: var(--s3); z-index: 25;
  display: flex; flex-direction: column; gap: var(--s2);
}
.edge-rail > button {
  width: 26px; height: 26px; flex: none; padding: 0;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); border-radius: 7px;
  background: var(--bg-raised); color: var(--ink-2);
  font-size: 13px; line-height: 1; cursor: pointer;
  box-shadow: var(--shadow-sm);
}
.edge-rail > button:hover { color: var(--ink); background: var(--bg-hover); }
.edge-rail > button[aria-pressed="true"] { color: var(--primary-hi);
                                           border-color: var(--primary); }

/* Le bouton du tiroir ne se montre QUE tiroir replie -- ouvert, le tiroir porte
   deja son propre bouton de repli. Les autres boutons du rail suivent la meme
   regle chez la page qui les declare.
   POSITION STATIQUE, voulue : ce bouton etait une languette absolue collee au
   bord avant le 2026-09-24. La languette a disparu avec le rail, mais sa regle
   de position etait restee et sortait le bouton du flux -- il se superposait
   exactement au bouton voisin. Corrige a la racine plutot que neutralise page
   par page. */
/* Ces deux regles ciblent `.edge-rail > .drawer-reveal` et non `.drawer-reveal`
   seul : la regle d'apparence ci-dessus (`.edge-rail > button`, specificite
   0-1-1) battait sinon la regle de masquage (0-1-0), et le bouton restait
   visible tiroir ouvert. Les autres boutons du rail y echappaient par hasard --
   ils sont cibles par identifiant. Mesure du 2026-09-24, pas une precaution. */
.edge-rail > .drawer-reveal { display: none; }
.shell__body.drawer-collapsed .edge-rail > .drawer-reveal { display: flex; }

/* Telephone et tablette : le tiroir passe AU-DESSUS du contenu au lieu de le
   pousser -- en dessous de 1180 px, trois colonnes cote a cote ne tiennent pas. */
@media (max-width: 1179px) {
  .drawer {
    position: absolute; left: 0; top: 0; bottom: 0; z-index: 40;
    box-shadow: var(--shadow-lg);
  }
  .drawer.is-collapsed { transform: translateX(-100%); width: var(--drawer-w, 264px); }
  .drawer-scrim { position: absolute; inset: 0; z-index: 30;
                  background: rgba(21,30,45,.34); }
  .shell__body.drawer-collapsed .drawer-scrim { display: none; }
}
@media (min-width: 1180px) { .drawer-scrim { display: none; } }

/* ═══════════════════════════════════════════════════════════════════
   ZONE PRINCIPALE + SEPARATEURS
   ═══════════════════════════════════════════════════════════════════ */
.main { position: relative; flex: 1; min-width: 0; min-height: 0;
        display: flex; flex-direction: column; background: var(--bg-page); }

/* Colonnes redimensionnables : la grille porte ses tailles dans une variable,
   la poignee la reecrit (MuUI.splitter). Pas de docking deplacable -- decision
   de portee pour C-1, premier jet : des colonnes qu'on redimensionne, pas des
   panneaux qu'on deplace. */
.split { display: grid; min-height: 0; min-width: 0; flex: 1; }
.split--cols { grid-template-columns: var(--split, 1fr 6px 1fr); }
.split--rows { grid-template-rows: var(--split, 1fr 6px 1fr); }
.split > .pane { min-width: 0; min-height: 0; overflow: hidden; }
/* Une grille imbriquee ne doit pas couper l'ombre de ses panneaux enfants.
   Les panneaux feuilles gardent leur overflow hidden pour leur contenu. */
.split > .pane.split { overflow: visible; }
/* Le `:not(.split)` n'est pas une precaution : un panneau qui est LUI-MEME un
   split (trois colonnes imbriquees, C-1) recevait `display:flex` par cette
   regle, plus specifique que `.split { display:grid }` -- sa grille interieure
   disparaissait et ses enfants s'ecrasaient a zero. Mesure du 2026-09-24, au
   premier usage imbrique. */
.split > .pane:not(.split) { display: flex; flex-direction: column; }

/* Poignee INVISIBLE au repos (2026-09-24) : ce sont les cartes qui se
   detachent, par leur ombre et l'espace entre elles -- un rail gris de plus
   entre chaque panneau alourdissait l'ecran pour ne rien dire. Elle se montre
   au survol, la ou la main va. */
.handle { position: relative; background: transparent; }
.handle::before {
  content: ''; position: absolute; inset: 2px; border-radius: var(--r-pill);
  background: transparent; transition: background var(--dur) var(--ease);
}
.handle::after { content: ''; position: absolute; inset: -3px; z-index: 10; }  /* cible
                 de pointage elargie : 6 px visibles, 12 px attrapables */
.split--cols > .handle { cursor: col-resize; }
.split--rows > .handle { cursor: row-resize; }
.handle:hover::before, .handle.is-dragging::before { background: var(--primary); }

/* ═══════════════════════════════════════════════════════════════════
   PANNEAU -- la carte de travail, commune aux quatre produits
   ═══════════════════════════════════════════════════════════════════ */
/* Parti pris du 2026-09-24 : pas de liseré, un grand rayon, une ombre douce et
   de l'air. Une bordure de 1 px autour de chaque panneau, multipliee par six
   panneaux et trois separateurs, fabriquait une grille de traits ou l'oeil ne
   trouvait plus le contenu. La profondeur dit mieux la separation que le trait.
   En theme sombre, l'ombre porte moins : le fond de surface, plus clair que la
   page, suffit a detacher la carte (jetons du kit). */
.panel {
  display: flex; flex-direction: column; overflow: hidden;
  min-width: 0; min-height: 0;
  background: var(--bg-surface); border: none;
  border-radius: 5px; box-shadow: var(--shadow-sm);
}
:root:not([data-theme="dark"]) .panel:not(.panel--bare) {
  box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px;
}
.panel-head {
  flex: none; display: flex; align-items: center; gap: var(--s2);
  padding: 6px var(--s4) 4px;
  background: none; border: none;
}
.panel-title { font-size: var(--fs-md); font-weight: 600; color: var(--ink);
               white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Le numero de l'etape : pastille douce facon tuile d'icone, plutot qu'un rond
   plein qui criait plus fort que le titre. */
.panel-badge {
  width: 22px; height: 22px; flex: none; border-radius: 7px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--primary-soft); color: var(--primary-hi);
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
}
.panel-head .spacer { flex: 1; }
.panel-hint { font-size: var(--fs-xs); color: var(--ink-muted); white-space: nowrap; }
.panel-act {
  border: none; background: none; color: var(--ink-muted); cursor: pointer;
  font: inherit; font-size: 13px; line-height: 1; flex: none;
  width: 26px; height: 26px; border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
}
.panel-act:hover { background: var(--bg-hover); color: var(--ink); }
.panel-body { flex: 1; min-height: 0; overflow: auto; padding: 0 var(--s3) var(--s3); }
/* Un rendu ou un graphique va d'un bord a l'autre : il porte sa propre marge
   interieure, ou n'en veut aucune. */
/* `display:flex` et non le defaut : un enfant bord-a-bord (un rendu, un
   graphique) se donne `flex:1` pour remplir la carte. Sans cela il retombait a
   hauteur nulle -- vu a l'ecran sur la vue 3D de C-1. */
.panel-body--flush { padding: 0; display: flex; flex-direction: column; }
.panel-body--flush > :first-child { border-radius: 0 0 var(--r-lg) var(--r-lg); }
body.is-resizing { user-select: none; }
body.is-resizing iframe, body.is-resizing canvas { pointer-events: none; }  /* sinon
                 le canvas WebGL avale les evenements de pointeur en cours de glisse */

/* ═══════════════════════════════════════════════════════════════════
   SCENE 3D -- le cadre commun aux quatre produits
   ═══════════════════════════════════════════════════════════════════ */
/* Le canvas est toujours dans un cadre positionne : les surcouches (transport,
   badges, etat de chargement) s'y posent en absolu. mu-player-core.js fixe la
   taille en pixels physiques, jamais le CSS -- voir Docs/apps/player_web.md. */
.scene { position: relative; flex: 1; min-height: 0; background: var(--dark-bg); }
.scene > canvas { display: block; width: 100%; height: 100%; }
.scene__overlay { position: absolute; left: 0; right: 0; bottom: 0; z-index: 10; }
.scene__badge {
  position: absolute; left: var(--s3); top: var(--s3); z-index: 10;
  padding: 4px 10px; border-radius: var(--r-pill);
  background: rgba(21,30,45,.62); color: #fff; font-size: var(--fs-xs);
  backdrop-filter: blur(6px);
}
/* Etat vide / en attente : la scene n'est pas encore branchee au coeur. */
.scene__placeholder {
  position: absolute; inset: 0; display: grid; place-content: center; gap: var(--s2);
  text-align: center; color: var(--dark-muted); font-size: var(--fs-sm);
}

/* ═══════════════════════════════════════════════════════════════════
   BASCULE -- telephone : une chose OU l'autre
   ═══════════════════════════════════════════════════════════════════ */
/* C-2 sur telephone : soit la scene, soit le rapport (jamais les deux a la
   fois, l'ecran ne le permet pas). Le meme jeu sert a C-1. */
.segmented {
  display: none; gap: 2px; padding: 2px; flex: none;
  background: var(--bg-sunken); border-radius: var(--r-pill);
}
.segmented button {
  flex: 1; border: none; background: transparent; color: var(--ink-2);
  font: inherit; font-size: var(--fs-sm); padding: 6px 14px;
  border-radius: var(--r-pill); cursor: pointer;
}
.segmented button[aria-pressed="true"] { background: var(--bg-raised); color: var(--ink);
                                         box-shadow: var(--shadow-sm); font-weight: 600; }
@media (max-width: 719px) { .segmented { display: flex; } }

/* ═══════════════════════════════════════════════════════════════════
   POPOVER -- connexion, vitesse, reglages
   ═══════════════════════════════════════════════════════════════════ */
.popover {
  position: absolute; z-index: 60; min-width: 220px;
  background: var(--bg-raised); border: 1px solid var(--border);
  border-radius: var(--r); box-shadow: var(--shadow-lg);
  padding: var(--s3);
}
.popover[hidden] { display: none; }
.popover__title { font-size: var(--fs-sm); font-weight: 600; color: var(--ink-2);
                  margin-bottom: var(--s2); }
.popover .field + .field { margin-top: var(--s2); }

/* ═══════════════════════════════════════════════════════════════════
   NOTIFICATIONS -- la pile de messages, en bas a droite
   ═══════════════════════════════════════════════════════════════════ */
.toasts { position: fixed; right: var(--s4); bottom: var(--s4); z-index: 80;
          display: flex; flex-direction: column; gap: var(--s2); align-items: flex-end; }
.toast {
  display: flex; align-items: center; gap: var(--s2);
  max-width: min(420px, calc(100vw - 2 * var(--s4)));
  padding: var(--s2) var(--s4); border-radius: var(--r-pill);
  background: var(--bg-raised); border: 1px solid var(--border);
  box-shadow: var(--shadow); font-size: var(--fs-sm);
  animation: toast-in var(--dur) var(--ease);
}
.toast--ok   { border-left: 3px solid var(--primary); }
.toast--err  { border-left: 3px solid var(--danger); }
.toast--warn { border-left: 3px solid var(--warn); }
.toast.is-leaving { opacity: 0; transition: opacity var(--dur) var(--ease); }
@keyframes toast-in { from { opacity: 0; transform: translateY(6px); } }
@media (prefers-reduced-motion: reduce) {
  .toast { animation: none; }
  .drawer { transition: none; }
  .mu-downloads__spin, .mu-downloads__bar.is-indeterminate > span { animation: none; }
}

/* Téléchargements en cours (mu-downloads.js) : sous la pile des messages. */
.mu-downloads { position: fixed; right: var(--s4); bottom: var(--s4); z-index: 79;
  width: min(300px, calc(100vw - 2 * var(--s4))); padding: var(--s3) var(--s4);
  background: var(--bg-raised); border: 1px solid var(--border); border-left: 3px solid var(--info);
  border-radius: var(--r); box-shadow: var(--shadow); font-size: var(--fs-sm);
  animation: toast-in var(--dur) var(--ease); }
.mu-downloads[hidden] { display: none; }
body.has-downloads .toasts { bottom: calc(var(--s4) + var(--mu-downloads-h, 0px) + var(--s2)); }
.mu-downloads__title { font-weight: 600; margin-bottom: var(--s2); }
.mu-downloads__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
.mu-downloads__row { display: grid; grid-template-columns: 1fr auto; align-items: center; column-gap: var(--s3); row-gap: 3px; }
.mu-downloads__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }
.mu-downloads__pct { font-variant-numeric: tabular-nums; color: var(--ink-2); }
.mu-downloads__spin { width: 12px; height: 12px; border: 2px solid var(--border); border-top-color: var(--info);
  border-radius: 50%; animation: mu-spin .8s linear infinite; }
.mu-downloads__bar { grid-column: 1 / -1; height: 3px; border-radius: 2px; background: var(--border-soft); overflow: hidden; }
.mu-downloads__bar > span { display: block; height: 100%; width: 0; background: var(--info); transition: width .15s linear; }
.mu-downloads__bar.is-indeterminate > span { width: 35%; animation: mu-slide 1.1s ease-in-out infinite; }
.mu-downloads__ok { font-variant-numeric: tabular-nums; color: var(--primary-hi); }
.mu-downloads__row.is-done .mu-downloads__name { color: var(--ink-2); }
.mu-downloads__row.is-done .mu-downloads__bar > span { background: var(--primary); }
@keyframes mu-spin { to { transform: rotate(360deg); } }
@keyframes mu-slide { from { transform: translateX(-100%); } to { transform: translateX(290%); } }

/* Remise à zéro locale (Alt+F5, mu-reset.js), commune à toutes les pages. */
.mu-local-dialog { max-width: 460px; padding: 18px 20px; border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--bg-surface); color: var(--ink); box-shadow: var(--shadow-lg); }
.mu-local-dialog::backdrop { background: rgba(12, 20, 30, .55); }
.mu-local-dialog h3 { margin: 0 0 8px; }
.mu-local-dialog p { margin: 0 0 10px; font-size: var(--fs-sm); color: var(--ink-2); }
.mu-local-dialog label { display: flex; align-items: flex-start; gap: 8px; margin: 6px 0; font-size: var(--fs-sm); }
.mu-local-dialog .mu-local-warn { color: var(--danger); }
.mu-local-actions { display: flex; flex-direction: column; gap: 6px; margin-top: 14px; }
.mu-local-actions button { padding: 7px 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg-surface); color: var(--ink); font: inherit; cursor: pointer; text-align: left; }
.mu-local-actions button:hover { background: var(--bg-hover); }
.mu-local-actions .mu-local-danger { border-color: var(--danger); color: var(--danger); }

/* ═══════════════════════════════════════════════════════════════════
   ETATS COMMUNS
   ═══════════════════════════════════════════════════════════════════ */
.empty { padding: var(--s5) var(--s4); text-align: center;
         color: var(--ink-muted); font-size: var(--fs-sm); line-height: 1.6; }
.skeleton { background: linear-gradient(90deg, var(--bg-sunken) 25%,
            var(--bg-hover) 37%, var(--bg-sunken) 63%);
            background-size: 400% 100%; border-radius: var(--r-sm);
            animation: skel 1.4s ease infinite; }
@keyframes skel { from { background-position: 100% 50%; } to { background-position: 0 50%; } }
@media (prefers-reduced-motion: reduce) { .skeleton { animation: none; } }

/* Bandeau de portee : dit franchement quand l'ecran montre de fausses donnees.
   Il DISPARAIT au branchement du coeur -- c'est son seul role. */
.fixture-banner {
  display: flex; align-items: center; gap: var(--s2); flex: none;
  padding: 6px var(--s4); font-size: var(--fs-xs);
  background: var(--warn-soft); color: var(--warn-hi);
  border-bottom: 1px solid var(--border-soft);
}
.fixture-banner__close { margin-left: auto; flex: none; width: 22px; height: 22px;
  border: 0; border-radius: 5px; background: transparent; color: inherit;
  font: inherit; font-size: 18px; line-height: 1; cursor: pointer; }
.fixture-banner__close:hover, .fixture-banner__close:focus-visible {
  background: var(--bg-hover); }

/* Shared navigation button theme. */
.icon-btn {
  width: 26px; height: 26px; flex: none; border-radius: 7px;
  border: 1px solid var(--border); background: var(--bg-surface); color: var(--ink-2);
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  font-size: 13px; line-height: 1; padding: 0;
}
.icon-btn:hover { background: var(--bg-hover); color: var(--ink); }
