/* Application de collecte Nguiemboo — deux thèmes.
   Mode CLAIR « Aurore claire » par défaut (:root / [data-theme="light"]),
   mode SOMBRE premium conservé à l'identique sous [data-theme="dark"].
   Le thème est posé sur <html data-theme="…"> par un script en <head>
   (aucun flash au chargement). Toutes les surfaces passent par des variables. */
:root, :root[data-theme="light"] {
  color-scheme: light;
  /* Largeur maximale du contenu (conteneur .wrap + pied). Élargie pour occuper
     davantage l'espace horizontal sur PC (marges latérales fortement réduites) ;
     sur les écrans < cette valeur, le contenu reste pleinement fluide (mobile intact). */
  --wrap-max: 1320px;
  /* Polices (voir fonts.css, embarquées hors-ligne). Titres = display géométrique
     (Space Grotesk) ; logo + étiquettes techniques (version, tags, URL) = mono
     (IBM Plex Mono) ; corps de texte = Noto Sans (lisible, couverture ngiemboon). */
  --font-body: "Noto Sans", "DejaVu Sans", system-ui, sans-serif;
  --font-display: "Space Grotesk", "Noto Sans", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "Cascadia Code", monospace;
  --bg: #f4f8fc;
  --panel: #ffffff;
  --panel2: #eef4fa;
  --border: #d4e0ec;
  --text: #0e1f2c;
  --muted: #445468;
  --label: #2f4256;
  --cyan: #0e7490;
  --green: #047857;
  --blue: #2560d8;
  --gold: #a06e12;
  --violet: #6d4fd0;
  --red: #dc2626;
  /* Boutons de NAVIGATION (ouvrent une vue/page) : or DOUX identique dans les deux
     thèmes (celui du mode sombre) + encre foncée → même ambiance en clair et sombre
     (ne PAS intensifier en clair, ça casse le design). Le `:root` couvre les 2 thèmes. */
  --nav-gold: #e5c07b;
  --nav-ink: #06121a;
  --bg-grad: radial-gradient(1100px 560px at 50% -12%, #e7f2fb 0%, var(--bg) 60%);
  /* Motif Ndop IDENTIQUE au cadre du QR (losange laiton #e2b56f + losange cyan
     #2ad4ee + points), utilisé en fond sur toute l'app — grand (tuile 156) et
     DISCRET (décoration de fond). MÊME transparence partout : flyer, PDF, PNG,
     app clair ET sombre (aucun ajustement par thème). */
  --lattice-img: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='132' height='132' viewBox='0 0 132 132'><g fill='none' stroke='%23c98a2e' stroke-opacity='0.30' stroke-width='1.4'><path d='M66 4 128 66 66 128 4 66Z'/></g><g fill='none' stroke='%230e97b8' stroke-opacity='0.26' stroke-width='1.2'><path d='M66 32 100 66 66 100 32 66Z'/></g><g fill='none' stroke='%23c98a2e' stroke-opacity='0.20' stroke-width='0.9'><path d='M66 50 82 66 66 82 50 66Z'/></g><circle cx='66' cy='66' r='2.1' fill='%23c98a2e' fill-opacity='0.40'/><circle cx='0' cy='66' r='2.1' fill='%230e97b8' fill-opacity='0.30'/><circle cx='132' cy='66' r='2.1' fill='%230e97b8' fill-opacity='0.30'/><circle cx='66' cy='0' r='2.1' fill='%230e97b8' fill-opacity='0.30'/><circle cx='66' cy='132' r='2.1' fill='%230e97b8' fill-opacity='0.30'/></svg>");
  --header-bg: linear-gradient(180deg, rgba(255,255,255,0.93), rgba(238,244,250,0.86));
  --card-bg: linear-gradient(180deg, rgba(255,255,255,.95), rgba(240,246,252,.98)), var(--panel);
  --footer-bg: linear-gradient(180deg, rgba(238,244,250,.82), rgba(224,235,246,.94));
  --toast-bg: #ffffff;
  --tip-bg: linear-gradient(180deg, rgba(6,182,212,.12), rgba(255,255,255,.94));
  --slider-off: #cdd9e6;
  --placeholder: #7a89a0;
  --hairline: rgba(18,34,47,.08);
  --shadow-card: 0 16px 40px rgba(31,54,77,.13);
  --shadow-drop: 0 18px 44px rgba(31,54,77,.22);
  --card-sheen: rgba(255,255,255,.7);          /* reflet de verre en haut des cartes (clair) */
  --card-inner: rgba(18,34,47,.05);            /* liseré interne bas, donne du relief */
  --aurora-a: rgba(6,182,212,.22);
  --aurora-b: rgba(16,185,129,.19);
  --aurora-c: rgba(160,110,18,.13);
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0a0e14;
  --panel: #12181f;
  --panel2: #161d26;
  --border: #253041;
  --text: #e9f0f6;
  --muted: #8b97a6;
  --label: #a9b6c5;
  --cyan: #22d3ee;
  --green: #34d399;
  --blue: #4f8cff;
  --gold: #e5c07b;
  --violet: #a78bfa;
  --red: #f87171;
  --share-ico-bg: #ffffff;              /* icônes réseaux sur fond BLANC en sombre (logos bien visibles) */
  --share-ico-bd: rgba(0,0,0,.14);
  --bg-grad: radial-gradient(1100px 560px at 50% -12%, #12222e 0%, var(--bg) 60%);
  /* Thème sombre : même motif, mais alpha RÉDUIT — sur fond sombre les couleurs
     cyan/laiton ressortent bien plus qu'en clair ; on baisse pour une discrétion
     PERÇUE équivalente au thème clair. */
  --lattice-img: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='132' height='132' viewBox='0 0 132 132'><g fill='none' stroke='%23e5c07b' stroke-opacity='0.22' stroke-width='1.4'><path d='M66 4 128 66 66 128 4 66Z'/></g><g fill='none' stroke='%2322d3ee' stroke-opacity='0.19' stroke-width='1.2'><path d='M66 32 100 66 66 100 32 66Z'/></g><g fill='none' stroke='%23e5c07b' stroke-opacity='0.14' stroke-width='0.9'><path d='M66 50 82 66 66 82 50 66Z'/></g><circle cx='66' cy='66' r='2.1' fill='%23e5c07b' fill-opacity='0.30'/><circle cx='0' cy='66' r='2.1' fill='%2322d3ee' fill-opacity='0.22'/><circle cx='132' cy='66' r='2.1' fill='%2322d3ee' fill-opacity='0.22'/><circle cx='66' cy='0' r='2.1' fill='%2322d3ee' fill-opacity='0.22'/><circle cx='66' cy='132' r='2.1' fill='%2322d3ee' fill-opacity='0.22'/></svg>");
  --header-bg: linear-gradient(180deg, rgba(20,27,36,0.88), rgba(12,17,24,0.8));
  --card-bg: linear-gradient(180deg, rgba(30,38,48,.78), rgba(18,24,31,.85)), var(--panel);
  --footer-bg: linear-gradient(180deg, rgba(18,24,31,.7), rgba(9,12,17,.92));
  --toast-bg: #0d1420;
  --tip-bg: linear-gradient(180deg, rgba(34,211,238,.08), rgba(18,24,31,.6));
  --slider-off: #1f2733;
  --placeholder: #61708280;
  --hairline: rgba(255,255,255,.05);
  --shadow-card: 0 16px 40px rgba(0,0,0,0.4);
  --shadow-drop: 0 16px 40px rgba(0,0,0,.6);
  --card-sheen: rgba(255,255,255,.10);         /* reflet de verre en haut des cartes (sombre) */
  --card-inner: rgba(0,0,0,.35);               /* liseré interne bas, donne du relief */
  --aurora-a: rgba(34,211,238,.30);
  --aurora-b: rgba(52,211,153,.22);
  --aurora-c: rgba(229,192,123,.16);
}
* { box-sizing: border-box; }
/* Motif africain en fond global (couche fixe, derrière tout le contenu), très discret.
   Variante claire par défaut, plus marquée en sombre (où il se marie mieux). */
/* Motif ambiant en fond de page : couche ABSOLUE couvrant tout le document (pas le
   viewport) → elle défile solidairement avec le contenu, à la même vitesse. */
.bg-motif { position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: url("icons/bg-pattern-light.jpg") center top / 520px auto repeat; opacity: .17; }
:root[data-theme="dark"] .bg-motif { background-image: url("icons/bg-pattern-dark.jpg"); opacity: .40; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .bg-motif { background-image: url("icons/bg-pattern-dark.jpg"); opacity: .34; } }
/* Trame plus VIVANTE : une lueur diagonale (cyan→vert) balaie lentement le motif Ndop, comme un
   reflet qui glisse sur un tissu. Purement décorative (z-index -1), GPU (transform), n'altère ni
   la lisibilité ni le fond. Reste visible sur mobile (règle décor mobile) ; gelée clavier ouvert
   et sous prefers-reduced-motion. */
.bg-motif::after {
  content: ""; position: absolute; inset: -30% -30%; pointer-events: none;
  background: linear-gradient(112deg, transparent 43%,
    color-mix(in srgb, var(--cyan) 16%, transparent) 49%,
    color-mix(in srgb, var(--green) 12%, transparent) 53%, transparent 61%);
  animation: motif-sweep 19s linear infinite; will-change: transform;
}
@keyframes motif-sweep { 0% { transform: translate3d(-58%, 0, 0); } 100% { transform: translate3d(58%, 0, 0); } }
body.kb-docked .bg-motif::after { animation: none; }
@media (prefers-reduced-motion: reduce) { .bg-motif::after { animation: none; } }

/* Garde-fou anti-défilement HORIZONTAL : `overflow-x: clip` borne la largeur au viewport
   sans créer de conteneur de défilement (contrairement à `hidden`), donc il n'altère PAS le
   header collant `position: sticky`. Empêche tout léger débord latéral (décor, marge, arrondi). */
html { overflow-x: clip; }
body {
  margin: 0;
  overflow-x: clip;
  max-width: 100%;
  /* Fond = MOTIF africain (Ndop/Bogolan) via la couche fixe .bg-motif (clair ET sombre) ;
     ici on ne garde que l'aurore d'ambiance + le dégradé de base (la trame losange est retirée). */
  background:
    radial-gradient(54vmax 34vmax at 50% -3%, var(--aurora-c), transparent 62%),
    var(--bg-grad);
  color: var(--text);
  font-family: var(--font-body);
  /* Footer TOUJOURS ancré en bas : body en colonne pleine hauteur, le <main>
     grandit pour occuper l'espace restant → le footer se cale au bas de l'écran
     sur les pages courtes, et suit le contenu sur les pages longues. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  /* Ancre la couche de motif (.bg-motif) : elle couvre toute la hauteur du document
     et défile AVEC le contenu (solidaires, même vitesse). */
  position: relative;
}
/* Mobile / tablette : trame Ndop ATTÉNUÉE (opacités ~÷2) pour qu'elle ne soit pas
   dominante sur petit écran. On ne redéfinit QUE --lattice-img, rien d'autre. */
@media (max-width: 1024px) {
  :root, :root[data-theme="light"] {
    --lattice-img: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='132' height='132' viewBox='0 0 132 132'><g fill='none' stroke='%23c98a2e' stroke-opacity='0.15' stroke-width='1.4'><path d='M66 4 128 66 66 128 4 66Z'/></g><g fill='none' stroke='%230e97b8' stroke-opacity='0.13' stroke-width='1.2'><path d='M66 32 100 66 66 100 32 66Z'/></g><g fill='none' stroke='%23c98a2e' stroke-opacity='0.10' stroke-width='0.9'><path d='M66 50 82 66 66 82 50 66Z'/></g><circle cx='66' cy='66' r='2.1' fill='%23c98a2e' fill-opacity='0.20'/><circle cx='0' cy='66' r='2.1' fill='%230e97b8' fill-opacity='0.15'/><circle cx='132' cy='66' r='2.1' fill='%230e97b8' fill-opacity='0.15'/><circle cx='66' cy='0' r='2.1' fill='%230e97b8' fill-opacity='0.15'/><circle cx='66' cy='132' r='2.1' fill='%230e97b8' fill-opacity='0.15'/></svg>");
  }
  :root[data-theme="dark"] {
    --lattice-img: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='132' height='132' viewBox='0 0 132 132'><g fill='none' stroke='%23e5c07b' stroke-opacity='0.11' stroke-width='1.4'><path d='M66 4 128 66 66 128 4 66Z'/></g><g fill='none' stroke='%2322d3ee' stroke-opacity='0.10' stroke-width='1.2'><path d='M66 32 100 66 66 100 32 66Z'/></g><g fill='none' stroke='%23e5c07b' stroke-opacity='0.07' stroke-width='0.9'><path d='M66 50 82 66 66 82 50 66Z'/></g><circle cx='66' cy='66' r='2.1' fill='%23e5c07b' fill-opacity='0.15'/><circle cx='0' cy='66' r='2.1' fill='%2322d3ee' fill-opacity='0.11'/><circle cx='132' cy='66' r='2.1' fill='%2322d3ee' fill-opacity='0.11'/><circle cx='66' cy='0' r='2.1' fill='%2322d3ee' fill-opacity='0.11'/><circle cx='66' cy='132' r='2.1' fill='%2322d3ee' fill-opacity='0.11'/></svg>");
  }
}

/* Texte d'intro des langues : CALLOUT bien en évidence (bordure dorée, fond teinté,
   halo lumineux) et texte plus grand/contrasté, pour être remarqué et lu. */
.hub-vision{ margin-top:10px; font-size:1rem; line-height:1.55;
  color: color-mix(in srgb, var(--text) 82%, var(--muted));
  padding:16px 18px; border-radius:16px;
  border:1.5px solid color-mix(in srgb, var(--gold) 55%, var(--border));
  background:
    radial-gradient(130% 130% at 0% 0%, color-mix(in srgb, var(--gold) 16%, transparent), transparent 60%),
    linear-gradient(120deg, rgba(226,181,111,.10), rgba(34,211,238,.05) 72%), var(--card-bg);
  box-shadow: inset 0 1px 0 var(--card-sheen), 0 0 26px -8px var(--gold); }
.hub-vision b{ color:var(--text); font-weight:800; }

/* --- Barre supérieure --- */
/* Header en GRILLE 2 niveaux (max), identique PC / mobile / tablette :
   ligne 1 = marque (gauche) + méta état/version/langue/thème (droite) ;
   ligne 2 = boutons de navigation (avec texte). */
.topbar {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  /* Grand écart vertical logo → boutons, petite marge boutons → bordure du bas :
     les lignes de boutons descendent sous le logo et se calent près du bas. */
  gap: 18px 12px;
  padding: 12px clamp(14px, 4vw, 36px) 6px;
  border-bottom: 1px solid var(--border);
  /* Header en verre : fond SEMI-TRANSPARENT posé sur son PROPRE motif (plus dense que le
     body → le header se distingue) + flou marqué. Variante sombre plus bas. */
  background: var(--header-bg), url("icons/bg-pattern-light.jpg") center top / 240px auto repeat;
  backdrop-filter: blur(18px) saturate(1.3);
  -webkit-backdrop-filter: blur(18px) saturate(1.3);
  position: sticky; top: 0; z-index: 20;
}
:root[data-theme="dark"] .topbar { background: var(--header-bg), url("icons/bg-pattern-dark.jpg") center top / 240px auto repeat; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .topbar { background: var(--header-bg), url("icons/bg-pattern-dark.jpg") center top / 240px auto repeat; } }
.brand { grid-column: 1; grid-row: 1; display: flex; align-items: center; gap: 14px; position: relative; }
/* En-tête cinématique : aurore douce (cyan↔vert) qui dérive derrière la marque, posée
   entre le verre et le texte. Purement décorative, gelée sur mobile + prefers-reduced-motion. */
.brand::before {
  content: ""; position: absolute; z-index: -1; inset: -16px -44px -20px -28px; pointer-events: none;
  background:
    radial-gradient(58% 140% at 18% 50%, color-mix(in srgb, var(--cyan) 46%, transparent), transparent 70%),
    radial-gradient(54% 140% at 52% 42%, color-mix(in srgb, var(--green) 36%, transparent), transparent 72%),
    radial-gradient(48% 130% at 82% 58%, color-mix(in srgb, var(--gold) 26%, transparent), transparent 74%);
  filter: blur(17px); opacity: .7; border-radius: 44px;
  animation: ngBrandAurora 8s ease-in-out infinite;
}
@keyframes ngBrandAurora {
  0%, 100% { transform: translateX(-6px) scale(1);     opacity: .55; }
  50%      { transform: translateX(16px) scale(1.12);  opacity: 1; }
}
.chips-meta { grid-column: 3; grid-row: 1; justify-self: end; }
.chips-nav  { grid-column: 1 / -1; grid-row: 2; }
.brand-mark {
  width: 60px; height: 60px; display: block; border-radius: 16px;
  box-shadow: 0 0 10px rgba(34,211,238,0.3), 0 6px 16px rgba(0,0,0,0.4);
}
.brand-mark img { width: 100%; height: 100%; display: block; border-radius: 16px; }
.brand-txt h1 { margin: 0; font-size: 2.1rem;
  font-family: var(--font-mono); font-weight: 600; letter-spacing: -.02em; }
.brand-txt h1 {
  background: linear-gradient(100deg, #eafcff 0%, var(--cyan) 45%, var(--green) 100%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: var(--cyan);
}
/* « · Collecte » : nettement plus petit que « LANGIAL » (qui domine). */
.brand-sub { -webkit-text-fill-color: var(--green); color: var(--green); font-weight: 700; font-size: .5em; }
/* En clair, l'amorce near-white du dégradé du titre serait invisible : on part
   directement du cyan pour garder un titre lisible et coloré. */
:root[data-theme="light"] .brand-txt h1 {
  background: linear-gradient(100deg, var(--cyan) 0%, var(--green) 100%);
  -webkit-background-clip: text; background-clip: text;
}
.tagline { margin: 2px 0 0; color: var(--muted); font-size: .78rem; }
.chips-nav, .chips-meta { display: flex; align-items: center; }
/* Nav resserrée (H et V) pour densifier et remplir la place libre en bout de ligne.
   Sur grand écran : groupée à gauche, gaps uniformes, la cloche (dernier bouton
   de la 1re ligne) juste après « Aide ». Sur téléphone (≤560px, plus bas) : la
   1re ligne est répartie UNIFORMÉMENT (space-between) pour remplir la largeur. */
.chips-nav  { gap: 6px 6px; flex-wrap: wrap; }
/* Saut de ligne dur APRÈS la cloche : actif UNIQUEMENT sur téléphone (réactivé
   dans le bloc ≤560px). Sur PC/tablette il est neutralisé (display:none) → tous
   les boutons tiennent sur une seule ligne et ne basculent à la ligne suivante
   que s'ils débordent réellement (wrap naturel), sans mise en page mobile. */
.chips-break { display: none; margin: 0; padding: 0; border: 0; }
/* Méta (état) : les deux pastilles « en ligne » / « Drive : prêt » restent TOUJOURS
   sur une seule ligne (jamais empilées) ; leur taille est réduite si besoin. */
.chips-meta { gap: 6px 7px; flex-wrap: nowrap; }
.chips-meta .chip { white-space: nowrap; }
/* Outils (version, EN, thème) : sous-groupe poussé à DROITE de la ligne de nav.
   margin-left:auto le décolle des boutons de nav ; avec le wrap, s'il n'y a plus
   la place il bascule sur la ligne suivante en restant collé à droite. */
.chips-tools { display: flex; gap: 6px; align-items: center; margin-left: auto; }
.chip {
  font-size: .72rem; padding: 5px 10px; border-radius: 999px;
  border: 1px solid var(--border); color: var(--muted);
  /* Matériau verre commun à TOUTES les pilules (reflet interne + légère profondeur) →
     jamais « plat » au repos, cohérent avec les cadres. */
  background-color: var(--panel);
  background-image: linear-gradient(180deg, rgba(255,255,255,.08), rgba(255,255,255,0));
  box-shadow: inset 0 1px 0 var(--card-sheen), 0 2px 6px -4px rgba(0,0,0,.38);
  white-space: nowrap;
}
/* Un display (flex) posé ailleurs écrasait l'attribut [hidden] → un chip « hidden »
   restait visible (sélecteur de langue, « Mon profil »…). On rend la main à [hidden]. */
.chip[hidden] { display: none !important; }
.chip--on { color: var(--green); font-weight: 700; border-color: currentColor;
  box-shadow: 0 0 12px -2px currentColor, 0 0 10px rgba(52,211,153,.16) inset; }
/* Pastille « live » qui clignote devant l'état (en ligne / Drive prête) */
.chip--on::before {
  content: ""; display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  margin-right: 7px; vertical-align: middle; background: currentColor;
  box-shadow: 0 0 8px 1px currentColor; animation: ngLiveDot 1.5s ease-in-out infinite;
}
@keyframes ngLiveDot {
  0%, 100% { opacity: 1; box-shadow: 0 0 9px 1px currentColor; }
  50%      { opacity: .4; box-shadow: 0 0 3px 0 currentColor; }
}
.chip--off { color: var(--red); border-color: rgba(248,113,113,.5); }
/* Pastille VERSION en retard (mise à jour disponible) : décorée comme les autres
   pastilles (dot clignotant + halo), mais en ROUGE (à jour = verte via .chip--on). */
#app-ver.chip--off { border-color: currentColor;
  box-shadow: 0 0 12px -2px currentColor, 0 0 10px rgba(248,113,113,.16) inset; }
#app-ver.chip--off::before {
  content: ""; display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  margin-right: 7px; vertical-align: middle; background: currentColor;
  box-shadow: 0 0 8px 1px currentColor; animation: ngLiveDot 1.5s ease-in-out infinite;
}
/* Les 3 pastilles d'état (version, en ligne, DB) : taille réduite ET hauteur IDENTIQUE
   (line-height fixe → la police mono de la version ne la rend plus plus haute). */
.chips-meta .chip { font-size: .66rem; line-height: 1.25; }
.chip--ghost { border-style: dashed; }
/* Bascule de langue en CAPSULE FR|EN (PC + mobile) : la moitié de la langue ACTIVE
   est VERTE, l'autre grisée ; l'attribut data-active (posé au chargement) inverse les
   couleurs à chaque changement de langue. Largeur suffisante pour lire FR et EN. */
.lang-switch { padding: 0; overflow: hidden; display: inline-flex; align-items: stretch;
  border: 1px solid var(--border); border-radius: 999px; line-height: 1; cursor: pointer; }
.lang-switch .lang-seg { display: inline-flex; align-items: center; justify-content: center;
  min-width: 2.4ch; padding: 4px 9px; font-weight: 800; font-size: .72rem; letter-spacing: .04em;
  color: var(--muted); background: color-mix(in srgb, var(--muted) 12%, var(--panel));
  transition: background .16s ease, color .16s ease; }
.lang-switch .lang-seg[data-seg="fr"] { border-right: 1px solid var(--border); }
.lang-switch[data-active="fr"] .lang-seg[data-seg="fr"],
.lang-switch[data-active="en"] .lang-seg[data-seg="en"] {
  background: var(--green); color: var(--bg); }
.lang-switch:hover { border-color: var(--cyan); box-shadow: 0 0 14px -6px var(--cyan); }
/* Bascule clair/sombre en CAPSULE ☀|🌙 (même principe que FR|EN) : la moitié du mode
   ACTIF est colorée SELON le mode — chaud (ambre) pour clair, froid (indigo) pour
   sombre ; l'autre moitié est grisée. */
.theme-switch { padding: 0; overflow: hidden; display: inline-flex; align-items: stretch;
  border: 1px solid var(--border); border-radius: 999px; line-height: 1; cursor: pointer; }
.theme-switch .theme-seg { display: inline-flex; align-items: center; justify-content: center;
  min-width: 2.1ch; padding: 4px 8px; font-size: .82rem;
  background: color-mix(in srgb, var(--muted) 12%, var(--panel));
  filter: grayscale(1) opacity(.6); transition: background .16s ease, filter .16s ease; }
.theme-switch .theme-seg[data-seg="light"] { border-right: 1px solid var(--border); }
.theme-switch[data-active="light"] .theme-seg[data-seg="light"] {
  background: color-mix(in srgb, #fbbf24 42%, var(--panel)); filter: none; }
.theme-switch[data-active="dark"] .theme-seg[data-seg="dark"] {
  background: color-mix(in srgb, #6366f1 46%, var(--panel)); filter: none; }
.theme-switch:hover { border-color: var(--cyan); box-shadow: 0 0 14px -6px var(--cyan); }
/* Étiquettes techniques (version) en mono, cohérent avec le logo */
#app-ver { font-family: var(--font-mono); letter-spacing: -.02em; }
.chip--btn { cursor: pointer; font: inherit; font-size: .75rem; line-height: 1.1;
  padding: 5px 10px; background-color: var(--panel); color: var(--text); text-decoration: none;
  display: inline-flex; align-items: center;
  transition: color .16s ease, border-color .16s ease, box-shadow .16s ease, transform .1s ease; }
/* Chip ICÔNE SEULE (ex. la cloche des notifications) : pas de texte. Épaisseur
   (hauteur) ~1.2× celle des autres chips pour mieux la repérer sans dominer. */
.chip--icon { padding: 7px 11px; }
.chip--icon .chip-ico { width: 21px; height: 21px; }
a#about-link { color: var(--cyan); border-color: rgba(34,211,238,.4); font-weight: 600; }
.chip--btn:hover { color: var(--cyan); border-color: var(--cyan);
  box-shadow: inset 0 1px 0 var(--card-sheen), 0 0 16px -2px rgba(34,211,238,.45); transform: translateY(-1px); }
.chip--btn:active { transform: translateY(0); box-shadow: inset 0 2px 5px -2px rgba(0,0,0,.45); }
.chip--btn .chip-ico { transition: filter .16s ease; }
.chip--btn:hover .chip-ico { filter: drop-shadow(0 0 6px rgba(34,211,238,.7)); }

/* --- Header MOBILE / TABLETTE (≤900px) : réorganisation lisible -----------------
   Nom LANGIAL agrandi (≈ hauteur du logo) ; boutons de nav AVEC leur texte (l'icône
   seule rendait les boutons peu clairs) ; « en ligne », « Drive », version et « EN »
   repoussés EN DERNIER (2e ligne), les deux pastilles clignotantes réduites. */
@media (max-width: 900px) {
  .topbar { padding: 8px 14px 5px; gap: 7px 8px; }         /* header compact : peu d'espace vertical */
  .brand { gap: 11px; }
  .brand-mark { width: 48px; height: 48px; border-radius: 13px; }
  .brand-mark img { border-radius: 13px; }
  .brand-txt h1 { font-size: 1.95rem; line-height: 1; }    /* LANGIAL agrandi, proche du logo */
  .brand-sub { display: none; }                            /* « · Collecte » retiré sur mobile (place au nom) */
  .tagline { display: none; }                              /* déjà répété dans le footer */
  .chip { font-size: .72rem; padding: 4px 6px; }
  .chip--btn { padding: 4px 6px; gap: 4px; }
  .chip--btn .chip-ico { width: 14px; height: 14px; }
  /* Cloche (icône seule) : épaisseur ~1.2× les autres chips, compacte pour tenir
     sur la 1re ligne juste après « Aide » (boutons resserrés ci-dessus). Placée
     APRÈS .chip--btn pour l'emporter sur son padding réduit. */
  .chip--icon { padding: 6px 7px; }
  .chip--icon .chip-ico { width: 17px; height: 17px; }
  /* Méta (ligne 1, droite) : les deux pastilles d'état gardent leur texte (« en ligne »,
     « Drive : prêt ») avec le point clignotant devant, et restent sur UNE SEULE ligne
     (jamais empilées), quitte à être un peu plus compactes. */
  .chips-meta { gap: 4px; flex-wrap: nowrap; justify-content: flex-end; }
  #srv-stats { display: none; }
  #net, #srv, #app-ver { font-size: .5rem; padding: 2px 5px; }
  #net.chip--on::before, #srv.chip--on::before { width: 4px; height: 4px; margin-right: 3px; }
  /* Nav (ligne 2) : boutons resserrés (H et V) qui BASCULENT à la ligne suivante quand
     ils débordent (jamais de scroll ni de bouton caché), le groupe outils reste à droite. */
  .chips-nav { flex-wrap: wrap; gap: 4px 4px; }
  .chips-nav .chip--btn { flex: 0 0 auto; }
}
/* Téléphone étroit : la marque et les deux pastilles d'état doivent tenir sur UNE ligne,
   avec leur libellé (« en ligne », « Drive : prêt ») et le point clignotant. */
@media (max-width: 560px) {
  .brand-mark { width: 42px; height: 42px; }
  .brand-txt h1 { font-size: 1.62rem; white-space: nowrap; }
  /* Nav TÉLÉPHONE : boutons COMPACTS, taille naturelle, AVEC leur icône (ni géants
     ni minuscules). La cloche reste le dernier bouton de la 1re ligne ; Bugs, Profil
     et les outils passent en 2e ligne via le saut de ligne. */
  .chips-nav { gap: 2px 6px; }        /* deux lignes de boutons plus rapprochées */
  .chip { font-size: .7rem; padding: 4px 8px; }   /* hauteur ~x1.1 */
  .chip--btn { padding: 4px 8px; gap: 5px; }
  .chip--btn .chip-ico { width: 15px; height: 15px; }
  /* Cloche : MÊME hauteur que les autres boutons de la ligne (padding vertical = 4px,
     icône 15px qui s'insère sans déborder) ; seule son ÉPAISSEUR (horizontal) est
     augmentée de ~x1.08 (8→9px). */
  .chip--icon { padding: 4px 10px; }   /* cloche : épaisseur (horizontal) x1.1, hauteur inchangée */
  .chip--icon .chip-ico { width: 15px; height: 15px; }
  /* Nom de langue tronqué seulement s'il est vraiment très long. */
  #lang-chip-name { display: inline-block; max-width: 140px; overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }
  .chips-meta { gap: 4px; }
  #net, #srv, #app-ver { font-size: .52rem; padding: 2px 5px; line-height: 1.15; }
  #net.chip--on::before, #srv.chip--on::before { margin-right: 3px; width: 4px; height: 4px; }
  #ui-lang-toggle, #theme-toggle { padding: 0; }   /* capsules : le padding est sur les segments */
  .lang-switch .lang-seg, .theme-switch .theme-seg { padding: 4px 8px; font-size: .66rem; }
}
/* Petits téléphones (≤ 389px) : le nom se réduit d'un cran pour que « LANGIAL · Collecte »
   ET les deux pastilles d'état tiennent sur la même ligne, sans scroll. Dès 390px le nom
   garde sa grande taille (1.42rem), donc les téléphones courants ne sont pas touchés. */
@media (max-width: 389px) {
  .brand-txt h1 { font-size: 1.42rem; }
}
/* Téléphones très étroits (≤ 340px : vieux modèles, écrans pliés) : on resserre encore
   un peu. */
@media (max-width: 340px) {
  .brand-mark { width: 36px; height: 36px; }
  .brand-txt h1 { font-size: 1.08rem; }
  #net, #srv, #app-ver { font-size: .46rem; padding: 2px 4px; }
  #net.chip--on::before, #srv.chip--on::before { margin-right: 3px; width: 4px; height: 4px; }
  /* Très petits écrans : boutons un cran plus compacts (icônes conservées). */
  .chip { font-size: .66rem; padding: 4px 6px; }
  .chip--btn { padding: 4px 6px; gap: 4px; }
}

/* --- Cartes --- */
.wrap {
  max-width: var(--wrap-max); margin: 0 auto; padding: 22px clamp(12px, 4vw, 28px) 60px;
  display: flex; flex-direction: column; gap: 18px;
  flex: 1 0 auto;   /* occupe l'espace restant → pousse le footer en bas d'écran */
  width: 100%;
}
.card {
  background: var(--card-bg);
  /* PAS de backdrop-filter ici : il crée un bloc conteneur qui casse le
     position:fixed des menus déroulants (combo-list) placés à l'intérieur.
     Les cartes sont opaques → le flou n'apportait rien de visible. */
  border: 1px solid var(--border); border-radius: 18px;
  padding: 18px clamp(14px, 3vw, 22px);
  /* Matière PREMIUM (identique sur TOUS les cadres de l'app) : halo d'ambiance cyan +
     ombre portée + reflet de verre en haut + fin liseré interne en bas (relief/épaisseur). */
  box-shadow: 0 0 32px -20px color-mix(in srgb, var(--cyan) 70%, transparent),
    var(--shadow-card), inset 0 1px 0 var(--card-sheen), inset 0 -1px 0 var(--card-inner);
}

/* Vues (profil / app) */
.view { display: flex; flex-direction: column; gap: 18px; }
.view[hidden] { display: none; }
/* TITRE DE PAGE = PLAQUE ENCADRÉE (sans motif) : voile teinté de la couleur d'activité
   (--acc), avec le MÊME halo et la MÊME bordure-comète lumineuse que les 4 onglets du haut.
   Le titre (icône + texte) s'insère dans ce cadre. */
.view-title { --acc: var(--gold); margin: 0 0 16px; position: relative; overflow: hidden;
  display: inline-flex; align-items: center; gap: 10px; max-width: 100%;
  font-family: var(--font-display); font-weight: 700; letter-spacing: -.015em; font-size: 1.4rem; color: var(--text);
  padding: 9px 20px; border-radius: 14px;
  border: 1px solid color-mix(in srgb, var(--acc) 42%, var(--border));
  background:
    radial-gradient(130% 90% at 50% -25%, color-mix(in srgb, var(--acc) 20%, transparent), transparent 60%),
    color-mix(in srgb, var(--acc) 13%, var(--panel));
  box-shadow: 0 0 26px -14px var(--acc), inset 0 1px 0 var(--card-sheen), 0 3px 10px -5px rgba(0,0,0,.34);
  animation: ngCardBreath 6s ease-in-out infinite; }
.view-title > * { position: relative; z-index: 3; }   /* icône + texte au-dessus du décor */
/* Bordure-comète lumineuse qui tourne (identique aux onglets). */
.view-title::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 2px;
  pointer-events: none; z-index: 2;
  background:
    conic-gradient(from var(--ng-angle), transparent 0%,
      color-mix(in srgb, #fff 88%, var(--acc)) 7%, color-mix(in srgb, var(--acc) 70%, transparent) 17%, transparent 30%),
    linear-gradient(var(--acc), var(--acc));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--acc) 70%, transparent));
  animation: ngBorderSpin 4s linear infinite;
}
.view-title::after { content: none; }
/* Couleur d'activité par page (comme les 4 onglets). */
#hub-title, .hub-head .view-title { --acc: var(--cyan); }
.hub-head { text-align: center; }
#work-title, #amorce-title { --acc: var(--green); }
@keyframes ornBead {
  0%, 100% { background-position: 0% 50%, 0 50%; }
  50%      { background-position: 100% 50%, 0 50%; }
}
@keyframes ornPulse {
  0%, 100% { box-shadow: 0 0 8px -1px var(--gold), inset 0 0 0 2px rgba(34,211,238,.5), inset 0 0 6px -1px var(--cyan); }
  50%      { box-shadow: 0 0 18px 1px var(--gold), inset 0 0 0 2px rgba(34,211,238,.75), inset 0 0 9px 0 var(--cyan); }
}
.profile-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 18px; }
.app-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.welcome { color: var(--cyan); font-weight: 600; font-size: .95rem; }
.mini-profile {
  border: 1px solid rgba(34,211,238,.4); background: rgba(34,211,238,.08);
  color: var(--cyan); border-radius: 10px; padding: 8px 14px; cursor: pointer;
  font: inherit; font-size: .86rem; font-weight: 600;
  transition: box-shadow .16s ease, border-color .16s ease;
}
.mini-profile:hover { box-shadow: 0 0 16px rgba(34,211,238,.3); border-color: var(--cyan); }

/* ---- Navigation entre espaces (Traduire / Transcrire / Explorer) ---- */
/* Barre des 4 onglets REMONTÉE près du header (comble ~80% de l'espace vide). */
/* Barre des 4 espaces : 3e rangée du header (intégrée au header, pleine largeur). */
.main-nav { grid-column: 1 / -1; grid-row: 3; display: flex; align-items: center; gap: 12px; margin: 2px 0 0; }
.main-nav[hidden] { display: none; }
/* Onglets : chaque bouton porte SA couleur d'activité (contour + fond teinté + halo),
   IDENTIQUE sur PC et téléphone. Sur PC ils s'étirent pour remplir la largeur dédiée
   (fini le vide dans le header). */
.nav-tabs { display: flex; flex: 1 1 auto; gap: 8px; padding: 0; background: transparent;
  border: none; flex-wrap: nowrap; }
/* Onglets = MÊMES effets que les cartes de l'accueil : lavis de couleur d'activité,
   halo d'ambiance qui « respire », bordure comète blanche qui tourne, shimmer au survol
   et glow d'icône pulsé. Bien mis en évidence. */
.nav-tab { --acc: var(--cyan); flex: 1 1 0; min-width: 0; justify-content: center;
  position: relative; overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--acc) 40%, var(--border));
  background: radial-gradient(130% 80% at 50% -20%, color-mix(in srgb, var(--acc) 18%, transparent), transparent 62%),
    color-mix(in srgb, var(--acc) 10%, var(--panel)); color: var(--text);
  padding: 11px 18px; border-radius: 12px; cursor: pointer; font: inherit; font-size: 1.12rem;
  font-weight: 700; display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  box-shadow: 0 0 26px -14px var(--acc), inset 0 1px 0 var(--card-sheen), 0 2px 8px -4px rgba(0,0,0,.28);
  transition: color .15s ease, background .15s ease, box-shadow .2s ease, border-color .2s ease, transform .12s ease;
  animation: ngCardBreath 6s ease-in-out infinite; }
.nav-tab > * { position: relative; z-index: 3; }   /* icône + libellé au-dessus des effets */
.nav-tab::before { content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 2px;
  pointer-events: none; z-index: 2;
  background:
    conic-gradient(from var(--ng-angle), transparent 0%,
      color-mix(in srgb, #fff 88%, var(--acc)) 7%, color-mix(in srgb, var(--acc) 70%, transparent) 17%, transparent 30%),
    linear-gradient(var(--acc), var(--acc));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--acc) 70%, transparent));
  animation: ngBorderSpin 4s linear infinite; }
.nav-tab::after { content: ""; position: absolute; inset: 0; border-radius: inherit; z-index: 1; pointer-events: none;
  background: linear-gradient(115deg, transparent 26%, color-mix(in srgb, var(--acc) 55%, #fff) 50%, transparent 74%);
  opacity: 0; transform: translateX(-120%); }
.nav-tab:hover { transform: translateY(-2px); animation-play-state: paused;
  box-shadow: 0 18px 40px -14px var(--acc), 0 0 0 2px color-mix(in srgb, var(--acc) 65%, transparent),
    0 0 40px -8px var(--acc), inset 0 1px 0 var(--card-sheen); }
.nav-tab:hover::after { animation: ngShimmer 760ms ease; }
/* Chaque onglet porte SA couleur d'activité (comme l'accueil et le mode présentation). */
#tab-traduire  { --acc: var(--green); }
#tab-transcrire { --acc: #a78bfa; }
#tab-explorer  { --acc: var(--gold); }
#tab-demander  { --acc: var(--cyan); }
#tab-explorer  { --acc: var(--gold); }
.nav-tab:hover { color: var(--text);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--acc) 42%, transparent),
    0 0 14px -6px var(--acc); }
/* Icône : boîte carrée + object-fit contain (jamais de débordement, jamais de distorsion) ;
   glow pulsé de la couleur d'activité, comme les icônes des cartes de l'accueil. */
.nav-tab .nav-ico { width: 30px; height: 30px; flex: none; object-fit: contain;
  filter: drop-shadow(0 0 8px color-mix(in srgb, var(--acc) 55%, transparent));
  animation: ngIcoGlow 3.4s ease-in-out infinite;
  transition: filter .15s ease; }
/* Normalisation VISUELLE par icône (sources d'aspects différents) : chaque glyphe est
   calibré pour occuper la même hauteur apparente dans son cadre, sans déborder. */
#tab-transcrire .nav-ico { width: 26px; height: 30px; }   /* micro : haut et étroit */
#tab-traduire  .nav-ico { width: 31px; height: 31px; }
#tab-explorer  .nav-ico { width: 30px; height: 30px; }
#tab-demander  .nav-ico { width: 31px; height: 31px; }
.nav-tab:hover .nav-ico, .nav-tab.is-active .nav-ico {
  filter: drop-shadow(0 0 10px color-mix(in srgb, var(--acc) 78%, transparent)); }
.nav-tab.is-active { color: var(--bg);
  background: var(--acc); border-color: var(--acc);   /* couleur d'activité UNIE (sans dégradé) */
  box-shadow: 0 0 20px -3px var(--acc); }
.nav-right { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
/* Mobile : les 3 onglets Transcrire/Traduire/Explorer TOUJOURS sur une seule ligne
   (chacun un tiers égal de la largeur), au lieu de déborder — optimise l'espace. */
@media (max-width: 600px) {
  .main-nav { gap: 8px; }
  .nav-right { display: none; }             /* accueil « bonjour » non essentiel ici */
  /* Onglets TÉLÉPHONE : les 4 boutons sur UNE SEULE LIGNE, icône + libellé côte à
     côte. Chaque onglet est un vrai bouton visible (contour + fond teinté de sa
     couleur d'activité). Icône et texte un peu agrandis pour remplir le bouton. */
  .nav-tabs { width: 100%; flex-wrap: nowrap; gap: 4px; padding: 0; background: transparent; border: none; }
  /* Ensemble icône + libellé CENTRÉ dans chaque cadre ; icône et texte agrandis.
     Gap et marges resserrés pour laisser toute la place au libellé (aucune troncature). */
  .nav-tab { flex: 1 1 0; min-width: 0; justify-content: center;
    gap: 2px; padding: 8px 0; font-size: .6rem; border-radius: 11px; }
  .nav-tab span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
  /* Icônes calibrées une à une pour une même hauteur apparente, sans débordement.
     Les glyphes larges (mégaphone) sont resserrés pour ne pas rogner le libellé. */
  .nav-tab .nav-ico { width: 27px; height: 27px; flex: none; }
  #tab-transcrire .nav-ico { width: 26px; height: 28px; }
  #tab-traduire  .nav-ico { width: 27px; height: 27px; }
  #tab-explorer  .nav-ico { width: 27px; height: 27px; }
  #tab-demander  .nav-ico { width: 25px; height: 27px; }
  /* Onglet actif : couleur d'activité pleine (déjà géré par .is-active) — on garde. */
}
/* Écrans très étroits (≤ 374 px, type 360) : on réduit d'un cran police et icônes pour
   que « Transcrire » et « Demander » restent ENTIÈREMENT visibles, sans troncature. */
@media (max-width: 374px) {
  .nav-tab { gap: 2px; font-size: .54rem; }
  .nav-tab .nav-ico { width: 24px; height: 24px; }
  #tab-transcrire .nav-ico { width: 23px; height: 25px; }
  #tab-traduire  .nav-ico { width: 24px; height: 24px; }
  #tab-explorer  .nav-ico { width: 24px; height: 24px; }
  #tab-demander  .nav-ico { width: 22px; height: 24px; }
}

/* ---- Accueil « Que veux-tu faire ? » ---- */
.hub-head { text-align: center; margin-bottom: 4px; }
/* 4 portes : 2 par ligne (PC / tablette), 1 par ligne en mobile étroit. Image à hauteur
   pleine du cadre dans tous les cas. */
.hub-cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
@media (max-width: 560px) { .hub-cards { grid-template-columns: 1fr; } }
/* Chaque porte porte SA couleur d'identité (assortie à son icône et au mode
   présentation) : Traduire → vert, Transcrire → violet, Explorer → or. */
/* Angle enregistré (animable) pour la bordure conique tournante des cartes du hub. */
@property --ng-angle { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
.hub-card { --acc: var(--cyan);
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px; text-align: left;
  padding: 22px 20px; border-radius: 18px; cursor: pointer; font: inherit; position: relative; overflow: hidden;
  min-height: 226px;   /* cartes ~×1.2 plus hautes qu'auparavant (respiration + place à l'image) */
  /* lavis de couleur discret en haut de carte, posé sur le fond de carte */
  background: radial-gradient(130% 78% at 50% -14%, color-mix(in srgb, var(--acc) 16%, transparent), transparent 62%), var(--card-bg);
  border: 1px solid color-mix(in srgb, var(--acc) 20%, var(--border));
  /* Matière + halo d'ambiance (couleur d'activité) + reflet de verre + relief interne. */
  box-shadow: 0 0 34px -18px var(--acc), var(--shadow-card), inset 0 1px 0 var(--card-sheen), inset 0 -1px 0 var(--card-inner);
  transition: transform .18s ease, box-shadow .2s ease, border-color .2s ease;
  animation: ngCardBreath 6s ease-in-out infinite; }
/* Halo d'ambiance qui « respire » doucement (gelé sur mobile et prefers-reduced-motion). */
@keyframes ngCardBreath {
  0%, 100% { box-shadow: 0 0 40px -14px var(--acc), var(--shadow-card), inset 0 1px 0 var(--card-sheen), inset 0 -1px 0 var(--card-inner); }
  50%      { box-shadow: 0 0 78px -6px var(--acc), 0 0 22px -4px var(--acc), var(--shadow-card), inset 0 1px 0 var(--card-sheen), inset 0 -1px 0 var(--card-inner); }
}
.hub-card:nth-child(1) { --acc: var(--green); }
.hub-card:nth-child(2) { --acc: #a78bfa; }
.hub-card:nth-child(3) { --acc: var(--gold); }
.hub-card:nth-child(4) { --acc: var(--cyan); }
/* Illustration africaine en FOND de carte, sous un filtre assombrissant (dégradé vers la
   couleur de carte, plus fort en bas) pour que l'icône, le titre et le texte restent
   parfaitement lisibles par-dessus, dans les deux thèmes. --card-illus posé en HTML. */
/* Image RÉALISTE ENTIÈRE (jamais recadrée), réduite à 70 % de la hauteur du cadre et
   COLLÉE au coin NORD-EST (haut-droite, jusqu'aux bords haut/droite du cadre). width:auto
   → l'image garde ses proportions, rien n'est coupé. Elle se fond vers le SUD-OUEST via un
   masque en dégradé : le coin est illustré, la zone de texte (bas-gauche) reste dégagée. */
/* Image RÉALISTE/illustrée ENTIÈRE (jamais recadrée) : HAUTEUR PLEINE du cadre (déborde
   jusqu'aux bords haut/bas/droite), calée tout à DROITE. Cartes larges (empilées) → l'image
   chevauche peu le texte. Fondu vers la GAUCHE pour dégager la zone de texte. Contour de la
   COULEUR DU CADRE tracé autour de l'image (silhouette pour les illustrations, bord net pour
   les photos). Identique PC et mobile. */
/* Carte = deux colonnes flex : TEXTE à gauche (prend la place restante, jamais recouvert) et
   IMAGE à droite en COLONNE propre, pleine hauteur du cadre, calée en bas. Aucun chevauchement
   possible quelle que soit la largeur d'écran (le texte se réduit tout seul). */
.hub-card--illus { flex-direction: row; align-items: stretch; gap: 0; padding: 0; }
.hub-card--illus .hub-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column;
  align-items: flex-start; justify-content: center; gap: 8px; padding: 20px 6px 20px 20px; }
/* Colonne de droite : conteneur étiré à la hauteur du cadre (align-self stretch). Il est en
   position:relative et l'image est en absolute inset:0 → l'image NE participe PLUS au calcul de
   la hauteur (fini la dépendance circulaire qui variait selon le navigateur). Largeur 52% pour
   que l'image carrée atteigne bien 100% de la hauteur du cadre. */
.hub-illus-wrap { flex: 0 0 48%; align-self: stretch; position: relative; overflow: hidden; min-width: 0; }
/* L'image occupe tout le conteneur (= hauteur du cadre), sans recadrage (contain), plaquée à
   DROITE et en bas. */
.hub-illus { position: absolute; right: 0; bottom: 0; width: 100%; height: 98%;
  object-fit: contain; object-position: right bottom; pointer-events: none;
  -webkit-mask-image: linear-gradient(to left, #000 50%, rgba(0,0,0,.5) 80%, transparent 100%);
          mask-image: linear-gradient(to left, #000 50%, rgba(0,0,0,.5) 80%, transparent 100%);
  filter: drop-shadow(1.4px 0 0 var(--acc)) drop-shadow(-1.4px 0 0 var(--acc))
          drop-shadow(0 1.4px 0 var(--acc)) drop-shadow(0 -1.4px 0 var(--acc)); }
/* Le texte passe au-dessus de l'image, avec une ombre portée pour un contraste garanti. */
.hub-card--illus .hub-card-head, .hub-card--illus .hub-desc, .hub-card--illus .hub-go { position: relative; z-index: 2; }
.hub-card--illus .hub-name, .hub-card--illus .hub-desc, .hub-card--illus .hub-go {
  text-shadow: 0 1px 10px var(--panel), 0 0 6px var(--panel), 0 0 2px var(--panel); }
/* Le texte n'occupe que ~70% à gauche : il passe à la ligne AVANT d'atteindre l'image ;
   les 30% de droite restent réservés à l'image. */
/* Texte AGRANDI (PC) ; titre = plus gros glyphe devant l'icône. */
.hub-card--illus .hub-name { font-size: 2.05rem; }
.hub-card--illus .hub-desc { font-size: 1rem; line-height: 1.55; }
.hub-card--illus .hub-go { font-size: 1.02rem; }
/* Icône AGRANDIE, posée dans un CERCLE au contour de la couleur du cadre (accent). */
.hub-card--illus .hub-ico {
  width: 92px; height: 92px; padding: 13px; box-sizing: border-box; border-radius: 50%;
  border: 2.5px solid var(--acc); object-fit: contain;
  background: radial-gradient(circle at 50% 32%, color-mix(in srgb, var(--acc) 18%, var(--panel)), var(--panel));
  box-shadow: 0 0 17px -7px var(--acc), inset 0 1px 0 var(--card-sheen); }
/* MOBILE étroit : cartes ~2× plus basses (×0.5), contenu compacté pour tenir dans cette
   hauteur réduite ; l'image reste pleine hauteur (plus courte donc plus étroite → laisse
   d'autant plus de place au texte). */
@media (max-width: 560px) {
  .hub-card { min-height: 113px; }
  .hub-card--illus .hub-text { padding: 10px 4px 10px 14px; gap: 4px; justify-content: center; }
  .hub-card--illus .hub-name { font-size: 1.28rem; }
  .hub-card--illus .hub-desc { font-size: .8rem; line-height: 1.35; }
  .hub-card--illus .hub-go { font-size: .86rem; }
  .hub-card--illus .hub-ico { width: 48px; height: 48px; padding: 7px; }
  .hub-card-head { gap: 10px; }
}
/* Bordure vive et PLEINE de la couleur d'activité (bien lisible à l'arrêt) SURMONTÉE d'une
   comète blanche large qui fait le tour, rapide. Anneau réalisé au masque → reste dans la boîte. */
.hub-card::before { content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 3px;
  pointer-events: none; z-index: 2;
  background:
    conic-gradient(from var(--ng-angle), transparent 0%,
      color-mix(in srgb, #fff 88%, var(--acc)) 7%, color-mix(in srgb, var(--acc) 70%, transparent) 17%, transparent 30%),
    linear-gradient(var(--acc), var(--acc));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  filter: drop-shadow(0 0 8px color-mix(in srgb, var(--acc) 70%, transparent));
  animation: ngBorderSpin 4s linear infinite; }
@keyframes ngBorderSpin { to { --ng-angle: 360deg; } }
/* Balayage « shimmer » : une lumière traverse la carte en diagonale au survol. */
.hub-card::after { content: ""; position: absolute; inset: 0; border-radius: inherit; z-index: 1; pointer-events: none;
  background: linear-gradient(115deg, transparent 26%, color-mix(in srgb, var(--acc) 55%, #fff) 50%, transparent 74%);
  opacity: 0; transform: translateX(-120%); }
.hub-card:hover { transform: translateY(-6px); border-color: var(--acc); animation-play-state: paused;
  box-shadow: 0 32px 68px -12px var(--acc),
    0 0 0 2.5px color-mix(in srgb, var(--acc) 70%, transparent),   /* liseré lumineux net */
    0 0 56px -6px var(--acc), var(--shadow-card), inset 0 1px 0 var(--card-sheen); }
.hub-card:hover::after { animation: ngShimmer 760ms ease; }
@keyframes ngShimmer { 0% { opacity: 0; transform: translateX(-120%); } 18% { opacity: .92; } 100% { opacity: 0; transform: translateX(120%); } }
/* Onde (ripple) au clic : disque lumineux injecté en JS (attachRipple). */
.hub-ripple { position: absolute; border-radius: 50%; pointer-events: none; z-index: 3;
  background: radial-gradient(circle, color-mix(in srgb, var(--acc) 45%, #fff) 0%, transparent 70%);
  transform: translate(-50%, -50%) scale(0); opacity: .7; }
.hub-card.is-rippling .hub-ripple { animation: ngRipple 620ms ease-out forwards; }
@keyframes ngRipple { to { transform: translate(-50%, -50%) scale(1); opacity: 0; } }
/* En-tête de carte : icône À GAUCHE, titre à sa droite, centré sur l'icône
   (gain de hauteur ; on occupe l'espace horizontal libre, surtout sur mobile). */
.hub-card-head { display: flex; align-items: center; gap: 15px; width: 100%; }
.hub-ico { width: 60px; height: 60px; line-height: 1; display: block; flex: 0 0 auto;
  filter: drop-shadow(0 0 15px color-mix(in srgb, var(--acc) 62%, transparent));
  animation: ngIcoGlow 3.4s ease-in-out infinite; }
/* Glow pulsé de l'icône d'activité (gelé sur mobile + prefers-reduced-motion). */
@keyframes ngIcoGlow {
  0%, 100% { filter: drop-shadow(0 0 14px color-mix(in srgb, var(--acc) 62%, transparent)); }
  50%      { filter: drop-shadow(0 0 34px color-mix(in srgb, var(--acc) 100%, transparent)) drop-shadow(0 0 12px color-mix(in srgb, var(--acc) 70%, transparent)); }
}
/* Onglets de nav : icône + libellé alignés */
.nav-tab { display: inline-flex; align-items: center; gap: 7px; }
.nav-ico { width: 26px; height: 26px; flex: 0 0 auto; }
/* Boutons du header : icône premium + libellé */
.chip--btn { display: inline-flex; align-items: center; gap: 6px; }
.chip-ico { width: 19px; height: 19px; flex: 0 0 auto; }
/* Icône devant un titre de page (Traduire/Transcrire/Explorer) */
.view-title--ico { display: inline-flex; align-items: center; gap: 10px; }
.title-ico { width: 34px; height: 34px; flex: 0 0 auto; }
/* Icône « info » du titre « À propos » (remplace l'ancien symbole étoilé) : teinte
   cyan d'accent, ne rétrécit pas. */
/* Emblème premium du titre « À propos » : badge en verre dégradé, soleil levant (LANGIAL =
   « la lumière ») ; halo doux, léger relief. */
.about-emblem { flex: 0 0 auto; display: inline-flex; line-height: 0;
  filter: drop-shadow(0 4px 10px rgba(0,0,0,.28)) drop-shadow(0 0 14px color-mix(in srgb, var(--green) 40%, transparent)); }
.about-emblem svg { display: block; border-radius: 14px; }
.hub-name { font-size: 1.55rem; font-family: var(--font-display); font-weight: 700;
  letter-spacing: -.01em; color: var(--text); }
.hub-desc { color: var(--muted); font-size: .86rem; line-height: 1.5; }
.hub-go { margin-top: auto; padding-top: 6px; color: var(--cyan); font-weight: 700; font-size: .9rem; }

/* ---- Choix de la langue (plateforme communautaire) ---- */
/* Contrôles toujours visibles en haut : recherche (prend la place) + bouton
   « déclarer » DISTINCT (dégradé doré, jamais confondu avec une carte de langue). */
.lang-controls { display: flex; flex-direction: column; gap: 10px; margin: 4px 0 14px; }
.lang-search-row { display: flex; gap: 10px; align-items: stretch; }
.lang-search { flex: 1 1 auto; min-width: 0; box-sizing: border-box; padding: 12px 14px; border-radius: 12px;
  font: inherit; font-size: .95rem; color: var(--text); background: var(--panel);
  border: 1px solid var(--border); transition: border-color .15s ease, box-shadow .15s ease; }
.lang-search::placeholder { color: var(--muted); }
.lang-search:focus { outline: none; border-color: var(--cyan); box-shadow: 0 0 0 3px color-mix(in srgb, var(--cyan) 22%, transparent); }
/* Boutons de l'écran des langues : couleur UNIE (pas de dégradé). Le texte prend
   la couleur du FOND de page (--bg), toujours à l'opposé de --cyan dans chaque
   thème → contraste garanti en clair ET en sombre. */
.lang-btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; cursor: pointer;
  font: inherit; font-size: .95rem; font-weight: 700; padding: 12px 20px; border-radius: 12px;
  color: var(--bg); border: 1px solid transparent;
  transition: filter .15s ease, box-shadow .15s ease, transform .1s ease; }
.lang-btn:active { transform: translateY(1px); }
/* ACTION → cyan ; NAVIGATION (ouvre le formulaire de déclaration) → or. */
.lang-search-btn { flex: 0 0 auto; background: var(--cyan); border-color: var(--cyan); }
.lang-search-btn:hover { filter: brightness(1.06); box-shadow: 0 0 16px -6px var(--cyan); }
/* NAVIGATION (ouvre une vue) : or DOUX fixe + encre foncée, identique clair/sombre. */
.lang-declare-cta { width: 100%; background: var(--nav-gold); border-color: var(--nav-gold); color: var(--nav-ink); }
.lang-declare-cta:hover { filter: brightness(1.04); box-shadow: 0 0 16px -6px var(--nav-gold); }
.lang-empty { text-align: center; color: var(--muted); font-size: .9rem; padding: 20px 12px; }
.lang-empty[hidden] { display: none; }
@media (max-width: 480px) { .lang-search-btn span:last-child { display: none; } }
/* Jumelage de langues (Phase C) : panneau sur l'écran des langues (confirmations en
   attente pour ce contributeur + suggestions de doublons à fusionner). */
.lang-merge-panel { display: flex; flex-direction: column; gap: 10px; margin: 6px 0 14px; }
.lang-merge-panel[hidden] { display: none; }
.merge-item { border: 1px solid var(--border); border-radius: 14px; padding: 12px 14px; background: var(--panel); }
.merge-item--ask { border-color: rgba(34,211,238,.55); box-shadow: 0 0 16px -5px var(--cyan); }
.merge-item--sugg { border-style: dashed; }
.merge-q { margin: 0 0 10px; color: var(--text); font-size: .92rem; line-height: 1.45; }
.merge-q b { color: var(--cyan); }
.merge-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
/* Bloc « réunir deux langues » : callout BIEN EN ÉVIDENCE (accent doré, fond teinté,
   halo lumineux) — action importante placée en haut de la page des langues. */
.merge-item--manual { border: 1.5px solid color-mix(in srgb, var(--gold) 60%, var(--border));
  background:
    radial-gradient(130% 130% at 0% 0%, color-mix(in srgb, var(--gold) 15%, transparent), transparent 62%),
    var(--card-bg);
  box-shadow: inset 0 1px 0 var(--card-sheen), 0 0 26px -8px var(--gold);
  border-radius: 16px; padding: 16px; }
.merge-item--manual .merge-q { white-space: pre-line; font-weight: 700; font-size: 1rem;
  line-height: 1.4; color: var(--text); }
.merge-manual-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.merge-sel { flex: 1 1 150px; min-width: 130px; padding: 7px 10px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--panel); color: var(--text); font: inherit; font-size: .86rem; }
/* Bouton « Proposer la fusion » : action MISE EN ÉVIDENCE (cyan tinté, halo respirant). */
#merge-manual-go, .merge-propose { border: 1.5px solid var(--cyan); color: var(--cyan);
  background: color-mix(in srgb, var(--cyan) 12%, var(--panel)); font-weight: 800; letter-spacing: .01em;
  border-radius: 999px; padding: 9px 18px; white-space: nowrap;
  box-shadow: inset 0 1px 0 var(--card-sheen), 0 0 16px -5px var(--cyan);
  --cta-g: rgba(34,211,238,.5); animation: ngCtaGlow 2.8s ease-in-out infinite;
  transition: background .15s ease, color .15s ease, box-shadow .15s ease, transform .1s ease; }
#merge-manual-go:hover, .merge-propose:hover { background: var(--cyan); color: var(--bg);
  transform: translateY(-1px); box-shadow: 0 0 20px -4px var(--cyan); }
@media (prefers-reduced-motion: reduce) { #merge-manual-go, .merge-propose { animation: none; } }

/* Découpe d'un enregistrement (#47) : outil « garder une partie de l'audio ». */
.trim-modal { position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center;
  background: rgba(4,12,20,.62); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); padding: 16px; }
.trim-modal[hidden] { display: none; }
.trim-card { background: var(--panel); border: 1px solid var(--border); border-radius: 18px;
  padding: 18px clamp(14px,3vw,22px); width: min(680px, 100%); box-shadow: 0 20px 60px -12px rgba(0,0,0,.6);
  display: flex; flex-direction: column; gap: 12px; }
.trim-card h3 { margin: 0; font-family: var(--font-display); color: var(--text); font-size: 1.15rem; }
.trim-hint { margin: 0; color: var(--muted); font-size: .9rem; line-height: 1.45; }
.trim-wave-wrap { border: 1px solid var(--border); border-radius: 12px; background: var(--bg); overflow: hidden; }
.trim-wave { display: block; width: 100%; height: auto; touch-action: none; cursor: ew-resize; }
.trim-times { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; }
.trim-time { display: flex; flex-direction: column; gap: 4px; font-size: .82rem; color: var(--muted); }
.trim-time input { width: 110px; padding: 7px 10px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--panel); color: var(--text); font: inherit; }
.trim-dur { margin-left: auto; color: var(--cyan); font-weight: 600; font-size: .9rem; }
.trim-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.trim-spacer { flex: 1 1 auto; }
#trim-audio { display: none; }
.lang-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 14px; margin-top: 6px; }
.lang-card[hidden] { display: none; }
.lang-card { --acc: var(--cyan); position: relative; overflow: hidden; display: flex; flex-direction: column; align-items: flex-start;
  gap: 4px; text-align: left; padding: 16px 16px; border-radius: 16px; cursor: pointer; font: inherit;
  background: var(--card-bg); border: 1.5px solid transparent; box-shadow: 0 0 26px -20px var(--acc), var(--shadow-card);
  transition: transform .16s ease, box-shadow .2s ease; }
/* Bordure en dégradé vif tout autour (tri-couleur, statique → perf), avec halo. Anneau au masque. */
.lang-card::before { content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1.5px; z-index: 2; pointer-events: none;
  background: linear-gradient(135deg, var(--cyan), var(--green) 45%, var(--gold));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  filter: drop-shadow(0 0 4px color-mix(in srgb, var(--acc) 45%, transparent)); }
/* Balayage shimmer au survol. */
.lang-card::after { content: ""; position: absolute; inset: 0; border-radius: inherit; z-index: 1; pointer-events: none;
  background: linear-gradient(115deg, transparent 30%, color-mix(in srgb, var(--acc) 40%, #fff) 50%, transparent 70%);
  opacity: 0; transform: translateX(-120%); }
.lang-card:hover, .lang-card:focus-visible { transform: translateY(-4px);
  box-shadow: 0 22px 46px -14px var(--acc), 0 0 34px -10px var(--acc), var(--shadow-card); outline: none; }
.lang-card:hover::after, .lang-card:focus-visible::after { animation: ngShimmer 820ms ease; }
.lang-card.is-current { --acc: var(--green); box-shadow: 0 0 0 1px var(--green) inset, 0 0 32px -12px var(--green), var(--shadow-card); }
.lang-card.is-current::before { background: linear-gradient(135deg, var(--green), var(--cyan) 55%, var(--green)); filter: drop-shadow(0 0 6px color-mix(in srgb, var(--green) 60%, transparent)); }
/* 1re ligne : emblème + nom alignés à la même hauteur. */
.lang-head { display: flex; align-items: center; gap: 10px; width: 100%; }
.lang-emblem { flex: none; width: 42px; height: 42px; border-radius: 12px; display: grid; place-items: center;
  font-size: 1.35rem; font-weight: 800; color: #06121a;
  background: linear-gradient(145deg, var(--cyan), var(--green)); box-shadow: 0 0 14px -4px var(--cyan); }
.lang-name { font-size: 1.08rem; font-weight: 800; color: var(--text); line-height: 1.2; }
/* 2e ligne : autonyme à gauche, pastille de contributions à droite (espace horizontal exploité). */
.lang-sub { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; margin-top: 2px; }
.lang-autonym { font-size: .84rem; color: var(--cyan); font-weight: 600; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lang-region { font-size: .8rem; color: var(--muted); line-height: 1.35; }
.lang-kb { margin-top: 3px; font-size: .72rem; color: var(--gold); font-weight: 700; letter-spacing: .02em; }
.lang-card.is-current .lang-kb::after { content: " · sélectionnée"; color: var(--green); }
:root[lang="en"] .lang-card.is-current .lang-kb::after { content: " · selected"; }
/* Pastille d'enrichissement (nb de contributions), compacte, sur la ligne de l'autonyme. */
.lang-count { flex: none; margin-left: auto; font-size: .72rem; font-weight: 800; white-space: nowrap;
  color: var(--cyan); background: color-mix(in srgb, var(--cyan) 12%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--cyan) 30%, var(--border)); border-radius: 999px; padding: 2px 9px; }
.lang-count--empty { color: var(--muted); background: transparent;
  border-color: var(--border); font-weight: 600; }
/* Principaux contributeurs de la langue, dans la carte communautaire d'Explorer. */
.exp-contrib { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--hairline);
  display: flex; flex-wrap: wrap; align-items: center; gap: 7px; }
.exp-contrib-lbl { font-size: .78rem; font-weight: 700; color: var(--text); margin-right: 2px; }
.exp-contrib-item { font-size: .76rem; font-weight: 600; color: var(--green);
  background: color-mix(in srgb, var(--green) 12%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--green) 30%, var(--border));
  border-radius: 999px; padding: 3px 10px; }
.exp-contrib-item b { color: var(--text); font-weight: 800; margin-left: 2px; }
.lang-declare { margin-top: 16px; }
.lang-declare h3 { margin: 0 0 4px; color: var(--text); }
.lang-declare-hint { margin: 0 0 6px; color: var(--muted); font-size: .86rem; }
.lang-declare-req { margin: 0 0 12px; color: var(--muted); font-size: .82rem; }
.lang-declare-actions { display: flex; gap: 12px; align-items: center; margin-top: 14px; flex-wrap: wrap; }
.lang-declare-err { color: var(--red); font-weight: 600; font-size: .88rem; margin: 8px 0 0; }
.lang-declare-err[hidden] { display: none; }
/* Champ pleine largeur dans la grille du formulaire de déclaration */
.field--wide { grid-column: 1 / -1; }
/* Suggestions anti-doublon : langues déjà présentes qui ressemblent à la saisie */
.ld-similar { margin: 6px 0 10px; padding: 13px 15px; border-radius: 13px;
  background: color-mix(in srgb, var(--gold) 9%, var(--card-bg));
  border: 1px solid color-mix(in srgb, var(--gold) 42%, var(--border)); }
.ld-similar[hidden] { display: none; }
.ld-similar-head { margin: 0 0 9px; font-weight: 700; color: var(--text); font-size: .92rem; }
.ld-similar-row { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 9px 12px; border-radius: 10px; background: var(--panel); border: 1px solid var(--border);
  margin-bottom: 7px; flex-wrap: wrap; }
.ld-similar-info b { color: var(--text); font-size: 1rem; }
.ld-similar-meta { display: block; color: var(--muted); font-size: .8rem; margin-top: 1px; }
.ld-similar-pick { padding: 8px 15px; font-size: .85rem; white-space: nowrap; }
.ld-similar-hint { margin: 7px 0 0; color: var(--muted); font-size: .82rem; }

/* ---- Langues d'appartenance (puces multi-sélection dans le profil) ---- */
.field--langs { grid-column: 1 / -1; }
.lang-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.lang-chip-toggle { display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  border: 1px solid var(--border); background: var(--panel2); color: var(--txt-dim);
  border-radius: 999px; padding: 7px 13px; font: inherit; font-size: .84rem; font-weight: 600;
  transition: border-color .15s ease, color .15s ease, background .15s ease, box-shadow .15s ease; }
.lang-chip-toggle:hover { border-color: var(--cyan); color: var(--text); }
.lang-chip-toggle.is-on { border-color: var(--cyan); color: var(--cyan);
  background: color-mix(in srgb, var(--cyan) 10%, var(--panel2)); }
.lang-chip-toggle.is-primary { border-color: var(--green); color: var(--green);
  box-shadow: 0 0 14px -6px var(--green); }
.lct-primary { font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  background: var(--green); color: #04120b; border-radius: 6px; padding: 1px 6px; }
.lang-chip-add { border-style: dashed; color: var(--muted); }
.lang-chip-add:hover { border-color: var(--gold); color: var(--gold); }

/* ---- Amorce sonore : premières voix d'une langue créée ---- */
.amorce-intro { color: var(--muted); font-size: .92rem; line-height: 1.5; margin: 0 0 18px; }
.amorce-progress { display: flex; align-items: center; gap: 12px; margin: 6px 0 20px; }
.amorce-bar { flex: 1; height: 10px; border-radius: 999px; background: var(--panel2);
  border: 1px solid var(--border); overflow: hidden; }
.amorce-bar-fill { display: block; height: 100%; width: 0;
  background: linear-gradient(90deg, var(--cyan), var(--green)); border-radius: 999px;
  transition: width .35s ease; }
.amorce-count { font-size: .9rem; color: var(--text); white-space: nowrap; }
.amorce-count b { color: var(--cyan); font-size: 1.1rem; }
.amorce-word { display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 24px 16px; border: 1px solid var(--border); border-radius: 16px;
  background: var(--panel2); text-align: center; }
.amorce-word-cat { font-size: .74rem; letter-spacing: .06em; text-transform: uppercase; color: var(--gold); }
.amorce-word-fr { font-size: 1.9rem; font-weight: 800; color: var(--text); line-height: 1.15; }
.amorce-word-hint { font-size: .84rem; color: var(--muted); }
.amorce-rec { display: flex; flex-direction: column; align-items: center; gap: 10px; margin: 18px 0; }
.amorce-rec-status { font-size: .85rem; color: var(--muted); min-height: 1.1em; }
.amorce-audio { width: min(360px, 100%); }
.amorce-audio[hidden] { display: none; }
.amorce-actions { display: flex; gap: 12px; align-items: center; justify-content: center; flex-wrap: wrap; }
.amorce-note { color: var(--muted); font-size: .85rem; text-align: center; margin: 12px 0 0; }
.amorce-note[hidden] { display: none; }
/* Mise en avant du bouton « Terminer » dès le minimum atteint. */
.btn--go { border-color: var(--green); color: var(--green); box-shadow: 0 0 18px -6px var(--green); }

/* ---- En-tête d'espace + mise en avant de l'enregistrement en transcription ---- */
.work-head { margin-bottom: 2px; }
.work-help { color: var(--muted); font-size: .86rem; line-height: 1.55; margin: 8px 0 0; }

/* Indicateur FORT de la langue de la contribution (anti-mauvais étiquetage) : pastille
   proéminente, cliquable, toujours visible sur la vue de travail. */
.work-lang {
  display: inline-flex; align-items: center; gap: 8px; margin: 10px 0 0;
  padding: 7px 12px; border-radius: 999px; cursor: pointer;
  border: 1.5px solid color-mix(in srgb, var(--cyan) 55%, var(--border));
  background:
    radial-gradient(120% 120% at 0% 0%, color-mix(in srgb, var(--cyan) 15%, transparent), transparent 62%),
    color-mix(in srgb, var(--cyan) 8%, var(--card));
  color: var(--text); font-size: .9rem; line-height: 1;
  box-shadow: inset 0 1px 0 var(--card-sheen), 0 0 20px -10px var(--cyan);
  transition: border-color .2s, box-shadow .2s, background .2s;
}
.work-lang:hover { border-color: var(--cyan); box-shadow: inset 0 1px 0 var(--card-sheen), 0 0 24px -6px var(--cyan); }
.work-lang-ico { font-size: 1.05rem; }
.work-lang-lead { color: var(--muted); }
.work-lang-name { font-weight: 800; letter-spacing: .2px;
  color: color-mix(in srgb, var(--cyan) 72%, var(--text)); }
.work-lang-chev { color: var(--muted); font-size: .8rem; }
/* Tant que la langue n'a pas été confirmée cette session : teinte d'alerte ambrée + halo qui
   respire pour attirer l'œil (respecte prefers-reduced-motion). */
.work-lang.is-unconfirmed {
  border-color: color-mix(in srgb, var(--gold) 65%, var(--border));
  background:
    radial-gradient(120% 120% at 0% 0%, color-mix(in srgb, var(--gold) 18%, transparent), transparent 62%),
    color-mix(in srgb, var(--gold) 9%, var(--card));
  animation: worklang-breathe 2.4s ease-in-out infinite;
}
.work-lang.is-unconfirmed .work-lang-name { color: color-mix(in srgb, var(--gold) 78%, var(--text)); }
@keyframes worklang-breathe {
  0%, 100% { box-shadow: inset 0 1px 0 var(--card-sheen), 0 0 14px -10px var(--gold); }
  50% { box-shadow: inset 0 1px 0 var(--card-sheen), 0 0 22px -4px var(--gold); }
}
@media (prefers-reduced-motion: reduce) { .work-lang.is-unconfirmed { animation: none; } }
/* Ligne de doute (écriture qui contredit la langue) dans le modal de confirmation. */
.lc-doubt {
  margin: 0 0 6px; padding: 9px 12px; border-radius: 10px; font-size: .88rem; line-height: 1.5;
  color: color-mix(in srgb, var(--gold) 40%, var(--text));
  border: 1px solid color-mix(in srgb, var(--gold) 45%, var(--border));
  background: color-mix(in srgb, var(--gold) 10%, var(--card));
}
/* La zone encadre déjà l'audio → pas de cadre interne redondant (dans TOUS les modes,
   pour un rendu identique Traduire/Transcrire/amorce). */
.zone--audio .audio-row { padding: 0; margin-top: 12px; background: transparent; border: none; }
/* « Enregistrer l'audio » : MÊME apparence PARTOUT où l'audio est utilisé (bouton
   d'action cyan tinté, dot rouge) — plus de couleur différente selon le mode.
   `.btn.btn--rec` pour l'emporter sur la bordure neutre de `.btn`. */
.btn.btn--rec { border: 1.5px solid var(--cyan); color: var(--cyan);
  background: color-mix(in srgb, var(--cyan) 10%, var(--panel));
  box-shadow: inset 0 1px 0 var(--card-sheen), 0 8px 22px -12px var(--cyan); font-weight: 700; }
.btn.btn--rec:hover { background: var(--cyan); color: var(--bg); border-color: var(--cyan); }

/* ---- Menu « À traduire / À prononcer » (prop-cat) en ligne ---- */
.prop-cat.combo { display: inline-block; width: auto; min-width: 150px; vertical-align: middle; }
.prop-cat.combo .combo-display { padding: 8px 32px 8px 11px; font-size: .9rem; border-radius: 9px; }
.prop-cat.combo .combo-toggle { width: 26px; }
.prop-cat.combo .combo-list { left: 0; right: auto; min-width: 210px; }

/* ---- Page Explorer (bibliothèque communautaire) ---- */
.explore-controls { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
.explore-search { width: 100%; }
.explore-filters { display: flex; gap: 10px; flex-wrap: wrap; }
.explore-export { display: flex; gap: 8px; flex-wrap: wrap; }
.explore-export .chip--btn { font-size: .78rem; }
.explore-filters .combo--select { flex: 1 1 170px; min-width: 150px; }
.explore-filters select { flex: 1 1 170px; }
.explore-status { margin-top: 10px; color: var(--muted); font-size: .82rem; }
.explore-list { display: flex; flex-direction: column; gap: 12px; }
.explore-empty { text-align: center; color: var(--muted); padding: 26px 12px; line-height: 1.6; }
.entry { position: relative; background: var(--card-bg); border: 1px solid var(--border);
  border-radius: 14px; padding: 14px 16px; box-shadow: var(--shadow-card); }
.entry-pair { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.entry-src { font-size: 1.12rem; color: var(--text); font-weight: 600; }
.entry-arrow { color: var(--muted); }
.entry-tgt { font-size: 1.12rem; color: var(--cyan); font-weight: 700; }
.badge-dir { margin-left: auto; font-size: .64rem; font-weight: 700; letter-spacing: .02em;
  padding: 3px 9px; border-radius: 7px; color: #06121a; white-space: nowrap;
  background: linear-gradient(145deg, var(--cyan), var(--green)); }
.entry-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.entry-chip { font-size: .72rem; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--border);
  color: var(--muted); background: var(--panel2); white-space: nowrap; }
.entry-note { color: var(--muted); font-size: .8rem; font-style: italic; }
.entry-audio { display: flex; align-items: center; gap: 10px; margin-top: 10px; flex-wrap: wrap; }
.entry-audio audio { height: 38px; max-width: 300px; flex: 1 1 220px; }

/* ===== Lecteur audio SUR-MESURE (premium) ===== */
.aplayer-native { display: none !important; }   /* <audio> natif masqué : piloté par l'UI */
.aplayer { flex: 1 1 100%; width: 100%; box-sizing: border-box;
  display: flex; align-items: center; gap: clamp(8px, 2.5vw, 14px);
  padding: 10px clamp(10px, 3vw, 14px); border-radius: 14px;
  /* Cadre FUTURISTE (aucune photo) : verre foncé + halos diffus cyan (haut-gauche) et or
     (bas-droite), assortis à l'onde ; fin liseré lumineux + lueur d'ambiance. */
  background:
    radial-gradient(130% 180% at 0% 0%, color-mix(in srgb, var(--cyan) 16%, transparent), transparent 55%),
    radial-gradient(130% 180% at 100% 100%, color-mix(in srgb, var(--gold) 12%, transparent), transparent 55%),
    linear-gradient(180deg, color-mix(in srgb, var(--cyan) 6%, var(--panel)), var(--panel2));
  border: 1px solid color-mix(in srgb, var(--cyan) 32%, var(--border));
  box-shadow: 0 0 26px -14px var(--cyan), inset 0 1px 0 var(--card-sheen), var(--shadow-card); }
/* Bouton play/pause rond (aplat cyan, icône = couleur du fond → contraste 2 thèmes) */
.aplayer-play { position: relative; flex: 0 0 auto; width: clamp(42px, 12vw, 52px); height: clamp(42px, 12vw, 52px);
  border-radius: 50%; border: 0; cursor: pointer; display: grid; place-items: center;
  background: var(--cyan); box-shadow: 0 4px 14px -6px var(--cyan), 0 0 0 0 var(--cyan);
  transition: transform .12s ease, box-shadow .2s ease; }
.aplayer-play:hover { transform: translateY(-1px); box-shadow: 0 6px 18px -6px var(--cyan); }
.aplayer-play:active { transform: translateY(1px); }
.aplayer-play svg { width: 54%; height: 54%; fill: var(--bg); position: relative; z-index: 1; }
.aplayer-play .aplayer-ring { position: absolute; inset: -4px; border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--cyan) 45%, transparent); opacity: 0; }
.aplayer.is-playing .aplayer-play .aplayer-ring { opacity: 1; animation: aplayerPulse 1.8s ease-out infinite; }
@keyframes aplayerPulse { 0% { transform: scale(1); opacity: .7; } 100% { transform: scale(1.35); opacity: 0; } }
.aplayer-play:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; }
/* Zone centrale : onde + minuteur */
.aplayer-mid { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.aplayer-wave { width: 100%; height: clamp(34px, 9vw, 46px); display: block; cursor: pointer; touch-action: none; border-radius: 6px; }
.aplayer-wave:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
.aplayer-time { display: flex; gap: 5px; font-size: .74rem; color: var(--muted);
  font-variant-numeric: tabular-nums; letter-spacing: .01em; }
.aplayer-cur { color: var(--cyan); font-weight: 700; }
.aplayer-sep { opacity: .6; }
/* Volume : bouton + curseur (le curseur se replie sur petit écran) */
.aplayer-vol { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; }
.aplayer-mute { width: 34px; height: 34px; border-radius: 9px; border: 1px solid var(--border);
  background: var(--panel2); color: var(--text); cursor: pointer; display: grid; place-items: center;
  transition: border-color .15s ease, color .15s ease; }
.aplayer-mute svg { width: 20px; height: 20px; fill: currentColor; }
.aplayer-mute:hover { border-color: var(--cyan); color: var(--cyan); }
.aplayer-volslider { width: 74px; accent-color: var(--cyan); cursor: pointer; }
@media (max-width: 480px) { .aplayer-volslider { display: none; } }

/* ===== Consignes de transcription (boîte obligatoire) ===== */
.tr-guide { position: fixed; inset: 0; z-index: 10050; display: flex; align-items: center;
  justify-content: center; padding: 4vmin; overflow-y: auto;
  background: color-mix(in srgb, var(--bg) 80%, transparent); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
.tr-guide[hidden] { display: none; }
.tr-guide-card { width: 100%; max-width: 480px; box-sizing: border-box; margin: auto; overflow: hidden; text-align: center;
  background: var(--panel); border: 1px solid color-mix(in srgb, var(--cyan) 34%, var(--border));
  border-radius: 22px; box-shadow: 0 28px 70px -22px rgba(0,0,0,.55), 0 0 50px -26px var(--cyan); }
/* Deux variantes (Transcrire / Traduire) : on n'affiche que celle de l'activité. */
.tr-guide-variant { display: none; }
.tr-guide-card[data-show="transcribe"] .tr-guide-variant[data-guide="transcribe"],
.tr-guide-card[data-show="translate"] .tr-guide-variant[data-guide="translate"] { display: block; }
/* En-tête accentué (bandeau) */
.tr-guide-head { padding: 24px 24px 18px;
  background: linear-gradient(160deg, color-mix(in srgb, var(--cyan) 14%, var(--panel)), var(--panel));
  border-bottom: 1px solid color-mix(in srgb, var(--cyan) 18%, var(--border)); }
.tr-guide-ico { width: 62px; height: 62px; margin: 0 auto 8px; border-radius: 50%; display: grid; place-items: center;
  font-size: 1.9rem; color: #06121a; background: linear-gradient(145deg, var(--cyan), var(--green));
  box-shadow: 0 0 28px -6px var(--cyan); }
/* Variante avec icône SVG (ex-icône Transcrire déplacée ici) : pas de pastille,
   l'icône premium s'affiche seule. */
.tr-guide-ico--img { width: auto; height: auto; background: none; box-shadow: none; }
.tr-guide-ico--img img { width: 66px; height: 66px; display: block;
  filter: drop-shadow(0 4px 10px rgba(0,0,0,.4)); }
.tr-guide-card h2 { margin: 2px 0 4px; font-size: 1.32rem; color: var(--text); }
.tr-guide-lead { margin: 0; color: var(--muted); font-size: .92rem; }
/* Règles en cartes, avec icône + mots-clés surlignés */
.tr-guide-rules { padding: 18px 20px 2px; display: flex; flex-direction: column; gap: 11px; }
.tr-guide-rule { display: flex; align-items: flex-start; gap: 13px; text-align: left; padding: 12px 14px; border-radius: 14px;
  background: color-mix(in srgb, var(--cyan) 5%, var(--panel2)); border: 1px solid var(--border); }
.tr-guide-ri { flex: 0 0 auto; width: 38px; height: 38px; border-radius: 11px; display: grid; place-items: center;
  font-size: 1.2rem; background: var(--panel); border: 1px solid color-mix(in srgb, var(--cyan) 30%, var(--border)); }
.tr-guide-rtext b { display: block; color: var(--text); font-size: 1rem; line-height: 1.4; margin-bottom: 3px; }
.tr-guide-rtext span { color: var(--muted); font-size: .88rem; line-height: 1.5; }
/* Mise en évidence par la COULEUR DU TEXTE seule (pas de fond « surligneur »). */
.tr-guide-rtext mark { background: transparent; padding: 0; font-weight: 800; }
.tr-guide-rtext mark.ok { color: var(--green); }
.tr-guide-rtext mark.no { color: var(--red); }
/* Deux cartes d'exemple étiquetées (À éviter / À faire) */
.tr-guide-ex { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 14px 20px 2px; }
.tr-guide-ex-card { display: flex; flex-direction: column; gap: 5px; align-items: center; padding: 12px 10px; border-radius: 14px; }
.tr-guide-ex-label { font-size: .72rem; font-weight: 800; letter-spacing: .03em; text-transform: uppercase; }
.tr-guide-ex-txt { font-size: 1.05rem; font-weight: 800; }
.tr-guide-ex-card.bad { background: color-mix(in srgb, var(--red) 10%, var(--panel)); border: 1px solid color-mix(in srgb, var(--red) 38%, var(--border)); }
.tr-guide-ex-card.bad .tr-guide-ex-label { color: var(--red); }
.tr-guide-ex-card.bad .tr-guide-ex-txt { color: var(--red); display: inline-flex; align-items: center; gap: 8px; }
/* Panneau « INTERDIT » (cercle rouge barré en diagonale) devant le mot à éviter : bien plus
   parlant qu'un simple barré. Dessiné en CSS → net, à la couleur de marque, sombre comme clair. */
.tr-guide-ex-card.bad .tr-guide-ex-txt::before {
  content: ""; flex: 0 0 auto; width: 1.15em; height: 1.15em; border-radius: 50%;
  border: 2.2px solid var(--red);
  background: linear-gradient(45deg, transparent calc(50% - 1.3px), var(--red) calc(50% - 1.3px),
    var(--red) calc(50% + 1.3px), transparent calc(50% + 1.3px)); }
.tr-guide-ex-card.good { background: color-mix(in srgb, var(--green) 10%, var(--panel)); border: 1px solid color-mix(in srgb, var(--green) 38%, var(--border)); }
.tr-guide-ex-card.good .tr-guide-ex-label { color: var(--green); }
.tr-guide-ex-card.good .tr-guide-ex-txt { color: var(--green); }
.tr-guide-ok { display: block; width: calc(100% - 40px); margin: 10px 20px 22px; }
@media (max-width: 380px) { .tr-guide-ex { grid-template-columns: 1fr; } }
/* En TRANSCRIRE, l'enregistrement (le cœur de l'activité) vient JUSTE APRÈS le mot
   source, AVANT la traduction (facultative ici). On réordonne via flex `order` — les
   contrôles du haut (mode, proposition, sens) gardent leur place (order 0 par défaut). */
#work-card { display: flex; flex-direction: column; gap: 16px; }
/* Chaque grande zone est ENCADRÉE avec sa couleur d'identité, pour une démarcation
   nette : mot source = bleu, traduction = vert, voix = violet. Le libellé (plus grand,
   coloré) coiffe SA zone et colle au champ → on voit à quoi il se rapporte. */
.zone { --acc: var(--cyan); position: relative;
  border: 1px solid color-mix(in srgb, var(--acc) 42%, var(--border));
  border-left: 4px solid var(--acc); border-radius: 14px; padding: 13px 16px 15px;
  background: color-mix(in srgb, var(--acc) 7%, var(--card-bg));
  box-shadow: 0 0 28px -20px var(--acc), inset 0 1px 0 var(--card-sheen), inset 0 -1px 0 var(--card-inner);
  transition: box-shadow .2s ease, border-color .2s ease; }
/* Liseré gauche lumineux + intensification quand on écrit dans la zone (interactif, pas d'animation continue = perf de frappe préservée). */
.zone::before { content: ""; position: absolute; left: 0; top: 8px; bottom: 8px; width: 4px; border-radius: 4px;
  box-shadow: 0 0 14px 0 var(--acc); opacity: .55; pointer-events: none; }
.zone:focus-within { border-color: color-mix(in srgb, var(--acc) 62%, var(--border));
  box-shadow: 0 0 40px -12px var(--acc), inset 0 1px 0 var(--card-sheen), inset 0 -1px 0 var(--card-inner); }
.zone:focus-within::before { opacity: 1; }
.zone--source { --acc: var(--blue); }
.zone--target { --acc: var(--green); }
.zone--audio  { --acc: var(--violet); }
.zone > .field-label, .zone > .audio-label {
  font-size: 1rem; font-weight: 700; color: var(--acc); margin: 0 0 10px;
  letter-spacing: .005em; }
/* La ligne d'enregistrement n'a plus son propre cadre : la zone violette l'encadre. */
.zone--audio .audio-row { margin-top: 0; padding: 0; border: none; background: transparent; }
.zone--audio #mic-diag { margin-top: 10px; }
/* Mode TRANSCRIRE : la voix passe juste après le mot source (avant la traduction,
   facultative ici). Contrôles du haut = order 0 (gardent leur place). */
/* Transcrire : source, puis l'AUDIO (principal) et domaine/note, puis la traduction OPTIONNELLE
   (repliée derrière « Ajouter une traduction ») TOUT EN BAS, juste avant « Enregistrer ». */
#view-app[data-act="transcribe"] #source-wrap     { order: 1; }
#view-app[data-act="transcribe"] .zone--audio     { order: 2; }
#view-app[data-act="transcribe"] .grid2           { order: 3; }
#view-app[data-act="transcribe"] #add-translation { order: 4; }
#view-app[data-act="transcribe"] #target-wrap     { order: 5; }
#view-app[data-act="transcribe"] .actions         { order: 6; }
/* Traduire : source, la TRADUCTION (principale) et domaine/note, puis l'audio OPTIONNEL
   (replié derrière « Ajouter une transcription ») TOUT EN BAS, juste avant « Enregistrer ». */
#view-app[data-act="translate"] #source-wrap        { order: 1; }
#view-app[data-act="translate"] #target-wrap        { order: 2; }
#view-app[data-act="translate"] .grid2              { order: 3; }
#view-app[data-act="translate"] #add-transcription  { order: 4; }
#view-app[data-act="translate"] .zone--audio        { order: 5; }
#view-app[data-act="translate"] .actions            { order: 6; }
/* « Revoir les consignes » : DEUX emplacements selon la consigne du moment.
   - Transcrire : le bouton reste dans la zone audio (#tr-guide-open, défaut).
   - Traduire : il passe sur la LIGNE du label « Traduction [langue] », à droite
     (#tr-guide-open-t), et celui de la zone audio est masqué. */
#tr-guide-open-t { display: none; }
/* Transcrire : « revoir les consignes » vit sur la LIGNE du label audio, repoussé à droite.
   Traduire : il passe sur la ligne du label « Traduction » (#tr-guide-open-t) et l'autre est masqué. */
#view-app[data-act="translate"] #tr-guide-open { display: none; }
#view-app[data-act="translate"] #tr-guide-open-t { display: inline-flex; }
.audio-label { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
/* « Revoir les consignes » : TOUJOURS sur sa PROPRE ligne (sous le label), pleine
   largeur, texte sur une seule ligne, MÊME rendu en Traduire et en Transcrire. */
.tr-guide-open { flex: 0 0 100%; margin-left: 0; justify-content: center; margin-top: 8px; }
.entry-audio-alt { color: var(--cyan); font-size: .78rem; font-weight: 600; text-decoration: none; white-space: nowrap; }
.entry-audio-alt:hover { text-decoration: underline; }
.entry-foot { display: flex; align-items: center; gap: 10px; margin-top: 10px; flex-wrap: wrap; }
.entry-credit { color: var(--green); font-size: .8rem; font-weight: 600; }
.entry-date { color: var(--muted); font-size: .72rem; margin-left: auto; }

/* ---- Explorer NIVEAU 1 : grille de cadres (un par mot/expression) ---- */
.explore-groups { display: grid; grid-template-columns: repeat(auto-fill, minmax(238px, 1fr)); gap: 12px; }
.explore-detail { display: block; }
/* Explorer = OR : accent doré (liseré gauche + lavis + halo au survol) ; le cyan
   reste réservé aux liens/données pour l'affordance. */
.grp-card { --acc: var(--gold); position: relative; overflow: hidden; display: flex; flex-direction: column; gap: 9px;
  background: radial-gradient(130% 62% at 0% 0%, color-mix(in srgb, var(--gold) 11%, transparent), transparent 56%), var(--card-bg);
  border: 1.5px solid transparent; border-radius: 14px;
  padding: 13px 15px 13px 17px; cursor: pointer;
  box-shadow: 0 0 24px -18px var(--gold), var(--shadow-card), inset 0 1px 0 var(--card-sheen), inset 0 -1px 0 var(--card-inner);
  transition: box-shadow .16s ease, transform .16s ease; }
/* Bordure or vive tout autour (statique → perf), avec halo. Anneau au masque. */
.grp-card::before { content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1.5px; z-index: 2; pointer-events: none;
  background: linear-gradient(140deg, var(--gold), color-mix(in srgb, var(--gold) 35%, var(--cyan)) 70%, var(--gold));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  filter: drop-shadow(0 0 4px color-mix(in srgb, var(--gold) 48%, transparent)); }
/* Balayage shimmer au survol. */
.grp-card::after { content: ""; position: absolute; inset: 0; border-radius: inherit; z-index: 1; pointer-events: none;
  background: linear-gradient(115deg, transparent 30%, color-mix(in srgb, var(--gold) 42%, #fff) 50%, transparent 70%);
  opacity: 0; transform: translateX(-120%); }
.grp-card:hover, .grp-card:focus-visible {
  box-shadow: 0 20px 46px -14px var(--gold), 0 0 38px -10px var(--gold), 0 0 0 1.5px color-mix(in srgb, var(--gold) 55%, transparent),
    var(--shadow-card), inset 0 1px 0 var(--card-sheen); transform: translateY(-4px); outline: none; }
.grp-card:hover::after, .grp-card:focus-visible::after { animation: ngShimmer 820ms ease; }
.grp-head { display: flex; align-items: center; gap: 10px; }
.grp-word { font-size: 1.16rem; font-weight: 700; color: var(--text); overflow-wrap: anywhere; }
.grp-head .badge-dir { margin-left: auto; }
.grp-metrics { display: flex; gap: 7px; flex-wrap: wrap; }
.grp-m { font-size: .74rem; font-weight: 600; color: var(--text); background: var(--panel2);
  border: 1px solid var(--border); border-radius: 999px; padding: 2px 9px; }
.grp-villages { display: flex; gap: 6px; flex-wrap: wrap; }
.grp-foot { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 2px; }
.grp-consensus { font-size: .78rem; color: var(--muted); line-height: 1.4; }
.grp-consensus.is-ok { color: var(--green); font-weight: 600; }
.grp-open { margin-left: auto; color: var(--cyan); font-size: .78rem; font-weight: 700; white-space: nowrap; }

/* ---- Explorer NIVEAU 2 : détail d'un mot (propositions par village) ---- */
.grp-detail { display: flex; flex-direction: column; gap: 12px; }
.grp-back { align-self: flex-start; border: 1px solid var(--border); background: var(--panel2);
  color: var(--cyan); border-radius: 10px; padding: 7px 13px; cursor: pointer; font: inherit;
  font-size: .82rem; font-weight: 600; transition: border-color .15s ease, box-shadow .15s ease; }
.grp-back:hover { border-color: var(--cyan); box-shadow: 0 0 14px -6px var(--cyan); }
.grp-detail-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.grp-detail-head .grp-word { font-size: 1.5rem; }
.grp-intro { color: var(--muted); font-size: .86rem; line-height: 1.55; margin: 0; }
.grp-missing { padding: 10px 12px; border-radius: 10px; font-size: .85rem; line-height: 1.5;
  background: rgba(217,119,6,.12); border: 1px solid rgba(217,119,6,.42); color: var(--text); }
.vil-block { border: 1px solid var(--border); border-radius: 14px; padding: 13px 15px; background: var(--panel); }
.vil-title { display: flex; align-items: baseline; gap: 10px; color: var(--text); font-weight: 700; font-size: 1rem; }
.vil-count { color: var(--muted); font-size: .76rem; font-weight: 500; }
.vil-note { margin-top: 8px; padding: 9px 11px; border-radius: 10px; font-size: .82rem; line-height: 1.5; }
.vil-diff { background: rgba(217,119,6,.13); border: 1px solid rgba(217,119,6,.5); color: var(--text); }
.vil-same { background: rgba(5,150,105,.12); border: 1px solid rgba(5,150,105,.4); color: var(--text); }
.vil-neutral { background: var(--panel2); border: 1px solid var(--border); color: var(--muted); }
.vil-block .corr-consensus { margin-top: 8px; }
.entry--prop { margin-top: 10px; }
.entry-tgt--empty { color: var(--muted); font-weight: 500; font-style: italic; font-size: .95rem; }

/* ---- Corrections & consensus (par entrée) ---- */
.entry-improve { margin-top: 10px; border: 1px solid var(--border); background: var(--panel2);
  color: var(--cyan); border-radius: 10px; padding: 8px 12px; cursor: pointer; font: inherit;
  font-size: .82rem; font-weight: 600; transition: border-color .15s ease, box-shadow .15s ease; }
.entry-improve:hover { border-color: var(--cyan); box-shadow: 0 0 14px -6px var(--cyan); }
/* Vote à 3 états : juste ✓ VERT, doute ? JAUNE, faux ✗ ROUGE. Chaque bouton porte
   SA couleur d'emblée (reconnaissable au premier coup d'œil) ; le mélange vers
   --text garde le contraste lisible dans les deux thèmes. Le choix du locuteur
   ressort (is-mine : rempli + halo). Re-clic sur son choix = annulation. */
.entry-vote { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin: 9px 0 2px; }
.ev-lbl { font-size: .8rem; color: var(--muted); margin-right: 1px; }
.ev-ok    { --evc: var(--green); }
.ev-doubt { --evc: var(--gold); }
.ev-no    { --evc: var(--red); }
.ev-btn { display: inline-flex; align-items: center; gap: 5px; font: inherit; font-size: .82rem; font-weight: 700;
  cursor: pointer; border-radius: 999px; padding: 4px 11px; white-space: nowrap;
  color: color-mix(in srgb, var(--evc) 62%, var(--text));
  border: 1.5px solid color-mix(in srgb, var(--evc) 42%, var(--border));
  background-color: color-mix(in srgb, var(--evc) 7%, var(--panel2));
  background-image: linear-gradient(180deg, rgba(255,255,255,.05), rgba(255,255,255,0));
  box-shadow: inset 0 1px 0 var(--card-sheen); transition: color .14s, border-color .14s, background .14s, box-shadow .14s, transform .1s; }
.ev-btn:active { transform: translateY(1px); }
.ev-btn .ev-n { font-weight: 800; }
.ev-btn:hover { border-color: var(--evc); box-shadow: 0 0 13px -5px var(--evc), inset 0 1px 0 var(--card-sheen); }
.ev-btn.is-mine { color: var(--evc); border-color: var(--evc);
  background-color: color-mix(in srgb, var(--evc) 20%, var(--panel2));
  box-shadow: 0 0 15px -4px var(--evc), inset 0 1px 0 var(--card-sheen); }
.entry-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 10px; }
.entry-actions .entry-improve { margin-top: 0; }
.entry-share { border: 1px solid var(--border); background: var(--panel2); color: var(--txt-dim);
  border-radius: 10px; padding: 8px 12px; cursor: pointer; font: inherit; font-size: .82rem;
  font-weight: 600; transition: border-color .15s ease, box-shadow .15s ease, color .15s ease; }
.entry-share:hover { border-color: var(--gold); color: var(--gold); box-shadow: 0 0 14px -6px var(--gold); }
/* CTA « Dis-le dans ta langue » : couleur de l'activité Traduire (vert), invite à contribuer. */
.entry-saymine { border: 1px solid var(--green); background: var(--panel2); color: var(--green);
  border-radius: 10px; padding: 8px 12px; cursor: pointer; font: inherit; font-size: .82rem;
  font-weight: 600; transition: border-color .15s ease, box-shadow .15s ease, background .15s ease; }
.entry-saymine:hover { background: var(--green); color: var(--bg); box-shadow: 0 0 16px -5px var(--green); }
.entry-corr { margin-top: 12px; padding-top: 12px; border-top: 1px dashed var(--border); }
.entry-corr[hidden] { display: none; }
.corr-loading, .corr-empty { color: var(--muted); font-size: .84rem; padding: 6px 0; }
.corr-consensus { padding: 10px 12px; border-radius: 10px; margin-bottom: 10px;
  background: rgba(5,150,105,.12); border: 1px solid rgba(5,150,105,.45); font-size: .88rem; line-height: 1.5; }
.corr-win { color: var(--green); font-weight: 700; }
.corr-wvotes { color: var(--muted); font-size: .78rem; }
.corr-noconsensus { color: var(--muted); font-size: .82rem; margin-bottom: 10px; font-style: italic; }
.corr-sub { font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); margin: 12px 0 6px; }
.corr-cand { display: flex; align-items: center; gap: 10px; justify-content: space-between;
  padding: 8px 10px; border-radius: 9px; border: 1px solid var(--border); background: var(--panel2); margin-bottom: 6px; }
.corr-cand.is-win { border-color: rgba(5,150,105,.55); box-shadow: 0 0 0 1px rgba(5,150,105,.25) inset; }
.corr-cand-txt { color: var(--text); font-size: .95rem; }
.corr-tag { font-size: .6rem; text-transform: uppercase; letter-spacing: .03em; color: var(--muted);
  border: 1px solid var(--border); border-radius: 999px; padding: 1px 7px; margin-left: 6px; }
.corr-vote { border: 1px solid var(--border); background: var(--panel); color: var(--cyan);
  border-radius: 999px; padding: 5px 12px; cursor: pointer; font: inherit; font-size: .82rem; font-weight: 600;
  white-space: nowrap; transition: border-color .14s ease, box-shadow .14s ease; }
.corr-vote:hover { border-color: var(--cyan); box-shadow: 0 0 12px -5px var(--cyan); }
.corr-vote:disabled { opacity: .5; cursor: default; }
.corr-com { color: var(--text); font-size: .86rem; padding: 5px 0; border-bottom: 1px solid var(--hairline); }
.corr-credit { color: var(--green); font-size: .76rem; }
.corr-form { margin-top: 12px; }
.corr-form-row { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.corr-form-row .combo--select { flex: 0 0 220px; }
.corr-text-wrap, .corr-audio-wrap { margin-bottom: 8px; }
.corr-text-wrap { display: flex; flex-direction: column; gap: 6px; }
.corr-text-wrap[hidden], .corr-audio-wrap[hidden] { display: none; }
.corr-text { width: 100%; }
.corr-kb-btn { align-self: flex-start; border: 1px solid rgba(34,211,238,.5); background: var(--panel2);
  color: var(--cyan); border-radius: 9px; padding: 6px 12px; cursor: pointer; font: inherit;
  font-size: .8rem; font-weight: 600; transition: border-color .15s ease, box-shadow .15s ease; }
.corr-kb-btn:hover { border-color: var(--cyan); box-shadow: 0 0 14px -6px var(--cyan); }
.corr-kb-btn[hidden] { display: none; }
.corr-audio-wrap { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.corr-rec { padding: 8px 14px; font-size: .85rem; }
.corr-rec-timer { font-size: .92rem; }
.corr-rec-preview audio { height: 34px; max-width: 200px; }
/* Lecteur audio intégré Google Drive (dernier recours) + statut de chargement. */
.entry-audio-frame { width: 100%; max-width: 340px; height: 62px; border: 0; border-radius: 10px; background: var(--panel2); }
.entry-audio-status { color: var(--muted); font-size: .76rem; }
.corr-submit { border: 1px solid var(--cyan); color: var(--bg); font-weight: 700;
  background: var(--cyan); border-radius: 10px;
  padding: 9px 16px; cursor: pointer; font: inherit; font-size: .86rem; }
.corr-submit:hover { box-shadow: 0 0 18px -6px var(--cyan); }
.corr-submit:disabled { opacity: .5; cursor: default; }

/* Contributeur */
.contrib summary { cursor: pointer; font-weight: 600; }
.hint-inline { color: var(--muted); font-weight: 400; font-size: .8rem; }
.contrib-why { color: var(--muted); font-size: .8rem; line-height: 1.5; margin: 10px 0 2px; }
.req { color: var(--red); font-weight: 700; }
/* Bouton d'amorce sous le seuil : « M'arrêter pour l'instant » (le travail est gardé, langue
   provisoire à compléter). Aspect secondaire NEUTRE (pas destructif). */
.btn--next.amorce-stop { background: transparent; color: var(--muted);
  border: 1.5px solid var(--border); box-shadow: none; animation: none; filter: none; }
.btn--next.amorce-stop:hover { background: var(--panel); color: var(--text); transform: none; }
.tel-row { display: flex; gap: 8px; flex-wrap: wrap; }
.tel-ind { flex: 1 1 148px; min-width: 128px; }
.tel-num { flex: 2 1 150px; }
.gate {
  margin: 0 0 6px; padding: 12px 16px; border-radius: 12px;
  background: rgba(229,192,123,.10); border: 1px solid rgba(229,192,123,.5);
  color: var(--gold); font-size: .88rem; line-height: 1.4;
}
.gate[hidden] { display: none; }
.btn:disabled, .btn--next:disabled, .btn--send:disabled {
  opacity: .45; cursor: not-allowed; transform: none; box-shadow: none;
}
/* Mention explicative sous un bouton verrouillé (profil incomplet) */
.lock-hint {
  margin: 10px 0 0; padding: 9px 12px; border-radius: 10px;
  background: rgba(229,192,123,.10); border: 1px solid rgba(229,192,123,.45);
  color: var(--gold); font-size: .82rem; line-height: 1.45;
}
.lock-hint[hidden] { display: none; }
.lock-hint b { color: #f4d68a; }

/* --- Footer --- */
.site-footer {
  flex-shrink: 0;   /* toujours ancré en bas, ne se comprime jamais */
  margin-top: 28px; border-top: 1px solid var(--border);
  /* EXACTEMENT le même verre que le header : même fond translucide (--header-bg)
     et même flou. Rien peint par-dessus (ni trame, ni dégradé) → le flou du fond
     derrière le footer se voit, comme sur le header. */
  background: var(--header-bg);
  backdrop-filter: blur(18px) saturate(1.3);
  -webkit-backdrop-filter: blur(18px) saturate(1.3);
  padding: 26px clamp(14px, 4vw, 36px) 18px;
}
.foot-inner {
  max-width: var(--wrap-max); margin: 0 auto; display: flex; align-items: flex-start;
  justify-content: space-between; gap: 24px 44px; flex-wrap: wrap;
}
/* Raccourcis thématiques au milieu du footer. */
.foot-nav { display: flex; gap: 18px 46px; flex-wrap: wrap; }
.foot-nav-col { display: flex; flex-direction: column; gap: 7px; }
.foot-nav-title { color: var(--gold); font-size: .7rem; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; margin-bottom: 3px; }
.foot-nav a { color: var(--label); font-size: .87rem; text-decoration: none;
  width: fit-content; transition: color .14s ease, transform .14s ease; }
.foot-nav a:hover { color: var(--cyan); transform: translateX(2px); }
.foot-brand { display: flex; align-items: center; gap: 13px; }
.foot-mark {
  width: 52px; height: 52px; display: block; border-radius: 14px;
  box-shadow: 0 6px 16px -4px rgba(0,0,0,.4);   /* l'aura ::before/::after fournit la lueur cyan */
}
.foot-mark img { width: 100%; height: 100%; display: block; border-radius: 13px; }
/* Nom du footer : MÊME traitement que le header (dégradé clair→cyan→vert en text-clip),
   agrandi et aligné avec le logo (plus de blanc plat). */
.foot-title { font-family: var(--font-mono); font-weight: 600; letter-spacing: -.02em;
  font-size: 1.55rem; line-height: 1.03;
  background: linear-gradient(100deg, #eafcff 0%, var(--cyan) 45%, var(--green) 100%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: var(--cyan); }
.foot-title span { -webkit-text-fill-color: var(--green); color: var(--green); font-weight: 700; font-size: .5em; }
.foot-sub { color: var(--muted); font-size: .82rem; margin-top: 3px; }
/* Logo + nom cliquables → accueil (header et footer). Affordance sobre : curseur,
   soulignement du nom au survol, contour net au focus clavier (pas de dégradé
   qui ferait fondre l'élément dans le fond). */
.brand--home, .foot-brand--home { cursor: pointer; }
.brand--home:hover .brand-txt h1,
.foot-brand--home:hover .foot-title { text-decoration: underline; text-underline-offset: 3px; }
.brand--home:focus-visible, .foot-brand--home:focus-visible {
  outline: 2px solid var(--cyan); outline-offset: 4px; border-radius: 12px; }
.foot-info { text-align: right; }
.foot-by { margin: 0 0 4px; color: var(--text); font-size: .92rem; }
.foot-contact { margin: 0; color: var(--muted); font-size: .82rem; }
.foot-contact a { color: var(--cyan); text-decoration: none; font-weight: 600; }
.foot-contact a:hover { text-decoration: underline; }
/* Barre du bas : liens légaux à gauche, copyright à droite, sur une seule ligne. */
.foot-bottom {
  max-width: var(--wrap-max); margin: 16px auto 0; padding-top: 12px;
  border-top: 1px solid var(--hairline);
  display: flex; align-items: center; justify-content: space-between; gap: 8px 22px; flex-wrap: wrap;
}
.foot-copy { color: var(--muted); font-size: .72rem; }
@media (max-width: 560px) {
  .foot-inner { flex-direction: column; align-items: flex-start; }
  .foot-info { text-align: left; }
}
/* Liens légaux du pied de page + page légale */
.foot-legal { display: flex; flex-wrap: wrap; gap: 6px 18px; }
.foot-legal-link { color: var(--muted); font-size: .74rem; text-decoration: none;
  transition: color .14s ease; }
.foot-legal-link:hover { color: var(--cyan); text-decoration: underline; }
.legal-nav { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 18px; }
.legal-navlink { text-decoration: none; font-size: .82rem; font-weight: 600; color: var(--cyan);
  border: 1px solid var(--border); border-radius: 999px; padding: 6px 14px;
  transition: background .14s ease, color .14s ease, border-color .14s ease; }
.legal-navlink:hover { border-color: var(--cyan); background: color-mix(in srgb, var(--cyan) 10%, var(--panel)); }
.legal-navlink.is-active { background: var(--cyan); color: var(--bg); border-color: var(--cyan); }
.legal-content { max-width: 760px; }
.legal-sec { margin: 0 0 26px; padding: 18px 20px; border-radius: 14px;
  background: var(--panel); border: 1px solid var(--border); scroll-margin-top: 16px; }
.legal-h { margin: 0 0 12px; font-size: 1.12rem; color: var(--text);
  border-bottom: 1px solid var(--hairline); padding-bottom: 8px; }
.legal-body { color: var(--text); font-size: .9rem; line-height: 1.65; }
.legal-body p { margin: 0 0 10px; }
.legal-body b { color: var(--text); }
.legal-body a { color: var(--cyan); }
.contrib .grid2 { margin-top: 14px; }
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 560px) { .grid2 { grid-template-columns: 1fr; } }

.field { display: flex; flex-direction: column; gap: 6px; }
/* `.field { display:flex }` écrasait l'attribut [hidden] (même piège que .chip, cf. plus haut) :
   la section optionnelle repliée (#target-wrap en Transcrire, #audio-wrap en Traduire) restait
   VISIBLE malgré hidden. On rend la main à [hidden]. */
#target-wrap[hidden], #audio-wrap[hidden] { display: none !important; }
/* Infobulle par champ : petit ⓘ en coin haut-droit + popover au clic. */
.field.has-tip { position: relative; }
.field-tip { position: absolute; top: 0; right: 0; width: 22px; height: 22px; padding: 0;
  border: none; background: none; cursor: pointer; color: var(--cyan); font-size: 1.02rem; line-height: 22px;
  border-radius: 999px; opacity: .78; transition: opacity .14s, transform .1s, background .14s; z-index: 2; }
.field-tip:hover { opacity: 1; background: color-mix(in srgb, var(--cyan) 16%, transparent); }
.field-tip:active { transform: scale(.92); }
.field-tip-pop { position: absolute; top: 26px; right: 0; z-index: 30; max-width: min(320px, 88vw);
  padding: 10px 12px; border-radius: 12px; font-size: .84rem; line-height: 1.45; font-weight: 400;
  color: var(--text); background: var(--card-bg);
  border: 1.5px solid color-mix(in srgb, var(--cyan) 45%, var(--border));
  box-shadow: 0 14px 40px rgba(0,0,0,.4), 0 0 22px -8px var(--cyan), inset 0 1px 0 var(--card-sheen);
  animation: updIn .2s ease both; }
.field > span, .field-label { color: var(--label); font-size: .8rem; font-weight: 500;
  letter-spacing: .01em; }
.field-label { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; flex-wrap: wrap; }
.lang-tag {
  font-family: var(--font-mono);
  font-size: .66rem; font-weight: 600; letter-spacing: 0;
  padding: 3px 10px; border-radius: 7px; color: #06121a; white-space: nowrap;
  background: linear-gradient(145deg, var(--cyan), var(--green));
}
.field--check { flex-direction: row; align-items: flex-start; gap: 10px; }
.field--check span { color: var(--text); font-size: .82rem; line-height: 1.35; }
.field--check input { margin-top: 3px; }

/* Bloc consentement — pleine largeur + fortement mis en évidence : on ne doit pas
   pouvoir le rater (sinon « Continuer » reste grisé sans qu'on comprenne pourquoi). */
.contrib .grid2 .field--consent { grid-column: 1 / -1; }
.field--consent {
  align-items: center; gap: 14px; margin-top: 2px;
  padding: 14px 16px; border-radius: 14px;
  background: linear-gradient(120deg, rgba(8,145,178,.12), rgba(5,150,105,.07)), var(--panel);
  border: 1.5px solid rgba(8,145,178,.45);
  transition: border-color .2s ease, box-shadow .2s ease, background .2s ease;
}
.field--consent input {
  width: 24px; height: 24px; flex: 0 0 auto; margin-top: 0;
  accent-color: var(--cyan); cursor: pointer;
}
.field--consent span { color: var(--text); font-size: .9rem; font-weight: 500; line-height: 1.4; }
/* Tant que non coché : un halo respire pour attirer l'œil. Une fois coché :
   la boîte passe au vert et se calme (feedback clair « c'est bon »). */
.field--consent:not(.is-checked) { animation: ngConsentPulse 2.4s ease-in-out infinite; }
.field--consent.is-checked {
  border-color: rgba(5,150,105,.6);
  background: linear-gradient(120deg, rgba(5,150,105,.16), rgba(8,145,178,.07)), var(--panel);
}
@keyframes ngConsentPulse {
  0%,100% { box-shadow: 0 0 0 1px rgba(8,145,178,.16) inset; }
  50%     { box-shadow: 0 0 0 1px rgba(8,145,178,.42) inset, 0 0 18px rgba(8,145,178,.30); }
}

/* Bloc crédit (facultatif, opt-in) — pleine largeur, sobre, sans halo pulsant */
.contrib .grid2 .field--credit,
.contrib .grid2 #credit-format-wrap { grid-column: 1 / -1; }
.field--credit {
  align-items: center; gap: 12px; margin-top: 2px;
  padding: 12px 14px; border-radius: 12px;
  background: var(--panel2); border: 1px dashed var(--border);
}
.field--credit input { width: 22px; height: 22px; flex: 0 0 auto; margin-top: 0;
  accent-color: var(--cyan); cursor: pointer; }
.field--credit span { color: var(--text); font-size: .86rem; line-height: 1.4; }
.credit-preview { color: var(--cyan); font-size: .82rem; font-weight: 600; }

input[type="text"], select, textarea {
  width: 100%; background: var(--bg); color: var(--text);
  border: 1px solid var(--border); border-radius: 11px;
  padding: 11px 13px; font-size: 1rem; font-family: inherit;
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}
textarea {
  resize: vertical; font-size: 1.35rem; line-height: 1.5;
  background: linear-gradient(180deg, rgba(34,211,238,.035), rgba(0,0,0,0) 60%), var(--bg);
}
::placeholder { color: var(--placeholder); }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--cyan);
  box-shadow: 0 0 0 3px rgba(34,211,238,.22), 0 0 20px rgba(34,211,238,.14);
}
/* Champ où écrit le clavier ngiemboon : accent cyan permanent pour qu'on voie
   toujours d'un coup d'œil où le texte s'inscrit. */
#target-wrap textarea {
  border-color: rgba(34,211,238,.32);
  box-shadow: 0 0 0 1px rgba(34,211,238,.12) inset;
}
textarea:focus { box-shadow: 0 0 0 3px rgba(34,211,238,.28), 0 0 26px rgba(34,211,238,.20); }
/* Curseur clignotant (caret) coloré selon l'ACTIVITÉ : repère visuel du contexte de saisie.
   Cyan par défaut, vert en Traduire, violet en Transcrire, or dans Explorer. */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]), textarea { caret-color: var(--cyan); }
#view-app[data-act="translate"] :is(input, textarea) { caret-color: var(--green); }
#view-app[data-act="transcribe"] :is(input, textarea) { caret-color: var(--violet); }
#view-explore :is(input, textarea) { caret-color: var(--gold); }
/* Autofill : le navigateur force sinon un fond clair qui casse le thème sombre */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--text);
  -webkit-box-shadow: 0 0 0 40px var(--bg) inset;
  box-shadow: 0 0 0 40px var(--bg) inset;
  caret-color: var(--text);
  transition: background-color 100000s ease-in-out 0s;
}

/* Menu déroulant custom (village) : s'ouvre au clic, liste complète + « Autre » */
.combo { position: relative; }
.combo input { padding-right: 36px; }
.combo-toggle {
  position: absolute; right: 4px; top: 4px; bottom: 4px; width: 30px;
  background: transparent; border: none; color: var(--muted); cursor: pointer;
  font-size: 1rem; border-radius: 8px;
}
.combo-toggle:hover { color: var(--cyan); background: rgba(34,211,238,.08); }
.combo-list {
  position: absolute; z-index: 40; left: 0; right: 0; top: calc(100% + 4px);
  max-height: 240px; overflow-y: auto; margin: 0; padding: 4px; list-style: none;
  background: var(--panel2); border: 1px solid rgba(34,211,238,.45); border-radius: 12px;
  box-shadow: var(--shadow-drop);
}
.combo-list[hidden] { display: none; }
.combo-list li {
  padding: 9px 12px; border-radius: 8px; cursor: pointer; color: var(--text); font-size: .9rem;
}
.combo-list li:hover { background: rgba(34,211,238,.15); }
.combo-list li.combo-autre { color: var(--cyan); border-bottom: 1px solid var(--border); margin-bottom: 4px; font-style: italic; }
.combo-list li.is-sel { color: var(--cyan); font-weight: 600; }

/* Menu personnalisé « select » (Rôle) — même rendu que le combo Village, mais
   valeur choisie dans une liste (pas de saisie libre). Le vrai <select> est masqué. */
.combo-display {
  width: 100%; text-align: left; cursor: pointer;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--border); border-radius: 11px;
  padding: 11px 40px 11px 13px; font: inherit; font-size: 1rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: border-color .16s ease, box-shadow .16s ease;
}
/* Menu indicatif (dans la rangée téléphone) : liste un peu plus large que le champ */
.tel-ind.combo { min-width: 128px; }
.tel-ind .combo-list { left: 0; right: auto; min-width: 240px; max-width: 84vw; }
.combo-display.is-placeholder { color: var(--placeholder); }
.combo-display:hover, .combo-display:focus {
  outline: none; border-color: var(--cyan);
  box-shadow: 0 0 0 3px rgba(34,211,238,.18);
}
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Mode de saisie (proposer / libre) */
.mode-toggle {
  display: inline-flex; gap: 4px; padding: 4px; margin-bottom: 12px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 12px;
}
.prop-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 14px;
  padding: 10px 12px 10px 14px; position: relative;
  background: linear-gradient(120deg, rgba(34,211,238,.09), rgba(52,211,153,.05) 70%);
  border: 1px solid rgba(34,211,238,.28); border-radius: 12px;
}
/* Pas d'overflow:hidden ici, sinon la liste déroulante du menu « À traduire »
   (positionnée en absolu) serait rognée. Le liseré ::before garde ses coins
   arrondis via border-radius. */
.prop-bar::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: linear-gradient(180deg, var(--cyan), var(--green));
  border-radius: 12px 0 0 12px;
}
.prop-catwrap { color: var(--muted); font-size: .8rem; display: inline-flex; align-items: center; gap: 8px; }
.prop-cat {
  width: auto; background: var(--bg); color: var(--text); border: 1px solid var(--border);
  border-radius: 9px; padding: 6px 10px; font-size: .85rem;
}
.prop-progress { color: var(--cyan); font-size: .78rem; margin-left: auto; }
.prop-bar[hidden], .dir-toggle[hidden] { display: none; }

/* Sens de traduction */
.dir-toggle {
  display: inline-flex; gap: 4px; padding: 4px; margin-bottom: 16px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 12px;
}
.dir-btn {
  border: 1px solid var(--border); background: var(--panel2); color: var(--text);
  padding: 9px 15px; border-radius: 9px; cursor: pointer; font: inherit; font-size: .86rem;
  transition: background .15s ease, color .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.dir-btn:hover { border-color: var(--cyan); box-shadow: 0 0 14px -6px var(--cyan); }
.dir-btn.is-active {
  color: var(--bg); font-weight: 700; border-color: var(--cyan);
  background: var(--cyan);   /* sélecteur actif : aplat cyan (action), sans dégradé */
  box-shadow: 0 0 16px -4px var(--cyan);
}

/* Bloc clavier */
.kb-block { margin-top: 12px; }
.kb-bar { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.kb-bar-right { display: inline-flex; align-items: center; gap: 12px; }
.kb-label { color: var(--muted); font-size: .74rem; }
.kb-host { display: flex; justify-content: center; }
/* Barre de suggestions du clavier prédictif (mots RÉELS proposés à la frappe).
   Cyan = affordance (comme les autres éléments interactifs). Défile horizontalement
   si besoin, ne pousse jamais le clavier hors écran. */
.kb-suggest { display: flex; gap: 8px; overflow-x: auto; padding: 6px 6px 8px;
  scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.kb-suggest[hidden] { display: none; }
.kb-suggest::-webkit-scrollbar { display: none; }
.kb-sugg { flex: 0 0 auto; display: inline-flex; align-items: baseline; gap: 7px;
  font: inherit; cursor: pointer; white-space: nowrap;
  padding: 7px 14px; border-radius: 999px;
  color: var(--text);
  background: color-mix(in srgb, var(--cyan) 10%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--cyan) 42%, var(--border));
  box-shadow: 0 0 14px -8px var(--cyan);
  transition: border-color .14s ease, box-shadow .14s ease, transform .1s ease; }
.kb-sugg:hover { border-color: var(--cyan); box-shadow: 0 0 16px -5px var(--cyan); }
.kb-sugg:active { transform: translateY(1px); }
.kb-sugg-w { font-weight: 700; font-size: 1.02rem; color: var(--cyan); }
.kb-sugg-fr { font-size: .78rem; color: var(--muted); }
/* Clavier repliable : masqué par défaut, ouvert au focus du champ ngiemboon.
   OUVERT → ancré en BAS de l'écran (comme le clavier d'une messagerie) : il reste
   fixe pendant que le contenu défile au-dessus. */
.kb-panel { display: none; }
/* Ouvert, le panneau est DÉTACHÉ vers <body> (portail) et flotte ancré en bas :
   ainsi il est au niveau racine → TOUJOURS au premier plan, jamais recouvert par
   une carte ou le footer. */
.kb-panel.kb-floating {
  display: block;
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 900;
  max-height: 46vh; overflow-y: auto;      /* compact, façon clavier natif */
  background: var(--panel); border-top: 1px solid var(--border);
  padding: 3px 4px calc(4px + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 -12px 34px rgba(0,0,0,.28);
}
.kb-floating .kb-host { max-width: 640px; margin: 0 auto; }
/* Ancré = barre compacte : on masque le long libellé, on garde aide + croix ;
   zone d'aide phonétique amincie pour gagner de la place. */
.kb-floating .kb-bar { margin-bottom: 4px; }
.kb-floating .kb-label { display: none; }
/* Aide phonétique ancrée : amincie ET police réduite pour qu'elle tienne sur une
   ligne sans défilement horizontal (glyphe + [API] + description + exemple). */
.kb-floating .tip-panel.is-on { min-height: 26px; max-height: 2.9em; margin-bottom: 3px; padding: 3px 10px; gap: 0 9px; }
.kb-floating .tip-panel .tip-glyph { font-size: 1.15rem; }
.kb-floating .tip-panel .tip-prononce { font-size: .82rem; font-weight: 600; }
.kb-floating .tip-panel .tip-ipa   { font-size: .72rem; }
.kb-floating .tip-panel .tip-desc,
.kb-floating .tip-panel .tip-ex     { font-size: .72rem; }
.kb-floating .tip-panel .tip-ex .arrow { margin: 0 4px; }
.kb-block.is-open .kb-open-btn { display: none; }
/* de la place en bas pour que le champ puisse défiler AU-DESSUS du clavier ancré */
body.kb-docked { padding-bottom: var(--kb-h, 50vh); }
.kb-open-btn {
  width: 100%; margin-top: 4px; padding: 12px 14px; border-radius: 12px; cursor: pointer;
  font: inherit; font-size: .92rem; font-weight: 600; color: var(--cyan);
  background: var(--panel2); border: 1px dashed rgba(34,211,238,.5);
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}
.kb-open-btn:hover { border-color: var(--cyan); box-shadow: 0 0 16px -6px var(--cyan); }
/* Bouton FERMER bien mis en évidence (rouge, à droite) : n'importe quel
   utilisateur comprend d'un coup d'œil qu'il referme le clavier. */
.kb-close-btn {
  display: inline-flex; align-items: center; gap: 5px; margin-left: auto;
  border: 1.5px solid var(--red); background: rgba(239,68,68,.16); color: var(--red);
  border-radius: 999px; padding: 5px 13px; min-height: 30px; cursor: pointer;
  font: inherit; font-size: .8rem; font-weight: 700; line-height: 1; white-space: nowrap;
  box-shadow: 0 0 12px -4px var(--red);
  transition: background .14s ease, color .14s ease, box-shadow .14s ease, transform .12s ease;
}
.kb-close-btn:hover { background: var(--red); color: #fff; box-shadow: 0 0 16px -2px var(--red); }
.kb-close-btn:active { transform: scale(.95); }

/* Zone d'aide phonétique — juste au-dessus du clavier. Affiche la lettre pressée
   (grand glyphe + [API] + description + exemple → traduction). Masquée si l'aide
   est désactivée ; visible (hauteur réservée) quand elle est activée. */
.tip-panel { display: none; }
.tip-panel.is-on {
  /* Le texte peut s'étaler sur DEUX lignes au besoin (jamais de défilement
     horizontal). Le panneau est ancré en bas et grandit vers le HAUT → les
     touches ne bougent pas pendant la frappe. */
  display: flex; align-items: center; flex-wrap: wrap; gap: 1px 10px;
  min-height: 40px; max-height: 3.3em; box-sizing: border-box;
  margin-bottom: 8px; padding: 6px 12px;
  overflow: hidden; white-space: normal; line-height: 1.25;
  border-radius: 12px;
  background: var(--tip-bg);
  border: 1px solid rgba(34,211,238,.28);
  box-shadow: 0 0 0 1px rgba(34,211,238,.08) inset;
}
.tip-panel.is-on > * { flex: 0 1 auto; min-width: 0; }
.tip-panel .tip-glyph { font-size: 1.35rem; line-height: 1; color: var(--text); font-weight: 700; }
/* « Comment prononcer » = texte PRINCIPAL, bien lisible (peut passer à la ligne). */
.tip-panel .tip-prononce { color: var(--text); font-size: .92rem; font-weight: 600; white-space: normal; }
.tip-panel .tip-ipa { color: var(--cyan); font-size: .82rem; font-weight: 600; opacity: .85; }
.tip-panel .tip-desc { color: var(--text); font-size: .86rem; }
.tip-panel .tip-ex { color: var(--muted); font-size: .84rem; }
.tip-panel .tip-ex b { color: var(--green); }
.tip-panel .tip-ex .arrow { margin: 0 6px; color: var(--muted); }
.tip-panel .tip-empty { color: var(--muted); font-size: .82rem; font-style: italic; }
.switch-row { display: inline-flex; align-items: center; gap: 9px; color: var(--muted); font-size: .76rem; cursor: pointer; user-select: none; }
.switch { position: relative; width: 40px; height: 22px; }
.switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.slider { position: absolute; inset: 0; border-radius: 999px; background: var(--slider-off); border: 1px solid var(--border); transition: background .16s ease, border-color .16s ease; }
.slider::before { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: var(--muted); transition: transform .16s ease, background .16s ease; }
.switch input:checked + .slider { background: rgba(34,211,238,.22); border-color: var(--cyan); }
.switch input:checked + .slider::before { transform: translateX(18px); background: var(--cyan); box-shadow: 0 0 10px rgba(34,211,238,.7); }

/* Audio */
.audio-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 16px;
  padding: 10px 12px; border-radius: 12px; background: var(--panel2); border: 1px solid var(--border); }
.rec-state { color: var(--red); font-size: .8rem; min-width: 8ch; }
/* Cadre de progression audio : SEUL sur sa ligne, pleine largeur, aucun bouton devant
   (indispensable sur mobile). Les actions vont dans .audio-actions, dessous. */
.audio-preview { display: block; margin-top: 12px; }
.audio-preview:empty { display: none; }
.audio-preview audio { height: 38px; max-width: 260px; }
/* Ligne d'ACTIONS sous le cadre : Découper (cyan) + retirer (rouge), bien mis en
   évidence, alignés, jamais dispersés. N'apparaît que quand un enregistrement existe. */
.audio-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 12px; }
.audio-actions[hidden] { display: none; }
.audio-act { display: inline-flex; align-items: center; gap: 6px; border: 1.5px solid var(--border);
  background: var(--panel); color: var(--text); border-radius: 999px; padding: 9px 18px; cursor: pointer;
  font: inherit; font-size: .84rem; font-weight: 700; letter-spacing: .01em;
  transition: background .15s ease, color .15s ease, box-shadow .15s ease, transform .1s ease; }
.audio-act--trim { border-color: var(--cyan); color: var(--cyan);
  background: color-mix(in srgb, var(--cyan) 12%, var(--panel)); }
.audio-act--trim:hover { background: var(--cyan); color: var(--bg);
  transform: translateY(-1px); box-shadow: 0 0 18px -5px var(--cyan); }
.audio-act--del { border-color: var(--red); color: var(--red);
  background: color-mix(in srgb, var(--red) 12%, var(--panel)); }
.audio-act--del:hover { background: var(--red); color: var(--bg);
  transform: translateY(-1px); box-shadow: 0 0 18px -5px var(--red); }
.audio-act:active { transform: translateY(1px); }
.audio-info { color: var(--muted); font-size: .78rem; }
/* Timer d'enregistrement : pastille rouge qui pulse + temps écoulé (chiffres alignés) */
.rec-timer { display: inline-flex; align-items: center; gap: 9px; color: var(--red);
  font-weight: 700; font-variant-numeric: tabular-nums; font-size: 1.02rem; letter-spacing: .02em; }
.rec-timer[hidden] { display: none; }
.rec-timer::before { content: ""; width: 11px; height: 11px; border-radius: 50%; background: var(--red);
  box-shadow: 0 0 10px 1px var(--red); animation: ngRecPulse 1s ease-in-out infinite; }
@keyframes ngRecPulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .35; transform: scale(.6); } }
.btn--rec.is-recording { border-color: var(--red); color: var(--red);
  animation: ngRecBtn 1.4s ease-in-out infinite; }
@keyframes ngRecBtn { 0%, 100% { box-shadow: 0 0 16px rgba(248,113,113,.35); }
  50% { box-shadow: 0 0 28px rgba(248,113,113,.6); } }
@media (prefers-reduced-motion: reduce) {
  .rec-timer::before, .btn--rec.is-recording { animation: none; }
}

/* Diagnostic micro — état précis pour identifier un blocage sur mobile */
.mic-diag {
  margin-top: 12px; padding: 12px 14px; border-radius: 12px;
  background: var(--panel2); border: 1px solid var(--border);
  color: var(--text); font-size: .82rem; line-height: 1.5;
}
.mic-diag[hidden] { display: none; }
.mic-diag h4 { margin: 0 0 6px; font-size: .88rem; }
.mic-diag ul { margin: 6px 0 0; padding-left: 18px; }
.mic-diag li { margin: 2px 0; }
.mic-diag .ok { color: var(--green); font-weight: 600; }
.mic-diag .bad { color: var(--red); font-weight: 700; }
.mic-diag .advice {
  margin-top: 10px; padding: 9px 11px; border-radius: 9px;
  background: rgba(8,145,178,.09); border: 1px solid rgba(8,145,178,.35);
  color: var(--text);
}
.mic-diag .advice.ok { background: rgba(5,150,105,.10); border-color: rgba(5,150,105,.4); }

/* Boutons */
.btn {
  border: 1px solid var(--border); color: var(--text);
  background-color: var(--panel2);
  background-image: linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,0));
  box-shadow: inset 0 1px 0 var(--card-sheen), 0 3px 9px -5px rgba(0,0,0,.42);
  padding: 11px 18px; border-radius: 12px; cursor: pointer; font: inherit; font-size: .92rem;
  transition: transform .09s ease, box-shadow .16s ease, background .16s ease, border-color .16s ease;
}
.btn:hover { transform: translateY(-1px); border-color: var(--cyan);
  box-shadow: 0 0 16px -5px var(--cyan); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .5; cursor: not-allowed; transform: none; }
/* « Enregistrer » VERROUILLÉ pendant un enregistrement en cours : franchement grisé et inerte
   (plus de dégradé cyan ni de halo), pour qu'on ne le confonde plus avec « Arrêter » (rouge, actif). */
#btn-save.is-rec-locked, #btn-save:disabled {
  background: var(--panel) !important; color: var(--muted) !important;
  border-color: var(--border) !important; box-shadow: none !important;
  filter: grayscale(1) !important; opacity: .6; cursor: not-allowed; transform: none !important; }
#btn-save.is-rec-locked::after, #btn-save:disabled::after { content: none !important; animation: none !important; opacity: 0 !important; }
.btn--rec.is-recording { border-color: var(--red); color: var(--red); box-shadow: 0 0 16px rgba(248,113,113,.35); }
/* Bouton « Ajouter … » : déplie une contribution SECONDAIRE optionnelle (traduction en mode
   Transcrire, ou transcription audio en mode Traduire). Discret mais clairement cliquable :
   pointillé, teinte de l'activité au survol, pleine largeur. */
.add-optional { display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  width: 100%; padding: 12px 16px; border-radius: 14px; cursor: pointer;
  font: inherit; font-weight: 700; color: var(--muted);
  background: color-mix(in srgb, var(--cyan) 5%, transparent);
  border: 1.5px dashed color-mix(in srgb, var(--cyan) 40%, var(--border));
  transition: color .15s ease, border-color .15s ease, background .15s ease, box-shadow .2s ease; }
.add-optional[hidden] { display: none; }
.add-optional:hover { color: var(--cyan); border-color: var(--cyan);
  background: color-mix(in srgb, var(--cyan) 12%, transparent); box-shadow: 0 0 18px -8px var(--cyan); }
.add-optional:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
.add-optional-ico { font-size: 1.2em; line-height: 1; font-weight: 800; color: var(--cyan); }
/* « Ils parlent de nous » (À propos) : cartes de témoignages RÉELS, façon citation. */
.say-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; }
.say-grid[hidden] { display: none; }
.say-card { position: relative; padding: 18px 18px 16px; border-radius: 16px;
  background: color-mix(in srgb, var(--gold) 7%, var(--card-bg));
  border: 1px solid color-mix(in srgb, var(--gold) 32%, var(--border));
  box-shadow: inset 0 1px 0 var(--card-sheen), 0 0 26px -14px var(--gold); }
.say-card::before { content: "\201C"; position: absolute; top: 2px; left: 12px;
  font-family: Georgia, "Times New Roman", serif; font-size: 3rem; line-height: 1;
  color: color-mix(in srgb, var(--gold) 55%, transparent); }
.say-text { margin: 10px 0 12px; padding-left: 6px; color: var(--text); font-size: .96rem;
  line-height: 1.55; font-style: italic; }
.say-by { display: flex; flex-direction: column; gap: 1px; padding-left: 6px; }
.say-name { color: var(--gold); font-weight: 700; font-size: .9rem; }
.say-meta { color: var(--muted); font-size: .78rem; }
/* Popup de redirection profil : rangée de boutons (réutilise le cadre .tr-guide/.tr-guide-card). */
.pg-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.pg-actions .btn { flex: 1 1 auto; }
.pg-actions .btn--ghost { flex: 0 1 auto; }
/* CONVENTION boutons du CORPS du site (hors header, hors boutons neutres) —
   couleur UNIE, jamais de dégradé ; texte = var(--bg) (toujours à l'opposé de la
   couleur du bouton → lisible en clair ET en sombre) :
   · ACTION (exécute : Enregistrer, Envoyer, Prochain mot, Rechercher…) → CYAN
   · NAVIGATION (ouvre une vue : Déclarer une langue…)                  → OR
   Ces deux familles sont volontairement de couleurs distinctes. */
.btn--primary, .btn--send, .btn--next {
  color: var(--bg); font-weight: 700;
  background: var(--cyan); border-color: var(--cyan);
  box-shadow: 0 8px 20px -10px var(--cyan);
}
.btn--primary:hover, .btn--send:not(:disabled):hover, .btn--next:hover {
  box-shadow: 0 0 34px -4px var(--cyan), 0 0 12px -2px var(--cyan), 0 8px 20px -10px var(--cyan);
}
.actions { margin-top: 18px; }

.mini {
  border: 1px solid var(--border); color: var(--text);
  background-color: var(--panel2);
  background-image: linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,0));
  box-shadow: inset 0 1px 0 var(--card-sheen), 0 2px 7px -5px rgba(0,0,0,.4);
  border-radius: 9px; padding: 6px 12px; cursor: pointer; font-size: .8rem;
  transition: border-color .14s ease, color .14s ease, background .14s ease, box-shadow .14s ease, transform .1s ease;
}
.mini:hover { color: var(--cyan); border-color: var(--cyan); background: var(--panel); transform: translateY(-1px); box-shadow: 0 0 14px -6px var(--cyan); }
/* Boutons secondaires du corps (Explorer, navigation) : même reflet de verre au repos que
   les autres boutons → plus aucun bouton « plat ». (Le halo de couleur reste au survol.) */
.grp-back, .entry-improve, .entry-share, .mini-btn {
  background-image: linear-gradient(180deg, rgba(255,255,255,.05), rgba(255,255,255,0));
  box-shadow: inset 0 1px 0 var(--card-sheen), 0 2px 6px -4px rgba(0,0,0,.32);
}
/* Actions secondaires de l'audio MISES EN ÉVIDENCE + vivantes : pilule cyan tintée,
   halo respirant, remplissage au survol → bien vues et remarquées. */
#btn-mic-test, .tr-guide-open {
  border: 1.5px solid var(--cyan); color: var(--cyan); font-weight: 700; font-size: .82rem;
  background: color-mix(in srgb, var(--cyan) 10%, var(--panel)); border-radius: 999px; padding: 8px 16px;
  --cta-g: rgba(34,211,238,.5); animation: ngCtaGlow 2.8s ease-in-out infinite;
  transition: background .15s ease, color .15s ease, box-shadow .15s ease, transform .1s ease; }
#btn-mic-test:hover, .tr-guide-open:hover {
  background: var(--cyan); color: var(--bg); transform: translateY(-1px); box-shadow: 0 0 18px -5px var(--cyan); }

/* Bouton « Prochain mot » — action (cyan uni, couleur définie plus haut) */
.btn--next { padding: 10px 18px; white-space: nowrap; }
.btn--next:hover { transform: translateY(-1px); }
.btn--next:active { transform: translateY(1px); }
/* Halo « respirant » sur les CTAs principaux (attire l'œil sans bruit) : via
   filter:drop-shadow, indépendant du box-shadow → aucun conflit avec le survol.
   Chaque CTA respire dans sa couleur. Coupé en prefers-reduced-motion (plus bas). */
@keyframes ngCtaGlow { 0%, 100% { filter: drop-shadow(0 0 3px var(--cta-g)); }
  50% { filter: drop-shadow(0 0 17px var(--cta-g)) drop-shadow(0 0 6px var(--cta-g)); } }
.btn--primary, .btn--next, .btn--send:not(:disabled),
.lang-search-btn, .corr-submit, .tour-next {
  --cta-g: rgba(34,211,238,.55); animation: ngCtaGlow 2.8s ease-in-out infinite; }
.lang-declare-cta { --cta-g: rgba(229,192,123,.6); animation: ngCtaGlow 2.8s ease-in-out infinite; }

/* Envoi + compteurs */
.send-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.counters { display: flex; gap: 16px; flex-wrap: wrap; }
.counter { color: var(--muted); font-size: .82rem; }
.counter b { color: var(--text); font-size: 1.05rem; }
.send-actions { display: flex; align-items: center; gap: 12px; }
.send-status { color: var(--cyan); font-size: .8rem; }
.send-hint { color: var(--muted); font-size: .78rem; line-height: 1.5; margin: 12px 0 0; }

/* Liste */
.list { list-style: none; padding: 0; margin: 14px 0 0; display: flex; flex-direction: column; gap: 8px;
  /* Au-delà d'une dizaine de contributions, la liste DÉFILE dans son cadre au lieu d'occuper
     toute la page (un utilisateur qui en a fait 100 garde une page maniable). */
  max-height: 340px; overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: thin; padding-right: 4px; }
.list::-webkit-scrollbar { width: 8px; }
.list::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--cyan) 30%, var(--border)); border-radius: 8px; }
/* Recherche dans la liste des contributions. */
.send-search-wrap { margin-top: 14px; }
.send-search-wrap[hidden] { display: none; }
.send-search { width: 100%; box-sizing: border-box; padding: 10px 14px; border-radius: 12px;
  border: 1px solid var(--border); background: var(--panel); color: var(--text); font: inherit; font-size: .9rem; }
.send-search:focus { outline: none; border-color: color-mix(in srgb, var(--cyan) 55%, var(--border));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--cyan) 18%, transparent); }
.send-noresult { color: var(--muted); font-size: .86rem; padding: 10px 4px; }
.send-noresult[hidden] { display: none; }
/* Alerte DOUBLON (mode libre) : le mot saisi a déjà été traité par l'utilisateur. */
.dup-warn { margin-top: 12px; padding: 14px 16px; border-radius: 14px;
  background: color-mix(in srgb, var(--gold) 9%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--gold) 45%, var(--border));
  box-shadow: 0 0 24px -14px var(--gold); }
.dup-warn[hidden] { display: none; }
.dup-warn-head { display: flex; align-items: center; gap: 8px; font-weight: 800; color: var(--gold); }
.dup-warn-msg { margin: 8px 0 10px; color: var(--text); font-size: .9rem; line-height: 1.5; }
.dup-prev { margin-bottom: 10px; }
.dup-prev-trad { margin: 8px 0 0; font-size: .92rem; color: var(--text); }
.dup-prev-lbl { color: var(--muted); }
.dup-actions { display: flex; flex-wrap: wrap; gap: 10px; }
/* Saisie d'une NOUVELLE contribution grisée et inerte tant qu'un doublon est signalé (la SOURCE
   reste modifiable, et le panneau d'alerte reste cliquable : ils sont hors des zones grisées). */
.work-dup-locked #target-wrap, .work-dup-locked #audio-wrap, .work-dup-locked .actions {
  opacity: .5; filter: grayscale(.6); pointer-events: none; }
.item {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 12px; border: 1px solid var(--border); border-radius: 11px; background: var(--bg);
}
.item--sent { opacity: .75; }
.item-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.pair { font-size: 1.05rem; }
.pair b { color: var(--cyan); }
.pair .arrow { color: var(--muted); margin: 0 8px; }
.meta { color: var(--muted); font-size: .72rem; }
.item-side { display: flex; align-items: center; gap: 8px; }
.badge { font-size: .66rem; padding: 3px 8px; border-radius: 999px; white-space: nowrap; }
.badge--local { color: var(--gold); border: 1px solid rgba(229,192,123,.4); }
.badge--sent { color: var(--green); border: 1px solid rgba(52,211,153,.4); }

/* --- Deux groupes d'envoi : confirmés ✅ / à renvoyer ⟳ --- */
.counter--ok b { color: var(--green); }
.counter--todo b { color: var(--gold); }
.sendgrp { margin-top: 16px; }
.sendgrp-head { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding-bottom: 6px; border-bottom: 1px solid var(--border); }
.sendgrp-title { display: inline-flex; align-items: center; gap: 8px; font-weight: 700; font-size: .9rem; }
.sendgrp-title b { margin-left: 2px; padding: 1px 9px; border-radius: 999px; font-size: .8rem;
  background: color-mix(in srgb, currentColor 15%, transparent); }
.sendgrp--ok .sendgrp-title { color: var(--green); }
.sendgrp--todo .sendgrp-title { color: var(--gold); }
.dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
.dot--ok { background: var(--green); box-shadow: 0 0 8px var(--green); }
.dot--todo { background: var(--gold); box-shadow: 0 0 8px var(--gold); }
.mini-btn { font-size: .78rem; font-weight: 700; color: var(--gold); background: transparent;
  border: 1px solid rgba(229,192,123,.5); border-radius: 999px; padding: 4px 12px; cursor: pointer;
  white-space: nowrap; }
.mini-btn:hover { color: var(--text); border-color: var(--gold);
  background: color-mix(in srgb, var(--gold) 15%, transparent); }
.sendgrp .list { margin-top: 8px; }

/* --- Suivi des bugs --- */
.bug-report h3 { margin: 0 0 10px; font-size: 1rem; }
.bug-form { display: flex; flex-direction: column; gap: 12px; }
.bug-form label { display: flex; flex-direction: column; gap: 5px; font-size: .82rem; color: var(--muted); font-weight: 600; }
.bug-form input, .bug-form textarea, .bug-form select {
  font: inherit; color: var(--text); background: var(--panel); border: 1px solid var(--border);
  border-radius: 12px; padding: 10px 12px; }
.bug-form textarea { resize: vertical; }
.bug-form-row { display: flex; gap: 12px; flex-wrap: wrap; }
.bug-form-row label { flex: 1 1 160px; }
.bug-list { list-style: none; padding: 0; margin: 12px 0 0; display: flex; flex-direction: column; gap: 12px; }
.bug { border: 1px solid var(--border); border-radius: 16px; padding: 14px 16px; background: var(--card-bg); }
.bug--open { border-left: 4px solid var(--gold); }
.bug--done { border-left: 4px solid var(--green); }
.bug-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.bug-id { font-family: ui-monospace, "Cascadia Code", monospace; font-size: .78rem; font-weight: 700; color: var(--cyan); }
.bug-sev { font-size: .66rem; font-weight: 700; padding: 2px 8px; border-radius: 999px; }
.bug-sev--critique { color: #ff6b6b; border: 1px solid rgba(255,107,107,.5); }
.bug-sev--majeur { color: var(--gold); border: 1px solid rgba(229,192,123,.5); }
.bug-sev--mineur { color: var(--muted); border: 1px solid var(--border); }
.bug-zone { font-size: .66rem; color: var(--muted); border: 1px solid var(--border); border-radius: 999px; padding: 2px 8px; }
.bug-titre { font-weight: 700; font-size: .96rem; color: var(--text); }
.bug-desc { font-size: .86rem; color: var(--muted); margin-top: 4px; line-height: 1.5; }
.bug-fix { font-size: .84rem; color: var(--green); margin-top: 6px; line-height: 1.5; }
.bug-meta { font-size: .74rem; color: var(--muted); margin-top: 8px; }

/* --- Bannière « nouvelle version disponible » (voyante, avec halo & voyant) --- */
/* IMPORTANT : la règle de classe ci-dessous (display:flex) écraserait l'attribut
   [hidden] (piège de spécificité) → on rétablit explicitement le masquage. */
.update-banner[hidden] { display: none !important; }
.update-banner {
  position: fixed; z-index: 2147483600; right: 18px; bottom: 18px;
  width: min(370px, calc(100vw - 32px));
  display: flex; gap: 12px; align-items: flex-start;
  padding: 16px 18px; border-radius: 18px;
  /* Mise à jour = BLEU système (couleur réservée à ce type, distincte des autres popups). */
  background: var(--card-bg); border: 1px solid #4f8cff;
  box-shadow: 0 18px 50px rgba(0,0,0,.45), 0 0 26px rgba(79,140,255,.4);
  animation: updIn .45s cubic-bezier(.2,.8,.2,1) both, updGlow 1.8s ease-in-out infinite;
}
@keyframes updIn { from { opacity:0; transform: translateY(20px) scale(.96); } to { opacity:1; transform:none; } }
@keyframes updGlow {
  0%,100% { box-shadow: 0 18px 50px rgba(0,0,0,.45), 0 0 20px rgba(79,140,255,.30); border-color: #4f8cff; }
  50%     { box-shadow: 0 18px 50px rgba(0,0,0,.45), 0 0 36px rgba(79,140,255,.6); border-color: #7ba9ff; }
}
.update-dot { flex:0 0 auto; width: 12px; height: 12px; margin-top: 5px; border-radius: 50%;
  background: #4f8cff; box-shadow: 0 0 10px #4f8cff; animation: updBlink 1s steps(1,end) infinite; }
@keyframes updBlink { 0%,50% { opacity:1; } 51%,100% { opacity:.2; } }
.update-body { min-width:0; }
.update-title { font-weight: 800; font-size: .98rem; color: var(--text); }
.update-title b { color: #4f8cff; }
.update-sub { margin: 4px 0 6px; font-size: .8rem; color: var(--muted); }
.update-notes { margin: 0 0 12px; font-size: .82rem; color: var(--muted);
  display: flex; flex-direction: column; gap: 9px; max-height: 42vh; overflow-y: auto; }
.update-vgrp { display: flex; flex-direction: column; gap: 3px; }
.update-vtag { font-size: .68rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  color: #4f8cff; }
.update-notes-list { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 3px; }
.update-notes-list li { line-height: 1.4; }
.update-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.update-banner .btn--primary { background: #4f8cff; border-color: #4f8cff; color: #06122b; }
.update-btn { animation: updPulse 1.6s ease-in-out infinite; }
@keyframes updPulse { 0%,100% { box-shadow: 0 8px 20px rgba(79,140,255,.35); } 50% { box-shadow: 0 8px 30px rgba(79,140,255,.65); } }
.update-later { background: none; border: none; color: var(--muted); font: inherit; cursor: pointer; text-decoration: underline; }
.update-later:hover { color: var(--text); }
@media (max-width: 560px) { .update-banner { right: 12px; left: 12px; bottom: 12px; width: auto; } }
@media (prefers-reduced-motion: reduce) {
  .update-banner { animation: updIn .3s ease both; }
  .update-dot, .update-btn { animation: none; }
}

/* Invitation à contribuer (nudge quotidien) : carte flottante douce en bas. Entrée
   animée UNE fois (pas d'animation continue → conforme à la politique perf). */
.incite-banner[hidden] { display: none !important; }
.incite-banner {
  /* ACCENT SÉMANTIQUE par type de popup : `--pop-acc` est redéfini selon data-ptype
     (voir plus bas). Toute la coloration du popup (fond, bordure, halo, icône, bouton)
     en découle → l'utilisateur reconnaît le TYPE de message à sa couleur, avant de lire. */
  --pop-acc: var(--cyan);
  position: fixed; z-index: 2147483500; right: 18px; bottom: 18px;
  width: min(380px, calc(100vw - 32px));
  display: flex; gap: 12px; align-items: flex-start;
  padding: 16px 40px 16px 18px; border-radius: 18px;
  background: radial-gradient(120% 100% at 0% 0%, color-mix(in srgb, var(--pop-acc) 13%, transparent), transparent 60%), var(--card-bg);
  border: 1.5px solid color-mix(in srgb, var(--pop-acc) 58%, var(--border));
  box-shadow: 0 18px 50px rgba(0,0,0,.42), 0 0 30px -6px var(--pop-acc), inset 0 1px 0 var(--card-sheen);
  animation: updIn .45s cubic-bezier(.2,.8,.2,1) both;
}
/* Un liséré coloré épais à gauche = repère de type visible en un éclair. */
.incite-banner::before { content: ""; position: absolute; left: 0; top: 14px; bottom: 14px; width: 5px;
  border-radius: 0 4px 4px 0; background: var(--pop-acc); box-shadow: 0 0 14px -2px var(--pop-acc); }
/* Couleur par TYPE : vert = on t'invite à contribuer ; or = on t'invite à évaluer/voter ;
   violet = retour d'activité sur TES contributions ; cyan = demandes de la communauté. */
.incite-banner[data-ptype="contribute"] { --pop-acc: var(--green); }
.incite-banner[data-ptype="rate"]       { --pop-acc: var(--gold); }
.incite-banner[data-ptype="activity"]   { --pop-acc: var(--violet); }
.incite-banner[data-ptype="request"]    { --pop-acc: var(--cyan); }
.incite-ico { flex: 0 0 auto; font-size: 1.7rem; line-height: 1.2;
  filter: drop-shadow(0 2px 5px rgba(0,0,0,.3)) drop-shadow(0 0 10px color-mix(in srgb, var(--pop-acc) 60%, transparent)); }
/* Certaines catégories utilisent une VRAIE image (illustration) plutôt qu'un emoji :
   grand avatar rond cerclé de la couleur du type, qui DÉBORDE volontairement en haut et
   à gauche du popup (l'overflow reste visible, le halo fond joliment le débord). */
.incite-ico { overflow: visible; }
.incite-ico .pop-photo { display: block; width: 104px; height: 104px; border-radius: 50%;
  object-fit: cover; border: 2.5px solid color-mix(in srgb, var(--pop-acc) 80%, transparent);
  box-shadow: 0 0 22px -2px var(--pop-acc), 0 8px 22px -6px rgba(0,0,0,.5);
  margin: -30px 2px -8px -34px; }
/* Bouton principal et bouton « Écouter » : teintés dans la couleur du type. */
.incite-banner .btn--primary { background: var(--pop-acc); border-color: var(--pop-acc); color: var(--bg);
  box-shadow: 0 8px 22px -8px var(--pop-acc); }
.incite-banner .btn--primary:hover { box-shadow: 0 8px 28px -6px var(--pop-acc); filter: brightness(1.06); }
.incite-body { min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.incite-msg { margin: 0; font-size: .92rem; line-height: 1.5; color: var(--text); white-space: pre-line; }
.incite-actions { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.incite-actions .btn--primary { padding: 9px 16px; font-size: .9rem; }
.incite-later { background: none; border: none; color: var(--muted); font: inherit; cursor: pointer; text-decoration: underline; }
.incite-later:hover { color: var(--text); }
.incite-listen[hidden] { display: none; }
.incite-listen { font: inherit; font-weight: 700; font-size: .85rem; cursor: pointer; white-space: nowrap;
  color: var(--pop-acc); border: 1.5px solid color-mix(in srgb, var(--pop-acc) 55%, var(--border)); border-radius: 999px; padding: 8px 14px;
  background-color: color-mix(in srgb, var(--pop-acc) 8%, var(--panel));
  background-image: linear-gradient(180deg, rgba(255,255,255,.08), rgba(255,255,255,0));
  box-shadow: inset 0 1px 0 var(--card-sheen); transition: background .14s, box-shadow .14s, transform .1s; }
.incite-listen:hover { background-color: var(--pop-acc); color: var(--bg); box-shadow: 0 0 16px -5px var(--pop-acc); }
.incite-listen:active { transform: translateY(1px); }
.incite-close { position: absolute; top: 8px; right: 10px; width: 26px; height: 26px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--panel); color: var(--muted); cursor: pointer;
  font-size: .8rem; line-height: 1; display: grid; place-items: center; transition: color .14s, border-color .14s; }
.incite-close:hover { color: var(--text); border-color: var(--pop-acc); }
@media (max-width: 560px) { .incite-banner { right: 12px; left: 12px; bottom: 12px; width: auto; } }
@media (prefers-reduced-motion: reduce) { .incite-banner { animation: updIn .3s ease both; } }
/* Popup de notification : sa couleur suit le TYPE de notification via data-ptype
   (violet = activité sur tes contributions, cyan = demandes). Défaut violet si non typé. */
.notif-popup { --pop-acc: var(--violet); }

/* Cloche du header : pastille de non-lues qui déborde en haut à droite. */
.chip--notif { position: relative; }
.notif-badge { position: absolute; top: -5px; right: -4px; min-width: 17px; height: 17px; padding: 0 4px;
  border-radius: 999px; background: var(--red); color: #fff; font-size: .62rem; font-weight: 800; line-height: 17px;
  text-align: center; box-shadow: 0 0 0 2px var(--bg), 0 0 10px -2px var(--red); pointer-events: none; }
.notif-badge[hidden] { display: none; }

/* Centre de notifications : flux horodaté, non-lues mises en avant. */
.notif-toolbar { display: flex; justify-content: flex-end; margin: 4px 0 10px; }
.notif-feed { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.notif { display: flex; gap: 12px; align-items: flex-start; padding: 12px 14px; border-radius: 14px;
  border: 1px solid var(--border); background: var(--panel);
  box-shadow: inset 0 1px 0 var(--card-sheen); }
.notif--unread { border-color: color-mix(in srgb, var(--violet) 55%, var(--border));
  background: color-mix(in srgb, var(--violet) 9%, var(--panel));
  box-shadow: 0 0 16px -8px var(--violet), inset 0 1px 0 var(--card-sheen); }
.notif--unread .notif-msg { font-weight: 600; }
.notif-ico { flex: 0 0 auto; font-size: 1.25rem; line-height: 1.3; filter: drop-shadow(0 2px 4px rgba(0,0,0,.25)); }
.notif-body { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.notif-msg { margin: 0; font-size: .92rem; line-height: 1.45; color: var(--text); }
.notif-time { font-size: .74rem; color: var(--muted); }
.notif-empty { color: var(--muted); font-size: .92rem; line-height: 1.5; padding: 14px 4px; }
/* Notification ACTIONNABLE : un clic mène quelque part (répondre à une demande, voir le
   mot). On la rend visiblement cliquable (curseur, chevron, léger relief au survol). */
.notif--action { cursor: pointer; transition: transform .12s ease, box-shadow .2s ease, border-color .2s ease; }
.notif--action:hover { border-color: color-mix(in srgb, var(--cyan) 50%, var(--border));
  box-shadow: 0 0 18px -8px var(--cyan), inset 0 1px 0 var(--card-sheen); transform: translateY(-1px); }
.notif--action:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
.notif-go { flex: 0 0 auto; align-self: center; color: var(--cyan); font-size: 1.15rem; font-weight: 700;
  opacity: .8; transition: transform .15s ease, opacity .15s ease; }
.notif--action:hover .notif-go { transform: translateX(3px); opacity: 1; }
/* Demande mise en avant après un clic depuis une notification (elle « pulse » brièvement). */
.req-item--flash { animation: reqFlash 1.7s ease; }
@keyframes reqFlash {
  0%, 100% { box-shadow: inset 0 1px 0 var(--card-sheen); }
  20%, 60% { box-shadow: 0 0 0 2px var(--cyan), 0 0 22px -6px var(--cyan), inset 0 1px 0 var(--card-sheen); }
}

/* --- Porte « Demander » : formulaire + liste des demandes --- */
/* LOT 5 : bandeau des demandes de la communauté à traiter (haut de Traduire/Transcrire). */
.req-strip { --acc: var(--cyan); margin: 0 0 4px; padding: 14px 16px; border-radius: 16px;
  border: 1px solid color-mix(in srgb, var(--cyan) 38%, var(--border));
  background:
    radial-gradient(120% 140% at 0% 0%, color-mix(in srgb, var(--cyan) 12%, transparent), transparent 60%),
    var(--card-bg);
  box-shadow: inset 0 1px 0 var(--card-sheen), 0 0 22px -10px var(--cyan); }
.req-strip-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px;
  font-family: var(--font-display); font-size: .96rem; font-weight: 700; color: var(--text); }
.req-strip-ico { width: 20px; height: 20px; flex: none; }
.req-strip-list { display: flex; flex-wrap: wrap; gap: 8px; }
.req-chip { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 2px;
  max-width: 100%; padding: 8px 13px; border-radius: 12px; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--cyan) 45%, var(--border));
  background: color-mix(in srgb, var(--cyan) 8%, var(--panel));
  color: var(--text); font: inherit; text-align: left;
  transition: transform .12s ease, box-shadow .16s ease, border-color .16s ease, background .16s ease; }
.req-chip:hover { transform: translateY(-1px); border-color: var(--cyan);
  background: color-mix(in srgb, var(--cyan) 16%, var(--panel));
  box-shadow: 0 0 16px -5px var(--cyan); }
.req-chip:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
.req-chip-word { font-weight: 700; font-size: .95rem; max-width: 60ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.req-chip-note { font-size: .74rem; color: var(--muted); max-width: 40ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (prefers-reduced-motion: reduce) { .req-chip { transition: none; } }

.req-form { --acc: var(--cyan); }
.req-form h3, .req-list-head h3 { margin: 0 0 12px; font-family: var(--font-display); font-size: 1.05rem; color: var(--text); }
.req-list-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin: 22px 0 12px; }
.req-filter { display: inline-flex; align-items: center; gap: 8px; font-size: .86rem; color: var(--muted); }
.req-filter select { min-width: 160px; }
.req-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.req-item { position: relative; padding: 14px 16px; border-radius: 16px; border: 1px solid var(--border);
  background: radial-gradient(120% 80% at 0% 0%, color-mix(in srgb, var(--cyan) 7%, transparent), transparent 60%), var(--panel);
  box-shadow: inset 0 1px 0 var(--card-sheen); }
.req-item--mine { border-color: color-mix(in srgb, var(--cyan) 45%, var(--border));
  box-shadow: 0 0 18px -10px var(--cyan), inset 0 1px 0 var(--card-sheen); }
.req-top { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.req-word { font-family: var(--font-display); font-weight: 800; font-size: 1.15rem; color: var(--text); }
.req-badge { font-size: .74rem; font-weight: 700; color: var(--cyan); padding: 2px 10px; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--cyan) 45%, var(--border)); background: color-mix(in srgb, var(--cyan) 10%, var(--panel2)); white-space: nowrap; }
.req-meta { font-size: .82rem; color: var(--muted); margin-top: 3px; }
.req-note { font-size: .88rem; color: var(--text); margin-top: 8px; padding: 8px 10px; border-radius: 10px;
  background: var(--panel2); border-left: 3px solid color-mix(in srgb, var(--cyan) 50%, var(--border)); }
.req-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
.req-mine-tag { font-size: .78rem; font-weight: 700; color: var(--cyan); }
.req-count { font-size: .78rem; color: var(--muted); margin-left: auto; }
.btn--sm { padding: 7px 14px; font-size: .85rem; border-radius: 999px; }
.req-answer-box { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.req-answer-box[hidden] { display: none; }
.req-answer-input { flex: 1 1 220px; min-width: 0; }
@media (max-width: 520px) { .req-answer-input { flex-basis: 100%; } .req-count { margin-left: 0; } }
/* Déclaration LÉGÈRE d'une langue absente, depuis le formulaire Demander. */
.req-newlang { padding: 12px 14px; border-radius: 12px;
  border: 1px dashed color-mix(in srgb, var(--cyan) 45%, var(--border));
  background: color-mix(in srgb, var(--cyan) 6%, var(--panel2)); }
.req-newlang[hidden] { display: none; }
.req-newlang > span { font-size: .82rem; color: var(--muted); font-weight: 600; }
.req-newlang-grid { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; align-items: center; }
.req-newlang-grid input { flex: 1 1 150px; min-width: 0; }

/* ---- Visite guidée (projecteur + bulle « Étape N sur N ») ---- */
.tour { position: fixed; inset: 0; z-index: 9998; }
.tour[hidden] { display: none; }
.tour-spot { position: fixed; border-radius: 12px; pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(4, 9, 18, .62); border: 2px solid var(--cyan);
  transition: top .25s ease, left .25s ease, width .25s ease, height .25s ease; }
.tour-card { position: fixed; width: min(340px, calc(100vw - 24px)); z-index: 9999;
  background: var(--panel); color: var(--text); border: 1px solid var(--border);
  border-radius: 14px; padding: 13px 15px; box-shadow: var(--shadow-drop);
  max-height: calc(100vh - 24px); overflow-y: auto; }
.tour-step { font-size: .66rem; color: var(--cyan); font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; margin-bottom: 4px; }
.tour-title { font-size: .98rem; font-weight: 800; margin-bottom: 5px; line-height: 1.25; }
.tour-text { font-size: .8rem; color: var(--muted); line-height: 1.46; margin-bottom: 12px; }
.tour-actions { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.tour-skip { background: transparent; border: 0; color: var(--muted); cursor: pointer; font: inherit; font-size: .8rem; }
.tour-skip:hover { color: var(--text); }
.tour-next { background: var(--cyan); color: var(--bg); border: 0;
  border-radius: 9px; padding: 8px 16px; cursor: pointer; font: inherit; font-weight: 700; font-size: .85rem; }
.tour-next:hover { box-shadow: 0 0 16px -5px var(--cyan); }

/* Toast */
.toast {
  position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%) translateY(20px);
  max-width: min(560px, 92vw); padding: 12px 16px; border-radius: 12px;
  background: var(--toast-bg); border: 1px solid var(--border); color: var(--text);
  box-shadow: var(--shadow-drop); font-size: .86rem; line-height: 1.4;
  opacity: 0; pointer-events: none; transition: opacity .2s ease, transform .2s ease; z-index: 50;
}
.toast.is-on { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast--ok { border-color: rgba(52,211,153,.5); }
.toast--warn { border-color: rgba(229,192,123,.55); }
.toast--err { border-color: rgba(248,113,113,.55); }

/* ── Micro-célébration à l'enregistrement ─────────────────────────────────
   Un bref halo + quelques confettis EN LOSANGE (cyan/vert/or, cohérents avec le
   décor Ndop) jaillissent du bouton. Sobre et court (~1 s), calque retiré après
   coup → aucun coût persistant. Entièrement désactivable via prefers-reduced-motion. */
.celebrate { position: fixed; inset: 0; pointer-events: none; z-index: 9997; overflow: hidden; }
.celebrate .halo {
  position: absolute; width: 36px; height: 36px; border-radius: 50%;
  border: 2px solid var(--cyan); opacity: .9;
  transform: translate(-50%, -50%) scale(.4); animation: celHalo .65s ease-out forwards;
}
@keyframes celHalo { to { transform: translate(-50%,-50%) scale(4.2); opacity: 0; } }
.celebrate .cfd {
  position: absolute; width: 9px; height: 9px; opacity: 0;
  animation: celFall .95s ease-in forwards;
}
@keyframes celFall {
  0%   { opacity: 0; transform: translate(-50%,-50%) rotate(45deg) scale(.5); }
  15%  { opacity: 1; }
  100% { opacity: 0;
    transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) rotate(320deg) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .celebrate .cfd { display: none; }
  .celebrate .halo { animation-duration: .35s; }
}

@media (prefers-reduced-motion: reduce) {
  .btn, .toast, .slider, .slider::before, .dir-btn { transition: none; }
  .btn:hover, .btn:active { transform: none; }
}

/* =======================================================================
   COUCHE PREMIUM — décor & effets « spectaculaires », 100 % composités
   (transform/opacity), placés sur le CHROME uniquement. Aucun effet sur le
   clavier ni sur le chemin de frappe → la saisie reste instantanée.
   ======================================================================= */
html { overflow-x: clip; }

/* Fond « aurore » vivant : deux halos cyan/vert qui dérivent lentement */
body::before, body::after {
  content: ""; position: fixed; z-index: -1; pointer-events: none;
  width: 62vmax; height: 62vmax; border-radius: 50%;
}
body::before {
  top: -22vmax; left: -16vmax;
  background: radial-gradient(circle, var(--aurora-a), transparent 62%);
  animation: ngAurora1 26s ease-in-out infinite;
}
body::after {
  bottom: -26vmax; right: -18vmax;
  background: radial-gradient(circle, var(--aurora-b), transparent 62%);
  animation: ngAurora2 32s ease-in-out infinite;
}
@keyframes ngAurora1 {
  0%, 100% { transform: translate(-6%, -4%) scale(1); }
  50%      { transform: translate(7%, 9%) scale(1.16); }
}
@keyframes ngAurora2 {
  0%, 100% { transform: translate(5%, 4%) scale(1.12); }
  50%      { transform: translate(-7%, -6%) scale(1); }
}

/* En-tête : liseré cyan→vert qui balaie lentement */
.topbar::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: linear-gradient(90deg, transparent, var(--cyan), var(--green), transparent);
  background-size: 220% 100%; opacity: .75;
  animation: ngHeaderLine 7s linear infinite;
}
@keyframes ngHeaderLine { to { background-position: 220% 0; } }

/* Logo : halo qui respire */
.brand-mark, .foot-mark { position: relative; }
/* Aura identitaire du logo — IDENTIQUE en clair et en sombre (Brice : « exactement
   comme le mode sombre »), sur le header ET le footer. Halo cyan qui respire + aura
   conique colorée qui tourne, en couleurs VIVES FIXES (pas les jetons de thème, qui
   rendaient l'effet terne/délavé en clair). */
.brand-mark::after, .foot-mark::after {
  content: ""; position: absolute; inset: -3px; border-radius: 16px; z-index: -1; pointer-events: none;
  background: radial-gradient(circle, rgba(34,211,238,.5), transparent 72%);
  animation: ngHalo 3.4s ease-in-out infinite;
}
@keyframes ngHalo { 0%, 100% { opacity: .45; } 50% { opacity: .95; } }
.brand-mark::before, .foot-mark::before {
  content: ""; position: absolute; inset: -3px; border-radius: 16px; z-index: -1; pointer-events: none;
  background: conic-gradient(from 0deg, #22d3ee, #34d399, #4f8cff, #22d3ee);
  filter: blur(4px); opacity: .35;
  animation: ngSpin 9s linear infinite;
}
@keyframes ngSpin { to { transform: rotate(360deg); } }
/* Mode CLAIR : tout halo DIFFUS se mélange au blanc du fond → « feuille blanche »
   inévitable. On le retire donc, et on rend l'effet « qui tourne » sous forme d'un
   ANNEAU conique NET (contour dégradé masqué), subtil, dont la lumière circule via
   l'angle du dégradé. Aucun voile blanc. Le mode sombre (aura douce) reste intact. */
:root:not([data-theme="dark"]) .brand-mark::after,
:root:not([data-theme="dark"]) .foot-mark::after { display: none; }
@property --ng-ring { syntax: "<angle>"; initial-value: 0deg; inherits: false; }
:root:not([data-theme="dark"]) .brand-mark::before,
:root:not([data-theme="dark"]) .foot-mark::before {
  border-radius: 17px; padding: 2.5px; filter: none; opacity: .6; transform: none;
  background: conic-gradient(from var(--ng-ring), #22d3ee, #34d399, #4f8cff, #e5c07b, #22d3ee);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  animation: ngRingSpin 7s linear infinite;
}
:root:not([data-theme="dark"]) .foot-mark::before { border-radius: 16px; }
@keyframes ngRingSpin { to { --ng-ring: 360deg; } }

/* Cartes : filet lumineux en haut + relief au survol */
.card { position: relative; transition: box-shadow .25s ease, transform .25s ease, border-color .25s ease; }
.card::before {
  content: ""; position: absolute; top: 0; left: 18px; right: 18px; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(34,211,238,.55), transparent);
}
.card:hover {
  border-color: rgba(34,211,238,.28);
  box-shadow: 0 18px 46px rgba(0,0,0,.45), 0 0 0 1px rgba(34,211,238,.10) inset;
}
/* Bordure identitaire « vivante » : un dégradé cyan→vert circule sur le pourtour.
   (Continu → gelé sur mobile pour ne rien coûter à la frappe.) */
.card::after {
  content: ""; position: absolute; inset: -1px; border-radius: 19px; padding: 1px;
  background: linear-gradient(130deg, var(--cyan), transparent 38%, var(--green) 62%, var(--gold));
  background-size: 300% 300%;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  opacity: .6; pointer-events: none;
  animation: ngCardBorder 12s linear infinite;
}
@keyframes ngCardBorder { to { background-position: 300% 0; } }
/* Apparition douce des cartes (une seule fois, légère — OK même sur mobile) */
.card { animation: ngCardIn .5s cubic-bezier(.2, .7, .2, 1) both; }
.card + .card { animation-delay: .1s; }
/* Fondu SANS transform : un transform sur .card créerait un bloc conteneur qui
   « capturerait » le position:fixed du clavier ancré (il ne serait plus collé au
   bas de l'écran). Le fondu suffit visuellement. */
@keyframes ngCardIn { from { opacity: 0; } to { opacity: 1; } }

/* CTA : sheen (reflet) qui traverse au survol ; balayage périodique sur le
   bouton principal « Prochain mot ». Élément composité, hors flux → coût nul. */
/* BRILLANCE des boutons pleins : un reflet lumineux (façon « laser ») balaie le bouton
   en CONTINU (pas seulement au survol) → le bouton n'est jamais statique, on comprend
   qu'il est cliquable. Au survol, un balayage net supplémentaire. */
.btn--next, .btn--primary, .btn--send,
.lang-search-btn, .lang-declare-cta, .corr-submit, .tour-next { position: relative; overflow: hidden; }
.btn--next::after, .btn--primary::after, .btn--send::after,
.lang-search-btn::after, .lang-declare-cta::after, .corr-submit::after, .tour-next::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,.45), transparent);
  transform: translateX(-160%); pointer-events: none;
  animation: ngSheenLoop 5s ease-in-out infinite;
}
.btn--next:hover::after, .btn--primary:hover::after, .btn--send:not(:disabled):hover::after,
.lang-search-btn:hover::after, .lang-declare-cta:hover::after, .corr-submit:hover::after, .tour-next:hover::after {
  animation: ngSheen .8s ease;
}
@keyframes ngSheen { to { transform: translateX(320%); } }
@keyframes ngSheenLoop {
  0%, 78%, 100% { transform: translateX(-160%); }
  88%           { transform: translateX(320%); }
}

/* Puce « en ligne » : pulsation douce */
.chip--on { animation: ngChipPulse 2.4s ease-in-out infinite; }
@keyframes ngChipPulse {
  0%, 100% { box-shadow: 0 0 9px -2px currentColor, 0 0 10px rgba(52,211,153,.14) inset; }
  50%      { box-shadow: 0 0 20px 0 currentColor, 0 0 14px rgba(52,211,153,.30) inset; }
}

/* Pied de page : filet identitaire en haut */
/* Image en FOND de l'élément footer (derrière TOUT le contenu), COMPLÈTEMENT OPAQUE (aucun voile).
   Comme l'image reste SOMBRE dans les 2 modes (en attendant footer-bg-light.jpg), on force les
   couleurs de texte du footer à rester CLAIRES (valeurs du thème sombre) même en mode clair, pour
   une lisibilité parfaite. ⏳ À rétablir/adapter quand l'image claire sera dispo. */
.site-footer { position: relative; overflow: hidden;
  background: url("icons/footer-bg.jpg") center / cover no-repeat;
  --text: #e9f0f6; --muted: #8b97a6; --cyan: #22d3ee; --green: #34d399; --gold: #e5c07b;
  --violet: #a78bfa; --border: #253041; --panel: #12181f; --panel2: #1a2230;
  /* Logos réseaux du footer : fond BLANC dans les deux modes (les marques ressortent). */
  --share-ico-bg: #ffffff; --share-ico-bd: rgba(0,0,0,.14); }
/* Galon Kente (pattern-accent) en liseré ornemental au sommet du footer. */
.site-footer::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 12px; z-index: 2;
  background: url("icons/pattern-accent.jpg") left center / auto 100% repeat-x;
  box-shadow: 0 1px 6px -2px rgba(0,0,0,.5);
}
.foot-inner, .foot-bottom { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) {
  body::before, body::after, .topbar::after, .brand-mark::after, .brand-mark::before,
  .btn--next::after, .btn--primary::after, .btn--send::after,
  .lang-search-btn::after, .lang-declare-cta::after, .corr-submit::after, .tour-next::after,
  .chip--on, .chip--on::before, .field--consent,
  .view-title::after, .view-title::before, .card, .card::after,
  .btn--primary, .btn--next, .btn--send, .lang-search-btn, .lang-declare-cta, .corr-submit, .tour-next,
  #btn-mic-test, .tr-guide-open,
  .hub-card, .hub-card::before, .hub-card::after, .hub-ico, .brand::before, .ndop-sep i, .ndop-sep::before, .ndop-sep::after,
  .nav-tab, .nav-tab::before, .nav-tab::after, .nav-tab .nav-ico { animation: none; }
  .btn--primary, .btn--next, .btn--send, .lang-search-btn, .lang-declare-cta, .corr-submit, .tour-next,
  #btn-mic-test, .tr-guide-open { filter: none; }
  .card { transition: none; }
}

/* PERF mobile : on coupe les animations CONTINUES (repeint chaque frame :
   background-position de l'en-tête, box-shadow de la puce, scale de l'aurore
   sur un très grand calque) pour libérer le thread principal → la frappe au
   clavier s'affiche INSTANTANÉMENT. Le look premium STATIQUE est conservé
   (dégradés, halos, glows). Les effets ponctuels (survol) restent, ils ne
   tournent pas en boucle. */
@media (max-width: 640px) {
  /* DÉCOR VIVANT SUR MOBILE (Brice le veut visible partout, pas seulement sur PC). On ne
     gèle QUE l'aurore PLEIN ÉCRAN (body::before/after) : c'est le seul calque assez grand
     pour peser vraiment. Tout le reste (bordures tournantes des cartes du hub, halos qui
     respirent, glow d'icônes, aurore d'en-tête, anneau des cartes, brillance des boutons,
     ornements) RESTE animé sur téléphone. */
  body::before { animation: none; top: -28vmax; left: -20vmax; opacity: .8; }
  body::after  { animation: none; bottom: -30vmax; right: -22vmax; opacity: .8; }
  /* Exception ciblée : quand le CLAVIER ngiemboon est ouvert, on gèle les animations
     continues pour garder la frappe parfaitement fluide (le clavier couvre le bas de
     l'écran, le décor n'y est de toute façon plus visible). */
  body.kb-docked .hub-card, body.kb-docked .hub-card::before, body.kb-docked .hub-ico,
  body.kb-docked .nav-tab, body.kb-docked .nav-tab::before, body.kb-docked .nav-tab::after, body.kb-docked .nav-tab .nav-ico,
  body.kb-docked .card::after, body.kb-docked .brand::before { animation: none; }
}

/* ============ Page « À propos » (vraie vue de l'app, style app) ============ */
/* Bannière hero : illustration de communauté, pleine largeur, coins arrondis + halo. */
.about-hero { display: block; width: 100%; height: auto; border-radius: 18px; margin: 4px 0 18px;
  border: 1px solid color-mix(in srgb, var(--cyan) 22%, var(--border));
  box-shadow: var(--shadow-card), 0 0 46px -24px var(--cyan), inset 0 1px 0 var(--card-sheen); }
/* Bannière en tête de page : CONTENEUR (image entière non recadrée + accroche superposée dans
   la zone sombre de gauche). */
/* BANNIÈRE SOUDÉE AU HEADER (2026-07-20) : pleine largeur (déborde des marges du .wrap),
   collée au bas du header (annule le padding haut du .wrap), SANS coins arrondis ni bordure
   sur les 3 côtés : seule la bordure INFÉRIEURE est visible. Elle fait ainsi corps avec le
   header et le décor, comme une bande intégrée et non une image « posée ». */
.page-banner { position: relative; display: block; overflow: hidden;
  width: 100vw; margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw);
  margin-top: -22px; margin-bottom: 20px;           /* soudée sous le header */
  border: 0; border-radius: 0;
  border-bottom: 2px solid color-mix(in srgb, var(--cyan) 52%, var(--gold));
  box-shadow: 0 14px 28px -22px rgba(0,0,0,.6); }
.page-banner-img { display: block; width: 100%; height: auto; }
/* Accroche calée à gauche (sur la zone sombre), centrée verticalement. */
.page-banner-cap { position: absolute; left: clamp(12px, 3.5%, 40px); top: 50%; transform: translateY(-50%);
  max-width: 44%; z-index: 2; display: flex; flex-direction: column; gap: clamp(7px, 1.8vw, 16px); text-align: left; }
/* La bannière est TOUJOURS sombre (image identique dans les 2 thèmes), donc le texte utilise des
   couleurs VIVES fixes (indépendantes du thème) → contraste maximal et lisibilité parfaite en
   clair COMME en sombre. Repli à la ligne (max-width + break-word) : le texte reste dans la zone
   sombre, ne touche jamais les personnes. */
/* 1er texte (HAUT) = TITRE de la page : or vif, PRÉDOMINANT (bien plus grand). */
.pb-eye { font-family: var(--font-display); font-weight: 800; line-height: 1.02; text-transform: none;
  letter-spacing: 0; font-size: clamp(1.5rem, 5.2vw, 3.2rem); overflow-wrap: break-word; word-break: break-word;
  color: #f0cd85; text-shadow: 0 2px 4px rgba(0,0,0,.85), 0 2px 18px rgba(0,0,0,.7); }
/* 2e texte (DESSOUS) = phrase d'accroche : plus petite, dégradé de marque VIF fixe. */
.pb-title { font-family: var(--font-display); font-weight: 700; line-height: 1.12;
  font-size: clamp(.9rem, 3vw, 1.55rem); overflow-wrap: break-word; word-break: break-word;
  background: linear-gradient(100deg, #f0cd85, #4be3a6 55%, #45dcf5);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,.9)) drop-shadow(0 2px 12px rgba(0,0,0,.6)); }
/* ═══ HARMONIE DES TAILLES SUR TÉLÉPHONE ═══════════════════════════════════════
   Sur petit écran, certains textes du corps ressortaient trop gros par rapport au reste
   (titres de page « Que veux-tu faire ? », vision « LANGIAL numérise… », textes des
   bannières). On les réduit LÉGÈREMENT pour une meilleure harmonie, sans toucher au design
   (cadres, dégradés, halos conservés). */
@media (max-width: 640px) {
  .view-title { font-size: 1.02rem; padding: 7px 13px; gap: 7px; }
  .hub-vision { font-size: .82rem; padding: 12px 14px; line-height: 1.5; }
  .hub-desc { font-size: .8rem; }
  .pb-eye { font-size: clamp(.95rem, 4.3vw, 1.6rem); }
  .pb-title { font-size: clamp(.72rem, 2.6vw, 1.2rem); }
}
/* État vide illustré (Explorer, Notifications, Demandes) : illustration + message centrés. */
.empty-state { text-align: center; padding: 16px 10px 6px; }
.empty-illus { display: block; width: clamp(140px, 40vw, 220px); height: auto; margin: 0 auto 12px;
  filter: drop-shadow(0 8px 24px rgba(0,0,0,.4)); }
.explore-empty { text-align: center; padding: 18px 10px; color: var(--muted); }
.explore-empty .empty-msg { margin-top: 4px; }
/* Illustration « merci » qui apparaît brièvement après une contribution réussie. */
.celebrate-illus { position: fixed; width: clamp(120px, 24vw, 168px); z-index: 10001; pointer-events: none;
  opacity: 0; transform: translate(-50%, -72%) scale(.5); filter: drop-shadow(0 12px 30px rgba(0,0,0,.5));
  animation: celebThanks 1300ms ease forwards; }
@keyframes celebThanks {
  12% { opacity: 1; transform: translate(-50%, -84%) scale(1.03); }
  72% { opacity: 1; transform: translate(-50%, -86%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -94%) scale(1); }
}
@media (prefers-reduced-motion: reduce) { .celebrate-illus { display: none; } }
/* Cadre « La vision » = HÉROS premium : fond en lavis d'accent, bordure dégradée vive tout
   autour, eyebrow, titre au dégradé de marque, filet lumineux. */
.about-vision { position: relative; overflow: hidden; border: 1.5px solid transparent;
  background:
    radial-gradient(120% 90% at 0% 0%, color-mix(in srgb, var(--cyan) 12%, transparent), transparent 55%),
    radial-gradient(120% 90% at 100% 0%, color-mix(in srgb, var(--gold) 12%, transparent), transparent 55%),
    var(--card-bg);
  box-shadow: 0 0 40px -22px var(--cyan), var(--shadow-card), inset 0 1px 0 var(--card-sheen), inset 0 -1px 0 var(--card-inner);
  padding: 22px clamp(16px, 3.5vw, 26px); }
.about-vision::after { content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1.5px; z-index: 1; pointer-events: none;
  background: linear-gradient(135deg, var(--cyan), var(--green) 45%, var(--gold)); background-size: 100% 100%;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--cyan) 40%, transparent)); animation: none; opacity: 1; }
.about-vision > * { position: relative; z-index: 2; }
.about-vision-eyebrow { display: inline-block; font-family: var(--font-mono); font-size: .72rem; font-weight: 700;
  letter-spacing: .18em; color: var(--gold); margin-bottom: 8px;
  padding: 3px 10px; border-radius: 999px; background: color-mix(in srgb, var(--gold) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--gold) 30%, var(--border)); }
.about-vision h3 { margin: 0 0 12px; font-size: clamp(20px, 3.6vw, 26px); line-height: 1.25;
  font-family: var(--font-display); font-weight: 700; letter-spacing: -.01em;
  background: linear-gradient(100deg, var(--cyan), var(--green) 55%, var(--gold));
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: var(--green); }
.about-share h3 { margin: 0 0 8px; font-size: 20px; color: var(--text); }
.about-vision p { margin: 0 0 11px; line-height: 1.62; color: var(--text); font-size: .96rem; }
.about-vision p:last-child { margin-bottom: 0; }
.about-vision p b { color: var(--text); font-weight: 700; }

.about-sec {
  margin: 28px 0 14px; font-size: 14px; font-weight: 800;
  letter-spacing: .16em; text-transform: uppercase; color: var(--cyan);
  display: flex; align-items: center; gap: 14px; text-align: center;
}
/* Titre de section flanqué de filets Ndop (ornement Grassfields discret) */
.about-sec::before, .about-sec::after {
  content: ""; flex: 1; height: 2px;
  background: linear-gradient(90deg, transparent, var(--gold) 55%, var(--cyan));
  opacity: .85;
}
.about-sec::after { background: linear-gradient(270deg, transparent, var(--gold) 55%, var(--cyan)); }
/* ── Séparateur Ndop réutilisable ─────────────────────────────────────────
   Filet dégradé laiton + losange central (laiton avec losange cyan à l'intérieur),
   même vocabulaire visuel que la trame de fond et le cadre du QR. Statique →
   aucun coût de rendu. Usage : <div class="ndop-sep"><i></i></div> */
.ndop-sep { display: flex; align-items: center; justify-content: center; gap: 12px; margin: 22px 0; }
.ndop-sep::before, .ndop-sep::after {
  content: ""; flex: 1; height: 2px;
  background: linear-gradient(90deg, transparent, var(--gold) 55%, var(--cyan), transparent 85%);
  background-size: 220% 100%; opacity: .85;
  animation: sepSweep 5.5s ease-in-out infinite;
}
.ndop-sep::after { background: linear-gradient(270deg, transparent, var(--gold) 55%, var(--cyan), transparent 85%);
  background-size: 220% 100%; animation-direction: reverse; }
@keyframes sepSweep { 0%,100% { background-position: 120% 0; } 50% { background-position: -20% 0; } }
/* losange central Grassfields + halo qui respire */
/* Centre du séparateur = véritable ORNEMENT africain (étoile rayonnante), à la place
   de l'ancien losange ; halo or qui respire ; la perle de lumière continue de balayer la barre. */
.ndop-sep i {
  position: relative; width: 34px; height: 34px;
  background: url("icons/orn/orn-07.png") center / contain no-repeat;
  filter: drop-shadow(0 0 7px color-mix(in srgb, var(--gold) 75%, transparent));
  animation: ngCardBreath 4.2s ease-in-out infinite;
}
.ndop-sep i::after { content: none; }
@keyframes sepPulse {
  0%,100% { box-shadow: 0 0 8px -2px var(--gold), inset 0 0 6px -2px var(--cyan); }
  50%     { box-shadow: 0 0 18px 1px var(--gold), inset 0 0 9px -1px var(--cyan); }
}

/* ── Carte stylisée des variantes (d'où viennent les contributions) ────────
   SVG inline (aucune dépendance, offline) : chaque village = un losange Ndop
   dimensionné par le nombre de contributions ; le village du contributeur est
   mis en avant en laiton. Positions STYLISÉES (pas une carte GPS). */
.vmap { margin: 4px 0 14px; padding: 12px 14px 8px; border: 1px solid var(--border);
  border-radius: 14px; background: var(--panel); box-shadow: var(--shadow-card); }
.vmap-head { font-weight: 700; color: var(--cyan); font-size: .92rem; margin-bottom: 4px; }
.vmap-sub { color: var(--muted); font-size: .76rem; margin-bottom: 6px; }
.vmap-svg { width: 100%; height: auto; max-height: 320px; display: block; overflow: visible; }

/* ── Mode présentation (plein écran, événements/réunions) ──────────────────── */
.present { position: fixed; inset: 0; z-index: 10000; background-color: var(--bg);
  /* MÊME FOND QUE LE SITE : motif Ndop (bg-pattern) sous un voile de la couleur de fond
     pour rester discret, en clair ET sombre. */
  background-image: linear-gradient(color-mix(in srgb, var(--bg) 72%, transparent), color-mix(in srgb, var(--bg) 72%, transparent)), url("icons/bg-pattern-light.jpg");
  background-size: auto, 480px auto; background-repeat: no-repeat, repeat;
  overflow-y: auto; overflow-x: hidden;
  /* Centrage SANS coupure : on NE met PAS align/justify-center (qui, quand le contenu
     dépasse la hauteur, rogne le haut et le rend inaccessible sur les petits écrans).
     On centre via `margin:auto` sur l'enfant → défilement propre depuis le haut. */
  display: flex; padding: 3vmin; }
.present[hidden] { display: none; }
:root[data-theme="dark"] .present { background-image: linear-gradient(color-mix(in srgb, var(--bg) 60%, transparent), color-mix(in srgb, var(--bg) 60%, transparent)), url("icons/bg-pattern-dark.jpg"); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .present { background-image: linear-gradient(color-mix(in srgb, var(--bg) 60%, transparent), color-mix(in srgb, var(--bg) 60%, transparent)), url("icons/bg-pattern-dark.jpg"); } }
/* Effet « TORCHE » : halos radiaux (cyan haut-gauche, vert bas-droite, reflet or
   au-dessus du logo) en fusion « screen » → la lumière s'ADDITIONNE au fond, comme
   l'aurore de l'app. Fixé derrière le contenu (z-index 0 < .present-inner z-index 1). */
.present::before {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  mix-blend-mode: screen;
  background:
    radial-gradient(62vmax 62vmax at 14% 9%,  var(--aurora-a), transparent 62%),
    radial-gradient(62vmax 62vmax at 88% 93%, var(--aurora-b), transparent 62%),
    radial-gradient(44vmax 44vmax at 50% 3%,  color-mix(in srgb, var(--gold) 34%, transparent), transparent 60%);
}
.present-close { position: fixed; top: 2vmin; right: 2vmin; width: 46px; height: 46px;
  border-radius: 12px; border: 1px solid var(--border); background: var(--panel);
  color: var(--text); font-size: 1.2rem; cursor: pointer; z-index: 2; }
.present-close:hover { border-color: var(--cyan); color: var(--cyan); }
.present-inner { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center;
  gap: clamp(3vmin, 4.6vmin, 5.2vmin); max-width: 1240px; width: 100%;
  margin: auto; box-sizing: border-box; text-align: center; }
.present-brand { display: flex; flex-direction: column; align-items: center; }
/* Halo cyan RENFORCÉ (double drop-shadow → lumière plus dense), comme l'affiche. */
.present-logo { width: clamp(96px, 16vmin, 170px); height: auto;
  filter: drop-shadow(0 0 48px rgba(34,211,238,.6)) drop-shadow(0 0 22px rgba(34,211,238,.5)); }
.present-title { margin: 1.5vmin 0 0; font-size: clamp(2.4rem, 9vmin, 5rem); font-weight: 800;
  letter-spacing: .02em; background: linear-gradient(100deg, var(--cyan), var(--green));
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.present-tag { margin: 1vmin 0 0; font-size: clamp(1rem, 3vmin, 1.6rem); color: var(--muted); }
/* Trois cadres RÉPARTIS ÉQUITABLEMENT sur toute la largeur (grille 3 colonnes
   égales ; se replie proprement sur petit écran). */
.present-acts { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(3vmin, 5.5vmin, 7vmin); width: 100%; }
.present-act { display: flex; flex-direction: column; align-items: center; gap: .6vmin;
  background: var(--panel); border: 4px solid var(--border); border-radius: 18px;
  padding: 3vmin 4vmin; box-sizing: border-box; box-shadow: var(--shadow-card); }
/* Une COULEUR de lumière propre à chaque cadre (assortie à son icône) :
   Traduire → vert, Transcrire → violet, Explorer → or. Bordure épaisse + halo. */
.present-act:nth-child(1) { border-color: var(--green);
  background: color-mix(in srgb, var(--green) 9%, var(--panel));
  box-shadow: 0 0 52px -14px var(--green), var(--shadow-card); }
.present-act:nth-child(2) { border-color: #a78bfa;
  background: color-mix(in srgb, #a78bfa 10%, var(--panel));
  box-shadow: 0 0 52px -14px #a78bfa, var(--shadow-card); }
.present-act:nth-child(3) { border-color: var(--gold);
  background: color-mix(in srgb, var(--gold) 10%, var(--panel));
  box-shadow: 0 0 52px -14px var(--gold), var(--shadow-card); }
@media (max-width: 640px) { .present-acts { grid-template-columns: 1fr; } }
.present-act .present-ico { width: clamp(56px, 9vmin, 92px); height: auto; display: block; }
.present-act b { font-size: clamp(1.1rem, 3.2vmin, 1.7rem); color: var(--text); }
.present-act span { color: var(--muted); font-size: clamp(.8rem, 2.2vmin, 1.05rem); }
/* Bloc d'appel à l'action MIS EN ÉVIDENCE : panneau encadré cyan (l'action),
   adresse publique en pastille laiton/or (l'accent Ndop) sous le QR. Hiérarchie
   nette : titre → QR → adresse → compteur. */
.present-cta { display: flex; flex-direction: column; align-items: center; gap: 2.2vmin;
  padding: 3.4vmin clamp(16px, 4vmin, 44px); border-radius: 28px;
  max-width: 100%; box-sizing: border-box;
  background: color-mix(in srgb, var(--cyan) 7%, var(--panel));
  border: 2px solid color-mix(in srgb, var(--cyan) 48%, var(--border));
  box-shadow: 0 0 70px -22px var(--cyan),
    inset 0 0 0 1px color-mix(in srgb, var(--gold) 22%, transparent); }
.present-scan { font-size: clamp(1.35rem, 4.2vmin, 2.5rem); font-weight: 800; color: var(--cyan);
  letter-spacing: .01em; text-align: center; }
.present-qr { width: clamp(220px, 38vmin, 360px); height: auto; border-radius: 16px;
  box-shadow: 0 0 72px -10px var(--cyan), 0 0 32px -6px var(--cyan); }
.present-url-wrap { display: flex; flex-direction: column; align-items: center; gap: .9vmin; max-width: 100%; }
.present-url-label { color: var(--muted); font-size: clamp(.85rem, 2.2vmin, 1.15rem); }
/* Lien MIS EN ÉVIDENCE sous le QR : pastille dorée dense, bordure épaisse, halo. */
.present-url { font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: clamp(.95rem, 2.8vmin, 1.55rem); font-weight: 700; color: var(--gold);
  text-decoration: none; padding: 1.6vmin 3.4vmin; border-radius: 14px;
  background: color-mix(in srgb, var(--gold) 20%, var(--bg));
  border: 3px solid color-mix(in srgb, var(--gold) 62%, var(--border));
  box-shadow: 0 0 34px -8px var(--gold), inset 0 0 0 1px color-mix(in srgb, var(--gold) 22%, transparent);
  /* Reste TOUJOURS dans le panneau : borné à 100 % et coupé proprement au besoin. */
  max-width: 100%; box-sizing: border-box; overflow-wrap: anywhere; word-break: break-word; text-align: center;
  transition: box-shadow .15s ease, border-color .15s ease, color .15s ease; }
.present-url:hover { border-color: var(--gold); color: var(--text);
  box-shadow: 0 0 40px -6px var(--gold); }
.present-stat { color: var(--muted); font-size: clamp(.9rem, 2.4vmin, 1.2rem); }
.present-tools { display: flex; gap: 2vmin; flex-wrap: wrap; justify-content: center; margin-top: 1vmin; }
.present-dl { border: 1px solid var(--border); background: var(--panel); color: var(--text);
  border-radius: 12px; padding: 1.4vmin 3vmin; font-size: clamp(.85rem, 2.2vmin, 1.05rem);
  cursor: pointer; transition: border-color .15s ease, color .15s ease, box-shadow .15s ease; }
.present-dl:hover { border-color: var(--cyan); color: var(--cyan); box-shadow: 0 0 16px -6px var(--cyan); }
.about-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
/* Cartes « À propos » : même stylisation que les cartes du flyer — accent
   coloré par carte (--a), barre haute, losange, icône SVG en boîte flottée. */
.about-cell {
  position: relative; overflow: hidden;
  padding-top: 24px;
  border: 1px solid color-mix(in srgb, var(--a, var(--cyan)) 32%, var(--border));
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--a, var(--cyan)) 13%, transparent), transparent 60%),
    var(--card-bg);
}
.about-cell::before {
  content: ""; position: absolute; left: 0; top: 0; right: 0; height: 4px;
  background: linear-gradient(90deg, var(--a, var(--cyan)), color-mix(in srgb, var(--a, var(--cyan)) 25%, transparent));
}
.about-cell::after {
  content: ""; position: absolute; right: 14px; bottom: 14px; width: 12px; height: 12px;
  transform: rotate(45deg); border-radius: 3px;
  background: var(--a, var(--cyan)); opacity: .38; box-shadow: 0 0 12px var(--a, var(--cyan));
}
.about-cell .about-ic {
  float: right; margin: 0 0 10px 14px;
  width: 50px; height: 50px; border-radius: 14px; color: var(--a, var(--cyan));
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--a, var(--cyan)) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--a, var(--cyan)) 34%, transparent);
}
.about-cell h4 { margin: 0 0 7px; font-size: 19px; color: var(--text); }
.about-cell p { margin: 0; line-height: 1.55; color: var(--muted); }

.about-share {
  display: flex; gap: 20px; align-items: center; justify-content: space-between;
  margin-top: 26px;
}
.about-share-txt { flex: 1; }
.about-share-txt p { margin: 6px 0 12px; color: var(--muted); }
.about-links { display: flex; flex-wrap: wrap; gap: 12px; }
/* Boutons « Partager le projet » MIS EN ÉVIDENCE : vrais boutons pleins, plus grands
   que des chips, avec accent coloré (téléchargements en cyan, Mode présentation en
   accent principal cyan→vert lumineux). */
.about-share-btn { display: inline-flex; align-items: center; gap: 8px; text-decoration: none;
  font: inherit; font-size: .95rem; font-weight: 700; cursor: pointer; line-height: 1;
  padding: 12px 20px; border-radius: 12px; color: var(--cyan);
  border: 1.5px solid color-mix(in srgb, var(--cyan) 55%, var(--border));
  background: color-mix(in srgb, var(--cyan) 9%, var(--panel));
  transition: transform .12s ease, box-shadow .15s ease, border-color .15s ease, color .15s ease; }
.about-share-btn:hover { transform: translateY(-2px); color: var(--text);
  border-color: var(--cyan); box-shadow: 0 6px 22px -8px var(--cyan); }
.about-share-btn--main { color: #04120b; border: none;
  background: linear-gradient(100deg, var(--cyan), var(--green)); box-shadow: 0 0 22px -8px var(--cyan); }
.about-share-btn--main:hover { color: #04120b; transform: translateY(-2px);
  box-shadow: 0 8px 26px -8px var(--green); }
.about-qr { width: clamp(200px, 46vw, 280px); height: auto; flex: 0 0 auto; border-radius: 16px; }

.about-cta { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; margin-top: 26px; }

@media (max-width: 680px) {
  .about-grid { grid-template-columns: 1fr; }
  .about-share { flex-direction: column-reverse; align-items: stretch; text-align: center; }
  .about-qr { align-self: center; }
  .about-links { justify-content: center; }
}

/* ---- Boutons de partage du site (réseaux sociaux) ---- */
.share-lead { display: block; color: var(--muted); font-size: .86rem; margin: 12px 0 9px; }
.sharebar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.share-btn--native { display: inline-flex; align-items: center; gap: 8px; font: inherit; font-weight: 700;
  font-size: .9rem; padding: 9px 16px; border-radius: 999px; cursor: pointer;
  border: 1.5px solid var(--cyan); color: var(--cyan);
  background: color-mix(in srgb, var(--cyan) 12%, var(--panel));
  transition: background .15s ease, color .15s ease, transform .1s ease; }
.share-btn--native svg { width: 18px; height: 18px; fill: currentColor; }
.share-btn--native:hover { background: var(--cyan); color: var(--bg); transform: translateY(-1px); }
/* Fond des icônes via une VARIABLE (le survol coloré la remplace directement, sans
   guerre de spécificité) : blanc en mode sombre pour que les logos ressortent bien. */
.share-ico { display: inline-grid; place-items: center; width: 42px; height: 42px; border-radius: 50%;
  cursor: pointer; border: 1px solid var(--share-ico-bd, var(--border));
  background: var(--share-ico-bg, var(--panel)); color: var(--text);
  text-decoration: none; transition: transform .12s ease, box-shadow .15s ease, background .15s ease, color .15s ease; }
.share-ico svg { width: 22px; height: 22px; fill: currentColor; }
.share-ico:hover { transform: translateY(-2px); }
.share-ico--whatsapp { color: #25D366; }
.share-ico--whatsapp:hover { background: #25D366; color: #fff; box-shadow: 0 7px 16px -6px #25D366; }
.share-ico--facebook { color: #1877F2; }
.share-ico--facebook:hover { background: #1877F2; color: #fff; box-shadow: 0 7px 16px -6px #1877F2; }
.share-ico--x { color: #0f1419; }                                  /* noir X : visible sur blanc */
.share-ico--x:hover { background: #0f1419; color: #fff; box-shadow: 0 7px 16px -8px #0f1419; }
.share-ico--telegram { color: #229ED9; }
.share-ico--telegram:hover { background: #229ED9; color: #fff; box-shadow: 0 7px 16px -6px #229ED9; }
.share-ico--instagram { color: #8134AF; }
.share-ico--instagram:hover { color: #fff;
  background: linear-gradient(45deg, #F58529, #8134AF, #515BD4);   /* IG sans le magenta */
  box-shadow: 0 7px 16px -6px #8134AF; }
.share-ico--copy { color: var(--cyan); }
.share-ico--copy:hover { background: var(--cyan); color: var(--bg); box-shadow: 0 7px 16px -6px var(--cyan); }
/* Emplacements */
.foot-share { display: flex; align-items: center; justify-content: center; gap: 12px; flex-wrap: wrap;
  padding: 16px 0 2px; margin-top: 10px; border-top: 1px solid var(--border); }
.foot-share .share-lead { margin: 0; }
/* Section partage de l'accueil : CADRE OPAQUE soigné (la trame Ndop ne le traverse
   pas), liseré dégradé en haut + halo cyan. */
.hub-share { margin-top: 28px; text-align: center; position: relative; overflow: hidden;
  padding: 22px 24px 24px; border-radius: 18px; background: var(--card-bg);
  border: 1px solid color-mix(in srgb, var(--cyan) 30%, var(--border));
  box-shadow: 0 0 34px -20px var(--cyan), var(--shadow-card); }
.hub-share::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: linear-gradient(90deg, var(--cyan), var(--green), var(--gold), var(--green), var(--cyan)); }
.hub-share .sharebar { justify-content: center; }
.hub-share .share-lead { margin: 0 0 14px; color: var(--text); font-weight: 600; font-size: .96rem; }
.present-share { margin-top: 12px; }
.present-share .sharebar { justify-content: center; }
@media (prefers-reduced-motion: reduce) {
  .share-btn--native, .share-ico { transition: none; }
}

/* ============================================================================
   PERF — DÉCOR ALLÉGÉ + FIGÉ PENDANT LA FRAPPE
   ----------------------------------------------------------------------------
   Les animations décoratives continues sont CONSERVÉES mais allégées (durées
   rallongées, glows moins intenses : cf. plus bas). Surtout, elles sont TOUTES
   GELÉES quand le clavier ngiemboon est ouvert (`body.kb-docked`) → la frappe
   reste parfaitement fluide (le fil principal est libre), et le décor reprend
   vie dès que le clavier se ferme. Ainsi le décor ne disparaît pas, il se met
   juste en pause là où la réactivité prime. */
body.kb-docked::before, body.kb-docked::after,
body.kb-docked .brand::before, body.kb-docked .topbar::after,
body.kb-docked .brand-mark::before, body.kb-docked .brand-mark::after,
body.kb-docked .foot-mark::before, body.kb-docked .foot-mark::after,
body.kb-docked .view-title::before, body.kb-docked .view-title::after,
body.kb-docked .hub-card, body.kb-docked .hub-card::before, body.kb-docked .hub-ico,
body.kb-docked #btn-mic-test, body.kb-docked .tr-guide-open,
body.kb-docked .btn--primary, body.kb-docked .btn--next, body.kb-docked .btn--send,
body.kb-docked .btn--primary::after, body.kb-docked .btn--next::after, body.kb-docked .btn--send::after,
body.kb-docked .lang-search-btn, body.kb-docked .lang-declare-cta, body.kb-docked .corr-submit, body.kb-docked .tour-next,
body.kb-docked .lang-search-btn::after, body.kb-docked .lang-declare-cta::after, body.kb-docked .corr-submit::after, body.kb-docked .tour-next::after,
body.kb-docked .card::after, body.kb-docked .chip--on,
body.kb-docked .ndop-sep, body.kb-docked .ndop-sep i, body.kb-docked .ndop-sep::before, body.kb-docked .ndop-sep::after,
body.kb-docked .field--consent {
  animation: none !important;
}

/* ===== Voile de CHARGEMENT (boot / rechargement) =========================
   Visible d'emblée (posé dans le HTML), retiré en fin d'init par hideAppLoader().
   Anneau conique aux couleurs de la marque qui tourne autour du logo qui respire. */
.app-loader { position: fixed; inset: 0; z-index: 9999; display: grid; place-items: center;
  gap: 18px; align-content: center;
  background: radial-gradient(120% 90% at 50% 32%, var(--panel), var(--bg));
  transition: opacity .5s ease, visibility .5s ease; }
.app-loader--hide { opacity: 0; visibility: hidden; pointer-events: none; }
.app-loader-mark { position: relative; width: 262px; height: 262px; display: grid; place-items: center; }
.app-loader-mark img { width: 168px; height: 168px; border-radius: 44px;
  filter: drop-shadow(0 0 30px color-mix(in srgb, var(--cyan) 55%, transparent));
  animation: loaderPulse 1.8s ease-in-out infinite; }
.app-loader-ring { position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0deg, var(--cyan) 95deg, var(--green) 210deg, transparent 320deg);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 9px), #000 calc(100% - 8px));
          mask: radial-gradient(farthest-side, transparent calc(100% - 9px), #000 calc(100% - 8px));
  animation: loaderSpin 1s linear infinite; }
.app-loader-txt { color: var(--muted); font-size: .9rem; letter-spacing: .03em; }
@keyframes loaderSpin { to { transform: rotate(360deg); } }
@keyframes loaderPulse { 0%, 100% { transform: scale(1); opacity: .92; } 50% { transform: scale(1.07); opacity: 1; } }
/* ═══ PERF TÉLÉPHONE (fluidité avant tout) ═══════════════════════════════════════
   Sur petit écran (machines faibles), deux coûts dominent et provoquent la lenteur :
   (1) le décor animé EN CONTINU (aurores, comètes coniques, respirations de box-shadow,
       halos, sheens, glows) qui repeint/compose à chaque frame ;
   (2) le flou d'arrière-plan `backdrop-filter` qui recalcule un flou de toute la zone à
       chaque frame de défilement.
   On FIGE donc tout le décor (il reste VISIBLE mais statique) et on RETIRE le flou, puis on
   RÉACTIVE uniquement les animations FONCTIONNELLES (retour d'état) : chargement,
   enregistrement, consentement requis, bannière de mise à jour, lecture audio en cours.
   Le décor animé complet reste actif sur ordinateur (> 900px). */
@media (max-width: 900px) {
  *, *::before, *::after {
    animation: none !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }
  /* Animations d'ÉTAT réactivées (elles renseignent l'utilisateur, coût négligeable) */
  .app-loader-mark img { animation: loaderPulse 1.8s ease-in-out infinite !important; }
  .app-loader-ring { animation: loaderSpin 1s linear infinite !important; }
  .rec-timer::before { animation: ngRecPulse 1s ease-in-out infinite !important; }
  .btn--rec.is-recording { animation: ngRecBtn 1.4s ease-in-out infinite !important; }
  .field--consent:not(.is-checked) { animation: ngConsentPulse 2.4s ease-in-out infinite !important; }
  .aplayer.is-playing .aplayer-play .aplayer-ring { animation: aplayerPulse 1.8s ease-out infinite !important; }
  .update-banner { animation: updGlow 1.8s ease-in-out infinite !important; }
  .update-dot { animation: updBlink 1s steps(1,end) infinite !important; }
  .update-btn { animation: updPulse 1.6s ease-in-out infinite !important; }
}
/* Curseur « occupé » pendant une attente pilotée (rechargement, fetch long). */
body.is-busy, body.is-busy * { cursor: progress !important; }
/* Curseur de MARQUE (PC) : flèche cyan->vert comme curseur par défaut partout où l'on
   navigue. `cursor` étant hérité, on rétablit explicitement le curseur TEXTE sur les champs
   de saisie ; les éléments cliquables gardent leur `pointer` (main système = affordance). */
body { cursor: url("icons/cur-pointer.png") 2 1, auto; }
/* Sur les éléments cliquables : curseur MAIN système normal (le doigt du navigateur),
   via le `cursor: pointer` déjà présent sur chaque bouton/lien. Le curseur cyan reste
   sur le reste de la page. */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="button"]):not([type="submit"]),
textarea, [contenteditable="true"] { cursor: text; }
@media (prefers-reduced-motion: reduce) {
  .app-loader-ring { animation: none; opacity: .55; }
  .app-loader-mark img { animation: none; }
}

/* ALLÈGEMENT des animations continues (moins d'intensité / plus lentes) : impact réduit
   au repos, tout en gardant un mouvement présent. */
.card::after { animation-duration: 26s !important; opacity: .5 !important; }   /* bordure des cartes : drift très lent */
.hub-card { animation-duration: 9s !important; }                              /* halo qui respire : plus doux */
.hub-card::before { animation-duration: 9s !important; }                      /* comète : plus lente */
.hub-ico { animation-duration: 6s !important; }                              /* glow d'icône : plus lent */
.nav-tab { animation-duration: 9s !important; }                              /* onglets : halo plus doux */
.nav-tab::before { animation-duration: 9s !important; }                      /* onglets : comète plus lente */
.nav-tab .nav-ico { animation-duration: 6s !important; }                     /* onglets : glow d'icône plus lent */
.brand::before { animation-duration: 16s !important; }                        /* aurore d'en-tête : plus lente */
.btn--primary, .btn--next, .btn--send:not(:disabled),
.lang-search-btn, .lang-declare-cta, .corr-submit, .tour-next,
#btn-mic-test, .tr-guide-open { animation-duration: 5s !important; }          /* halo des CTA : plus lent */
@keyframes ngCtaGlowLite { 0%,100% { filter: drop-shadow(0 0 2px var(--cta-g)); } 50% { filter: drop-shadow(0 0 8px var(--cta-g)); } }
.btn--primary, .btn--next, .btn--send:not(:disabled),
.lang-search-btn, .lang-declare-cta, .corr-submit, .tour-next,
#btn-mic-test, .tr-guide-open { animation-name: ngCtaGlowLite !important; }   /* glow CTA moins intense */
