/* Mathslab - feuille de style principale */
/* ------------------------------------------------------------------
   Palette "Aurore" — tiree de img/fond.jpg.

   Le fond est un degrade corail -> rose magenta -> violet -> bleu ciel.
   Les quatre couleurs de niveau en descendent, DANS L'ORDRE DE L'IMAGE,
   et sont etagees en luminosite (0.062 < 0.094 < 0.133 < 0.174, soit des
   rapports de 1,52 / 1,42 / 1,31) : la distinction des niveaux survit
   ainsi au daltonisme, ou une famille chromatique commune se resserre.

   L'ancienne palette echouait en accessibilite : --c6 tombait a 3,3:1 sur
   blanc et --c5 a 4,3:1, sous le seuil AA de 4,5:1. Toutes les valeurs
   ci-dessous sont >= 4,5:1 sur la plaque blanche des titres.
   ------------------------------------------------------------------ */
:root {
    --primary: #3B1E5E;                      /* prune profond, 13,7:1 sur blanc */
    --sidebar: rgba(46, 22, 64, 0.82);       /* verre prune : le degrade passe au travers */
    --bg: #ecf0f1;
    --c6: #108276;   /* teal      4,7:1 */
    --c5: #1565C0;   /* bleu      5,8:1 */
    --c4: #6A1B9A;   /* violet    9,4:1 */
    --c3: #A81252;   /* framboise 7,3:1 */
    --cd: #F0A020;   /* l'orange des Demonstrations : identite conservee */

    /* --cd plafonne a 2,2:1 sur du blanc : inutilisable pour du TEXTE, meme en
       grand. --cd-txt en est la variante assombrie (5,9:1). --cd reste l'orange
       d'identite pour les liseres et les bordures de carte .bd, ou le contraste
       texte ne joue pas. */
    --cd-txt: #8A5A00;

    /* Anneau de focus : jaune vif, il ressort sur le verre prune de la sidebar,
       sur les boutons et sur le blanc des cartes. */
    --focus: #FFD400;
}
* { box-sizing: border-box; }

body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    margin: 0;
    display: flex;
    /* Menu HORIZONTAL : la barre passe en haut, le contenu occupe toute la
       largeur en dessous. Les 270 px que prenait la sidebar reviennent aux
       outils larges (Thales, la potence, les triangles de trigonometrie). */
    flex-direction: column;
    height: 100vh;
    /* Fond rapatrie en local (img/fond.jpg) : l'outil marche en file:// et hors ligne,
       meme si mathsmorant.fr est injoignable. La couleur de repli evite le fond blanc. */
    background: #24455f url('../img/fond.jpg') no-repeat center center fixed;
    background-size: cover;
    color: #333; 
    overflow: hidden; 
}

/* La barre de navigation. L'identifiant #sidebar est conserve : il est cible
   par core.js (querySelector sur .nav-btn) et par la media query mobile, le
   renommer aurait touche du JS pour un gain nul. */
#sidebar {
    flex: none;                      /* la barre ne s'etire pas : #main prend le reste */
    width: 100%;
    background: var(--sidebar);
    color: white;
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 2px;
    padding: 0 14px;
    overflow-x: auto;                /* si les onglets depassent, on fait defiler */
    overflow-y: hidden;
    z-index: 10;
    box-shadow: 0 4px 15px rgba(0,0,0,0.3);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid rgba(255,255,255,0.08);
}
/* Logo : la tuile au radical + le mot-symbole.
   Le mot reste BLANC (10:1 sur le verre prune, meme au-dessus de la zone la
   plus claire du fond). Le remplir du degrade tombait a 2,8-3,8:1 : le degrade
   ne vit donc que dans la tuile, ou il ne porte aucun texte. */
.logo {
    flex: none;
    padding: 10px 16px 10px 4px;
    margin-right: 8px;
    display: flex;
    align-items: center;
    gap: 11px;
    border-right: 1px solid rgba(255,255,255,0.14);
    color: #fff;
}
.logo img {
    flex: none;
    width: 36px;
    height: 36px;
    border-radius: 9px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.35);
}
/* Sous 900 px, le mot-symbole s'efface : la tuile suffit a l'identite, et les
   cinq onglets tiennent alors sans defilement horizontal. Le seuil est plus
   haut que celui du mobile (768) parce que la gene apparait avant. */
@media (max-width: 900px) {
    .logo span { display: none; }
}
.logo span {
    font-size: 1.25rem;
    font-weight: 900;
    letter-spacing: .5px;
    white-space: nowrap;
    text-shadow: 0 2px 4px rgba(0,0,0,0.5);
}
.nav-btn {
    flex: none;                      /* dans une rangee, les onglets ne se compriment pas */
    white-space: nowrap;
    display: flex;
    align-items: center;
    gap: 9px;
    margin: 8px 3px;
    padding: 11px 16px;
    border: none;
    background: transparent;
    color: #d5d9dd;                  /* 8,3:1 sur le verre prune */
    font-size: 1rem;
    cursor: pointer;
    transition: all 0.25s ease;
    border-radius: 10px;
    font-weight: 500;
}
/* Le deplacement se fait vers le HAUT, pas vers la droite : dans une barre
   horizontale, un decalage lateral bousculerait les onglets voisins. */
.nav-btn:hover {
    background: rgba(255,255,255,0.10);
    color: white;
    transform: translateY(-2px);
}
/* Le bouton actif reprend le degrade d'identite, mais dans les versions
   SOMBRES des couleurs de niveau (framboise -> violet -> bleu). Les teintes
   claires du fond auraient donne 3,2:1 pour le libelle blanc ; celles-ci
   tiennent 5,8:1 au minimum. */
.nav-btn.active {
    background: linear-gradient(135deg, var(--c3) 0%, var(--c4) 55%, var(--c5) 100%);
    color: white;
    font-weight: bold;
    box-shadow: 0 4px 12px rgba(59,30,94,0.45);
}

#main { 
    flex: 1; 
    overflow-y: auto; 
    padding: 40px; 
    position: relative; 
    padding-bottom: 80px; 
    /* Verre BLANC et non plus gris : le gris a 45 % eteignait le degrade du fond,
       qui est la seule identite visuelle de la page. Le blanc laisse passer les
       couleurs tout en gardant les cartes lisibles par-dessus. */
    background: rgba(255, 255, 255, 0.55);
    backdrop-filter: blur(8px); /* Effet verre dépoli */
}

.section { display: none; animation: fadeIn 0.3s; }
.section.active { display: block; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }

/* ------------------------------------------------------------------
   Titres de section : lisibilite en projection.
   Le h1 posait la couleur du niveau a meme #main (verre depoli sur la photo) :
   2,1:1 pour le vert, 1,4:1 pour l'orange, tres loin du 3:1 exige pour du
   grand texte. On pose le titre sur une plaque claire opaque, avec un lisere
   gauche qui garde le code couleur. Le border-bottom #bdc3c7 d'avant valait
   1,1:1 sur ce fond : il ne se voyait pas, il est supprime.
   La couleur vient toujours du style="color:var(--cX)" en ligne d'index.html,
   d'ou le currentColor du lisere.
   ------------------------------------------------------------------ */
h1 {
    display: inline-block;
    margin: 0 0 30px;
    padding: 10px 20px;
    background: rgba(255, 255, 255, 0.92);
    border-left: 8px solid currentColor;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
/* Le titre des Demonstrations porte style="color:var(--cd)" en ligne, qu'on ne
   peut pas battre en specificite sans !important : on redefinit --cd LOCALEMENT
   sur ce seul titre pour que la valeur resolue soit la variante sombre.
   Le lisere, lui, reprend explicitement l'orange d'identite. */
#nd h1 { --cd: var(--cd-txt); border-left-color: #F0A020; }

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 20px; }
.card { background: white; border-radius: 8px; padding: 25px; box-shadow: 0 4px 6px rgba(0,0,0,0.05); border-top: 5px solid #ccc; display: flex; flex-direction: column; }
.card h3 { margin-top: 0; margin-bottom: 10px; color: var(--primary); }
/* Le gris #7f8c8d ne valait que 3,5:1 sur le blanc de la carte, sous le seuil
   de 4,5:1 pour du texte de cette taille. On assombrit (7:1) et on monte a
   0,95rem : le texte reste secondaire face au h3, mais il se lit de loin. */
.card p { flex-grow: 1; color: #4f5b5c; font-size: 0.95rem; margin-bottom: 20px; }

/* ------------------------------------------------------------------
   Pastilles de type d'outil (contrat 3 : index.html pose les <span>).
   align-self indispensable : la carte est un flex column, un enfant
   inline-block y devient un item etire sur toute la largeur.
   Contrastes : 7,6:1 (exercice) et 6,8:1 (manipulation) sur leur propre fond.
   ------------------------------------------------------------------ */
.tag {
    align-self: flex-start;
    display: inline-block;
    margin-bottom: 10px;
    padding: 3px 9px;
    border-radius: 4px;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    line-height: 1.5;
}
.tag-ex { background: #e8f1fb; color: #1b4f72; }
.tag-manip { background: #eaf5ef; color: #17603f; }

.b6 { border-top-color: var(--c6); } .b5 { border-top-color: var(--c5); }
.b4 { border-top-color: var(--c4); } .b3 { border-top-color: var(--c3); } .bd { border-top-color: var(--cd); }

/* min-height 44px : cible tactile minimale au doigt (les deux boutons sont
   dans un flex row en align-items:stretch, ils gardent la meme hauteur). */
.btn-open { background: var(--primary); color: white; border: none; padding: 12px; border-radius: 6px; cursor: pointer; font-weight: bold; transition: 0.2s; flex: 1; min-height: 44px; }
.btn-open:hover { transform: scale(0.98); opacity: 0.9; }

/* Bordure renforcee : #bdc3c7 sur carte blanche valait 1,8:1, le bouton
   n'avait pas de contour visible. #8ba0a3 (3,1:1) le dessine sans en faire
   un concurrent du bouton Ouvrir, qui reste le seul bouton plein. */
.btn-copy { background: #ecf0f1; color: var(--primary); border: 1px solid #8ba0a3; border-radius: 6px; cursor: pointer; padding: 0 15px; min-height: 44px; font-size: 1.2rem; transition: 0.2s; display: flex; align-items: center; justify-content: center; }
.btn-copy:hover { background: #bdc3c7; transform: scale(0.98); }

#modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.85); z-index: 1000; justify-content: center; align-items: center; }
/* Contrat 4 : core.js pose/retire la classe sur <body> a l'ouverture de la
   modale. Le selecteur body.modal-ouverte est plus specifique que le simple
   body{overflow:auto} du bloc responsive : il gagne dans les deux dispositions
   et le fond ne defile plus derriere l'overlay. */
body.modal-ouverte { overflow: hidden; }
/* overscroll-behavior:contain : arrive en butee de la boite, le geste ne
   se transmet plus a la page derriere l'overlay. */
.modal-box { background: white; width: 95%; max-width: 900px; padding: 30px; border-radius: 12px; position: relative; text-align: center; max-height: 95vh; overflow-y: auto; overscroll-behavior: contain; box-shadow: 0 10px 30px rgba(0,0,0,0.5); }

/* La croix de fermeture est la commande la plus utilisee de l'application :
   elle ne faisait qu'environ 20x37 px, sous le minimum tactile. On lui donne
   un corps de 44x44 avec le signe centre. */
.close-btn {
    position: absolute; top: 10px; right: 12px;
    width: 44px; height: 44px;
    display: flex; align-items: center; justify-content: center;
    font-size: 2rem; line-height: 1;
    cursor: pointer; border: none; background: none; border-radius: 8px;
    color: #7f8c8d;
}
.close-btn:hover { color: var(--c3); background: #f2f4f4; }

.workspace { background: #f8f9fa; border: 2px dashed #bdc3c7; padding: 20px; border-radius: 8px; margin-top: 20px; min-height: 300px; display: flex; flex-direction: column; align-items: center; justify-content: center; overflow: hidden; }
/* Blanc sur #3498db ne valait que 3,2:1 pour du texte de 1rem : bleu assombri
   a #2471a3 (5,3:1). min-height 44px pour la cible tactile. */
.tool-btn { background: #2471a3; color: white; border: none; padding: 10px 20px; min-height: 44px; border-radius: 5px; cursor: pointer; font-size: 1rem; margin: 5px; transition: 0.2s; }
/* Blanc sur #bdc3c7 valait 1,8:1, illisible en projection : gris assombri
   a 4,5:1, assez sombre pour se lire, assez terne pour rester "inactif". */
.tool-btn:disabled { background: #6c7a7d; cursor: not-allowed; }
input[type="range"] { width: 100%; margin: 10px 0; cursor: pointer; }
input[type="number"] { padding: 8px; font-size: 1.1rem; border: 1px solid #ccc; border-radius: 4px; }

/* ------------------------------------------------------------------
   Barre de recherche des outils.

   Avant : le champ etait pose nu sur le verre depoli, SANS aucune regle
   de placement (le style precedent s'en remettait a index.html, qui n'en
   posait pas non plus). Resultat : il touchait le titre de section juste
   dessous et n'appartenait a aucun des vocabulaires visuels de la page.

   Maintenant : meme grammaire que les h1 et les cartes (plaque blanche,
   rayon 10px, liosere de couleur au focus), une loupe pour dire ce que
   c'est sans texte, de l'air dessous, et le compte de resultats en
   pastille a cote plutot qu'en texte nu dessous.

   Volontairement AUCUN box-shadow sur #q-outils : l'anneau de focus
   d'accessibilite (plus bas) passe par box-shadow sur `input:focus-visible`,
   dont la specificite (0,1,1) perdrait contre un selecteur d'ID (1,0,0).
   Les etats se jouent donc sur la bordure, jamais sur l'ombre.
   ------------------------------------------------------------------ */
.recherche {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px 14px;
    margin: 0 0 34px;            /* l'air qui manquait entre le champ et le titre */
}

#q-outils {
    flex: 1 1 320px;
    max-width: 460px;
    /* 46px a gauche : la place de la loupe, pour que le texte ne passe pas dessus */
    padding: 12px 16px 12px 46px;
    min-height: 48px;
    font-size: 1.05rem;
    color: var(--primary);
    background: #fff
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235f6d6e' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cline x1='16.5' y1='16.5' x2='21' y2='21'/%3E%3C/svg%3E")
        no-repeat 15px center;
    background-size: 19px 19px;
    border: 2px solid #b3c1c3;
    border-radius: 10px;
    transition: border-color 0.15s;
}
#q-outils::placeholder { color: #6f7f81; }
#q-outils:hover { border-color: #8ba0a3; }
/* Liosere bleu au focus souris. Au clavier, l'anneau jaune du contrat 5
   prend le relais : on ne le concurrence pas. */
#q-outils:focus:not(:focus-visible) { border-color: var(--c5); }

/* Compte de resultats : pastille, et seulement quand il y a quelque chose
   a dire (:empty couvre l'etat "champ vide" pilote par filtrerOutils). */
#q-compte:not(:empty) {
    padding: 7px 14px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.94);
    border: 1px solid #cfd8d9;
    font-size: 0.92rem;
    font-weight: bold;
    color: var(--primary);
    white-space: nowrap;
}
/* Recherche infructueuse : on le dit avec autre chose que du gris neutre. */
#q-compte.vide {
    background: #fdecea;
    border-color: #e6b0aa;
    color: #922b21;
}

/* #95a5a6 sur la plaque blanche a 90 % : 2,2:1. Decoratif, mais on l'assombrit
   a 5,2:1 pour qu'il ne soit pas qu'une tache grise. */
.watermark { position: fixed; bottom: 15px; right: 15px; font-size: 0.9rem; color: #5f6d6e; font-weight: bold; background: rgba(255,255,255,0.9); padding: 8px 15px; border-radius: 8px; border: 1px solid #ddd; z-index: 100; pointer-events: none; }

#toast { display: none; position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%); background: #27ae60; color: white; padding: 12px 24px; border-radius: 30px; z-index: 9999; font-weight: bold; box-shadow: 0 4px 10px rgba(0,0,0,0.2); animation: popUp 0.3s; }
@keyframes popUp { from { bottom: -20px; opacity: 0; } to { bottom: 30px; opacity: 1; } }

/* ============================================================
   Anneau de focus (contrat 5)
   Il n'existait aucune regle :focus dans le projet : un eleve au
   clavier ne savait jamais ou il se trouvait. L'anneau n'apparait
   qu'en navigation clavier (:focus-visible), pas au clic souris.
   ============================================================ */
.nav-btn:focus-visible,
.btn-open:focus-visible,
.btn-copy:focus-visible,
.tool-btn:focus-visible,
.close-btn:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
    outline: 3px solid var(--focus);
    outline-offset: 2px;
    /* Halo sombre debordant l'anneau : seul, le jaune se perdrait sur le blanc
       des cartes. Pris en sandwich, il reste visible sur tous les fonds. */
    box-shadow: 0 0 0 7px rgba(20, 30, 40, 0.55);
}
/* On n'annule l'anneau natif que pour le pointeur, jamais globalement. Si un
   navigateur ignore :focus-visible, tout ce selecteur est invalide et son
   anneau par defaut survit : aucune regression. */
button:focus:not(:focus-visible),
input:focus:not(:focus-visible),
select:focus:not(:focus-visible),
textarea:focus:not(:focus-visible),
[tabindex]:focus:not(:focus-visible) { outline: none; }

/* ============================================================
   Responsive - tablettes et telephones
   La sidebar passe en barre horizontale scrollable, le contenu
   defile normalement (on leve le overflow:hidden du body).
   ============================================================ */
@media (max-width: 768px) {
    body {
        flex-direction: column;
        height: auto;
        min-height: 100vh;
        overflow: auto;
        background-attachment: scroll;   /* 'fixed' est ignore/couteux sur mobile */
    }
    /* Repete ici : la regle ci-dessus remet body{overflow:auto} en mobile, et
       sans ce rappel explicite on croirait le verrou perdu. Le selecteur est
       plus specifique, il gagne de toute facon. */
    body.modal-ouverte { overflow: hidden; }

    /* La barre est deja horizontale en bureau : il ne reste ici que ce qui
       differe vraiment sur petit ecran. */
    #sidebar {
        padding: 4px 6px;
        position: sticky;      /* la page defile en entier en mobile : on epingle */
        top: 0;
    }
    /* Le mot-symbole s'efface faute de place, la tuile suffit a l'identite. */
    #sidebar .logo { padding: 0 8px 0 4px; margin-right: 4px; }
    #sidebar .logo span { display: none; }
    #sidebar .logo img { width: 30px; height: 30px; }
    /* L'espaceur repoussait "Demonstrations" a l'extreme droite, hors de vue
       sur un ecran etroit : on le neutralise, les onglets se suivent. */
    #sidebar > div[style*="flex-grow"] { display: none; }

    .nav-btn {
        margin: 4px 6px !important;
        padding: 10px 14px;
        font-size: 0.95rem;
        white-space: nowrap;
        flex: 0 0 auto;
        min-height: 44px;    /* cible tactile : la barre tombait a ~38 px */
    }
    .nav-btn:hover { transform: none; }

    #main { padding: 20px 15px 60px; }
    h1 { font-size: 1.5rem; margin-bottom: 20px; padding: 8px 14px; }

    .grid { grid-template-columns: 1fr; gap: 15px; }
    .card { padding: 20px; }

    /* Le champ prend toute la largeur ; la pastille passe dessous plutot
       que de comprimer le champ a cote d'elle. */
    .recherche { margin-bottom: 24px; }
    #q-outils { flex-basis: 100%; max-width: none; }

    /* Defaut corrige : max-height:100vh mesure le GRAND viewport (barre d'URL
       comprise) alors que le parent #modal est en height:100% (petit viewport).
       Une boite plus haute que la ligne flex, centree, debordait des DEUX cotes :
       sur un exerciseur long, le titre et la croix sortaient par le haut et
       devenaient inatteignables. 100dvh mesure le viewport reellement visible ;
       la declaration 100vh reste juste avant, en repli pour les navigateurs qui
       ignorent dvh. flex-start + overflow-y:auto : si la boite deborde malgre
       tout, on la fait defiler au lieu de la perdre. */
    #modal { align-items: flex-start; overflow-y: auto; }
    .modal-box { width: 100%; padding: 20px 12px; border-radius: 0; max-height: 100vh; max-height: 100dvh; }
    .close-btn { top: 8px; right: 8px; }
    .workspace { padding: 12px; min-height: 200px; }

    .watermark { display: none; }
}

/* Les outils dessinent en SVG et en grilles a largeur fixe :
   on autorise le defilement horizontal plutot que le debordement. */
@media (max-width: 768px) {
    .workspace > div,
    .workspace svg { max-width: 100%; }
    .workspace { overflow-x: auto; }
}

/* ============================================================
   Impression : fond blanc pur sans gaspillage d'encre
   ============================================================ */
@media print {
    html, body {
        background: #ffffff !important;
        background-image: none !important;
    }
}

/* ============================================================
   Mouvement reduit - a garder en DERNIER dans la feuille.
   Le systeme signale que l'utilisateur ne supporte pas les animations
   (vertiges, migraines, troubles de l'attention). On neutralise fadeIn
   des sections, popUp du toast, les glissements au survol, et surtout
   les transitions posees en style INLINE par les outils (ascenseur 5e,
   droites de Thales, puzzle des identites) : seul le selecteur universel
   avec !important peut les atteindre depuis la feuille de style.
   Duree 0,01 ms et non 0 : l'etat final est bien applique et les
   evenements transitionend/animationend continuent d'etre emis.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-delay: 0ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        transition-delay: 0ms !important;
        scroll-behavior: auto !important;
    }
    /* Les deplacements au survol ne sont pas des transitions mais des
       transform : il faut les couper separement. */
    .nav-btn:hover,
    .btn-open:hover,
    .btn-copy:hover,
    .tool-btn:hover { transform: none; }
}

/* Mise en valeur de la carte ciblée par ancre profonde */
@keyframes cardGlowPulse {
    0% {
        box-shadow: 0 0 0 0 rgba(99, 102, 241, 0.7);
        transform: scale(1.02);
    }
    50% {
        box-shadow: 0 0 0 14px rgba(99, 102, 241, 0);
        transform: scale(1.02);
    }
    100% {
        box-shadow: 0 0 0 0 rgba(99, 102, 241, 0);
        transform: scale(1);
    }
}

.card.card-highlight {
    animation: cardGlowPulse 1.6s ease-in-out 2 !important;
    border-color: #6366f1 !important;
    outline: 2px solid #6366f1 !important;
}
