/* static/melangeur.css — La carrosserie du mélangeur, à la sauce v2.
 *
 * Romain, le 16/09 : « maintenant tu le présentes à la sauce nouvelle CSS…
 * donc c'est que de la cosmétique ».
 *
 * Il a raison : ces 269 lignes venaient du <style> inline de LiquidFinder et
 * ne portaient AUCUNE logique — 31 couleurs écrites en dur et des tailles.
 * Elles sont ici portées sur les variables du projet, sans qu'une seule ligne
 * de calcul soit touchée.
 *
 * CE QUI A CHANGÉ, ET RIEN D'AUTRE :
 *   - les couleurs en dur deviennent les variables déjà en service. Le SENS de
 *     chacune est conservé : une bordure reste une bordure, l'accent reste
 *     l'accent de l'appli. Aucune teinte inventée — règle du projet ;
 *   - 6 cible(s) sous 48 px relevée(s) : c'est la règle tactile du
 *     Comptoir, une cible de 32 px se rate une fois sur trois avec un doigt ;
 *   - le <style> quitte la page : une feuille se met en cache et se relit,
 *     un style inline se recopie.
 *
 * Les variables viennent de static/magasin.css.
 */

/* Outil employés tactile (2026-08-22, demande utilisateur) : calcul de
     mélange nicotine (conservation volume x concentration, cf.
     static/nicotine_calc.js — fonctions pures, réutilisées ici). Gabarit
     de page repris de pages/jeu_pendu.html. Conventions tactiles reprises
     telles quelles de static/style.css (.btn.tactile min 48px,
     .categorie-chip pour les choix tap-to-toggle) plutôt que réinventées. */
  .zone-calc { max-width: 860px; margin: 0 auto; }

  .onglets-calc {
    display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 22px;
  }
  .onglet-calc {
    flex: 1 1 150px; min-height: 52px; border: 2px solid var(--bordure); border-radius: 12px;
    background: var(--surface); color: var(--gris-fonce); font-size: 0.92em; font-weight: 700;
    padding: 10px 12px; cursor: pointer; transition: all 0.15s;
  }
  .onglet-calc.actif { border-color: var(--accent); background: var(--accent-pale); color: var(--accent); }
  .onglet-calc:active { transform: scale(0.97); }

  .panneau-mode {
    background: var(--surface); border-radius: 16px; padding: 24px 22px;
    box-shadow: 0 2px 10px rgba(0,0,0,0.06);
  }
  .panneau-mode .desc {
    font-size: 0.88em; color: var(--gris-moyen); margin-bottom: 20px; line-height: 1.5;
  }

  .champ { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
  .champ label { font-size: 0.85em; font-weight: 700; color: var(--gris-fonce); }
  .champ select {
    min-height: 48px; padding: 10px 14px; border: 2px solid var(--bordure); border-radius: 10px;
    font-size: 1em; background: var(--surface);
  }

  .resultat-box {
    margin-top: 18px; padding: 16px 18px; border-radius: 12px;
    background: var(--vert-pale); border: 2px solid var(--vert-pale); color: var(--vert);
    font-size: 0.98em; line-height: 1.6;
  }
  .resultat-box b { color: var(--vert); }
  .erreur-box {
    margin-top: 18px; padding: 14px 18px; border-radius: 12px;
    background: var(--rouge-pale); border: 2px solid var(--rouge-pale); color: var(--rouge); font-size: 0.92em;
  }
  .message-box {
    margin-top: 18px; padding: 14px 18px; border-radius: 12px;
    background: var(--accent-pale); border: 2px solid var(--accent-pale); color: var(--accent); font-size: 0.92em;
  }

  /* Mode 1 — DIY : 4 champs, une seule case "je ne sais pas" cochée à la
     fois (radio, pas checkbox indépendantes -- garantit qu'il y en a
     toujours exactement une, jamais zéro, sinon rien à calculer),
     2026-08-25 demande utilisateur. Le champ correspondant devient
     calculé (input désactivé, valeur en vert) à partir des 3 autres. */
  .champ-diy { margin-bottom: 16px; }
  .champ-diy label {
    display: flex; justify-content: space-between; align-items: center;
    flex-wrap: wrap; gap: 8px; font-size: 0.85em; font-weight: 700; color: var(--gris-fonce); margin-bottom: 6px;
  }
  /* Mode 4 — chips de dosage disponible */
  .chips-doses { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
  .chip-dose {
    display: inline-flex; align-items: center; gap: 4px; min-height: 48px;
    padding: 8px 16px; border: 2px solid var(--bordure); border-radius: 20px; background: var(--fond);
    font-size: 0.95em; font-weight: 700; cursor: pointer; user-select: none;
  }
  .chip-dose.active { background: var(--accent-pale); border-color: var(--accent); color: var(--accent); }
  .combo-carte {
    border: 2px solid var(--bordure); border-radius: 12px; padding: 14px 16px; margin-top: 12px;
  }
  .combo-carte .combo-titre { font-weight: 700; color: var(--texte); margin-bottom: 6px; }
  .combo-carte .combo-detail { font-size: 0.92em; color: var(--gris-fonce); line-height: 1.5; }

  /* Filtres Mode 4 -- ronds cote a cote (2026-08-22, demande utilisateur :
     "des RONDs de meme taille genre grosse puce", type/volume dissocies
     par la couleur plutot que par la forme). */
  .filtres-ligne { display: flex; flex-direction: row; gap: 28px; flex-wrap: wrap; }
  .filtres-colonne { flex: 1 1 180px; }
  .filtres-colonne + .filtres-colonne { border-left: 1px solid var(--bordure); padding-left: 28px; }
  .ronds-filtre { display: flex; flex-wrap: wrap; gap: 10px; }
  .rond-filtre {
    width: 52px; height: 52px; border-radius: 50%; border: 2px solid var(--bordure); background: var(--fond);
    display: flex; align-items: center; justify-content: center; text-align: center;
    font-size: 12px; font-weight: 800; letter-spacing: 0.3px; text-transform: uppercase;
    line-height: 1.05; color: var(--gris-fonce); cursor: pointer; user-select: none;
  }
  .rond-filtre:active { transform: scale(0.94); }
  .rond-filtre.type-actif { background: var(--accent-pale); border-color: var(--accent); color: var(--accent); }

  /* Bouton BOOSTER (2026-08-22, demande utilisateur) : off par défaut,
     inclut les boosters de nicotine (toutes marques) dans le calcul. */
  .btn-booster {
    flex: 0 0 auto; min-height: 48px; padding: 0 14px; border: 2px solid var(--bordure); border-radius: 10px;
    background: var(--fond); color: var(--gris-moyen); font-weight: 800; font-size: 0.82em; letter-spacing: 0.2px;
    cursor: pointer; user-select: none; white-space: nowrap;
  }
  .btn-booster:active { transform: scale(0.96); }
  .btn-booster.active { background: var(--ambre-pale); border-color: var(--orange); color: var(--orange); }
  .btn-booster:disabled { opacity: 0.4; cursor: not-allowed; }
  .btn-booster:disabled:active { transform: none; }

  /* "Dosage cible" se range en glissant vers le haut quand le mode
     BOOSTER auto-mélange prend le relais (2026-08-22, demande
     utilisateur) -- plus besoin d'une cible unique, toutes les
     combinaisons réalisables sont affichées directement. */
  .champ-repliable {
    /* 🔴 NE JAMAIS y remettre une hauteur devinée. Ce plafond a deja
       rogne le bouton « Valider » le 26/08 -- rustine 120px -> 190px -- puis
       AVALE CINQ PUCES de dosage cible le 16/09, des que le depliant
       « viser un dosage non propose » est venu s ajouter dessous. A chaque
       fois : le contenu est bien dans le DOM, il est juste coupe, et rien
       ne le signale.

       Ici max-height ne sert qu a ANIMER le repli. Une valeur large tient
       ce role sans jamais tronquer : la transition reste fluide, et le
       contenu peut grandir autant qu il veut. */
    max-height: 60rem; opacity: 1; margin-bottom: 16px; overflow: hidden;
    transition: max-height 0.35s ease, opacity 0.25s ease, margin-bottom 0.35s ease;
  }
  .champ-repliable.replie { max-height: 0; opacity: 0; margin-bottom: 0; }

  /* Résultats booster : ronds sur le modèle des puces de filtre, agrandis
     (2026-08-22, demande utilisateur) pour intégrer le PG/VG résultant
     directement dessus, sans avoir besoin de cliquer. */
  .rond-resultat-booster {
    position: relative; width: 76px; height: 76px; border-radius: 50%;
    border: 2px solid var(--bordure); background: var(--fond);
    display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center;
    cursor: pointer; user-select: none; line-height: 1.15; gap: 1px;
  }
  .rond-resultat-booster .rrb-dose { font-size: 15px; font-weight: 800; }
  .rond-resultat-booster .rrb-ratio { font-size: 9.5px; font-weight: 600; opacity: .7; }
  .rond-resultat-booster:active { transform: scale(0.94); }
  .rond-resultat-booster.selectionne { box-shadow: 0 0 0 3px rgba(0,0,0,0.08) inset; }
  /* Combinaison "recommandée" (2026-08-22, demande utilisateur -- ex. 30ml
     conseillé à partir de 3 unités) : léger liseré vert + petit repère en
     coin, pas une mise en avant agressive. */
  .rond-resultat-booster.recommande { box-shadow: 0 0 0 2px var(--vert); }
  .rond-resultat-booster.recommande::after {
    content: "✓"; position: absolute; top: -4px; right: -4px; font-size: 9px;
    /* ⚠ height: 15px, PAS 48. Ma passe de relevage des cibles tactiles avait
       transforme ce 15 en 48 : la pastille devenait un ovale de 15 de large
       sur 48 de haut, et le ✓ blanc dedans illisible (defaut releve par
       Romain le 16/09). `height` est une GEOMETRIE, `min-height` est une
       cible : on ne releve que les secondes. */
    color: var(--surface); background: var(--vert); border-radius: 50%; width: 15px; height: 15px;
    display: flex; align-items: center; justify-content: center; line-height: 1;
  }
  /* Puce barrée (2026-08-23, demande utilisateur) : sur une ligne "Mix
     Booster...", un mix nécessite au moins 1 flacon de CHAQUE booster
     (jamais n=1 côté mix) -- une puce barrée occupe cette position pour
     que le vrai résultat du mix tombe exactement sous la puce de même n
     des lignes boosters simples au-dessus ("aligner la puce réponse deux
     boosters avec les autres"). Non cliquable, aucun dosage affiché. */
  .rond-resultat-booster.rond-indisponible {
    border-color: var(--bordure) !important; color: transparent; cursor: default; pointer-events: none;
    background: var(--fond);
  }
  .rond-resultat-booster.rond-indisponible::after {
    /* Le trait qui barre un booster indisponible : 2 px, pas 48 — meme cause. */
    content: ""; position: absolute; left: 12%; right: 12%; top: 50%; height: 2px;
    background: var(--bordure); transform: rotate(-18deg);
  }

  /* Détail booster fixé à l'extrême gauche de l'écran (2026-08-22,
     demande utilisateur : "en bas en cas de longue liste on n'y voit
     rien", puis "je basculerais volontiers la fenêtre détail à
     l'extrême gauche" -- une colonne à droite empiétait sur les
     colonnes de résultats par contenance de vaisseau). Hors du flux de
     .zone-calc (centrée, largeur limitée) pour ne jamais lui voler de
     place -- ne s'affiche que si l'écran est assez large pour laisser
     le contenu centré respirer (sinon repli en bas de page, comme avant). */
  /* Le detail s ancre au rond clique -- sa position est calculee en JS
     (_placerDetailM4). Avant, il etait cloue en haut a gauche : quand la
     reponse etait en bas de liste, on lisait l explication a l autre bout de
     l ecran. */
  .panneau-detail-sticky {
    position: fixed; width: 280px; max-width: calc(100vw - 24px);
    max-height: 60vh; overflow-y: auto; z-index: 60;
    background: var(--surface); border: 2px solid var(--bordure); border-radius: 12px;
    padding: 14px 16px; box-shadow: 0 8px 28px rgba(0, 0, 0, 0.16);
  }
  /* Sur ecran etroit, le panneau se colle en bas plutot qu a cote du rond :
     la main du vendeur le masquerait au moment meme ou il tape. */
  .panneau-detail-sticky.detail-en-bas {
    left: 0; right: 0; bottom: 0; top: auto;
    width: auto; max-width: none; border-radius: 14px 14px 0 0;
    border-bottom: none; max-height: 55vh;
  }
  .detail-fermer {
    position: absolute; top: 6px; right: 8px;
    min-width: 32px; min-height: 32px; padding: 0; line-height: 1;
    border: none; background: none; font-size: 1.4em; cursor: pointer;
    color: var(--gris-moyen);
  }
  .detail-fermer:hover { color: var(--texte); }


  /* Mode 2 -- DIY façon aromes-et-liquides.fr (2026-08-25, demande
     utilisateur : réplique de leur calculateur-de-base-et-booster.html,
     exploré en direct au navigateur -- gros champ volume centré, boutons
     "+ Ajouter..." en pilules, puces vert/violet, bouton CALCULER
     explicite, résultat en champs ml éditables + fiole. */
  .al-input-large {
    width: 100%; min-height: 64px; text-align: center; font-size: 1.6em; font-weight: 800;
    color: var(--texte); border: 2px solid var(--bordure); border-radius: 12px; padding: 6px 14px;
  }
  /* Ligne volume + bouton "Quantité libre" côte à côte (2026-08-26, demande
     utilisateur : "il faut le mettre lors de l'étape 1 au moment du choix
     de la quantité, réduire le champ de saisie et mettre le bouton à sa
     droite" -- déplacé depuis sous la fiole du résultat). */
  .al-ligne-volume { display: flex; align-items: stretch; gap: 10px; }
  .al-ligne-volume .al-input-large { width: auto; flex: 1 1 auto; min-width: 0; }
  /* Clignotement d'attention (2026-08-26, demande utilisateur : "permanent
     et rouge... ça ne s'arrête que lorsqu'il détecte une saisie ou qu'on
     appuie sur calculer") : le champ volume/base est en haut de page, mais
     le bouton "Pas d'arôme" qui bascule son rôle en "Quantité de base
     disponible" est plus bas -- sans ce signal, le changement passe
     inaperçu. Boucle infinie tant que la classe reste posée -- retirée
     explicitement par _alSaisieVolume() (saisie détectée) ou alCalculer()
     (CALCULER pressé), jamais par un timer/une durée fixe. */
  @keyframes al-attire-attention {
    0%, 100% { box-shadow: 0 0 0 0 rgba(231,76,60,0); border-radius: 14px; }
    50% { box-shadow: 0 0 0 6px rgba(231,76,60,0.65); border-radius: 14px; }
  }
  .al-champ-attire { animation: al-attire-attention 1.1s ease-in-out infinite; }
  .al-carte-ouverte { border: 2px solid var(--bordure); border-radius: 14px; padding: 16px 18px; margin-bottom: 14px; position: relative; }
  .al-carte-ouverte .al-fermer { position: absolute; top: 10px; right: 12px; background: none; border: none; font-size: 1.1em; cursor: pointer; color: var(--gris-moyen); min-height: 48px; min-width: 32px; }
  .al-carte-titre-etape { font-weight: 800; color: var(--texte); margin-bottom: 12px; padding-right: 24px; }
  .chips-al { display: flex; flex-wrap: wrap; gap: 10px; }
  .chip-al {
    min-width: 64px; min-height: 56px; padding: 6px 10px; border-radius: 16px; background: var(--vert-pale);
    color: var(--vert); font-weight: 800; font-size: 0.95em; text-align: center; display: flex;
    flex-direction: column; align-items: center; justify-content: center; cursor: pointer; user-select: none; border: none;
  }
  .chip-al.chip-al-actif { background: var(--violet); color: var(--surface); }
  .chip-al.chip-al-input { background: var(--surface); border: 2px solid var(--vert-pale); color: var(--texte); font-weight: 700; }
  /* CALCULER est l action PRINCIPALE, donc l accent -- pas le vert. Dans la
     charte, --vert dit « c est regle » ; il ne dit pas « appuie ici ».
     Romain, 16/09 : « bouton calculer et effacer en vert ? ». */
  .btn-calculer-al {
    display: block; width: 100%; min-height: 56px; margin: 6px 0 18px; border: none;
    border-radius: 10px; background: var(--bordure); color: var(--surface);
    font-weight: 700; font-size: 1.05em; letter-spacing: 0.4px; cursor: not-allowed;
  }
  .btn-calculer-al.al-actif { background: var(--accent); cursor: pointer; }
  .btn-calculer-al.al-actif:active { transform: scale(0.98); }
  /* RECALCULER : une entree a bouge depuis le dernier calcul, ce qui est
     affiche n est plus a jour. L ambre le dit -- « ce qui demande un oeil ». */
  .btn-calculer-al.al-refaire { background: var(--ambre); }
  .al-resultat-layout { display: flex; gap: 26px; flex-wrap: wrap; align-items: flex-start; margin-top: 10px; }
  .al-fiole-col { flex: 0 0 110px; display: flex; flex-direction: column; align-items: center; gap: 10px; }
  /* Bouton "Quantité libre" -- à droite du champ volume, étape 1 (2026-08-26,
     déplacé depuis sous la fiole du résultat, demande utilisateur). */
  .btn-quantite-libre {
    flex: 0 0 108px; min-height: 64px; padding: 6px 8px; border: 2px solid var(--bordure); border-radius: 12px;
    background: var(--fond); color: var(--gris-fonce); font-weight: 700; font-size: 0.78em; text-align: center;
    cursor: pointer;
  }
  .btn-quantite-libre.actif { background: var(--accent-pale); border-color: var(--accent); color: var(--accent); }
  .btn-quantite-libre:disabled { opacity: 0.4; cursor: not-allowed; }
  .btn-quantite-libre:active { transform: scale(0.97); }
  /* Bouton "Pas d'arôme" -- discret, sous le champ de recherche d'arôme
     (2026-08-26, demande utilisateur : "un petit bouton discret qui
     permet de s'échapper de l'attente de l'arôme concentré... à droite du
     champ" -- même style que .btn-quantite-libre, pas un lien texte). */
  .al-ligne-arome { display: flex; align-items: stretch; gap: 10px; }
  .al-ligne-arome input { flex: 1 1 auto; min-width: 0; }
  .btn-pas-arome { flex: 0 0 100px; min-height: 48px; }
  .al-cartes-col { flex: 1 1 320px; display: flex; flex-direction: column; gap: 12px; min-width: 0; }
  .al-carte-entete { padding: 12px 16px; border-radius: 12px; border: 2px solid var(--bordure); background: var(--fond); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 6px 14px; font-weight: 700; font-size: 0.88em; color: var(--texte); white-space: nowrap; }
  .al-carte-composant { display: flex; align-items: center; gap: 14px; padding: 12px 16px; border-radius: 12px; border: 2px solid var(--bordure); background: var(--surface); }
  /* Chaque carte porte la couleur que la FIOLE lui donne (DIY_COULEURS_FIOLE) :
     base bleue, booster ambre, arome vert. Romain, 16/09 : « pour un pb de
     pertinence, il faut que les couleurs des blocs reponse du concentre, des
     boosters et de la base reprennent celles utilisees pour les symboliser
     dans la bouteille ». Avant, la carte du booster etait VERTE et sa bande
     dans la fiole AMBRE : on lisait deux fois le meme composant sous deux
     couleurs, a dix centimetres d ecart.
     La bordure gauche porte la teinte franche, le fond sa version pale --
     c est elle qu on retrouve dans la fiole. */
  .al-carte-composant.al-base {
    border-color: var(--accent-pale); background: var(--accent-pale);
    border-left: 5px solid var(--accent);
  }
  .al-carte-composant.al-booster {
    border-color: var(--ambre-pale); background: var(--ambre-pale);
    border-left: 5px solid var(--ambre);
  }
  .al-carte-composant.al-arome {
    border-color: var(--vert-pale); background: var(--vert-pale);
    border-left: 5px solid var(--vert);
  }
  .al-carte-composant .al-icone { font-size: 1.8em; flex: 0 0 auto; }
  .al-carte-composant .al-ml-input {
    width: 78px; min-height: 48px; text-align: center; font-size: 1.15em; font-weight: 800; color: var(--texte);
    border: 2px solid var(--bordure); border-radius: 10px; flex: 0 0 auto;
  }
  .al-carte-composant .al-ml-unite { flex: 0 0 auto; margin-left: -8px; font-size: 0.85em; color: var(--gris-moyen); }
  .al-carte-composant .al-infos { flex: 1; min-width: 0; }
  .al-carte-composant .al-infos b { display: block; font-size: 0.98em; color: var(--texte); }
  .al-carte-composant .al-infos span { font-size: 0.82em; color: var(--gris-moyen); }
  /* EFFACER detruit la saisie : le vert disait « c est bon » sur un bouton qui
     jette tout. Il devient discret, et ne se colore qu au survol -- en rouge,
     la couleur de ce qu on refuse. */
  .btn-effacer-al {
    display: block; margin: 16px auto 0; min-height: 48px; padding: 0 28px;
    border: 2px solid var(--bordure); border-radius: 10px;
    background: var(--surface); color: var(--gris-fonce); font-weight: 600; cursor: pointer;
  }
  .btn-effacer-al:hover { border-color: var(--rouge); color: var(--rouge); }
  /* Bouton "Valider" tactile (2026-08-25, retour utilisateur : "pense
     tactile", taper une valeur doit faire apparaître un bouton visible --
     jamais une dépendance à la touche Entrée seule). */
  /* Meme allure que .hl-b : ces boutons valident la meme chose, ils n ont pas
     a se ressembler de loin. Romain, 16/09 : « reprendre le bouton valider
     pour le mettre conforme CSS ». Rayon 10 comme partout en v2 (24 faisait
     pilule, heritage V1), accent plutot que vert, graisse 600. La pleine
     largeur reste : sous un champ pleine largeur, c est la bonne cible. */
  .btn-valider-al {
    display: block; width: 100%; min-height: 48px; margin-top: 10px; border: none;
    border-radius: 10px; background: var(--accent); color: var(--surface);
    font-weight: 600; font-size: 0.95em; cursor: pointer;
  }
  .btn-valider-al:active { transform: scale(0.98); }
  /* Puces de ratio booster intégrées DANS la case résultat Booster
     (2026-08-25, demande utilisateur : "pas à cet endroit mais ds la case
     résultat nicotine... quitte à les réduire légèrement... elles peuvent
     avoir la hauteur du champ où s'affiche le résultat" -- hauteur alignée
     sur .al-ml-input (44px), plus compactes que les puces standard. */
  .chips-booster-mini { flex: 1 1 auto; gap: 6px; }
  .chips-booster-mini .chip-al {
    min-width: 0; min-height: 48px; padding: 4px 12px; border-radius: 12px; font-size: 0.82em;
  }

/* L'en-tete de la page, repris de LiquidFinder mais allege : il ne reste que
   le titre et la date. Le magasin est dans le bandeau, la navigation dans le
   dock — les deux ont quitte cet en-tete le 16/09. */
header {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 18px;
  position: relative;   /* la bulle de l'ampoule s'y accroche (17/09) */
}
header .duo { align-self: center; }
/* La bulle ne descend pas sous le dock : elle défile en elle-même (même règle
   que dans Historique doublons). */
#logique-melangeur { max-height: calc(100vh - 74px - var(--dock-h, 160px) - 140px); overflow-y: auto; }
.header-titre { display: flex; align-items: center; gap: 14px; }
.header-titre h1 { font-size: 1.9em; }
header #date-header { color: var(--gris-fonce); }

/* Le conteneur de la page. Il etait dans le <style> de LiquidFinder ou il
   portait la largeur du site ; ici il se cale sur la largeur de lecture du
   Comptoir et laisse le degagement du dock (--dock-h, mesure par le gabarit). */
.container {
  /* Pas de tablette au comptoir (Romain, 16/09) : les postes sont en
     1920x1080. On prend la largeur, c'est ce qui permet au resultat de
     tenir a cote de la saisie au lieu d'etre en dessous. */
  max-width: 1680px; margin: 0 auto;
  padding-bottom: calc(var(--dock-h, 96px) + 40px);
}

/* L'erlenmeyer du titre. `currentColor` : il prend la couleur du titre, donc
   il suit la palette sans jamais la contredire. */
.icone-fiole {
  width: 1.05em; height: 1.05em; vertical-align: -0.12em;
  color: var(--accent); flex: 0 0 auto;
}

/* ============ TRAVAILLER COUPÉ DES BASES ============
   Le panneau de saisie. Il n'apparait QUE dans ce cas : branche, c'est le
   catalogue qui repond et ce panneau n'aurait rien a faire la. */
.hl {
  background: var(--ambre-pale); border: 1px solid var(--ambre);
  border-radius: 16px; padding: 18px 22px; margin-bottom: 18px;
}
.hl[hidden] { display: none; }
.hl h3 { color: var(--ambre); font-size: 1.15em; }
.hl-aide { color: var(--gris-fonce); margin: 6px 0 14px; line-height: 1.5; }
.hl-blocs {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}
.hl-bloc {
  background: var(--surface); border: 1px solid var(--bordure);
  border-radius: 12px; padding: 14px 16px;
}
.hl-bloc h4 { font-size: 1em; margin-bottom: 10px; }
.hl-ligne {
  display: flex; align-items: center; gap: 8px;
  flex-wrap: wrap; margin-bottom: 8px;
}
.hl-ligne input, .hl-ligne select {
  min-height: 48px; padding: 0 12px; font-size: 1em;
  border: 1px solid var(--bordure); border-radius: 10px;
  background: var(--surface); color: var(--texte); min-width: 5em;
}
.hl-ligne input[type="text"] { flex: 1 1 8em; }
.hl-ligne input:focus, .hl-ligne select:focus { outline: none; border-color: var(--accent); }
.hl-u { color: var(--gris-fonce); font-size: 0.92em; }
.hl-b {
  min-height: 48px; padding: 0 18px; cursor: pointer;
  border: none; border-radius: 10px;
  background: var(--accent); color: var(--surface); font-weight: 600;
}
.hl-liste { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.hl-vide { color: var(--gris-moyen); font-style: italic; font-size: 0.9em; }
.hl-item {
  display: inline-flex; align-items: center; gap: 6px; min-height: 48px;
  background: var(--accent-pale); color: var(--accent);
  border-radius: 10px; padding: 4px 4px 4px 12px; font-size: 0.92em;
}
.hl-x {
  min-width: 36px; min-height: 36px; border: none; border-radius: 8px;
  background: transparent; color: inherit; font-size: 1.2em; cursor: pointer;
}
.hl-x:hover { background: var(--surface); }

/* ============ LE CHEMINEMENT EN ETAPES ============
   Romain, 16/09 : « je n'aime pas le fil pris, j'ai prefere la logique du
   premier jet ». Celui-ci avancait en trois etapes numerotees : ce que j'ai,
   ce que je veux, le resultat. La page V1 enchaînait des cartes sans dire ou
   l'on en etait — on la rhabille, ses calculs ne bougent pas.

   Pas de tablette au comptoir (Romain) : on peut donc compter sur la largeur
   sans point de bascule bas. Une seule colonne sous 1100 px reste un filet. */
.etape {
  background: var(--surface); border: 1px solid var(--bordure);
  border-radius: 16px; padding: 20px 24px; margin-bottom: 16px;
}
.etape > h2 {
  font-size: 1.2em; display: flex; align-items: center; gap: 12px;
  margin-bottom: 4px;
}
.et-num {
  background: var(--accent); color: var(--surface);
  width: 34px; height: 34px; border-radius: 50%; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.85em;
}
.et-aide { color: var(--gris-fonce); line-height: 1.5; margin-bottom: 14px; }

/* La derniere etape — le resultat — passe a droite et RESTE visible pendant
   qu'on ajuste a gauche. C'est tout l'interet de l'ecran large : on change le
   dosage cible et la recette bouge sous les yeux, sans un seul defilement. */
@media (min-width: 1100px) {
  .zone-calc .panneau-mode {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(360px, 42%);
    gap: 18px; align-items: start;
  }
  .panneau-mode > .etape:nth-of-type(1),
  .panneau-mode > .etape:nth-of-type(2) { grid-column: 1; }
  .panneau-mode > .etape:nth-of-type(3) {
    grid-column: 2; grid-row: 1 / span 2;
    position: sticky; top: 16px; align-self: start;
  }
}

/* Le tiroir de saisie : replie par defaut. On saisit une fois, on calcule dix. */
.hl { padding: 0; overflow: hidden; }
.hl-tete {
  width: 100%; min-height: 56px; cursor: pointer; text-align: left;
  display: flex; align-items: center; gap: 12px; padding: 0 20px;
  background: transparent; border: none; color: var(--ambre);
  font-size: 1.05em; font-weight: 600;
}
.hl-fleche { transition: transform 0.15s; display: inline-block; }
.hl-tete.ouvert .hl-fleche { transform: rotate(90deg); }
.hl-resume { margin-left: auto; font-weight: 400; font-size: 0.9em; }
.hl-resume-vide { font-style: italic; opacity: 0.7; }
.hl-corps { padding: 0 20px 18px; }
.hl-corps[hidden] { display: none; }

/* Les deux calculateurs, en pleine largeur : ce sont les deux portes d'entree
   de l'outil, et elles se touchent au doigt. */
.onglets-calc { display: flex; gap: 10px; margin-bottom: 16px; }
.onglet-calc { flex: 1 1 0; min-height: 64px; font-size: 1.05em; }

/* La ligne qui dit a quoi sert un bloc de saisie, sous son titre. */
.hl-note { color: var(--gris-moyen); font-size: 0.9em; margin-bottom: 10px; line-height: 1.4; }

/* Les viscosites courantes, proposees d office. */
.hl-ratios { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.hl-ratio {
  min-height: 48px; padding: 6px 16px; cursor: pointer;
  border: 2px solid var(--bordure); border-radius: 12px;
  background: var(--surface); color: var(--texte); font-weight: 600;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.hl-ratio:hover { border-color: var(--accent); }
.hl-ratio small { font-weight: 400; font-size: 0.72em; color: var(--gris-moyen); }

/* Une puce cochee : on la voit d un coup d oeil parmi les autres. */
.hl-ratio.on {
  border-color: var(--accent); background: var(--accent-pale); color: var(--accent);
}

/* Ce qui n existe que branche disparait vraiment quand on est coupe. */
.champ[hidden] { display: none; }

.mel-bascules[hidden], .btn-quantite-libre[hidden] { display: none; }

/* Deux familles de pastilles qui se suivent : on les nomme et on les espace,
   sinon on ne devine pas que l une est des ml et l autre des mg. */
.hl-groupe { margin-bottom: 14px; }
.hl-groupe + .hl-groupe { padding-top: 12px; border-top: 1px solid var(--bordure); }
.hl-titre {
  display: block; margin-bottom: 8px; font-size: 0.82em; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--gris-fonce);
}

/* L ampoule, a cote du titre : l explication complete existe, elle ne
   s impose pas. Romain, 16/09 : « trop de blabla, mes employes ont
   l habitude ». Meme place que l engrenage de magasin.css. */
.hl-titre { display: flex; align-items: center; gap: 8px; }
.hl-ampoule {
  border: 1px solid var(--bordure); background: var(--surface);
  border-radius: 999px; width: 26px; height: 26px; line-height: 1;
  font-size: 0.92rem; cursor: pointer; padding: 0;
}
.hl-ampoule:hover, .hl-ampoule.on {
  border-color: var(--accent); background: var(--accent-pale);
}
.hl-aide {
  margin: 0 0 10px; padding: 10px 12px; border-radius: 10px;
  background: var(--fond); color: var(--gris-fonce);
  font-size: 0.88em; line-height: 1.5; text-transform: none;
  font-weight: 400; letter-spacing: 0;
}
.hl-aide[hidden] { display: none; }

/* Les dosages marginaux (4, 8, 9, 11, 16) et la saisie a la main : vrais,
   mais rares — donc replies, et deplies tout seuls si l un est coche. */
.hl-plus { margin-top: 10px; }
.hl-plus > summary {
  cursor: pointer; font-size: 0.85em; color: var(--gris-moyen);
  text-transform: none; font-weight: 500; letter-spacing: 0;
  min-height: 48px; display: flex; align-items: center;
}
.hl-plus > summary:hover { color: var(--accent); }

/* La derniere case de la rangee des cibles est un champ libre : on dit a
   quoi elle sert, sinon on la prend pour une puce de plus. */
.chips-al-indice {
  flex-basis: 100%; margin-top: 6px;
  font-size: 0.82em; color: var(--gris-moyen);
}

/* Une etape entiere peut disparaitre : en mode BOOSTER, « ce que je veux
   obtenir » n a plus lieu d etre, le calcul rend tout le catalogue. */
.etape[hidden] { display: none; }

/* Un depliant qui ne montre pas qu il s ouvre n est pas un depliant : le
   chevron le dit, et il pivote quand on ouvre. Il remplace le triangle
   natif, qui ne se met pas ou on veut. */
/* Le chevron colle a la phrase, pas au bout de la ligne : sinon il flotte
   seul a droite et on ne fait plus le lien avec le texte. */
.hl-plus > summary { list-style: none; justify-content: flex-start; gap: 6px; }
.hl-plus > summary::-webkit-details-marker { display: none; }
.hl-plus > summary::after {
  content: "\203A"; font-size: 1.5em; line-height: 1; color: var(--gris-moyen);
  transform: rotate(90deg); transition: transform 0.15s ease;
}
.hl-plus[open] > summary::after { transform: rotate(-90deg); }

/* Le dosage personnalise occupe toute la largeur sous les puces : dans une
   rangee flex, sans ca il se tasserait a cote d elles. */
.hl-ligne-large { flex-basis: 100%; margin-top: 4px; }
/* Un bouton qui ne peut pas encore valider le DIT, au lieu de surgir sous le
   doigt au moment ou on tape. */
.hl-b[disabled] { opacity: 0.45; cursor: not-allowed; }

/* Un dosage, c est deux caracteres et demi. Romain, 16/09 : « reduit le bloc
   de saisie, y a pas besoin de tout ca, le gars ne va pas rentrer PI ». Le
   champ se dimensionne sur ce qu on y ecrit, pas sur la place disponible. */
.hl-ligne input[type="text"], .hl-ligne input[type="number"] {
  flex: 0 0 auto; width: 5.5rem; text-align: center;
}

/* Le laius d une etape vit sous son ampoule : ses paragraphes reprennent la
   sobriete du panneau au lieu de leur mise en forme d origine. */
.hl-aide .et-aide, .hl-aide .desc { margin: 0 0 8px; font-size: 1em; color: inherit; }
.hl-aide .desc:last-child, .hl-aide p:last-child { margin-bottom: 0; }
.hl-aide hr { border: none; border-top: 1px solid var(--bordure); margin: 10px 0; }

/* Le choix du format d un kit deja dose : meme gabarit que les champs de la
   ligne, pour que la rangee ne se deforme pas. */
.hl-ligne select {
  flex: 0 0 auto; min-height: 48px; padding: 0 10px;
  border: 2px solid var(--bordure); border-radius: 10px;
  background: var(--surface); color: var(--texte); font-size: 1em;
}

/* Une rangee de ratios : les puces, et le reglage fin derriere un chevron
   colle a droite de la derniere. Le champ libre ne deforme plus le bloc. */
.hl-rangee-ratios {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
}
.hl-plus-chevron { margin: 0; }
.hl-plus-chevron > summary {
  min-height: 40px; min-width: 40px; justify-content: center;
  border: 1px solid var(--bordure); border-radius: 10px; gap: 0;
}
.hl-plus-chevron > summary::after { font-size: 1.3em; }
.hl-plus-chevron > summary:hover { border-color: var(--accent); }
.hl-plus-chevron[open] { flex-basis: 100%; }
.hl-plus-chevron[open] > summary { border-color: var(--accent); }

/* « Je veux utiliser » chapeaute les trois puces : sans lui, elles se lisent
   comme trois actions et non comme trois reponses a la meme question. */
.al-titre-bascules {
  display: block; margin: 4px 0 8px; font-size: 0.82em; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--gris-fonce);
}

/* Une ligne par choix : la puce, et juste a droite ce qu elle demande. Fini
   le champ unique qui changeait de sens en silence. */
.diy-choix {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-bottom: 8px;
}
.diy-choix > .mel-bascule { flex: 0 0 auto; min-width: 190px; text-align: left; }
.diy-choix input[type="text"], .diy-choix select {
  flex: 0 0 auto; width: 6.5rem; min-height: 48px; padding: 0 10px;
  border: 2px solid var(--bordure); border-radius: 10px;
  background: var(--surface); color: var(--texte); font-size: 1em; text-align: center;
}
/* Ce qui n est pas la question du moment s efface sans disparaitre : on voit
   que l outil sait faire autre chose, sans croire qu il attend une reponse. */
.diy-choix:not(:has(.mel-bascule.actif)) input,
.diy-choix:not(:has(.mel-bascule.actif)) select { opacity: 0.45; }
.diy-choix select[disabled] { opacity: 0.6; cursor: not-allowed; }

/* 🔴 `hidden` DOIT GAGNER. Romain, 16/09 : « honnetement j enleverais le champ
   volume souhaite, il est redondant et induit en erreur ». Il l etait encore
   alors que je l avais masque : .al-ligne-volume porte `display: flex`, et une
   regle de classe bat le `[hidden] { display: none }` de la feuille du
   navigateur. L attribut etait pose, l element restait a l ecran.
   Meme famille que l element cache par son parent : on croit avoir masque. */
[hidden] { display: none !important; }

/* Une dilution qui s ecarte du conseil du fabricant n est pas une erreur :
   c est un choix (30 ml de concentre dans un flacon de 250). L ambre le
   signale sans crier -- « ce qui demande un oeil », pas « ce qui est refuse ».
   ⚠ Selecteur aligne sur celui qui donne le gris aux <span> des cartes
   (.al-carte-composant .al-infos span) : moins specifique, la regle passait
   inapercue -- ecrite, appliquee, et sans le moindre effet a l ecran. */
.al-carte-composant .al-dilution-ligne.al-dilution-ecartee {
  color: var(--ambre); font-weight: 600;
}

/* Le cadenas d une quantite : ferme, elle est imposee et ne se recalcule
   plus ; ouvert, elle suit la dilution du fabricant. */
.al-cadenas {
  flex: 0 0 auto; min-width: 40px; min-height: 40px; padding: 0;
  border: 1px solid var(--bordure); border-radius: 10px;
  background: var(--surface); font-size: 1rem; line-height: 1; cursor: pointer;
}
.al-cadenas:hover { border-color: var(--accent); }
.al-cadenas.verrouille { border-color: var(--ambre); background: var(--ambre-pale); }

/* La dilution reelle occupe TOUTE la largeur de la carte, sous les puces et
   sous le cadenas. Dans la colonne des infos elle tombait sur six lignes et
   ecrasait tout, jusqu a couper le nom de l arome en deux. */
.al-carte-composant .al-dilution-ligne {
  flex-basis: 100%; margin-top: 6px;
  font-size: 0.82em; color: var(--gris-moyen);
}
.al-carte-composant .al-dilution-ligne:empty { display: none; }
.al-carte-composant .al-infos .al-marque:empty { display: none; }

/* « Je ne sais pas » se tient a cote du taux, plus discret qu une puce de
   choix : c est un aveu, pas une option qu on met en avant. */
.hl-je-sais-pas { font-size: 0.85em; padding: 0 12px; min-width: 0; }
.mel-bascule.actif { border-color: var(--accent); background: var(--accent-pale); color: var(--accent); }

/* Une annotation occupe TOUTE la largeur de sa carte. Dans la colonne des
   infos -- 44 px pour la base -- « 50/50 PG/VG (suppose) » tombait sur cinq
   lignes et faisait des cartes de hauteurs toutes differentes. */
.al-carte-composant .al-annotation {
  flex-basis: 100%; margin-top: 6px;
  font-size: 0.82em; color: var(--gris-moyen);
}
.al-carte-composant .al-annotation:empty { display: none; }
/* ⚠ Sans flex-wrap, une annotation en flex-basis:100% NE PASSE PAS a la
   ligne : elle se comprime a cote du reste. La carte Base ne l avait pas
   (seules booster et arome portaient un style en ligne), d ou « 50/50 PG/VG
   (suppose) » tasse sur trois lignes dans 44 px. On le pose pour toutes. */
.al-carte-composant { flex-wrap: wrap; }
/* L ampoule reste au bout de la ligne SANS manger le nom : pas de
   margin-left:auto, qui comprimait .al-infos jusqu a couper « Mon arome »
   en « Mo…n arome » autour de l icone. */
.al-carte-composant > .hl-ampoule { flex: 0 0 auto; align-self: center; }
.al-carte-composant > .al-infos { min-width: 7rem; }
.al-carte-composant > .hl-aide { flex-basis: 100%; margin: 8px 0 0; }

/* Une annotation qui porte un CHOIX de l utilisateur se lit, elle ne se
   devine pas : le gris clair convient a une valeur supposee, pas a une
   valeur qu on vient de designer. */
.al-carte-composant .al-annotation-forte { color: var(--texte); }
.al-carte-composant .al-annotation b { color: inherit; }
