/*
 * index-v3.css — Styles de la page d'accès Time-ECOS.
 * Design institutionnel sobre (2026-07-21) : une carte centrale unique,
 * l'organisation active, le compte connecté et une action principale.
 * Le sélecteur multi-organisation reste disponible comme filet de secours.
 */

body#index-page,
body#page-root {
  display: block;
  min-height: 100dvh;
  padding: 0 !important;
  background: var(--bg, #EEF6FB);
}

#page-root .container.center-in-page {
  width: 100%;
  max-width: none;
  min-height: 100dvh;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background: transparent;
  overflow: visible;
}

.index-v3-shell {
  min-height: 100dvh;
  display: grid;
  grid-template-rows: auto 1fr auto;
}

/* ---------- Bandeau de marque (2026-08-14) ----------
   Remplace l'ancienne barre du haut (.index-v3-topbar & co) ET le bloc
   logo/titre qui vivait en tête de la carte (.header, .welcome-title,
   .index-v3-panel-subtitle) : le nom du produit et sa description étaient
   dits DEUX fois dans la page, ils ne le sont plus qu'une.
   La carte, en débord sur le bandeau, ne porte plus que le formulaire —
   c'est ce qui casse la silhouette « logo + titre + formulaire empilés au
   centre d'une carte flottante », héritée telle quelle de la V2.
   Maquette validée : mockups/accueil/accueil-03-bandeau-marque.html */

/* Resserré le 2026-08-20 : le bandeau tenait ~340px de haut et poussait le bas
   de page sous la ligne de flottaison d’un 13 pouces. Écrin, paddings et interlignes
   réduits — silhouette et débord de la carte inchangés. */
.index-v3-hero {
  padding: clamp(10px, 1.6vh, 14px) clamp(20px, 4vw, 54px) clamp(34px, 6vh, 60px);
  background: linear-gradient(135deg, var(--brand, #004777) 0%, #015b7f 55%, var(--accent, #00AFB5) 130%);
  color: #fff;
  text-align: center;
}

.index-v3-hero-top {
  display: flex;
  /* En colonne alignée à droite : la pastille owner de te-gate.js (« Pause »),
     posée après le badge, tombe juste dessous (2026-09-04). */
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
  min-height: 26px;
  margin-bottom: clamp(3px, 1vh, 10px);
}

.index-v3-hero-top .te-gate-ownerbar--ancree { margin: 0; }

.index-v3-hero-title {
  margin: clamp(4px, 1vh, 8px) 0 0;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 4.2vh, 2.4rem);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.03em;
}

.index-v3-hero-subtitle {
  margin: clamp(2px, 0.8vh, 6px) 0 0;
  color: rgba(255, 255, 255, 0.82);
  font-size: clamp(0.82rem, 1.7vh, 0.95rem);
  font-weight: 600;
}

/* L'écrin est désormais posé sur un fond sombre : ses paths (currentColor)
   passent en blanc et l'ombre bleutée devient neutre. Il est aussi plus petit
   qu'au centre d'une carte. `auto` en marge latérale car le parent centre au
   texte, pas en flex comme l'ancien .header. */
.index-v3-hero .ecrin {
  width: clamp(56px, 11vh, 88px);
  height: clamp(56px, 11vh, 88px);
  margin: -14px auto -12px;
  color: #fff;
  filter: drop-shadow(0 10px 18px rgba(0, 20, 35, 0.28));
}

/* État d'erreur sur le bandeau : var(--danger) (#a30000) est illisible sur ce
   fond, on garde donc un rouge clair. Les 3 sélecteurs battent en spécificité
   les 3 règles d'erreur par thème définies plus bas. */
.index-v3-hero .ecrin.ecrin--error,
:root.theme-dark .index-v3-hero .ecrin.ecrin--error,
:root.theme-system .index-v3-hero .ecrin.ecrin--error {
  color: #ffb4b4;
  filter: drop-shadow(0 10px 18px rgba(163, 0, 0, 0.42));
}

@media (max-width: 640px) {
  .index-v3-hero .ecrin {
    width: 84px;
    height: 84px;
    margin-top: -12px;
    margin-bottom: -10px;
  }
}

/* ---------- Carte centrale ---------- */

/* La marge négative fait remonter la carte SUR le bandeau : c'est le débord
   qui lie les deux blocs. Elle est absorbée par le padding bas du bandeau
   (clamp 52→60px), toujours supérieur au débord (clamp 32→44px). */
body#page-root .index-v3-main {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  margin-top: calc(-1 * clamp(22px, 4vh, 44px));
  padding: 0 clamp(16px, 4vw, 54px) clamp(10px, 3vh, 64px);
}

.index-v3-card {
  width: min(720px, 100%);
  margin: 0 auto;
  border-radius: 16px;
  background: var(--surface, #fff);
  border: 1px solid var(--line, #E3ECF2);
  box-shadow: 0 18px 44px rgba(2, 44, 78, 0.09);
}

/* Carte d'accès */
.index-v3-panel {
  padding: clamp(16px, 3.2vh, 32px) clamp(20px, 4vw, 40px);
  box-sizing: border-box;
}

/* Titre d'étape de la carte. Reprend l'id panel-title de l'ancien <h1> : c'est
   scripts/index.js qui écrit son texte selon l'état (« Choisir une
   organisation » ↔ « Accéder à Time-ECOS »), donc le JS n'a pas bougé.
   Aligné à gauche — comme la maquette, et pour s'éloigner du « tout centré »
   de la V2. Le titre de page, lui, est désormais dans le bandeau. */
.index-v3-panel-step {
  margin: 0 0 clamp(10px, 2vh, 18px);
  color: var(--brand, #004777);
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 2.2vw, 1.4rem);
  font-weight: 800;
  line-height: 1.25;
  letter-spacing: -0.02em;
  text-align: left;
}

.form-section {
  display: grid;
  gap: clamp(10px, 1.8vh, 18px);
  width: 100%;
}

#form-content {
  display: grid;
  gap: clamp(10px, 2.2vh, 20px);
}

#form-content.hidden {
  display: none !important;
}

#organisation-field {
  margin: 0;
  display: grid;
  gap: 14px;
}

#organisation-field.hidden {
  display: none !important;
}

/* ---------- État 1 : liste des organisations ---------- */

#org-picker-view {
  display: grid;
  gap: 14px;
}

#org-picker-view.hidden {
  display: none !important;
}

.orgpick-search {
  position: relative;
}

.orgpick-search.hidden {
  display: none !important;
}

.orgpick-search-icon {
  position: absolute;
  left: 13px;
  top: 50%;
  width: 12px;
  height: 12px;
  border: 2px solid color-mix(in srgb, var(--muted, #6b7280) 60%, #fff 40%);
  border-radius: 50%;
  transform: translateY(-62%);
  pointer-events: none;
}

.orgpick-search-icon::after {
  content: "";
  position: absolute;
  left: 10px;
  top: 11px;
  width: 7px;
  height: 2px;
  border-radius: 2px;
  background: color-mix(in srgb, var(--muted, #6b7280) 60%, #fff 40%);
  transform: rotate(45deg);
}

.orgpick-search input {
  width: 100%;
  box-sizing: border-box;
  font-family: inherit;
  font-size: 0.88rem;
  color: var(--text, #04151F);
  padding: 12px 14px 12px 38px;
  border: 1.5px solid var(--line, #E3ECF2);
  border-radius: 12px;
  background: var(--surface, #fff);
  outline: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.orgpick-search input::placeholder {
  color: color-mix(in srgb, var(--muted, #6b7280) 65%, #fff 35%);
}

.orgpick-search input:focus {
  border-color: var(--accent, #00AFB5);
  box-shadow: 0 0 0 3px rgba(0, 175, 181, 0.12);
}

.orgpick-group-label {
  margin: 0 0 -6px;
  color: var(--muted, #6b7280);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.orgpick-group-label.hidden {
  display: none !important;
}

#org-recent-block {
  display: grid;
  gap: 14px;
}

#org-recent-block.hidden {
  display: none !important;
}

/* Deux colonnes dès que la largeur le permet (2026-08-20) : les lignes
   d'organisation sont courtes, une seule colonne gaspillait la moitié de la
   carte et allongeait la page d'autant. `auto-fill` retombe seul sur une
   colonne sous ~500px de large. */
.orgpick-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  align-content: start;
  gap: 8px;
}

/* Le raccourci « Récentes » reste pleine largeur : c'est le chemin rapide. */
#org-recent-list {
  grid-template-columns: 1fr;
}

.orgpick-list.orgpick-scroll {
  max-height: 300px;
  overflow-y: auto;
  padding-right: 4px;
  margin-right: -4px;
}

.orgpick-list::-webkit-scrollbar {
  width: 6px;
}

.orgpick-list::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--line, #E3ECF2) 80%, var(--muted, #6b7280) 20%);
  border-radius: 3px;
}

.orgpick-list::-webkit-scrollbar-track {
  background: transparent;
}

.orgpick-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 0 0 auto;
  padding: 11px 13px;
  border-radius: 12px;
  background: var(--surface, #fff);
  border: 1px solid var(--line, #E3ECF2);
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.orgpick-row:hover,
.orgpick-row:focus-visible {
  border-color: var(--accent, #00AFB5);
  background: rgba(0, 175, 181, 0.03);
  outline: none;
}

.orgpick-avatar {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: color-mix(in srgb, var(--brand, #004777) 8%, var(--surface, #fff) 92%);
}

.orgpick-avatar img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 3px;
  box-sizing: border-box;
}

.orgpick-avatar .orgpick-initials {
  color: #fff;
  font-size: 0.72rem;
  font-weight: 700;
}

.orgpick-avatar.orgpick-avatar--initials {
  background: var(--brand, #004777);
}

.orgpick-info {
  flex: 1;
  min-width: 0;
}

.orgpick-name {
  display: block;
  color: var(--text, #04151F);
  font-size: 0.9rem;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.orgpick-sub {
  display: block;
  margin-top: 1px;
  color: var(--muted, #6b7280);
  font-size: 0.74rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Pastille filière : une teinte par filière, repli sur la couleur de marque. */
.orgpick-filiere {
  --filiere-tint: var(--brand, #004777);
  flex: 0 0 auto;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 700;
  white-space: nowrap;
  background: color-mix(in srgb, var(--filiere-tint) 12%, var(--surface, #fff) 88%);
  color: color-mix(in srgb, var(--filiere-tint) 80%, var(--text, #04151F) 20%);
}

.orgpick-filiere[data-filiere="medecine"],
.orgid-chip--filiere[data-filiere="medecine"] {
  --filiere-tint: #0F766E;
}

.orgpick-filiere[data-filiere="maieutique"],
.orgid-chip--filiere[data-filiere="maieutique"] {
  --filiere-tint: #5B4BB7;
}

.orgpick-filiere[data-filiere="odontologie"],
.orgid-chip--filiere[data-filiere="odontologie"] {
  --filiere-tint: #B4436C;
}

.orgpick-go {
  color: color-mix(in srgb, var(--line, #E3ECF2) 55%, var(--muted, #6b7280) 45%);
  font-size: 0.95rem;
  transition: color 0.15s ease, transform 0.15s ease;
}

.orgpick-row:hover .orgpick-go {
  color: color-mix(in srgb, var(--accent, #00AFB5) 80%, #000 20%);
  transform: translateX(3px);
}

.orgpick-empty {
  grid-column: 1 / -1;
  margin: 0;
  padding: 14px 0;
  color: var(--muted, #6b7280);
  font-size: 0.82rem;
  text-align: center;
}

/* ---------- État 2 : fiche de l'organisation sélectionnée ---------- */

#org-selected-view {
  display: grid;
  gap: 14px;
  padding: 20px 22px;
  border: 1px solid var(--line, #E3ECF2);
  border-radius: 14px;
  background: var(--surface, #fff);
}

#org-selected-view.hidden {
  display: none !important;
}

.orgid-head {
  display: flex;
  align-items: center;
  gap: 18px;
}

.orgid-logo {
  width: 68px;
  height: 68px;
  border-radius: 12px;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: color-mix(in srgb, var(--brand, #004777) 8%, var(--surface, #fff) 92%);
}

.orgid-logo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 5px;
  box-sizing: border-box;
}

.orgid-logo .orgpick-initials {
  color: #fff;
  font-size: 1rem;
  font-weight: 800;
}

.orgid-logo.orgid-logo--initials {
  background: var(--brand, #004777);
}

.orgid-title {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.orgid-name-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}

.orgid-name {
  color: var(--brand, #004777);
  font-size: 1.2rem;
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1.25;
}

/* Ligne d'action séparée, en bas de la fiche : identité en haut, action en bas. */
.orgid-actions {
  padding-top: 12px;
  border-top: 1px solid var(--line, #E3ECF2);
  text-align: right;
}

.orgid-actions:has(.orgid-change.hidden) {
  display: none;
}

.orgid-change {
  font-family: inherit;
  font-size: 0.76rem;
  font-weight: 600;
  color: color-mix(in srgb, var(--accent, #00AFB5) 80%, #000 20%);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  white-space: nowrap;
  transition: color 0.15s ease;
}

.orgid-change:hover {
  color: var(--brand, #004777);
  text-decoration: underline;
}

.orgid-meta {
  flex-basis: 100%;
  margin: -4px 0 0;
  color: var(--muted, #6b7280);
  font-size: 0.78rem;
}

.orgid-meta.hidden {
  display: none !important;
}

.orgid-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
}

.orgid-badges.hidden {
  display: none !important;
}

.orgid-chip {
  font-size: 0.72rem;
  font-weight: 700;
  padding: 5px 11px;
  border-radius: 999px;
  white-space: nowrap;
  background: color-mix(in srgb, var(--brand, #004777) 9%, var(--surface, #fff) 91%);
  color: var(--brand, #004777);
}

.orgid-chip--main {
  background: color-mix(in srgb, var(--accent, #00AFB5) 10%, var(--surface, #fff) 90%);
  color: color-mix(in srgb, var(--accent, #00AFB5) 70%, #000 30%);
}

.orgid-chip--filiere {
  --filiere-tint: var(--brand, #004777);
  background: color-mix(in srgb, var(--filiere-tint) 12%, var(--surface, #fff) 88%);
  color: color-mix(in srgb, var(--filiere-tint) 80%, var(--text, #04151F) 20%);
}

/* ---------- Compte connecté & actions ---------- */

.actions-row {
  display: grid;
  gap: 10px;
  width: 100%;
  margin: 0;
}

.index-v3-panel .actions-row .btn {
  width: 100%;
  min-height: clamp(44px, 6.5vh, 52px);
  border-radius: 11px;
}

/* Wrapper d'infobulle du bouton d'accès (2026-08-22) : il porte l'explication du
   seul état grisé restant (compte connecté sans organisation) et ne doit rien
   changer à la mise en page. Le socle le rend `inline-flex` ; en tant qu'enfant
   de la grille `.actions-row`, il est blockifié, mais on fixe la largeur et on
   autorise le bouton à rétrécir — `.actions-row > *` ne cible plus le bouton
   lui-même depuis qu'il est enveloppé. */
.index-v3-panel .actions-row #btn-access-wrap {
  width: 100%;
  min-width: 0;
}

.index-v3-panel .actions-row #btn-access-wrap > .btn {
  min-width: 0;
}

/* ===== Raccourcis réservés (Admin / Owner) — 2026-08-19 =====
   Rangée secondaire nichée DANS `.actions-row` (et non enfant direct de
   `#form-content`, dont le `gap: 24px` aurait trop éloigné les raccourcis de
   l'action principale). Elle hérite ainsi du `gap: 10px` de la rangée.

   `grid-auto-flow: column` + `grid-auto-columns: 1fr` répartit la largeur entre
   les SEULS boutons présents dans le flux : un owner qui n'a pas encore choisi
   d'organisation ne voit que « Owner » (le bouton Admin est en `display: none`),
   et celui-ci prend toute la largeur sans règle supplémentaire. */
.index-v3-reserved-actions {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 10px;
  width: 100%;
}

.index-v3-reserved-actions.hidden {
  display: none !important;
}

/* Sélecteur volontairement à 4 classes : il doit l'emporter sur
   `.index-v3-panel .actions-row .btn` (52 px) sans dépendre de l'ordre du
   fichier. Les raccourcis sont plus bas que l'action principale : la hiérarchie
   visuelle doit rester lisible d'un coup d'œil. */
.index-v3-panel .actions-row .index-v3-reserved-actions .btn {
  width: 100%;
  min-height: 44px;
  border-radius: 11px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 0.94rem;
}

/* Lucide remplace le <i data-lucide> par un <svg> : les deux sont ciblés pour
   que la taille soit correcte avant comme après le rendu des icônes. */
.index-v3-reserved-actions .btn svg,
.index-v3-reserved-actions .btn i[data-lucide] {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
}

/* Très petit mobile (iPhone SE, 320 px) : deux demi-largeurs ne laissent plus
   la place à « Admin » + son icône sans rogner. On repasse en colonne. */
@media (max-width: 380px) {
  .index-v3-reserved-actions {
    grid-auto-flow: row;
  }
}

/* [2026-09-17, règle N-6 : « ça doit tenir en Mobile S »] Sous 480px, le nom de
   l'organisation n'a plus la place d'une ligne à côté de la pastille de filière et
   de la flèche : « Université de D… » ne permet plus de distinguer deux facultés.
   Le nom revient à la ligne (deux lignes au plus), la pastille passe dessous. */
@media (max-width: 480px) {
  .orgpick-row {
    display: grid;
    grid-template-columns: 38px minmax(0, 1fr) auto;
    grid-template-areas:
      "avatar info go"
      "avatar chip go";
    row-gap: 6px;
  }

  .orgpick-avatar { grid-area: avatar; align-self: center; }
  .orgpick-info { grid-area: info; }
  .orgpick-go { grid-area: go; align-self: center; }

  .orgpick-name {
    white-space: normal;
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }

  .orgpick-filiere {
    grid-area: chip;
    justify-self: start;
  }
}

.index-v3-logout {
  display: flex;
  justify-content: center;
  margin-top: -10px;
}

.index-v3-logout.hidden {
  display: none !important;
}

.auth-info {
  margin: 0;
  padding-top: 22px;
  border-top: 1px solid var(--line, #E3ECF2);
}

.index-v3-account-label {
  margin: 0 0 14px;
  color: var(--muted, #6b7280);
  font-size: 0.82rem;
  font-weight: 650;
}

.index-v3-account-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 14px;
  align-items: center;
}

.index-v3-account-avatar {
  display: grid;
  place-items: center;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  color: var(--brand, #004777);
  background: color-mix(in srgb, var(--brand, #004777) 10%, var(--surface, #fff) 90%);
  font-size: 0.98rem;
  font-weight: 800;
}

.index-v3-account-identity {
  display: grid;
  gap: 2px;
  min-width: 0;
}

#auth-user-name {
  display: block;
  margin: 0;
  color: var(--text, #04151F);
  font-size: 0.96rem;
  font-weight: 750;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

#auth-user-email {
  display: block;
  margin: 0;
  color: var(--muted, #6b7280);
  font-size: 0.82rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.index-v3-account-status {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 10px;
  border: 1px solid var(--line, #E3ECF2);
  border-radius: 999px;
  color: var(--muted, #6b7280);
  background: var(--surface, #fff);
  font-size: 0.75rem;
  font-weight: 650;
  white-space: nowrap;
}

.index-v3-account-status-dot {
  width: 9px;
  height: 9px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--success, #16a34a);
}

.index-v3-text-action {
  min-height: 44px;
  padding: 8px 12px;
  border: 0;
  background: transparent;
  color: var(--brand, #004777);
  font: inherit;
  font-size: 0.88rem;
  font-weight: 650;
  cursor: pointer;
}

.index-v3-text-action:hover {
  text-decoration: underline;
}

.index-v3-text-action:disabled {
  opacity: 0.55;
  cursor: wait;
  text-decoration: none;
}

.index-v3-text-action:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--accent, #00AFB5) 60%, transparent);
  outline-offset: 2px;
  border-radius: 6px;
}

.loading-container {
  min-height: 260px;
  padding: 8px 0 0;
}

.progress-fill {
  background: var(--accent, #00AFB5);
}

/* ---------- Badge d'environnement ---------- */

.environment-badge {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: fit-content;
  margin: 0;
  min-width: 0;
  padding: 7px 8px;
  border-radius: 7px;
  font-size: 0.78rem;
  font-weight: 900;
  letter-spacing: 0.045em;
  text-transform: uppercase;
  white-space: nowrap;
  border: 1px solid transparent;
  opacity: 0.95;
  box-shadow: 0 8px 16px rgba(15, 23, 42, 0.18), 0 1px 0 rgba(255, 255, 255, 0.7) inset;
}

.environment-badge--development {
  color: #ffffff;
  background: linear-gradient(135deg, #7c3aed, #4c1d95);
  border-color: rgba(255, 255, 255, 0.8);
}

.environment-badge--staging {
  color: #ffffff;
  background: linear-gradient(135deg, #f59e0b, #b45309);
  border-color: rgba(255, 255, 255, 0.82);
}

.environment-badge--local {
  color: #ffffff;
  background: linear-gradient(135deg, #475569, #1e293b);
  border-color: rgba(255, 255, 255, 0.8);
}

.environment-badge--production {
  color: #ffffff;
  background: linear-gradient(135deg, #dc2626, #7f1d1d);
  border-color: rgba(255, 255, 255, 0.85);
}

/* ---------- Pied de page ---------- */

.index-v3-footer {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 18px;
  padding: clamp(6px, 1.4vh, 16px) clamp(20px, 4vw, 54px) clamp(8px, 1.8vh, 20px);
  color: var(--muted, #6b7280);
  font-size: 0.88rem;
}

#legal-links {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px 14px;
  margin: 0;
  padding: 0;
  border: 0;
}

#legal-links > :first-child {
  flex-basis: auto;
  text-align: left;
}

#legal-links a {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: inherit;
  text-decoration: none;
}

#legal-links a:hover {
  color: var(--brand, #004777);
  text-decoration: none;
}

#legal-links i,
#legal-links svg {
  width: 15px;
  height: 15px;
}

#legal-links span[aria-hidden="true"] {
  color: var(--line, #e5e7eb);
}

.footer-environment-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  margin-left: 6px;
  padding: 2px 6px;
  border-radius: 6px;
  font-size: 0.68rem;
  font-weight: 900;
  line-height: 1.2;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
  color: #fff;
  opacity: 0.95;
  border: 1px solid rgba(255, 255, 255, 0.55);
  vertical-align: middle;
}

.environment-badge--scope-local::before,
.footer-environment-badge--scope-local::before {
  content: "";
  flex: 0 0 auto;
  width: 0.72em;
  height: 0.52em;
  border: 1.5px solid currentColor;
  border-radius: 2px;
  box-shadow: 0 0.18em 0 -0.08em currentColor;
  opacity: 0.95;
}

.environment-badge--scope-online::before,
.footer-environment-badge--scope-online::before {
  content: "";
  flex: 0 0 auto;
  width: 0.9em;
  height: 0.9em;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9.5'/%3E%3Cpath d='M2.5 12h19'/%3E%3Cpath d='M12 2.5c2.6 2.6 4 5.8 4 9.5s-1.4 6.9-4 9.5c-2.6-2.6-4-5.8-4-9.5s1.4-6.9 4-9.5z'/%3E%3C/g%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9.5'/%3E%3Cpath d='M2.5 12h19'/%3E%3Cpath d='M12 2.5c2.6 2.6 4 5.8 4 9.5s-1.4 6.9-4 9.5c-2.6-2.6-4-5.8-4-9.5s1.4-6.9 4-9.5z'/%3E%3C/g%3E%3C/svg%3E") center / contain no-repeat;
  opacity: 0.95;
}

.footer-environment-badge--development {
  background: #5b21b6;
}

.footer-environment-badge--staging {
  background: #b45309;
}

.footer-environment-badge--local {
  background: #334155;
}

.footer-environment-badge--production {
  background: #991b1b;
}

/* ---------- Responsive ---------- */

@media (max-width: 980px) {
  body#page-root .index-v3-main {
    align-items: start;
  }
}

@media (max-width: 640px) {
  .index-v3-hero {
    padding: 12px 16px 48px;
  }

  /* Pas de padding haut : le débord de la carte sur le bandeau est porté par
     la marge négative de .index-v3-main, un padding le reboucherait. */
  body#page-root .index-v3-main {
    padding: 0 12px 20px;
  }

  .index-v3-card {
    border-radius: 14px;
  }

  .index-v3-panel {
    padding: 26px 18px;
  }

  .index-v3-panel-step {
    margin-bottom: 18px;
  }

  .orgpick-list.orgpick-scroll {
    max-height: 42vh;
  }

  .orgid-logo {
    width: 54px;
    height: 54px;
    border-radius: 10px;
  }

  .orgid-name {
    font-size: 1rem;
  }

  .index-v3-account-row {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .index-v3-account-status {
    grid-column: 2;
    justify-self: start;
  }

  .index-v3-footer,
  #legal-links {
    justify-content: center;
    text-align: center;
  }

  .foot-text {
    display: none;
  }
}

@media (max-width: 380px) {
  .index-v3-hero {
    padding-inline: 12px;
  }

  body#page-root .index-v3-main {
    padding-inline: 8px;
  }

  .index-v3-panel {
    padding-inline: 14px;
  }

  #org-selected-view {
    padding: 16px;
  }

  .orgid-head {
    align-items: flex-start;
    gap: 12px;
  }

  .orgid-name {
    font-size: 1rem;
  }

  .index-v3-account-row {
    gap: 10px;
  }

  .index-v3-account-avatar {
    width: 44px;
    height: 44px;
  }
}

/* ---------- Thème sombre ---------- */

/* Le bandeau n'a PAS de variante sombre : son dégradé est déjà foncé et son
   texte déjà blanc dans tous les thèmes. Les anciennes règles de la barre du
   haut (.index-v3-topbar, .index-v3-logo, .index-v3-hero-logo) sont donc
   parties avec elle. Reste ce qui vit dans la carte, elle bien claire. */

:root.theme-dark .index-v3-panel-step,
:root.theme-dark .orgid-name,
:root.theme-dark .index-v3-text-action {
  color: color-mix(in srgb, var(--brand, #004777) 38%, white 62%);
}

@media (prefers-color-scheme: dark) {
  :root.theme-system .index-v3-panel-step,
  :root.theme-system .orgid-name,
  :root.theme-system .index-v3-text-action {
    color: color-mix(in srgb, var(--brand, #004777) 38%, white 62%);
  }
}

/* ==========================================================================
   Écrin de chargement (2026-07-21)
   Le logo sablier est décomposé en 2 moitiés SVG inline (les 2 paths pleins
   de logo.svg) empilées dans un conteneur qui reprend exactement
   l'encombrement de l'ancienne image hero (.index-v3-hero-logo) : pas de
   layout shift. Sablier seul : les moitiés s'écartent pendant le chargement
   puis se réassemblent à 100 % (pas de logo d'organisation au centre sur la
   page d'accès). La chorégraphie (ouverture, fermeture, rebond) est pilotée
   en Web Animations API par scripts/index-loading-ecrin.js ;
   ici : mise en page, états de base, cascade du formulaire et thèmes.
   ========================================================================== */

.ecrin {
  position: relative;
  width: clamp(154px, 18vw, 188px);
  height: clamp(154px, 18vw, 188px);
  /* Même marge négative que l'ancienne img : le canevas 1024 du SVG contient
     une marge transparente autour du symbole. */
  margin: -30px 0 -24px;
  color: #02476e; /* couleur exacte du logo (paths currentColor) */
  filter: drop-shadow(0 8px 14px rgba(0, 71, 119, 0.1));
  /* Transition douce vers l'état d'erreur (teinte rouge). Le transform du
     rebond est piloté en WAAPI, pas ici : aucune interférence. */
  transition: color 320ms ease, filter 320ms ease;
}

.ecrin-half {
  position: absolute;
  inset: 0;
  will-change: transform, opacity, filter;
}

.ecrin-half svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* Cascade d'apparition des enfants directs de #form-content après fermeture
   de l'écrin. La classe et la variable --ecrin-cascade-i sont posées par
   scripts/index-loading-ecrin.js (cascade()), puis retirées à la fin. */
#form-content.ecrin-cascade > * {
  animation: ecrinCascadeIn 460ms cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: calc(var(--ecrin-cascade-i, 0) * 110ms);
}

@keyframes ecrinCascadeIn {
  from {
    opacity: 0;
    transform: translateY(9px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes ecrinCascadeFadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Accessibilité : fondus simples, sans translation. Les mouvements pilotés
   en JS sont eux aussi remplacés par des fondus (matchMedia côté script). */
@media (prefers-reduced-motion: reduce) {
  #form-content.ecrin-cascade > * {
    animation-name: ecrinCascadeFadeIn;
  }

  .ecrin-half {
    will-change: auto;
  }
}

/* Responsive : réplique des règles de l'ancienne .index-v3-hero-logo. */
@media (max-width: 640px) {
  .ecrin {
    width: 150px;
    height: 150px;
    margin-top: -24px;
    margin-bottom: -20px;
  }
}

/* État d'erreur : quand le chargement échoue, l'écrin reste « cassé » (figé
   ouvert par freeze()) et se teinte en rouge — même teinte que l'icône X
   d'erreur (var(--danger)). Classe posée par index-loading-ecrin.js > freeze().
   Les 3 sélecteurs couvrent thème clair, sombre et système : chacun a une
   spécificité supérieure à la règle de thème correspondante pour la battre. */
.ecrin.ecrin--error,
:root.theme-dark .ecrin.ecrin--error,
:root.theme-system .ecrin.ecrin--error {
  color: var(--danger, #a30000);
  filter: drop-shadow(0 8px 14px color-mix(in srgb, var(--danger, #a30000) 24%, transparent));
}

/* Thème sombre : logo en blanc (équivalent de l'ancien brightness(0) invert(1)
   sur l'img). */
:root.theme-dark .ecrin {
  color: #ffffff;
  filter: drop-shadow(0 8px 14px rgba(0, 0, 0, 0.18));
}

@media (prefers-color-scheme: dark) {
  :root.theme-system .ecrin {
    color: #ffffff;
    filter: drop-shadow(0 8px 14px rgba(0, 0, 0, 0.18));
  }
}

/* Badge d'environnement cliquable — bascule local <-> site en ligne
   (scripts/environment-badge-switch.js). L'attribut est posé par le script
   uniquement quand la bascule est possible : sans lui, le badge reste inerte. */
[data-environment-switch] {
  cursor: pointer;
  transition: filter 0.15s ease, opacity 0.15s ease;
}

[data-environment-switch]:hover {
  opacity: 1;
  filter: brightness(1.12);
}

[data-environment-switch]:active {
  filter: brightness(0.94);
}

[data-environment-switch]:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}


/* ============================================================
   Page à hauteur d'écran (2026-08-20)
   ------------------------------------------------------------
   Demande QG : la page d'accès doit tenir dans l'écran « de manière
   relative », quel que soit le nombre d'organisations et la hauteur
   de la fenêtre.

   Principe : la page cesse d'être une PILE de blocs en pixels qui
   pousse vers le bas, et devient une GRILLE de la hauteur de l'écran
   où un seul bloc est élastique — la liste des organisations. Les
   autres blocs gardent leur place ; ce sont les vides et les tailles
   en `vh` (bornées par `clamp`) qui absorbent la différence.

   Trois pièces indispensables :
   1. `100dvh` et non `100vh` — seul `dvh` suit la barre d'URL mobile
      et le clavier virtuel.
   2. `minmax(0, 1fr)` et non `1fr` — sans le `0`, une piste de grille
      REFUSE de descendre sous la taille naturelle de son contenu, et
      la page déborde malgré tout.
   3. `min-height: 0` répété sur TOUTE la chaîne d'ancêtres de la
      liste : il suffit d'un maillon qui l'oublie pour que le
      défilement interne ne s'active jamais.

   Plancher assumé : tout ceci ne s'applique qu'au-dessus de 520px de
   hauteur. En dessous (téléphone en paysage), même à la borne basse
   le contenu ne rentre pas : la page redevient scrollable, parce
   qu'un bouton « Accéder » hors d'atteinte serait pire qu'un scroll.

   [2026-09-17, règle N-6 du nettoyage : « ça doit tenir en Mobile S »]
   Même plancher en LARGEUR : sous 641px (téléphone en portrait), la
   grille est désactivée. Mesuré en prod locale : à 375 × 667 (iPhone SE,
   iPhone 8) la liste des organisations, seul bloc élastique, tombait à
   0 pixel, et à 390 × 844 il en restait 38 : une demi-ligne sur quatre
   organisations. Un étudiant ne pouvait plus choisir la sienne. Sur
   téléphone, la page défile : bandeau, carte entière, pied de page.
   ============================================================ */

@media (min-height: 521px) and (min-width: 641px) {
  body#page-root {
    display: flex;
    flex-direction: column;
    height: 100dvh;
    min-height: 0;
    overflow: hidden;
  }

  /* Le bandeau « Site en construction » est un frère de la page : en flex
     colonne, sa hauteur est déduite structurellement, quelle qu'elle soit.
     C'est plus juste que l'approximation en pixels de bandeau-construction.css,
     qui laissait dépasser quelques pixels dès que son texte passait à la ligne. */
  body#page-root > * {
    flex: 0 0 auto;
  }

  html.te-construction #page-root .container.center-in-page,
  html.te-construction .index-v3-shell {
    min-height: 0;
  }

  /* `max-height` et `overflow` neutralisés : app.css (règle « iPhone SE »,
     max-width 500px) fait défiler ce conteneur lui-même. Avec la grille de
     hauteur d'écran, ce serait un second défilement imbriqué autour de celui
     de la liste. Un seul endroit doit défiler à la fois. */
  #page-root .container.center-in-page {
    flex: 1 1 auto;
    display: flex;
    min-height: 0;
    max-height: none;
    overflow: visible;
  }

  .index-v3-shell {
    flex: 1 1 auto;
    width: 100%;
    min-height: 0;
    grid-template-rows: auto minmax(0, 1fr) auto;
  }

  body#page-root .index-v3-main {
    min-height: 0;
    overflow: hidden;
  }

  .index-v3-card {
    max-height: 100%;
  }

  /* La carte devient une colonne : son titre et ses actions gardent leur
     hauteur, seul le bloc « organisation » a le droit de rétrécir. */
  /* `auto` et non `hidden` : si un cas non prévu dépasse malgré tout, on
     préfère un défilement DANS la carte à un bouton coupé hors d'atteinte. */
  .index-v3-panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow-x: hidden;
    overflow-y: auto;
  }

  .index-v3-panel > .form-section {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
  }

  .form-section > *,
  #form-content > * {
    flex: 0 0 auto;
  }

  .form-section > #form-content {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
  }

  #form-content > #organisation-field,
  #organisation-field > #org-picker-view,
  #org-picker-view > #org-all-block {
    display: flex;
    flex-direction: column;
    flex: 0 1 auto;
    min-height: 0;
  }

  #org-picker-view > * {
    flex: 0 0 auto;
  }

  #org-all-block > .orgpick-group-label {
    flex: 0 0 auto;
  }

  /* Le seul bloc élastique de la page. `0 1 auto` et non `1 1 auto` :
     une liste courte garde sa hauteur naturelle (elle ne s'étire pas pour
     remplir la carte), une liste longue rétrécit et défile en interne. */
  .orgpick-list {
    flex: 0 1 auto;
    min-height: 0;
    overflow-y: auto;
  }

  /* Le plafond fixe de 300px n'a plus lieu d'être : c'est la place
     réellement disponible qui borne la liste. */
  .orgpick-list.orgpick-scroll {
    max-height: none;
  }
}

/* ---------- Écran court : le bandeau bascule en ligne ----------
   Sous 620px de haut, le sablier passe à gauche du titre au lieu d'être
   empilé au-dessus. C'est la variante « bandeau horizontal » maquettée le
   2026-08-20, mais déclenchée par la place disponible plutôt que figée :
   sur un grand écran la silhouette d'origine est conservée.
   Grille à zones car le HTML garde ses quatre enfants à plat (badge, écrin,
   titre, sous-titre) — aucun conteneur intermédiaire n'a été ajouté. */
@media (min-height: 521px) and (max-height: 620px) {
  .index-v3-hero {
    display: grid;
    grid-template-columns: auto minmax(0, auto);
    grid-template-areas:
      "badge badge"
      "logo  title"
      "logo  subtitle";
    justify-content: center;
    align-items: center;
    column-gap: 14px;
    padding-bottom: clamp(26px, 5vh, 34px);
  }

  /* La hauteur réservée est conservée : le badge d'environnement est écrit
     par le JS après le rendu, la retirer ferait sauter la page à son arrivée.
     Les ~100px gagnés par la bascule en ligne valent mieux que ces 24px. */
  .index-v3-hero-top {
    grid-area: badge;
    min-height: 24px;
    margin-bottom: 4px;
  }

  .index-v3-hero .ecrin {
    grid-area: logo;
    width: 52px;
    height: 52px;
    margin: 0;
  }

  .index-v3-hero-title {
    grid-area: title;
    align-self: end;
    margin: 0;
    font-size: 1.45rem;
    text-align: left;
  }

  .index-v3-hero-subtitle {
    grid-area: subtitle;
    align-self: start;
    margin: 2px 0 0;
    text-align: left;
  }
}
