/* ================================================================
   Bleme — thème sombre « application mobile »
   Même grammaire que /srv/annuaire, /srv/contact, /srv/agenda,
   /srv/play et /srv/actu (topbar fixe + pastille d'onglets flottante
   opaque, sidebar sur grand écran, icônes Lucide inline), avec une
   identité propre : UNE COULEUR PLEINE PAR PAGE sur un quasi-noir
   commun (jaune, rouge, vert-cyan), chacune dérivant vers une
   seconde teinte — là où l'Annuaire est bleu marine, Contact
   turquoise, l'Agenda vert et or, Play violet et Actu corail.
   Règle absolue : AUCUN box-shadow, nulle part (préférence
   utilisateur) — les reliefs sont rendus par bordures et fonds.
   Jamais d'emoji : uniquement des icônes Lucide.
   ================================================================ */
:root {
  color-scheme: dark;
  /* LE QUASI-NOIR COMMUN. Tout le sol d'une page est bâti dessus, en y posant
     un peu de la couleur de la page (§ « la couleur de la page », plus bas).
     Ce n'est plus une nuit ambrée teintée après coup : une page est de sa
     couleur DÈS le fond, ce qui la rend à la fois plus sombre et plus franche.
     Ne jamais s'en servir directement dans une règle. */
  --nuit: #070609;
  --accent: #a3e635;
  --accent-2: #c8f27e;
  --sur-accent: #101c02;
  --puce: var(--accent);
  --degrade-marque: linear-gradient(135deg, #a3e635, #2dd4bf);
  --sur-marque: #ffffff;
  --ok: #48d6a0;
  --ok-doux: #113026;
  --warn: #ffcc4d;
  --warn-doux: #3a2f0f;
  --danger: #ff6b78;
  --danger-doux: #381820;
  --rayon: 18px;
  --rayon-petit: 12px;
  --sidebar: 238px;
  /* Encoches et barres système : la topbar et la pastille d'onglets s'en
     écartent au lieu de passer dessous. Mêmes noms que dans les autres
     applications du groupe. */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

/* LA COULEUR DE LA PAGE. Une classe `zone-*` sur <body> (posée par head.ejs)
   suffit à habiller toute la page : accent, sol, gris de texte, dégradé et
   bouton plein en découlent, sans une seule règle dupliquée.

   Chaque page EST d'une couleur, et son dégradé DÉRIVE vers une seconde :
     Solutions       JAUNE      qui dérive vers un ROSE GIRLY
     Problématiques  ROUGE      qui dérive vers un PRUNE VIOLET
     Sujets          VERT-CYAN  qui dérive vers un JAUNE CLAIR
     Administration  VIOLET     (sans dérive : ce n'est pas une page de travail)

   Trois réglages par zone, et rien d'autre à écrire :
     --fruit    la couleur de la page. Elle bâtit TOUT le sol — fond, surfaces,
                traits, pastille du bas, fond des champs — et jusqu'aux gris du
                texte, qui portent une pointe de la même couleur pour ne pas
                rester des gris d'une autre page.
     --fruit-2  la dérive : où va le dégradé, et vers quoi penche le coin du
                bouton plein.
     --halo     la force de cette dérive en haut de page.

   Le sol est bâti SUR LE QUASI-NOIR (--nuit), pas sur une nuit ambrée qu'on
   teinterait : c'est ce qui donne un fond franchement coloré et nettement plus
   sombre qu'avant. La rampe (6 % pour le fond, 14 % pour une carte, 32 % pour
   un trait…) est la même pour toutes les zones — seule la couleur change.

   Les chiffres sont MESURÉS, pas choisis à l'œil, et `npm test` les revérifie :
   3:1 pour --accent (il sert de bordure de focus et de trait fin), 4,5:1 pour
   --muet, --texte et --sur-accent, qui portent du texte. Le point qui décide
   est toujours le plus clair réellement visible : le fond, PLUS le voile,
   PLUS le halo. Ne retoucher aucun de ces réglages sans relancer le test. */

/* AUJOURD'HUI — page VERT POMME, dérive TURQUOISE. C'est la page d'accueil et
   la seule où l'on écrit : sa couleur est celle de la vitalité, et elle dérive
   vers le turquoise de l'historique pour dire que l'une nourrit l'autre.
   Le vert pomme est très clair : il tient 11,4:1 sur une carte, et son encre de
   bouton plein est donc presque noire (--sur-accent). */
.zone-jour {
  --accent: #a3e635;
  --accent-2: #c8f27e;
  --sur-accent: #101c02;
  --puce: var(--accent);
  --fruit: #a3e635;
  --fruit-2: #2dd4bf;
  --halo: 12%;
}

/* HISTORIQUE — page TURQUOISE, dérive VERT POMME. L'inverse exact de la page
   du jour : on y relit ce qu'on y a écrit. */
.zone-historique {
  --accent: #2dd4bf;
  --accent-2: #6ee7d7;
  --sur-accent: #021816;
  --puce: var(--accent);
  --fruit: #2dd4bf;
  --fruit-2: #a3e635;
  --halo: 10%;
}

/* MESURES — page CORAIL, dérive AMBRE. C'est la page des réglages de fond :
   elle se distingue franchement des deux pages de contenu, parce qu'on n'y
   note pas une journée, on y décide ce qu'une journée doit valoir. */
.zone-mesures {
  --accent: #ff8a5c;
  --accent-2: #ffb494;
  --sur-accent: #26100a;
  --puce: var(--accent);
  --fruit: #ff8a5c;
  --fruit-2: #ffc21f;
  --halo: 13%;
}

/* ADMINISTRATION — page VIOLET, sans dérive : le dégradé y reste dans la
   couleur de la page. Ce n'est pas une matière de l'application, elle n'a pas
   à s'annoncer d'une seconde teinte. Même violet que dans tout le groupe. */
.zone-admin {
  --accent: #c9a6ff;
  --accent-2: #ddc4ff;
  --sur-accent: #150b20;
  --puce: var(--accent);
  --fruit: #c9a6ff;
  --fruit-2: #c9a6ff;
  --halo: 10%;
}

* { box-sizing: border-box; }
/* Pas de fond sur <html> : sans lui, c'est celui de <body> qui remonte au
   canevas, teinte comprise. Une page verte reste verte jusque dans le
   rebond élastique du défilement, où l'on verrait sinon la nuit nue. */
html { min-height: 100%; }
body {
  /* Sans zone — connexion, page d'erreur — la page prend l'or de Bleme et
     dérive vers son or clair : jamais de page grise, jamais de couleur
     étrangère écrite en dur. */
  --fruit: var(--accent);
  --fruit-2: var(--accent-2);
  --halo: 10%;

  /* LE SOL, bâti sur le quasi-noir avec la couleur de la page. La rampe est
     la même partout : c'est elle qui fait qu'une carte se distingue du fond et
     qu'un trait se distingue d'une carte. Une carte ne se détache PAS par sa
     luminance (1,06:1 à peine) mais par sa bordure — c'était déjà vrai avant,
     ne pas essayer de « corriger » ça en éclaircissant les surfaces. */
  --fond: color-mix(in srgb, var(--fruit) 6%, var(--nuit));
  --fond-2: color-mix(in srgb, var(--fruit) 10%, var(--nuit));
  --surface: color-mix(in srgb, var(--fruit) 14%, var(--nuit));
  --surface-2: color-mix(in srgb, var(--fruit) 19%, var(--nuit));
  --surface-3: color-mix(in srgb, var(--fruit) 24%, var(--nuit));
  --trait: color-mix(in srgb, var(--fruit) 32%, var(--nuit));
  --trait-fort: color-mix(in srgb, var(--fruit) 45%, var(--nuit));
  /* Un champ de saisie est plus SOMBRE que la page : c'est un creux, pas une
     carte. Jamais de couleur de champ écrite en dur (règle héritée). */
  --champ: color-mix(in srgb, var(--fruit) 3%, var(--nuit));
  --tabbar-base: color-mix(in srgb, var(--fruit) 8%, var(--nuit));
  /* Le fond des boutons secondaires, onglets actifs et notices. 13 % et pas
     plus : à 18 %, le bordeaux des problématiques ne tenait plus que 2,96:1
     sur son propre fond doux, alors qu'il lui sert de bordure. */
  --accent-doux: color-mix(in srgb, var(--accent) 13%, var(--fond));

  /* LES GRIS APPARTIENNENT À LA PAGE. Un gris ambré sur une page vert-cyan a
     l'air sale : chaque gris porte donc une pointe de la couleur de la page.
     Assez pour appartenir à la page, pas assez pour colorer la lecture. */
  --texte: color-mix(in srgb, var(--fruit) 5%, #fbf8f4);
  --texte-2: color-mix(in srgb, var(--fruit) 10%, #ded8d0);
  --muet: color-mix(in srgb, var(--fruit) 14%, #9d9791);

  min-height: 100vh;
  margin: 0;
  /* LE DÉGRADÉ : la page part de sa couleur et DÉRIVE vers la seconde, en haut
     à droite, là où le regard entre. Deux couches et pas une ombre — le relief
     reste affaire de fonds et de bordures.
     Le halo est posé en REM, pas en pourcentage : un « -20% » se mesure sur la
     hauteur du document, et sur une longue liste il partait si haut qu'on ne le
     voyait plus. En rem, une page courte et une page longue portent le même
     dégradé. Et surtout pas de `background-attachment: fixed` — Safari mobile
     le rend par à-coups au défilement, et c'est ici une application mobile. */
  background:
    radial-gradient(circle 36rem at 78% -7rem, color-mix(in srgb, var(--fruit-2) var(--halo), transparent), transparent),
    linear-gradient(178deg, color-mix(in srgb, var(--fruit-2) 5%, transparent), transparent 44rem),
    var(--fond);
  color: var(--texte);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; }
button, select { cursor: pointer; }
button:disabled { cursor: not-allowed; opacity: .55; }
img, svg { display: block; }
.lucide { width: 1.12em; height: 1.12em; flex: 0 0 auto; }
.muted { color: var(--muet); }

.layout { min-height: 100vh; }
.sidebar {
  position: fixed;
  inset: 0 auto 0 0;
  z-index: 20;
  display: flex;
  width: var(--sidebar);
  flex-direction: column;
  gap: 6px;
  padding: 24px 16px;
  border-right: 1px solid var(--trait);
  /* Le fond de la barre latérale vient de la nuit de l'application, jamais
     d'une couleur écrite en dur : même formule que /srv/play. */
  background: color-mix(in srgb, var(--fond) 92%, transparent);
}
.brand {
  display: flex;
  align-items: center;
  gap: 11px;
  min-height: 54px;
  margin: 0 4px 22px;
  font-size: 1.2rem;
  font-weight: 800;
  letter-spacing: -.02em;
}
.brand-ico {
  display: inline-grid;
  width: 38px;
  height: 38px;
  flex: 0 0 auto;
  place-items: center;
  border-radius: 12px;
  background: var(--degrade-marque);
  color: var(--sur-marque);
}
.brand-ico svg { width: 25px; height: 25px; }
.sidebar > a {
  display: flex;
  min-height: 47px;
  align-items: center;
  gap: 12px;
  padding: 0 13px;
  border: 1px solid transparent;
  border-radius: 13px;
  color: var(--texte-2);
  font-weight: 660;
}
.sidebar > a:hover { border-color: var(--trait); background: var(--surface); color: var(--texte); }
.sidebar > a.active { border-color: color-mix(in srgb, var(--accent) 45%, var(--trait)); background: var(--accent-doux); color: var(--accent-2); }
.sidebar .ico { display: grid; width: 22px; place-items: center; }
.logout-form { margin-top: auto; }
.logout-form button {
  width: 100%;
  min-height: 44px;
  border: 1px solid var(--trait);
  border-radius: 12px;
  background: transparent;
  color: var(--muet);
}
.logout-form button:hover { color: var(--texte); border-color: var(--trait-fort); }

.topbar, .tabbar { display: none; }

/* Pastille du SEUL compteur de l'interface (cloche de la topbar). Rouge, comme
   dans le reste du groupe : elle ne compte que les problématiques ouvertes sans
   solution, jamais une bonne nouvelle. */
.notif-dot {
  position: absolute; top: -4px; right: -6px; min-width: 18px; height: 18px;
  background: var(--danger); color: #fff; border-radius: 99px; font-size: 11px; font-weight: 700;
  display: flex; align-items: center; justify-content: center; padding: 0 4px;
}

.content {
  width: min(1160px, calc(100% - var(--sidebar)));
  min-height: 100vh;
  margin-left: var(--sidebar);
  padding: 42px clamp(28px, 5vw, 72px) 90px;
}

h1, h2, h3, p { margin-top: 0; }
h1 { margin-bottom: 0; font-size: clamp(2rem, 5vw, 3.3rem); line-height: 1.06; letter-spacing: -.045em; }
h2 { margin-bottom: 14px; font-size: 1.18rem; letter-spacing: -.018em; }
h3 { margin-bottom: 7px; font-size: 1.05rem; }
.eyebrow { margin: 0 0 6px; color: var(--accent-2); font-size: .75rem; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; }
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; margin-bottom: 24px; }
.head-actions, .action-bar, .carte-actions, .inline-end { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
.inline-end { justify-content: flex-end; margin-top: 24px; }
.section-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin: 38px 0 15px; }
.section-head h2 { margin: 0; }
.back { display: inline-flex; align-items: center; gap: 7px; margin-bottom: 22px; color: var(--muet); font-weight: 700; }
.back:hover { color: var(--accent-2); }

.notice {
  display: flex;
  align-items: flex-start;
  gap: 13px;
  margin-bottom: 25px;
  padding: 15px 17px;
  border: 1px solid color-mix(in srgb, var(--accent) 36%, var(--trait));
  border-radius: var(--rayon-petit);
  background: color-mix(in srgb, var(--accent-doux) 65%, var(--surface));
  color: var(--texte-2);
}
.notice p { margin: 0; }
.notice-ico { display: grid; margin-top: 2px; color: var(--accent-2); }
.flash, .alerte {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 18px;
  padding: 13px 15px;
  border: 1px solid var(--trait-fort);
  border-radius: var(--rayon-petit);
  background: var(--surface);
}
.flash.ok { border-color: color-mix(in srgb, var(--ok) 45%, var(--trait)); color: var(--ok); }
.flash.err, .alerte { border-color: color-mix(in srgb, var(--danger) 45%, var(--trait)); background: var(--danger-doux); color: #ffb3bb; }

.btn, button.btn {
  display: inline-flex;
  min-height: 44px;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 9px 15px;
  border: 1px solid transparent;
  border-radius: 12px;
  font-weight: 760;
  line-height: 1.2;
}
/* Le bouton plein porte le MÊME geste que la page : il part de l'accent et
   dérive vers la seconde teinte dans son coin haut gauche. C'est ce qui le
   raccroche au dégradé du fond au lieu d'en être un aplat posé dessus.
   L'encre reste --sur-accent, mesurée sur les deux bouts du dégradé — 5,84:1
   au plus serré (le blanc sur le bordeaux des problématiques). */
.btn.primaire {
  background: linear-gradient(142deg, color-mix(in srgb, var(--fruit-2) 30%, var(--accent)), var(--accent) 62%);
  color: var(--sur-accent);
}
.btn.primaire:hover {
  background: linear-gradient(142deg, color-mix(in srgb, var(--fruit-2) 30%, var(--accent-2)), var(--accent-2) 62%);
}
.btn.secondaire { border-color: color-mix(in srgb, var(--accent) 45%, var(--trait)); background: var(--accent-doux); color: var(--accent-2); }
.btn.secondaire:hover { border-color: var(--accent); }
.btn.fantome { border-color: var(--trait); background: transparent; color: var(--texte-2); }
.btn.fantome:hover { border-color: var(--trait-fort); color: var(--texte); }
.btn.danger { border-color: color-mix(in srgb, var(--danger) 55%, var(--trait)); background: var(--danger-doux); color: #ffadb7; }
.icon-btn {
  display: inline-grid;
  width: 44px;
  height: 44px;
  flex: 0 0 auto;
  place-items: center;
  border: 1px solid var(--trait);
  border-radius: 12px;
  background: transparent;
  color: var(--muet);
}
.icon-btn:hover, .icon-btn.active { border-color: var(--accent); background: var(--accent-doux); color: var(--accent-2); }
.danger-text { color: var(--danger); }

/* ================================================================
   LA RANGÉE DE CHIFFRES — même dessin que /srv/admin, au pixel près.
   Une tuile dit toujours trois choses, dans cet ordre :
     1. un LIBELLÉ porté par une icône ;
     2. une VALEUR, chiffres proportionnels — surtout pas `tabular-nums`,
        qui donne à chaque chiffre la largeur d'un zéro et fait flotter un
        « 12 » à cette taille ; le tabulaire est réservé aux colonnes ;
     3. une PREUVE : la jauge d'un rapport, quand il y a un rapport.
   L'encre reste de l'encre : la valeur ne prend JAMAIS la couleur de
   l'état, c'est la jauge et l'icône qui la portent. Sans quoi un chiffre
   rouge se lit comme une alarme alors qu'il dit juste « 2 sur 3 ».
   ================================================================ */
.stats-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
  margin: 22px 0 28px;
}
.stat {
  display: flex;
  min-height: 124px;
  flex-direction: column;
  gap: 9px;
  padding: 15px 17px 16px;
  border: 1px solid var(--trait);
  border-radius: var(--rayon);
  /* Un fond très légèrement dégradé : le relief vient du fond et de la
     bordure, jamais d'une ombre (règle absolue de l'application). */
  background: linear-gradient(158deg, var(--surface-2), var(--surface) 62%);
}
.stat:hover { border-color: color-mix(in srgb, var(--accent) 55%, var(--trait)); }
.stat-tete {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--muet);
  font-size: .8rem;
  font-weight: 700;
  letter-spacing: -.005em;
}
/* L'icône porte l'état EN PLUS de la jauge : une couleur seule ne dit rien
   à qui ne la distingue pas, et l'ambre et le vert sont justement la paire
   la plus proche pour un œil protanope. */
.stat-ico {
  display: grid;
  width: 26px;
  height: 26px;
  flex: 0 0 auto;
  place-items: center;
  border-radius: 9px;
  background: var(--accent-doux);
  color: var(--accent-2);
}
.stat-ico .lucide { width: 15px; height: 15px; }
.stat-ico.bon { background: var(--ok-doux); color: var(--ok); }
.stat-ico.moyen { background: var(--warn-doux); color: var(--warn); }
.stat-ico.mauvais { background: var(--danger-doux); color: var(--danger); }
.stat-val {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 3px 8px;
  margin-top: auto;
  color: var(--texte);
  font-size: 1.9rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.035em;
}
.stat-val small {
  color: var(--muet);
  font-size: .78rem;
  font-weight: 640;
  letter-spacing: 0;
}

/* La jauge : la preuve d'un rapport, sous la valeur. Neutre par défaut —
   une teinte d'état ne se pose que là où le rapport dit vraiment une bonne
   ou une mauvaise nouvelle. */
.jauge {
  position: relative;
  height: 8px;
  overflow: hidden;
  border-radius: 999px;
  --jauge-teinte: var(--accent);
  background: color-mix(in srgb, var(--jauge-teinte) 17%, var(--fond));
  border: 1px solid color-mix(in srgb, var(--jauge-teinte) 26%, transparent);
}
.jauge > i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--jauge-teinte);
  transition: width .25s ease;
}
.jauge.bon { --jauge-teinte: var(--ok); }
.jauge.moyen { --jauge-teinte: var(--warn); }
.jauge.mauvais { --jauge-teinte: var(--danger); }

.tabs { display: flex; gap: 7px; margin: 18px 0; overflow-x: auto; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tabs a { flex: 0 0 auto; padding: 9px 13px; border: 1px solid var(--trait); border-radius: 999px; color: var(--muet); font-size: .88rem; font-weight: 720; }
.tabs a:hover { color: var(--texte); }
.tabs a.active { border-color: var(--accent); background: var(--accent-doux); color: var(--accent-2); }

.filters {
  display: grid;
  grid-template-columns: minmax(240px, 1fr) auto auto auto;
  gap: 9px;
  margin-bottom: 22px;
}
.search-wrap { position: relative; }
.search-wrap > .lucide { position: absolute; top: 50%; left: 13px; z-index: 1; color: var(--muet); transform: translateY(-50%); }
.search-wrap input { width: 100%; padding-left: 40px; padding-right: 46px; }
.micro { position: absolute; inset: 4px 4px 4px auto; display: grid; width: 38px; place-items: center; border: 0; border-radius: 9px; background: transparent; color: var(--muet); }
.micro.ecoute { background: var(--danger-doux); color: var(--danger); outline: 1px solid var(--danger); }

input, select, textarea {
  width: 100%;
  min-height: 44px;
  border: 1px solid var(--trait);
  border-radius: 11px;
  outline: 0;
  background: var(--champ);
  color: var(--texte);
}
input, select { padding: 9px 12px; }
input::placeholder, textarea::placeholder { color: color-mix(in srgb, var(--muet) 78%, transparent); opacity: 1; }
textarea { min-height: 100px; padding: 12px 13px; resize: vertical; }
input:focus, select:focus, textarea:focus { border-color: var(--accent); outline: 2px solid color-mix(in srgb, var(--accent) 20%, transparent); }
input[type="color"] { width: 58px; padding: 4px; }
label { display: grid; gap: 7px; color: var(--texte-2); font-size: .9rem; font-weight: 680; }
label small { color: var(--muet); font-weight: 450; }
label.check { display: flex; min-height: 44px; align-items: center; gap: 9px; align-self: end; }
label.check input { width: 19px; min-height: 19px; accent-color: var(--accent); }

.form-card, .panel {
  margin-bottom: 24px;
  padding: clamp(18px, 4vw, 27px);
  border: 1px solid var(--trait);
  border-radius: var(--rayon);
  background: var(--surface);
}
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 17px; margin-bottom: 20px; }
.form-grid .full { grid-column: 1 / -1; }
.compact-form { display: flex; align-items: end; gap: 12px; }
.compact-form label:first-of-type { flex: 1; }
.highlight { border-color: color-mix(in srgb, var(--accent) 45%, var(--trait)); background: color-mix(in srgb, var(--accent-doux) 45%, var(--surface)); }
.error-panel { border-color: color-mix(in srgb, var(--danger) 50%, var(--trait)); }
.danger-zone { display: flex; align-items: end; justify-content: flex-end; gap: 12px; margin-top: 38px; padding-top: 20px; border-top: 1px solid var(--trait); }
.danger-zone input[type="number"] { width: 110px; }

.cards-list { display: grid; gap: 13px; }
.carte {
  position: relative;
  display: flex;
  gap: 16px;
  padding: 20px;
  overflow: hidden;
  border: 1px solid var(--trait);
  border-radius: var(--rayon);
  background: var(--surface);
}
.carte::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 3px; background: var(--puce); }
.carte:hover { border-color: color-mix(in srgb, var(--puce) 52%, var(--trait)); }
.carte.is-new { background: color-mix(in srgb, var(--accent-doux) 35%, var(--surface)); }
.carte-main { min-width: 0; flex: 1; }
.actu-visuel { width: clamp(170px, 24vw, 245px); aspect-ratio: 16 / 9; flex: 0 0 auto; align-self: flex-start; overflow: hidden; border: 1px solid var(--trait); border-radius: 14px; background: var(--fond-2); }
.actu-visuel img, .article-hero img { width: 100%; height: 100%; object-fit: cover; }
.actu-visuel:hover { border-color: color-mix(in srgb, var(--puce) 55%, var(--trait)); }
.carte h2 { margin: 6px 0 9px; font-size: clamp(1.05rem, 2vw, 1.25rem); line-height: 1.3; }
.carte h2 a:hover { color: var(--accent-2); }
.meta-line { display: flex; align-items: center; flex-wrap: wrap; gap: 7px 10px; color: var(--muet); font-size: .78rem; }
.puce { display: inline-flex; align-items: center; gap: 5px; color: var(--puce); font-weight: 800; }
.resume { margin-bottom: 12px; color: var(--texte-2); }
.points { margin: 11px 0 15px; padding: 0; list-style: none; }
.points li { position: relative; margin: 6px 0; padding-left: 19px; color: var(--texte-2); }
.points li::before { content: ""; position: absolute; top: .62em; left: 2px; width: 6px; height: 6px; border-radius: 50%; background: var(--puce); }
.points.large li { margin: 11px 0; color: var(--texte); font-size: 1rem; }
.lien-offre { display: flex; align-items: flex-start; gap: 8px; color: var(--accent-2); font-size: .91rem; }
.carte-actions { margin-top: 15px; }
.carte-actions form { display: flex; }
.pourquoi { padding: 10px 12px; border-left: 2px solid var(--puce); background: color-mix(in srgb, var(--puce) 7%, transparent); color: var(--texte-2); font-size: .9rem; }
.details-inline { display: flex; flex-wrap: wrap; gap: 8px 15px; color: var(--muet); font-size: .84rem; }
.details-inline span { display: inline-flex; align-items: center; gap: 5px; }
.date-puce { display: grid; width: 57px; height: 62px; flex: 0 0 auto; place-content: center; border: 1px solid color-mix(in srgb, var(--puce) 50%, var(--trait)); border-radius: 14px; background: color-mix(in srgb, var(--puce) 10%, var(--fond)); text-align: center; }
.date-puce strong { color: var(--texte); font-size: 1.45rem; line-height: 1; }
.date-puce span { margin-top: 4px; color: var(--puce); font-size: .69rem; font-weight: 800; }

.badge { display: inline-flex; align-items: center; width: max-content; padding: 3px 8px; border: 1px solid var(--trait); border-radius: 999px; color: var(--texte-2); font-size: .71rem; font-weight: 780; white-space: nowrap; }
.badge.ok { border-color: color-mix(in srgb, var(--ok) 48%, var(--trait)); background: var(--ok-doux); color: #82ebc1; }
.badge.warn { border-color: color-mix(in srgb, var(--warn) 48%, var(--trait)); background: var(--warn-doux); color: #ffd080; }
.badge.err { border-color: color-mix(in srgb, var(--danger) 48%, var(--trait)); background: var(--danger-doux); color: #ffadb7; }
.badge.gris { color: var(--muet); }

.detail-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 9px 15px; margin: 0 0 18px; color: var(--muet); }
/* Une carte de solution illustrée : l'image à gauche, le texte à droite —
   même dessin qu'une carte d'actualité. Sur téléphone, elle passe au-dessus
   (voir la règle ≤ 900 px), sinon il ne resterait rien du texte. */
.carte-illustree { align-items: flex-start; }
.article-hero-bloc { margin: 0 0 20px; }
.article-hero-bloc figcaption { display: flex; align-items: center; gap: 6px; margin-top: 8px; font-size: .8rem; }
.article-hero-bloc .article-hero { margin-bottom: 0; }
.article-hero { width: 100%; max-height: 520px; aspect-ratio: 16 / 8; margin: 0 0 20px; overflow: hidden; border: 1px solid var(--trait); border-radius: var(--rayon); background: var(--fond-2); }
.detail-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
.article-text { max-width: 76ch; color: var(--texte-2); font-size: 1.02rem; }
.article-text p { margin-bottom: 1.1em; }
.callout { margin-top: 19px; padding: 14px 16px; border-left: 3px solid var(--accent); background: var(--accent-doux); }
.callout p { margin: 6px 0 0; color: var(--texte-2); }
.facts { margin: 0; }
.facts > div { display: grid; grid-template-columns: minmax(105px, .45fr) 1fr; gap: 15px; padding: 11px 0; border-bottom: 1px solid var(--trait); }
.facts > div:last-child { border-bottom: 0; }
.facts dt { display: flex; align-items: center; gap: 7px; color: var(--muet); }
.facts dd { margin: 0; overflow-wrap: anywhere; }
.facts a { display: inline-flex; align-items: center; gap: 5px; color: var(--accent-2); }

.mini-list { display: grid; gap: 8px; }
.mini-list > a { display: flex; min-height: 57px; align-items: center; justify-content: space-between; gap: 15px; padding: 11px 13px; border: 1px solid var(--trait); border-radius: 12px; background: var(--surface); }
.mini-list > a:hover { border-color: var(--accent); }
.mini-list > a > span { display: grid; min-width: 0; }
.mini-list strong { overflow: hidden; text-overflow: ellipsis; }
.mini-list small { color: var(--muet); }
.empty { display: grid; min-height: 210px; place-items: center; align-content: center; padding: 25px; border: 1px dashed var(--trait-fort); border-radius: var(--rayon); color: var(--muet); text-align: center; }
.empty > .lucide { width: 34px; height: 34px; margin-bottom: 10px; color: var(--accent); }
.empty h2 { margin-bottom: 5px; color: var(--texte); }
.empty p { margin: 0; }
.empty.compact { min-height: 130px; }

.progress-card { display: none; margin: 0 0 20px; padding: 15px 17px; border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--trait)); border-radius: 14px; background: var(--accent-doux); }
.progress-card.visible { display: block; }
.progress-top { display: flex; justify-content: space-between; gap: 15px; }
.progress-track { height: 7px; margin: 11px 0 8px; overflow: hidden; border-radius: 999px; background: var(--fond); }
.progress-track span { display: block; width: 12%; height: 100%; border-radius: inherit; background: var(--accent); transition: width .25s ease; }
.progress-card p { margin: 0; color: var(--muet); font-size: .84rem; }

/* L'avis de moteur : quel moteur répond, et pourquoi. Il n'apparaît que
   lorsqu'il a quelque chose à dire — un relais pris ou deux quotas épuisés. */
.progress-avis { display: none; align-items: flex-start; gap: 9px; margin-top: 11px !important;
  padding: 10px 12px; border: 1px solid var(--trait-fort); border-radius: var(--rayon-petit);
  background: var(--surface); font-size: .84rem; line-height: 1.45; }
.progress-avis.visible { display: flex; }
.progress-avis svg { flex: none; margin-top: 2px; width: 16px; height: 16px; }
.progress-avis.info { border-color: color-mix(in srgb, var(--warn) 45%, var(--trait));
  background: var(--warn-doux); color: var(--warn); }
.progress-avis.alerte { border-color: color-mix(in srgb, var(--danger) 45%, var(--trait));
  background: var(--danger-doux); color: #ffb3bb; }

.actions-grid { display: grid; gap: 12px; margin: 18px 0 26px; }
.actions-grid.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.action-tile { display: flex; width: 100%; min-height: 78px; align-items: center; gap: 13px; padding: 15px; border: 1px solid var(--trait); border-radius: 15px; background: var(--surface); color: var(--texte); text-align: left; }
.action-tile:hover { border-color: var(--accent); }
.action-tile > .lucide { width: 25px; height: 25px; color: var(--accent); }
.action-tile span { display: grid; }
.action-tile small { color: var(--muet); font-weight: 450; }

.table-list { display: grid; gap: 9px; }
.source-row, .subject-row { display: flex; align-items: center; gap: 13px; padding: 15px; border: 1px solid var(--trait); border-radius: 14px; background: var(--surface); }
.source-row { border-left: 3px solid var(--puce); }

/* ================================================================
   LA LIGNE D'UN SUJET — une ligne EST un formulaire.
   Le CSS a longtemps visé un formulaire IMBRIQUÉ dans la ligne, élément qui
   n'existe pas dans le balisage : toute la mise en grille, écran large comme
   téléphone, ne s'appliquait donc à rien. Restait le `display: flex`, où le
   nom et la couleur — chacun en `width: 100 %` par la règle générale des
   champs — s'écrasaient côte à côte sans jamais passer à la ligne. D'où une
   page illisible sur téléphone. Viser `.subject-row` DIRECTEMENT.
   Les zones nommées sont là pour ça : le balisage ne bouge pas, seule la
   disposition change d'un écran à l'autre.
   ================================================================ */
.subject-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto auto auto;
  grid-template-areas: "puce nom couleur compte valider archiver";
  align-items: center;
  gap: 10px;
  /* La couleur du sujet se voit sur toute la hauteur de sa ligne, comme pour
     une source : une pastille de 11 px ne suffit pas à repérer une ligne dans
     une liste de quarante. */
  border-left: 3px solid var(--puce);
}
.subject-row .color-dot { grid-area: puce; }
.subject-row .sujet-nom { grid-area: nom; }
.subject-row .sujet-couleur { grid-area: couleur; width: auto; }
.subject-row .sujet-compte { grid-area: compte; font-size: .82rem; white-space: nowrap; }
.subject-row .sujet-compte a { text-decoration: underline; text-underline-offset: 3px; }
.subject-row .sujet-compte a:hover { color: var(--texte); }
.subject-row .sujet-valider { grid-area: valider; }
.subject-row .sujet-archiver { grid-area: archiver; }
/* Les deux boutons n'ont qu'une icône : ils gardent la cible de 44 px du
   groupe, mais sans le rembourrage d'un bouton qui porte du texte. */
.subject-row .btn.fantome { min-width: 44px; padding-inline: 10px; }
.source-icon { display: grid; width: 43px; height: 43px; flex: 0 0 auto; place-items: center; border-radius: 12px; background: color-mix(in srgb, var(--puce) 12%, var(--fond)); color: var(--puce); }
.source-main { min-width: 0; flex: 1; }
.source-main h2 { margin: 4px 0 2px; }
.source-main p { margin: 0; }
.source-message { color: var(--danger); font-size: .82rem; }
.row-actions { display: flex; gap: 7px; }
.muted-row { opacity: .58; }
.color-dot { width: 11px; height: 11px; border-radius: 50%; background: var(--puce); }

/* ================================================================
   LES PRIORITÉS DES SUJETS. Une grille et non une ligne flex : un
   <input type="range"> a une largeur intrinsèque têtue sur iOS, et
   `minmax(0, 1fr)` est ce qui l'oblige à rétrécir au lieu de pousser
   la ligne hors de l'écran (leçon reprise du module d'origine).
   ================================================================ */
.prio-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto minmax(0, 40%) 42px;
  grid-template-areas: "puce nom compte jauge valeur" "mots mots mots mots mots";
  align-items: center;
  gap: 9px 10px;
  padding: 12px 14px;
  border: 1px solid var(--trait);
  border-left: 3px solid var(--puce);
  border-radius: 14px;
  background: var(--surface);
}
.prio-row .color-dot { grid-area: puce; }
.prio-nom { grid-area: nom; min-width: 0; overflow: hidden; font-weight: 680; text-overflow: ellipsis; white-space: nowrap; }
.prio-compte { grid-area: compte; font-size: .76rem; white-space: nowrap; }
.prio-jauge { grid-area: jauge; width: 100%; min-width: 0; min-height: 0; padding: 0; border: 0; background: transparent; accent-color: var(--accent); }
.prio-valeur {
  grid-area: valeur;
  padding: 3px 0;
  border: 1px solid var(--trait);
  border-radius: 9px;
  background: var(--fond);
  color: var(--texte);
  font-size: .84rem;
  font-weight: 780;
  text-align: center;
}
/* Une priorité à 0 ne veut pas dire « faible » mais « jamais » : elle
   s'éteint, au lieu de se fondre dans les autres valeurs basses. */
.prio-valeur.zero { border-style: dashed; color: var(--muet); }
.prio-valeur.haute { border-color: color-mix(in srgb, var(--ok) 45%, var(--trait)); color: var(--ok); }
.prio-mots { grid-area: mots; font-size: .84rem; }

@media (max-width: 900px) {
  /* Le libellé prend toute la largeur, le trio compteur/curseur/valeur passe
     dessous — sinon le nom d'un sujet se réduit à trois lettres. */
  .prio-row {
    grid-template-columns: auto minmax(0, 1fr) 42px;
    grid-template-areas: "puce nom nom" "compte jauge valeur" "mots mots mots";
  }
  .prio-nom { white-space: normal; }
}

/* Sources, thèmes et médias fiables. Les deux pages partagent la même zone
   ambre et restent des réglages passifs de l'unique recherche manuelle. */
.section-head.compact { margin: 0 0 17px; }
.source-tabs { margin-top: 0; }
.source-add-panel { margin-top: 22px; }
.source-quick-form { margin-bottom: 0; }
.source-submit { margin-top: 0; }
.source-managed { align-items: flex-start; }
.source-managed .row-actions { align-self: center; }
.source-assign { display: grid; grid-template-columns: repeat(2, minmax(130px, 1fr)); gap: 8px; margin-top: 11px; }
.source-assign select { min-height: 38px; padding-block: 6px; color: var(--texte-2); font-size: .82rem; }

.themes-panel { margin-top: 38px; scroll-margin-top: 20px; }
.theme-list { display: grid; gap: 11px; }
.theme-card { padding: 14px; border: 1px solid var(--trait); border-left: 3px solid var(--puce); border-radius: 14px; background: var(--surface-2); }
.theme-top { display: flex; align-items: center; gap: 10px; }
.theme-edit { display: grid; grid-template-columns: auto minmax(170px, 1fr) auto auto; align-items: center; gap: 9px; min-width: 0; flex: 1; }
.theme-edit input[type="color"] { width: 45px; min-height: 40px; }
.theme-edit input[name="nom"] { min-height: 40px; font-weight: 760; }
.theme-edit .icon-btn, .theme-top > form .icon-btn { width: 40px; height: 40px; }
.category-list { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; margin-top: 12px; }
.category-chip { display: inline-flex; min-height: 34px; align-items: center; gap: 5px; padding: 4px 5px 4px 11px; border: 1px solid var(--trait); border-radius: 999px; background: var(--fond-2); color: var(--texte-2); font-size: .8rem; font-weight: 700; }
.category-chip form { display: inline-flex; }
.category-chip button { display: grid; width: 27px; height: 27px; padding: 0; place-items: center; border: 0; border-radius: 50%; background: transparent; color: var(--muet); }
.category-chip button:hover { background: var(--danger-doux); color: var(--danger); }
.category-chip .lucide { width: 14px; height: 14px; }
.category-add { display: flex; align-items: center; gap: 6px; min-width: min(270px, 100%); }
.category-add input { min-height: 36px; }
.category-add .icon-btn { width: 36px; height: 36px; }
.theme-add { margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--trait); }

.tag-fieldset { margin: 0; padding: 0; border: 0; }
.tag-fieldset legend { margin-bottom: 8px; color: var(--texte-2); font-size: .9rem; font-weight: 680; }
.tag-choices { display: flex; flex-wrap: wrap; gap: 7px; }
.tag-choices label { display: inline-flex; min-height: 38px; align-items: center; gap: 7px; padding: 6px 11px; border: 1px solid var(--trait); border-radius: 999px; background: var(--fond-2); cursor: pointer; }
.tag-choices label:has(input:checked) { border-color: var(--accent); background: var(--accent-doux); color: var(--accent-2); }
.tag-choices input { width: 17px; min-height: 17px; accent-color: var(--accent); }
.trusted-hint { margin: -5px 0 0; font-size: .82rem; }
.trusted-import-panel { display: grid; grid-template-columns: minmax(0, 1fr) minmax(360px, .8fr); align-items: end; gap: 22px; }
.trusted-import-panel h2 { margin-bottom: 7px; }
.trusted-import-panel p { margin-bottom: 0; }
.trusted-import-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.trusted-import-form .btn { grid-column: 1 / -1; }
.trusted-list-head { align-items: end; }
.trusted-search { width: min(390px, 100%); }
.trusted-search input { padding-left: 40px; }
.trusted-tags button { flex: 0 0 auto; min-height: 38px; padding: 8px 12px; border: 1px solid var(--trait); border-radius: 999px; background: transparent; color: var(--muet); font-size: .84rem; font-weight: 720; }
.trusted-tags button:hover { color: var(--texte); }
.trusted-tags button.active { border-color: var(--accent); background: var(--accent-doux); color: var(--accent-2); }
.trusted-tags button span { color: var(--muet); font-size: .72rem; }
.trusted-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 11px; }
.trusted-card { display: flex; min-width: 0; min-height: 155px; flex-direction: column; justify-content: space-between; gap: 15px; padding: 16px; border: 1px solid var(--trait); border-radius: 15px; background: var(--surface); }
.trusted-card:hover { border-color: var(--trait-fort); }
.trusted-card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.trusted-card-top > div { min-width: 0; }
.trusted-card h2 { margin: 0 0 5px; overflow-wrap: anywhere; }
.trusted-card a { display: inline-flex; max-width: 100%; align-items: center; gap: 5px; overflow: hidden; color: var(--accent-2); font-size: .85rem; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; }
.trusted-card-tags { display: flex; flex-wrap: wrap; gap: 5px; }
.trusted-card[hidden] { display: none; }

.service-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.service-card { display: flex; align-items: flex-start; gap: 13px; padding: 17px; border: 1px solid var(--trait); border-radius: 15px; background: var(--surface); }
.service-card > div { min-width: 0; flex: 1; }
.service-card p { margin-bottom: 0; color: var(--texte-2); }
.service-card .icon-btn { width: 38px; height: 38px; }
.service-ico { display: grid; width: 43px; height: 43px; flex: 0 0 auto; place-items: center; border-radius: 12px; background: var(--accent-doux); color: var(--accent-2); }

.admin-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 13px; margin-bottom: 25px; }
.admin-tile { display: flex; min-height: 105px; align-items: center; gap: 14px; padding: 18px; border: 1px solid var(--trait); border-radius: var(--rayon); background: var(--surface); }
.admin-tile:hover { border-color: var(--accent); }
.admin-tile > span:nth-child(2) { display: grid; min-width: 0; flex: 1; }
.admin-tile small { color: var(--muet); }
.tile-ico { display: grid; width: 48px; height: 48px; place-items: center; border-radius: 14px; background: var(--accent-doux); color: var(--accent-2); }
.tile-ico .lucide { width: 23px; height: 23px; }

/* Un tableau large défile DANS son cadre, jamais en poussant la page. La règle
   porte sur le <div> qui l'enveloppe : un <table> ne défile pas, overflow-x n'a
   aucun effet sur un display: table. Même conteneur que .table-scroll chez les
   voisines. */
.data-table {
  max-width: 100%; overflow-x: auto; overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--trait); border-radius: 14px;
}
table { width: 100%; border-collapse: collapse; background: var(--surface); font-size: .86rem; }
th, td { padding: 11px 13px; border-bottom: 1px solid var(--trait); text-align: left; vertical-align: top; }
th { background: var(--surface-2); color: var(--muet); font-size: .73rem; letter-spacing: .06em; text-transform: uppercase; }
tbody tr:last-child td { border-bottom: 0; }

.bars { display: flex; height: 135px; align-items: end; gap: 5px; padding-top: 10px; }
.bars > div { display: flex; height: 100%; min-width: 7px; flex: 1; flex-direction: column; justify-content: end; gap: 5px; }
.bars span { width: 100%; min-height: 4px; border-radius: 4px 4px 1px 1px; background: var(--accent); }
.bars small { color: var(--muet); font-size: .6rem; text-align: center; }

.pagination { display: flex; align-items: center; justify-content: center; gap: 14px; margin-top: 24px; color: var(--muet); }

/* La page de connexion suit la même règle que les autres : son dégradé vient
   de la couleur de l'application, pas d'un bleu écrit en dur hérité d'ailleurs
   (c'est le même travers que le fond de champ bleu corrigé plus haut). */
.login-page { display: grid; min-height: 100vh; place-items: center; padding: 22px; background: radial-gradient(circle 40rem at 50% -4rem, color-mix(in srgb, var(--fruit-2) 16%, transparent), transparent), var(--fond); }
.login-box { width: min(430px, 100%); padding: clamp(23px, 6vw, 36px); border: 1px solid var(--trait); border-radius: 24px; background: var(--surface); }
.login-brand { display: flex; align-items: center; gap: 13px; margin-bottom: 23px; }
.login-brand h1 { font-size: 2.25rem; }
.login-box form { display: grid; gap: 15px; }
.error-box { text-align: center; }
.error-box .login-brand { justify-content: center; }
.error-box .notice { text-align: left; }

@media (max-width: 980px) {
  .filters { grid-template-columns: 1fr 1fr; }
  .filters .search-wrap { grid-column: 1 / -1; }
  .detail-grid { grid-template-columns: 1fr; }
  .service-grid { grid-template-columns: 1fr; }
  .trusted-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .trusted-import-panel { grid-template-columns: 1fr; }
}

/* ================================================================
   MODE APPLICATION (≤ 900px) : topbar fixe + pastille d'onglets
   flottante opaque. Grammaire commune à /srv/annuaire, /srv/contact,
   /srv/agenda et /srv/play — même seuil, mêmes mesures, mêmes gestes.
   La barre du bas est une pastille d'encre OPAQUE, détachée des bords,
   sans bordure ni flou, dont les onglets sont strictement identiques :
   la seule destination mise en avant est la page ouverte. Ne pas y
   réintroduire de trait, d'ombre ni de backdrop-filter.
   ================================================================ */
@media (max-width: 900px) {
  .layout { display: block; }
  .sidebar { display: none; }

  .topbar {
    display: flex; align-items: center; gap: 12px;
    position: fixed; top: 0; left: 0; right: 0; z-index: 60;
    background: color-mix(in srgb, var(--fond) 86%, transparent);
    -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
    border-bottom: 1px solid var(--trait);
    padding: 10px 16px;
    padding-top: calc(10px + var(--safe-top));
    padding-left: calc(16px + var(--safe-left));
    padding-right: calc(16px + var(--safe-right));
  }
  /* La marque reprend la taille du groupe (34 px) : c'est elle qui donne sa
     hauteur à la barre, et une barre plus haute que chez les voisines se
     verrait au premier coup d'œil. */
  .topbar .brand-ico { margin: 0; width: 34px; height: 34px; border-radius: 11px; }
  .topbar .brand-ico svg { width: 21px; height: 21px; }
  .topbar-title { flex: 1; font-weight: 800; font-size: 17px; letter-spacing: -.2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* Bouton texte « Admin » (sans icône) : même convention que l'Annuaire. */
  .topbar-admin {
    display: inline-flex; align-items: center; min-height: 34px;
    padding: 6px 14px; border-radius: 999px;
    background: rgba(255, 255, 255, .07); border: 1px solid var(--trait);
    color: var(--texte); font-size: 13.5px; font-weight: 700; letter-spacing: -.01em;
    white-space: nowrap; flex: none;
  }
  .topbar-admin:hover { text-decoration: none; border-color: var(--accent); }
  .topbar-admin.on {
    background: var(--accent-doux); color: var(--accent-2);
    border-color: color-mix(in srgb, var(--accent) 45%, var(--trait));
  }
  .topbar-bell { position: relative; display: inline-flex; padding: 4px 2px; color: var(--texte); flex: none; }
  .topbar-bell .lucide { width: 22px; height: 22px; }
  .topbar-bell:hover { text-decoration: none; }

  .tabbar {
    display: flex; align-items: stretch; gap: 6px;
    position: fixed; z-index: 60;
    left: calc(12px + var(--safe-left));
    right: calc(12px + var(--safe-right));
    bottom: calc(4px + var(--safe-bottom));
    transform: translateY(15px);
    padding: 7px;
    background: var(--tabbar-base);
    border-radius: 26px;
  }
  /* Sous la barre, la safe area devient un aplat opaque : le contenu
     s'arrête visuellement avant les bords arrondis. */
  body::after {
    content: ""; position: fixed; z-index: 59;
    left: 0; right: 0; bottom: 0;
    height: calc(4px + var(--safe-bottom));
    pointer-events: none; background: var(--tabbar-base);
  }
  .tab {
    position: relative; flex: 1 1 0; min-width: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 6px; min-height: 66px; padding: 10px 2px;
    color: var(--muet); text-decoration: none; cursor: pointer;
    font-weight: 700; line-height: 1; letter-spacing: -.01em;
    border-radius: 20px; background: transparent;
    -webkit-user-select: none; user-select: none;
    transition: background .16s ease, color .16s ease, transform .1s ease;
  }
  .tab:hover { text-decoration: none; }
  .tab:active { transform: scale(.95); }
  .tab .t-ico { display: flex; align-items: center; justify-content: center; }
  .tab .t-ico .lucide { width: 25px; height: 25px; }
  .tab .t-lbl { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
  .tab.on { background: var(--accent-doux); color: var(--accent-2); font-weight: 800; }

  .content {
    width: 100%; margin-left: 0; min-height: 0;
    padding: calc(64px + var(--safe-top)) 14px calc(96px + var(--safe-bottom));
    padding-left: calc(14px + var(--safe-left));
    padding-right: calc(14px + var(--safe-right));
  }
  .login-box { margin: max(8vh, calc(24px + var(--safe-top))) auto; }
}

@media (max-width: 740px) {
  :root { --rayon: 16px; }
  h1 { font-size: 2.15rem; }
  .page-head { align-items: flex-start; flex-direction: column; margin-bottom: 19px; }
  /* Un titre de section et son bouton passent l'un sous l'autre plutôt que de
     forcer la largeur de la page. */
  .section-head { flex-wrap: wrap; }
  .page-head > form, .page-head > .btn, .head-actions { width: 100%; }
  .page-head > form .btn, .page-head > .btn, .head-actions .btn { flex: 1; }
  .notice { margin-bottom: 18px; }
  .stats-row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .stat { min-height: 108px; padding: 13px 14px 14px; gap: 12px; }
  .stat-val { font-size: 1.6rem; }
  .stat-tete { font-size: .74rem; }
  .filters { grid-template-columns: 1fr; }
  .filters .search-wrap { grid-column: auto; }
  .filters .btn { width: 100%; }
  input, select, textarea { font-size: 16px; }
  .form-grid { grid-template-columns: 1fr; }
  .form-grid .full { grid-column: auto; }
  .compact-form { align-items: stretch; flex-direction: column; }
  .carte { padding: 16px; }
  .actu-card { flex-direction: column; }
  .actu-visuel { width: 100%; aspect-ratio: 16 / 9; }
  .carte-illustree { flex-direction: column; }
  .article-hero { aspect-ratio: 16 / 9; }
  .carte-actions .btn { padding-inline: 12px; }
  .piste-card { align-items: flex-start; }
  .date-puce { width: 50px; height: 57px; }
  .actions-grid.two, .admin-grid { grid-template-columns: 1fr; }
  .source-row { align-items: flex-start; }
  .source-icon { display: none; }
  .row-actions { flex-direction: column; }
  .source-assign { grid-template-columns: 1fr; }
  .theme-top { align-items: flex-start; }
  .theme-edit { grid-template-columns: auto minmax(0, 1fr) auto; }
  .theme-edit .muted { grid-column: 2 / -1; }
  .category-add { width: 100%; }
  .category-add input { min-width: 0; }
  .trusted-import-form { grid-template-columns: 1fr; }
  .trusted-import-form .btn { grid-column: auto; }
  .trusted-list-head { align-items: stretch; }
  .trusted-search { width: 100%; }
  .trusted-grid { grid-template-columns: 1fr; }
  /* SUR TÉLÉPHONE, la ligne se plie en trois : le nom sur toute la largeur —
     c'est le seul champ qu'on vient vraiment modifier —, puis la couleur avec
     les deux actions, puis les compteurs. Rien ne se chevauche et rien ne
     descend sous la taille où l'on peut le lire. */
  .subject-row {
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-areas:
      "puce    nom     nom     nom"
      "couleur couleur valider archiver"
      "compte  compte  compte  compte";
    gap: 11px 9px;
  }
  .subject-row .sujet-couleur { width: 100%; }
  .subject-row .sujet-compte { justify-self: start; white-space: normal; }
  .service-card { padding: 14px; }
  .service-ico { display: none; }
  .facts > div { grid-template-columns: 1fr; gap: 4px; }
  .action-bar { align-items: stretch; }
  .action-bar form { flex: 1 1 auto; }
  .action-bar .btn { width: 100%; }
  .danger-zone { align-items: stretch; flex-direction: column; }
  .danger-zone label, .danger-zone input[type="number"], .danger-zone .btn { width: 100%; }
  .bars { height: 105px; }
  .bars small { display: none; }
  .pagination { flex-wrap: wrap; }
}

/* ================================================================
   iPhone étroit (≤ 380px) : la pastille et la topbar se resserrent —
   même réglage que dans le reste du groupe.
   ================================================================ */
@media (max-width: 380px) {
  .tabbar { gap: 4px; padding: 6px; }
  .tab { min-height: 62px; gap: 5px; border-radius: 18px; }
  .tab .t-ico .lucide { width: 23px; height: 23px; }
  .tab .t-lbl { font-size: 12px; }
  .topbar-admin { padding: 6px 11px; font-size: 13px; }
  .topbar { gap: 9px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; transition-duration: .01ms !important; }
}

/* ================================================================
   LES COMPOSANTS PROPRES À SANTÉ
   Quatre, et pas un de plus : la ligne de saisie d'une mesure, la
   frise des derniers jours, le grand score du jour et la ligne de
   réglage d'une mesure. Tout le reste vient de la grammaire commune
   du groupe (.stat, .jauge, .carte, .panel, .badge…).
   Règle absolue héritée : AUCUN box-shadow, nulle part.
   ================================================================ */

/* LE SCORE DU JOUR. Un grand nombre, sa jauge, et ce qu'il vaut dit en
   toutes lettres — la couleur ne porte jamais l'information seule.
   L'encre du nombre reste de l'encre : c'est la jauge et l'icône qui
   portent l'état, sinon « 72 » se lirait comme une alarme. */
.score-jour {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 20px;
  margin: 22px 0 26px;
  padding: 20px 22px;
  border: 1px solid var(--trait);
  border-radius: var(--rayon);
  background: linear-gradient(158deg, var(--surface-2), var(--surface) 62%);
}
.score-rond {
  display: grid;
  width: 96px;
  height: 96px;
  place-items: center;
  align-content: center;
  border: 2px solid color-mix(in srgb, var(--jauge-teinte, var(--accent)) 55%, var(--trait));
  border-radius: 50%;
  background: color-mix(in srgb, var(--jauge-teinte, var(--accent)) 12%, var(--fond));
}
.score-rond strong { font-size: 2.1rem; font-weight: 800; line-height: 1; letter-spacing: -.04em; }
.score-rond small { margin-top: 3px; color: var(--muet); font-size: .68rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }
.score-rond.bon { --jauge-teinte: var(--ok); }
.score-rond.moyen { --jauge-teinte: var(--warn); }
.score-rond.mauvais { --jauge-teinte: var(--danger); }
.score-rond.vide { --jauge-teinte: var(--muet); }
.score-corps > p { margin: 0 0 10px; color: var(--texte-2); }
.score-corps .jauge { margin-bottom: 9px; }

/* LA FRISE des derniers jours : un bâton par jour, sa hauteur est le score.
   Un jour non renseigné n'est PAS un bâton à zéro — c'est un trait en
   pointillé au ras du sol. Les confondre ferait passer un dimanche sans
   saisie pour la pire journée de la semaine. */
.frise { display: flex; height: 78px; align-items: end; gap: 4px; margin: 4px 0 0; }
.frise > a, .frise > span {
  position: relative;
  display: flex;
  min-width: 6px;
  height: 100%;
  flex: 1;
  flex-direction: column;
  justify-content: end;
}
.frise i {
  display: block;
  width: 100%;
  min-height: 5px;
  border-radius: 4px 4px 2px 2px;
  background: color-mix(in srgb, var(--jauge-teinte, var(--accent)) 85%, transparent);
}
.frise .bon { --jauge-teinte: var(--ok); }
.frise .moyen { --jauge-teinte: var(--warn); }
.frise .mauvais { --jauge-teinte: var(--danger); }
.frise .vide i { min-height: 3px; border: 1px dashed var(--trait-fort); background: transparent; }
.frise-legende { display: flex; justify-content: space-between; margin-top: 7px; color: var(--muet); font-size: .72rem; }

/* LA LIGNE DE SAISIE d'une mesure. Une grille et non une ligne flex : un champ
   de nombre a une largeur intrinsèque têtue sur iOS, et `minmax(0, 1fr)` est
   ce qui l'oblige à rétrécir au lieu de pousser la page hors de l'écran. */
.mesure-saisie {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) 128px;
  grid-template-areas: "ico nom champ" "ico cible jauge";
  align-items: center;
  gap: 6px 13px;
  padding: 13px 15px;
  border: 1px solid var(--trait);
  border-left: 3px solid var(--puce);
  border-radius: 14px;
  background: var(--surface);
}
.mesure-saisie + .mesure-saisie { margin-top: 9px; }
.mesure-saisie:focus-within { border-color: color-mix(in srgb, var(--accent) 55%, var(--trait)); }
.mesure-ico {
  grid-area: ico;
  display: grid;
  width: 40px;
  height: 40px;
  place-items: center;
  border-radius: 12px;
  background: color-mix(in srgb, var(--puce) 13%, var(--fond));
  color: var(--puce);
}
.mesure-nom { grid-area: nom; min-width: 0; font-weight: 700; }
.mesure-cible { grid-area: cible; color: var(--muet); font-size: .78rem; }
.mesure-champ { grid-area: champ; }
.mesure-champ input, .mesure-champ select { text-align: center; font-weight: 700; }
.mesure-jauge { grid-area: jauge; }
.mesure-aide { color: var(--muet); font-size: .78rem; font-weight: 450; }

/* LA LIGNE DE RÉGLAGE d'une mesure (/mesures). Elle porte son nom, sa cible,
   son sens et son poids — c'est la page qui tient l'invariant « aucune cible
   dans le code », et elle doit se lire d'un coup d'œil. */
.mesure-reglage {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) auto auto;
  grid-template-areas: "ico nom etat outils" "ico faits faits faits";
  align-items: center;
  gap: 8px 12px;
  padding: 13px 15px;
  border: 1px solid var(--trait);
  border-left: 3px solid var(--puce);
  border-radius: 14px;
  background: var(--surface);
}
.mesure-reglage + .mesure-reglage { margin-top: 9px; }
.mesure-reglage.inactive { opacity: .55; }
.mesure-reglage .mesure-ico { grid-area: ico; width: 36px; height: 36px; }
.mesure-reglage .r-nom { grid-area: nom; min-width: 0; font-weight: 700; }
.mesure-reglage .r-etat { grid-area: etat; }
.mesure-reglage .r-outils { grid-area: outils; display: flex; gap: 6px; }
.mesure-reglage .r-outils form { display: flex; }
.mesure-reglage .r-outils .btn { min-width: 40px; padding-inline: 9px; }
.mesure-reglage .r-faits { grid-area: faits; display: flex; flex-wrap: wrap; gap: 6px 14px; color: var(--muet); font-size: .78rem; }
.mesure-reglage .r-faits span { display: inline-flex; align-items: center; gap: 5px; }

@media (max-width: 740px) {
  .score-jour { grid-template-columns: 1fr; gap: 15px; padding: 17px; }
  .score-rond { width: 84px; height: 84px; }
  .mesure-saisie {
    grid-template-columns: 40px minmax(0, 1fr) 104px;
  }
  .mesure-reglage {
    grid-template-columns: 36px minmax(0, 1fr) auto;
    grid-template-areas: "ico nom etat" "ico outils outils" "faits faits faits";
  }
  .mesure-reglage .r-outils { justify-content: flex-start; }
}
