/* MEDITRANS — charte graphique, extraite de index.html le 19/08/2026 */

  :root {
    --blue:        #0057FF;
    --blue-light:  #3B82F6;
    --blue-glow:   #60A5FA;
    --cyan:        #06B6D4;
    --cyan-light:  #67E8F9;
    --green:       #10B981;
    --green-light: #6EE7B7;
    --orange:      #F59E0B;
    --danger:      #EF4444;
    --bg:          #F0F6FF;
    --surface:     #FFFFFF;
    --surface2:    #F8FBFF;
    --border:      rgba(0,87,255,0.12);
    --border-soft: rgba(0,87,255,0.06);
    --text:        #0A1628;
    --text2:       #4B6080;
    --text3:       #8BA3C4;

    /* Ces quatre noms sont employés quatre-vingt-une fois dans les pages sans
       avoir jamais été définis. Une variable inconnue rend la propriété
       invalide : le bandeau de prise d'appel n'avait donc aucun fond, et le
       bouton d'annulation, écrit en blanc, devenait invisible dessus.

       Ils sont déclarés ici comme alias des couleurs existantes plutôt que
       remplacés dans les pages : un alias corrige les quatre-vingt-une
       occurrences d'un coup, une recherche-remplacement en oublierait. */
    --primary:      var(--blue);
    --text-primary: var(--text);
    --accent:       var(--cyan);
    --success:      var(--green);
    /* Deux autres du même genre, trouvées à l'audit du 26/08/2026 :
       `--text-muted` était employée sans repli sur les boutons d'affichage du
       mot de passe, `--warning` avec un repli qui masquait l'oubli. */
    --text-muted:   var(--text3);
    --warning:      var(--orange);
    --glow-blue:   0 0 0 1px rgba(0,87,255,0.15), 0 4px 24px rgba(0,87,255,0.10);
    --glow-hover:  0 0 0 1px rgba(0,87,255,0.25), 0 8px 32px rgba(0,87,255,0.16);
    --glow-card:   0 1px 3px rgba(0,40,120,0.06), 0 4px 16px rgba(0,40,120,0.06);
    --r:  12px;
    --rs: 8px;
    --rl: 18px;
  }

  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

  body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
    background: var(--bg);
    color: var(--text);
    -webkit-font-smoothing: antialiased;
    min-height: 100vh;
  }

  /* ── Animated background ─────────────────────── */
  body::before {
    content: '';
    position: fixed;
    inset: 0;
    background:
      radial-gradient(ellipse 80% 50% at 20% -10%, rgba(0,87,255,0.07) 0%, transparent 60%),
      radial-gradient(ellipse 60% 40% at 80% 110%, rgba(6,182,212,0.06) 0%, transparent 60%);
    pointer-events: none;
    z-index: 0;
  }

  /* ── Sidebar ─────────────────────────────────── */
  .sidebar {
    position: relative;
    z-index: 10;
    background: var(--surface);
    min-height: 100vh;
    width: 240px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--border);
    box-shadow: 4px 0 24px rgba(0,40,120,0.06);
  }

  .nav-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    color: var(--text2);
    cursor: pointer;
    border-radius: var(--rs);
    margin: 1px 8px;
    transition: all .18s ease;
    font-size: 13.5px;
    font-weight: 500;
    letter-spacing: -0.01em;
    position: relative;
  }
  .nav-item svg { flex-shrink: 0; transition: color .18s; }
  .nav-item:hover {
    background: rgba(0,87,255,0.06);
    color: var(--blue);
  }
  .nav-item.active {
    background: linear-gradient(135deg, rgba(0,87,255,0.10) 0%, rgba(6,182,212,0.07) 100%);
    color: var(--blue);
    font-weight: 600;
    box-shadow: inset 3px 0 0 var(--blue);
  }

  /* ── Pages ───────────────────────────────────── */
  .page { display: none; }
  .page.active { display: block; animation: fadeUp .25s ease; }
  @keyframes fadeUp { from { opacity:0; transform:translateY(6px); } to { opacity:1; transform:none; } }

  /* ── Cards ───────────────────────────────────── */
  .card {
    background: var(--surface);
    border-radius: var(--r);
    border: 1px solid var(--border);
    box-shadow: var(--glow-card);
    padding: 20px;
    position: relative;
    z-index: 1;
    transition: box-shadow .2s, border-color .2s;
  }
  .card:hover { border-color: rgba(0,87,255,0.2); }

  /* ── KPI Cards ───────────────────────────────── */
  .kpi {
    background: var(--surface);
    border-radius: var(--r);
    padding: 20px;
    border: 1px solid var(--border);
    box-shadow: var(--glow-card);
    position: relative;
    overflow: hidden;
    transition: box-shadow .2s, transform .2s, border-color .2s;
    z-index: 1;
  }
  .kpi:hover {
    box-shadow: var(--glow-hover);
    transform: translateY(-2px);
    border-color: rgba(0,87,255,0.25);
  }
  .kpi::after {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 3px;
    background: linear-gradient(90deg, var(--blue), var(--cyan));
    border-radius: var(--r) var(--r) 0 0;
  }

  /* ── Buttons ─────────────────────────────────── */
  .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px 15px;
    border-radius: var(--rs);
    font-size: 13.5px;
    cursor: pointer;
    font-weight: 600;
    font-family: inherit;
    border: none;
    letter-spacing: -0.01em;
    white-space: nowrap;
    transition: all .15s ease;
  }
  .btn:active { transform: scale(0.96); }
  .btn svg { flex-shrink: 0; }

  .btn-primary {
    background: linear-gradient(135deg, var(--blue) 0%, #1E6BFF 100%);
    color: #fff;
    box-shadow: 0 2px 8px rgba(0,87,255,0.28), 0 1px 2px rgba(0,87,255,0.2);
  }
  .btn-primary:hover {
    box-shadow: 0 4px 16px rgba(0,87,255,0.40), 0 1px 4px rgba(0,87,255,0.3);
    transform: translateY(-1px);
  }

  .btn-green {
    background: linear-gradient(135deg, var(--green) 0%, #059669 100%);
    color: #fff;
    box-shadow: 0 2px 8px rgba(16,185,129,0.28);
  }
  .btn-green:hover { box-shadow: 0 4px 16px rgba(16,185,129,0.40); transform: translateY(-1px); }

  .btn-red {
    background: linear-gradient(135deg, var(--danger) 0%, #DC2626 100%);
    color: #fff;
    box-shadow: 0 2px 8px rgba(239,68,68,0.25);
  }
  .btn-red:hover { box-shadow: 0 4px 14px rgba(239,68,68,0.38); transform: translateY(-1px); }

  .btn-orange {
    background: linear-gradient(135deg, var(--orange) 0%, #D97706 100%);
    color: #fff;
    box-shadow: 0 2px 8px rgba(245,158,11,0.28);
  }
  .btn-orange:hover { box-shadow: 0 4px 14px rgba(245,158,11,0.38); transform: translateY(-1px); }

  .btn-gray {
    background: var(--surface);
    color: var(--text2);
    border: 1px solid var(--border);
    box-shadow: 0 1px 3px rgba(0,40,120,0.06);
  }
  .btn-gray:hover { background: var(--surface2); color: var(--blue); border-color: rgba(0,87,255,0.25); }

  .btn-icon { width: 30px; height: 30px; padding: 0; border-radius: 7px; }

  /* ── Forms ───────────────────────────────────── */
  .form-input {
    width: 100%;
    border: 1px solid var(--border);
    border-radius: var(--rs);
    padding: 9px 12px;
    font-size: 13.5px;
    font-family: inherit;
    outline: none;
    background: var(--surface);
    color: var(--text);
    transition: border-color .15s, box-shadow .15s;
  }
  .form-input:focus {
    border-color: var(--blue-light);
    box-shadow: 0 0 0 3px rgba(0,87,255,0.10);
  }
  .form-input::placeholder { color: var(--text3); }

  .form-label {
    font-size: 11.5px;
    font-weight: 700;
    color: var(--text3);
    margin-bottom: 5px;
    display: block;
    letter-spacing: 0.06em;
    text-transform: uppercase;
  }

  /* ── Tables ──────────────────────────────────── */
  .table-wrap { overflow-x: auto; }
  table { width: 100%; border-collapse: collapse; }
  th {
    background: linear-gradient(180deg, #F0F6FF 0%, #EBF2FF 100%);
    padding: 11px 14px;
    text-align: left;
    font-size: 10.5px;
    font-weight: 700;
    color: var(--text3);
    text-transform: uppercase;
    letter-spacing: .08em;
    border-bottom: 1px solid var(--border);
  }
  td {
    padding: 12px 14px;
    font-size: 13.5px;
    color: var(--text);
    border-bottom: 1px solid var(--border-soft);
  }
  tr:last-child td { border-bottom: none; }
  tr:hover td { background: rgba(0,87,255,0.025); }

  /* ── Badges ──────────────────────────────────── */
  .badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 10px;
    border-radius: 99px;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.02em;
  }
  .badge-green  { background: rgba(16,185,129,0.1);  color: #059669; }
  .badge-red    { background: rgba(239,68,68,0.10);  color: #DC2626; }
  .badge-orange { background: rgba(245,158,11,0.12); color: #B45309; }
  .badge-blue   { background: rgba(0,87,255,0.09);   color: var(--blue); }
  .badge-gray   { background: rgba(0,40,120,0.06);   color: var(--text2); }

  /* ── Modals ──────────────────────────────────── */
  .modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(5,20,60,0.40);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    z-index: 50;
    align-items: center;
    justify-content: center;
  }
  .modal-overlay.open { display: flex; }
  .modal {
    background: var(--surface);
    border-radius: var(--rl);
    padding: 28px;
    max-width: 640px;
    width: 90%;
    max-height: 90vh;
    overflow-y: auto;
    box-shadow: 0 32px 80px rgba(0,40,120,0.18), 0 0 0 1px rgba(0,87,255,0.12);
    animation: modalIn .22s cubic-bezier(0.34, 1.56, 0.64, 1);
  }
  .modal-lg { max-width: 800px; }
  @keyframes modalIn { from { opacity:0; transform:scale(0.94) translateY(10px); } to { opacity:1; transform:none; } }

  /* ── Tabs ────────────────────────────────────── */
  .tab-btn {
    padding: 7px 16px;
    border-radius: var(--rs);
    font-size: 13.5px;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    color: var(--text2);
    border: none;
    background: transparent;
    transition: all .15s;
  }
  .tab-btn:hover { background: rgba(0,87,255,0.07); color: var(--blue); }
  .tab-btn.active {
    background: linear-gradient(135deg, var(--blue), #1E6BFF);
    color: #fff;
    box-shadow: 0 2px 10px rgba(0,87,255,0.30);
  }

  /* ── Misc ────────────────────────────────────── */
  .gain-positive { color: var(--green); font-weight: 700; }
  .gain-negative { color: var(--danger); font-weight: 700; }

  #toast { position: fixed; bottom: 24px; right: 24px; z-index: 100; }
  .toast-msg {
    padding: 12px 20px;
    border-radius: 12px;
    color: #fff;
    font-size: 13.5px;
    font-weight: 600;
    margin-top: 8px;
    box-shadow: 0 8px 28px rgba(0,40,120,0.22);
    animation: toastIn .28s cubic-bezier(0.34,1.56,0.64,1);
  }
  @keyframes toastIn { from { transform:translateX(60px) scale(0.9); opacity:0; } to { transform:none; opacity:1; } }

  .spinner {
    display: inline-block;
    width: 15px; height: 15px;
    border: 2px solid rgba(255,255,255,0.3);
    border-top-color: #fff;
    border-radius: 50%;
    animation: spin .6s linear infinite;
  }
  @keyframes spin { to { transform: rotate(360deg); } }

  .quota-bar { height: 5px; border-radius: 99px; background: rgba(0,87,255,0.08); overflow: hidden; }
  .quota-fill { height: 100%; border-radius: 99px; transition: width .4s ease; }

  /* ── Scrollbar ───────────────────────────────── */
  ::-webkit-scrollbar { width: 5px; height: 5px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb { background: rgba(0,87,255,0.18); border-radius: 99px; }
  ::-webkit-scrollbar-thumb:hover { background: rgba(0,87,255,0.32); }

  /* ── Responsive sidebar ──────────────────────── */
  @media (max-width: 768px) {
    .sidebar { width: 60px; }
    .sidebar .nav-label, .sidebar .brand-text { display: none; }
    .nav-item { justify-content: center; padding: 10px; }
  }

  /* ══════════════════════════════════════════════════════════════════════
     LES FENÊTRES SUR TÉLÉPHONE ET TABLETTE
     ══════════════════════════════════════════════════════════════════════
     Le dossier médical se remplit au chevet du patient, dans l'ambulance ou
     aux urgences — pas devant un ordinateur de bureau. Les fenêtres étaient
     pourtant taillées pour un grand écran : grilles à quatre colonnes serrées
     à trois centimètres de large, champs de 36 pixels de haut impossibles à
     viser du pouce, et la barre de boutons qui disparaissait sous le clavier.

     Rien n'est masqué au passage : un médecin qui remplit sur tablette doit
     avoir accès aux mêmes rubriques que sur un poste fixe. Ce qui change est
     la mise en page, pas le contenu. */

  /* Tablette : les grilles denses se détendent, la fenêtre prend la place. */
  @media (max-width: 1024px) {
    .modal { max-width: none; width: calc(100% - 32px); padding: 22px; }
    .modal-lg { max-width: none; }
    .modal .grid-cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .modal .grid-cols-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .modal .grid-cols-5 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .modal .md\:grid-cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }

  /* Téléphone : une colonne, la fenêtre occupe l'écran, et l'on vise au doigt. */
  @media (max-width: 700px) {
    .modal-overlay { align-items: flex-end; }
    /* La fenêtre monte du bas et s'arrête à la hauteur de son contenu : une
       fenêtre de six champs n'a aucune raison d'occuper l'écran entier. */
    .modal {
      width: 100%;
      /* La fenêtre monte du bas et couvre l'écran : sur un téléphone, une
         boîte flottante entourée de flou perd déjà un tiers de la hauteur
         utile, et il en reste d'autant moins quand le clavier s'ouvre. */
      max-height: 100dvh;
      border-radius: 0;
      padding: 18px 16px calc(18px + env(safe-area-inset-bottom));
      animation: modalMonte .24s cubic-bezier(.16, 1, .3, 1);
      /* Défilement au doigt, sans inertie perdue. */
      -webkit-overflow-scrolling: touch;
      overscroll-behavior: contain;
    }
    @keyframes modalMonte {
      from { opacity: 0; transform: translateY(24px); }
      to   { opacity: 1; transform: none; }
    }

    /* Les grilles de formulaire passent en colonne. Deux champs côte à côte
       sur un téléphone font trois centimètres chacun : on ne lit plus
       l'intitulé, et on tape à côté.

       On ne vise que les grilles à colonnes égales, celles que Tailwind nomme
       `grid-cols-N`. Les rangées de tableau — lignes de proforma, lignes du
       point journalier, schéma corporel — posent leurs colonnes en style
       direct parce qu'elles ont des largeurs choisies. Un `!important` sur
       `.grid` les écrasait aussi : l'en-tête « Désignation / Qté / Unité /
       Prix » devenait sept mots empilés, puis chaque ligne sept champs sans
       étiquette. Le lien entre l'en-tête et les colonnes était sa seule
       raison d'être. */
    .modal [class*="grid-cols-"] { grid-template-columns: 1fr !important; }
    .modal .col-span-2, .modal .col-span-3, .modal .col-span-4 { grid-column: span 1; }

    /* Les champs se visent au pouce. 44 px est le minimum retenu par Apple et
       Google ; en dessous, on rate une fois sur cinq. Et 16 px de police
       empêchent iOS de zoomer tout seul au premier appui, ce qui décalait la
       page et faisait perdre le champ de vue. */
    .modal .form-input,
    .modal input, .modal select, .modal textarea {
      min-height: 44px;
      font-size: 16px;
    }
    .modal textarea { min-height: 88px; }
    .modal .btn { min-height: 44px; padding-left: 16px; padding-right: 16px; }

    /* Les cases à cocher d'antécédents et de signes cliniques : on double la
       cible et on aère, sinon deux lignes voisines se touchent. */
    .modal input[type="checkbox"], .modal input[type="radio"] {
      width: 20px; height: 20px;
    }
    .modal label.flex { padding: 6px 0; }

    /* Les listes internes à hauteur fixe étouffaient sur un petit écran. Elles
       portent une classe Tailwind `max-h-*`, pas un style en ligne : la règle
       précédente visait l'attribut `style` et ne touchait donc que deux
       tableaux qui, eux, se portaient bien — et qu'elle rétrécissait. */
    .modal [class*="max-h-"] { max-height: 40vh !important; }

    /* Les cases à cocher ne sont pas des champs de saisie : la règle des 44 px
       ci-dessus les étirait, et chaque ligne d'antécédent occupait cinquante
       pixels dans une liste qui n'en fait que cent soixante. */
    .modal input[type="checkbox"], .modal input[type="radio"] {
      min-height: 0;
    }

    /* La barre d'actions reste sous la main plutôt qu'au bout du défilement.
       Un médecin qui a rempli trente champs ne doit pas chercher où valider. */
    .modal .modal-actions {
      position: sticky;
      bottom: calc(-18px - env(safe-area-inset-bottom));
      background: var(--surface);
      margin: 12px -16px calc(-18px - env(safe-area-inset-bottom));
      padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
      border-top: 1px solid var(--border);
      z-index: 2;
    }
    .modal .modal-actions .btn { flex: 1 1 auto; }

    /* Le schéma corporel reste utilisable : il se pointe du doigt. */
    .modal svg { max-width: 100%; height: auto; }
  }

/* ══════════════════════════════════════════════════════════════════════════
   ÉCRAN DE CONNEXION
   ══════════════════════════════════════════════════════════════════════════
   C'est la première chose que voient les équipes chaque matin, et la seule
   que voit un visiteur à qui l'on montre l'outil. Elle disait jusqu'ici qu'on
   n'avait pas pris le temps.

   Deux moitiés. À gauche, ce que fait l'entreprise : une chronologie
   d'intervention qui s'anime, un tracé, une route. À droite, le formulaire,
   sobre, où rien ne distrait de la saisie.

   Aucune donnée réelle n'apparaît à gauche. Un compteur d'activité affiché
   avant l'authentification renseignerait n'importe quel visiteur sur le volume
   et les horaires de l'entreprise. Ce qui s'anime est une démonstration du
   déroulé d'une intervention, pas le journal du jour.
   ────────────────────────────────────────────────────────────────────────── */

#loginScreen {
  display: flex;
  flex-direction: row;
  align-items: stretch;
  justify-content: stretch;
  background: var(--surface);
  overflow: hidden;
}

/* ── Le panneau vivant ─────────────────────────────────────────────────── */

.cx-scene {
  position: relative;
  flex: 1 1 58%;
  min-width: 0;
  overflow: hidden;
  background:
    radial-gradient(1200px 800px at 15% 10%, #0B49C8 0%, transparent 60%),
    radial-gradient(900px 700px at 85% 85%, #0A8BB4 0%, transparent 62%),
    linear-gradient(150deg, #041638 0%, #062A6B 45%, #04204F 100%);
  color: #fff;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 48px 52px;
}

/* Deux halos qui dérivent lentement. Assez lents pour qu'on ne les remarque
   pas, assez présents pour que l'écran ne paraisse pas figé. */
.cx-halo {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  filter: blur(8px);
  opacity: .5;
}
.cx-halo-a {
  width: 520px; height: 520px; top: -160px; right: -120px;
  background: radial-gradient(circle, rgba(96,165,250,.38) 0%, transparent 68%);
  animation: cx-derive-a 26s ease-in-out infinite;
}
.cx-halo-b {
  width: 420px; height: 420px; bottom: -140px; left: -100px;
  background: radial-gradient(circle, rgba(103,232,249,.30) 0%, transparent 68%);
  animation: cx-derive-b 32s ease-in-out infinite;
}
@keyframes cx-derive-a {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50%      { transform: translate(-56px, 44px) scale(1.09); }
}
@keyframes cx-derive-b {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50%      { transform: translate(48px, -38px) scale(1.12); }
}

/* La trame en fond : discrète, elle donne de la profondeur sans motif visible. */
.cx-trame {
  position: absolute; inset: 0; pointer-events: none; opacity: .16;
  background-image:
    linear-gradient(rgba(255,255,255,.5) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.5) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(circle at 30% 40%, #000 0%, transparent 72%);
  -webkit-mask-image: radial-gradient(circle at 30% 40%, #000 0%, transparent 72%);
}

.cx-entete { position: relative; z-index: 2; }
.cx-corps  { position: relative; z-index: 2; }
.cx-pied   { position: relative; z-index: 2; }

/* Le logo porte déjà le nom et la signature de la maison : les redoubler en
   texte à côté ferait deux fois la même chose, avec deux typographies. */
.cx-logo {
  display: block; width: clamp(230px, 26vw, 320px); height: auto;
  animation: cx-paraitre .7s cubic-bezier(.16,1,.3,1) both;
}
@keyframes cx-paraitre {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

.cx-titre {
  font-size: clamp(26px, 3.1vw, 40px); font-weight: 800; line-height: 1.14;
  letter-spacing: -.035em; margin: 0 0 14px; max-width: 15ch;
}
.cx-texte {
  font-size: 15px; line-height: 1.62; color: rgba(255,255,255,.72);
  max-width: 42ch; margin: 0 0 34px;
}

/* ── Le tracé et la route ──────────────────────────────────────────────── */

.cx-toile { width: 100%; max-width: 520px; display: block; overflow: visible; }

/* Le tracé se dessine de gauche à droite, puis recommence. */
.cx-pouls {
  fill: none; stroke: #67E8F9; stroke-width: 2.2;
  stroke-linecap: round; stroke-linejoin: round;
  filter: drop-shadow(0 0 6px rgba(103,232,249,.85));
  stroke-dasharray: 620; stroke-dashoffset: 620;
  animation: cx-tracer 4.6s cubic-bezier(.5,.05,.3,1) infinite;
}
@keyframes cx-tracer {
  0%        { stroke-dashoffset: 620; }
  62%, 100% { stroke-dashoffset: -620; }
}

.cx-route {
  fill: none; stroke: rgba(255,255,255,.26); stroke-width: 2;
  stroke-linecap: round; stroke-dasharray: 7 9;
  animation: cx-defiler 2.4s linear infinite;
}
@keyframes cx-defiler { to { stroke-dashoffset: -32; } }

.cx-jalon-point { fill: rgba(255,255,255,.30); }
.cx-vehicule    { filter: drop-shadow(0 0 10px rgba(255,255,255,.7)); }

/* ── La chronologie qui s'allume ───────────────────────────────────────── */

.cx-chrono { display: flex; gap: 0; margin-top: 30px; max-width: 520px; }
.cx-etape  { flex: 1; min-width: 0; position: relative; padding-top: 20px; }
.cx-etape::before {
  content: ''; position: absolute; top: 5px; left: 0; right: 0;
  height: 2px; background: rgba(255,255,255,.16);
}
.cx-etape::after {
  content: ''; position: absolute; top: 1px; left: 0;
  width: 10px; height: 10px; border-radius: 50%;
  background: rgba(255,255,255,.24);
  animation: cx-allumer 6s ease-in-out infinite;
}
.cx-etape:nth-child(1)::after { animation-delay: 0s; }
.cx-etape:nth-child(2)::after { animation-delay: .9s; }
.cx-etape:nth-child(3)::after { animation-delay: 1.8s; }
.cx-etape:nth-child(4)::after { animation-delay: 2.7s; }
@keyframes cx-allumer {
  0%, 8%   { background: rgba(255,255,255,.24); box-shadow: none; transform: scale(1); }
  14%, 58% { background: #67E8F9; box-shadow: 0 0 0 5px rgba(103,232,249,.20); transform: scale(1.25); }
  70%, 100%{ background: rgba(255,255,255,.24); box-shadow: none; transform: scale(1); }
}
.cx-code   { font-size: 11px; font-weight: 800; letter-spacing: .08em; color: rgba(255,255,255,.55); }
.cx-etiq   { font-size: 12.5px; font-weight: 500; color: rgba(255,255,255,.86); margin-top: 2px; }

.cx-pied {
  display: flex; flex-wrap: wrap; gap: 8px 22px; align-items: center;
  font-size: 12px; color: rgba(255,255,255,.52);
}
.cx-pastille { display: inline-flex; align-items: center; gap: 7px; }
.cx-point-vif {
  width: 7px; height: 7px; border-radius: 50%; background: #6EE7B7;
  box-shadow: 0 0 0 0 rgba(110,231,183,.55);
  animation: cx-battre 2.6s ease-out infinite;
}
@keyframes cx-battre {
  0%   { box-shadow: 0 0 0 0 rgba(110,231,183,.55); }
  70%  { box-shadow: 0 0 0 9px rgba(110,231,183,0); }
  100% { box-shadow: 0 0 0 0 rgba(110,231,183,0); }
}

/* ── Le formulaire ─────────────────────────────────────────────────────── */

.cx-panneau {
  flex: 0 0 clamp(390px, 42%, 520px);
  display: flex; align-items: center; justify-content: center;
  padding: 40px 44px; background: var(--surface);
  overflow-y: auto;
}
.cx-carte { width: 100%; max-width: 352px; animation: cx-monter .55s cubic-bezier(.16,1,.3,1) both; }
@keyframes cx-monter {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

.cx-accueil { font-size: 25px; font-weight: 800; letter-spacing: -.032em; color: var(--text); margin-bottom: 5px; }
.cx-invite  { font-size: 13.5px; color: var(--text2); margin-bottom: 30px; }

.cx-champ { margin-bottom: 17px; }
.cx-etiquette {
  display: block; font-size: 11.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text3); margin-bottom: 7px;
}
/* La saisie ne se contente pas d'un cadre : le champ se soulève au focus, ce
   qui donne le repère visuel qui manquait sur un écran tactile en plein jour. */
.cx-saisie {
  width: 100%; padding: 13px 15px; font-size: 15px; font-family: inherit;
  color: var(--text); background: var(--surface2);
  border: 1.5px solid var(--border); border-radius: 12px;
  transition: border-color .18s ease, box-shadow .18s ease, background .18s ease;
  -webkit-appearance: none; appearance: none;
}
.cx-saisie::placeholder { color: var(--text3); }
.cx-saisie:focus {
  outline: none; background: var(--surface);
  border-color: var(--blue);
  box-shadow: 0 0 0 4px rgba(0,87,255,.13);
}
.cx-enveloppe { position: relative; }
.cx-oeil {
  position: absolute; right: 5px; top: 50%; transform: translateY(-50%);
  background: none; border: 0; cursor: pointer; padding: 8px 11px;
  color: var(--text3); font-size: 12px; font-weight: 700; font-family: inherit;
  border-radius: 8px; transition: color .15s ease, background .15s ease;
}
.cx-oeil:hover { color: var(--blue); background: rgba(0,87,255,.06); }

.cx-entrer {
  width: 100%; margin-top: 9px; padding: 14px; border: 0; border-radius: 12px;
  font-family: inherit; font-size: 15px; font-weight: 700; letter-spacing: -.01em;
  color: #fff; cursor: pointer; position: relative; overflow: hidden;
  background: linear-gradient(135deg, var(--blue) 0%, #2563EB 55%, var(--cyan) 130%);
  box-shadow: 0 6px 20px rgba(0,87,255,.28);
  transition: transform .16s cubic-bezier(.16,1,.3,1), box-shadow .16s ease, filter .16s ease;
}
.cx-entrer:hover  { transform: translateY(-1.5px); box-shadow: 0 10px 28px rgba(0,87,255,.36); }
.cx-entrer:active { transform: translateY(0); box-shadow: 0 4px 14px rgba(0,87,255,.30); }
.cx-entrer[disabled] { filter: saturate(.4); cursor: progress; transform: none; }
/* Un reflet traverse le bouton, une fois toutes les cinq secondes. */
.cx-entrer::after {
  content: ''; position: absolute; top: 0; bottom: 0; width: 42%;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,.26), transparent);
  transform: translateX(-160%);
  animation: cx-reflet 5s ease-in-out infinite;
}
@keyframes cx-reflet {
  0%, 72%  { transform: translateX(-160%); }
  88%, 100%{ transform: translateX(340%); }
}

/* Le message d'échec entre par la gauche : on le voit sans le chercher. */
.cx-echec {
  margin-top: 15px; padding: 11px 14px; border-radius: 11px;
  background: rgba(239,68,68,.08); border: 1px solid rgba(239,68,68,.22);
  color: #B91C1C; font-size: 13px; font-weight: 500; line-height: 1.45;
  animation: cx-secousse .42s cubic-bezier(.36,.07,.19,.97) both;
}
@keyframes cx-secousse {
  0%, 100%   { transform: translateX(0); }
  18%, 58%   { transform: translateX(-5px); }
  38%, 78%   { transform: translateX(5px); }
}

.cx-bas {
  margin-top: 26px; padding-top: 20px; border-top: 1px solid var(--border-soft);
  font-size: 11.5px; color: var(--text3); line-height: 1.6;
}

/* ── Écrans étroits ────────────────────────────────────────────────────── */
/* Sous 900 px, le panneau vivant devient un bandeau : sur le téléphone d'un
   équipage, ce qui compte est d'atteindre le champ de saisie sans faire
   défiler une illustration. */
@media (max-width: 900px) {
  #loginScreen { flex-direction: column; }
  .cx-scene {
    flex: 0 0 auto; padding: 26px 24px 22px;
    justify-content: flex-start; gap: 14px;
  }
  .cx-logo { width: 208px; }
  .cx-titre { font-size: 21px; margin-bottom: 8px; }
  .cx-texte, .cx-toile, .cx-chrono, .cx-pied { display: none; }
  .cx-panneau { flex: 1 1 auto; padding: 30px 22px 40px; }
  .cx-carte { max-width: 420px; }
}

/* Certaines personnes désactivent les animations pour de bonnes raisons —
   migraine, vertiges, trouble de l'attention. On les respecte. */
@media (prefers-reduced-motion: reduce) {
  .cx-halo-a, .cx-halo-b, .cx-pouls, .cx-route, .cx-etape::after,
  .cx-point-vif, .cx-entrer::after, .cx-carte, .cx-echec, .cx-logo {
    animation: none !important;
  }
  /* Le véhicule est animé par SVG, pas par CSS : on l'arrête autrement. */
  .cx-vehicule animateMotion { display: none; }
  .cx-pouls { stroke-dashoffset: 0; }
  .cx-etape::after { background: #67E8F9; }
}

/* ── Ce qui dépend d'un droit ne s'affiche pas avant qu'on le connaisse ─────
   Le menu était écrit en entier dans la page, puis réduit par le JavaScript
   une fois les permissions reçues. Entre les deux — le temps d'un aller-retour
   au serveur — tout le monde voyait tous les onglets, administration comprise.

   La règle est posée ici plutôt qu'en ligne dans le balisage : elle vaut pour
   les seize entrées de menu et pour tous les boutons porteurs d'un droit,
   présents et à venir, sans qu'on ait à y penser à chaque ajout.

   `visibility` plutôt que `display` sur la barre de navigation : la largeur
   reste réservée, et l'écran ne se réorganise pas sous les yeux au moment où
   les droits arrivent.                                                      */
body.acces-inconnus [data-permission] {
  display: none !important;
}
body.acces-inconnus .sidebar nav {
  visibility: hidden;
}
