/* ==========================================================================
   Mon Journal de Bébé — feuille de style.
   Portée de la V18, avec les améliorations : en-tête de feuille collant,
   marges de timeline réduites, tooltip de groupe réactivé, grille de filtres
   sur N colonnes (piloté par --cat-cols), libellés de groupe sans « oui ».
   ========================================================================== */
:root {
  --bg: #FFF7EB; --card: #ffffff; --card2: #F2EFE9;
  --text: #1F1F1F; --muted: #6B6B6B; --border: #E6E1D6;
  --accent: #EFC05D; --accent-ink: #2A1B04;
  --shadow: 0 4px 18px rgba(120, 90, 20, .12);
  --radius: 18px; --star: #f2b01e;
  --app-max: 520px; --cat-cols: 6;
  /* Couleurs SÉMANTIQUES (danger/succès/info) — jamais réécrites en dur, ni
     en CSS ni en JS (règle CLAUDE.md). Elles étaient dupliquées 7 fois avant
     l'audit du 08/08/2026, dont 3 fois en JS, et n'avaient donc jamais été
     ajustées pour le thème sombre. */
  --danger: #d94f4f; --danger-ink: #ffffff;
  --success: #2fb6a3; --success-ink: #ffffff;
  --info: #3d9be0;
}
html[data-theme="dark"] {
  --bg: #1B1B1B; --card: #232323; --card2: #2A2A2A;
  --text: #F5F5F5; --muted: #BDBDBD; --border: #3A3A3A;
  --accent: #F6CA6E; --accent-ink: #1B1B1B;
  --shadow: 0 4px 18px rgba(0, 0, 0, .35);
  /* Éclaircies en sombre : les versions claires descendent sous le seuil de
     contraste AA sur fond #1B1B1B. */
  --danger: #ff7b7b; --danger-ink: #2A0A0A;
  --success: #4fd6c3; --success-ink: #06231F;
  --info: #6fb9ef;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
/* Icône Lucide générique (iconSvg(), voir render.js) — taille et alignement
   par défaut, chaque conteneur (badge/disc/bouton...) affine au besoin.
   vertical-align sur l'élément lui-même (pas son enrobage) : ignoré des
   conteneurs flex (où l'alignement vient de align-items), donc sans risque
   d'y ajouter cette règle globale — seuls les contextes de texte en ligne
   (ex. un titre "icône + nom") en ont besoin. */
.ico { width: 18px; height: 18px; vertical-align: -4px; flex: none; }
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg); color: var(--text);
  transition: background .25s, color .25s;
  /* Dégage juste la barre de nav fixe (~46px, icônes seules depuis le
     09/08/2026) + une petite marge — laissé à 86px après le passage aux
     icônes seules, l'écart en bas de chaque écran était devenu trop grand. */
  padding-bottom: 64px; overflow-x: hidden;
}
body.sheet-open { overflow: hidden; touch-action: none; }
.app { max-width: var(--app-max); margin: 0 auto; padding: 0 16px; }
/* Zone swipeable minimale : sans ça, un journal vide laisse #tab-home trop
   court, et le geste de changement de jour démarré sous le contenu visible
   tombe hors de l'élément écouté (voir bindSwipe dans app.js). */
#journal { min-height: 40vh; }
h1, h3, h4 { margin: 0; }
button { font-family: inherit; }

/* EN-TÊTE */
header {
  display: flex; align-items: center; justify-content: space-between;
  padding: calc(env(safe-area-inset-top) + 14px) 0 6px;
}
.baby { display: flex; align-items: center; gap: 12px; cursor: pointer; }
.header-icons { display: flex; align-items: center; gap: 8px; }
.icon-btn {
  position: relative; border: none; cursor: pointer; background: var(--card);
  color: var(--text); width: 38px; height: 38px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; font-size: 17px;
  box-shadow: var(--shadow); flex-shrink: 0;
}
.alert-badge {
  display: none; position: absolute; top: -3px; right: -3px; min-width: 18px; height: 18px;
  border-radius: 999px; background: var(--danger); color: var(--danger-ink); font-size: 10px; font-weight: 800;
  align-items: center; justify-content: center; padding: 0 4px; line-height: 1; box-shadow: 0 0 0 2px var(--bg);
}
.alert-badge.show { display: flex; }
/* Même traitement visuel que la cloche d'alertes (.icon-btn : rond + ombre),
   amélioration #32 — remplace l'ancienne pastille texte en forme de gélule. */
#offlineBadge { display: none; color: var(--muted); }
#offlineBadge.show { display: flex; }
.wifioff-ico { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.bell-ico { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.alert-row { display: flex; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--border); }
.alert-row:last-child { border-bottom: none; }
.alert-icon {
  width: 40px; height: 40px; border-radius: 50%; background: var(--card2);
  display: flex; align-items: center; justify-content: center; font-size: 19px; flex-shrink: 0;
}
.alert-icon .ico { width: 19px; height: 19px; }
.alert-body { flex: 1; min-width: 0; }
.alert-label { font-weight: 700; font-size: 14px; }
.alert-why { font-size: 12.5px; color: var(--muted); margin-top: 1px; }
.alert-actions { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.alert-actions .btn { padding: 7px 12px; font-size: 12.5px; width: auto; }
.avatar {
  width: 44px; height: 44px; border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), #e26d9b);
  display: flex; align-items: center; justify-content: center;
  font-size: 23px; background-size: cover; background-position: center;
}
.baby h1 { font-size: 18px; }
.baby .role { font-size: 12px; color: var(--muted); }

/* EN-TÊTE COLLANT */
.top-sticky { position: sticky; top: 0; z-index: 25; background: var(--bg); padding-bottom: 4px; }
.daybar { display: flex; align-items: center; gap: 8px; padding: 8px 2px; margin-top: 2px; }
.daybar .nav-d {
  background: var(--card); border: 1px solid var(--border); color: var(--text);
  width: 32px; height: 32px; border-radius: 9px; font-size: 15px; cursor: pointer;
}
.daybar .lbl { font-weight: 700; font-size: 14.5px; flex: 1; cursor: pointer; text-align: center; }
.circles { display: flex; gap: 7px; overflow-x: auto; padding: 5px 2px 3px; scrollbar-width: none; }
.circles::-webkit-scrollbar { display: none; }
.circle {
  /* min-width:0 annule le minimum automatique des flex items : sans lui, un
     libellé/ago non cassable plus large que 52px (ex. "Médicament") repousse
     la largeur réelle du bouton au-delà de 52px et désaxe le disque, centré
     via margin:auto DANS cette largeur devenue variable (amélioration #25). */
  flex: 0 0 52px; min-width: 0; text-align: center; cursor: pointer;
  border: none; background: none; color: var(--text);
}
.circle .disc {
  width: 42px; height: 42px; border-radius: 50%; margin: 0 auto 5px;
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; position: relative;
}
.circle .disc .ico { width: 20px; height: 20px; }
.circle .lbl {
  font-size: 9.5px; font-weight: 600; line-height: 1.1;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.circle .ago {
  display: block; font-size: 9.5px; color: var(--muted); margin-top: 2px; line-height: 1.05;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.circle .ago .ago-ico {
  width: 9px; height: 9px; vertical-align: -1px; margin-right: 1px;
  fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round;
}
/* Alerte active sur cette catégorie (C8b) — le point de chrono en cours a
   été remplacé par le halo animé ci-dessous, celui-ci reste un simple point
   (coin opposé) pour que les deux puissent coexister sans se chevaucher. */
.adot { position: absolute; top: -2px; left: -2px; width: 12px; height: 12px; border-radius: 50%; background: var(--danger); border: 2px solid var(--bg); }

/* Halo de chrono en cours : anneau/bordure animé dans la couleur de la
   catégorie, pour le contour rond de l'accueil (.disc.on) et la bordure de la
   carte "en cours" du journal (.journal-active). Base commune : technique du
   double masque (content-box vs plein cadre, XOR) — ne peint QUE l'anneau,
   quel que soit le rayon d'arrondi — border-radius: inherit fonctionne aussi
   bien pour un cercle que pour un rectangle arrondi. `currentColor` vient du
   `color:` posé en inline par render.js (couleur de la catégorie), donc
   jamais de couleur en dur ici. Le CONTENU du halo diffère en revanche : la
   rotation conique convient au cercle (une révolution = un tour visuel
   cohérent), mais sur la carte journal, très allongée, la même rotation
   déforme le trajet des reflets et donne l'impression d'un spinner cassé
   (signalé le 08/08/2026) — la carte utilise donc un dégradé qui glisse par
   translation plutôt que rotation, plus une texture de bruit (SVG
   feTurbulence) en fusion "overlay" pour un rendu scintillant/organique
   plutôt qu'un balayage trop géométrique. */
.circle .disc.on::before,
.journal-active::before {
  content: '';
  position: absolute;
  border-radius: inherit;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  pointer-events: none;
}

@keyframes chrono-shimmer { to { transform: rotate(1turn); } }
.circle .disc.on::before {
  inset: -5px; padding: 2px;
  background: conic-gradient(from 0deg,
    currentColor 0%,
    color-mix(in srgb, currentColor 55%, white) 6%,
    currentColor 12%,
    currentColor 45%,
    color-mix(in srgb, currentColor 55%, white) 51%,
    currentColor 57%,
    currentColor 100%);
  animation: chrono-shimmer 4s linear infinite;
}

/* .journal-active garde une bordure transparente de la même épaisseur (pas
   de border:none) pour ne pas décaler le contenu de 1.5px quand un chrono
   démarre/s'arrête (box-sizing:border-box global). Le halo compense cet
   inset en débordant du même montant, pour retomber exactement là où
   l'ancienne bordure pleine se dessinait. */
@keyframes journal-shimmer-sweep { to { background-position: -200% 0, -60px -45px; } }
.journal-active::before {
  inset: -1.5px; padding: 1.5px;
  background-image:
    linear-gradient(100deg,
      currentColor 0%,
      color-mix(in srgb, currentColor 60%, white) 10%,
      currentColor 22%,
      currentColor 100%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60' height='60'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.4'/%3E%3C/svg%3E");
  background-size: 220% 100%, 60px 60px;
  background-blend-mode: overlay, normal;
  animation: journal-shimmer-sweep 3.2s ease-in-out infinite alternate;
}
@media (prefers-reduced-motion: reduce) {
  .circle .disc.on::before, .journal-active::before { animation: none; }
}

/* ACCUEIL — carte récap */
.card { background: var(--card); border-radius: var(--radius); border: 1px solid var(--border); box-shadow: var(--shadow); }
.agecard { margin: 8px 0; }
.agecard .top { display: flex; align-items: center; padding: 11px 12px; gap: 10px; }
.agecard .top .age { flex: 1; font-size: 14px; font-weight: 700; color: var(--text); }
.agecard .top .ic { background: none; border: none; color: var(--muted); font-size: 18px; cursor: pointer; width: 30px; }
.compact { display: flex; flex-wrap: wrap; gap: 5px 6px; padding: 0 10px 10px; }
.cc {
  display: inline-flex; align-items: center; gap: 3px;
  border: 1.5px solid var(--border); background: var(--card2);
  border-radius: 16px; padding: 4px 7px; font-size: 12px; cursor: pointer; color: var(--text);
}
.cc .ico { width: 14px; height: 14px; }
.cc.on { border-color: currentColor; }
.detail { padding: 0 6px 8px; }
.drow { display: flex; align-items: center; gap: 10px; padding: 11px 10px; border-top: 1px solid var(--border); cursor: pointer; }
.drow .e { font-size: 18px; width: 26px; display: inline-flex; align-items: center; justify-content: center; }
.drow .e .ico { width: 17px; height: 17px; }
.drow .n { font-weight: 700; min-width: 20px; }
.drow .sm { flex: 1; color: var(--muted); font-size: 13px; white-space: normal; line-height: 1.32; }
.drow .chk { color: var(--accent); font-size: 16px; opacity: .25; }
.drow.on .chk { opacity: 1; }

/* ACCUEIL — note du jour */
.daynote { margin: 8px 0; display: flex; align-items: center; gap: 12px; padding: 12px 14px; cursor: pointer; }
.daynote .st { font-size: 15px; letter-spacing: 1px; color: var(--star); }
.daynote .cm { flex: 1; font-size: 13px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.daynote .ed { color: var(--muted); }
.daynote .ed .ico { width: 14px; height: 14px; }

/* ACCUEIL — journal */
.sect { font-size: 12px; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); font-weight: 700; margin: 18px 4px 10px; }
.sect-row { display: flex; align-items: center; justify-content: space-between; }
.sect-row .sect { margin: 18px 0 10px; }
.search-btn { background: none; border: none; color: var(--muted); cursor: pointer; padding: 6px; margin: 10px 0 6px; }
.search-btn svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; }
.search-btn.on { color: var(--accent); }

.dfield { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.dlabel { font-size: 11px; color: var(--muted); padding-left: 2px; }
#apptsUpcoming { margin-top: 12px; }
/* Filtres repliés (09/08/2026) : rien entre le titre et la liste ne justifie
   le même écart que lorsque les filtres sont dépliés. Marge NÉGATIVE
   (13/08/2026) : le titre porte déjà 10px de marge basse et le bouton de
   filtre 6px, un simple `margin-top: 0` laissait encore un blanc trop
   large. Remonter la liste est le seul levier qui n'oblige pas à toucher
   aux marges partagées par tous les titres de section. */
#apptsUpcoming.filters-closed { margin-top: -8px; }
/* Les deux listes vivent dans deux conteneurs distincts depuis que le bouton
   d'ajout les suit toutes les deux : le sélecteur de voisinage
   (`.appt-section + .appt-section`) ne s'applique donc plus, l'écart est posé
   ici (13/08/2026). */
#apptsPast { margin-top: 12px; }
/* Feuille de recherche (journal + notes de jour) */
.search-input { width: 100%; margin-bottom: 4px; }
.search-empty { text-align: center; color: var(--muted); padding: 30px 12px; font-size: 13.5px; }
.search-group { font-size: 11px; text-transform: uppercase; letter-spacing: .4px; color: var(--muted); font-weight: 700; margin: 18px 4px 8px; }
.search-group:first-of-type { margin-top: 6px; }
.search-hit { display: block; width: 100%; text-align: left; background: var(--card); border: 1px solid var(--border);
  border-radius: 12px; padding: 9px 12px; margin-bottom: 7px; cursor: pointer; color: var(--text); }
.search-hit .d { font-size: 11.5px; color: var(--muted); margin-bottom: 2px; }
.search-hit .d .ico { width: 12px; height: 12px; vertical-align: -2px; }
.set-row .lab .ico { width: 15px; height: 15px; }
.search-hit .n { font-size: 13.5px; line-height: 1.35; }
.search-hit mark { background: color-mix(in srgb, var(--accent) 55%, transparent); color: inherit; border-radius: 3px; padding: 0 1px; }
.event {
  background: var(--card); border-radius: 13px; border: 1px solid var(--border);
  box-shadow: var(--shadow); padding: 10px 12px; display: flex; align-items: center;
  gap: 11px; margin-bottom: 7px; cursor: pointer;
}
.event .badge { width: 36px; height: 36px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 18px; flex-shrink: 0; }
.event .badge .ico { width: 18px; height: 18px; }
.event .info { flex: 1; min-width: 0; }
.event .info .t { font-weight: 600; font-size: 14px; display: flex; align-items: center; gap: 6px; }
.event .info .t .stars { font-size: 11px; color: var(--star); letter-spacing: .5px; font-weight: 400; }
.event .info .s { font-size: 12.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.event .rt { font-size: 12.5px; color: var(--muted); text-align: right; white-space: nowrap; }
.event .rt .veille { color: var(--accent); font-weight: 600; }
.event.cont { opacity: .85; }
.journal-filtered .event .info .s { white-space: normal; overflow: visible; text-overflow: clip; line-height: 1.35; }
.interval { display: flex; justify-content: center; margin: -2px 0 7px; }
.interval span { background: var(--card2); border: 1px solid var(--border); border-radius: 14px; padding: 3px 12px; font-size: 12px; color: var(--muted); }
.empty { text-align: center; color: var(--muted); padding: 26px 12px; font-size: 14px; line-height: 1.5; }
/* Décoration très discrète au-dessus du texte d'état vide (C7) — fill:none
   + stroke conservent le tracé fin d'origine, opacité réduite pour rester en
   retrait du texte plutôt que rivaliser avec lui. */
.empty-deco {
  display: block; width: 34px; height: 34px; margin: 0 auto 8px;
  fill: none; stroke: currentColor; stroke-width: 4; stroke-linecap: round; stroke-linejoin: round;
  color: var(--muted); opacity: .45;
}
.journal-active { border: 1.5px solid transparent; position: relative; background: var(--card); }
.journal-active .info .s { white-space: normal; }
.chrono-live { font-variant-numeric: tabular-nums; }
.chrono-actions { display: flex; gap: 8px; margin-left: auto; align-items: center; }
.chrono-ico { width: 32px; height: 32px; border-radius: 999px; border: none; display: flex; align-items: center; justify-content: center; cursor: pointer; flex: 0 0 auto; }
.chrono-ico.stop { background: var(--danger); }
/* Fond toujours sombre (jamais dérivé de --text, qui passe au blanc cassé en
   dark et inversait le contraste de la croix blanche — signalé le 08/08/2026,
   amélioration #29) : une croix blanche reste lisible sur ce noir translucide
   quel que soit le thème. */
.chrono-ico.cancel { background: rgba(0, 0, 0, .55); }
.chrono-ico svg { width: 14px; height: 14px; fill: #fff; }
.chrono-ico.cancel svg { fill: none; stroke: #fff; stroke-width: 2; stroke-linecap: round; }

/* BARRE DE NAVIGATION */
.nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  background: var(--card); border-top: 1px solid var(--border);
  display: flex; padding: 6px 4px calc(env(safe-area-inset-bottom) + 6px);
}
.nav button {
  flex: 1; background: none; border: none; color: var(--muted); cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  font-size: 10px; padding: 6px 0; transition: .15s ease;
}
.nav button.on { color: var(--accent); background: color-mix(in srgb, var(--accent) 13%, transparent); border-radius: 14px; }
.nav button .e { display: flex; }
.nav button .e svg { width: 22px; height: 22px; display: block; }
.nav button svg { stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
/* Icônes seules, sans nom d'écran sous chaque bouton (09/08/2026) : libère
   la place pour un 6e onglet sans surcharger la barre. Le nom reste
   accessible en appui long (infobulle, comme #26/U4) et via aria-label
   (posé sur le bouton en même temps que ce texte, voir applyStaticLabels) —
   display:none plutôt qu'un masquage visuel seul, pour ne jamais faire
   annoncer le nom deux fois par un lecteur d'écran (aria-label + .lb). */
.nav .lb { display: none; }
.tab { display: none; }
.tab.on { display: block; }

/* CHRONOLOGIE */
/* Le sélecteur grille/journées a disparu le 13/08/2026 : les deux vues sont
   devenues deux écrans distincts (voir index.html). */
.periodselect { margin: 8px 0 10px; }
.datepair { display: none; gap: 8px; margin: 0 0 12px; }
.datepair.show { display: flex; }
.datepair input { min-width: 0; }

/* Filtres de catégories : grille auto-remplie, icônes compactes pour en
   afficher davantage par ligne (amélioration U7). */
.tl-filter {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(38px, 1fr));
  gap: 6px; padding: 6px 2px 12px; position: relative; justify-items: center;
}
.fic {
  position: relative; width: 100%; max-width: 38px; aspect-ratio: 1 / 1; border-radius: 10px;
  border: 1.5px solid var(--border); background: var(--card); font-size: 16px;
  cursor: pointer; opacity: .35; display: flex; align-items: center; justify-content: center;
}
.fic .ico { width: 16px; height: 16px; }
.fic.on { opacity: 1; background: color-mix(in srgb, currentColor 16%, var(--card)); border-color: currentColor; }
.fic:not(.on) { background: var(--card); color: var(--muted) !important; }
/* Filtre par choix (U60) : icône entonnoir discrète sur les catégories qui
   ont des choix (appui long pour l'ouvrir) — plus autoporteur qu'un simple
   point de couleur (retour du 09/08/2026). */
.fic-filter-ico {
  position: absolute; bottom: 2px; right: 2px; width: 9px; height: 9px;
  fill: none; stroke: currentColor; stroke-width: 2.5; stroke-linejoin: round;
  opacity: .55; pointer-events: none;
}
.fic.filtered { border-width: 2px; box-shadow: 0 0 0 2px color-mix(in srgb, currentColor 25%, transparent); }
.tl-choice-active {
  display: none; align-items: center; gap: 8px; margin: -6px 2px 10px; padding: 6px 10px;
  border-radius: 12px; background: var(--card2); border: 1.5px solid var(--border);
  font-size: 12.5px; font-weight: 600; width: fit-content;
}
.tl-choice-active.show { display: flex; }
.tl-choice-active .ic { background: none; border: none; color: var(--muted); cursor: pointer; font-size: 15px; padding: 0; }
#tlTip {
  position: fixed; background: var(--text); color: var(--bg); padding: 5px 10px;
  border-radius: 8px; font-size: 12px; z-index: 70; display: none;
  pointer-events: none; white-space: nowrap; text-align: center; line-height: 1.4;
}
/* Marge gauche réduite pour les dates & l'axe des heures (amélioration #7).
   Graduations toutes les 3h depuis le 12/08/2026 (9 repères au lieu de 5) :
   les libellés extrêmes sont ancrés sur les bords, les autres répartis entre
   eux — `justify-content: space-between` place ainsi chaque « Nh » très
   exactement au-dessus de sa position sur la piste. */
.tl-hours { display: flex; justify-content: space-between; font-size: 9px; color: var(--muted); padding: 0 0 4px 30px; }
.tl-row { display: flex; align-items: center; gap: 6px; margin-bottom: 5px; }
.tl-row .d { width: 26px; font-size: 10px; color: var(--muted); text-align: right; }
.track { flex: 1; position: relative; height: 22px; background: var(--card); border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
/* Amélioration #33 : les barres/tics prennent toute la hauteur de la piste
   (avant : insets top de quelques px qui laissaient une bande vide en haut
   et en bas). */
.bar { position: absolute; top: 0; height: 100%; border-radius: 4px; opacity: .85; }
.tick { position: absolute; top: 0; width: 3px; height: 100%; border-radius: 2px; }
/* Barre « maintenant » (12/08/2026), sur la seule ligne d'aujourd'hui.
   `top/bottom: 0` plutôt qu'une hauteur fixe : elle traverse aussi bien la
   piste repliée que l'empilement de sous-pistes d'une journée dépliée. Le
   liseré clair autour la garde lisible par-dessus une barre de catégorie de
   couleur proche. */
.tl-now {
  position: absolute; top: 0; bottom: 0; width: 2px; z-index: 3;
  background: var(--danger); pointer-events: none;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--card) 70%, transparent);
}
/* Journée dépliée : espace haut/bas resserré (amélioration #8). */
.tl-row.exp { align-items: flex-start; }
/* Amélioration #34 : plus de rectangle (fond/bordure de la piste unique)
   autour des sous-lignes par groupe une fois la journée dépliée — chaque
   sous-ligne (.grouptrack) porte déjà son propre encadré, l'ancien
   conteneur ne faisait plus que rajouter une boîte dans la boîte. Le padding
   horizontal disparaît aussi pour que les sous-lignes filent sur toute la
   largeur. */
.tl-row.exp .track { height: auto; min-height: 0; overflow: visible; padding: 2px 0; background: none; border: none; border-radius: 0; }
.tl-row.exp .d { font-weight: 700; color: var(--text); }
.grouptrack { height: 22px; position: relative; background: var(--card2); border: 1px solid var(--border); border-radius: 7px; margin: 3px 0; overflow: hidden; cursor: pointer; }
.grouptrack:first-child { margin-top: 0; }
.grouptrack:last-child { margin-bottom: 0; }

/* Vue « Journées » */
/* Date + étoiles sur une ligne, commentaire en dessous sur toute la
   largeur (10/08/2026) — auparavant une colonne de gauche étroite pour
   date/étoiles (empilées) et le commentaire compressé à droite. */
.dayline { display: flex; flex-direction: column; gap: 4px; padding: 9px 12px; border-bottom: 1px solid var(--border); cursor: pointer; }
.dayline:last-child { border-bottom: none; }
.dayline-head { display: flex; align-items: center; gap: 8px; }
.dayline .dd { font-size: 12px; color: var(--muted); }
.dayline .st { color: var(--star); font-size: 13px; letter-spacing: 1px; line-height: 1.1; }
.dayline-body { min-width: 0; }
.dayline .cm { font-size: 13px; white-space: normal; line-height: 1.35; }
/* Jalons atteints ce jour-là, sous la note (09/08/2026) : puces cliquables
   individuellement vers l'écran "Premières fois" (goToMilestone). */
.day-mstones { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.day-mstone {
  display: inline-flex; align-items: center; gap: 5px; padding: 4px 9px 4px 6px;
  border-radius: 12px; background: color-mix(in srgb, var(--accent) 16%, var(--card2));
  color: var(--text); font-size: 11.5px; font-weight: 600; cursor: pointer;
}
.day-mstone svg { width: 13px; height: 13px; }

/* GRAPHIQUES */
.controls { display: flex; gap: 10px; margin-bottom: 14px; }
select, .field {
  width: 100%; padding: 12px; border: 1.5px solid var(--border); border-radius: 12px;
  font-size: 15px; background: var(--card); color: var(--text);
}
.gcard { margin-bottom: 14px; padding: 12px 14px; }
.gcard h4 { font-size: 14px; }
.gcard .gk { font-size: 12px; color: var(--muted); margin: 2px 0 4px; }
/* Commandes d'un graphique (12/08/2026) : réglages puis plein écran, en haut
   à droite de la carte. L'engrenage s'allume dès qu'un réglage s'écarte du
   défaut — sans quoi rien ne signalerait, panneau refermé, qu'un filtre ou
   une agrégation restent actifs. */
.gcard-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.gcard-head h4 { flex: 1; min-width: 0; }
.gcard-actions { display: flex; align-items: center; gap: 2px; flex: none; }
.chart-icon-btn { background: none; border: none; color: var(--muted); cursor: pointer; padding: 4px; display: flex; }
.chart-icon-btn svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.chart-icon-btn.on { color: var(--accent); }

/* Vue tableau : mêmes données, même agrégation, mêmes filtres que le
   graphique. Le défilement horizontal reste DANS le tableau (jamais la page
   entière) quand les séries sont nombreuses, et l'en-tête colle pour garder
   les noms de séries en vue sur une longue période. */
.chart-table-wrap { overflow-x: auto; max-height: 60vh; overflow-y: auto; margin-top: 6px; }
.chart-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.chart-table th, .chart-table td { padding: 7px 8px; text-align: right; white-space: nowrap; border-bottom: 1px solid var(--border); }
.chart-table th:first-child, .chart-table td:first-child { text-align: left; position: sticky; left: 0; background: var(--card); }
.chart-table thead th { position: sticky; top: 0; z-index: 2; background: var(--card); color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .3px; }
.chart-table thead th:first-child { z-index: 3; }
.chart-table td.tot { font-weight: 700; }
.chart-table tbody tr:last-child td { border-bottom: none; }

/* Plein écran d'un graphique : réglages en bandeau sous le titre (pas de
   feuille imbriquée — `sheet2` est déjà occupé par le plein écran lui-même),
   puis le graphique en grand. Les réglages restent compacts : la hauteur
   utile est précisément ce qu'on vient chercher ici. */
.chart-fs-opts { border-bottom: 1px solid var(--border); padding-bottom: 10px; margin-bottom: 10px; }
.chart-fs-opts .flabel { margin: 8px 0 4px; }
.chart-fs-opts .toggle button { padding: 8px; font-size: 12.5px; }
.chart-fs-body .chart { height: 46vh; }
.chart-fs-body .chart-table-wrap { max-height: 72vh; }
.chart-fs-body .col { flex: 1 0 34px; }
.chartwrap { position: relative; padding-top: 24px; margin-top: 4px; }
.chart {
  display: flex; align-items: stretch; gap: 4px; height: 150px;
  overflow-x: auto; overflow-y: visible; scrollbar-width: thin; touch-action: pan-x;
}
.chart::-webkit-scrollbar { height: 5px; }
.chart::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
.col { flex: 1 0 26px; display: flex; flex-direction: column; align-items: center; height: 100%; }
.col .vlab { font-size: 8px; color: var(--muted); height: 12px; line-height: 12px; }
.col .bw { flex: 1; width: 100%; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; gap: 0; position: relative; overflow: visible; }
.col .bar2, .col .seg { width: 74%; }
.col .bar2 { background: var(--accent); border-radius: 6px 6px 0 0; min-height: 2px; }
.col .seg { display: block; flex: none; margin: 0; padding: 0; border: 0; border-radius: 0; min-height: 2px; }
/* :first-of-type/:last-of-type, PAS :first-child/:last-child : .bw précède
   souvent ses .seg d'un <span class="stat-total"> (le total posé au-dessus
   de la barre) — position:absolute le sort du FLUX visuel, mais pas de
   l'arbre DOM, donc il compte quand même comme premier enfant. Résultat
   avec :first-child : plus AUCUN segment n'était jamais "premier enfant"
   dès qu'un total s'affichait (le cas courant), donc plus aucune barre
   empilée n'était arrondie en haut. :first-of-type/:last-of-type ignorent
   ce <span> (autre type d'élément) et ciblent le premier/dernier <div class="seg">
   quel que soit ce qui les précède.
   :last-of-type AVANT :first-of-type : quand une colonne n'a qu'un seul
   segment visible ce jour-là (fréquent — le groupe "confort" n'a qu'une
   catégorie), le même <div> est à la fois premier ET dernier de son type.
   À spécificité égale, la règle déclarée en dernier l'emporte : en mettant
   :first-of-type après, l'arrondi du sommet gagne dans ce cas au lieu
   d'être annulé par le "pas d'arrondi" du bas — sans rien changer aux
   colonnes à plusieurs segments, où les deux règles visent des éléments
   différents. */
.col .seg:last-of-type { border-radius: 0; }
.col .seg:first-of-type { border-radius: 6px 6px 0 0; }
.col .cl { font-size: 8px; color: var(--muted); margin-top: 3px; height: 12px; white-space: nowrap; }
.stat-total { position: absolute; left: 50%; transform: translateX(-50%); font-size: 8px; color: var(--muted); line-height: 1; white-space: nowrap; pointer-events: none; z-index: 5; }
.scrub-line { position: absolute; top: 16px; bottom: 22px; width: 2px; background: var(--accent); display: none; pointer-events: none; z-index: 2; }
.scrub-label {
  position: absolute; top: -2px; left: 50%; transform: translateX(-50%);
  background: var(--text); color: var(--bg); padding: 3px 10px; border-radius: 10px;
  font-size: 11px; display: none; z-index: 3; white-space: nowrap; pointer-events: none;
}
.stack-tip { white-space: pre-line; text-align: center; line-height: 1.4; }
.legend { display: flex; flex-wrap: wrap; gap: 6px 12px; margin-top: 10px; }
.legend .lg { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; }
.legend .lg i { width: 10px; height: 10px; border-radius: 3px; }
.gmetric-tabs { display: flex; gap: 5px; margin: 8px 0; flex-wrap: wrap; }
.gmetric-tabs button { border: 1px solid var(--border); background: var(--card2); color: var(--muted); border-radius: 10px; padding: 7px 8px; font-size: 11px; font-weight: 800; }
.gmetric-tabs button.on { background: var(--card); color: var(--text); border-color: var(--accent); }
.gmetric-tabs button[data-order="1"] { order: 1; }
.gmetric-tabs button[data-order="2"] { order: 2; }
.gmetric-tabs button[data-order="3"] { order: 3; }
.gmetric-tabs button[data-order="4"] { order: 4; }
.gmetric-tabs button[data-order="5"] { order: 5; }

/* CROISSANCE */
.growth-wrap { position: relative; touch-action: none; }
.growth-line { position: absolute; top: 0; bottom: 18px; width: 2px; background: var(--accent); display: none; pointer-events: none; }
.growth-label { position: absolute; top: 2px; left: 50%; transform: translateX(-50%); background: var(--text); color: var(--bg); padding: 3px 8px; border-radius: 10px; font-size: 11px; display: none; pointer-events: none; white-space: nowrap; z-index: 2; }
.glist { margin-top: 14px; }
.grow-row { display: flex; gap: 12px; padding: 11px 12px; border-bottom: 1px solid var(--border); cursor: pointer; font-size: 14px; }
.grow-row:last-child { border-bottom: none; }
.grow-row .gd { color: var(--muted); flex: 1; }

/* "Premières fois" (C10) : badge rond thème (jaune atteint, neutre pas
   encore) — jamais de rouge/urgence pour un jalon pas encore marqué,
   qu'il soit dans sa tranche d'âge typique ou après (proactif sans mettre
   la pression, exigence du 09/08/2026). */
.mstone-row { display: flex; align-items: center; gap: 12px; padding: 11px 12px; border-bottom: 1px solid var(--border); cursor: pointer; }
.mstone-row:last-child { border-bottom: none; }
.mstone-badge {
  flex: none; width: 38px; height: 38px; border-radius: 50%; display: flex; align-items: center;
  justify-content: center; background: var(--card2); color: var(--muted); border: 1.5px solid var(--border);
}
.mstone-badge svg { width: 19px; height: 19px; }
.mstone-badge.on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.mstone-body { flex: 1; min-width: 0; }
.mstone-label { font-size: 14px; }
.mstone-sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
.mstone-row .chk { color: var(--success); font-weight: 700; }
.mstone-row.flash { animation: mstoneFlash 1.2s ease; }
@keyframes mstoneFlash {
  0%, 100% { background: transparent; }
  25% { background: color-mix(in srgb, var(--accent) 25%, transparent); }
}
/* Sélecteur d'icônes partagé (catégories, jalons, C10/09/08/2026 puis
   généralisé le 09/08/2026 au dépôt Lucide complet, 1768 icônes, avec
   onglets de catégorie officiels en plus de la recherche). */
.icon-cat-tabs { display: flex; gap: 6px; overflow-x: auto; padding: 10px 0 2px; scrollbar-width: none; }
.icon-cat-tabs::-webkit-scrollbar { display: none; }
.icon-cat-tab {
  flex: none; border: 1.5px solid var(--border); background: var(--card2); color: var(--text);
  border-radius: 14px; padding: 6px 12px; font-size: 12.5px; cursor: pointer; white-space: nowrap;
}
.icon-cat-tab.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, transparent); font-weight: 600; }
/* Plein écran (09/08/2026) : la grille grandit avec son contenu, c'est
   .sheet (100dvh en mode fullscreen) qui défile, pas la grille elle-même —
   plus besoin de la borner en hauteur comme dans l'ancienne feuille du bas. */
.icon-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(40px, 1fr)); gap: 8px; margin: 6px 0 4px; }
.icon-opt {
  aspect-ratio: 1 / 1; border-radius: 10px; border: 1.5px solid var(--border); background: var(--card2);
  color: var(--muted); display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.icon-opt svg { width: 18px; height: 18px; }
.icon-opt.on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }

/* Rendez-vous (C11, révision du 09/08/2026) : bouton de suppression compact
   réutilisé pour observations/traitements/questions — toujours au sein
   d'une ligne flex, jamais positionné en absolu. */
.qa-remove { background: none; border: none; color: var(--muted); cursor: pointer; font-size: 13px; padding: 4px; line-height: 1; flex: none; }

/* Listes de préparation (observations/traitements/questions, révision du
   09/08/2026) : UNE bordure pour toute la section (.card, réutilisé tel
   quel) plutôt qu'une par ligne — chaque ligne se sépare de la suivante
   par un simple liseré (comme .set-row), et les champs à l'intérieur
   perdent leur cadre/fond individuel pour ne pas empiler les boîtes.
   Rendu seulement si la liste a au moins une ligne (voir renderAppointmentEditor) —
   une carte vide avant le bouton "+ Ajouter" n'apporterait rien. */
.qa-list { margin-bottom: 8px; }
.qa-list > * { padding: 10px 12px; border-bottom: 1px solid var(--border); }
.qa-list > *:last-child { border-bottom: none; }
.obs-row .field, .qa2-q, .qa2-r {
  border: none; background: transparent; padding: 4px 2px; border-radius: 0;
}
.qa2-r { min-height: 40px; border-top: 1px solid var(--border); border-radius: 0; padding-top: 8px; }

.obs-row { display: flex; gap: 8px; align-items: center; }
.obs-row .field { flex: 1; min-width: 0; font-size: 13px; }

.flabel-row { display: flex; justify-content: space-between; align-items: center; margin: 14px 0 6px; }
.flabel-row .flabel { margin: 0; }

.icon-btn-sm { background: none; border: none; color: var(--muted); cursor: pointer; padding: 4px; display: flex; }
.icon-btn-sm svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; }

/* Questions minimalistes : ligne compacte (pastille répondue/pas de
   réponse + question + chevron), réponse repliée par défaut. */
.qa2-head { display: flex; align-items: center; gap: 6px; }
.qa2-head .qa2-q { flex: 1; min-width: 0; font-size: 13px; }
.qa2-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--border); flex: none; }
.qa2-dot.on { background: var(--success); }
.qa2-toggle { background: none; border: none; color: var(--muted); cursor: pointer; padding: 4px; flex: none; display: flex; }
.qa2-toggle svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; transition: transform .15s; }
.qa2-toggle.open svg { transform: rotate(180deg); }
.qa2-r { margin-top: 6px; font-size: 13px; }

/* Suivi (blocs) : bouton de retrait en médaillon flottant au coin du bloc. */
.block-wrap { margin-bottom: 10px; }
.block-head { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.block-collapse-btn {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 6px; background: none; border: none;
  color: var(--text); font-size: 13px; font-weight: 600; padding: 4px 0; cursor: pointer; text-align: left;
}
.block-collapse-btn span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.block-collapse-btn .chev { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; flex: none; transition: transform .15s; }
.block-collapse-btn .chev.open { transform: rotate(180deg); }
.block-remove { flex: none; background: none; border: none; color: var(--muted); cursor: pointer; font-size: 13px; padding: 4px; line-height: 1; }

/* Réordonnancement compact (observations/traitements/questions du rdv) —
   variante réduite de .move-btn (Réglages > Catégories), ces lignes portant
   déjà plusieurs autres contrôles. */
.reorder-mini { display: flex; flex-direction: column; gap: 1px; flex: none; }
.reorder-mini button {
  width: 18px; height: 15px; border: none; background: var(--card2); color: var(--muted);
  border-radius: 4px; font-size: 8px; line-height: 1; display: flex; align-items: center;
  justify-content: center; cursor: pointer; padding: 0;
}
.reorder-mini button:disabled { opacity: .3; }

/* Indicateur d'humeur d'une observation (positif/neutre/négatif) — pastille
   discrète en mode lecture, code couleur sémantique (jamais de couleur en
   dur). Cycle sur clic : aucun -> positif -> neutre -> négatif -> aucun. */
.mood-dot { width: 15px; height: 15px; border-radius: 50%; border: 1.5px solid var(--border); background: transparent; flex: none; cursor: pointer; padding: 0; }
.mood-dot.mood-positive { background: var(--success); border-color: var(--success); }
.mood-dot.mood-neutral { background: var(--muted); border-color: var(--muted); }
.mood-dot.mood-negative { background: var(--danger); border-color: var(--danger); }

/* RÉGLAGES */
.set-row { padding: 13px 14px; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.set-row:last-child { border-bottom: none; }
.set-row .lab { font-size: 14px; }
.set-row .sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
.btn { border: none; background: var(--accent); color: var(--accent-ink); font-weight: 700; padding: 10px 14px; border-radius: 12px; cursor: pointer; font-size: 13px; }
.btn.ghost { background: transparent; color: var(--muted); border: 1px solid var(--border); font-weight: 600; }
.group-row { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--border); cursor: pointer; }
.group-row:last-child { border-bottom: none; }
.group-row .gn { font-weight: 700; flex: 1; }
.group-row .gf { font-size: 11px; color: var(--muted); margin-top: 2px; }
.catrow { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--border); cursor: default; }
.catrow:last-child { border-bottom: none; }
.catrow .nm, .catrow .e { cursor: pointer; }
.catrow .e { font-size: 20px; width: 26px; display: inline-flex; align-items: center; justify-content: center; }
.catrow .e .ico { width: 18px; height: 18px; }
.catrow .nm { flex: 1; font-weight: 600; }
.catrow .grp { font-size: 11px; color: var(--muted); font-weight: 500; margin-top: 2px; }
.reorder-actions { display: flex; gap: 6px; margin-left: auto; }
.move-btn {
  width: 32px; height: 32px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--card2); color: var(--text); font-weight: 800; font-size: 14px;
  display: flex; align-items: center; justify-content: center;
}
.move-btn:disabled { opacity: .28; }

/* FEUILLES MODALES */
.overlay {
  position: fixed; inset: 0; background: rgba(20, 15, 40, .5); z-index: 50;
  display: none; align-items: flex-end; justify-content: center; padding: 0;
}
.overlay.show { display: flex; }
#overlay2 { z-index: 55; }
/* Sélecteur d'icônes (révision du 09/08/2026) : plein écran plutôt qu'une
   feuille du bas — un catalogue de 1768 icônes a besoin de toute la
   hauteur disponible, pas d'un tiers d'écran. */
#overlay2.fullscreen { align-items: stretch; padding: 0; }
#overlay2.fullscreen .sheet {
  max-width: none; width: 100%; height: 100dvh; max-height: 100dvh;
  border-radius: 0; padding-top: env(safe-area-inset-top); animation: none;
}
.sheet {
  background: var(--card); width: 100%; max-width: var(--app-max);
  border-radius: 22px 22px 0 0; padding: 0 18px calc(env(safe-area-inset-bottom) + 18px);
  max-height: 100vh; height: auto; overflow-y: auto; animation: up .22s ease; position: relative;
}
@keyframes up { from { transform: translateY(100%); } to { transform: translateY(0); } }
/* En-tête de feuille collant : poignée + croix + titre restent visibles (amélioration #1). */
.sheet .sheet-head {
  position: sticky; top: 0; z-index: 3; background: var(--card);
  padding: 16px 0 8px; margin-bottom: 4px;
}
.sheet .grab { width: 40px; height: 4px; background: var(--border); border-radius: 2px; margin: 0 auto 12px; }
.sheet .x {
  position: absolute; top: 12px; right: 0; width: 32px; height: 32px; border-radius: 50%;
  border: none; background: var(--card2); color: var(--muted); font-size: 17px; cursor: pointer; z-index: 2;
}
.sheet h3 { font-size: 17px; display: flex; align-items: center; gap: 8px; padding-right: 34px; }
.entry-title-ico .ico { width: 20px; height: 20px; }
.sheet .sub { font-size: 12px; color: var(--muted); margin: 2px 0 0; }
.sheet-icons { display: flex; gap: 10px; margin-top: 12px; }
.iconbtn { flex: 1; border: 1.5px solid var(--border); background: var(--card2); border-radius: 16px; padding: 12px 6px; font-size: 20px; color: var(--text); font-weight: 800; }
.iconbtn.stop { color: var(--danger); }
.iconbtn.edit { color: var(--accent); }
.iconbtn.cancel { color: var(--muted); }
.flabel { font-size: 11.5px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .4px; margin: 14px 0 6px; }
.field-warn { font-size: 12px; color: var(--info); margin: 5px 2px 0; min-height: 0; }
.field-warn:empty { display: none; }
.dtfield {
  width: 100%; border: 1.5px solid var(--border); background: var(--card2); color: var(--text);
  border-radius: 12px; padding: 13px; font-size: 15px; text-align: left; cursor: pointer;
  font-weight: 600; display: flex; justify-content: space-between; align-items: center;
}
.dtfield.empty { color: var(--muted); font-weight: 500; }
.dtfield .chev { color: var(--muted); font-size: 12px; font-weight: 500; }
.duree-box { background: var(--card2); border-radius: 11px; padding: 10px 13px; font-size: 14px; margin-top: 10px; display: flex; justify-content: space-between; }
.stepper { display: flex; align-items: center; gap: 12px; }
.stepper .pm { width: 52px; height: 52px; border-radius: 15px; border: 1.5px solid var(--border); background: var(--card2); font-size: 25px; cursor: pointer; color: var(--accent); flex-shrink: 0; }
.stepper .amt { flex: 1; height: 52px; border: 1.5px solid var(--border); background: var(--card2); border-radius: 15px; font-size: 23px; font-weight: 700; cursor: pointer; color: var(--text); display: flex; align-items: center; justify-content: center; gap: 6px; }
.stepper .amt small { font-size: 14px; color: var(--muted); font-weight: 500; }
/* Molettes : la hauteur de LIGNE (--pk-item) est un contrat partagé avec le
   JS — setW()/idxOf() (app.js) convertissent un index en scrollTop en la
   multipliant. Elle ne bouge donc jamais. Seule la hauteur totale (--pk-h)
   est ajustable (paysage sur téléphone, où la hauteur est la ressource rare) :
   le rembourrage des molettes et la position de la bande de sélection s'en
   déduisent, au lieu des 72px en dur qui les liaient silencieusement à une
   hauteur de 180px. */
.picker { --pk-h: 180px; --pk-item: 36px; --pk-pad: calc((var(--pk-h) - var(--pk-item)) / 2); display: flex; gap: 6px; position: relative; height: var(--pk-h); margin: 6px 0; }
.pk-band { position: absolute; left: 0; right: 0; top: var(--pk-pad); height: var(--pk-item); background: color-mix(in srgb, var(--accent) 14%, transparent); border-radius: 10px; pointer-events: none; }
.wheel { flex: 1; overflow-y: scroll; scroll-snap-type: y mandatory; text-align: center; padding: var(--pk-pad) 0; scrollbar-width: none; position: relative; z-index: 1; }
.wheel::-webkit-scrollbar { display: none; }
.wheel.date { flex: 2; }
.wheel .it { height: var(--pk-item); line-height: var(--pk-item); scroll-snap-align: center; font-size: 16px; color: var(--muted); }
.wheel .it.sel { color: var(--text); font-weight: 700; font-size: 19px; }
/* Calendrier du sélecteur de jour (12/08/2026) — remplace la molette, qui ne
   remontait que 400 jours et obligeait à faire défiler date par date. Les
   journées hors plage (avant la naissance, dans le futur) restent VISIBLES
   mais désactivées : une grille tronquée passerait pour un bug d'affichage. */
.cal-head { display: flex; align-items: center; gap: 8px; margin: 8px 0 10px; }
.cal-title { flex: 1; text-align: center; font-weight: 700; font-size: 15px; text-transform: capitalize; }
.cal-nav {
  width: 36px; height: 36px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--card2); color: var(--text); font-size: 17px; cursor: pointer; flex: none;
}
.cal-nav:disabled { opacity: .3; cursor: default; }
.cal-weekdays, .cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.cal-weekdays { margin-bottom: 4px; }
.cal-weekdays span { text-align: center; font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; }
.cal-cell {
  aspect-ratio: 1 / 1; border: none; background: var(--card2); color: var(--text);
  border-radius: 10px; font-size: 14px; font-weight: 600; cursor: pointer;
  display: flex; align-items: center; justify-content: center; padding: 0;
}
/* Cases de remplissage avant le 1er du mois : ni fond ni interaction. */
.cal-cell.empty { background: none; pointer-events: none; }
.cal-cell.off { opacity: .25; cursor: default; }
/* Aujourd'hui : un simple liseré. La journée SÉLECTIONNÉE, elle, est pleine —
   les deux doivent rester distinguables quand elles coïncident. */
.cal-cell.today { box-shadow: inset 0 0 0 1.5px var(--accent); }
.cal-cell.on { background: var(--accent); color: var(--accent-ink); }

.pk-actions { display: flex; justify-content: space-between; align-items: center; margin-top: 10px; gap: 10px; }
.pk-now { background: none; border: none; color: var(--accent); font-weight: 700; font-size: 14px; cursor: pointer; }
.pk-clear { background: none; border: none; color: var(--muted); font-size: 13px; cursor: pointer; text-decoration: underline; }
.pk-ok { border: none; background: var(--accent); color: var(--accent-ink); font-weight: 700; padding: 11px 28px; border-radius: 12px; cursor: pointer; font-size: 15px; }
.stars { display: flex; gap: 8px; font-size: 32px; color: var(--border); }
.stars span { cursor: pointer; }
.stars span.on { color: var(--star); }
.mchips { display: flex; flex-wrap: wrap; gap: 8px; }
.mchip { border: 1.5px solid var(--border); background: var(--card2); border-radius: 16px; padding: 8px 12px; font-size: 13px; cursor: pointer; color: var(--text); }
.mchip.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, transparent); font-weight: 600; }
.mchip.add { color: var(--accent); border-style: dashed; }
.toggle { display: flex; gap: 8px; margin-top: 2px; }
.toggle button { flex: 1; border: 1.5px solid var(--border); background: var(--card2); border-radius: 12px; padding: 11px; font-size: 13.5px; cursor: pointer; color: var(--text); font-weight: 600; }
.toggle button.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
textarea.field { min-height: 64px; resize: vertical; font-family: inherit; }
textarea.daynote-text { min-height: 132px; }
.save-btn { width: 100%; border: none; background: var(--accent); color: var(--accent-ink); font-size: 15px; font-weight: 700; padding: 14px; border-radius: 14px; cursor: pointer; margin-top: 16px; }
/* Action destructrice confirmée (askConfirm) — jamais la couleur d'accent,
   qui signifie « action normale » partout ailleurs. */
.save-btn.danger { background: var(--danger); color: var(--danger-ink); }
.del-btn { width: 100%; border: 1px solid var(--border); background: transparent; color: var(--danger); font-size: 13px; padding: 11px; border-radius: 12px; cursor: pointer; margin-top: 8px; }
.start-btn { width: 100%; border: none; background: var(--success); color: var(--success-ink); font-size: 15px; font-weight: 700; padding: 14px; border-radius: 14px; cursor: pointer; margin-bottom: 6px; display: flex; align-items: center; justify-content: center; gap: 8px; }
.or { text-align: center; color: var(--muted); font-size: 12px; margin: 12px 0 4px; }
.cat-name-row { display: flex; gap: 10px; align-items: end; }
.field-pair { display: flex; gap: 10px; }
.field-pair .field { flex: 1; min-width: 0; }
/* Bouton icône de catégorie (remplace le champ emoji texte, 09/08/2026) —
   même gabarit que .field pour s'aligner avec le champ nom à côté. */
.icon-field-btn {
  width: 45px; height: 45px; border: 1.5px solid var(--border); border-radius: 12px;
  background: var(--card2); display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.icon-field-btn .ico { width: 22px; height: 22px; }

/* Infos cœur d'un rendez-vous (nom/date/praticien/profession, révision du
   10/08/2026) : affichées en dur plutôt qu'en champs — gagne la place
   qu'occupait la section Configuration, ces infos n'ayant pas besoin
   d'être modifiées à chaque passage dans la feuille. Le crayon rouvre le
   mini-formulaire dédié (voir openApptCoreEdit) en sheet2. */
/* Sections « À venir » / « Passés » de la liste des rendez-vous
   (12/08/2026). L'en-tête est un bouton pleine largeur : le geste de
   dépliage doit être facile à viser au pouce, pas réservé au chevron. */
.appt-section { padding: 0; overflow: hidden; }
.appt-section + .appt-section { margin-top: 12px; }
.appt-section-head {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: none; border: none; color: var(--text); cursor: pointer;
  padding: 12px 14px; font-size: 12.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .4px;
}
.appt-section-head .ttl { flex: 1; text-align: left; }
.appt-section-head .n {
  background: var(--card2); color: var(--muted); border-radius: 999px;
  padding: 2px 8px; font-size: 11px; font-weight: 700; letter-spacing: 0;
}
.appt-section-head .chev { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transform: rotate(-90deg); transition: transform .18s; }
.appt-section-head .chev.open { transform: rotate(0); }
.appt-section-body { border-top: 1px solid var(--border); }
.appt-section-body .set-row:last-child { border-bottom: none; }

/* ==========================================================================
   SUIVI DES TRAITEMENTS (12/08/2026) — frise type Gantt.
   Le graphique défile HORIZONTALEMENT : sa largeur intérieure est calculée
   en JS à partir de l'échelle choisie (jour/semaine/mois), c'est elle qui
   permet de parcourir le temps plutôt que de tout comprimer dans la largeur
   de l'écran. Il s'ouvre à droite (aujourd'hui).
   ========================================================================== */
.gantt-scroll { overflow-x: auto; overflow-y: hidden; padding-bottom: 6px; touch-action: pan-x; }
.gantt-scroll::-webkit-scrollbar { height: 5px; }
.gantt-scroll::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
.gantt-inner { position: relative; }
.gantt-axis { position: relative; height: 16px; margin-bottom: 4px; }
.gantt-tick { position: absolute; top: 0; font-size: 9px; color: var(--muted); white-space: nowrap; transform: translateX(-50%); }
/* Repères verticaux : discrets, ils servent à situer une barre dans le
   temps, pas à quadriller l'écran. */
.gantt-grid { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--border); opacity: .5; }
.gantt-row { position: relative; height: 26px; margin-bottom: 6px; background: var(--card2); border-radius: 8px; }
.gantt-row:last-child { margin-bottom: 0; }
.gantt-bar {
  position: absolute; top: 3px; bottom: 3px; border-radius: 6px; cursor: pointer;
  display: flex; align-items: center; opacity: .9;
}
/* Traitement EN COURS : bord droit ouvert, pour dire « ça continue » plutôt
   que de laisser croire à une fin nette à la date du jour. */
.gantt-bar.ongoing { border-top-right-radius: 0; border-bottom-right-radius: 0; }
/* Barre COUPÉE par le bord de la fenêtre affichée : même logique, le bord
   concerné perd son arrondi — le traitement déborde de ce qu'on regarde. */
.gantt-bar.clip-start { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.gantt-bar.clip-end { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.gantt-label { font-size: 10.5px; font-weight: 700; white-space: nowrap; pointer-events: none; }
/* Nom DANS la barre quand elle est assez large, sinon juste après : le
   choix est fait en JS à partir de la largeur réelle de la barre. */
.gantt-label.in { padding: 0 7px; color: #fff; text-shadow: 0 1px 2px rgba(0, 0, 0, .35); overflow: hidden; text-overflow: ellipsis; }
.gantt-label.out { position: absolute; left: 100%; margin-left: 6px; color: var(--text); }

.treat-dot { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.tag-ongoing {
  font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .3px;
  background: color-mix(in srgb, var(--success) 20%, transparent); color: var(--success);
  border-radius: 6px; padding: 1px 5px; margin-left: 5px;
}
/* Commentaire daté : la date au-dessus, le texte en dessous, la croix à
   droite — même gabarit que les lignes d'un rendez-vous. */
.trnote-row { display: grid; grid-template-columns: 1fr auto; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--border); align-items: start; }
.trnote-row:last-child { border-bottom: none; }
.trnote-date { grid-column: 1; padding: 8px 10px; font-size: 13px; }
.trnote-text { grid-column: 1; min-height: 48px; }
.trnote-row .qa-remove { grid-column: 2; grid-row: 1 / span 2; align-self: center; }

.appt-core { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.appt-core-info { flex: 1; min-width: 0; }
/* Date + praticien seulement : le nom du rendez-vous est le titre de la
   feuille (12/08/2026), il n'est plus répété ici. */
.appt-core-sub { font-size: 12.5px; color: var(--muted); }
.appt-core-edit {
  flex: none; width: 34px; height: 34px; border-radius: 50%; border: none;
  background: var(--card2); color: var(--muted); display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.appt-core-edit .ico { width: 16px; height: 16px; }
.colorgrid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; margin-top: 8px; }
.colorchip { height: 32px; border-radius: 12px; border: 2px solid var(--border); background: var(--c); cursor: pointer; position: relative; }
.colorchip.on { border-color: var(--text); box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--c); }
.colorchip.used:not(.on) { opacity: .34; filter: saturate(.25); cursor: not-allowed; }
.colorchip.used:not(.on)::after { content: '✓'; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-weight: 900; color: var(--text); text-shadow: 0 1px 2px var(--bg); }
.colorchip .own { position: absolute; right: -5px; top: -6px; background: var(--text); color: var(--bg); border-radius: 50%; font-size: 10px; width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; }
.photo-adjust { display: grid; gap: 10px; margin-top: 12px; }
.photo-adjust label { font-size: 12px; color: var(--muted); font-weight: 700; }
.photo-adjust input { width: 100%; }

/* DIVERS */
.holdtip {
  position: fixed; z-index: 100; background: var(--text); color: var(--bg);
  border-radius: 12px; padding: 8px 10px; font-size: 12px; box-shadow: var(--shadow);
  display: none; pointer-events: none; max-width: 270px; line-height: 1.35;
}
#toast {
  position: fixed; bottom: 76px; left: 50%; transform: translateX(-50%) translateY(20px);
  background: var(--text); color: var(--bg); padding: 11px 18px; border-radius: 20px;
  font-size: 13.5px; font-weight: 600; opacity: 0; transition: .25s; z-index: 80; pointer-events: none;
  max-width: min(88vw, 320px);
}
#toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
/* Toast annulable : seul cas où le toast est cliquable.
   Élargi (09/08/2026) : le texte se serrait sur une colonne étroite et le
   bouton passait sur deux lignes dès qu'un message dépassait "Supprimé" —
   voir la suggestion de jalon depuis une note de jour (C10), plus longue.

   `pointer-events: auto` est conditionné à `.show` (13/08/2026) — et c'est
   CAPITAL. Le toast reste dans le DOM une fois masqué (il ne fait que passer
   en `opacity: 0`), et la classe `with-undo`, elle, n'était pas retirée à
   l'extinction : une bande INVISIBLE de 380 px de large restait donc
   cliquable en bas de l'écran, à l'endroit exact des boutons jaunes
   (« Ajouter une mesure », « Ajouter un rendez-vous »…) et des puces de
   choix des feuilles. D'où des boutons « qui ne réagissent pas », partout
   dans l'app, seulement après une suppression annulable, et jusqu'au
   prochain toast ordinaire qui nettoyait la classe. Lier l'interactivité à
   la VISIBILITÉ rend cet état impossible, quoi que fasse le JS. */
#toast.with-undo {
  display: flex; align-items: center; gap: 12px; padding: 10px 10px 10px 18px;
  max-width: min(92vw, 380px);
}
#toast.with-undo.show { pointer-events: auto; }
#toast.with-undo span { flex: 1; line-height: 1.35; }
#toast.with-undo button {
  flex: none; white-space: nowrap; border: none; background: var(--bg); color: var(--text);
  font-weight: 700; font-size: 13px; padding: 7px 13px; border-radius: 14px; cursor: pointer;
}
/* Variante empilée (suggestion de jalon, C10) : texte au-dessus, bouton
   pleine largeur en dessous — le bouton "Ajouter un jalon" à côté du texte
   se lisait mal, contrairement à un simple "Annuler" à côté d'un court
   accusé de suppression, seul cas ordinaire de #toast.with-undo. */
#toast.with-undo.stacked { flex-direction: column; align-items: stretch; padding: 12px 14px; }
#toast.with-undo.stacked button { width: 100%; padding: 9px 13px; }

#updateBanner {
  position: fixed; top: 0; left: 0; right: 0; z-index: 85;
  display: flex; align-items: center; justify-content: center; gap: 12px;
  background: var(--accent); color: var(--accent-ink); padding: 10px 16px;
  font-size: 13px; font-weight: 600; box-shadow: var(--shadow);
  transform: translateY(-100%); transition: transform .25s;
}
#updateBanner.show { transform: translateY(0); }
#updateBanner button {
  background: var(--accent-ink); color: var(--accent); border: none;
  border-radius: 999px; padding: 5px 14px; font-size: 12.5px; font-weight: 700;
}

/* ==========================================================================
   Responsive desktop — au-delà du breakpoint, on élargit et on répartit
   les blocs longs sur deux colonnes. La barre de nav reste centrée.
   ========================================================================== */
@media (min-width: 900px) {
  :root { --app-max: 960px; }
  .app { padding: 0 28px; }
  #statGroups,
  #developCharts { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
  .circles { flex-wrap: wrap; }
  .nav {
    left: 50%; right: auto; transform: translateX(-50%);
    width: 100%; max-width: var(--app-max);
    border: 1px solid var(--border); border-bottom: none;
    border-radius: 18px 18px 0 0;
  }
}

/* ==========================================================================
   Paysage sur téléphone (12/08/2026) — la rotation est désormais autorisée
   (`orientation: any` dans manifest.json). En paysage, la ressource rare
   n'est plus la largeur mais la HAUTEUR : ~390 px utiles sur un téléphone
   courant, dont l'en-tête et la barre de nav mangeaient un bon tiers.

   Ciblé sur `max-height` et non sur la seule orientation : une tablette ou
   un écran de bureau en paysage a toute la hauteur voulue et doit garder
   les gabarits normaux (le point de rupture bureau à 900px s'en charge).
   ========================================================================== */
@media (orientation: landscape) and (max-height: 560px) {
  /* Plus large qu'en portrait sans aller jusqu'au gabarit bureau : un
     téléphone en paysage fait 700-950px de large, deux colonnes de
     graphiques y seraient illisibles. */
  :root { --app-max: 780px; }
  header { padding: calc(env(safe-area-inset-top) + 6px) 0 2px; }
  .avatar { width: 34px; height: 34px; font-size: 18px; }
  .baby h1 { font-size: 16px; }
  /* Barre de nav resserrée + moins de marge basse à réserver. */
  body { padding-bottom: 50px; }
  .nav { padding: 2px 4px calc(env(safe-area-inset-bottom) + 2px); }
  .nav button { padding: 4px 0; }
  .nav button .e svg { width: 20px; height: 20px; }
  #toast { bottom: 60px; }
  /* Molettes et graphiques : même contenu, moins haut (voir --pk-h). */
  .picker { --pk-h: 144px; }
  .chart { height: 116px; }
  .stars { font-size: 26px; }
  textarea.daynote-text { min-height: 84px; }
  /* Une feuille modale qui occupe tout l'écran en paysage n'a plus de
     poignée visible ni d'ancrage bas : on la borne pour laisser voir le
     contenu derrière, comme en portrait. */
  .sheet { max-height: 100dvh; }
}

/* Catégorie masquée (Réglages) : listée mais visiblement en retrait — c'est
   le seul endroit d'où on peut la réafficher. */
.catrow.is-hidden .e { opacity: .45; }
.catrow.is-hidden .nm { color: var(--muted); }
.tag-hidden {
  font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .3px;
  background: var(--card2); color: var(--muted); border-radius: 6px; padding: 1px 5px; margin-left: 5px;
}


/* Plage de dates d'un traitement (13/08/2026) : deux champs date côte à côte
   et la croix de retrait, une ligne par plage. La croix disparaît quand il ne
   reste qu'une plage — un traitement sans aucune date n'aurait plus de sens. */
.trperiod-row { display: flex; align-items: flex-end; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--border); }
.trperiod-row:last-child { border-bottom: none; }
.trperiod-row .field { padding: 9px 10px; font-size: 13px; }
/* Lien d'action dans un avertissement de formulaire (« ouvrir le traitement
   existant ») : un bouton qui se lit comme un lien, pour rester discret dans
   une phrase. */
.link-btn { background: none; border: none; padding: 0; font: inherit; color: var(--accent); text-decoration: underline; cursor: pointer; }

/* ==========================================================================
   Thèmes de couleur par ENFANT (lot D).
   ==========================================================================
   `data-theme` porte le MODE (clair/sombre), propre à l'appareil ;
   `data-palette` porte le THÈME, propriété de l'enfant et donc synchronisée —
   c'est ce qui fait que le profil de chaque enfant a la même couleur sur tous
   les téléphones de la famille, et qu'on voit d'un coup d'œil chez qui on est.

   « Sable » n'a AUCUN bloc ici : c'est la palette de :root et de
   html[data-theme="dark"] plus haut, c'est-à-dire l'apparence historique de
   l'application. Un enfant sans thème choisi ne déclenche donc aucune règle
   supplémentaire, et le rendu est rigoureusement celui d'avant ce lot.

   Spécificité : les deux familles de sélecteurs ci-dessous valent (0,2,1) et
   sont placées APRÈS le bloc sombre de base, qu'elles doivent l'une comme
   l'autre pouvoir surcharger. Écrire simplement html[data-palette="ciel"]
   (0,1,1) aurait laissé le bloc sombre gagner en mode clair, et l'inverse en
   mode sombre — selon l'ordre du fichier, ce qui est exactement le genre de
   dépendance qu'on ne veut pas.
   -------------------------------------------------------------------------- */

/* Ciel — clair */
html[data-palette="ciel"]:not([data-theme="dark"]) {
  --bg: #F2F7FC; --card: #FFFFFF; --card2: #E8F0F8; --text: #16202B; --muted: #5E7183; --border: #D8E4F0; --accent: #4E9BD8; --accent-ink: #06243B; --star: #E8A33C;
}

/* Ciel — sombre */
html[data-theme="dark"][data-palette="ciel"] {
  --bg: #12181F; --card: #1A222B; --card2: #212B35; --text: #EEF3F8; --muted: #9FB2C2; --border: #313D49; --accent: #6FB6EE; --accent-ink: #0A1620; --star: #F0B95E;
}

/* Sauge — clair */
html[data-palette="sauge"]:not([data-theme="dark"]) {
  --bg: #F2F7F3; --card: #FFFFFF; --card2: #E7F0EA; --text: #16211B; --muted: #5E7267; --border: #D8E6DC; --accent: #5FA787; --accent-ink: #0A2A1D; --star: #E0A33F;
}

/* Sauge — sombre */
html[data-theme="dark"][data-palette="sauge"] {
  --bg: #131A16; --card: #1B241E; --card2: #222D27; --text: #EEF4F0; --muted: #A0B4A8; --border: #313D36; --accent: #7DC7A5; --accent-ink: #0B1A13; --star: #EDB962;
}

/* Terracotta — clair */
html[data-palette="terracotta"]:not([data-theme="dark"]) {
  --bg: #FDF4F1; --card: #FFFFFF; --card2: #F6E8E3; --text: #241816; --muted: #7A6259; --border: #EEDAD3; --accent: #D97757; --accent-ink: #331007; --star: #DFA33C;
}

/* Terracotta — sombre */
html[data-theme="dark"][data-palette="terracotta"] {
  --bg: #1B1614; --card: #241D1A; --card2: #2D2521; --text: #F6F0ED; --muted: #BBA69D; --border: #3E332E; --accent: #E8916F; --accent-ink: #1A0F0A; --star: #EFB963;
}

/* Lilas — clair */
html[data-palette="lilas"]:not([data-theme="dark"]) {
  --bg: #F6F3FC; --card: #FFFFFF; --card2: #EDE7F8; --text: #1D1729; --muted: #6B6180; --border: #E1D9F0; --accent: #8E76CE; --accent-ink: #1D1040; --star: #DFA33C;
}

/* Lilas — sombre */
html[data-theme="dark"][data-palette="lilas"] {
  --bg: #17141F; --card: #1F1B29; --card2: #272233; --text: #F2EFF8; --muted: #ADA3C0; --border: #383049; --accent: #AE97E6; --accent-ink: #120C22; --star: #EFB963;
}

/* Ardoise — clair */
html[data-palette="ardoise"]:not([data-theme="dark"]) {
  --bg: #F3F5F7; --card: #FFFFFF; --card2: #E8ECF0; --text: #171B1F; --muted: #61707C; --border: #DAE0E6; --accent: #5C7D91; --accent-ink: #071820; --star: #DFA33C;
}

/* Ardoise — sombre */
html[data-theme="dark"][data-palette="ardoise"] {
  --bg: #14171A; --card: #1C2024; --card2: #23282D; --text: #EFF2F5; --muted: #A3AFB9; --border: #333A40; --accent: #85A6BA; --accent-ink: #0C1418; --star: #EFB963;
}


/* Pastilles du sélecteur de thème : deux moitiés, clair et sombre, pour que
   le choix se fasse sur ce qu'on verra vraiment de jour comme de nuit. */
.theme-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin: 6px 0 2px; }
.theme-swatch {
  border: 2px solid var(--border); border-radius: 14px; padding: 8px 6px 6px;
  background: var(--card); cursor: pointer; text-align: center; font: inherit; color: var(--text);
}
.theme-swatch.on { border-color: var(--accent); }
.theme-swatch .disc {
  width: 100%; height: 34px; border-radius: 10px; margin-bottom: 6px;
  border: 1px solid var(--border); overflow: hidden; display: flex;
}
.theme-swatch .disc > i { flex: 1; display: block; }
.theme-swatch .nm { font-size: 12px; color: var(--muted); }
.theme-swatch.on .nm { color: var(--text); font-weight: 600; }

/* ==========================================================================
   Sélecteur d'enfant (lot D)
   ========================================================================== */
.child-list { display: flex; flex-direction: column; gap: 8px; }
.child-row {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 10px 12px; border: 2px solid var(--border); border-radius: 14px;
  background: var(--card); color: var(--text); font: inherit; text-align: left; cursor: pointer;
}
.child-row.on { border-color: var(--accent); background: var(--card2); }
.child-av {
  width: 42px; height: 42px; border-radius: 50%; flex: none;
  background: var(--card2) center/cover no-repeat;
  display: flex; align-items: center; justify-content: center; font-size: 22px;
}
.child-nm { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.child-nm b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.child-nm i { font-style: normal; font-size: 12px; color: var(--muted); }
/* Pastille « cet enfant réclame de l'attention ». Couleur sémantique, jamais
   une valeur en dur (règle CLAUDE.md). */
.child-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--danger); flex: none; }

/* Même pastille, sur la photo de l'en-tête : elle signale qu'un AUTRE enfant
   que celui affiché a un rappel en attente. Sans elle, ce rappel resterait
   invisible tant qu'on n'a pas pensé à basculer. */
#babyHead { position: relative; }
#babyHead.has-other-alerts .avatar::after {
  content: ''; position: absolute; top: 0; left: 30px;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--danger); border: 2px solid var(--bg);
}

/* ==========================================================================
   Lecture seule (lot C) — ce que l'habilitation ne permet pas ne s'affiche pas
   ==========================================================================
   Le contrôle RÉEL est ailleurs : côté serveur (qui refuse) et dans save()
   (point de passage unique côté client). Ces règles ne protègent rien, elles
   évitent de proposer un geste qui échouerait. D'où le choix de masquer
   plutôt que de griser : un bouton grisé invite à chercher comment
   l'activer. */
html[data-readonly="1"] #addBar,
html[data-readonly="1"] [data-act^="open"][data-act$="Form"],
html[data-readonly="1"] .save-btn,
html[data-readonly="1"] .btn.danger,
html[data-readonly="1"] .add-fab { display: none !important; }
.readonly-badge {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; padding: 2px 8px; border-radius: 999px;
  background: var(--card2); color: var(--muted); border: 1px solid var(--border);
}
