@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600&family=Poppins:wght@500;600&display=swap');
/* Le lettrage "School Editor" est figé en tracés SVG (voir .wordmark-svg) —
   il ne dépend plus de Harrington, French Script MT, Berkshire Swash,
   Yeseva One ni Fondamento, qui ont donc été retirées de cet import. */

  :root{
    --ink:#1F2937; --muted:#6B7280;
    --teal:#1FB6A6; --pink:#D6265E; --blue:#2E7BD9; --navy:#26344A; --gold:#D9A441;
    --paper:#FFFFFF; --line:#ECEDF0; --bg-soft:#FAFBFC; --card:#FFFFFF;
    /* Même couleur que --bg-soft, en composantes : un rgba() ne se dérive
       pas d'une variable hexadécimale, et c'est ce qu'exige le fondu de la
       bande de preuve vers la savane (voir .proof). */
    --bg-soft-rgb:250,251,252;
    --scale:1;
  }
  [data-theme="dark"]{
    --ink:#E8ECF1; --muted:#9AA5B1;
    --paper:#121821; --line:#26303C; --bg-soft:#161D27; --card:#1C2430; --navy:#0C1118;
    --bg-soft-rgb:22,29,39;
  }
  *{box-sizing:border-box;}
  /* Contrôle "Aa" (voir js/textscale.js) : zoom plutôt que rem/transform —
     tout le reste de cette feuille est en px, zoom scale texte+icônes+cartes
     uniformément sans rien casser, contrairement à transform:scale qui
     interagit mal avec les éléments position:absolute/fixed du design. */
  html{zoom:var(--scale);}
  html,body{height:100%;margin:0;}
  /* overflow-y:auto (pas hidden) : l'accueil vise à tenir sur un seul écran
     à taille de texte normale, mais un scroll doit apparaître automatiquement
     dès que le contenu ne rentre plus (taille de texte agrandie via "Aa",
     traduction plus longue...) plutôt que de couper silencieusement des
     éléments hors cadre. Voir aussi .hero{overflow:visible} plus bas. */
  body{font-family:'IBM Plex Sans',sans-serif;background:var(--paper);color:var(--ink);
    overflow-y:auto;overflow-x:hidden;
    transition:background .25s ease,color .25s ease;display:flex;flex-direction:column;}

  .bokeh{position:absolute;border-radius:50%;background:radial-gradient(circle at 30% 30%, var(--card), var(--bg-soft));
    box-shadow: inset -4px -4px 8px rgba(0,0,0,.04);animation: float 4s ease-in-out infinite;}
  @keyframes float{0%,100%{transform:translateY(0);}50%{transform:translateY(-16px);}}

  .topbar{position:relative;padding:14px 28px;display:flex;justify-content:space-between;align-items:center;flex-shrink:0;}
  .topbar-left,.topbar-right{display:flex;align-items:center;gap:14px;}
  .topbar a{color:var(--ink);text-decoration:none;font-size:11.5px;letter-spacing:.07em;font-weight:500;
    text-transform:uppercase;display:flex;align-items:center;gap:6px;}
  .topbar a svg{width:16px;height:16px;stroke:var(--ink);fill:none;stroke-width:1.8;flex-shrink:0;}

  .lang-toggle{
    position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
    display:flex;align-items:center;background:var(--card);border:1px solid var(--line);
    border-radius:20px;padding:3px;gap:2px;
  }
  .lang-toggle button{
    font-family:'Poppins',sans-serif;font-size:11px;font-weight:600;padding:5px 12px;
    border:none;background:none;border-radius:16px;cursor:pointer;color:var(--muted);
  }
  @keyframes gradShift{0%{background-position:0% 50%;}50%{background-position:100% 50%;}100%{background-position:0% 50%;}}
  .lang-toggle button.active,.cta-row a,.wave-strip,.feature{
    background-size:200% 200%;animation:gradShift 3s ease infinite;
  }
  .lang-toggle button.active{background:linear-gradient(135deg,var(--teal),var(--blue));color:#fff;}

  .theme-toggle{display:flex;align-items:center;gap:6px;border:1px solid var(--line);border-radius:20px;
    padding:5px 12px;font-size:11px;font-weight:500;color:var(--muted);cursor:pointer;background:var(--card);}
  .theme-toggle svg{width:13px;height:13px;stroke:var(--muted);}

  /* Bouton "Aa" — taille du texte, voir js/textscale.js */
  .text-scale-btn{
    display:flex;align-items:center;gap:2px;border:1px solid var(--line);border-radius:20px;
    padding:5px 12px;font-family:'Poppins',sans-serif;font-weight:600;color:var(--muted);
    cursor:pointer;background:var(--card);
  }
  .text-scale-btn .ts-sm{font-size:9.5px;}
  .text-scale-btn .ts-lg{font-size:13px;}

  .contact-trigger{
    color:var(--ink);text-decoration:none;font-size:11.5px;letter-spacing:.07em;font-weight:500;
    text-transform:uppercase;display:flex;align-items:center;gap:6px;background:none;border:none;
    font-family:'IBM Plex Sans',sans-serif;cursor:pointer;padding:0;
  }
  .contact-trigger svg{width:16px;height:16px;stroke:var(--ink);fill:none;stroke-width:1.8;flex-shrink:0;}

  .contact-box{max-width:340px;}
  .contact-list{display:flex;flex-direction:column;gap:14px;margin-top:6px;}
  .contact-row{display:flex;align-items:center;gap:12px;font-size:14.5px;color:var(--ink);}
  .contact-row svg{width:18px;height:18px;stroke:var(--teal);fill:none;stroke-width:1.8;flex-shrink:0;}
  .contact-row a{color:var(--ink);text-decoration:none;}
  .contact-row a.wa{color:#1FB6A6;font-weight:600;}
  .contact-row .wa-badge{
    display:inline-flex;align-items:center;gap:5px;background:rgba(31,182,166,.12);
    padding:4px 10px;border-radius:14px;font-size:12px;font-weight:600;color:#0E8C7F;margin-left:4px;
  }

  @media (max-width:820px){
    .topbar a span, .theme-toggle span, .contact-trigger span{display:none;}
    .theme-toggle, .text-scale-btn{padding:7px;}
  }

  .hero{position:relative;flex:1;min-height:0;overflow:visible;background:var(--bg-soft);
    display:flex;flex-direction:column;justify-content:center;padding:10px 28px;}
  .hero-inner{max-width:1120px;width:100%;margin:0 auto;display:grid;grid-template-columns:1fr 1fr;gap:16px;align-items:center;position:relative;z-index:2;}
  @media (max-width:820px){
    html,body{height:auto;overflow:auto;}
    body{overflow-y:auto;-webkit-overflow-scrolling:touch;}
    .hero{flex:none;overflow:visible;min-height:auto;padding:14px 20px 24px;}
    .illus{min-height:130px;}
    .savanna,.sky{flex-shrink:0;}
    .hero-inner{grid-template-columns:1fr;}
    .illus{order:2;}
    .brandcol{order:1;}
  }

  .illus{display:flex;align-items:center;justify-content:center;min-height:170px;position:relative;}
  .illus svg{width:100%;max-width:280px;height:auto;position:absolute;opacity:0;transition:opacity .5s ease;}
  .illus svg.active{opacity:1;position:relative;}

  .brandcol{text-align:center;}
  .brandcol img{width:110px;height:auto;margin-bottom:4px;}
  .wordmark{color:var(--ink);margin:0 0 6px;display:flex;justify-content:center;}
  .wordmark-svg{color:var(--ink);width:122px;height:auto;}
  .wordmark-svg path{fill:currentColor;}
  .brandcol .tagline{font-size:11px;letter-spacing:.06em;color:var(--muted);margin-bottom:14px;}

  .cta-row{margin-bottom:8px;}
  .cta-row a{
    font-family:'Poppins',sans-serif;color:#fff;text-decoration:none;font-weight:600;
    padding:10px 28px;border-radius:22px;font-size:13.5px;letter-spacing:.01em;
    background:linear-gradient(135deg,var(--teal),var(--blue));display:inline-block;
    box-shadow:0 6px 16px rgba(31,182,166,.28);
  }
  .sub-row{display:flex;justify-content:center;gap:8px;flex-wrap:wrap;}
  .btn-ico{width:20px;height:20px;flex-shrink:0;}
  .sub-row a, .sub-row button{display:inline-flex;align-items:center;gap:7px;}
  .cta-row a{display:inline-flex;align-items:center;gap:8px;}

  .sub-row a, .sub-row button{
    font-family:'Poppins',sans-serif;color:var(--navy);text-decoration:none;font-weight:600;
    padding:6px 14px 6px 10px;border-radius:18px;border:1.5px solid var(--line);
    background:var(--card);letter-spacing:.01em;cursor:pointer;font-size:11.5px;
    transition:transform .15s ease, box-shadow .15s ease;
  }
  [data-theme="dark"] .sub-row a,[data-theme="dark"] .sub-row button{color:var(--ink);}
  .sub-row a:hover,.sub-row button:hover{transform:translateY(-2px);box-shadow:0 4px 10px rgba(0,0,0,.08);}

  .slide-caption{max-width:1120px;margin:12px auto 0;padding:0 28px;position:relative;z-index:2;width:100%;}
  .slide-caption h3{font-family:'Poppins',sans-serif;font-size:16px;font-weight:600;color:var(--ink);margin:0 0 4px;letter-spacing:.01em;text-transform:uppercase;}
  .slide-caption p{font-size:13px;color:var(--muted);margin:0;max-width:64ch;line-height:1.5;}
  .slide-caption b{color:var(--ink);}
  .slide-caption .hl{color:var(--pink);text-decoration:underline;text-decoration-color:var(--pink);}

  .dots{display:flex;gap:7px;margin-top:10px;}
  .dot{width:8px;height:8px;border-radius:5px;background:var(--ink);opacity:.3;border:none;cursor:pointer;padding:0;}
  .dot.active{width:22px;background:var(--teal);opacity:1;}

  .wave-strip{height:5px;background:linear-gradient(90deg,var(--pink),var(--blue),var(--teal));flex-shrink:0;background-size:200% 200%;animation:gradShift 3s ease infinite;}

  .sky{height:46px;flex-shrink:0;overflow:hidden;position:relative;background:var(--bg-soft);}
  .sky svg{width:100%;height:100%;display:block;}
  .sky .sky-day{display:block;}
  .sky .sky-night{display:none;}
  [data-theme="dark"] .sky .sky-day{display:none;}
  [data-theme="dark"] .sky .sky-night{display:block;}

  .cloud{animation:drift linear infinite;}
  @keyframes drift{from{transform:translateX(-120px);}to{transform:translateX(920px);}}

  .star{animation:twinkle 2.6s ease-in-out infinite;}
  @keyframes twinkle{0%,100%{opacity:.15;}50%{opacity:.9;}}

  .savanna{height:58px;flex-shrink:0;overflow:hidden;position:relative;background:var(--bg-soft);}
  .savanna svg{width:100%;height:100%;display:block;}
  .sv-ink{color:var(--ink);}
  .sv-teal{color:var(--teal);}
  .sv-sun{color:var(--gold,#D9A441);}
  .footer{background:var(--navy);color:#C4CCD6;padding:8px 28px;text-align:center;font-size:11px;flex-shrink:0;}

  .modal-overlay{display:none;position:fixed;inset:0;background:rgba(10,14,20,.45);align-items:center;justify-content:center;z-index:50;padding:20px;}
  .modal-overlay.open{display:flex;}
  .modal-box{background:var(--card);border-radius:16px;max-width:640px;width:100%;max-height:90vh;overflow-y:auto;
    padding:22px 24px 24px;position:relative;box-shadow:0 20px 50px rgba(0,0,0,.25);}
  .modal-box h2{font-family:'Poppins',sans-serif;font-size:18px;color:var(--ink);margin:0 0 4px;}
  .modal-box p.sub{color:var(--muted);font-size:12.5px;margin:0 0 18px;}
  .modal-close{position:absolute;top:14px;right:16px;background:none;border:none;font-size:18px;color:var(--muted);cursor:pointer;line-height:1;}
  .feature-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;}
  .feature{border-radius:12px;padding:16px;color:#fff;min-height:96px;display:flex;flex-direction:column;justify-content:space-between;}
  .feature svg{width:22px;height:22px;stroke:#fff;fill:none;stroke-width:1.7;}
  .feature b{font-size:12.5px;font-weight:600;line-height:1.35;}
  .schools-box{max-width:720px;}
  .marquee-wrap{
    overflow:hidden;margin:14px 0 0;
    -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
    mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
  }
  .marquee-row{display:flex;gap:12px;width:max-content;animation:marqueeLeft 168s linear infinite;}
  .marquee-row.marquee-reverse{animation:marqueeRight 200s linear infinite;}
  @keyframes marqueeLeft{from{transform:translateX(0);}to{transform:translateX(-50%);}}
  @keyframes marqueeRight{from{transform:translateX(-50%);}to{transform:translateX(0);}}
  @media (prefers-reduced-motion: reduce){.marquee-row{animation:none;}}
  .marquee-wrap:hover .marquee-row{animation-play-state:paused;}

  .school-card{
    flex:0 0 auto;width:118px;display:flex;flex-direction:column;align-items:center;text-align:center;
    gap:6px;padding:12px 8px;background:var(--bg-soft);border:1px solid var(--line);border-radius:12px;
  }
  .school-logo{
    width:38px;height:38px;border-radius:50%;display:flex;align-items:center;justify-content:center;
    color:#fff;font-family:'Poppins',sans-serif;font-weight:600;font-size:12.5px;flex-shrink:0;
    position:relative;overflow:hidden;
  }
  .school-logo img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border-radius:50%;}
  .school-name{font-size:10px;font-weight:600;color:var(--ink);line-height:1.3;
    display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}
  .school-region{font-size:9px;color:var(--muted);text-transform:uppercase;letter-spacing:.03em;}

  .f1{background:linear-gradient(135deg,var(--teal),#0E8C7F);}
  .f2{background:linear-gradient(135deg,var(--blue),#1D5AA8);}
  .f3{background:linear-gradient(135deg,var(--pink),#A31A48);}
  .f4{background:linear-gradient(135deg,var(--navy),#16202E);}
  .f5{background:linear-gradient(135deg,#7A3F9E,#4E2668);}
  .f6{background:linear-gradient(135deg,#E08A2E,#B85F14);}

  /* ===============================================================
     Pages du parcours de connexion (région > département >
     établissement > connexion). Contrairement à l'accueil, ces pages
     défilent normalement (liste d'options de longueur variable).
  =============================================================== */
  body.step-body{height:auto;min-height:100vh;overflow:visible;}
  body.step-body .topbar{border-bottom:1px solid var(--line);}

  .back-link{
    display:inline-flex;align-items:center;gap:6px;color:var(--muted);text-decoration:none;
    font-size:12px;font-weight:500;background:none;border:none;cursor:pointer;padding:0;
    font-family:'IBM Plex Sans',sans-serif;
  }
  .back-link svg{width:15px;height:15px;stroke:var(--muted);fill:none;stroke-width:2;}
  .back-link:hover{color:var(--ink);}
  .back-link:hover svg{stroke:var(--ink);}

  .breadcrumb-steps{
    display:flex;align-items:center;gap:6px;flex-wrap:wrap;
    font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);
  }
  .breadcrumb-steps .sep{opacity:.5;}
  .breadcrumb-steps .done{color:var(--teal);}
  .breadcrumb-steps a.done{text-decoration:none;cursor:pointer;}
  .breadcrumb-steps a.done:hover{text-decoration:underline;}
  .breadcrumb-steps a.done:focus-visible{outline:2px solid var(--teal);outline-offset:2px;border-radius:3px;}
  .breadcrumb-steps .now{color:var(--ink);font-weight:700;}

  /* Bouton retour rapproché du contenu, juste au-dessus du fil d'Ariane,
     plutôt qu'isolé dans la barre du haut — plus facile à remarquer. */
  .step-nav-row{display:flex;align-items:center;gap:16px;margin-bottom:12px;flex-wrap:wrap;}
  .step-nav-row .back-link{flex-shrink:0;}

  /* Logo compact dans le header des pages autres que l'accueil — sert aussi
     de lien de retour à l'accueil (topbar-left, vide sur ces pages sinon). */
  .topbar-logo{display:flex;align-items:center;flex-shrink:0;}
  .topbar-logo img{height:30px;width:auto;display:block;}
  .topbar-logo:focus-visible{outline:2px solid var(--teal);outline-offset:2px;border-radius:6px;}

  /* margin-top négatif : le bloc remonte vers le décor ciel, mais reste
     assez conservateur pour que le fil d'Ariane (premier élément, juste
     après le padding-top) ne chevauche jamais le ciel — seul le blanc entre
     les deux se réduit. */
  /* flex:1 0 auto (motif "footer collant") : le bloc grandit pour occuper
     l'espace vertical restant quand le contenu est court, ce qui pousse la
     savane tout en bas de l'écran plutôt que de la laisser flotter juste
     après un contenu court. Ne rétrécit jamais sous sa taille de contenu
     (flex-basis:auto), donc reste scrollable normalement si le contenu
     dépasse la hauteur de l'écran. */
  .step-main{max-width:760px;margin:-8px auto 0;padding:28px 24px 60px;width:100%;position:relative;z-index:2;flex:1 0 auto;}
  .step-header h1{font-family:'Poppins',sans-serif;font-size:22px;margin:0 0 6px;font-weight:600;}
  .step-header .step-sub{font-size:13px;color:var(--muted);margin:0 0 24px;}

  .option-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px;}
  .option-card{
    display:flex;flex-direction:column;gap:10px;text-align:left;
    background:var(--card);border:1px solid var(--line);border-radius:14px;padding:16px;
    cursor:pointer;font-family:inherit;color:var(--ink);
    transition:transform .15s ease, box-shadow .15s ease, border-color .15s ease;
  }
  .option-card:hover{transform:translateY(-2px);box-shadow:0 8px 20px rgba(0,0,0,.08);border-color:var(--teal);}
  .option-card:focus-visible{outline:2px solid var(--teal);outline-offset:2px;}
  .option-card .oc-icon{
    width:38px;height:38px;border-radius:10px;display:flex;align-items:center;justify-content:center;
    background:linear-gradient(135deg,var(--teal),var(--blue));color:#fff;flex-shrink:0;
  }
  /* COULEURS VARIEES (2026-08-23, demande explicite). Une grille de trente
     pastilles identiques ne se parcourt pas : l'oeil n'a aucun point d'appui
     et relit chaque libelle. Six teintes suffisent a rendre les positions
     memorisables d'une visite a l'autre, sans transformer la page en
     arc-en-ciel.
     Toutes sont tirees de la palette de l'identite — teal, bleu, rose, navy,
     or — jamais de couleur inventee ici. Elles s'appliquent par un
     `data-teinte` pose au rendu (cartes de departement ET d'arrondissement),
     donc depuis un seul endroit. */
  .option-card .oc-icon[data-teinte="0"]{background:linear-gradient(135deg,var(--teal),var(--blue));}
  .option-card .oc-icon[data-teinte="1"]{background:linear-gradient(135deg,var(--blue),var(--navy));}
  .option-card .oc-icon[data-teinte="2"]{background:linear-gradient(135deg,var(--pink),var(--navy));}
  .option-card .oc-icon[data-teinte="3"]{background:linear-gradient(135deg,var(--gold),var(--pink));}
  .option-card .oc-icon[data-teinte="4"]{background:linear-gradient(135deg,var(--navy),var(--teal));}
  .option-card .oc-icon[data-teinte="5"]{background:linear-gradient(135deg,var(--teal),var(--gold));}
  .option-card .oc-icon svg{width:19px;height:19px;stroke:#fff;fill:none;stroke-width:1.8;}
  .option-card .oc-title{font-weight:600;font-size:14px;line-height:1.3;}
  .option-card .oc-sub{font-size:11.5px;color:var(--muted);}
  .option-card .oc-badge{
    align-self:flex-start;font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;
    background:rgba(31,182,166,.14);color:#0E8C7F;padding:2px 8px;border-radius:999px;
  }

  /* Carte établissement : réutilise le badge logo/initiales du carrousel accueil */
  .option-card.etab-card{flex-direction:row;align-items:center;gap:12px;}
  /* LOGO DOMINANT (2026-08-23, demande explicite). A 42 px, le logo n'etait
     qu'une vignette a cote du nom : on lisait la liste, on ne la reconnaissait
     pas. A 64 px il devient le premier element identifie, et le nom passe au
     second plan — ce qui est l'ordre naturel pour quelqu'un qui cherche SON
     etablissement, dont il connait le blason avant l'intitule administratif.
     Le nom est a peine reduit : il doit rester lisible, pas disparaitre. */
  .option-card.etab-card .school-logo{width:64px;height:64px;font-size:20px;}
  .option-card.etab-card .oc-title{font-size:13px;font-weight:600;}
  .option-card.etab-card .oc-sub{font-size:11px;}
  /* La carte respire un peu plus, sinon le logo touche les bords. */
  .option-card.etab-card{gap:14px;}
  /* Établissement non actif : grisé mais le bouton reste cliquable (demande
     explicite) — pas de disabled/pointer-events:none, juste un signal visuel. */
  .option-card.etab-card-inactive{opacity:.5;}
  .option-card.etab-card-inactive:hover{opacity:.75;}

  .empty-state{
    text-align:center;padding:40px 20px;color:var(--muted);font-size:13px;
  }

  /* Carte interactive des régions (sélection région). Statut par région
     (voir cmrRegionStats dans etabs-data.js), encodé par couleur — carte
     chaleur (Point 6, 2026-08-09) : teal, d'autant plus foncé qu'il y a
     d'établissements actifs (palier heat-low/-mid/-high calculé en JS dans
     renderRegions(), connexion-region.html) ; gris neutre = a des
     établissements mais aucun actif ; quasi blanc = aucun établissement.
     Seules les régions teal (status-active) sont cliquables. La hauteur de
     la carte est calée en JS (cmrFitMapHeight) sur l'espace réellement
     restant sous le titre, pas une fraction fixe de la fenêtre. */
  .cmr-map-wrap{display:flex;flex-direction:column;align-items:center;margin-top:4px;}
  /* Marges resserrées (2026-08-11) : chaque pixel repris au-dessus est rendu à
     la carte, dont la hauteur est calculée à partir de la place restante.
     La barre de nom garde en revanche sa hauteur réservée même invisible —
     sinon la carte sauterait à chaque survol de région. */
  .cmr-name-bar{
    margin-bottom:10px;min-height:34px;text-align:center;
    font-family:'Poppins',sans-serif;font-weight:600;font-size:14.5px;color:var(--ink);
    background:var(--card);border:1px solid var(--line);border-radius:20px;
    padding:7px 22px;opacity:0;transition:opacity .2s ease;
  }
  .cmr-name-bar.show{opacity:1;}
  /* La HAUTEUR pilote (2026-08-11, demande explicite : la carte doit occuper
     l'espace vertical laissé libre au lieu de flotter au milieu du vide).
     `--cmr-map-h` est calculée en JS d'après la place réellement disponible
     sous le titre — voir cmrFitMapHeight() dans connexion-region.html.
     `aspect-ratio` reprend les dimensions du viewBox (448x664), donc la
     largeur suit toute seule : inutile de la contraindre, et l'ancien
     `max-width:460px` bridait justement la carte à ~350px de haut sur un
     écran de bureau, quelle que soit la place libre.
     Plancher à 480px comme demandé ; `max-width:100%` garde la priorité sur
     un écran étroit, où c'est la largeur qui contraint. */
  /* Pas d'`aspect-ratio` ici : sur un bloc, `width:auto` veut dire « remplis le
     conteneur » et l'emporte sur le ratio — la carte se retrouvait étirée à la
     largeur de la page. Les DEUX dimensions sont donc posées en JS à partir de
     la hauteur disponible, ce qui est déterministe. */
  .cmr-map{width:auto;max-width:100%;overflow:visible;display:block;margin:0 auto;}

  .reg-wrap{
    transform:scale(.93);cursor:pointer;transition:transform .25s ease;
    animation-timing-function:ease-in-out;animation-iteration-count:infinite;
  }
  .cmr-fl1{animation-name:cmrFloat1;} .cmr-fl2{animation-name:cmrFloat2;}
  .cmr-fl3{animation-name:cmrFloat3;} .cmr-fl4{animation-name:cmrFloat4;}
  @keyframes cmrFloat1{0%,100%{transform:scale(.93) translate(0,0);}50%{transform:scale(.93) translate(1.5px,-2.5px);}}
  @keyframes cmrFloat2{0%,100%{transform:scale(.93) translate(0,0);}50%{transform:scale(.93) translate(-2px,-1.5px);}}
  @keyframes cmrFloat3{0%,100%{transform:scale(.93) translate(0,0);}50%{transform:scale(.93) translate(1px,2px);}}
  @keyframes cmrFloat4{0%,100%{transform:scale(.93) translate(0,0);}50%{transform:scale(.93) translate(-1.5px,2px);}}

  /* COULEURS PLEINES, et non `fill:url(#grad-...)` — correction du 2026-08-11.
     Ces dégradés sont définis dans le <defs> de connexion-region.html : la
     couleur d'une région dépendait donc d'un identifiant vivant dans le HTML.
     Que le HTML et cette feuille servis divergent d'une version — ce qui
     arrive après un déploiement, le CDN de l'hébergeur pouvant resservir l'un
     des deux périmé pendant plusieurs minutes — et `url(#...)` ne résout plus
     rien : la région devient BLANCHE, donc invisible, et comme seules les
     régions actives sont cliquables, la carte paraît morte. Panne signalée
     deux fois. Une couleur pleine ne peut pas manquer sa cible.
     Teintes reprises au milieu de chaque ancien dégradé : à l'échelle de la
     carte, le rendu est le même, et les trois paliers de densité restent
     parfaitement distincts. */
  .reg-wrap.status-active .region, .reg-wrap.status-active .region-shadow{fill:#3ECBB7;}
  .reg-wrap.status-active.heat-low .region, .reg-wrap.status-active.heat-low .region-shadow{fill:#9FF0E0;}
  .reg-wrap.status-active.heat-mid .region, .reg-wrap.status-active.heat-mid .region-shadow{fill:#3ECBB7;}
  .reg-wrap.status-active.heat-high .region, .reg-wrap.status-active.heat-high .region-shadow{fill:#199991;}
  .reg-wrap.status-inactive .region, .reg-wrap.status-inactive .region-shadow{fill:#CED4DC;}
  .reg-wrap.status-none .region, .reg-wrap.status-none .region-shadow{fill:#EEF1F4;}

  .reg-wrap:hover, .reg-wrap.active{animation:none;}
  .reg-wrap.status-active:hover, .reg-wrap.status-active.active{transform:scale(1.05);}
  .reg-wrap.status-inactive, .reg-wrap.status-none{cursor:not-allowed;}

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

  /* Noms de région annotés directement sur la carte (PC uniquement — sur
     mobile la légende ci-dessous prend le relais, les libellés seraient
     illisibles sur les petites régions). Élément frère des tracés dans le
     même <g> : hérite donc du même flottement/animation ("flottants"). */
  .region-label{
    font-family:'Poppins',sans-serif;font-weight:600;font-size:11px;
    fill:#fff;pointer-events:none;paint-order:stroke fill;
    stroke:rgba(15,25,40,.45);stroke-width:3px;stroke-linejoin:round;
  }
  @media (max-width: 640px){.region-label{display:none;}}

  /* Légende mobile : les cartes SVG sont trop petites au doigt pour les
     régions étroites — sur petit écran, une liste texte cliquable des seules
     régions actives (bleues) prend le relais, au-dessus de la carte. */
  .cmr-legend{display:none;}
  @media (max-width: 640px){
    .cmr-legend{
      order:-1;
      display:flex;flex-wrap:wrap;gap:8px;justify-content:center;
      margin:0 0 20px;padding:0 4px;
    }
    .cmr-legend button{
      font-family:inherit;font-size:12.5px;font-weight:600;color:#fff;
      background:linear-gradient(135deg,#2E7BD9,#1F5FA8);border:none;border-radius:999px;
      padding:8px 16px;cursor:pointer;transition:transform .15s ease,box-shadow .15s ease;
    }
    .cmr-legend button:hover, .cmr-legend button:focus-visible{
      transform:translateY(-1px);box-shadow:0 4px 12px rgba(46,123,217,.35);outline:none;
    }
  }

  /* Page de connexion (formulaire) */
  .login-shell{max-width:400px;margin:-8px auto 0;padding:28px 24px 0;position:relative;z-index:2;flex:1 0 auto;}
  .etab-context{
    display:flex;align-items:center;gap:12px;background:var(--bg-soft);border:1px solid var(--line);
    border-radius:14px;padding:14px 16px;margin-bottom:22px;
  }
  /* Meme raison sur l'ecran de connexion : c'est le logo qui confirme d'un
     coup d'oeil qu'on est au bon endroit avant de taper son mot de passe. */
  .etab-context .school-logo{width:56px;height:56px;font-size:18px;flex-shrink:0;}
  .etab-context .ec-name{font-weight:600;font-size:13px;line-height:1.3;}
  .etab-context .ec-region{font-size:11px;color:var(--muted);}
  .etab-context .ec-change{margin-left:auto;font-size:11px;color:var(--teal);font-weight:600;background:none;border:none;cursor:pointer;white-space:nowrap;}

  .login-form .field{margin-bottom:14px;}
  .login-form label{display:block;font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin-bottom:6px;}
  .login-form input{
    width:100%;background:var(--bg-soft);border:1px solid var(--line);border-radius:10px;
    padding:11px 13px;font-size:14px;color:var(--ink);font-family:'IBM Plex Sans',sans-serif;
  }
  .login-form input:focus-visible{outline:2px solid var(--teal);outline-offset:1px;}
  .pass-field-wrap{position:relative;}
  .pass-field-wrap input{padding-right:38px;width:100%;}
  .pass-toggle-btn{
    position:absolute;top:50%;right:8px;transform:translateY(-50%);
    background:none;border:none;padding:4px;cursor:pointer;color:var(--muted);
    display:flex;align-items:center;justify-content:center;
  }
  .pass-toggle-btn:hover{color:var(--teal);}
  .pass-toggle-btn .icon-eye-off{display:none;}
  .pass-toggle-btn.showing .icon-eye{display:none;}
  .pass-toggle-btn.showing .icon-eye-off{display:block;}
  .login-form .btn-submit{
    width:100%;font-family:'Poppins',sans-serif;color:#fff;font-weight:600;
    padding:12px;border-radius:22px;font-size:14px;border:none;cursor:pointer;margin-top:6px;
    background:linear-gradient(135deg,var(--teal),var(--blue));box-shadow:0 6px 16px rgba(31,182,166,.28);
    display:flex;align-items:center;justify-content:center;gap:8px;
    transition:opacity .2s ease;
  }
  /* ---- Animation de connexion (Point 4, proposition n°2 "Clé qui tourne",
     choisie 2026-08-10) — le bouton passe en chargement pendant l'appel
     réseau réel (/api/login, voir <script> en bas de page), aujourd'hui
     totalement inerte pendant cette attente. Au succès, un cadenas apparaît
     au centre de l'écran et se déverrouille (l'anse pivote) pendant que le
     formulaire s'efface en fondu-flou, juste avant la redirection vers le
     tableau de bord. */
  .btn-submit-spinner{
    display:none;width:14px;height:14px;border-radius:50%;flex-shrink:0;
    border:2px solid rgba(255,255,255,.4);border-top-color:#fff;
    animation:loginBtnSpin .7s linear infinite;
  }
  .btn-submit.is-loading{opacity:.85;cursor:default;pointer-events:none;}
  .btn-submit.is-loading .btn-submit-spinner{display:block;}
  @keyframes loginBtnSpin{to{transform:rotate(360deg);}}

  .login-unlock{
    position:absolute;top:50%;left:50%;z-index:5;width:60px;height:60px;
    margin:-30px 0 0 -30px;color:var(--teal);opacity:0;pointer-events:none;
    transform:scale(.6);transition:opacity .3s ease,transform .3s ease;
  }
  .login-unlock svg{width:100%;height:100%;filter:drop-shadow(0 6px 14px rgba(31,182,166,.35));}
  .login-unlock-shackle{transform-origin:12px 8px;transition:transform .5s cubic-bezier(.4,0,.2,1) .35s;}
  .login-unlock.is-active{opacity:1;transform:scale(1);}
  .login-unlock.is-active .login-unlock-shackle{transform:rotate(35deg) translateY(-2px);}

  .login-form.is-success{opacity:0;filter:blur(4px);pointer-events:none;transition:opacity .35s ease .5s,filter .35s ease .5s;}

  @media (prefers-reduced-motion: reduce){
    .btn-submit-spinner,.login-unlock,.login-unlock-shackle,.login-form{transition:none !important;animation:none !important;}
  }
  .login-foot-note{text-align:center;font-size:11.5px;color:var(--muted);margin-top:18px;display:flex;align-items:center;justify-content:center;gap:6px;}
  .login-foot-note .dot{width:5px;height:5px;border-radius:50%;background:#6fae7c;display:inline-block;}

  /* Connexion réelle (Lycée de Wack uniquement, voir js/wack-login-data.js) */
  .login-demo-hint{text-align:center;font-size:11.5px;color:var(--muted);margin-top:10px;padding:8px 12px;background:var(--bg-soft);border-radius:8px;}
  .login-notbuilt{margin-top:14px;padding:14px 16px;border-radius:10px;background:var(--bg-soft);border:1px solid var(--line);font-size:12.5px;color:var(--ink);text-align:center;}
  .login-notbuilt b{color:var(--pink);}
  .login-error{margin-top:10px;padding:8px 12px;border-radius:8px;background:rgba(214,38,94,.1);color:var(--pink);font-size:12.5px;text-align:center;}
/* ---- Connexion impossible sans établissement (2026-08-11, correction du
   bug « connexion dans le vide → établissement aléatoire », voir
   js/etab-context.js) : les champs et le bouton sont réellement `disabled`
   en JS ; ce style rend l'état visible au lieu de laisser un formulaire
   d'apparence normale qui ne répond pas. ---- */
.login-form.is-locked .field input,
.login-form.is-locked .btn-submit{opacity:.5;cursor:not-allowed;}
.empty-state-hint{display:inline-block;margin-top:6px;font-size:12.5px;opacity:.75;line-height:1.45;}

/* ===========================================================================
   BANDE DE PREUVE — chiffres réels + ruban d'établissements (2026-08-25)
   ===========================================================================
   POURQUOI ELLE EXISTE. Un utilisateur déjà connecté a cru que School Editor
   « ne fait que les bulletins » — parce que c'est le seul module que son
   établissement avait ouvert. La page d'accueil ne le contredisait nulle
   part : elle montrait des NOMS d'établissements (« il y en a plusieurs »)
   et jamais l'échelle réelle du service.

   Trois nombres et une phrase de croissance disent en une seconde ce qu'un
   ruban de noms ne dit pas : combien d'établissements, combien d'élèves,
   combien d'enseignants — et depuis quand.

   L'ANNÉE COURANTE N'EST JAMAIS ÉCRITE (demande explicite). Elle vieillit mal
   à l'écran : lue en août, « 2025/2026 » ressemble à des chiffres périmés
   alors que ce sont les plus récents qui existent. Seule l'année de DÉPART
   est affichée, parce qu'elle raconte le chemin parcouru au lieu de dater
   la page.

   Les valeurs viennent de /api/vitrine-stats, jamais du HTML : rien n'est
   figé ici, la bande se met à jour toute seule à chaque rentrée. */
.proof{
  /* Posée SUR la savane (voir .ground) : le fond n'est plein que sur la
     moitié haute — les chiffres et la phrase, qui doivent rester nets — puis
     se fond vers rien sur la moitié basse, là où passe le ruban. C'est ce
     fondu qui laisse apercevoir le décor derrière les logos.
     Plus de bordures : elles couperaient la savane en deux. */
  position:relative;z-index:2;flex-shrink:0;
  background:linear-gradient(to bottom,
    var(--bg-soft) 0%,
    var(--bg-soft) 46%,
    rgba(var(--bg-soft-rgb),0.55) 72%,
    rgba(var(--bg-soft-rgb),0) 100%);
}
.proof-inner{max-width:1120px;margin:0 auto;padding:9px 28px 7px;}
.proof-figs{display:flex;justify-content:center;align-items:flex-end;gap:30px;flex-wrap:wrap;}
.proof-fig{display:flex;flex-direction:column;align-items:center;line-height:1;}
.proof-fig b{
  font-family:'Poppins',sans-serif;font-size:23px;font-weight:600;letter-spacing:-.01em;
  font-variant-numeric:tabular-nums;
}
.proof-fig[data-teinte="0"] b{color:var(--teal);}
.proof-fig[data-teinte="1"] b{color:var(--pink);}
.proof-fig[data-teinte="2"] b{color:var(--blue);}
.proof-fig span{
  font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.07em;
  margin-top:4px;font-weight:600;
}
/* Point de départ de l'histoire — la seule année écrite sur cette page. */
.proof-since{
  text-align:center;font-size:11.5px;color:var(--muted);margin:7px 0 0;line-height:1.45;
}
.proof-since b{color:var(--ink);font-weight:600;}

/* Ruban d'établissements. Il défilait déjà, mais UNIQUEMENT dans une fenêtre
   qu'il fallait penser à ouvrir : la preuve sociale n'était vue que par les
   visiteurs déjà convaincus. Ici elle est visible sans un clic, et le ruban
   reste cliquable pour ouvrir la liste complète. */
.etab-ribbon{
  margin-top:7px;padding-bottom:3px;overflow:hidden;cursor:pointer;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
}
.ribbon-row{display:flex;align-items:flex-start;gap:16px;width:max-content;animation:ribbonLeft 90s linear infinite;}
@keyframes ribbonLeft{from{transform:translateX(0);}to{transform:translateX(-50%);}}
.etab-ribbon:hover .ribbon-row,.etab-ribbon:focus-visible .ribbon-row{animation-play-state:paused;}
.etab-ribbon:focus-visible{outline:2px solid var(--teal);outline-offset:2px;border-radius:8px;}
.ribbon-item{
  flex:0 0 auto;width:74px;display:flex;flex-direction:column;align-items:center;
  gap:4px;text-align:center;
}
/* Le logo est la raison d'être du ruban : un chef d'établissement reconnaît
   le blason d'un confrère bien avant de lire l'intitulé administratif. Il
   était rendu à 38 px dans une fenêtre fermée — ici il porte la bande. */
.ribbon-item .school-logo{width:36px;height:36px;font-size:12px;}
.ribbon-name{
  /* Les noms passent devant la savane : le halo de la couleur de fond les
     décolle des silhouettes d'arbres sans poser de rectangle opaque, qui
     reboucherait justement ce qu'on vient d'ouvrir. */
  text-shadow:0 1px 2px var(--bg-soft),0 0 4px var(--bg-soft);
  font-size:8.5px;color:var(--ink);opacity:.75;line-height:1.25;font-weight:600;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  height:21px;
}
@media (prefers-reduced-motion: reduce){.ribbon-row{animation:none;}}

@media (max-width:820px){
  .proof-inner{padding:8px 16px 6px;}
  .proof-figs{gap:18px;}
  .proof-fig b{font-size:19px;}
  .proof-fig span{font-size:9px;letter-spacing:.05em;}
  .proof-since{font-size:10.5px;}
  .ribbon-item{width:64px;}
  .ribbon-item .school-logo{width:32px;height:32px;font-size:11px;}
}

/* En-tête de la fenêtre « Établissements actifs » : les mêmes chiffres, plus
   la ligne de croissance. La fenêtre servait une liste sans échelle ; on lui
   donne d'abord l'échelle, la liste ensuite. */
.schools-stats{
  display:flex;justify-content:center;gap:26px;flex-wrap:wrap;
  padding:12px 0 10px;margin-top:4px;border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
}
.schools-growth{text-align:center;font-size:12px;color:var(--muted);margin:10px 0 0;line-height:1.5;}
.schools-growth b{color:var(--ink);font-weight:600;}

/* Chapeau FIXE au-dessus des volets (2026-08-25). Il ne tourne pas avec eux :
   c'est la phrase qui corrige le malentendu (« ça ne fait que les bulletins »),
   elle doit être lisible quel que soit le volet affiché à la seconde où le
   visiteur pose les yeux sur la page. Les six volets qui défilent en dessous
   ne font ensuite que la démontrer, domaine par domaine. */
.slide-kicker{
  font-family:'Poppins',sans-serif;font-size:10.5px;font-weight:600;
  text-transform:uppercase;letter-spacing:.1em;color:var(--pink);
  margin:0 0 5px;line-height:1.3;
}
@media (max-width:820px){
  .slide-kicker{font-size:9.5px;letter-spacing:.07em;}
}

/* ---- Fenêtre « Ce que School Editor gère » (2026-08-25) -------------------
   Elle ne listait que des QUALITÉS (hors connexion, mobilité, horaires
   libres) et pas un seul domaine métier — elle donnait donc raison au
   visiteur qui croit que le service se limite aux bulletins. Les huit
   pastilles ci-dessous nomment les domaines réellement construits ; les six
   cartes colorées d'origine restent en dessous, elles répondent à une autre
   question (« et si je n'ai pas de connexion ? »). */
.domain-intro{
  font-size:12.5px;color:var(--ink);background:var(--bg-soft);border:1px solid var(--line);
  border-radius:10px;padding:10px 13px;margin:0 0 14px;line-height:1.5;
}
.domain-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:9px;margin-bottom:20px;}
.domain{
  background:var(--bg-soft);border:1px solid var(--line);border-radius:11px;
  padding:13px 8px;display:flex;flex-direction:column;align-items:center;gap:8px;text-align:center;
}
.domain svg{width:22px;height:22px;fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;flex-shrink:0;}
.domain[data-teinte="0"] svg{stroke:var(--teal);}
.domain[data-teinte="1"] svg{stroke:var(--pink);}
.domain[data-teinte="2"] svg{stroke:var(--blue);}
.domain[data-teinte="3"] svg{stroke:var(--gold);}
.domain b{font-size:10.5px;font-weight:600;color:var(--ink);line-height:1.3;}
/* Séparateur entre « ce que ça gère » et « et partout, tout le temps » : deux
   questions différentes, deux blocs, une frontière lisible entre les deux. */
.feat-sep{
  font-family:'Poppins',sans-serif;font-size:10.5px;font-weight:600;text-transform:uppercase;
  letter-spacing:.1em;color:var(--muted);margin:0 0 11px;display:flex;align-items:center;gap:10px;
}
.feat-sep::after{content:"";flex:1;height:1px;background:var(--line);}
@media (max-width:820px){
  .domain-grid{grid-template-columns:repeat(2,1fr);}
  .domain b{font-size:11px;}
}

/* ===========================================================================
   GUIDE AU DOIGT (2026-08-25) — voir js/guide-doigt.js
   ===========================================================================
   Les quatre réglages de la barre du haut sont des ICÔNES SEULES sur mobile
   (leurs libellés sont masqués par la requête média à 820 px plus haut). Un
   visiteur qui ne les reconnaît pas ne les essaie jamais. Le doigt les montre
   une fois à l'ouverture, deux secondes chacun, puis s'efface — et s'efface
   aussi au premier geste du visiteur : il guide qui hésite, il ne gêne pas
   qui sait déjà. */
.guide-doigt{
  position:fixed;inset:0;pointer-events:none;z-index:900;
  opacity:0;transition:opacity .35s ease;
}
.guide-doigt.gd-visible{opacity:1;}

/* Anneau posé sur le bouton lui-même : c'est lui qui DÉSIGNE, le doigt ne
   fait que venir le confirmer. */
.gd-halo{
  position:absolute;top:0;left:0;width:52px;height:52px;border-radius:50%;
  border:2px solid var(--teal);background:rgba(31,182,166,.13);
  transition:transform .45s cubic-bezier(.4,0,.2,1);
  animation:gdPulse 1.7s ease-out infinite;
}
@keyframes gdPulse{
  0%{box-shadow:0 0 0 0 rgba(31,182,166,.35);}
  70%{box-shadow:0 0 0 14px rgba(31,182,166,0);}
  100%{box-shadow:0 0 0 0 rgba(31,182,166,0);}
}

/* Couleurs FIXES et non tokenisées : la main doit rester lisible sur les deux
   thèmes, et un `var(--card)` la rendrait sombre sur fond sombre. */
.gd-main{position:absolute;top:0;left:0;transition:transform .45s cubic-bezier(.4,0,.2,1);}
.gd-main svg{display:block;filter:drop-shadow(0 3px 7px rgba(0,0,0,.3));}
.gd-trait,.gd-paume{fill:#F7FAFB;stroke:#26344A;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round;}
/* Le tap joue sur `margin-top` et non sur `transform` : le transform porte
   déjà la POSITION, écrite par le script à chaque étape — une animation
   dessus effacerait le déplacement. */
.guide-doigt.gd-tape .gd-main{animation:gdTape .55s ease-in-out 2;}
@keyframes gdTape{0%,100%{margin-top:0;}50%{margin-top:-9px;}}

.gd-bulle{
  position:absolute;top:0;left:0;white-space:nowrap;
  background:linear-gradient(135deg,var(--teal),var(--blue));color:#fff;
  font-family:'Poppins',sans-serif;font-size:11.5px;font-weight:600;letter-spacing:.01em;
  padding:7px 13px;border-radius:14px;box-shadow:0 6px 18px rgba(0,0,0,.22);
  transition:transform .45s cubic-bezier(.4,0,.2,1);
}

/* ===========================================================================
   LA BANDE DE PREUVE PASSE SUR LA SAVANE (2026-08-25)
   ===========================================================================
   Demande explicite : la bande descend au niveau de la savane et la
   chevauche, et le ruban d'établissements devient transparent pour qu'on
   aperçoive le décor derrière les logos.

   Le fond opaque ne couvre donc que la MOITIÉ HAUTE de la bande — les
   chiffres et la phrase de croissance, qui doivent rester nets — puis se
   fond vers rien sur la moitié basse, exactement là où passe le ruban. La
   savane, elle, garde sa hauteur et sa place en pied de page.

   `--bg-soft-rgb` existe pour ce dégradé : on ne peut pas dériver un rgba()
   d'une variable écrite en hexadécimal, et un `transparent` nu se dégrade
   vers du noir transparent sur certains moteurs — ce qui grise le fondu. */
.ground{
  position:relative;flex-shrink:0;background:var(--bg-soft);
  min-height:58px;   /* la savane seule, quand la bande ne s'affiche pas */
}
.ground .savanna{position:absolute;left:0;right:0;bottom:0;z-index:1;}
