/* LES COULEURS.
   Deux familles, et il ne faut pas les mélanger.

   Les couleurs de MARQUE (encre, niagara, ocean, menthe, brume, terre) sont celles qui se
   posent SUR une surface fixe : le fond du bouton principal, la pastille active, l'écran de
   photo qui reste noir dans les deux thèmes. Elles ne basculent pas, sinon on obtient du
   texte blanc sur fond blanc. La seule exception est la terre, qui ne sert jamais de fond :
   elle n'apparaît qu'en texte et en bordure, donc elle doit s'éclaircir comme un texte.

   Les couleurs de SURFACE, de TEXTE et de SIGNAL basculent. C'est le seul endroit à toucher
   pour régler le mode sombre. Toute couleur écrite en dur ailleurs qu'ici est un bogue :
   elle ne bascule pas, et le texte disparaît dans l'autre thème.

   Le contraste a été volontairement ABAISSÉ le 19 septembre 2026. L'encre pure sur blanc
   pur donnait 16:1, ce qui éblouit sur un téléphone à pleine luminosité, en cabine, à bout
   de bras. On vise maintenant environ 12:1, bien au-dessus du minimum AA de 4,5:1, mais
   sans le tranchant du noir sur blanc. */
:root { --encre:#102526; --niagara:#4A6B6B; --ocean:#3F4E4D; --menthe:#5C6C64; --brume:#D0CDCD;
  --titre:"Zen Maru Gothic","Trebuchet MS",Verdana,sans-serif; --texte:"Raleway",Calibri,Arial,sans-serif;
  --fond:#F7F8F8;        /* le fond de la page : blanc cassé, pas blanc pur */
  --carte:#ffffff;       /* une surface posée dessus : champ, bouton secondaire, barre du bas */
  --trait:#D0CDCD;       /* les bordures */
  --lire:#3F4E4D;        /* le texte courant, 8,2:1 */
  --lire-fort:#23383A;   /* les titres, les chiffres, ce qui doit ressortir, 11,6:1 */
  --accent:#4A6B6B;      /* les liens et le trait actif, 5,5:1 */
  --alerte:#7A2E2E;      /* ce qui bloque : un lien invalide, un solde à zéro */
  --attention:#7A5A22;   /* ce qui mérite un coup d'œil : une fréquence à respecter */
  --bien:#3D6B4E;        /* ce qui va dans le bon sens : une hausse, une peau au-dessus de la moyenne */
  --terre:#8A4B3C;       /* ce qui détruit, et le prix manquant */
  --creux:#102526;       /* la tuile principale, volontairement plus foncée que la page */
  --faible:#7C8886;      /* ce qui est éteint sans disparaître : un jour de fermeture, 3,5:1 */
}

/* Le mode sombre. Les fonds s'éclaircissent JUSTE assez pour ne plus être noirs : un texte
   clair sur noir pur bave et fatigue autant qu'un noir sur blanc pur. Les textes
   s'assombrissent d'un cran par la même logique. */
:root[data-theme="sombre"] {
  --fond:#14211F;
  --carte:#1D2C2A;
  --trait:#334744;
  --lire:#AEBCB9;        /* 8,4:1 */
  --lire-fort:#D6DEDC;   /* 12,1:1 sur le fond, 10,6:1 sur une carte */
  --accent:#8FB3B1;      /* 7,3:1 */
  --alerte:#E8A9A2;
  --attention:#D9BC7A;
  --bien:#8FC7A4;
  --terre:#D79A87;
  --creux:#0A1617;
  --faible:#708280;
}
* { box-sizing: border-box; }
/* LA TAILLE DE TOUT LE TEXTE SE RÈGLE ICI, ET NULLE PART AILLEURS.
   Toutes les tailles du fichier sont en rem, donc relatives à cette racine : la changer
   grossit ou réduit l'application entière, d'un seul coup et sans rien déformer.
   17px au lieu des 16 par défaut, à la demande de Francis le 19 septembre 2026 : le texte
   se lisait mal en cabine, où l'esthéticienne tient son téléphone à bout de bras devant une
   cliente installée. Monter encore se fait en changeant ce seul nombre. */
html { font-size: 17px; }
/* ATTENTION : aucune règle après celle-ci ne doit poser une font-size sur `html`.
   Le 18 septembre 2026, la ligne suivante disait `html, body { ... font-size:0.9375rem }`.
   Même spécificité que la règle ci-dessus, mais plus bas dans le fichier : c'est elle qui
   gagnait sur `html`. La racine valait donc 0,9375 × 16 = 15px, et le 17px demandé par
   Francis n'a jamais rien fait. Le texte n'a pas grossi d'un pixel pendant une journée. */
html, body { margin:0; background:var(--fond); color:var(--lire); font-family:var(--texte); line-height:1.55; }
body { font-size:0.9375rem; }
h1,h2,h3 { font-family:var(--titre); font-weight:500; color:var(--lire-fort); margin:0; line-height:1.3; }
h1{font-size:1.625rem} h2{font-size:1.125rem} h3{font-size:1rem}
p{margin:0} a{color:var(--accent);text-decoration:none;font-weight:600}
button{font:inherit}
#app { max-width:480px; margin:0 auto; min-height:100vh; display:flex; flex-direction:column; }
.ecran { display:flex; flex-direction:column; min-height:100vh; }
.ecran.sombre { background:var(--encre); color:#fff; } .ecran.sombre h2 { color:#fff; }
.barre { display:flex; align-items:center; justify-content:space-between; padding:22px 20px 12px; }
.barre .retour { background:none; border:0; padding:0; width:26px; height:26px; cursor:pointer; }
.barre .etape { font-size:0.8125rem; letter-spacing:.04em; color:var(--lire); } .sombre .barre .etape{ color:var(--brume) }
.contenu { padding:0 20px; display:flex; flex-direction:column; gap:14px; flex-grow:1; }
.bas { margin-top:auto; padding:14px 20px 26px; display:flex; flex-direction:column; gap:10px; border-top:1px solid var(--trait); background:var(--carte); position:sticky; bottom:0; }
.btn { display:flex; align-items:center; justify-content:center; gap:10px; height:52px; border-radius:10px; border:0; background:var(--niagara); color:#fff; font-weight:600; font-size:0.9375rem; letter-spacing:.02em; cursor:pointer; width:100%; }
.btn.second { background:var(--carte); color:var(--accent); border:1px solid var(--accent); }
.btn:disabled { opacity:.45; cursor:not-allowed; }
.carte { border:1px solid var(--trait); border-radius:12px; padding:14px 16px; }
.carte.choisie { border:1.5px solid var(--accent); }
.ligne { display:flex; align-items:center; gap:14px; padding:12px 0; border-bottom:1px solid var(--trait); }
.avatar { width:40px; height:40px; border-radius:50%; background:var(--menthe); color:#fff; display:flex; align-items:center; justify-content:center; font-weight:600; flex-shrink:0; }
.champ { display:flex; align-items:center; gap:10px; height:46px; border:1px solid var(--trait); border-radius:10px; padding:0 14px; width:100%; font:inherit; color:var(--lire-fort); background:var(--carte); }
/* Le texte d'invite doit rester lisible dans les deux thèmes sans devenir aussi présent
   que la vraie saisie. */
.champ::placeholder { color:var(--lire); opacity:.7; }
.hero { background:var(--encre); border-radius:14px; padding:22px 20px; color:#fff; display:flex; align-items:center; justify-content:space-between; gap:16px; cursor:pointer; }
/* En mode sombre, la page est déjà foncée : l'encre de la tuile s'y confond. On la
   creuse d'un cran et on la borde, pour qu'elle reste le bouton le plus visible de
   l'écran, qui est tout son rôle. */
.hero { background:var(--creux); }
:root[data-theme="sombre"] .hero { border:1px solid var(--trait); }
.hero p { color:var(--brume); font-size:0.875rem; }
.tuiles { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:12px; }
.tuile { border:1px solid var(--trait); border-radius:12px; padding:14px 16px; }
.tuile .n { font-family:var(--titre); font-size:1.5rem; color:var(--lire-fort); display:block; }
.tuile span:last-child { font-size:0.8125rem; }
.petit { font-size:0.8125rem; font-weight:500; } .muet { color:var(--lire); }
.encart { background:var(--menthe); color:#fff; border-radius:12px; padding:14px 16px; } .encart * { color:#fff; }
.puces { display:flex; gap:8px; flex-wrap:wrap; }
.puce { padding:6px 12px; border-radius:16px; border:1px solid var(--accent); color:var(--accent); font-size:0.8125rem; font-weight:600; background:none; cursor:pointer; }
.puce.active { background:var(--encre); color:#fff; border-color:var(--lire-fort); }
.indic { display:flex; flex-direction:column; gap:2px; padding:7px 0; }
.indic .haut { display:flex; align-items:center; gap:14px; }
.indic .nom { width:108px; color:var(--lire-fort); font-size:0.875rem; flex-shrink:0; }
.indic .sc { width:30px; text-align:right; font-weight:600; color:var(--lire-fort); }
.jauge { position:relative; height:6px; border-radius:3px; background:var(--trait); flex-grow:1; }
.jauge i { display:block; height:6px; border-radius:3px; background:var(--accent); }
.jauge b { position:absolute; top:-4px; width:2px; height:14px; background:var(--lire-fort); }
.indic .phrase { font-size:0.8125rem; padding-left:122px; }
/* La définition du problème de peau, repliée par défaut : l'esthéticienne la déplie
   quand une cliente demande « ça veut dire quoi ? ». Toujours là, jamais imposée. */
.indic .def { padding-left:110px; margin-top:3px; }
/* Le même dépliant sert ailleurs : les marques de la carte de soins, le déroulé d'un
   protocole. D'où des règles sur `details.def` et non plus seulement dans `.indic`. */
details.def > summary { font-size:0.8125rem; color:var(--accent); cursor:pointer; list-style:none; }
details.def > summary::-webkit-details-marker { display:none; }
details.def > summary::before { content:'＋ '; }
details.def[open] > summary::before { content:'－ '; }
details.def p { font-size:0.8125rem; color:var(--lire); margin:5px 0 0; line-height:1.55; max-width:62ch; }
/* Le prix d'un soin. Vide, le champ se borde en rouge : c'est ce qui fait voir d'un
   coup d'œil, dans une liste de quarante soins, lesquels ne sont pas encore offerts. */
.prix { width:66px; height:34px; border:1px solid var(--trait); border-radius:8px; padding:0 8px;
  font:inherit; font-size:0.875rem; text-align:right; color:var(--lire-fort); background:var(--carte); }
.prix:placeholder-shown { border-color:var(--terre); }
.score { font-family:var(--titre); font-size:3.375rem; color:var(--lire-fort); line-height:1; }
.photo { border-radius:12px; background:var(--ocean); object-fit:cover; }
.viseur { position:relative; width:100%; aspect-ratio:3/4; background:#000; border-radius:16px; overflow:hidden; }
.viseur video, .viseur img.guide { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.viseur img.guide { opacity:.35; pointer-events:none; }
.viseur .ovale { position:absolute; left:12%; right:12%; top:6%; bottom:10%; border:2px dashed var(--brume); border-radius:50%; }
.voyants { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:10px; }
.voyant { display:flex; align-items:center; justify-content:center; gap:6px; height:36px; border-radius:18px; border:1px solid var(--trait); color:#fff; font-size:0.8125rem; font-weight:600; }
.voyant.ok { background:#fff; color:var(--encre); border-color:#fff; } /* fond blanc fixe : texte encre, pas le jeton qui bascule */
.capture { width:78px; height:78px; border-radius:50%; border:3px solid #fff; background:none; margin:0 auto; display:flex; align-items:center; justify-content:center; cursor:pointer; }
.capture i { width:62px; height:62px; border-radius:50%; background:#fff; display:block; }
.capture:disabled { opacity:.45; border-color:var(--brume); } .capture:disabled i { background:var(--brume); }
.prio { display:flex; gap:14px; align-items:flex-start; }
.prio .num { font-family:var(--titre); font-size:1.375rem; color:var(--accent); line-height:1; }
.produit { display:flex; align-items:center; gap:12px; padding:10px 0; border-bottom:1px solid var(--trait); }
/* La vignette est soit une vraie photo de produit, soit un carré gris quand Odoo n'en
   a pas. Les deux doivent occuper exactement la même place, sinon la liste sautille
   pendant que les images arrivent. `object-fit: contain` parce qu'un flacon recadré en
   plein cadre perd son bouchon, et c'est au bouchon qu'on reconnaît un produit. */
.produit .vignette, img.vignette { width:54px; height:54px; border-radius:8px; background:var(--trait); flex-shrink:0; }
img.vignette { object-fit:contain; background:var(--carte); border:1px solid var(--trait); }
.ligne img.vignette { margin-right:2px; }
.chip { display:inline-flex; align-items:center; font-size:0.8125rem; font-weight:600; border-radius:10px; padding:2px 8px; }
.chip.ok { background:var(--menthe); color:#fff; } .chip.cmd { background:var(--encre); color:#fff; } .chip.last { border:1px solid var(--accent); color:var(--accent); }
.interrupteur { width:44px; height:26px; border-radius:13px; background:var(--trait); border:0; position:relative; cursor:pointer; }
.interrupteur.on { background:var(--niagara); } .interrupteur::after { content:""; position:absolute; top:3px; left:3px; width:20px; height:20px; border-radius:50%; background:#fff; transition:left .15s; } .interrupteur.on::after { left:21px; }
/* Le pad de signature garde un fond clair dans les deux thèmes : le trait est enregistré
   en image, et une signature tracée en pâle serait illisible partout ailleurs. */
.signature { height:110px; border:1px dashed var(--accent); border-radius:10px; width:100%; touch-action:none; background:#F7F8F8; }
.erreur { background:#fff; color:var(--encre); border-radius:14px; padding:18px; } /* idem : posé sur l'écran sombre */
.toast { position:fixed; left:50%; bottom:100px; transform:translateX(-50%); background:var(--encre); color:#fff; padding:10px 16px; border-radius:10px; font-size:0.875rem; z-index:9; }
.chargement { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:14px; flex-grow:1; color:var(--lire); }
.spin { width:36px; height:36px; border:3px solid var(--trait); border-top-color:var(--accent); border-radius:50%; animation:tourne 1s linear infinite; }
@keyframes tourne { to { transform:rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spin { animation:none; } }

/* ---- Agenda ---- */
.semaine { display:grid; grid-template-columns:repeat(7,minmax(0,1fr)); gap:4px; }
.jour { display:flex; flex-direction:column; align-items:center; gap:2px; padding:8px 0; border-radius:10px; border:1px solid transparent; cursor:pointer; }
.jour .n { font-family:var(--titre); font-size:1.125rem; color:var(--lire-fort); } .jour .l { font-size:0.8125rem; color:var(--lire); text-transform:uppercase; letter-spacing:.06em; }
.jour.actif { background:var(--encre); } .jour.actif .n, .jour.actif .l { color:#fff; }
.jour.ferme .n { color:var(--faible); }
.jour .pts { display:flex; gap:2px; height:4px; } .jour .pts i { width:4px; height:4px; border-radius:50%; background:var(--accent); } .jour.actif .pts i { background:#fff; }
.rdv { display:flex; gap:12px; padding:12px 0; border-bottom:1px solid var(--trait); align-items:flex-start; }
.rdv .h { width:52px; flex-shrink:0; font-weight:600; color:var(--lire-fort); font-variant-numeric:tabular-nums; }
.rdv .h small { display:block; font-weight:400; color:var(--lire); font-size:0.8125rem; }
.rdv .corps { flex-grow:1; display:flex; flex-direction:column; gap:4px; }
.rdv.annule .corps { opacity:.5; text-decoration:line-through; }
.rdv .actions { display:flex; gap:8px; flex-wrap:wrap; }
.mini { font-size:0.8125rem; font-weight:600; padding:6px 10px; border-radius:8px; border:1px solid var(--trait); background:var(--carte); color:var(--lire); cursor:pointer; }
.mini.p { background:var(--niagara); color:#fff; border-color:var(--niagara); }
/* Le bouton qui détruit. Il doit se voir, sans crier plus fort que le bouton principal
   de l'écran : bordé et en terre au repos, plein et rouge une fois armé. Le changement
   de couleur EST la confirmation, avec le changement de texte. */
.danger { display:flex; align-items:center; justify-content:center; gap:8px; width:100%;
  height:44px; border-radius:10px; background:var(--carte); color:var(--terre);
  border:1px solid var(--terre); font:inherit; font-weight:600; font-size:0.875rem; cursor:pointer; }
.danger[data-arme="1"] { background:#B3261E; border-color:#B3261E; color:#fff; height:auto;
  min-height:44px; padding:10px 14px; line-height:1.35; text-align:center; }
.danger:disabled { opacity:.5; cursor:not-allowed; }
.creneaux { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:8px; }
.creneau { height:40px; border-radius:8px; border:1px solid var(--trait); background:var(--carte); color:var(--lire-fort); font-weight:600; font-size:0.875rem; cursor:pointer; font-variant-numeric:tabular-nums; }
.creneau.choisi { background:var(--encre); color:#fff; border-color:var(--lire-fort); }
.libre { text-align:center; padding:24px 0; color:var(--lire); font-size:0.875rem; }
.nav-bas { position:sticky; bottom:0; background:var(--carte); border-top:1px solid var(--trait); display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); padding:10px 8px 22px; margin-top:auto; }
.nav-bas a { display:flex; flex-direction:column; align-items:center; gap:4px; font-size:0.8125rem; color:var(--lire); font-weight:400; }
.nav-bas a.actif { color:var(--lire-fort); font-weight:600; }
select.champ { appearance:none; background:var(--carte); }

/* ---- Tablettes et grands écrans ----
   Mesuré le 19 septembre 2026 : sur une tablette de 1180 pixels de large, l'application
   tenait dans une colonne de 480 pixels au centre, avec 350 pixels de fond vide de chaque
   côté. Lisible, mais c'était une application de téléphone posée sur un grand écran.

   La colonne s'élargit, et les deux longues listes répétitives, les indicateurs et la
   routine, passent sur deux colonnes. `break-inside: avoid` est ce qui empêche une fiche
   produit d'être coupée en deux par le changement de colonne.

   Rien ne change sous 900 pixels : le téléphone, qui reste l'appareil principal en
   cabine, garde exactement la mise en page dessinée pour lui. */
@media (min-width: 900px) {
  #app { max-width: 880px; }
  .colonnes { columns: 2; column-gap: 32px; }
  .colonnes > * { break-inside: avoid; }
  .tuiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .creneaux { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  /* Les boutons du bas n'ont plus à occuper toute la largeur : côte à côte, ils
     restent à portée de pouce sans s'étirer sur 880 pixels. */
  .bas { flex-direction: row-reverse; }
  .bas .btn { width: auto; flex: 1; }
}
