/* OPAL — Refonte UI Apple-style. CSS pur, dual theme via [data-theme]. */

/* ──────────────────────────────────────────────────────────── */
/* TOKENS — palette dual theme                                   */
/* SOURCE UNIQUE de la palette depuis le lot 7 (2026-09-05) : l'éditeur de
   thème, sa table et sa route sont retirés. Un token se change ICI, et nulle
   part ailleurs. */
/* ──────────────────────────────────────────────────────────── */
[data-theme="light"] {
  /* Palette NOALA (refonte visuelle 2026-07) : canvas blanc cassé froid,
     encres pétrole (#143B4A), accent teal (#2AAE9B). Cartes blanches,
     panneaux secondaires (surface-2) DISTINCTS du fond pour détacher les
     sections. Remplace le réglage Sérénité « B1 équilibré » (greige/sapin). */
  --bg:            #FAFAF8;
  --bg-elev:       #FFFFFF;
  --surface:       #FFFFFF;
  --surface-2:     #E9EDF0;
  --surface-alert: #FBEDE5;

  --border:        rgba(20, 59, 74, 0.12);
  --border-2:      rgba(20, 59, 74, 0.07);

  --ink:           #143B4A;
  --text:          #2E4A56;
  --text-2:        #5B7280;
  --text-3:        #8CA0AB;

  /* POLITIQUE ACCENT (refonte 2026-07) :
     --accent (#2AAE9B)      = aplats, fonds, bordures, icônes, éléments SUR fond sombre. JAMAIS en color: de texte sur fond clair (2,6:1 sur --bg).
     ⚠️ ET JAMAIS DE TEXTE PAR-DESSUS — la règle ne disait qu'un sens, et le
     défaut 5.47 est venu de l'autre. #fff sur cet aplat rend 2,75:1, et AUCUNE
     encre du système ne le sauve : --accent-text y tombe à 2,01:1 (PIRE que le
     blanc, contre-intuitif et mesuré), --ink plafonne à 4,35:1 (passe le 3:1
     du grand texte, échoue le 4,5:1). Un aplat accent porte une barre, un cœur
     de radio, une pastille SANS libellé. Pour un fond plein qui porte du
     texte : --ink, blanc dessus, 11,97:1.
     --accent-text (#1A7568) = TOUT texte teal sur fond clair (AA ≥ 4,5:1 — mesuré 5,3:1 sur #FAFAF8, 5,5:1 sur blanc).
     Pastilles/pills 10-13px bold sur --accent-soft : ≈ 4,8:1 — AA ok, cf spec §2.
     Phases : --phase-avant/-apres = segments graphiques ; texte → --phase-avant-text / --accent-text. */
  --accent:        #2AAE9B;   /* teal NOALA — token du thème global (A5) */
  /* --accent-soft DÉRIVÉ de --accent (audit couleurs 2026-07-07) : il suivait
     le sapin en dur alors que --accent est personnalisable (Réglages) — chaque
     surface pastel virait au vert quel que soit le choix du praticien. */
  --accent-soft:   color-mix(in srgb, var(--accent) 16%, #FFFFFF);
  --accent-tint:   rgba(42, 174, 155, 0.07);
  --accent-text:   #1A7568;   /* teal foncé LISIBLE (AA 5,3:1 sur --bg) — tout texte teal sur fond clair (jamais #2AAE9B en texte) */
  --sidebar-bg:      #143B4A;                   /* sidebar praticien sombre */
  --sidebar-ink:     #B8C7CE;                   /* texte nav sidebar */
  --sidebar-active:  #57D4C5;                   /* item actif — turquoise, AA 6,6:1 sur pétrole (le teal #2AAE9B ne tenait que 3,4:1 sur le voile hover) */
  --sidebar-surface: rgba(255, 255, 255, 0.08); /* hover/fonds internes sidebar */
  --accent-2:      #57D4C5;
  --accent-2-soft: rgba(87, 212, 197, 0.18);

  /* Statut parcours (J±N) — couleurs de phase. Refonte NOALA : les trois
     phases deviennent des LITTÉRAUX de la palette pétrole/teal (avant = teal
     clair, jour J = pétrole, après = teal) — plus de dérivation color-mix
     depuis --accent. --phase-jourj / --phase-apres restent HORS allowlist
     backend (exclusion P2-7/8.6 conservée volontairement). */
  --phase-avant:   #57D4C5;        /* pré-op (J-N) — teal clair */
  --phase-jourj:   #143B4A;        /* jour J (J0) — pétrole */
  --phase-apres:   #2AAE9B;        /* suivi — teal */
  --phase-avant-soft: #DFF6F2;     /* fond doux des états « expiré » (P1 frise) */
  --phase-avant-text: #2E7482;     /* TEXTE phase pré-op sur fond clair (AA 5,1:1 — les segments/nœuds restent --phase-avant) */
  --phase-apres-soft: #D9F2EE;     /* pastel du suivi (bande à venir) */

  --alert:         #B85A3F;
  --alert-soft:    rgba(184, 90, 63, 0.10);
  --warn:          #C49B5D;
  --warn-soft:     rgba(196, 155, 93, 0.14);
  /* TEXTE et glyphe de gravité « warn » sur fond clair (5,5:1 sur --surface).
     --warn (#C49B5D) rend 2,6:1 : il reste réservé aux aplats, fonds et bordures,
     exactement comme --accent. La maquette de référence prescrit #A87C33 pour ce
     rôle, mais il ne rend que 3,75:1 — sous le seuil AA. Reprendre la valeur de la
     maquette aurait introduit un défaut d'accessibilité avec la caution d'une
     spécification. Même raisonnement que --accent-text et --phase-avant-text. */
  --warn-text:     #8A6216;
  --success:       #6B9080;

  --cta-bg:        #143B4A;
  --cta-fg:        #FFFFFF;
  --cta-bg-hover:  #1D5468;

  --glass-blur:        16px;
  --glass-saturate:    130%;
  /* FIX-1 (validé PO) — teinte glass BLANCHE (≠ couleur du fond) : les cartes
     .noala-card--glass redeviennent visibles/détachées sur le fond greige. */
  --glass-tint:        rgba(255, 255, 255, 0.75);
  --glass-tint-strong: rgba(255, 255, 255, 0.92);
  --glass-edge-top:    transparent;
  --glass-edge-bot:    transparent;

  --shadow-sm:     0 1px 2px rgba(16, 42, 53, 0.06);
  --shadow-md:     0 2px 5px rgba(16, 42, 53, 0.07), 0 14px 30px -8px rgba(16, 42, 53, 0.15);
  --shadow-lift:   0 10px 20px rgba(16, 42, 53, 0.08), 0 30px 60px -12px rgba(16, 42, 53, 0.20);

  /* Variantes par niveau de score (vert/ambre/orange/rouge) + info (bleu, phase
     pré-op/status info). Consolidé depuis le bloc :root doublon ex-app.css:1049-1061
     (P2-7/8.6) — ce bloc gagnait silencieusement sur celui-ci par ordre de cascade
     (même spécificité, déclaré plus bas dans le fichier) ; valeurs EFFECTIVES
     conservées telles quelles, seule la cascade est assainie (zéro changement de
     rendu). Consommés par la gravité des pastilles (`--sev-ink`) et les rangées
     de la vue Scores. */
  --status-good:      #2F7D5E;  --status-good-soft: rgba(47, 125, 94, 0.10);
  /* Encres LISIBLES des deux familles, sur leur propre fond doux. Mesures du
     2026-08-30, recalculees trois fois de facon independante :
       --status-good  sur --status-good-soft : 4,3766:1  → ECHOUE (seuil 4,5)
       --status-good-text                    : 5,0012:1  → conforme
       --alert        sur --alert-soft       : 4,0427:1  → ECHOUE
       --alert-text                          : 5,0108:1  → conforme
     Teintes : 155,8° contre 156,2° pour le vert, 13,6° contre 13,4° pour le
     rouge. Sur blanc, les deux rendent 5,69:1 — utilisables partout.
     ⚠️ NE PAS les appliquer a `--sev-ink` : cette variable peint des ICONES
     (`.noala-ico-tile` et ses cinq freres), donc un element graphique au seuil
     de 3:1, que les couples actuels tiennent (3,73 et 4,39). Y toucher serait
     corriger ce qui n'est pas casse et assombrir la gravite sans raison. */
  --status-good-text: #2B7356;
  --alert-text:       #A14F37;
  --status-warn:      #C68A2E;  --status-warn-soft: rgba(198, 138, 46, 0.12);
  --status-mid:       #D67940;  --status-mid-soft:  rgba(214, 121, 64, 0.12);
  --status-bad:       #C44A2D;  --status-bad-soft:  rgba(196, 74, 45, 0.10);
  --status-info:      #4F46E5;  --status-info-soft: rgba(79, 70, 229, 0.12);

  /* ── Code couleur des TYPES DE CONTENU (2026-09-01) ────────────────────────
     Neuf types, deux champs porteurs DIFFÉRENTS — c'est le piège de la famille :
       · questionnaires → `Questionnaire.type` ∈ PROM | PREM | QUIZ  (QUIZ, un z)
       · médiathèque    → `Ressource.nature`  ∈ fiche | faq | video | lien |
                                                application | document
     PAS `Ressource.type`, qui confond fiche et FAQ (toutes deux `texte`), ni
     `Ressource.categorie`, qui est le SUJET et non la forme.

     ⚠️ Chaque encre est MESURÉE, pas choisie : descendue par pas de 0,5 % de
     luminosité jusqu'au premier palier ≥ 4,5:1 sur les TROIS fonds qu'elle peut
     rencontrer à la fois — sa propre pastille, #FFFFFF et --bg. Le pire des
     trois est en commentaire.

     ⚠️ Les fonds sont des APLATS OPAQUES, jamais des rgba. En translucide, le
     rapport dépendrait de la surface derrière — carte, ligne de tableau,
     accordéon n'ont pas la même — et un contraste mesuré une fois cesserait
     d'être vrai partout. C'est le mode de panne de --surface-2 / --text-2.

     ⚠️ Aucune ne dérive de --accent : c'est un token de thème personnalisable,
     et une pastille de type qui change de teinte avec le thème n'est plus un code.

     ⚠️ Huit teintes pour neuf types : `lien` et `application` partagent l'indigo.
     Au-delà de huit teintes de faible chroma sur une pastille de 11 px, deux
     voisines cessent d'être distinguables ; l'icône porte la neuvième
     distinction, là où la teinte ne le peut plus. */
  --type-prom-bg:        #E9F3F2;  --type-prom-ink:        #1D7A6D;  /* 4,60:1 */
  --type-prem-bg:        #E9F3EB;  --type-prem-ink:        #277C35;  /* 4,61:1 */
  --type-quiz-bg:        #F2EAF3;  --type-quiz-ink:        #A045A8;  /* 4,56:1 */
  --type-fiche-bg:       #E9EFF3;  --type-fiche-ink:       #2B71A3;  /* 4,53:1 */
  --type-faq-bg:         #F5F3E7;  --type-faq-ink:         #816C15;  /* 4,61:1 */
  --type-video-bg:       #F3EAED;  --type-video-ink:       #BA3B65;  /* 4,56:1 */
  --type-image-bg:       #EEF1E6;  --type-image-ink:       #5D6E1F;  /* 4,94:1 */
  --type-lien-bg:        #ECEAF3;  --type-lien-ink:        #6C5CBC;  /* 4,52:1 */
  --type-application-bg: #ECEAF3;  --type-application-ink: #6C5CBC;  /* 4,52:1 */
  --type-document-bg:    #F3ECE9;  --type-document-ink:    #A55634;  /* 4,55:1 */
}


/* ──────────────────────────────────────────────────────────── */
/* Typo & espacement                                             */
/* ──────────────────────────────────────────────────────────── */
:root {
  --font-display: 'Poppins', 'Segoe UI', system-ui, sans-serif;
  --font-serif: var(--font-display); /* ex-chiffres cliniques — tabular via font-variant-numeric global */
  --font-sans: 'Poppins', 'Segoe UI', system-ui, sans-serif;
  --font-body: var(--font-sans); /* fix : consommé par app.css:4270 + admin.html:33 sans être défini */
  --font-mono:    "JetBrains Mono", "SF Mono", Menlo, monospace;

  --fs-display:    52px;
  --fs-display-sm: 38px;
  --fs-h1:         28px;
  --fs-h2:         18px;
  --fs-h3:         15px;
  --fs-body:       14px;
  --fs-sm:         13px;
  --fs-xs:         12px;
  --fs-caps:       11px;

  --lh-tight:  1.10;
  --lh-normal: 1.50;
  --lh-loose:  1.65;

  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px;
  --s-5: 20px; --s-6: 24px; --s-8: 32px; --s-10: 40px;
  --s-12: 48px; --s-16: 64px;

  --radius-sm:   10px;
  --radius-md:   12px;
  --radius-lg:   14px;
  /* Rayon de CARTE, distinct de --radius-lg (2026-08-28). La maquette pose 16px
     sur `.card` ; --radius-lg vaut 14px et sert six autres surfaces qui ne sont
     pas des cartes (tuile de tableau de bord, panneaux de score, RDV et signature
     du portail). Le passer à 16 aurait déplacé le rayon d'éléments que personne
     n'a mesurés. */
  --radius-card: 16px;
  --radius-xl:   18px;
  --radius-btn:  11px;  /* boutons & CTA — refonte Sérénité (cards restent --radius-lg) */
  --modal-scrim: rgba(10, 30, 38, 0.45);  /* voile pétrole des surfaces — refonte NOALA */
  --radius-pill: 999px;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

/* Icône Tabler (sprite SVG self-hosté, refonte Sérénité). stroke=currentColor → suit `color`. */
.noala-ic { width: 1.05em; height: 1.05em; display: inline-block; vertical-align: -0.16em; color: inherit; flex: none; }

/* Transitions douces sur les changements de thème (cross-fade) */
:root {
  --t-theme: 220ms cubic-bezier(0.4, 0, 0.2, 1);
}
html, body, .noala-card, .noala-tab,
.noala-link-action, .noala-cta,
.noala-portal-info, .noala-portal-qs-item, .noala-portal-choice,
.noala-portal-yesno-btn, .noala-portal-scale-btn, .noala-tabs {
  transition:
    background-color var(--t-theme),
    color var(--t-theme),
    border-color var(--t-theme),
    box-shadow var(--t-theme);
}

/* Fade-in subtil à l'arrivée du contenu */
@keyframes noala-fade-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.noala-card, .noala-greeting, .noala-patient-header, .noala-tabs {
  animation: noala-fade-in 0.4s cubic-bezier(0.16, 1, 0.3, 1) both;
}


/* Reduce motion — respect des préférences utilisateur */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}

/* ── Skeletons de chargement (perçu-perf) ───────────────────────────
   Shimmer réutilisable, affiché via x-if="...loading" en Alpine puis
   remplacé par le contenu réel. Neutralisé sous prefers-reduced-motion
   (le bloc ci-dessus coupe l'animation). */
@keyframes noala-skel-shimmer {
  0%   { background-position: -360px 0; }
  100% { background-position:  360px 0; }
}
.noala-skel {
  background: linear-gradient(90deg,
    var(--surface-2) 25%, var(--surface) 38%, var(--surface-2) 54%);
  background-size: 720px 100%;
  animation: noala-skel-shimmer 1.3s ease-in-out infinite;
  border-radius: var(--radius-sm);
}
.noala-skel-line { height: 12px; margin: 9px 0; }
.noala-skel-line.sk-40 { width: 40%; }
.noala-skel-line.sk-55 { width: 55%; }
.noala-skel-line.sk-70 { width: 70%; }
.noala-skel-line.sk-90 { width: 90%; }
.noala-skel-row  { height: 44px; margin-bottom: 8px; border-radius: var(--radius-md); }


/* Focus visible — accessibilité clavier */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}
button:focus-visible, a:focus-visible { outline-offset: 3px; }
body {
  font-family: var(--font-sans);
  font-size:   var(--fs-body);
  line-height: var(--lh-normal);
  color:       var(--text);
  background:  var(--bg);
  min-height:  100vh;
  -webkit-font-smoothing: antialiased;
  font-variant-numeric: tabular-nums;
}

a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; }

.caps {
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-2);
}

.serif { font-family: var(--font-serif); font-weight: 400; }
.serif-italic { font-family: var(--font-serif); font-style: normal; font-weight: 600; } /* ex-italique Fraunces — la charte Poppins n'a pas d'italique (refonte 2026-07) */

/* ──────────────────────────────────────────────────────────── */
/* Layout principal                                              */
/* ──────────────────────────────────────────────────────────── */
.noala-app {
  display: grid;
  grid-template-columns: 224px 1fr;
  min-height: 100vh;
  /* Le pétrole doit couvrir TOUTE la hauteur de la page, pas seulement le
     viewport (la sidebar est sticky/100vh). On peint la colonne gauche via un
     dégradé à bord franc sur la grille → full-height sans toucher au sticky.
     Largeur re-calée par breakpoint (64px tablette ; retiré en mode drawer). */
  background: linear-gradient(to right, var(--sidebar-bg) 0 224px, transparent 224px);
}
/* Symbole vectoriel N-arche (remplace l'ancien glyphe demi-cercle en ::before).
   Sprite unique #noala-mark injecté par ui.js — l'arche est en currentColor,
   la couleur vient du contexte (blanc sur pétrole, encre sur clair). */
.noala-logo-svg { vertical-align: -6px; margin-right: 8px; }
/* La marque ecrite a cote du logo (decision de Pierre, 2026-10-07) : « NOALA »
   en capitales, le DERNIER A dans le vert du logo. Une seule ecriture sur tous
   les fronts :
   <span class="noala-marque" role="img" aria-label="NOALA">NOAL<span class="noala-marque-a">A</span></span>
   - Les quatre premieres lettres HERITENT la couleur du parent (encre sur fond
     clair, blanc sur la barre encre) : ne pas poser de couleur ici.
   - Le vert est ecrit EN DUR : la palette est gatee [data-theme="light"], et la
     marque doit valoir partout, fond encre compris. C est la seule exception
     admise a « jamais #2AAE9B en texte » : c est le logotype, pas un texte.
   - Taille et police viennent du parent. L espacement serre de « Noala »
     (letter-spacing negatif) ne va pas a des capitales : il est remis ici.
   - role="img" + aria-label : le nom se lit « NOALA » d un seul tenant, pas
     « NOAL A ». */
.noala-marque { font-weight: 600; letter-spacing: .017em; text-transform: none; white-space: nowrap; }
.noala-marque-a { color: #2AAE9B; }

/* MAIN */
.noala-main {
  display: flex; flex-direction: column;
  min-width: 0;
}
/* Fil d'Ariane : c'est le TITRE de la barre, pas une légende. La maquette le pose
   en 15px/600 sur `--ink` avec un letter-spacing serré (`.bc`). Le produit le
   rendait en 13px/400 sur `--text-2` avec un letter-spacing ÉLARGI (+.01em) —
   quatre écarts dans le même sens, qui l'effaçaient. Le `capitalize` est retiré
   depuis mai 2026 par la règle de la section suivante ; il l'est ici aussi. */
.noala-breadcrumb {
  font-size: 15px;
  color: var(--ink);
  letter-spacing: -0.01em;
  text-transform: none;
  font-weight: 600;
}
/* ⚠️ REVIREMENT ASSUMÉ, 2026-08-28 — la recherche n'est plus pleine largeur.
   La rédaction précédente disait : « Recherche pleine largeur : occupe tout
   l'espace entre la date et le CTA (choix PO) ». La maquette (`.srch`,
   maquettes/praticien.html:17) pose au contraire une CAPSULE de 280px calée à
   droite, juste avant l'avatar. L'arbitrage du 2026-08-28 est que la maquette
   est la cible ; on revient donc sur ce choix, et on l'écrit ici pour que le
   prochain lecteur ne voie pas une direction contredite sans explication.
   Le raisonnement technique de l'ancienne règle restait juste et reste valable
   EN SENS INVERSE : c'est bien `margin-left:auto` sur la recherche qui la cale
   à droite maintenant qu'elle ne s'étire plus, et il ne faut toujours PAS en
   poser sur `.noala-topbar-actions`, qui suit naturellement. */
/* `flex: 0 1 280px` et NON `flex: none; width: 280px` : la maquette decrit une
   fenetre de 1360px, ou la capsule tient ses 280px. En dessous, elle doit pouvoir
   se RETRECIR — mesure du 2026-08-28 a 768px : figee a 280px, elle poussait le CTA
   « Creer un parcours patient » (229px) a right:802 pour un viewport de 768, soit
   34px hors cadre, sur les DEUX routes de la console. C'est le defaut meme que
   responsive.spec.js:82 existe pour attraper, et l'ancienne regle `flex: 1 1 auto`
   s'en gardait deja — le grow etait de trop, le shrink ne l'etait pas.
   grow 0 : elle ne depasse jamais 280. shrink 1 + min-width 0 : elle cede l'espace
   avant que quiconque ne deborde. `margin-left:auto` la cale a droite. */
.noala-topbar-search { flex: 0 1 280px; min-width: 0; max-width: 280px !important; margin: 0 0 0 auto !important; }
.noala-topbar-search .noala-search-input { padding: 8px 0; font-size: 12.5px; }
/* < 760px : la recherche d'en-tête se masque (repli loupe à câbler — refinement).
   Lot 5 — la barre passe sur 2 lignes (date au-dessus, actions dessous) pour ne
   jamais déborder horizontalement à 375px. */
@media (max-width: 760px) {
  /* ⚠️ DEUX CLASSES, ET CE N'EST PAS DE LA COQUETTERIE. La rédaction d'origine
     ciblait `.noala-topbar-search` seul — spécificité 0-1-0, exactement celle de
     `.noala-search-wrap { display: flex }` déclarée plus bas (ligne 4652). Une
     media query n'ajoute AUCUNE spécificité : à égalité, c'est l'ordre source
     qui tranche, donc la règle sans media gagnait et la recherche restait
     affichée. Mesuré le 2026-08-30 : `display` calculé à `flex` alors que
     `matchMedia('(max-width: 760px)')` valait bien `true`.
     Conséquence en chaîne : trois rangées au lieu des deux annoncées. */
  .noala-search-wrap.noala-topbar-search { display: none; }
}


/* CTA */
/* La maquette n'a AUCUNE classe de bouton : ses boutons SONT des pastilles a
   fond pose a l'emploi, en deux tailles seulement — la base (3px 10px) pour une
   action de rangee, et 6px 13px pour un bouton de TETE. `.noala-cta` est un
   bouton de tete (« Creer un parcours patient », « + Creer un questionnaire »).
   Avant le 2026-08-28 : 13px/600 et padding 10px 18px, soit ~40px de haut la ou
   la maquette en fait 30. La hierarchie tient au seul FOND, jamais au relief :
   le `translateY(-1px)` du survol est retire avec le reste. */
.noala-cta {
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  padding: 6px 13px;
  border-radius: var(--radius-pill);
  background: var(--cta-bg);
  color: var(--cta-fg);
  border: none;
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.5;
  transition: background 0.15s ease, opacity 0.15s ease;
}
.noala-cta:hover { background: var(--cta-bg-hover); }


/* Refonte UX L.1 (2026-05-27) — helper tooltip pour acronymes.
   Pattern recommandé : `<abbr class="noala-tooltip" data-tooltip="..."
   tabindex="0">SIGLE</abbr>`. Le tabindex permet le focus tactile sur
   mobile (tap → focus → tooltip), tout en gardant le :hover desktop.
   Pure CSS (::after pseudo-element + attr(data-tooltip)). */
.noala-tooltip {
  position: relative;
  text-decoration: underline dotted;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  cursor: help;
  /* Override <abbr> par défaut qui peut être italic/uppercase */
  font-style: inherit;
  font-variant: inherit;
}
.noala-tooltip::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  /* Background fixe sombre (indépendant du thème) pour contraste constant */
  background: #2D2620;
  color: #fff;
  padding: 8px 12px;
  border-radius: 6px;
  font-size: 12px;
  line-height: 1.45;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  text-decoration: none;
  white-space: normal;
  width: max-content;
  max-width: 260px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
  z-index: 200;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
}
.noala-tooltip::before {
  content: "";
  position: absolute;
  bottom: calc(100% + 2px);
  left: 50%;
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-top-color: #2D2620;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
  z-index: 200;
}
.noala-tooltip:hover::after,
.noala-tooltip:hover::before,
.noala-tooltip:focus::after,
.noala-tooltip:focus::before,
.noala-tooltip:focus-visible::after,
.noala-tooltip:focus-visible::before {
  opacity: 1;
}


/* Refonte UX A.3 (2026-05-27) — template empty state unifié.
   Pattern : `<div class="noala-empty-state">` avec icône SVG/emoji
   + titre + message + CTA optionnel. Cohérent entre Dashboard,
   fiche patient, portail patient et toutes les listes vides. */
.noala-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--s-6) var(--s-4);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-2);
}
.noala-empty-state__icon {
  font-size: 44px;
  line-height: 1;
  margin-bottom: var(--s-3);
  color: var(--text-3);
  opacity: 0.7;
}
.noala-empty-state__title {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 500;
  color: var(--ink);
  margin: 0 0 6px;
  letter-spacing: -0.005em;
}
.noala-empty-state__message {
  font-size: 13px;
  color: var(--text-2);
  margin: 0;
  max-width: 380px;
  line-height: 1.55;
}


/* Refonte UX A.2 (2026-05-27) — spinner visible pendant les soumissions async.
   Activée via Alpine `:class="{ 'noala-cta--loading': state }"` en complément
   de `:disabled` déjà présent. Cohabite avec le texte conditionnel
   « Envoi⬦ »/« Envoyer » : le spinner s'affiche en plus, le bouton est
   désactivé visuellement (cursor + opacity), pas de hover transform. */
.noala-cta--loading,
.noala-cta:disabled {
  opacity: 0.65;
  cursor: not-allowed;
  pointer-events: none;
  transform: none !important;
}
.noala-cta--loading::before {
  content: "";
  display: inline-block;
  width: 14px;
  height: 14px;
  margin-right: 8px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  vertical-align: -2px;
  animation: noala-spin 0.7s linear infinite;
}
@keyframes noala-spin {
  to { transform: rotate(360deg); }
}
/* Variante portail patient : `.noala-portal-cta` qui n'hérite pas de
   `.noala-cta` (classe distincte) — couvre les CTAs view='fill' et
   view='sign_consent'. */
.noala-portal-cta--loading,
.noala-portal-cta:disabled {
  opacity: 0.65;
  cursor: not-allowed;
  pointer-events: none;
}
.noala-portal-cta--loading::before {
  content: "";
  display: inline-block;
  width: 14px;
  height: 14px;
  margin-right: 8px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  vertical-align: -2px;
  animation: noala-spin 0.7s linear infinite;
}

/* CONTENT */
/* Ecart 3.50 — 32px sur les quatre cotes contre 24px 26px dans la maquette.
   ⚠️ CE CHANGEMENT EST GLOBAL, PAS LOCAL A LA FICHE. `.noala-content` est le
   conteneur UNIQUE de toutes les routes de la console : tableau de bord,
   patients, activite, statistiques, questionnaires, protocoles, mediatheque,
   reglages. L'annoncer comme un ecart de fiche patient serait faux.
   Les quatre media queries plus bas posent toutes des valeurs INFERIEURES
   (--s-5, --s-4, --s-3) : aucune inversion introduite. */
.noala-content {
  padding: var(--s-6) 26px;
  max-width: 1280px;
}
/* Ecart 3.19 — la salutation et son sous-titre se lisaient comme deux blocs.
   La maquette pose 22px/600 à -0.02em avec 3px de marge basse ; le produit posait
   28px avec `--s-8` (32px). Les deux marges FUSIONNAIENT à 32px, ce qui décrochait
   le sous-titre de son titre : un défaut mesurable, pas une impression.
   ⚠️ L'écart est DESKTOP SEUL : `.noala-greeting` est déjà à 22px sous 700px
   (media query plus bas) et à 19px sous 380px. Ne pas « harmoniser » ces
   valeurs-là en croyant les aligner, elles sont déjà justes.
   ⚠️ Le sous-titre porte `x-show="patientsList.length"` : à zéro patient Alpine le
   sort du flux, donc il ne participe plus à la fusion des marges et l'écran
   d'accueil se retrouverait à 3px du titre. D'où le `margin-top` explicite sur la
   carte d'accueil, plus bas. */
.noala-greeting {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 22px;
  color: var(--ink);
  line-height: var(--lh-tight);
  margin: 0 0 3px 0;
  letter-spacing: -0.02em;
}
.noala-greeting em {
  font-family: var(--font-display);
  font-style: italic;
  color: var(--accent-text);
  font-weight: 600;
}

/* ──────────────────────────────────────────────────────────── */
/* Cards                                                          */
/* ──────────────────────────────────────────────────────────── */
/* Card de base — élévation marquée + relief subtil
   Le relief est obtenu par 3 couches superposées :
   1. Box-shadow externe : ombre portée pour décoller du fond
   2. Box-shadow interne haut clair : highlight (lumière au-dessus)
   3. Box-shadow interne bas sombre : ombre interne (poids en bas)
*/
/* La carte de la maquette (maquettes/style.css:22) : cernée d'un filet, à 16px,
   sur l'ombre la PLUS FAIBLE du jeu. Elle est posée à plat, pas en lévitation.
   Avant le 2026-08-28 : `border:none`, rayon 14px, `--shadow-md` (portée 30px).
   C'est ce trio, sur 114 cartes, qui donnait à chaque écran l'impression de
   flotter — l'écart le plus large du chantier d'alignement, et le seul qui se
   corrige d'une règle. Les tokens d'ombre, eux, coïncidaient déjà au caractère
   près avec ceux de la maquette : c'était un choix, pas une valeur. */
.noala-card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  isolation: isolate;
}
.noala-card > * { position: relative; z-index: 1; }

.noala-card--data { background: var(--surface); }

/* Card alerte — dégradé pêche horizontal (Annexe F) */
.noala-card--alert {
  background: linear-gradient(170deg, #FBEDE5 0%, #F8E0D2 100%);
  box-shadow: 0 2px 4px rgba(184, 90, 63, 0.08), 0 12px 28px -8px rgba(184, 90, 63, 0.20);
}

/* Card glass — translucidité opaque-ish (Annexe F) */
.noala-card--glass {
  background: var(--glass-tint-strong);
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  box-shadow: var(--shadow-lift);
}

.noala-card-body { padding: var(--s-6); }

.noala-card-title {
  font-size: var(--fs-caps);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--text-2);
}

/* ──────────────────────────────────────────────────────────── */
/* Hero : Radar 2/3 + Alertes 1/3                                */


/* ──────────────────────────────────────────────────────────── */
/* KPI strip                                                      */
/* ──────────────────────────────────────────────────────────── */


/* ──────────────────────────────────────────────────────────── */
/* Panneau « Interventions » (ex-programme hebdomadaire)         */
/* ──────────────────────────────────────────────────────────── */
/* Task 6 — 3 sub-sections en colonnes : neutralise le margin-top d'empilement
   (le gap de la grille gère l'espacement). Le grid-template-columns:repeat(3,1fr)
   est inline (spécificité > classe) → le fallback mobile ci-dessous force 1fr. */
/* ═══ LE PANNEAU DU TABLEAU DE BORD (ecarts 3.1, 3.25, 3.26, 3.27, 3.28, 3.29)
   La carte portait TROIS etages de titre — `.noala-card-title` en capitales de
   11px, puis un en-tete de colonne en capitales de 11px, puis la rangee — la ou
   la maquette n'en a que DEUX (en-tete de panneau, rangee). Deux etages de
   capitales de 11px se succedaient.

   ⚠️ ET LES TROIS COLONNES FABRIQUAIENT DU VIDE. Leurs etats vides s'affichaient
   INDEPENDAMMENT : « Aucune intervention aujourd'hui. » se peignait pendant que
   la carte etait pleine. Sur un cabinet reel, les interventions ne tombent
   presque jamais dans les trois seaux a la fois — mesure sur un dossier reel :
   deux colonnes vides sur trois, occupant les deux tiers du panneau. Un vide
   unique ne se declenche que si la fenetre entiere est vide, ce qui est a la
   fois plus rare et VRAI.
   Aucune donnee n'est perdue : le seau etait une fonction pure de l'offset
   (`dashboard.py`), et chaque rangee porte deja cet offset. */
.noala-panel-head {
  display: flex; align-items: center; gap: 10px;
  padding: 15px 18px;
  border-bottom: 1px solid var(--border-2);
}
.noala-panel-ic {
  display: inline-flex; flex: none;
  color: var(--accent-text);
}
.noala-panel-ic svg { width: 16px; height: 16px; }
.noala-panel-titles { flex: 1; min-width: 0; }
.noala-panel-title {
  font-size: 13.5px; font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.01em;
  margin: 0;
}
/* La fenetre reellement interrogee. Elle n'est pas decorative : c'est elle qui
   rend VISIBLE l'effet du reglage de perimetre, lequel passait pour inerte
   faute de rien changer a l'ecran. */
.noala-panel-sub {
  font-size: 11.5px;
  color: var(--text-2);
  margin: 1px 0 0;
}
/* `.mo` de la maquette : du texte d'accent, pas un bouton. Mesure :
   --accent-text sur --surface = 5,30:1. */
.noala-panel-more {
  flex: none;
  border: 0; background: none;
  padding: 4px 2px;
  font-family: var(--font-sans);
  font-size: 11.5px; font-weight: 600;
  color: var(--accent-text);
  cursor: pointer;
}
.noala-panel-more:hover { text-decoration: underline; }
.noala-panel-list { list-style: none; margin: 0; padding: 0; }
/* Rangee PLATE separee d'un filet — l'idiome `.row` de la maquette praticien,
   distinct du `.hr` encarte de la maquette patient. Cf le commentaire du socle
   `.noala-row-card` : la maquette porte deux idiomes, deliberement. */
.noala-panel-row {
  display: flex; align-items: center; gap: 12px;
  width: 100%; text-align: left;
  padding: 11px 18px;
  border: 0; background: transparent;
  border-bottom: 1px solid var(--border-2);
  cursor: pointer;
  transition: background 0.15s ease;
}
.noala-panel-row:last-child { border-bottom: 0; }
.noala-panel-row:hover { background: var(--surface-2); }
.noala-panel-row:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
/* Avatar teinte par PHASE. Trois couples, tous mesures sur seuil 4,5:1 (12px/700
   n'est pas du grand texte) :
     avant  #2E7482 sur #DFF6F2 = 4,7253:1
     apres  #1A7568 sur #D9F2EE = 4,7213:1
     jour J  blanc sur #143B4A  = 11,9712:1
   La maquette teinte cet avatar par ETAT DU DOSSIER (« 2 pieces manquantes »
   en terracotta). Ce signal n'etait pas servi par l'API jusqu'au lot 8
   (`dossier`, `{total, manquantes}` ou null) ; depuis le lot 17,
   `[data-dossier="manquant"]` passe par-dessus la phase, en encre `--alert-text`
   (AA sur `--alert-soft`), et la phase reste la teinte de repos. */
.noala-panel-avatar {
  width: 32px; height: 32px; flex: none;
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: 12px; font-weight: 700;
  letter-spacing: 0.02em;
  user-select: none;
  background: var(--phase-avant-soft);
  color: var(--phase-avant-text);
}
.noala-panel-avatar[data-phase="apres"] {
  background: var(--phase-apres-soft);
  color: var(--accent-text);
}
.noala-panel-avatar[data-phase="jourj"] {
  background: var(--phase-jourj);
  color: #FFFFFF;
}
.noala-panel-avatar[data-dossier="manquant"] {
  background: var(--alert-soft);
  color: var(--alert-text);
}
/* ⚠️ `display:flex` EXPLICITE. Ces conteneurs sont des `<span>` — un `<div>`
   serait invalide dans le `<button>` de la rangee — donc inline par defaut :
   sans cette declaration, le nom et l'intervention s'ecoulent SUR UNE LIGNE. */
.noala-panel-main {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column;
}
.noala-panel-name {
  font-size: 13.5px; font-weight: 600; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.noala-panel-meta {
  font-size: 11.5px; color: var(--text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.noala-panel-side {
  flex: none; text-align: right;
  display: flex; flex-direction: column;
}
.noala-panel-date {
  font-size: 12px; font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* ⚠️ `--text-2` et non `--text-3`. La maquette met `--text-3` sur cette ligne ;
   mesure : 2,7162:1 sur blanc, le pire ratio de tout son tableau de bord, pour
   du 11px. Or cette ligne porte le J±N, l'information CENTRALE de la rangee.
   Recopier la maquette propagerait l'echec sur ce qu'on cherche a rendre lisible.
   `--text-2` rend 5,04:1. */
.noala-panel-state {
  font-size: 11px; color: var(--text-2);
  font-variant-numeric: tabular-nums;
  margin-top: 1px;
}
/* Lot 17 — la ligne d'etat du dossier, a la suite du J±N. Une piece manquante
   s'ecrit en encre d'alerte AA (`--alert-text` ; la maquette ecrit `--alert` 600,
   sous 4,5:1 a 11px) ; « dossier complet » garde l'encre de la ligne. */
.noala-panel-dossier[data-etat="manquant"] { color: var(--alert-text); font-weight: 600; }
/* Etat vide : romain et aligne a gauche. L'italique centre de l'ancienne version
   n'appartient a aucun vocabulaire de la maquette, et Poppins n'a pas d'italique
   — le navigateur le fabriquait par oblique synthetique. */
.noala-panel-empty {
  font-size: 12.5px;
  color: var(--text-2);
  padding: 18px;
}

/* ──────────────────────────────────────────────────────────── */
/* δ.2 (A.2) — Carrousel scores (gauche) + Patients récents (droite) */

/* ══════════════════════════════════════════════════════════════════════════
   SOCLE DE COMPOSANTS — lot A de l'alignement sur la maquette de référence
   (docs/superpowers/specs/2026-08-26-alignement-ui-maquette-design.md §2).

   Vit dans app.css, chargé par les six fronts qui portent une palette — donc
   disponible partout, sans dépendre de ui.js (que tiers.html n'a rejoint qu'au
   lot 14c). Une harmonisation passant par un helper JS aurait dépendu de ce
   chargement.

   ⚠️ `.noala-task-row` est un ALIAS de la définition canonique, pas une classe
   distincte : patient_taches_lot_a.spec.js asserte sur
   `.noala-task-row[data-kind][data-sev]`. Son jumeau `.noala-hub-row` est parti le
   2026-09-29 avec la liste du bas de l'accueil (lot 1 de « Mes documents en six
   sections ») : plus aucun front ne le portait, et la galerie du design system
   emploie désormais `.noala-task-row`.
   ══════════════════════════════════════════════════════════════════════════ */

/* 1. Carte de rangée — tout item de liste est encadré, jamais une rangée nue
      séparée d'un filet. Rayon 17px et ombre douce : valeurs de la maquette.
      (la rangée `noala-resource-row` du sélecteur de médiathèque est partie avec lui :
      builders, lot 3, tâche 3.) */
.noala-task-row {
  display: flex; align-items: center; gap: 13px; width: 100%; text-align: left;
  padding: 12px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 17px;
  box-shadow: var(--shadow-sm);
  cursor: pointer;
}

/* 2. Pastille d'icône — une icône ne se pose jamais à nu sur le fond.
      Le rayon suit la taille (36→11, 38→12) : ce n'est pas un rayon unique. */
.noala-ico-tile, .noala-hub-row-ico, .noala-task-ico, .noala-acc-ico, .noala-jalon-item-ic {
  width: 36px; height: 36px; border-radius: 11px; flex: none;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent-text);
}
.noala-ico-tile > .noala-ic,
.noala-hub-row-ico > .noala-ic,
.noala-task-ico > .noala-ic,
.noala-acc-ico > .noala-ic,
.noala-ico-tile > svg { width: 19px; height: 19px; }
.noala-ico-tile--lg { width: 38px; height: 38px; border-radius: 12px; }
/* `.noala-jalon-item-ic` (tiroir de jalon, frise.css) est un ALIAS de --sm : le
   lot C.2 en avait recopie la definition mot pour mot dans frise.css. Fondu ici
   le 2026-08-28, sans toucher au markup — le tiroir empile jusqu'a 14 rangees,
   ou 32px se tient mieux que les 36 de la taille de base. */
.noala-ico-tile--sm, .noala-jalon-item-ic { width: 32px; height: 32px; border-radius: 10px; }
.noala-ico-tile--sm > .noala-ic, .noala-ico-tile--sm > svg, .noala-jalon-item-ic > .noala-ic, .noala-jalon-item-ic > svg { width: 17px; height: 17px; }

/* 3. Gravité — elle se lit à la COULEUR DU FOND, pas au texte. Trois niveaux.
      Les fonds de rangée consomment --surface-alert et --warn-soft, deux
      tokens jusqu'ici déclarés sans aucun consommateur. Les fonds de pastille
      sont DÉRIVÉS du token de gravité (color-mix) plutôt qu'écrits en dur :
      changer --warn ici garde ainsi une pastille cohérente avec sa rangée.

      ⚠️ Le texte et le glyphe ne prennent JAMAIS --warn (2,6:1) ni --accent
      (2,75:1) : ils prennent --warn-text et --accent-text. La maquette
      prescrit #A87C33 pour le glyphe warn, qui ne rend que 3,75:1 — sous AA.
      ⚠️ CORRECTION du 2026-08-29 (arbitrage Pierre). La rédaction précédente
      ajoutait ici « JAMAIS un score clinique ». C'est FAUX, et c'était une
      sur-lecture de la règle hors-DM. Ce que le dépôt interdit réellement
      (CLAUDE.md, arbitrage A1) : « drapeaux visuels à l'écran uniquement —
      jamais d'email/notification sur score ». La contrainte porte sur la
      NOTIFICATION AUTOMATISÉE, pas sur la couleur. Le produit code déjà ses
      scores en couleur (`.noala-score-pill[data-level]`, piloté par
      `scoreLevel()` et par les zones d'interprétation propres à chaque
      praticien), et LA MAQUETTE FAIT DE MÊME : son tableau de bord peint les
      jetons de score en `--good` / `--warn-soft` / `--alert-soft`
      (maquettes/praticien.html:139-142). Le code couleur clinique est donc dans
      la cible, pas contre elle. Étendre le code couleur est attendu ; seul reste
      interdit le déclenchement d'un e-mail, d'une notification push ou d'une
      alerte de tableau de bord à partir d'un score. */
/* Les pastilles ont CINQ noms (cf .noala-ico-tile plus haut) : la gravite doit
   tous les atteindre, sinon elle ne teinte que la moitie des surfaces. */
/* La gravite se declare en PROPRIETES PERSONNALISEES, pas en `background`
   direct. Raison : `.noala-hub-act` porte `background:none` dans patient.css,
   charge APRES app.css et de meme specificite — un fond pose ici serait ecrase
   en silence. Chaque composant lit donc `--sev-bg` dans sa propre regle, avec
   un repli quand aucune gravite n'est posee. Une seule source de verite, aucune
   guerre de specificite, aucune duplication de tokens. */
.noala-sev--alert {
  --sev-bg:   var(--surface-alert);
  --sev-tile: color-mix(in srgb, var(--alert) 16%, var(--surface));
  --sev-ink:  var(--alert);
}
.noala-sev--warn {
  --sev-bg:   var(--warn-soft);
  --sev-tile: color-mix(in srgb, var(--warn) 26%, var(--surface));
  --sev-ink:  var(--warn-text);
}
.noala-sev--info {
  --sev-bg:   var(--accent-tint);
  --sev-tile: var(--accent-soft);
  --sev-ink:  var(--accent-text);
}
/* « Termine » : la rangee se retire du premier plan sans disparaitre. */
.noala-sev--done {
  --sev-bg:   var(--bg);
  --sev-tile: var(--status-good-soft);
  --sev-ink:  var(--status-good);
  box-shadow: none;
}
.noala-sev--alert, .noala-sev--warn, .noala-sev--info, .noala-sev--done {
  background: var(--sev-bg);
}
/* Les pastilles ont CINQ noms (cf .noala-ico-tile plus haut) : la gravite doit
   tous les atteindre, sinon elle ne teinte que la moitie des surfaces.
   ⚠️ `.noala-resource-icon` avait rejoint la liste le 2026-08-29 (une pastille
   laissee en accent dans une rangee teintee ferait tenir deux discours
   contradictoires au meme objet) ; sans porteur, elle est partie au lot 14e.
   ⚠️ `.noala-jalon-item-ic` manquait a cette liste (releve du 2026-08-29) : une
   gravite posee sur une rangee du tiroir de jalon aurait teint le FOND en
   laissant la pastille en accent — deux registres contradictoires sur le meme
   objet, ce qui est pire qu'aucune gravite. */
/* GRAVITE TILE-ONLY — quatre variantes qui posent `--sev-tile` et `--sev-ink`
   SANS poser `--sev-bg`. Elles existent pour un cas precis et frequent : un
   conteneur qui doit rester BLANC alors que son icone doit dire la nature de ce
   qu'il contient. C'est ce que fait la maquette sur les plis de « Mes taches »
   (`.acc` reste `--surface`, seul `.acc-i` est teinte, maquettes/patient.html:171-174).
   ⚠️ Sans elles, poser `.noala-sev--warn` sur un `<details class="noala-acc">`
   teindrait TOUTE la carte : `.noala-acc` lit `var(--sev-bg, …)` depuis le lot 2.
   Le seul pli qui prend la classe PLEINE est « Termine » — la maquette lui donne
   `background: var(--bg); box-shadow: none`, ce que `.noala-sev--done` fait deja. */
.noala-sev--alert-tile { --sev-tile: color-mix(in srgb, var(--alert) 16%, var(--surface)); --sev-ink: var(--alert); }
.noala-sev--warn-tile  { --sev-tile: color-mix(in srgb, var(--warn) 26%, var(--surface));  --sev-ink: var(--warn-text); }
.noala-sev--info-tile  { --sev-tile: var(--accent-soft); --sev-ink: var(--accent-text); }
.noala-sev--good-tile  { --sev-tile: var(--status-good-soft); --sev-ink: var(--status-good); }
/* ⚠️ LA LISTE DOIT SUIVRE CELLE DE LA FAMILLE PLEINE, sinon la variante est
   MUETTE sur les composants qu'elle oublie. Elle ne portait que `.noala-acc-ico`
   quand la famille pleine atteint aussi `.noala-jalon-item-ic` : poser un
   `.noala-sev--warn-tile` sur un item du tiroir de jalon ne peignait donc rien,
   sans erreur ni avertissement. Ajouter un composant a l'une sans l'autre est le
   mode de panne « gravite muette » du lot 2, reproduit un etage plus bas. */
.noala-sev--alert-tile .noala-acc-ico, .noala-sev--warn-tile .noala-acc-ico,
.noala-sev--info-tile  .noala-acc-ico, .noala-sev--good-tile .noala-acc-ico,
.noala-sev--alert-tile .noala-jalon-item-ic, .noala-sev--warn-tile .noala-jalon-item-ic,
.noala-sev--info-tile  .noala-jalon-item-ic, .noala-sev--good-tile .noala-jalon-item-ic {
  background: var(--sev-tile); color: var(--sev-ink);
}

.noala-sev--alert .noala-ico-tile, .noala-sev--warn .noala-ico-tile, .noala-sev--info  .noala-ico-tile, .noala-sev--done .noala-ico-tile, .noala-sev--alert .noala-hub-row-ico, .noala-sev--warn .noala-hub-row-ico, .noala-sev--info  .noala-hub-row-ico, .noala-sev--done .noala-hub-row-ico, .noala-sev--alert .noala-task-ico, .noala-sev--warn .noala-task-ico, .noala-sev--info  .noala-task-ico, .noala-sev--done .noala-task-ico, .noala-sev--alert .noala-acc-ico, .noala-sev--warn .noala-acc-ico, .noala-sev--info  .noala-acc-ico, .noala-sev--done .noala-acc-ico, .noala-sev--alert .noala-jalon-item-ic, .noala-sev--warn .noala-jalon-item-ic, .noala-sev--info  .noala-jalon-item-ic, .noala-sev--done .noala-jalon-item-ic {
  background: var(--sev-tile); color: var(--sev-ink);
}

/* ⚠️ CONTRAT DE COHABITATION, pour tout composant qui veut porter une gravite.
   La regle ci-dessus peint avec UNE seule classe de specificite. Toute regle de
   composant qui pose un `background` PLUS BAS dans ce fichier gagne, et la
   gravite disparait — sans erreur, sans avertissement, sans test rouge. Le
   commentaire plus haut documente ce piege pour patient.css (chargee apres) ;
   il se rejoue A L'INTERIEUR d'app.css seule, ou rien ne le signale.
   Remede unique : le composant LIT le token, jamais l'inverse —
   `background: var(--sev-bg, <sa valeur d'origine>)`. Et son `:hover` se garde
   par `:not([data-sev])`, sinon il efface la gravite au moment precis ou
   l'utilisateur designe la rangee. D'ou les DEUX attributs du motif
   (`:data-sev` pour le crochet, `:class` pour la peinture) : ce n'est pas une
   redondance. */

/* -------------------------------------------------------------------------
   LA PASTILLE — une seule metrique, treize noms (2026-08-28, lot 1e).

   La maquette n'en a QU'UNE (maquettes/style.css:23) :
     inline-flex . gap 5px . rayon 999px . 11px/600 . padding 3px 10px .
     line-height 1.5 . aucune casse forcee . aucun letter-spacing.
   Toute la variation passe par `background` + `color` poses a l'emploi.

   Le produit en avait treize definitions concurrentes, aux graisses, casses,
   rayons et familles contradictoires : 10px uppercase a .04em pour `-tag`,
   11px/500 uppercase a .02em pour `-status-pill`, 14px en `--font-serif` pour
   `-score-pill`, 12px en monospace pour `-manager-tile-count`, 10px a .06em
   pour `-pb-qstype-tag`... soit trois familles de police concurrentes sur un
   objet que la maquette veut unique.

   /!\ ALIAS et non renommage — motif deja employe pour `.noala-row-card` :
   neuf specs e2e posent un localisateur sur ces noms, dont `admin.spec.js` qui
   selectionne `button.noala-tag` comme onglet de NAVIGATION. Renommer casserait
   par timeout, sans message pointant la cause.

   /!\ Chaque classe ne garde ci-dessous que ses COULEURS et les contraintes de
   mise en page qui ne sont pas de la metrique typographique (`nowrap`,
   `flex-shrink`, `align-items: baseline` du score). Une regle qui reposerait
   ici un font-size annulerait tout l'exercice — c'est ce que faisaient les
   variantes `[data-severity]` et `[data-phase]` de `.noala-tag`.

   HORS de ce jeu, deliberement : les COMPTEURS forment une famille ronde a
   geometrie propre, traitee juste en dessous. ⚠️ Correction du 2026-08-29 : la
   redaction precedente disait « dont la maquette ne donne aucune metrique ».
   C'est faux — la maquette la donne DEUX fois, `.hr-b` (maquettes/patient.html:34)
   et `.cnt` (maquettes/admin.html), aux memes valeurs. C'est la pastille de
   compteur, juste en dessous, qui les transcrit, et c'est pour cela que les
   compteurs partagent une regle plutot que de rester une famille a part. `.noala-nav-badge` garde en revanche
   sa propre specification de maquette (`.sb-b`, 10px/700).
   Les quatre pastilles de `frise.css` relevent du lot de la frise : elles
   GROSSIRAIENT, et `.noala-jalon-badge` est en position absolue sur le noeud.
   ⚠️ `.noala-weekly-count` a quitte cette famille le 2026-08-30 : les trois
   en-tetes de colonne du tableau de bord qui le portaient ont fusionne en un
   panneau unique, il n'a plus aucun porteur ; la classe est partie au lot 14e. */
.noala-tag, .noala-status-pill, .noala-score-pill, .noala-consent-state {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border-radius: var(--radius-pill);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.5;
  padding: 3px 10px;
  text-transform: none;
  letter-spacing: normal;
}

/* 4. Pastille de compteur — ronde ou capsule, fond plein, `min-width` fixe
      pour ne pas danser d'une ligne à l'autre. Le plein --alert est réservé
      au compteur : c'est le seul endroit où un nombre doit sauter aux yeux. */
/* PASTILLE DE COMPTEUR — la transcription fidele du `.hr-b` de la maquette
   (patient.html:34) : min-width 21, height 21, padding 0 6px, rond, 11px/700,
   tabulaire. Le produit avait quatre recettes concurrentes, aux rayons
   6/8/9/10px et aux graisses 500/600/700 ; elles ont converge ici le
   2026-08-29 en ALIAS (jamais un renommage : des specs e2e posent des
   localisateurs sur ces noms), chacune ne gardant plus bas que la couleur et
   le placement.
   ⚠️ Le nom canonique de cette regle etait `.noala-count-pill`, qui n'a JAMAIS
   eu de porteur : la classe est partie au lot 14e (2026-09-08), avec
   `-weekly-count` et `-resource-section-count`, dont les porteurs avaient
   disparu. Ce qui se verifie n'est pas un emploi de markup mais la GEOMETRIE
   RENDUE des compteurs qui restent. */
.noala-hub-badge, .noala-qs-sec-count {
  display: inline-grid; place-items: center; flex: none;
  min-width: 21px; height: 21px; padding: 0 6px;
  border-radius: 999px;
  background: var(--alert); color: #fff;
  font-size: 11px; font-weight: 700; line-height: 1;
  font-variant-numeric: tabular-nums;
}
/* ⚠️ Les alias prennent la variante DOUCE ici, et non chacun chez soi.
   Raison mesuree le 2026-08-29 sur `.noala-weekly-count` (depuis retire, plus
   aucun porteur) : il posait ses couleurs AVANT ce bloc, donc a specificite
   egale le `var(--alert)` du groupe canonique gagnait, et les compteurs du
   programme hebdomadaire rendaient en ROUGE ALERTE. Les autres, declares plus
   bas dans le fichier, n'avaient
   pas le defaut : deux cas sur trois marchaient, ce qui le rendait invisible a la
   lecture. Une seule ligne, juste apres le canonique : plus aucune couleur de
   compteur ne depend de sa position dans le fichier. */
/* EN-TETE DE SECTION — une seule recette. Le portail en avait QUATRE en
   concurrence : `.caps` (11px/500/.08em), `.noala-hub-sec` (11/700/.1em),
   `.noala-tasks-sec` (11/700/.1em) et `.noala-hub-hero-eyebrow` (12/700/.06em).
   La maquette n'en pose qu'une, et c'est la derniere : 12px/700/.06em — a 12px,
   .1em disperse les lettres au point qu'on lit des blocs et non des mots.
   La variante `--card` (icone d'accent, DANS une carte) est partie le
   2026-09-29 avec l'ecrin « En ce moment » de « Mes taches », son dernier
   porteur. */
.noala-hub-hero-eyebrow, .noala-tasks-sec {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-2);
}

.noala-qs-sec-count { background: var(--surface-2); color: var(--text); }

/* `.noala-tab-badge` — CLASSE ORPHELINE jusqu'au 2026-08-28 : six emplois HTML
   (admin.html:336, 340, 361 et patient.html:1869, 1875, 1881 — releves a nouveau
   le 2026-08-29 ; les trois premiers avaient glissé de 8 lignes) et ZERO regle
   dans les quatre feuilles. Les six compteurs rendaient en TEXTE BRUT, colles au
   libelle de leur onglet — dont trois dans le portail patient, une surface
   pourtant declaree terminee.
   Elle devient un ALIAS de la pastille de compteur du socle, en variante douce :
   ces compteurs denombrent (« 12 documents »), ils n'alertent pas. Le seul qui
   porte une gravite l'annonce par `data-severity`, traite juste en dessous. */
.noala-tab-badge {
  display: inline-grid; place-items: center; flex: none;
  min-width: 21px; height: 21px; padding: 0 6px; margin-left: 6px;
  border-radius: 999px;
  background: var(--surface-2); color: var(--text);
  font-size: 11px; font-weight: 700; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.noala-tab-badge[data-severity="alert"] { background: var(--alert); color: #fff; }

/* 5. Carte statistique de console — label capitales à icône, valeur franche,
      ligne de contexte dessous.
      ⚠️ NON APPLIQUÉE au tableau de bord dans ce lot : `.noala-tiles-compact`
      (app.css, « Style A retenu (PO) ») y impose délibérément label + chiffre
      sur une seule ligne. Adopter cette carte reviendrait à défaire cet
      arbitrage — c'est une décision produit, elle appartient au lot D. */
.noala-stat-card {
  display: flex; flex-direction: column;
  padding: 17px 18px;
  background: var(--surface); border: 1px solid var(--border);
  /* La carte statistique EST une carte au sens de la maquette (`class="card st"`,
     maquettes/praticien.html) : même rayon que `.noala-card`. Bordure et ombre
     étaient déjà justes ; seul le rayon divergeait (14 mesuré contre 16). */
  border-radius: var(--radius-card); box-shadow: var(--shadow-sm);
}
.noala-stat-card-label {
  display: flex; align-items: center; gap: 7px;
  font-size: 11px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--text-2); margin-bottom: 10px;
}
.noala-stat-card-label > .noala-ic,
.noala-stat-card-label > svg { width: 15px; height: 15px; color: var(--accent-text); }
.noala-stat-card-value {
  font-size: 32px; font-weight: 600; line-height: 1; letter-spacing: -0.03em;
  color: var(--ink); font-variant-numeric: tabular-nums;
}
.noala-stat-card-sub { font-size: 11.5px; color: var(--text-2); margin-top: 7px; }
/* Grille des quatre indicateurs du tableau de bord (2026-08-28). Elle remplace
   `.noala-tiles-compact`, qui posait label et chiffre sur UNE ligne de 40 px
   (« Style A retenu (PO) ») — arbitrage de Pierre : la maquette est la cible.
   ⚠️ `auto-fit` et non `repeat(4, 1fr)` : sous 900 px quatre colonnes rendraient
   des cartes de 200 px où le nombre à 32 px ne tiendrait plus. */
.noala-dash-stats {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
/* Sous-titre factuel sous la salutation (date + charge de la semaine), à la place
   de l'incise d'humeur qui s'y trouvait. */
.noala-dash-sub { margin: 0 0 20px; font-size: 13px; color: var(--text-2); }
/* Ces cartes sont cliquables (elles ouvrent l'écran correspondant) : elles
   doivent le montrer. */
.noala-stat-card--act { cursor: pointer; transition: border-color .12s, box-shadow .12s; }
.noala-stat-card--act:hover { border-color: var(--accent); box-shadow: var(--shadow-md); }
.noala-stat-card--act:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }


/* ─── KPI compact (bande secondaire en bas du dashboard) ─── */


/* ──────────────────────────────────────────────────────────── */
/* Patients récents                                              */


/* ──────────────────────────────────────────────────────────── */
/* Variantes par niveau de score : vert / jaune / orange / rouge */
/* Une bande colorée à gauche + un pastille discret en haut droite */
/* Tokens --status-* déclarés dans [data-theme="light"] (consolidation P2-7,
   cf commentaire ci-dessus l'ancien doublon :root supprimé ici). */


/* Boutons secondaires "Configurer", "Voir tous" → pill discret avec relief
   léger. Plus visibles que de simples liens texte mais sans concurrencer
   le CTA primaire. */
/* L'action de rangee de la maquette (« Modifier », maquettes/praticien.html:190) :
   la pastille de base, fond `--surface-2` sur `--text-2`. Avant le 2026-08-28 :
   13px/500, padding 6px 12px, une BORDURE et une DOUBLE ombre (dont une interne),
   plus un `translateY(-1px)` au survol — un relief que la maquette n'emploie sur
   AUCUN bouton. C'est la primitive la plus repandue du produit (395 porteurs). */
.noala-link-action {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  border: none;
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.5;
  font-family: var(--font-sans);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
  box-shadow: none;
}
/* Le survol se lit au CONTRASTE, pas au relief. */
.noala-link-action:hover {
  color: var(--ink);
  background: color-mix(in srgb, var(--surface-2) 82%, var(--ink));
}

/* ──────────────────────────────────────────────────────────── */
/* Fiche patient                                                 */
/* ──────────────────────────────────────────────────────────── */
.noala-back-btn {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  color: var(--text-2);
  background: transparent;
  border: none;
  padding: 4px 0;
  cursor: pointer;
  margin-bottom: var(--s-5);
  transition: color 0.15s;
}
.noala-back-btn:hover { color: var(--accent-text); }

/* Ecart 3.3 — l'identite etait posee A NU sur le fond de page : ni fond, ni
   bordure, ni padding, ni rayon. La maquette l'enferme dans une carte (`.card.ph`,
   praticien.html:22 et :43) : c'est ce qui la separe du reste de l'ecran et lui
   donne le meme statut que les autres blocs.
   ⚠️ On peint la carte ICI plutot que d'ajouter `.noala-card` au markup :
   `.noala-card` et `.noala-patient-header` figurent DEJA dans la meme regle
   d'animation plus haut dans ce fichier. Un element portant les deux classes n'y
   recevrait qu'une declaration, pas deux — donc pas de double animation — mais
   la classe apporterait aussi `overflow:hidden` et `isolation:isolate`, dont
   l'en-tete n'a que faire. */
.noala-patient-header {
  display: flex; align-items: center; gap: 14px;
  margin-bottom: 16px;
  flex-wrap: wrap;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-sm);
  padding: 18px 20px;
}
/* Ecart 3.5 — LA HIERARCHIE N'ETAIT PAS PLATE, ELLE ETAIT INVERSEE.
   Le nom du patient etait en 28px/400 ; le titre d'episode, six lignes plus bas,
   en 26px/1.15 ; son cote en 20px ; et le `strong` de la date operatoire en 19px
   — soit exactement la taille que la maquette donne au NOM DU PATIENT. Trois
   elements de contexte pesaient donc autant, ou plus, que le sujet de l'ecran.
   La maquette met le nom en 19px/600 et range tout le reste dans une meta de
   12,5px. */
.noala-patient-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 19px;
  color: var(--ink);
  margin: 0;
  line-height: var(--lh-tight);
  letter-spacing: -0.02em;
}
.noala-patient-meta {
  font-size: var(--fs-sm);
  color: var(--text-2);
  margin-top: 4px;
  letter-spacing: 0.005em;
}
.noala-meta-sep { color: var(--text-3); margin: 0 6px; }

/* Onglets — Annexe H
   `width:fit-content` + `max-width:100%` : la pilule hugge son contenu tant
   qu'il tient dans la colonne, puis se cape et SCROLLE. Les deux vont ensemble —
   `fit-content` SEUL se dimensionne au contenu et déborde sans scroller, et le
   débordement est COUPÉ (aucun ancêtre scrollable jusqu'à `.noala-app`, en
   `overflow-x:hidden`). C'est ce qui rendait « Sécurité », 8e onglet des
   Réglages et seul point d'entrée du groupe 2FA/audit/exports/effacement RGPD,
   inatteignable de 701 à 866 px — iPad portrait (768) compris. (Le seuil haut
   est le point ou la colonne atteint les 763 px de la barre : 763 + 84 de rail
   + 20 de padding. A 847 px de viewport la colonne ne fait encore que 743.)
   Ne PAS remplacer `fit-content` par `width:auto` : ça scrolle aussi, mais ça
   étire la pilule sur toute la colonne (1156 px à 1440) au lieu de la laisser
   hugger ses onglets. Corollaire assumé sous 700 px, où `width:auto` régnait
   avant : une barre qui NE déborde PAS hugge désormais ses onglets au lieu de
   s'étirer sur la colonne (sous-onglets Identité : 119 px au lieu de 351) —
   même rendu qu'en desktop, l'incohérence était là.

   Affordance du scroll — elle n'est PAS la même selon la plateforme :
   · Chrome / Firefox desktop : gouttière de scrollbar visible au repos (10 px,
     `scrollbar-width: thin`). Elle S'AJOUTE sous la padding-box quand la barre
     scrolle — la barre passe de 42 à 52 px de haut. C'est le prix de l'indice.
   · iPad, Safari, tout tactile : scrollbars en OVERLAY, donc invisibles au
     repos. Le seul indice y est l'onglet TRONQUÉ au bord droit. Sur l'appareil
     que ce correctif vise, c'est donc la troncature qui porte l'affordance, pas
     la scrollbar — ne pas compter sur celle-ci pour rendre le geste devinable.
   NE PAS rajouter `::-webkit-scrollbar` pour affiner : dès que `scrollbar-width`
   vaut autre chose que `auto`, Chrome IGNORE les pseudo-éléments webkit (3 px
   demandés, 10 px obtenus). Les deux ne cohabitent pas ; c'était du code mort
   doublé d'un commentaire faux sur la hauteur obtenue. */
.noala-tabs {
  display: flex;
  gap: 2px;
  padding: 4px;
  background: var(--surface-2);
  border: none;
  border-radius: var(--radius-pill);
  margin-bottom: var(--s-5);
  width: fit-content;
  max-width: 100%;
  overflow-x: auto;
  flex-wrap: nowrap;
  scrollbar-width: thin;
  box-shadow: var(--shadow-sm);
}
/* L'onglet n'est PAS une pastille : la maquette lui donne sa propre
   specification (`.tab`, maquettes/praticien.html:48) — 12,5px/500, padding
   6px 15px, dans une gouttiere `--surface-2`. Avant : 13px/500, 7px 18px. */
.noala-tab {
  padding: 6px 15px;
  border-radius: var(--radius-pill);
  border: none;
  background: transparent;
  font-family: var(--font-sans);
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-2);
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  transition: background 0.15s ease, color 0.15s ease;
}
.noala-tab:hover { color: var(--ink); }
/* L'anneau de focus doit TENIR dans les 4 px de padding de la barre :
   `overflow-x:auto` force `overflow-y` à `auto` (spec CSS overflow), donc ce qui
   déborde verticalement d'un onglet est rogné — à toutes les largeurs désormais,
   plus seulement ≤700 px. Le défaut `button:focus-visible` (offset 3 px + trait
   2 px = 5 px) dépassait d'1 px et se faisait couper, précisément sur la
   navigation clavier que ce correctif rend NÉCESSAIRE pour atteindre le dernier
   onglet. 1 + 2 = 3 px tient. Connu et laissé tel quel : l'ombre portée de
   `.noala-tab.active` (portée 8 px) perd ses 4 px les plus doux — cosmétique, et
   déjà le cas sous 700 px avant ce correctif. */
.noala-tab:focus-visible { outline-offset: 1px; }
.noala-tab.active {
  background: var(--accent);
  color: white;
  font-weight: 600;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.10);
}

/* Refonte UX F.3.a (2026-05-27) — variante secondaire pour les sous-tabs
   nested (ex: Compte > Réglages > Profil). Visuel plus discret pour
   marquer la hiérarchie. */
.noala-tabs--secondary {
  background: transparent;
  box-shadow: none;
  padding: 0;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  gap: 4px;
  flex-wrap: wrap;
}
.noala-tabs--secondary .noala-tab {
  font-size: 12px;
  padding: 6px 12px;
  font-weight: 400;
}
.noala-tabs--secondary .noala-tab.active {
  background: transparent;
  color: var(--accent-text);
  font-weight: 600;
  box-shadow: inset 0 -2px 0 var(--accent);
  border-radius: 0;
}

/* (`.noala-flash` et son `@keyframes` sont partis au lot 12 avec
   `openTimelineDay`, leur seul porteur : la classe n'était posée que par ce
   défilement-là.) */


/* B5/3.B — Frise de parcours + frise héros (jalons) : extraites dans
   frise.css (chantier C, source unique praticien ↔ patient). Chargé
   AVANT app.css dans index.html/patient.html — cf frise.css pour
   .noala-tl*, .noala-jalon-*, .noala-today, .noala-frise-progress et .noala-frise-ring.
   Restent ici (praticien-only, pas de markup patient) : le wrapper
   frise héros et son état vide. */
.noala-frise-hero { margin: var(--s-4) 0; }
.noala-frise-empty { color: var(--text-2); font-size: 13px; text-align: center; padding: var(--s-5) 0; }

/* ══ POPUP SCORES — DEUX VOLETS (2026-08-28) ═════════════════════════════════
   La liste et le detail etaient deux vues MUTUELLEMENT EXCLUSIVES, gatees sur le
   meme `scoreDetail.view` : changer de questionnaire imposait un aller-retour.
   La maquette les met cote a cote — liste etroite a gauche, detail a droite.

   ⚠️ `scoreDetail.view` est CONSERVE (quatre specs en dependent) et garde un role
   REEL : sous 900 px la grille se replie en une colonne et `data-view` decide
   lequel des deux volets s'affiche. Le repli est fait en CSS, pas en `x-show` :
   un `x-show` poserait un `display:none` INLINE qui gagnerait sur la media query,
   et il faudrait un listener de resize — que les regles du depot veulent au boot.

   ⚠️ Le nom `.noala-score-grid` est INTERDIT ici : chantier3b.spec.js:141 exige
   qu'il reste a zero occurrence (ancienne grille retiree en P0-2). */
.noala-score-main { padding: 18px 20px; min-width: 0; }


/* ═══ La rangee devient une GRILLE (revue du 2026-09-01, second passage) ════
   Mesure avant, derive de la position x d'une colonne d'une rangee a l'autre :
     tlabel 0 · date 0 · protocole 9 · statut 41 · scores 188 · chevron 0
   Le J±N et la date etaient donc DEJA alignes ; c'est tout ce qui les suivait
   qui partait en dents de scie. Une rangee en FLEX ne peut pas faire mieux —
   chaque element pousse le suivant, et la largeur des dates varie (« 04 août »
   contre « 18 sept. »). Des colonnes FIXES rendent zero partout.
   ⚠️ `minmax(0, 1fr)` pour les scores et non `1fr` : une colonne `1fr` prend au
   minimum la largeur de son contenu, donc ne retrecit jamais et repousse le
   chevron hors de la rangee des que les pastilles sont nombreuses. */
.noala-etape-qs-item {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  max-width: 210px;
  padding: 2px 8px;
  border-radius: var(--radius-pill, 999px);
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: 11px;
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
}
/* ⚠️ L'ELLIPSE VIT SUR LE NOM, PAS SUR LA PASTILLE. `text-overflow` ne s'applique
   qu'à un conteneur de TEXTE : posé sur la pastille, qui est `inline-flex`, il
   n'a aucun effet sur ses enfants — le nom était coupé net, sans les points de
   suspension qui disent qu'il continue. Défaut vu à la CAPTURE, invisible à la
   mesure (la largeur était bien de 210 px, comme demandé).
   `min-width: 0` est la moitié nécessaire : sans lui, un enfant de flex refuse
   de rétrécir sous la largeur de son contenu et ne déborde jamais. */
.noala-etape-qs-item > span:first-child {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.noala-etape-qs-item > strong, .noala-etape-qs-item > em { flex: none; }
.noala-etape-qs-item strong { color: var(--text); font-weight: 700; font-variant-numeric: tabular-nums; }
.noala-etape-qs-item em { color: var(--text-3); font-style: italic; }
.noala-etape-qs-item .noala-ic { width: 12px; height: 12px; flex: none; }

/* ═══ Les deux portes du nouvel envoi (revue du 2026-09-01, point 9) ══════
   Elles remplacent deux barres de recherche en ligne. Chacune ouvre le selecteur
   deja employe par le builder de protocole — meme composant, pas un jumeau. */

.noala-panel-list .noala-panel-avatar { flex: none; margin-right: 2px; }
.noala-panel-list .noala-card--data { margin-left: 18px; margin-right: 18px; }

.noala-envoi-portes { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 6px; }
.noala-envoi-porte {
  flex: 1 1 0;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 14px;
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.noala-envoi-porte:hover { border-color: var(--accent); border-style: solid; color: var(--accent-text); }
.noala-envoi-porte:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.noala-envoi-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0; }
.noala-envoi-chips .noala-etape-qs-item { max-width: 100%; }
.noala-envoi-chip-x {
  border: 0; background: none; cursor: pointer; color: inherit;
  line-height: 1; font-size: 14px; padding: 0 0 0 2px; flex: none;
}

/* L'aperçu d'un questionnaire ou d'un contenu (sous sa rangée dans la fenêtre de
   choix commune, `cabinet.css` y règle la mise en page). */
.noala-apercu { max-height: 62vh; overflow: auto; line-height: 1.55; }
.noala-apercu-lab {
  margin: 14px 0 4px; font-size: 11px; font-weight: 600;
  letter-spacing: .02em; text-transform: uppercase; color: var(--text-2);
}
.noala-apercu-bloc {
  padding: 10px 12px; border-radius: var(--radius-md);
  background: var(--accent-tint); border: 1px solid var(--border-2);
}
.noala-apercu-bloc + .noala-apercu-bloc { margin-top: 8px; }
.noala-apercu-bloc p { margin: 0; font-size: 13px; }
.noala-apercu-bloc .noala-apercu-lab { margin-top: 0; }
/* ⚠️ La note interne se distingue VISUELLEMENT de la phrase patient : les deux
   sont du texte libre côte à côte, et rien d'autre que la couleur du cadre ne
   dirait au praticien laquelle son patient va lire. */
.noala-apercu-bloc--interne { background: var(--surface-2); }
.noala-apercu-questions { margin: 4px 0 0 18px; padding: 0; font-size: 13px; }
.noala-apercu-questions li { margin-bottom: 8px; }
.noala-apercu-mod {
  display: block; font-size: 11.5px; color: var(--text-2); margin-top: 2px;
}
.noala-apercu-vide { font-size: 12.5px; color: var(--text-2); margin: 10px 0 0; }
.noala-apercu-corps { font-size: 13px; }

/* ═══ Le code couleur des types de contenu ═════════════════════════════════
   Source : la session `chantier-c-medical`, qui refond le builder en parallele —
   le proprietaire produit a demande le MEME style aux deux surfaces. Chaque
   couple a ete calcule (encre descendue par pas de 0,5 % de luminosite jusqu'au
   premier palier passant 4,5:1) puis REVERIFIE ici independamment : mes ratios
   tombent aux siens a 0,03 pres, le pire des trois fonds est >= 4,52 partout.

     type          /pastille  /blanc  /--bg
     PROM             4,58     5,18    4,95
     PREM             4,60     5,22    5,00
     QUIZ             4,56     5,37    5,14
     fiche            4,53     5,26    5,03
     faq              4,61     5,14    4,91
     video            4,56     5,38    5,15
     lien             4,53     5,39    5,16
     application      4,53     5,39    5,16
     document         4,52     5,28    5,05

   ⚠️ DES APLATS OPAQUES, jamais des `rgba`. En translucide le rapport dependrait
   de la surface derriere — or la meme pastille vit sur une rangee teintee, sur du
   blanc et sur `--bg`. C'est le mode de panne de `--surface-2` / `--text-2`
   (4,28:1) ecarte plus tot dans ce chantier.
   ⚠️ AUCUNE NE DERIVE DE `--accent` : c'est un token de theme personnalisable, et
   un code couleur qui change avec le theme cesse d'etre un code.
   ⚠️ HUIT TEINTES POUR NEUF TYPES, assume : `lien` et `application` partagent
   l'indigo. Au-dela de huit teintes de faible chroma a 11 px, deux voisines
   cessent d'etre distinguables ; la neuvieme distinction est portee par l'icone.
   ⚠️ Les tokens sont NOMMES d'apres la valeur en base, en minuscules, pour qu'un
   selecteur se derive sans table de correspondance.
   ⚠️ L'ATTRIBUT EST `data-nature`, PAS `data-type`, ALORS QUE LA VALEUR VIENT DE
   `Questionnaire.type` POUR LES QS. C'est un choix de VOCABULAIRE, pas d'exactitude :
   `.noala-content-chip[data-nature]` existe deja dans ce fichier et la session
   `chantier-c-medical` etend cette meme famille pour le builder. Deux surfaces qui
   disent la meme chose doivent employer le meme mot, sinon un lecteur croit a deux
   mecanismes. La source reste `type` cote QS et `nature` cote ressource — le front
   les fait converger vers une CLE unique (`typeCle`). */
:root {
  --type-prom-bg: #E9F3F2;        --type-prom-ink: #1D7A6D;
  --type-prem-bg: #E9F3EB;        --type-prem-ink: #277C35;
  --type-quiz-bg: #F2EAF3;        --type-quiz-ink: #A045A8;
  --type-fiche-bg: #E9EFF3;       --type-fiche-ink: #2B71A3;
  --type-faq-bg: #F5F3E7;         --type-faq-ink: #816C15;
  --type-video-bg: #F3EAED;       --type-video-ink: #BA3B65;
  --type-image-bg: #EEF1E6;       --type-image-ink: #5D6E1F;
  --type-lien-bg: #ECEAF3;        --type-lien-ink: #6C5CBC;
  --type-application-bg: #ECEAF3; --type-application-ink: #6C5CBC;
  --type-document-bg: #F3ECE9;    --type-document-ink: #A55634;
}
.noala-etape-qs-item[data-nature="prom"]        { background: var(--type-prom-bg);        color: var(--type-prom-ink);        border-color: transparent; }
.noala-etape-qs-item[data-nature="prem"]        { background: var(--type-prem-bg);        color: var(--type-prem-ink);        border-color: transparent; }
.noala-etape-qs-item[data-nature="quiz"]        { background: var(--type-quiz-bg);        color: var(--type-quiz-ink);        border-color: transparent; }
.noala-etape-qs-item[data-nature="fiche"]       { background: var(--type-fiche-bg);       color: var(--type-fiche-ink);       border-color: transparent; }
.noala-etape-qs-item[data-nature="faq"]         { background: var(--type-faq-bg);         color: var(--type-faq-ink);         border-color: transparent; }
.noala-etape-qs-item[data-nature="video"]       { background: var(--type-video-bg);       color: var(--type-video-ink);       border-color: transparent; }
.noala-etape-qs-item[data-nature="image"]       { background: var(--type-image-bg);       color: var(--type-image-ink);       border-color: transparent; }
.noala-etape-qs-item[data-nature="lien"]        { background: var(--type-lien-bg);        color: var(--type-lien-ink);        border-color: transparent; }
.noala-etape-qs-item[data-nature="application"] { background: var(--type-application-bg); color: var(--type-application-ink); border-color: transparent; }
.noala-etape-qs-item[data-nature="document"]    { background: var(--type-document-bg);    color: var(--type-document-ink);    border-color: transparent; }
/* ⚠️ LE CHIFFRE RESTE LISIBLE SUR CHAQUE TEINTE : il herite de l'encre du type,
   qui est justement celle qu'on a mesuree a 4,5:1 sur ce fond. Le laisser en
   `--text` aurait fallu remesurer neuf couples de plus. */
.noala-etape-qs-item[data-nature] strong { color: inherit; }
.noala-etape-qs-item[data-nature] em { color: inherit; opacity: .72; }
/* Le detail d'une etape, cote praticien : la pastille d'un contenu prend la teinte
   de son type. Une nature inconnue (`autre`) garde la teinte `.media` de frise.css.
   ⚠️ APRES frise.css, et c'est ce qui la fait gagner : meme specificite (0,2,0)
   que `.noala-jalon-pill.media`. */
.noala-jalon-pill[data-nature="fiche"]       { background: var(--type-fiche-bg);       color: var(--type-fiche-ink); }
.noala-jalon-pill[data-nature="faq"]         { background: var(--type-faq-bg);         color: var(--type-faq-ink); }
.noala-jalon-pill[data-nature="video"]       { background: var(--type-video-bg);       color: var(--type-video-ink); }
.noala-jalon-pill[data-nature="image"]       { background: var(--type-image-bg);       color: var(--type-image-ink); }
.noala-jalon-pill[data-nature="lien"]        { background: var(--type-lien-bg);        color: var(--type-lien-ink); }
.noala-jalon-pill[data-nature="application"] { background: var(--type-application-bg); color: var(--type-application-ink); }
.noala-jalon-pill[data-nature="document"]    { background: var(--type-document-bg);    color: var(--type-document-ink); }

/* ──────────────────────────────────────────────────────────── */
/* Login                                                          */
/* ──────────────────────────────────────────────────────────── */
.noala-login-shell {
  min-height: 100vh;
  display: flex; align-items: center; justify-content: center;
  padding: var(--s-5);
}
.noala-login-card {
  max-width: 440px;
  width: 100%;
  padding: var(--s-8) var(--s-6);
  display: flex; flex-direction: column; gap: var(--s-5);
}
.noala-login-brand {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: var(--s-2);
}
/* Le conteneur flex gère l'espacement (gap 8px) — pas de marge propre au SVG */
.noala-login-brand .noala-logo-svg { margin-right: 0; color: var(--ink); }
.noala-login-brand-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 24px;
  color: var(--ink);
  letter-spacing: -0.015em;
}
.noala-login-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 28px;
  color: var(--ink);
  margin: 0;
  letter-spacing: -0.015em;
  line-height: 1.25;
}
.noala-login-title .serif-italic { color: var(--accent-text); }
.noala-login-sub {
  font-size: var(--fs-sm);
  color: var(--text-2);
  margin: 0;
}
.noala-login-form {
  display: flex; flex-direction: column; gap: var(--s-3);
  margin-top: var(--s-3);
}
.noala-login-label {
  display: flex; flex-direction: column; gap: 6px;
  font-size: var(--fs-caps);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-2);
  font-weight: 500;
}
.noala-input {
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-2);
  font-family: var(--font-sans);
  font-size: 15px;
  color: var(--ink);
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
}
.noala-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.noala-login-error {
  padding: 10px 14px;
  background: var(--alert-soft);
  border: 1px solid rgba(196, 74, 45, 0.25);
  border-radius: var(--radius-md);
  font-size: var(--fs-sm);
  color: var(--alert);
}

/* ──────────────────────────────────────────────────────────── */
/* ──────────────────────────────────────────────────────────── */

/* Tableaux : scroll horizontal automatique sur la card parente, à toutes
   les tailles d'écran. Évite le débordement sur tablettes (700-1080px). */
.noala-card--data:has(.noala-table) { overflow-x: auto; }
.noala-page-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-h1);
  color: var(--ink);
  margin: 0;
  letter-spacing: -0.02em;
  line-height: 1.2;
}
.noala-page-sub {
  font-size: var(--fs-sm);
  color: var(--text-2);
  margin: var(--s-2) 0 0 0;
}

/* Recherche */
.noala-search-wrap {
  display: flex; align-items: center; gap: var(--s-2);
}
.noala-search-input {
  flex: 1;
  padding: 8px 12px;
  border: none;
  background: transparent;
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  color: var(--text);
  outline: none;
  width: 100%;
}
.noala-search-input::placeholder { color: var(--text-3); }

/* Table */
.noala-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}
.noala-table thead th {
  text-align: left;
  padding: var(--s-3) var(--s-4);
  font-size: var(--fs-caps);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-2);
  font-weight: 500;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.noala-table tbody td {
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--border-2);
  color: var(--text);
}

.noala-score-pill {
  /* `baseline` et non `center` : le « / 48 » doit rester sur la ligne de base
     du score. C'est la seule contrainte de mise en page que cette pastille
     surcharge — sa metrique vient du bloc `.noala-tag`. */
  align-items: baseline;
  /* ETAT NEUTRE PAR DEFAUT — et c'est le cas le PLUS FREQUENT, pas un repli.
     `scoreLevel` ne rend une severite que si le praticien a defini ses zones
     d'interpretation ; mesure du 2026-08-28 : 4 zones pour 317 praticiens. Sans
     fond declare ici, `data-level` valant null laissait donc une pastille
     TRANSPARENTE — un score pose a nu, plus une pastille — pour la quasi-totalite
     des utilisateurs. Les regles [data-level] ci-dessous ne font que teinter ce
     socle quand un bareme existe. */
  background: var(--surface-2);
  color: var(--text);
}
/* NIVEAU DE BAREME — les quatre valeurs du niveau : good, neutral, warn, alert.
   Elles venaient des zones perso (`PraticienInterpretation.severity`), parties au
   lot 10 ; depuis le lot 10 bis elles sont posees sur les bandes publiees des
   instruments (`scoring_config.interpretation[].severity`, migration 156), et
   `scoreLevel` (index.html) renvoie la valeur telle quelle. Or ces regles ciblaient good|warn|mid|bad : `alert`,
   le niveau le PLUS grave, n'avait donc AUCUNE couleur — le score le plus
   preoccupant etait le seul a ne pas se voir — pendant que `mid` et `bad`
   attendaient une valeur que rien n'emet. Aligne le 2026-08-28.

   ⚠️ HORS-DM : cette teinte vient du BAREME PUBLIE (les zones d'interpretation du
   praticien), jamais d'un pourcentage score/max calcule a la volee. Sans zone
   definie, `scoreLevel` rend `null` et la pastille reste NEUTRE — c'est le cas
   nominal (4 zones pour 317 praticiens en base, mesure du 2026-08-28), pas un
   repli. Ne JAMAIS deriver une couleur pour combler ce vide.

   ⚠️ Le texte ne prend pas --status-warn (#C68A2E, ~3,0:1 sur blanc, sous AA) mais
   --warn-text (#8A6216, 5,5:1) — le token que le lot A a introduit pour
   exactement ce role. Meme paire que --accent / --accent-text. */
/* Variante compacte — rangee de tiroir de jalon, ou la pastille cotoie un libelle
   de 13,5px. Remplace un `style="font-size:11px;padding:2px 9px"` inline. */
.noala-score-pill--sm { padding: 2px 9px; font-size: 11px; }
.noala-score-pill-max { opacity: .6; }
.noala-score-pill[data-level="good"]    { background: var(--status-good-soft); color: var(--status-good-text); }
.noala-score-pill[data-level="warn"]    { background: var(--status-warn-soft); color: var(--warn-text); }
.noala-score-pill[data-level="alert"]   { background: var(--alert-soft);       color: var(--alert-text); }
.noala-score-pill[data-level="neutral"] { background: var(--surface-2);        color: var(--text); }

/* Chantier #2 — Activité›Questionnaires : liste groupée par date + cellule
   QS empilée (chaque questionnaire + son score sur sa propre ligne). */


/* ── Lot F (audit V2 §7) — accordéon « Consentements » (<details>/<summary>).
   Partagé patient.html (page Consentements) + index.html (popup fiche patient,
   P1-5, 2026-07-15) — déplacé ici depuis patient.css pour rester un mécanisme
   unique chargé par les deux fronts (app.css est commun aux deux). ────────── */
.noala-acc {
  /* Lit la gravite si la rangee en porte une, sinon sa surface d'origine.
     Sans ce repli, `.noala-sev--*` serait battue ici en silence (accordeon (partage index.html + patient.html)). */
  /* Ecart 5.32 — radius 12 -> 17 px, ombre absente -> `--shadow-sm`, summary
     13/14 -> 15/16 px. ⚠️ PARTAGE avec la popup « Documents legaux »
     d'index.html et les accordeons d'admin.html : ce lot les change AUSSI,
     et c'est voulu (un composant, une definition). Mesure a l'appui. */
  background: var(--sev-bg, var(--surface)); border: 1px solid var(--border);
  border-radius: 17px; margin-bottom: 10px; overflow: hidden;
  box-shadow: var(--shadow-sm);
}
.noala-acc > summary {
  display: flex; align-items: center; gap: 12px; padding: 15px 16px;
  cursor: pointer; list-style: none;
}
.noala-acc > summary::-webkit-details-marker { display: none; }
.noala-acc > summary::after {
  content: "›"; margin-left: auto; color: var(--text-3);
  font-size: 17px; transform: rotate(90deg); transition: transform .15s;
}
.noala-acc[open] > summary::after { transform: rotate(-90deg); }
.noala-acc:not([data-sev]) > summary:hover { background: var(--surface-2); }
/* `.noala-acc-ico` : définition canonique plus haut, avec `.noala-ico-tile`. */
.noala-acc-t { display: flex; flex-direction: column; min-width: 0; }
.noala-acc-title { font-weight: 600; font-size: 14.5px; color: var(--ink); }
.noala-acc-sub { font-size: 12px; color: var(--text-2); }
.noala-acc-state[data-ok="1"] { color: var(--accent); flex-shrink: 0; }
/* ═══ Ecart 5.42 — L'ENCART DE MESSAGE, une definition pour quatorze sites.
   Quatorze boites vivaient en `style="…"` dans patient.html, dont dix melangeaient
   DEUX familles de rouge : fond et bordure en `--status-bad` (le rouge des
   statuts de donnee), texte en `--alert` (celui de la gravite d'un message).
   Un encart d'erreur releve de la gravite : il est desormais d'une seule famille.
   Effet de bord voulu — ces encarts suivent enfin les tokens de gravite.
   ⚠️ La classe ne porte QUE la couleur et le rayon. Padding, taille de texte et
   marges restent au site : ils varient legitimement (un encart de modal est plus
   serre qu'un encart de page), et les figer ici forcerait des variantes. */
.noala-alert-box {
  background: var(--alert-soft);
  border: 1px solid color-mix(in srgb, var(--alert) 30%, transparent);
  color: var(--alert);
  border-radius: var(--radius-md);
}
.noala-warn-box {
  background: var(--warn-soft);
  border: 1px solid color-mix(in srgb, var(--warn) 34%, transparent);
  color: var(--warn-text);
  border-radius: var(--radius-md);
}

/* B5 — pill de statut homogène de la page Consentements patient (états réels,
   ≠ .noala-acc-state binaire). Classe NOUVELLE (ne modifie pas .noala-acc-state,
   partagée avec le praticien). */
.noala-consent-state { white-space: nowrap; flex-shrink: 0; }
.noala-consent-state[data-state="ok"]        { background: var(--accent-soft); color: var(--accent-text); }
.noala-consent-state[data-state="pending"]   { background: var(--surface-2); color: var(--text-2); }
.noala-consent-state[data-state="withdrawn"] { background: var(--status-bad-soft); color: var(--status-bad); }
.noala-acc-body { padding: 4px 14px 16px; border-top: 1px solid var(--border-2, var(--border)); }
.noala-acc-body .noala-portal-doc-row { border: none; padding-left: 0; padding-right: 0; }
.noala-acc-mineur {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--accent-soft); border-radius: var(--radius-md);
  padding: 11px 14px; margin-bottom: var(--s-3);
  font-size: 12.5px; color: var(--ink); line-height: 1.5;
}
.noala-acc-mineur .noala-ic { color: var(--accent); flex-shrink: 0; margin-top: 1px; }

/* (Lot 4 — la colonne « Questionnaires & scores » a été retirée de la liste
   d'activité ; le détail QS/scores vit désormais dans le panneau latéral.) */

.noala-jn {
  font-family: var(--font-serif);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
}
.noala-jn[data-side="pre"]  { color: #3D7F8F; }
.noala-jn[data-side="j0"]   { color: #143B4A; }
.noala-jn[data-side="post"] { color: #1A7568; }


/* P1-9 — .noala-proto-card/.noala-protos-grid/.noala-proto-step (+ .noala-proto-head/
   -icon/-spec, déjà morts avant ce lot) retirés : la page Protocoles est passée
   à la table générique .noala-cat-rows (P1-8, cf plus bas) — plus aucun
   consommateur (grep confirmé sur tous les frontends).
   P1-10 — même sort pour .noala-qs-grid/.noala-qs-card (+ -name/-loc/-meta) :
   la page Médiathèque (dernière consommatrice) est passée à .noala-cat-rows —
   plus aucun consommateur (grep confirmé sur tous les frontends). Les bandes
   de groupement .noala-qs-sec-* (juste en dessous) restent utilisées par les
   3 catalogues (QS/Protocoles/Médiathèque) — NE PAS supprimer. */

/* Chantier #5 — bandes de région du listing Questionnaires */
.noala-qs-sec-head {
  display: flex; align-items: center; gap: 10px;
  margin: 28px 0 14px;
}
.noala-qs-sec-title {
  font-family: var(--font-display);
  font-size: 18px; font-weight: 600; color: var(--ink);
  letter-spacing: -0.01em;
}
.noala-qs-sec-rule { flex: 1; height: 1px; background: var(--border); }
.noala-tag {
  background: var(--border);
  color: var(--text-2);
}


/* ──────────────────────────────────────────────────────────── */
/* Modals (wizard nouveau suivi, edit patient, edit episode)     */
/* ──────────────────────────────────────────────────────────── */
.noala-modal-overlay {
  position: fixed;
  inset: 0;
  background: var(--modal-scrim);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  z-index: 1000;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 6vh var(--s-4) var(--s-4);
  overflow-y: auto;
  animation: noala-modal-fade 0.15s ease-out;
}
/* (Refonte Sérénité, Lot 5 slice 3) La règle `.noala-modal-backdrop` z-index:1100 a
   été retirée : les 9 modales secondaires qui l'utilisaient passent désormais par
   `.noala-modal-overlay[data-kind="dialog"]` + le mécanisme _openSecondary/
   _closeSecondaryReturn (empilement strict zéro, une seule surface visible à la
   fois). Plus aucun markup ne référence `.noala-modal-backdrop`. */
@keyframes noala-modal-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.noala-modal-card {
  width: 100%;
  max-width: 620px;
  /* Empêche les modales (builders, détails admin) de dépasser la fenêtre.
     Les contenus longs scrollent en interne au lieu de scroll la page. */
  max-height: calc(100vh - 4vh);
  overflow-y: auto;
  padding: var(--s-5) var(--s-5) var(--s-4);
  animation: noala-modal-rise 0.18s ease-out;
  /* Override .noala-card--glass : les wizards (nouveau suivi, edit patient,
     builders…) doivent être quasi opaques pour rester lisibles sur fond
     light, où le glass-tint 50% était fantomatique. */
  background: var(--bg-elev, #fdfaf5);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  /* Refonte UX A.1 (2026-05-27) — position relative pour ancrer le bouton
     X en absolute top-right, en complément ESC + click outside. */
  position: relative;
}

/* ───── Lot 5 (refonte Sérénité) — système de surfaces via data-kind ─────
   La classe .noala-modal-overlay est CONSERVÉE (contrat e2e) ; data-kind module
   le contenant : drawer (panneau latéral) · dialog (confirmation) · page (builders). */
.noala-modal-overlay[data-kind="drawer"] { align-items: stretch; justify-content: flex-end; padding: 0; }
/* A3 — largeur auto bornée : le drawer s'élargit jusqu'à la largeur naturelle
   de son contenu (tables denses), plafonné à l'écran. Supprime le scroll
   horizontal sans figer une largeur par contenu. */
.noala-modal-overlay[data-kind="drawer"] .noala-modal-card {
  /* min-width en `min(560px, 100%)` et non `560px` fixe : le plancher ne doit
     jamais dépasser le viewport, sinon la bottom-sheet mobile (≤640px, qui
     remet width:100% mais NE réinitialise PAS min-width) reste coincée à 560px
     sur un téléphone de 375px → contenu rogné / débordement horizontal. La
     règle de base n'est évaluée qu'au-delà de 640px (en-deçà la media query
     prend le relais), donc 100% y vaut toujours ≥ 641 → plancher = 560px. */
  width: fit-content; min-width: min(560px, 100%); max-width: min(960px, 96vw);
  height: 100vh; max-height: 100vh;
  border-radius: 0; animation: noala-drawer-in 0.26s cubic-bezier(.16, 1, .3, 1);
}
/* La prose ne doit PAS dicter la largeur : le max-content d'un <p> est son texte
   sur une seule ligne, ce qui collerait tous les drawers au plafond. Plafonné
   sous le plancher de 560px (re-mesuré refonte 2026-07 : 60ch Poppins = 528px
   à 14px, la taille body — un p à ≥15px dépasserait 560px sans déborder pour
   autant, max-width 96vw + wrap), un paragraphe ne pèse donc jamais sur
   fit-content à la taille standard. */
.noala-modal-overlay[data-kind="drawer"] .noala-modal-card p { max-width: 60ch; }
@keyframes noala-drawer-in { from { transform: translateX(36px); opacity: .5; } to { transform: none; opacity: 1; } }

.noala-modal-overlay[data-kind="dialog"] { align-items: center; }
.noala-modal-overlay[data-kind="dialog"] .noala-modal-card { max-width: 440px; }

.noala-modal-overlay[data-kind="page"] { align-items: stretch; justify-content: stretch; padding: 0; }
.noala-modal-overlay[data-kind="page"] .noala-modal-card {
  width: 100%; max-width: none; height: 100vh; max-height: 100vh; border-radius: 0;
}

@media (max-width: 640px) {
  .noala-modal-overlay[data-kind="drawer"] { align-items: flex-end; justify-content: stretch; }
  .noala-modal-overlay[data-kind="drawer"] .noala-modal-card {
    width: 100%; max-width: none; height: auto; max-height: 90vh;
    border-radius: 18px 18px 0 0; animation: noala-sheet-in 0.24s ease;
  }
}
@keyframes noala-sheet-in { from { transform: translateY(40px); } to { transform: none; } }

/* Refonte UX A.1 (2026-05-27) — bouton X unifié sur toutes les modales.
   Sélecteur enfant direct `.noala-modal-card > .noala-modal-close` (ou
   `.modal-shell > .noala-modal-close` pour les modales admin.html) pour
   ne PAS impacter les boutons inline (dans `.noala-modal-head` par
   exemple) qui réutilisent la même classe en pattern legacy.
   Cohabite avec ESC (handler global) et click outside (@click.self). */
.noala-modal-card > .noala-modal-close,
.modal-shell > .noala-modal-close {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid transparent;
  border-radius: 50%;
  background: transparent;
  color: var(--text-2);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
  z-index: 2;  /* Au-dessus du contenu modal scrollé */
}
.noala-modal-card > .noala-modal-close:hover,
.modal-shell > .noala-modal-close:hover {
  background: var(--surface-2);
  color: var(--ink);
  border-color: var(--border);
}
.noala-modal-card > .noala-modal-close:focus-visible,
.modal-shell > .noala-modal-close:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ── Lot 13a : la croix des SURFACES EN PLEINE PAGE ────────────────────────
   Écart 1.18 de l audit du 2026-08-28. Le grief n est pas la taille mais la
   DISTANCE : la carte est plein écran, son contenu recentré à 960 px, donc une
   croix ancrée au bord droit de la FENETRE se retrouvait à plusieurs centaines de
   pixels du titre qu elle ferme.

   ⚠️ ELLE RESTE ABSOLUE, elle n est pas « inline » comme l audit le demandait, et
   c est un arbitrage du 2026-09-06 : la croix est un bouton UNIQUE par coque, placé
   avant tous les `<template x-if>`, donc la rendre inline coûterait trois copies,
   une par en-tête de builder.
   ⚠️ Et cela ne réglerait PAS la disponibilité au défilement, contrairement à ce que
   ce commentaire a d abord affirmé : `.noala-modal-card` est le conteneur de
   défilement, la croix y est absolue, donc elle défile DÉJÀ hors de l écran quand on
   descend. Inline elle ferait de même. Rendre la croix permanente demanderait un
   en-tête `position: sticky` ou un bouton posé sur l overlay — un autre chantier,
   qui n est pas celui de l écart 1.18.

   Elle est donc ancrée sur la COLONNE de contenu plutôt que sur la fenêtre, et se
   loge dans la marge JUSTE à droite de cette colonne : elle touche le titre du
   regard.
   ⚠️ AU-DELÀ DE 1060 px SEULEMENT — c est le point où `max()` bascule, la marge à
   droite de la colonne valant alors exactement 10 px. En dessous, le repli ramène la
   croix au bord de la carte, comme avant ce lot, ET LA RÉSERVE DE 44 px REVIENT AVEC
   ELLE (cf le `@media` plus bas) : sans cela le groupe d actions de l en-tête serait
   passé sous la croix, ce qui aurait été une régression franche du lot.

   ⚠️ Le sélecteur est SCOPÉ à `[data-kind="page"]`. La règle générique gouverne une
   vingtaine de boutons sur les trois fronts, dont les tiroirs du portail patient :
   la modifier sans portée repeindrait tout, en silence.

   ⚠️ Les SIX surfaces en pleine page sont visées, les trois builders praticien
   (`.noala-modal-overlay`) comme les trois modales de la console
   (`.modal-overlay`, classes locales d admin.html) : même coque, même défaut,
   arbitrage du 2026-09-06. */
.noala-modal-overlay[data-kind="page"] > .noala-modal-card > .noala-modal-close,
.modal-overlay[data-kind="page"] > .modal-shell > .noala-modal-close {
  width: 30px;
  height: 30px;
  font-size: 15px;
  top: 16px;
  background: var(--surface-2);
  color: var(--text-2);
}
/* ⚠️ LE DÉCALAGE EST CONDITIONNÉ AU MÊME `:has()` QUE LA COLONNE. Le recentrage à
   960 px vit sous `:has(.noala-bsec)` : dans un
   navigateur sans `:has()`, la colonne n existe pas, le contenu occupe toute la
   largeur, et une croix décalée de 160 px atterrirait au milieu du texte. Les deux
   règles tombent donc ensemble, et la croix reprend alors le bord, où elle était. */
.noala-modal-overlay[data-kind="page"] > .noala-modal-card:has(.noala-bsec) > .noala-modal-close,
.modal-overlay[data-kind="page"] > .modal-shell:has(.noala-bsec) > .noala-modal-close {
  right: max(10px, calc((100% - 960px) / 2 - 40px));
}
/* Le fond plein au repos prend la place que le survol occupait. ⚠️ L écart entre
   `--surface-2` et `--border` est trop faible pour porter seul la réponse au survol
   (mesuré à 1,05:1) : ce sont la BORDURE et l encre du glyphe, héritées de la règle
   générique, qui la portent. La teinte n est qu un appoint. */
.noala-modal-overlay[data-kind="page"] > .noala-modal-card > .noala-modal-close:hover,
.modal-overlay[data-kind="page"] > .modal-shell > .noala-modal-close:hover {
  background: var(--border);
  color: var(--ink);
}
/* La reserve de 44 px n a plus d objet QUAND LA CROIX EST SORTIE DE LA COLONNE :
   elle laisserait un trou à droite du titre. ⚠️ ELLE EST DONC LEVÉE SOUS LES DEUX
   MEMES CONDITIONS QUE LE DÉCALAGE, et pas une de moins — le `:has()` de la colonne,
   et le seuil de 1060 px où `max()` bascule. La lever sans condition faisait passer
   le groupe d actions de l en-tête sous la croix dès 1060 px, ce qui n était pas une
   note de bas de page mais une régression du lot. ⚠️ La réserve ne visait d ailleurs
   pas le même élément selon le builder — le titre doit être enfant DIRECT de la
   rangée, ce qui n est vrai que pour le builder QS — donc elle n en protégeait qu un
   sur trois, avant comme après. */
@media (min-width: 1061px) {
  .noala-modal-overlay[data-kind="page"] .noala-modal-card:has(.noala-bsec) div:has(> .noala-modal-title),
  .modal-overlay[data-kind="page"] .modal-shell:has(.noala-bsec) div:has(> .noala-modal-title) {
    padding-right: 0;
  }
}
@keyframes noala-modal-rise {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.noala-modal-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 22px;
  letter-spacing: -0.01em;
  margin: 0 0 var(--s-4) 0;
  color: var(--ink);
}
.noala-modal-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  margin-top: var(--s-4);
  padding-top: var(--s-3);
  border-top: 1px solid var(--border);
  flex-wrap: wrap;
}

/* Stepper (4 barres) */
.noala-stepper {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  margin-bottom: var(--s-4);
}
.noala-stepper-bar {
  height: 4px;
  border-radius: 2px;
  background: var(--border);
  transition: background 0.2s;
}
.noala-stepper-bar.active { background: var(--accent); }
.noala-stepper-bar.current {
  background: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}
.noala-step-label {
  font-size: var(--fs-caps);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent-text);
  font-weight: 500;
  margin-bottom: var(--s-3);
}

/* Form rows */
.noala-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-3);
  margin-bottom: var(--s-3);
}
.noala-form-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: var(--s-3);
}
.noala-form-group > span {
  font-size: 12px;
  color: var(--text-2);
  font-weight: 500;
  letter-spacing: 0.01em;
}
.noala-form-group .noala-input { font-size: 14px; padding: 10px 12px; }
/* ⚠️ ÉCARTS 1.28 et 1.29 — « Publier dans le catalogue NOALA » existe en TROIS
   exemplaires dans la console, pour la MÊME action, dans DEUX styles opposés :
   teal rassurant dans l'éditeur de checklists (`index.html:4136`), rouge
   d'alerte dans les builders de questionnaire et de protocole.
   ⚠️ LE ROUGE ÉTAIT UN CONTRESENS, pas seulement une incohérence. `--alert` est
   l'encre du DESTRUCTIF ; publier au catalogue ne détruit rien, c'est une action
   réservée à l'admin. Le rouge y disait « attention, ça peut casser », ce qui est
   faux — et ce qui use le signal là où il compte vraiment.
   ⚠️ Le rayon valait `4px` en style inline, absent de l'échelle de tokens dont le
   plus petit est `--radius-sm: 10px` ; et le `border-left: 3px` en faisait le
   seul élément à bordure asymétrique de l'écran.
   Une classe, trois porteurs possibles : le précédent teal du produit fait foi. */
.noala-publier-catalogue {
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  border-radius: var(--radius-md);
  padding: 10px 14px;
}

.noala-checkbox {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 13px;
  color: var(--text-2);
  margin: var(--s-2) 0;
  cursor: pointer;
  line-height: 1.45;
}
.noala-checkbox input { margin-top: 3px; }

.caps {
  font-size: var(--fs-caps);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-2);
  font-weight: 500;
}

@media (max-width: 700px) {
  .noala-modal-overlay { padding: var(--s-3); }
  .noala-modal-card { padding: var(--s-4); }
  .noala-form-row { grid-template-columns: 1fr; }
}

/* ──────────────────────────────────────────────────────────── */
/* Builders (questionnaire + protocole) — wider modal            */
/* ──────────────────────────────────────────────────────────── */
/* Le plafond par défaut de 620px est déjà posé par `.noala-modal-card` plus
   haut (cf ~l.2145). Il était re-déclaré ici DEUX fois à l'identique, dont une
   via `:has(> div > h3.noala-modal-title:first-child)`. Aucune des deux ne
   changeait quoi que ce soit au rendu — mais la spécificité de la variante
   `:has()` vaut (0,3,2), soit PLUS que les plafonds par surface, qui sont tous
   en (0,3,0) : `[data-kind="drawer"]` (min(960px, 96vw)) et
   `[data-kind="dialog"]` (440px). Un drawer dont la carte s'ouvre sur un
   `<div><h3 class="noala-modal-title">` restait donc plafonné à 620px, et son
   contenu large scrollait horizontalement dans `.noala-card--data` — très
   exactement le symptôme que A3 (cf ~l.2167) devait supprimer, et qu'il n'a
   jamais réellement supprimé : la règle qui le défait lui est ANTÉRIEURE.
   Les deux déclarations sont retirées ; le défaut reste porté par la règle de
   base, et chaque surface garde la main sur son propre plafond. */
/* Override via classe distincte si on veut élargir tous les builders */
.noala-modal-overlay > .noala-modal-card:has(.noala-bsec) {
  max-width: 880px;
}

.noala-bsec {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-2);
  margin-bottom: var(--s-4);
  overflow: hidden;
}


.noala-bsec-hdr {
  padding: 10px 14px;
  font-size: var(--fs-caps);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-2);
  font-weight: 600;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}

.noala-bsec-body {
  padding: var(--s-4);
}


/* ⚠️ `.noala-resource-chip` A ÉTÉ RETIRÉ (écart 1.4, 2026-09-01). Il teintait par
   TYPE DE FICHIER et ne connaissait que `pdf` et `video` : un LIEN ou un
   INTERACTIF ne matchait aucune règle, donc aucune couleur — et recevait une
   icône de film. Ses teintes étaient des hexadécimaux Tailwind bruts, hors thème.
   ⚠️ Son commentaire le gardait au motif qu'il « sert ailleurs ». Mesuré : UN
   porteur dans les sept fronts, zéro garde e2e. C'était faux, et c'est la raison
   pour laquelle il a survécu à la vague qui devait le remplacer.
   `.noala-content-chip[data-nature]` le remplace — il teinte par NATURE, couvre
   les quatre types, et suit le thème. */

/* ═══ La pastille d'OBJECTIF, partagée par trois surfaces ═════════════════
   ⚠️ ELLE VENAIT DE `frise.css`, d'où son nom. Elle a déménagé ici le 2026-08-31
   parce que `admin.html` ne charge pas cette feuille et que la table des étapes
   de son builder l'emploie : elle y serait sortie NUE.
   Ses trois consommateurs aujourd'hui : la frise du parcours (index.html), le
   détail des étapes de la popup Scores, et la colonne « Objectif de score » du
   builder de protocole. Le nom reste trompeur — la renommer touche cinq sites
   d'appel et un e2e, c'est un geste séparé.
   ⚠️ Elle a failli être réécrite en double, sous le nom `.noala-obj-pill`, par
   quelqu'un qui avait vérifié que son NOM était libre sans chercher si le
   COMPOSANT existait. Chercher le composant, pas le nom. */
.noala-jalon-obj {
  display: inline-flex; align-items: center; flex: none;
  padding: 1px 8px;
  border-radius: var(--radius-pill, 999px);
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 20%, transparent);
  color: var(--accent-text);
  font-size: 11px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ⚠️ LE NOM DE CETTE CLASSE EST TROMPEUR, et c'est une dette consignée le
   2026-08-31, pas un oubli. `.noala-jalon-obj` n'a rien de propre à la frise :
   c'est LA pastille d'objectif du produit, et la popup Scores l'emploie depuis
   la vague 3 du lot 5 (écart 1.26 — « reprendre la pastille comme composant
   partagé »). Elle vit ici parce que c'est la frise qui en a eu besoin la
   première. La renommer et la déplacer dans app.css touche ce fichier, ses
   quatre sites d'appel et le cache-bust de trois fronts : geste séparé.
   ⚠️ Elle a failli être réécrite en double, sous le nom `.noala-obj-pill`, par
   quelqu'un qui avait vérifié que son nom était libre sans chercher si le
   composant existait. Chercher le COMPOSANT, pas le nom.

   Ce que l'emploi dans la popup Scores ajoute, et rien de plus : la pastille y
   est un BOUTON (elle ouvre l'édition de l'objectif), et elle doit s'y afficher
   MÊME SANS OBJECTIF — la frise, elle, la masque par `x-show`. Sans objectif,
   la colonne « Objectif » ne portait qu'une icône cible grise nue : rien ne
   disait qu'on pouvait cliquer. */
button.noala-jalon-obj { cursor: pointer; gap: 5px; padding: 3px 10px; }
button.noala-jalon-obj > svg { width: 12px; height: 12px; }
button.noala-jalon-obj:hover { border-color: var(--accent); }
/* Sans objectif défini : même forme, encre retenue. La forme dit « ici se pose
   une cible », l'encre dit qu'il n'y en a pas encore. */
.noala-jalon-obj[data-vide] {
  background: transparent;
  border-color: var(--border);
  color: var(--text-2);
  font-weight: 500;
}

/* ═══ Le chip de CONTENU, teinté par nature (écart 1.4) ═══════════════════
   ⚠️ Il ne remplace PAS `.noala-resource-chip`, qui teinte par TYPE DE FICHIER
   (pdf, vidéo) et sert ailleurs. Celui-ci teinte par NATURE de contenu, ce qui
   est un autre axe : un PDF de consigne et un PDF de pathologie ne se lisent pas
   de la même façon dans un protocole.
   Il emprunte la métrique du groupe de jetons ci-dessus (11px/600, pilule,
   3px 10px) sans la recopier. */
.noala-content-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border-radius: var(--radius-pill, 999px);
  padding: 3px 10px;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.5;
  max-width: 100%;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.noala-content-chip > svg { width: 12px; height: 12px; flex: none; }
/* Questionnaire destiné au patient — la nature la plus fréquente, en accent. */
.noala-content-chip[data-nature="qs"] {
  background: var(--accent-tint);
  color: var(--accent-text);
}
/* Questionnaire réservé au praticien ou à l'équipe : neutre, parce que le patient
   ne le verra jamais. ⚠️ `--text` (7,76:1) et non `--text-2` (4,32:1, sous AA). */
.noala-content-chip[data-nature="qs-praticien"] {
  background: var(--surface-2);
  color: var(--text);
}
/* Ressource interactive — le violet du produit, seul emploi de cette famille.
   Mesuré : 6,81:1. */
.noala-content-chip[data-nature="interactif"] {
  background: rgba(110, 63, 119, 0.10);
  color: #6E3F77;
}
/* Ressource à consulter : PDF, vidéo, lien. Accent doux, plus retenu que le
   questionnaire — on la consulte, on ne la remplit pas. */
.noala-content-chip[data-nature="ressource"] {
  background: var(--surface-2);
  color: var(--accent-text);
}
/* Pièce à fournir ou consigne à lire — devis, consentement.
   ⚠️ `--warn-text` (4,87:1) et non le `#C68A2E` de la maquette (2,64:1). */
.noala-content-chip[data-nature="piece"] {
  background: var(--warn-soft);
  color: var(--warn-text);
}

/* ── Les neuf natures réelles (2026-09-01) ────────────────────────────────────
   Les cinq règles ci-dessus regroupaient tout le contenu à consulter sous une
   seule nature `ressource` : une fiche d'information, une FAQ, une vidéo et un
   PDF s'y rendaient identiques. Elles restent en place — `admin.html` partage
   cette pastille et émet encore l'ancien vocabulaire.
   ⚠️ Les deux champs porteurs sont DIFFÉRENTS : `Questionnaire.type`
   (PROM|PREM|QUIZ) et `Ressource.nature` (fiche|faq|video|lien|application|
   document). Ni `Ressource.type`, qui confond fiche et FAQ — toutes deux
   `texte` —, ni `Ressource.categorie`, qui est le SUJET et non la forme. */
.noala-content-chip[data-nature="prom"]        { background: var(--type-prom-bg);        color: var(--type-prom-ink); }
.noala-content-chip[data-nature="prem"]        { background: var(--type-prem-bg);        color: var(--type-prem-ink); }
.noala-content-chip[data-nature="quiz"]        { background: var(--type-quiz-bg);        color: var(--type-quiz-ink); }
.noala-content-chip[data-nature="fiche"]       { background: var(--type-fiche-bg);       color: var(--type-fiche-ink); }
.noala-content-chip[data-nature="faq"]         { background: var(--type-faq-bg);         color: var(--type-faq-ink); }
.noala-content-chip[data-nature="video"]       { background: var(--type-video-bg);       color: var(--type-video-ink); }
.noala-content-chip[data-nature="image"]       { background: var(--type-image-bg);       color: var(--type-image-ink); }
.noala-content-chip[data-nature="lien"]        { background: var(--type-lien-bg);        color: var(--type-lien-ink); }
.noala-content-chip[data-nature="application"] { background: var(--type-application-bg); color: var(--type-application-ink); }
.noala-content-chip[data-nature="document"]    { background: var(--type-document-bg);    color: var(--type-document-ink); }
/* Repli EXPLICITE. Sans lui, une nature hors carte sortirait sans fond ni encre
   propres — une pastille fantôme, impossible à distinguer d'un choix délibéré.
   Il est atteignable : `Questionnaire.type` porte aussi `INFO` et `CUSTOM`, et
   ce dernier est du contenu système réel. Même couple que `qs-praticien`,
   mesuré 7,76:1. */
.noala-content-chip[data-nature="autre"]       { background: var(--surface-2); color: var(--text); }

/* Lot 5 slice 2b (refonte Sérénité) — les builders praticien en data-kind="page"
   passent plein écran : priment sur les cascades de largeur
   (:has(.noala-bsec) 880px pour les builders QS/Protocole — cf l.2718).
   Spécificité +1 attribut + ordre source postérieur. Le devis vit sur le socle
   des pages d'édition depuis le lot 5 des builders (cabinet.css). La règle générique data-kind="page" (width:100%/height:100vh/
   border-radius:0, l.2528) fournit le reste. */
.noala-modal-overlay[data-kind="page"] .noala-modal-card:has(.noala-bsec) {
  max-width: none;
}
/* Lot 5 polish (refonte Sérénité) — le CONTENU des builders plein écran est
   recentré à 960px : la carte reste plein écran (scrim + scroll interne), seul le
   contenu se contraint pour ne pas s'étaler à 1280px. Couvre QS/Proto
   (:has(.noala-bsec)) côté index ; le pendant admin
   (.modal-shell) vit dans admin.html. ⚠️ Ce commentaire revendiquait autrefois un
   « effet de bord voulu » : l'en-tête s'éloignait du bord droit, donc la croix ne
   chevauchait plus la pilule BROUILLON. C'était précisément ce que l'écart 1.18
   appelait un défaut — la croix se retrouvait à des centaines de pixels de son
   titre. Le lot 13a l'a ramenée contre la colonne ; la largeur de 960 px, elle,
   reste ce qui empêche le contenu de s'étaler à 1280 px. */
.noala-modal-overlay[data-kind="page"] .noala-modal-card > div:has(.noala-bsec) {
  max-width: 960px;
  margin-left: auto;
  margin-right: auto;
}
/* Lot 5 polish — safe-area croix (SYSTÉMIQUE, tous popups/ouvertures). La croix
   .noala-modal-close est absolute (top:10 right:10, 36px). Toute rangée d'en-tête de
   modale — identifiée par un .noala-modal-title en ENFANT DIRECT — réserve 44px à
   droite, pour qu'aucun CTA/pill/bouton aligné à droite ne passe sous la croix.
   Précis (pas de [style*=] ni !important) et général aux 6 fronts (drawers, popups,
   modales index .noala-modal-card + admin .modal-shell). --s-5=20px de padding carte
   + 44px ⇒ contenu droit au-delà des 46px occupés par la croix. */
.noala-modal-card div:has(> .noala-modal-title),
.modal-shell div:has(> .noala-modal-title) {
  padding-right: 44px;
}


/* Autocomplete CCAM dans le builder Acte — dropdown sous le champ */
.noala-ccam-dropdown {
  position: absolute;
  left: 0; right: 0; top: 100%;
  z-index: 50;
  margin-top: 4px;
  max-height: 320px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(20, 18, 14, 0.12);
}
.noala-ccam-item {
  display: flex;
  gap: 10px;
  align-items: baseline;
  width: 100%;
  padding: 8px 12px;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--border);
  text-align: left;
  cursor: pointer;
  font-size: 13px;
  color: var(--ink);
  transition: background 0.1s;
}
.noala-ccam-item:hover { background: var(--surface-2); }
.noala-ccam-item:last-child { border-bottom: 0; }


/* ⚠️ LES REGLES `:has(.noala-score-detail-modal)` ONT ETE RETIREES le 2026-09-01 :
   la surface Scores n'est plus dans une modale, c'est une VUE du cadre de la
   fiche. Elles ne gouvernaient que la largeur — elargir une modale centree de
   620 px, puis la deplafonner en mode page et recentrer son contenu. Un selecteur
   `:has()` qui ne trouvera plus jamais sa cible est du code mort qui se lit comme
   vivant.
   ⚠️ LE NOM DE CLASSE, LUI, RESTE : quatorze regles ci-dessous y sont scopees en
   DESCENDANT et survivent telles quelles, et six specs e2e s'y ancrent. Le
   renommer serait vingt reprises pour un mot. Il dit « la surface Scores », pas
   « une modale » — c'est le nom qui a vieilli, pas la classe. */
.noala-score-detail-modal { max-width: 1040px; margin: 0 auto; width: 100%; }
.noala-score-detail-modal .noala-tabs {
  flex-wrap: wrap;
  gap: 4px;
}
.noala-score-detail-modal .noala-tabs .noala-tab {
  font-size: 13px;
  padding: 8px 14px;
}
.noala-score-detail-modal table.noala-table {
  font-size: 13px;
  table-layout: auto;
  width: 100%;
}
.noala-score-detail-modal table.noala-table td,
.noala-score-detail-modal table.noala-table th {
  word-wrap: break-word;
  overflow-wrap: break-word;
  vertical-align: top;
  padding: 8px 10px;
}
/* Colonne « Interprétation » : reste lisible mais autorise les retours à la ligne. */
.noala-score-detail-modal table.noala-table td:nth-child(4),
.noala-score-detail-modal table.noala-table th:nth-child(4) {
  max-width: 280px;
  white-space: normal;
}
.noala-score-detail-modal table.noala-table td:nth-child(1),
.noala-score-detail-modal table.noala-table th:nth-child(1) {
  white-space: nowrap;
}
/* (L'exception `white-space: normal` du niveau 1 est partie avec sa table : le
   nom du questionnaire vit maintenant dans `.noala-score-row-nom`, un bloc qui
   se replie naturellement. Retire le 2026-08-28.) */
/* Empêche le scroll horizontal involontaire dans le card */
.noala-score-detail-modal .noala-card--data { overflow-x: auto; max-width: 100%; }
/* Écart 1.9 — le grand chiffre de la popup Scores.
   ⚠️ TROIS RÈGLES SE DISPUTAIENT SA TAILLE : 42px de base sur `.noala-score-big`,
   64px ici, et un `style="font-size:34px"` inline dans le markup qui gagnait sur
   les deux. Le style inline est retiré ; cette règle fait foi, à 52px.
   Le poids passe de 800 à 600 et l'approche à -.035em : à 52px, un 800 pèse
   comme un titre de page alors que c'est une VALEUR qu'on lit.
   ⚠️ Aucune couleur ici : `data-level` a quitté le chiffre, la gravité est
   portée par la pastille d'interprétation posée à côté. Une seule pièce peint la
   gravité — deux la diluent. */
.noala-score-detail-modal .noala-score-big {
  font-size: 52px;
  font-weight: 600;
  letter-spacing: -0.035em;
  line-height: 0.95;
}
/* ⚠️ 320px !important LAISSAIT ~45px DE VIDE SOUS LA COURBE, mesuré à l'écran le
   2026-08-31 : le SVG est en `viewBox 720x280` avec `height:auto`, donc il rend
   environ 276px à la largeur du volet, et le plancher le dépassait. Ce plancher
   datait de l'époque où le graphe vivait derrière un bouton « Voir le graphique » ;
   il est visible d'emblée depuis le 2026-08-28.
   160px reste un PLANCHER utile : sans donnée, `lineChart` rend « Pas encore de
   mesure. » dans un bloc à 40px de padding, qui serait sinon à l'étroit.
   ⚠️ Le `!important` est retiré avec la valeur : il n'avait rien à battre — c'est
   le seul sélecteur qui vise ce conteneur. Un `!important` sans adversaire donne
   au lecteur suivant l'idée qu'il y en a un. */
.noala-score-detail-modal #score-chart, .noala-score-detail-modal [id^="score-chart-"] {
  min-height: 160px;
}

/* Écart 1.30 — le bandeau d'avertissement rentre dans la charte.
   ⚠️ `rgba(252,211,77,.18)` et `rgba(252,180,0,.45)` sont un ambre TAILWIND
   (amber-300 / amber-400). Vérifié : ces deux littéraux n'apparaissent nulle part
   ailleurs dans la feuille — ce n'était pas une famille de couleurs, c'était une
   couleur orpheline. Le produit a son propre sable, `--warn` #C49B5D, employé par
   tout le reste du vocabulaire d'avertissement.
   Un seul sélecteur, dix bandeaux sur trois fronts (index 6, admin 3, devis 1),
   aucun e2e ne le cite, aucun ne repeint la couleur en inline (vérifié).
   Le corps reste en `--ink` : 10,66:1 sur le nouveau fond, 11,16:1 sur l'ancien —
   le changement ne coûte rien en lisibilité. */
.noala-warn-banner {
  background: var(--warn-soft);
  border: 1px solid color-mix(in srgb, var(--warn) 45%, transparent);
  border-radius: var(--radius-md);
  padding: 10px 14px;
  margin-bottom: var(--s-3);
  font-size: 13px;
  color: var(--ink);
}


/* Protocole — multi-select QS (étape) */
.noala-qs-checks {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 6px;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  max-height: 200px;
  overflow-y: auto;
}
.noala-qs-check {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-1);
  padding: 3px 6px;
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.15s;
}
.noala-qs-check:hover { background: var(--accent-soft); }
.noala-qs-check input { margin: 0; cursor: pointer; }

/* ──────────────────────────────────────────────────────────── */
/* Table Activité                                                */
/* ──────────────────────────────────────────────────────────── */
.noala-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.noala-table thead th {
  text-align: left;
  padding: 12px 16px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-2);
  font-weight: 500;
}
.noala-table tbody td {
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.noala-table tbody tr:not([data-sev]):hover { background: var(--surface-2); }
.noala-table tbody tr:last-child td { border-bottom: 0; }

/* (Metrique dans le bloc `.noala-tag` plus haut. Ne restent que les onze
   variantes [data-status] ci-dessous, deja couleur-seule.) */
/* STATUTS D'ENVOI — les SEULES définitions (le doublon mort d'app.css a été retiré
   le 2026-08-28). Toute la famille était en palette TAILWIND : indigo #4f46e5 pour
   « planifié », ambre #b45309 pour « ouvert », stone #57534e pour expiré/annulé.
   L'indigo, notamment, n'appartient à aucun des trois niveaux du vocabulaire et
   n'existe nulle part ailleurs dans la charte — un audit visuel l'a releve comme
   « lavande, hors charte » sur la capture du tiroir de jalon.
   Le mapping suit la gravité, pas l'ancienneté du code :
   planifié = rien à faire encore (neutre) · envoyé = en cours (info teal) ·
   ouvert = le patient l'a ouvert sans finir (warn) · complété = bon ·
   expiré / annulé = sorti du flux (neutre estompé) · erreur = alerte. */
.noala-status-pill[data-status="planifie"] { background: var(--surface-2);        color: var(--text); }
.noala-status-pill[data-status="envoye"]   { background: var(--accent-tint);      color: var(--accent-text); }
.noala-status-pill[data-status="ouvert"]   { background: var(--warn-soft);        color: var(--warn-text); }
.noala-status-pill[data-status="complete"] { background: var(--status-good-soft); color: var(--status-good); }
.noala-status-pill[data-status="expire"]   { background: var(--surface-2);        color: var(--text-2); }
.noala-status-pill[data-status="annule"]   { background: var(--surface-2);        color: var(--text-2); text-decoration: line-through; }
.noala-status-pill[data-status="erreur"]   { background: var(--alert-soft);       color: var(--alert); }
.noala-status-pill[data-status="signe"]    { background: rgba(42, 174, 155, 0.18); color: #1e7b4f; }
.noala-status-pill[data-status="refuse"]   { background: rgba(138, 75, 62, 0.12); color: #8a4b3e; }
.noala-status-pill[data-status="revoque"]  { background: rgba(196, 74, 45, 0.12); color: #b23a2e; }
.noala-status-pill[data-status="brouillon"] { background: rgba(99, 102, 241, 0.08); color: #6366f1; }

/* ──────────────────────────────────────────────────────────── */
/* Kiosque saisie consultation                                   */
/* ──────────────────────────────────────────────────────────── */
.noala-modal-overlay > .noala-modal-card:has(.noala-bsec) { /* déjà max 880px */ }

.noala-scale-btn {
  width: 44px;
  height: 44px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--ink);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.noala-scale-btn:hover { border-color: var(--accent); color: var(--accent-text); }
.noala-scale-btn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.noala-radio-label {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  background: var(--surface);
  transition: background 0.15s, border-color 0.15s;
  font-size: 14px;
  line-height: 1.4;
}
.noala-radio-label:hover { background: var(--accent-soft); border-color: var(--accent); }
.noala-radio-label input { margin: 0; cursor: pointer; }
.noala-radio-label input:checked + span { font-weight: 500; }

@media (max-width: 700px) {
  .noala-table { font-size: 12px; }
  .noala-table thead th, .noala-table tbody td { padding: 8px 10px; }
}

/* ──────────────────────────────────────────────────────────── */
/* Toasts (NoalaUI.toast)                                          */
/* ──────────────────────────────────────────────────────────── */
.noala-toast-stack {
  position: fixed;
  bottom: 20px;
  right: 20px;
  z-index: 2000;
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none;
  max-width: calc(100vw - 40px);
}
.noala-toast {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 16px;
  border-radius: var(--radius-md);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.10), 0 1px 2px rgba(0, 0, 0, 0.05);
  font-size: 13px;
  color: var(--ink);
  min-width: 240px;
  max-width: 420px;
  cursor: pointer;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.2s ease-out, transform 0.2s ease-out;
}
.noala-toast-shown { opacity: 1; transform: translateY(0); }
.noala-toast-hiding { opacity: 0; transform: translateY(-4px); }
.noala-toast-icon {
  font-size: 16px;
  font-weight: 600;
  flex-shrink: 0;
  line-height: 1.4;
}
.noala-toast-msg { flex: 1; line-height: 1.4; word-break: break-word; }
.noala-toast-success { border-left: 3px solid #10b981; }
.noala-toast-success .noala-toast-icon { color: #10b981; }
.noala-toast-warn    { border-left: 3px solid #f59e0b; }
.noala-toast-warn    .noala-toast-icon { color: #f59e0b; }
.noala-toast-error   { border-left: 3px solid var(--alert); }
.noala-toast-error   .noala-toast-icon { color: var(--alert); }
.noala-toast-info    { border-left: 3px solid var(--accent); }
.noala-toast-info    .noala-toast-icon { color: var(--accent); }

@media (max-width: 600px) {
  .noala-toast-stack { left: 16px; right: 16px; bottom: 16px; }
  .noala-toast { min-width: 0; max-width: none; }
}


/* Audit log — pills d'action */
/* ⚠️ Le `font-family: monospace` est RETIRÉ. Il faisait rendre « LCA
   (LIGAMENTOPLASTIE) » et « 4 EN COURS » dans une police à chasse fixe, un
   idiome typographique qui n'existe nulle part ailleurs dans le produit — la
   charte est Poppins depuis la refonte 2026-07. Mesuré au navigateur avant
   correction : font-family calculée = « monospace » sur l'écran Activité.
   Les couleurs rejoignent la charte : c'était un CINQUIÈME vocabulaire de
   gravité, avec ses propres rgba et l'ambre Tailwind #b45309.
   La classe et l'attribut `data-severity` sont CONSERVÉS — six specs e2e les
   sélectionnent (admin, mediatheque, devis_refonte, envoi_documents,
   patient_parcours) ; seul le style change. */
.noala-tag[data-severity="good"]    { background: var(--status-good-soft); color: var(--status-good); }
.noala-tag[data-severity="neutral"] { background: var(--surface-2); color: var(--text); }
.noala-tag[data-severity="warn"]    { background: var(--warn-soft); color: var(--warn-text); }
.noala-tag[data-severity="alert"]   { background: var(--alert-soft); color: var(--alert); }

/* Statut parcours J±N — couleur par phase (vars --phase-* theme-overridables) */
/* `font-variant-numeric: tabular-nums` plutôt que `monospace` : ces puces
   portent un jalon (« J-7 », « M+3 »), exactement ce que rend `.noala-jn`
   (app.css:2164) — et celle-ci le fait en Poppins tabulaire. Deux traitements
   pour une même valeur, sur le même écran. Les chiffres restent alignés. */
.noala-tag[data-phase]          { font-variant-numeric: tabular-nums; }
.noala-tag[data-phase="avant"]  { color: var(--phase-avant-text); background: color-mix(in srgb, var(--phase-avant) 15%, transparent); }
.noala-tag[data-phase="jourj"]  { color: var(--phase-jourj); background: color-mix(in srgb, var(--phase-jourj) 15%, transparent); }
.noala-tag[data-phase="apres"]  { color: var(--accent-text); background: color-mix(in srgb, var(--phase-apres) 15%, transparent); }
/* Segmented control (Mes / Tout) */
.noala-segmented {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 2px;
  background: var(--surface-2);
}
.noala-segmented button {
  background: transparent;
  border: 0;
  padding: 6px 14px;
  border-radius: var(--radius-pill);
  font-size: 12px;
  color: var(--text-2);
  cursor: pointer;
  transition: all 0.15s;
  font-family: inherit;
}
.noala-segmented button:hover { color: var(--ink); }
.noala-segmented button.active {
  background: var(--surface);
  color: var(--accent-text);
  font-weight: 500;
  box-shadow: 0 1px 2px rgba(0,0,0,0.05);
}

/* ALIAS de la pastille d'icone, variante courte. Le glyphe etait NU : 18px pose
   a meme le fond, alors que la maquette n'admet aucune icone sans support
   (`.pa`, admin.html:71 ; `.hr-i`, patient.html:30). Quatre emplois dans le
   selecteur de ressources — les memes rangees que celles branchees juste au
   dessus. Aucune spec e2e ne pointe cette classe. */

/* Score gros (modal détail) */
.noala-score-big {
  font-size: 42px;
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  color: var(--ink);
}
/* Meme correction que `.noala-score-pill` (2026-08-28) : ces regles ciblaient
   good|warn|mid|bad alors que `scoreLevel` ne peut rendre que
   good|neutral|warn|alert. `alert` restait donc en --ink comme un score sain, et
   deux regles attendaient une valeur que rien n'emet.
   Les trois couleurs Tailwind en dur (#10b981, #f59e0b, #f97316) rejoignent la
   charte au passage — meme menage que le lot B.3 sur patient.css.
   `neutral` n'a volontairement PAS de regle : le defaut --ink lui convient, et
   c'est aussi le rendu d'un score SANS bareme defini, le cas le plus frequent. */
.noala-score-big[data-level="good"]  { color: var(--status-good); }
.noala-score-big[data-level="warn"]  { color: var(--warn-text); }
.noala-score-big[data-level="alert"] { color: var(--alert); }

/* ──────────────────────────────────────────────────────────── */
/* Responsive                                                    */
/* ──────────────────────────────────────────────────────────── */
@media (max-width: 1100px) {
  /* Tablette : sidebar collapse à 64 px, icônes seules visibles */
  .noala-app { grid-template-columns: 64px 1fr;
    background: linear-gradient(to right, var(--sidebar-bg) 0 64px, transparent 64px); }
  .noala-logo-svg { margin-right: 0; vertical-align: middle; }
  .noala-content { padding: var(--s-5); }

}
@media (max-width: 700px) {
  .noala-content { padding: var(--s-4); }
  .noala-greeting { font-size: 22px; }


  /* Tabs — le scroll horizontal a été REMONTÉ dans la règle de base (cf
     `.noala-tabs`, Annexe H). Il vivait ici, sous `max-width:700px`, alors que
     le débordement, lui, ne connaît pas ce seuil : une barre de 8 onglets
     déborde jusqu'à 846 px. Le duplicat local ne faisait plus que masquer le
     trou de la bande tablette — et son `width:auto` étirait la pilule sur toute
     la colonne, ce que la règle de base évite en gardant `fit-content`. */

  /* Tables larges → le conteneur DIRECT scrolle horizontalement (sinon le
     min-width 600px déborde du viewport et est coupé par overflow-x:hidden). */
  .noala-table { min-width: 600px; }
  *:has(> .noala-table) { overflow-x: auto; -webkit-overflow-scrolling: touch; }

  /* Patient detail header */
  .noala-patient-title { font-size: 22px; }

  /* Builder & wizard — espacement réduit */
  .noala-modal-overlay { padding: var(--s-2); align-items: flex-start; }
  .noala-modal-card { padding: var(--s-3); border-radius: var(--radius-md); }
  .noala-modal-title { font-size: 18px; }

  /* Stepper plus compact */
  .noala-stepper { gap: 4px; margin-bottom: var(--s-3); }
  .noala-stepper-bar { height: 3px; }


  /* Form-row 1 col */
  .noala-form-row { grid-template-columns: 1fr; gap: 8px; }

  /* (`.noala-status-pill` etait REPRISE ici a 10px / 2px 6px sous 700px —
     retiree le 2026-08-28. Elle rejouait l'ancienne metrique en mobile et
     aurait fait mentir le lot 1e sur exactement le viewport ou l'ecart se
     voit le plus. La pastille a UNE metrique, a toutes les largeurs.) */

  /* Mobile ≤ 700 px : sidebar masquée par défaut, drawer overlay au clic du
     burger. La grille devient 1 colonne (le main prend toute la largeur). */
  .noala-app { grid-template-columns: 1fr; background: none; }
}

/* Très petits écrans (≤ 380 px) */
@media (max-width: 380px) {
  .noala-content { padding: var(--s-3); }
  .noala-greeting { font-size: 19px; }
  .noala-page-title { font-size: 22px; }

  .noala-modal-overlay { padding: 0; }
  .noala-modal-card { border-radius: 0; min-height: 100vh; }
}

/* Tablettes (768-1100 px) — sidebar collapsée + 2 col KPI */
@media (max-width: 1100px) and (min-width: 701px) {
  .noala-content { max-width: 100%; padding: var(--s-5); }
}

/* Anti-débordement horizontal */
html, body { overflow-x: hidden; }
.noala-content { min-width: 0; max-width: 100%; }
.noala-app { overflow-x: hidden; }

/* Backdrop drawer mobile */
.noala-sidebar-backdrop {
  display: none;
  position: fixed; inset: 0;
  background: rgba(20, 18, 14, 0.42);
  z-index: 150;
}
@media (max-width: 700px) {
  .noala-sidebar-backdrop { display: block; }
}


/* ────────────────────────────────────────────────────────────
   Command palette (Ctrl/Cmd + K)
   ──────────────────────────────────────────────────────────── */
.noala-cmdk-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 80px 16px 16px;
  animation: noala-cmdk-fade 0.18s ease-out;
}
@keyframes noala-cmdk-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.noala-cmdk-card {
  background: var(--surface);
  border-radius: 16px;
  width: 100%;
  max-width: 580px;
  max-height: 70vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: 0 24px 64px rgba(0,0,0,0.30);
  border: 1px solid var(--border-2);
  animation: noala-cmdk-slide 0.22s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes noala-cmdk-slide {
  from { transform: translateY(-12px); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}
.noala-cmdk-search {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border-2);
}
.noala-cmdk-input {
  flex: 1;
  background: transparent;
  border: 0;
  outline: 0;
  font-family: var(--font-sans);
  font-size: 15px;
  color: var(--ink);
}
.noala-cmdk-input::placeholder { color: var(--text-3); }
.noala-cmdk-results {
  flex: 1;
  overflow-y: auto;
  padding: 6px;
}
.noala-cmdk-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.08s;
}
.noala-cmdk-item.active { background: var(--accent-soft); }
.noala-cmdk-icon { font-size: 16px; flex-shrink: 0; width: 20px; text-align: center; }
.noala-cmdk-title { font-size: 13px; color: var(--ink); font-weight: 500; }
.noala-cmdk-subtitle { font-size: 11px; color: var(--text-2); margin-top: 1px; }
.noala-cmdk-empty {
  padding: 24px 16px;
  text-align: center;
  font-size: 13px;
  color: var(--text-2);
}
.noala-cmdk-footer {
  display: flex;
  gap: 14px;
  padding: 8px 16px;
  border-top: 1px solid var(--border-2);
  font-size: 11px;
  color: var(--text-2);
}
.noala-cmdk-kbd, .noala-cmdk-kbd-sm {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 6px;
  font-family: var(--font-mono, monospace);
  font-size: 10px;
  color: var(--text-2);
}
.noala-cmdk-kbd-sm { padding: 0 4px; font-size: 10px; }
@media (max-width: 600px) {
  .noala-cmdk-overlay { padding: 12px; }
  .noala-cmdk-card { max-height: 90vh; }
  .noala-cmdk-footer { display: none; }
}

/* ────────────────────────────────────────────────────────────
   Barre de recherche patient (top dashboard)
   ──────────────────────────────────────────────────────────── */
.noala-search-wrap {
  position: relative;
  margin-bottom: var(--s-5);
  max-width: 100%;
  width: 100%;
}
@media (min-width: 1200px) {
  .noala-search-wrap { max-width: 960px; }
}


/* ────────────────────────────────────────────────────────────
   Bouton icône (header dashboard, etc.) — icône seule en cercle
   ──────────────────────────────────────────────────────────── */
.noala-icon-btn {
  width: 34px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-2);
  cursor: pointer;
  transition: border-color .15s, color .15s, background .15s;
  padding: 0;
}
.noala-icon-btn svg {
  width: 16px;
  height: 16px;
  display: block;
  stroke: currentColor;
}
.noala-icon-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-soft, rgba(42,174,155,.06));
}


/* Capsule de recherche (`.srch`, maquettes/praticien.html:17) : rayon plein,
   34px de haut, 12,5px, SANS ombre. Le produit posait un rectangle arrondi de
   12px, ombré, dont l'input à `padding:14px 0; font-size:15px` portait la
   hauteur totale à ~48px — 41 % de plus que la maquette. L'ombre, surtout, la
   faisait flotter au-dessus d'une barre qui, elle, est un plan. */
.noala-search-input-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 34px;
  padding: 0 13px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  /* La maquette pose la taille et la couleur sur la CAPSULE (`.srch`), pas sur son
     champ : l'icone, le placeholder et le texte saisi partagent ainsi une seule
     source. Le champ ne surcharge que `color`, parce qu'un texte saisi doit etre
     plus fonce que son invite. */
  font-size: 12.5px;
  color: var(--text-3);
  transition: border-color 0.15s, box-shadow 0.15s;
  box-shadow: none;
}
/* Le focus garde son halo : c'est une affordance d'accessibilité, pas un relief. */
.noala-search-input-wrap:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(42, 174, 155, 0.15);
}
.noala-search-icon { font-size: 15px; color: var(--text-3); flex-shrink: 0; }
.noala-search-input {
  flex: 1;
  border: 0;
  outline: 0;
  background: transparent;
  padding: 0;
  font-family: var(--font-sans);
  font-size: 12.5px;
  color: var(--ink);
}
.noala-search-input::placeholder { color: var(--text-3); }
.noala-search-input::-webkit-search-cancel-button { display: none; }

.noala-search-clear {
  background: transparent;
  border: 0;
  color: var(--text-3);
  cursor: pointer;
  padding: 4px 8px;
  font-size: 12px;
  border-radius: var(--radius-pill);
}
.noala-search-clear:hover { background: var(--surface-2); color: var(--ink); }

/* Dropdown résultats */
.noala-search-results {
  position: absolute;
  top: calc(100% + 6px);
  left: 0; right: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 12px 32px rgba(0,0,0,.12);
  z-index: 20;
  overflow: hidden;
  animation: noala-search-pop 0.18s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes noala-search-pop {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.noala-search-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  cursor: pointer;
  border-bottom: 1px solid var(--border-2);
  transition: background 0.08s;
}
.noala-search-item:last-child { border-bottom: 0; }
.noala-search-item.active { background: var(--accent-soft); }
.noala-search-avatar {
  width: 32px; height: 32px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent) 0%, color-mix(in srgb, var(--accent) 70%, var(--ink)) 100%);
  color: white;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.noala-search-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
}
.noala-search-meta {
  font-size: 11px;
  color: var(--text-2);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.noala-search-empty {
  margin-top: 6px;
  padding: 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  text-align: center;
  font-size: 13px;
  color: var(--text-2);
}
@media (max-width: 600px) {
  .noala-search-input { font-size: 16px; padding: 12px 0; }

}


.noala-search-section-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-2);
  font-weight: 600;
  padding: 8px 14px 4px;
  background: var(--surface);
}

/* ════════════════════════════════════════════════════════════════
   Composants utilitaires — extraits des patterns inline dupliqués
   (audit graphique : ~700 occurrences réduites à ~50)
   ════════════════════════════════════════════════════════════════ */

/* Header de modale : titre + actions en haut, gap entre, wrap responsive.
   Remplace le style="display:flex;justify-content:space-between;..." dupliqué
   17 fois dans les modales détail (admin praticien, patient, pack, etc.). */
.noala-modal-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--s-3);
  margin-bottom: var(--s-4);
  flex-wrap: wrap;
}


/* Mini bouton d'action en table (cellule actions) — taille xs.
   Remplace style="font-size:11px;padding:3px 8px" répété 30+ fois. */
.noala-link-action--xs {
  font-size: 11px;
  padding: 3px 8px;
}

/* ──────────────────────────────────────────────────────────── */
/* Responsive — tailles polices adaptées tablette / mobile.
   Le dashboard praticien est pensé desktop ; sur tablette on
   reste utilisable mais on réduit display & H1 pour ne pas
   sortir du viewport. Sur mobile on réduit d'un cran de plus. */
/* ──────────────────────────────────────────────────────────── */

/* Tablette (1023px et moins) */
@media (max-width: 1023px) {
  :root {
    --fs-display:    48px;
    --fs-display-sm: 36px;
    --fs-h1:         24px;
    --fs-h2:         17px;
    --fs-h3:         14px;
  }
}

/* Mobile (767px et moins) */
@media (max-width: 767px) {
  :root {
    --fs-display:    32px;
    --fs-display-sm: 26px;
    --fs-h1:         20px;
    --fs-h2:         16px;
    --fs-h3:         14px;
    --fs-body:       14px; /* ne pas descendre : lisibilité */
  }

}

/* ──────────────────────────────────────────────────────────── */
/* Sprint 7 — Empty state onboarding (Annexe N)                 */
/* Affiché tant que praticien.onboarding_completed = false      */
/* (1er patient pas encore créé). Auto-set par migration 077    */
/* et patients.py:create_patient.                               */
/* ──────────────────────────────────────────────────────────── */
.noala-onboarding {
  padding: var(--s-12) 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-8);
}
.noala-onboarding-head { max-width: 540px; }
.noala-onboarding-lead {
  font-size: 15px;
  line-height: var(--lh-loose);
  color: var(--text);
  margin: 10px 0 0;
}
.noala-onboarding-steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-4);
}
.noala-onboarding-step {
  padding: var(--s-6);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}
.noala-onboarding-step-head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.noala-onboarding-step-num {
  width: 32px; height: 32px;
  border-radius: 10px;
  background: var(--accent-soft);
  color: var(--accent-text);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-weight: 700; font-size: 16px;
}
.noala-onboarding-step-icon { font-size: 32px; }
.noala-onboarding-step h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 18px;
  color: var(--ink);
  margin: 0;
  letter-spacing: -0.015em;
  line-height: 1.25;
}
.noala-onboarding-step p {
  font-size: 13px;
  color: var(--text-2);
  margin: 0;
  line-height: var(--lh-normal);
  flex: 1;
}

@media (max-width: 900px) {
  .noala-onboarding-steps { grid-template-columns: 1fr; }
}

/* ───── 3.C.1 — Barre d'actions (agir) ───── */
.noala-actionbar-zone { margin: 16px 0 4px; padding-top: 14px; border-top: 1px solid var(--border-2); }

.noala-actionbar { display: flex; flex-wrap: wrap; gap: 8px; }
.noala-actionbar button { display: inline-flex; align-items: center; gap: 7px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-btn); padding: 8px 15px; font-size: 13px;
  color: var(--ink); cursor: pointer; font-family: inherit; transition: border-color .15s, color .15s; }
.noala-actionbar button:hover { border-color: var(--accent); color: var(--accent-text); }
.noala-actionbar button .ic { font-size: 15px; }
.noala-actionbar button .noala-ic { width: 16px; height: 16px; }
.noala-actionbar button.is-transitional { border-style: dashed; }
/* Ecart 3.4 — les trois destinations qui restent sont PLEINES. Elles cessent
   d'etre des etiquettes parmi neuf et deviennent la seule chose coloree de la
   zone. ⚠️ Trois boutons pleins identiques reproduisent en miniature ce qu'on
   reprochait aux neuf : rien ne dit lequel sert le plus. Trois n'est pas neuf, et
   ils sont desormais separes des cinq tiroirs — a revoir seulement si l'usage
   montre que « Parcours » ecrase les deux autres. */
/* ⚠️ TROIS BOUTONS PLEINS NE DISENT PAS LEQUEL EST ACTIF, et depuis le
   2026-09-01 ces trois-là sont des VUES dont une seule l'est. Peints tous les
   trois en accent plein, ils se lisaient comme trois actions équivalentes ; le
   praticien ne savait pas ce qu'il regardait. L'inactive recule, l'active reste
   pleine — et `aria-current`, que le markup posait déjà sans que rien ne le
   montre, devient enfin visible. */
.noala-actionbar--plein button {
  background: var(--surface);
  border-color: var(--border);
  color: var(--text);
  font-weight: 600;
}
/* ⚠️ LES TROIS BOUTONS SE PARTAGENT LA LIGNE (revue du 2026-09-01). Mesure avant :
   114, 99 et 131 px dans une ligne de 1164 — 31 % de la largeur, alignes a gauche,
   de tailles inegales parce que `flex: 0 1 auto` les dimensionne par leur texte.
   Trois destinations equivalentes doivent peser pareil : `flex: 1 1 0` ignore la
   longueur du libelle et rend trois tiers exacts.
   ⚠️ `min-width: 0` est necessaire : sans lui, la base `auto` du contenu empeche
   le retrait et les tiers redeviennent inegaux sur ecran etroit. */
.noala-actionbar--plein { width: 100%; }

/* ═══ Un tiroir a une largeur FIXE (revue du 2026-09-01) ═══════════════════
   Mesure avant, sur les cinq portes du rail : Consentements 560, Devis 560,
   RDV 720, Preparation 960, Avis 648. Le panneau changeait de largeur a chaque
   ouverture — l'oeil doit reapprendre la surface a chaque porte.
   ⚠️ 800 px est un ARBITRAGE, pas une moyenne : c'est la largeur qui tient le
   tableau de Preparation (le contenu le plus large) sans dilater la liste de
   RDV. Preparation perd 160 px et defile a l'interieur, ce que `overflow` fait
   deja. Le prix est assume et mesure.
   ⚠️ `max-width` ET NON `width` seul : sous 860 px de fenetre, une largeur fixe
   deborderait. */
.noala-modal-overlay[data-kind="drawer"] > .noala-modal-card {
  width: 800px;
  max-width: 92vw;
}
.noala-actionbar--plein button { flex: 1 1 0; min-width: 0; justify-content: center; }
.noala-actionbar--plein button[aria-current="true"] {
  background: var(--accent-text);
  border-color: var(--accent-text);
  color: #FFFFFF;
}
.noala-actionbar--plein button:hover {
  background: var(--cta-bg-hover, var(--ink));
  border-color: var(--cta-bg-hover, var(--ink));
  color: #FFFFFF;
}

/* 3.C.1 — nom patient cliquable → onglet Identité */
.noala-patient-name-btn { background: transparent; border: 0; padding: 0; font: inherit; color: inherit; cursor: pointer; display: inline-flex; align-items: baseline; gap: 8px; border-radius: 6px; }
.noala-patient-name-btn:hover { color: var(--accent-text); }


/* Ecart 3.4 — l'intervention, le cote et la date operatoire sont CLIQUABLES dans
   la meta. Aucun mot ne le dit : l'affordance est le survol, pas une etiquette.
   C'est le meme parti que le nom juste au-dessus, et c'est ce qui permet a la
   ligne de se lire comme une phrase plutot que comme un formulaire. */
.noala-patient-episode {
  background: none; border: 0; padding: 0;
  font: inherit; color: inherit;
  cursor: pointer;
  text-align: left;
}
.noala-patient-episode:hover { color: var(--accent-text); text-decoration: underline; }
.noala-patient-episode:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px;
}

/* Ecart 3.4 — LE RAIL DES CINQ TIROIRS, a droite de l'identite.
   Style de la maquette : fond doux, pastilles arrondies.
   ⚠️ LA PASTILLE BLANCHE DIT UN ETAT REEL, elle n'est pas decorative. Elle suit
   `patientPopup` : le tiroir ouvert est celui qui s'eclaire. En figer une au
   premier onglet, comme le faisait la maquette d'arbitrage, aurait affiche en
   permanence un etat faux — le defaut exact que ce lot passe son temps a retirer
   ailleurs (« Synchronise · a l'instant », la date figee du fil d'Ariane).
   ⚠️ Ce style PROMET du contenu en page alors qu'il ouvre des tiroirs. Signale
   deux fois, retenu en connaissance de cause par le proprietaire produit. La
   variante segmentee — bordure partagee, pas de pastille active — est a deux
   declarations pres si l'usage montre que des praticiens attendent la page. */
.noala-patient-rail,
.noala-nature-pills {
  display: inline-flex; gap: 2px; flex: none;
  background: var(--surface-2);
  border-radius: var(--radius-pill);
  padding: 3px;
}
.noala-patient-rail button,
.noala-nature-pills button {
  border: 0; background: none;
  padding: 6px 13px;
  border-radius: var(--radius-pill);
  font-family: var(--font-sans);
  font-size: 12.5px;
  color: var(--text-2);
  cursor: pointer;
  white-space: nowrap;
  transition: background .12s, color .12s;
}
.noala-patient-rail button:hover,
.noala-nature-pills button:hover { color: var(--ink); }
.noala-patient-rail button[aria-current="true"],
.noala-nature-pills button.active {
  background: var(--surface);
  color: var(--ink);
  font-weight: 600;
  box-shadow: var(--shadow-sm);
}
/* Sous 900px le rail passe a la ligne : la carte reste lisible, elle grandit. */
@media (max-width: 900px) {
  .noala-patient-rail { margin-top: 10px; }
}
/* ⚠️ CORRECTIF D4 (mesure le 2026-08-30) : le rail heritait de `flex: none` sans
   `flex-wrap`, donc a 375 px il mesurait 400 px de large et son dernier onglet
   — « Avis » — se terminait a x=430. Et la page NE DEFILE PAS horizontalement
   (`scrollWidth == clientWidth`) : le debordement etait donc CLIPPE, pas
   atteignable en glissant. Une destination entiere disparaissait sur mobile,
   sans le moindre signe. Les cinq tiroirs passent a la ligne, comme les
   pastilles de nature — un retour a la ligne se voit, un defilement cache non. */
/* ⚠️ `flex-wrap` NE SUFFIT PAS SEUL, et c'est le piege : en `inline-flex` avec
   `flex: 0 0 auto`, le rail se dimensionne sur son contenu (`max-content`) et
   n'a donc JAMAIS a replier — il deborde, point. Mesure : `flexWrap` valait bien
   `wrap` et la largeur restait a 400 px dans une fenetre de 375. Il faut LUI
   DONNER une borne. `max-width: 100%` la prend sur le parent, `min-width: 0`
   leve le plancher implicite d'un element flex. */
.noala-patient-rail { flex-wrap: wrap; max-width: 100%; min-width: 0; }

/* Écart 2.22 — le compte porté par la pastille. Il se lit comme un exposant :
   plus petit et plus pâle que le libellé, il informe sans le concurrencer. La
   pastille courante le repasse à l'encre pleine, sinon le chiffre du filtre
   ACTIF serait le moins lisible de la rangée. Les pastilles passent à la ligne :
   la barre de filtres en porte déjà quatre autres. */
.noala-nature-pills { flex-wrap: wrap; }
.noala-nature-pills-n {
  margin-left: 5px;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--text-3);
}
.noala-nature-pills button.active .noala-nature-pills-n { color: var(--ink); }

/* Lot A — en-tête épisode prominent en tête de frise (carte unique) */
/* Ecart 3.4 — l'en-tete tient sur UNE ligne : le nom de la section, son compteur
   aligne sur la meme ligne de base (c'est le `.fr-h` de la maquette), puis les
   deux gestes qui MODIFIENT le parcours. Il empilait cinq choses avant ce lot. */
.noala-frise-ephead {
  display: flex; align-items: center; gap: 12px;
  flex-wrap: wrap;
  margin-bottom: var(--s-3);
}
/* Le compteur, remonte dans l'en-tete. Il garde ses deux noms d'origine (cf le
   commentaire du markup) ; cette classe n'ajoute que ce que la NOUVELLE PLACE
   impose — l'alignement sur la ligne de base du titre, et la marge basse a zero,
   que `.noala-frise-progress` posait quand il vivait sur son propre etage. */
.noala-frise-ephead-count { flex: 1; min-width: 0; margin-bottom: 0; }

.noala-frise-ephead-count .noala-frise-progress-txt { font-size: 12px; }
/* Le « + » qui remplace l'ancien bouton « Envoi ». Rond et plein : c'est le seul
   geste de CREATION de cette carte, et il doit se distinguer de l'engrenage, qui
   modifie l'existant. */
/* ⚠️ `margin-left: auto` — LES DEUX GESTES SONT TOUJOURS A DROITE (2026-09-01).
   Sans lui, ils suivent le contenu : sur une fiche SANS compteur (`x-show` sur
   `journeyQsLabel()`, donc masque tant qu'aucun questionnaire n'existe), le
   bouton remontait a gauche — et le menu ancre `right: 0` sortait alors de
   l'ecran PAR LA GAUCHE, de 53 px a 1024. Defaut trouve par la garde du lot, sur
   une largeur que je n'avais pas mesuree.
   Ancrer le menu ne suffisait donc pas : il fallait que le bouton ait une place
   fixe. Les deux corrections vont ensemble. */
.noala-frise-ephead-add {
  flex: none;
  margin-left: auto;
  width: 30px; height: 30px;
  display: inline-grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--accent-text);
  background: var(--accent-text);
  color: #FFFFFF;
  cursor: pointer;
  font-family: inherit;
}
.noala-frise-ephead-add:hover { background: var(--cta-bg-hover, var(--ink)); border-color: var(--cta-bg-hover, var(--ink)); }
.noala-frise-ephead-add .noala-ic { width: 16px; height: 16px; }
.noala-frise-ephead-add:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Ecart 3.5 — l'episode cesse de rivaliser avec le nom du patient. Les quatre
   tailles descendent d'un cran : 26 -> 17, 20 -> 15, 15 -> 13, 19 -> 14. Le bloc
   reste (il porte le menu ⚙ et le selecteur multi-episodes, et `lotA_fiche.spec.js`
   garde son unicite), mais il redevient un CONTEXTE et non un titre concurrent. */

.noala-frise-epnav { display:flex; align-items:center; gap:8px; color:var(--text-2); font-size:14px; flex-shrink:0; }
.noala-frise-epnav button { width:30px; height:30px; border-radius:8px; border:1px solid var(--border); background:var(--surface); cursor:pointer; font-size:15px; color:var(--text-2); }
.noala-frise-epnav button:hover { border-color: var(--accent); color: var(--accent); }


/* ══════════════════════════════════════════════════════════════════
   Barre de filtres — primitive partagee (lot 5, 2026-09-04)
   ══════════════════════════════════════════════════════════════════
   Trois ecrans posaient la meme grille en style inline, et leurs valeurs
   avaient deja diverge sans que personne ne l ait decide : minmax(200px)
   et marge --s-5 cote Patients, minmax(180px) et --s-3 cote Activite. La
   regle tranche a 200px et --s-4, et le dit ici pour que l ecart ne
   revienne pas par copie.

   ⚠️ CONTRAT ECRIT POUR TROIS CONSOMMATEURS, pas pour le seul qui l inaugure.
   Patients (ce lot) n a que des champs et un bouton de remise a zero ;
   Activite (lot 9) y viendra avec une recherche et quatre filtres ; la
   mediatheque (lot 11b) avec une recherche, trois selects et une case a
   cocher. Les trois formes sont prevues des maintenant : sans cela, la
   primitive serait etiree apres coup par chaque arrivant, ce qui est
   exactement la maniere dont les quatre valeurs ci-dessus ont diverge.

   ⚠️ ELLE NE REUTILISE PAS LES CLASSES DES SELECTEURS DE CONTENU, dont la
   barre de recherche est calibree pour une modale plein ecran et dont les
   filtres de type portent un etat presse. Les partager melangerait deux
   composants que rien n oblige a evoluer ensemble. */

/* ── Rangee du flux Activite (lot 9) ─────────────────────────────
   Famille neuve `.noala-flux-*`, partagee avec le panneau « Derniers
   bilans recus » du lot 17. Une rangee = un evenement : patient et titre
   sur la premiere ligne, sous-titre et statut sur la seconde, le moment a
   droite. La puce a gauche ne dit qu une chose, « non lu » : aucune
   gravite, aucune couleur de score n entre ici (hors DM). */
.noala-flux-liste { display: flex; flex-direction: column; }
.noala-flux-row {
  display: grid; grid-template-columns: 12px 1fr auto; gap: 0 12px;
  align-items: center; width: 100%; text-align: left;
  padding: 10px 16px; border: 0; border-bottom: 1px solid var(--border);
  background: none; font: inherit; color: inherit; cursor: pointer;
}
.noala-flux-row:hover { background: var(--surface-2); }
.noala-flux-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.noala-flux-corps { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.noala-flux-ligne1, .noala-flux-ligne2 { display: flex; gap: 8px; align-items: baseline; min-width: 0; }
.noala-flux-patient { font-weight: 600; color: var(--ink); white-space: nowrap; }
.noala-flux-sous { font-size: 12px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.noala-flux-quand { font-size: 12px; color: var(--text-3); white-space: nowrap; font-variant-numeric: tabular-nums; }
@media (max-width: 767px) {
  .noala-flux-row { grid-template-columns: 12px 1fr; }
  .noala-flux-quand { grid-column: 2; font-size: 11px; }
}

/* ── Source de la teinte d un score (lot 10 bis) ───────────────────────
   « bareme publie » ou « objectif du praticien », a cote de la pastille.
   Ce n est pas une decoration : sans ce mot, une cible indicative peinte
   comme une bande publiee se lirait comme un bareme (regle 2.11). */
.noala-score-source { font-size: 11px; color: var(--text-3); margin-left: 6px; white-space: nowrap; }
.noala-score-source[data-source="objectif"]::before { content: "cible · "; }

/* ── Lot 17 : les deux panneaux du tableau de bord, et la tuile de score ──
   La grille suit la maquette (`.g2`, 1.25fr / 1fr, gap 14) et se replie en une
   colonne sous 900 px. La tuile reprend les QUATRE couples de `.noala-score-pill`
   (meme source, `scoreLevel`, meme lecture hors DM), jamais la recette `--sev-tile`
   des pastilles d'icone : une tuile de score n'est pas une gravite de rangee.
   Neutre par defaut : sans bande publiee, un score se lit sans teinte. */
.noala-dash-panels {
  display: grid; grid-template-columns: 1.25fr 1fr; gap: 14px;
  align-items: start; margin-bottom: var(--s-3);
}
@media (max-width: 900px) { .noala-dash-panels { grid-template-columns: 1fr; } }
.noala-bilan-row { grid-template-columns: 44px 1fr auto; }
.noala-bilan-row:last-child { border-bottom: 0; }
/* Dans la rangee bilan la premiere ligne ne porte que le nom : sans ellipse un
   nom long deborderait sur la colonne « quand » (dans Activite, c est le titre
   qui rogne, le nom est court par construction). */
.noala-bilan-row .noala-flux-patient { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.noala-score-tile {
  width: 44px; height: 44px; border-radius: 12px; flex: none;
  display: grid; place-items: center;
  font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums;
  background: var(--surface-2); color: var(--text);
}
.noala-score-tile[data-level="good"]    { background: var(--status-good-soft); color: var(--status-good-text); }
.noala-score-tile[data-level="warn"]    { background: var(--status-warn-soft); color: var(--warn-text); }
.noala-score-tile[data-level="alert"]   { background: var(--alert-soft);       color: var(--alert-text); }
.noala-score-tile[data-level="neutral"] { background: var(--surface-2);        color: var(--text); }
@media (max-width: 767px) { .noala-bilan-row { grid-template-columns: 44px 1fr; } }

/* ── Lot 11a : catalogues depliables (Questionnaires, Protocoles, Mediatheque) ──
   `.noala-acc` reste intact (partage avec le portail et la fiche patient) :
   tout vit sous le modificateur `.noala-acc--cat`. Ecrit en FIN de feuille :
   `.noala-table` est declaree deux fois et la seconde gagne. L'en-tete
   `.noala-qs-sec-head` devient le summary : sa marge (28px 0 14px) et son
   filet `.noala-qs-sec-rule` n'ont plus de sens a cote du chevron `::after`.
   La table garde `.noala-card--data` pour son `overflow-x:auto` (375 px), le
   cadre de la carte est neutralise : pas de cadre dans un cadre. */
.noala-acc--cat > summary.noala-qs-sec-head { margin: 0; padding: 12px 16px; gap: 10px; }
.noala-acc--cat > summary.noala-qs-sec-head .noala-qs-sec-rule { display: none; }
.noala-acc--cat > summary.noala-qs-sec-head .noala-qs-sec-title { font-size: 16px; }
/* L'anneau rentre (`.noala-acc` rogne) et suit l'arc du parent : 17 px de
   rayon moins les 2 px de retrait ; angles du bas droits quand le pli est ouvert. */
.noala-acc--cat > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 15px; }
.noala-acc--cat[open] > summary:focus-visible { border-radius: 15px 15px 0 0; }
/* Au survol le summary prend `--surface-2`, la teinte de la pastille de compte :
   la pastille repasse sur `--surface` pour garder sa forme. */
.noala-acc--cat > summary:hover .noala-qs-sec-count { background: var(--surface); }
.noala-acc--cat > .noala-acc-body { padding: 0; border-top: 1px solid var(--border-2, var(--border)); }
.noala-acc--cat .noala-card--data { border: 0; border-radius: 0; box-shadow: none; margin: 0; }
/* Niveau 2 (une sous-specialite dans sa specialite) : un pli plus discret,
   sans ombre ni rayon, separe du suivant par un filet. */
.noala-acc--cat .noala-acc--cat-2 { border: 0; border-bottom: 1px solid var(--border-2, var(--border)); border-radius: 0; box-shadow: none; margin: 0; }
.noala-acc--cat .noala-acc--cat-2:last-child { border-bottom: 0; }
.noala-acc--cat .noala-acc--cat-2 > summary.noala-qs-sec-head { padding: 10px 16px 10px 28px; }
.noala-acc--cat .noala-acc--cat-2 > summary.noala-qs-sec-head .noala-qs-sec-title { font-family: inherit; font-size: 14.5px; letter-spacing: 0; }
.noala-acc--cat .noala-acc--cat-2 > .noala-acc-body { border-top: 0; }
.noala-acc--cat .noala-acc--cat-2 > summary:focus-visible { border-radius: 0; }
/* Un groupe sans sous-niveau (Général, parent inconnu) : le pli interieur est
   un simple conteneur toujours ouvert, son summary est cache. */
.noala-acc--cat .noala-acc--cat-seul > summary { display: none; }
/* La description d'une ressource, sur UNE ligne : `line-clamp` rogne sans
   imposer sa largeur a la colonne, la ou `white-space:nowrap` elargirait la
   table a la longueur du texte. */
.noala-cat-desc {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; overflow: hidden;
  font-weight: 400; font-size: 11.5px; color: var(--text-3); margin-top: 2px;
}

/* ── Lot 12 : la barre d onglets en pilules, et la rangee cle-valeur ──────
   Ecrit en FIN de feuille, sous le bloc du lot 11b : `.noala-tabs` est declaree
   plus haut (2021) et `.noala-table` l est DEUX fois, donc tout ce qui doit
   gagner se pose ici.

   ⚠️ `.noala-tabs--pills` est un MODIFICATEUR, jamais une famille neuve :
   `responsive.spec.js` fait `btn.closest('.noala-tabs')` puis dereference
   `bar.parentElement`. Changer la classe du conteneur ferait lever son
   `page.evaluate` sans meme rendre un message utile. Le defilement doit rester
   SUR cet element : un enveloppeur en `overflow-x:auto` serait defilable par
   script mais pas par le praticien, et le test le refuse a raison.

   La forme suit la maquette (chaque onglet est une carte bordee et ombree, plus
   une icone), la couleur de l ETAT ACTIF suit le produit (`--accent`) : la
   maquette le peint en `--ink`, ce qui creerait deux dessins d actif dans la
   meme application, la barre d Activite et celle de la popup Identite restant
   en accent. Ecart assume, ecrit dans la PR. */
.noala-tabs--pills {
  background: transparent;
  padding: 0;
  gap: 6px;
  box-shadow: none;
  border-radius: 0;
}
.noala-tabs--pills > .noala-tab {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 13px;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  color: var(--text);
}
.noala-tabs--pills > .noala-tab .noala-ic { width: 15px; height: 15px; flex: none; }
.noala-tabs--pills > .noala-tab:hover { border-color: var(--accent); color: var(--ink); }
.noala-tabs--pills > .noala-tab.active {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
/* ⚠️ L ANNEAU DE FOCUS EST INTERIEUR, et ce n est pas un gout : `.noala-tabs`
   porte `overflow-x: auto`, ce qui force `overflow-y` a `auto` (spec CSS
   overflow) et fait de la barre une boite de defilement qui rogne a sa boite de
   padding. La regle de base garde un offset de 1 px parce que les 4 px de
   gouttiere de `.noala-tabs` lui laissent la place ; le modificateur pilules
   RETIRE cette gouttiere, donc tout offset positif peint hors du rognage et
   l anneau perd ses traits haut et bas a toutes les largeurs.
   Le commentaire precedent affirmait le contraire (« la barre en pilules n a
   plus de gouttiere a rogner, donc l offset par defaut redevient sur ») : c est
   la gouttiere qui donnait la place, la retirer ne rend aucun offset positif
   utilisable. Meme motif que `.noala-acc--cat > summary:focus-visible` et
   `.noala-flux-row:focus-visible`, deja interieurs pour la meme raison. */
.noala-tabs--pills > .noala-tab:focus-visible { outline-offset: -2px; }

/* ── La rangee cle-valeur du lot 12 ──────────────────────────────────────
   ⚠️ Une famille NEUVE plutot que `.noala-defs`, qui est une grille
   `200px 1fr` a cle en capitales, portee par trois autres surfaces (dont
   `admin.html`) : la reprendre imposerait de la modifier pour elles.

   ⚠️ LA VALEUR EST UN CHAMP, PAS DU TEXTE (arbitrage du 2026-09-06) : la
   maquette ne montre que de la lecture, mais l enregistrement automatique doit
   survivre, et un composant « clic pour editer » perdrait la saisie sur un
   RPPS invalide, que l enregistrement refuse deja en silence. Le champ garde
   donc sa nature, habille en rangee : fond transparent, bordure absente,
   alignement a droite, et il ne se distingue au survol que par sa bordure
   basse. */
.noala-kv-liste { display: flex; flex-direction: column; gap: 4px; }
.noala-kv {
  /* ⚠️ `flex-wrap` : une rangee a trois elements (libelle, champ, pastille) dont
     deux sont `flex: none` ne peut reduire que le champ. Sur une colonne etroite,
     « E-mail de connexion » ecrasait sa valeur a quelques pixels ; la pastille
     passe desormais a la ligne. */
  display: flex; align-items: center; flex-wrap: wrap; gap: 11px;
  padding: 8px 11px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 15px;
  min-height: 42px;
}
.noala-kv-l { font-size: 13px; font-weight: 500; color: var(--text); flex: none; }
.noala-kv-v { margin-left: auto; font-size: 14.5px; font-weight: 600; color: var(--ink); text-align: right; min-width: 0; }
/* Le champ dans la cellule de droite : il EST la valeur. */
.noala-kv-v.noala-input,
.noala-kv-v input.noala-input,
.noala-kv-v select.noala-input,
.noala-kv-v textarea.noala-input {
  background: transparent; border: 1px solid transparent; box-shadow: none;
  text-align: right; font-size: 14.5px; font-weight: 600; color: var(--ink);
  padding: 4px 8px; border-radius: 9px; max-width: 100%;
}
.noala-kv-v.noala-input:hover:not(:disabled) { border-color: var(--border); }
.noala-kv-v.noala-input:focus { background: var(--surface-2); border-color: var(--accent); outline: none; }
.noala-kv-v.noala-input:disabled { color: var(--text-2); font-weight: 500; }
.noala-kv-v.noala-input::placeholder { font-weight: 400; color: var(--text-3); }
.noala-kv .noala-tag { flex: none; }
/* Une rangee dont la valeur est plus large qu une ligne (l introduction du
   devis) passe en colonne : la valeur a droite n a plus de sens a partir de
   deux lignes. */
.noala-kv--haut { align-items: flex-start; flex-direction: column; gap: 6px; }
.noala-kv--haut .noala-kv-v { margin-left: 0; width: 100%; text-align: left; }
.noala-kv--haut .noala-kv-v.noala-input { text-align: left; font-size: 13px; font-weight: 400; }

/* La grille de l onglet Profil : deux colonnes, la gauche plus large, chacune
   alignee en haut. Elle retombe a une colonne sous 900 px — la maquette n a
   aucune media query, et une grille 1.25fr/1fr a 375 px rendrait deux colonnes
   illisibles. */
.noala-reglages-grille {
  display: grid; grid-template-columns: 1.25fr 1fr; gap: var(--s-4); align-items: start;
}
/* ⚠️ Les cartes gardent leur `margin-bottom` d origine (style en ligne, partage
   avec les cinq autres onglets qui ne sont pas dans une grille) : la colonne
   n a donc PAS de `gap`, sans quoi la gouttiere serait doublee entre deux cartes
   et inegale d une colonne a l autre selon la derniere carte. La derniere marge
   de chaque colonne est neutralisee. */
.noala-reglages-grille > .noala-reglages-col { display: flex; flex-direction: column; min-width: 0; }
.noala-reglages-grille > .noala-reglages-col > *:last-child { margin-bottom: 0 !important; }
@media (max-width: 900px) { .noala-reglages-grille { grid-template-columns: 1fr; } }

/* Les pilules de sous-specialite : un groupe de bascules, pas des etiquettes.
   ⚠️ Elles sont des `<button>` avec `aria-pressed`, jamais des `<span>` : la
   maquette rend les non retenues en `--surface-2`/`--text-3`, ce qui se lit
   comme desactive alors qu elles selectionnent. La bordure et le curseur les
   rendent cliquables a l oeil, et le clavier les atteint. */
.noala-spe-pilules { display: flex; flex-wrap: wrap; gap: 6px; }
.noala-spe-pilule {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 12px; border-radius: var(--radius-pill);
  border: 1px solid var(--border); background: var(--surface);
  font: inherit; font-size: 12.5px; font-weight: 500; color: var(--text-2);
  cursor: pointer; white-space: nowrap;
}
.noala-spe-pilule:hover { border-color: var(--accent); color: var(--ink); }
.noala-spe-pilule[aria-pressed="true"] {
  background: var(--accent-soft); border-color: var(--accent); color: var(--accent-text); font-weight: 600;
}
/* La specialite elle-meme : un seul choix, rendu plein pour le distinguer des
   sous-specialites qui sont un choix multiple. */
.noala-spe-pilule--mere[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: #fff; }
.noala-spe-synthese { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: var(--s-3); font-size: 12px; color: var(--text-2); }
.noala-spe-synthese b { color: var(--ink); font-weight: 600; }
.noala-spe-synthese .noala-link-action { margin-left: auto; }


/* ─────────────────────────────────────────────────────────────
   Deux classes qui n'avaient de règle NULLE PART (lot 14c, écarts 4.3 et 4.4)
   ─────────────────────────────────────────────────────────────
   ⚠️ `.noala-btn-secondary` et `.noala-field-label` étaient employées dans
   `devis.html` sans exister dans aucune feuille — zéro occurrence dans
   `app.css` comme dans `patient.css`. Un élément avec une classe inconnue rend
   en CHROME NATIF du navigateur : bordure système de 2 px, fond gris système,
   police système, coins carrés, au milieu d'une page chartée. C'était l'élément
   le plus visiblement hors charte de tout le périmètre de l'audit.
   ⚠️ ET AUCUN TEST NE POUVAIT LE VOIR : une classe sans règle ne lève rien, ne
   journalise rien, et le sélecteur qui la vise trouve bien son élément. Seule
   une capture le montre.
   La règle vit ICI, et non dans la surcharge locale de `devis.html` : un nom
   préfixé `noala-` promet une règle globale, et la page suivante qui l'emploie
   de bonne foi doit la trouver. */
.noala-btn-secondary {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 10px 18px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--ink);
  font-family: inherit; font-size: 13px; font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  transition: background 0.15s;
}
.noala-btn-secondary:hover:not(:disabled) { background: var(--surface-2); }
.noala-btn-secondary:disabled { color: var(--text-3); cursor: not-allowed; }

.noala-field-label {
  display: block;
  font-size: 12.5px; font-weight: 600; color: var(--ink);
  margin-bottom: 6px;
}


/* ─────────────────────────────────────────────────────────────
   `x-show` et `display` : la mise en page vit dans une classe
   (lot 10 du plan d'audit, 2026-09-23)
   ─────────────────────────────────────────────────────────────
   ⚠️ `x-show` RETIRE la propriété `display` du style en ligne chaque fois
   qu'il affiche un élément (Alpine 3, `el.style.removeProperty('display')`,
   premier affichage compris). Un `display:flex` écrit dans l'attribut
   `style` d'un élément `x-show` est donc perdu : 23 éléments rendaient en
   bloc, mesurés dans le navigateur à l'audit du 2026-09-21.
   Ces classes sont en FIN de feuille : à spécificité égale, elles battent une
   règle de classe antérieure. Le `display:none` que pose `x-show` pour
   masquer est en ligne, il gagne toujours.
   Garde : `xshow_display.spec.js` refuse tout élément `x-show` qui porte un
   `display` en ligne, hors surcouches listées. */
.noala-show-flex        { display: flex; }
.noala-show-grid        { display: grid; }
.noala-show-inline-flex { display: inline-flex; }

/* `x-cloak` masque un élément jusqu'au démarrage d'Alpine, qui retire l'attribut. La règle
   ne vivait que dans `patient.css` : au cabinet et à la console, les panneaux `x-cloak`
   passaient à l'écran au chargement (lot 32, 2026-11-04). Les sept pages chargent cette
   feuille. Garde : `x_cloak.spec.js`. */
[x-cloak] { display: none !important; }

/* NOALA A+B foundation. Explicit opt-in only; see docs/brand/NOALA_DESIGN_SYSTEM.md.
   Density changes existing controls, never table rows or clinical color tokens. */
html[data-theme="light"][data-noala-ui="synthese"] {
  --bg: #F6F9F5;
  --surface: #FFFFFF;
  --surface-2: #E1F1E9;
  --ink: #143B4A;
  --accent-text: #197267;
  --accent-soft: #E1F1E9;
  --cta-bg: #143B4A;
  --cta-fg: #FFFFFF;
  --cta-bg-hover: #1D5468;
  --radius-btn: 15px;
  --control-height: 40px;
  --control-font-size: 0.875rem;
  --control-padding: 10px 16px;
  /* Le mouvement (spécification A du 2026-09-30) : une seule courbe, trois durées.
     Le portail patient les applique ; le cabinet et le site les adopteront sans recopie. */
  --motion-calme: cubic-bezier(.22, 1, .36, 1);
  --motion-court: 300ms;
  --motion-moyen: 420ms;
  --motion-long: 560ms;
  /* Les familles de carte du portail (conception du 2026-10-21, §2.2) : le fond
     pastel de la carte, la vague plus soutenue sous le titre, l'encre de l'icône.
     Teintes de la maquette `point2-tout-colore.html`. Le texte de la carte reste
     en --ink et --text : au moins 4,5:1 sur chaque vague (portail_cartes_familles). */
  --famille-fiche-fond: #E1F1E9;         --famille-fiche-vague: #CBE8DA;         --famille-fiche-encre: #1E8C7A;
  --famille-video-fond: #E1EAF0;         --famille-video-vague: #CBDDEA;         --famille-video-encre: #2F6690;
  --famille-faq-fond: #EDE8D9;           --famille-faq-vague: #E5D9B8;           --famille-faq-encre: #94701F;
  --famille-questionnaire-fond: #ECE7F4; --famille-questionnaire-vague: #DCD1EE; --famille-questionnaire-encre: #6B57A5;
  --famille-liste-fond: #E9EEDC;         --famille-liste-vague: #D8E3BF;         --famille-liste-encre: #5B7128;
  --famille-medical-fond: #F3E6E6;       --famille-medical-vague: #EAD2D2;       --famille-medical-encre: #A2504F;
  --famille-consentement-fond: #F7E9DC;  --famille-consentement-vague: #F0D6BF;  --famille-consentement-encre: #A0561D;
  --famille-lieu-fond: #E4EDF3;          --famille-lieu-vague: #D2E2EC;          --famille-lieu-encre: #3F6C86;
  /* Lot 34 : la palette de cabinet.css. Bloc écrit par scripts-dev/tokeniser-css.mjs. */
  /* Texte et filets. */
  --cab-texte: #244D58;
  --cab-doux: #526E74;
  --cab-ligne: #D3E1DC;
  --cab-bord: #7C9299;
  --cab-sur-encre: #D5E6E2;
  --cab-inactif: #A9BBB7;
  --cab-indice: #7C9AA3;
  --cab-etiquette: #6A777B;
  --cab-axe: #3D5C63;
  --cab-piste: #5C7C82;
  --cab-souligne: #9DB3AE;
  --cab-cta-inactif: #8FA5AD;
  --cab-noir: #000;
  /* Menthes. */
  --cab-menthe-2: #EDF6F1;
  --cab-menthe-survol: #D3EADF;
  --cab-segment-survol: #D8EDE2;
  --cab-vert-bord: #B9DACB;
  --cab-point-nonlu: #1B8573;
  --cab-bascule: #EDF3F0;
  --cab-replie: #F1F5F3;
  --cab-image-fond: #F1F8F4;
  --cab-tel-fond: #DCE8E2;
  --cab-puce-doc: #EEF3F8;
  --cab-cadre-gris: #E8EEEC;
  --cab-jour-perdu: #EEF2F0;
  --cab-bloc-interne: #F4F1EA;
  --cab-brouillon: #B9C7C2;
  /* États : bon, attention, alerte, neutre. */
  --cab-bon: #1E6B52;
  --cab-bon-fond: #DDEFE6;
  --cab-bon-bord: #BCDCCB;
  --cab-attention: #8A4F0B;
  --cab-attention-fond: #FBEBD5;
  --cab-attention-bord: #EBC89B;
  --cab-attention-bord-2: #E2BC8A;
  --cab-attention-rond: #B8741B;
  --cab-alerte: #9C3317;
  --cab-alerte-fond: #FBE3DC;
  --cab-alerte-bord: #EDB9A9;
  --cab-alerte-survol: #7E2912;
  --cab-danger: #B3261E;
  --cab-grave-fond: #FBF4EF;
  --cab-grave-bord: #EAD9CD;
  --cab-grave-souligne: #D9A996;
  --cab-neutre-fond: #EEF2F1;
  /* Étapes de la frise. */
  --cab-etape-faite: #CBE7DA;
  --cab-etape-faite-bord: #8DC3AE;
  --cab-etape-bord: #9DB9B2;
  --cab-etape-tiret: #9DBDB4;
  --cab-rond-avenir: #5E8A80;
  /* Bords de champs, de dépôts et de fenêtres. */
  --cab-depot-bord: #B9D3C8;
  --cab-note-bord: #B9D3C6;
  --cab-ferme-bord: #B9CCC6;
  /* Aperçu du document et de son état vide, Réglages. */
  --cab-document-texte: #263B43;
  --cab-document-bord: #D9E4E5;
  --cab-vide-fond: #F4F7F7;
  --cab-vide-texte: #526C73;
  /* Encre, blanc, menthe et vert en transparence : le nombre dit l'alpha. */
  --cab-encre-04: rgba(20, 59, 74, .04);
  --cab-encre-08: rgba(20, 59, 74, .08);
  --cab-encre-10: rgba(20, 59, 74, .10);
  --cab-encre-14: rgba(20, 59, 74, .14);
  --cab-encre-16: rgba(20, 59, 74, .16);
  --cab-encre-20: rgba(20, 59, 74, .2);
  --cab-encre-28: rgba(20, 59, 74, .28);
  --cab-encre-35: rgba(20, 59, 74, .35);
  --cab-encre-53: rgba(20, 59, 74, .53);
  --cab-encre-hex22: #143B4A22;
  --cab-doux-40: rgba(82, 110, 116, .4);
  --cab-blanc-18: rgba(255, 255, 255, .18);
  --cab-blanc-20: rgba(255, 255, 255, .2);
  --cab-blanc-35: rgba(255, 255, 255, .35);
  --cab-blanc-40: rgba(255, 255, 255, .4);
  --cab-blanc-45: rgba(255, 255, 255, .45);
  --cab-blanc-hexe6: #FFFFFFE6;
  --cab-menthe-15: rgba(225, 241, 233, .15);
  --cab-menthe-78: rgba(225, 241, 233, .78);
  --cab-vert-06: rgba(25, 114, 103, .06);
  --cab-vert-08: rgba(25, 114, 103, .08);
  --cab-vert-10: rgba(25, 114, 103, .10);
  /* Les chevrons des listes : un SVG ne lit pas de var(), le jeton porte l'adresse. */
  --cab-chevron-bas: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23143B4A' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  --cab-chevron-champ: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23143B4A' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m7 10 5 5 5-5'/%3E%3C/svg%3E");
  /* Fin du lot 34. */
}
html[data-theme="light"][data-noala-ui="synthese"] [data-noala-density="patient"] {
  --fs-body: 1rem;
  --control-height: 52px;
  --control-font-size: 1rem;
  --control-padding: 14px 20px;
  font-size: var(--fs-body);
  line-height: 1.65;
}
html[data-theme="light"][data-noala-ui="synthese"] [data-noala-density="professional"] {
  --control-height: 40px;
  --control-font-size: 0.875rem;
  --control-padding: 10px 16px;
}
html[data-theme="light"][data-noala-ui="synthese"] [data-noala-density="admin"] {
  --control-height: 32px;
  --control-font-size: 0.8125rem;
  --control-padding: 6px 12px;
}
html[data-theme="light"][data-noala-ui="synthese"] :is(.noala-cta, .noala-link-action, .noala-input, .noala-task-row, .noala-acc > summary) {
  min-height: var(--control-height);
  padding: var(--control-padding);
  font-family: var(--font-sans);
  font-size: var(--control-font-size);
  line-height: 1.5;
  white-space: normal;
  overflow-wrap: anywhere;
  max-width: 100%;
  min-width: 0;
}
html[data-theme="light"][data-noala-ui="synthese"] :is(.noala-cta, .noala-link-action) {
  border-radius: var(--radius-btn);
  cursor: pointer;
}
html[data-theme="light"][data-noala-ui="synthese"] .noala-link-action {
  color: var(--accent-text);
  background: var(--surface-2);
}
html[data-theme="light"][data-noala-ui="synthese"] .noala-link-action:hover { color: var(--ink); }
html[data-theme="light"][data-noala-ui="synthese"] :is(.noala-cta, .noala-link-action):disabled {
  opacity: 1;
  background: var(--surface-2);
  color: var(--text);
  cursor: not-allowed;
}
html[data-theme="light"][data-noala-ui="synthese"] .noala-input {
  background: var(--surface);
  border-color: var(--text-2);
}
html[data-theme="light"][data-noala-ui="synthese"] .noala-input[aria-invalid="true"] { border-color: var(--alert-text); }
html[data-theme="light"][data-noala-ui="synthese"] :is(input[type="checkbox"], input[type="radio"]) {
  accent-color: var(--accent-text);
  width: 20px;
  height: 20px;
  flex: none;
}
html[data-theme="light"][data-noala-ui="synthese"] [data-noala-density="patient"] label:has(> :is(input[type="checkbox"], input[type="radio"])) {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 48px;
  overflow-wrap: anywhere;
}
html[data-theme="light"][data-noala-ui="synthese"] :is(.noala-card, .noala-acc, .noala-modal-card) { overflow-wrap: anywhere; }
html[data-theme="light"][data-noala-ui="synthese"] .noala-card { animation: none; }
html[data-theme="light"][data-noala-ui="synthese"] .noala-acc-title { font-size: var(--control-font-size); }
html[data-theme="light"][data-noala-ui="synthese"] .noala-acc > summary::after { color: var(--accent-text); }
html[data-theme="light"][data-noala-ui="synthese"] :focus-visible {
  outline: 3px solid var(--accent-text);
  outline-offset: 3px;
}
html[data-theme="light"][data-noala-ui="synthese"] .noala-acc > summary:focus-visible { outline-offset: -4px; }
html[data-theme="light"][data-noala-ui="synthese"] dialog.noala-modal-card {
  width: min(620px, calc(100% - 32px));
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface);
  color: var(--ink);
}
html[data-theme="light"][data-noala-ui="synthese"] dialog::backdrop { background: var(--modal-scrim); }
@media (prefers-reduced-motion: reduce) {
  html[data-theme="light"][data-noala-ui="synthese"],
  html[data-theme="light"][data-noala-ui="synthese"] *,
  html[data-theme="light"][data-noala-ui="synthese"] *::before,
  html[data-theme="light"][data-noala-ui="synthese"] *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
}

/* ═══ Images de contenu dans une fiche (lot 2 des images, 2026-09-30) ═══════
   Rendues par `NoalaUI.imagesContenu.ligne` (ui.js), la seule règle qui
   transforme une ligne Markdown en image : aperçu du praticien, de la console
   et page de lecture du portail. L'image ne dépasse jamais sa colonne. */
.noala-md-figure { margin: var(--s-3) 0; }
.noala-md-image { display: block; max-width: 100%; height: auto; border-radius: var(--radius-md); }
/* Le bouton qui porte l'image : sans habillage, pour l'agrandir au clavier. */
.noala-md-zoom { display: block; max-width: 100%; padding: 0; border: 0; background: none; border-radius: var(--radius-md); }
