/* ══════════════════════════════════════════════════════════════
   KREYE — états

   LA SEULE FEUILLE QUI N'EST PAS ISSUE DU PROTOTYPE.

   Les 15 autres CSS de public_html sont copiées telles quelles depuis le
   prototype, au bit près : leur `diff` vide est la preuve de fidélité.
   Modifier l'une d'elles corromprait cette preuve en silence. D'où ce fichier,
   chargé APRÈS, et qui ne contient qu'une chose :

       LA PEINTURE DES ÉTATS QUE LE PROTOTYPE N'A JAMAIS EUS.

   Rien d'autre n'y entre. Pas de correctif, pas d'ajustement, pas de
   « pendant qu'on y est ». Chaque bloc dit quel état il peint, et pourquoi
   le prototype ne l'avait pas.

   ── Pourquoi ce fichier existe ───────────────────────────────────────────
   Une classe de bugs, pas un cas : le prototype n'a jamais rien désactivé,
   jamais rien mis en « Bientôt », jamais rien vidé. Chaque fois qu'on
   introduit un état qu'il ignorait, on change la SÉMANTIQUE sans changer la
   PEINTURE — et l'état passe inaperçu à l'œil tout en étant juste dans le DOM.

   Deux fois de suite, le DOM était correct et l'écran mentait :
     · une carte « Bientôt » = 8,64 px de gris dans un coin ;
     · un bouton `disabled` = lime plein, cursor:pointer.

   Règle : tout nouvel état a sa peinture AVANT d'être intégré, et un test
   qui la mesure.
   ══════════════════════════════════════════════════════════════ */


/* ──────────────────────────────────────────────────────────────
   1. COMMUNAUTÉ « BIENTÔT »

   Le prototype n'avait pas cet état : ses 8 cartes étaient toutes ouvertes,
   et son `.act` portait des points d'activité pulsants — un indicateur de
   vitalité, pas un état d'accès.

   Chez nous, 4 communautés sur 8 sont fermées au lancement (8 communautés
   vides = 8 villages fantômes ; 4 animées = une plateforme vivante).
   Une carte fermée qui ressemble à une carte ouverte est une promesse
   implicite d'accès.
   ────────────────────────────────────────────────────────────── */

/* L'icône perd le lime.
   C'est le signal le plus fort et le moins bruyant : dans TOUTE la charte, le
   lime veut dire vivant — le point qui pulse, l'accent du titre, le bouton
   principal. Une communauté fermée n'est pas vivante. À elle seule, cette
   règle rend les deux états lisibles d'un coup d'œil, à distance. */
.comm.is-soon .ic{ color:var(--muted-2); }

/* Le badge devient une pastille ambre.
   #E4B24A n'est pas inventé : le Design System le documente sous le nom
   « Ambre » (ds-app.jsx:20), et l'admin l'utilise DÉJÀ pour l'état soon des
   feature flags — .seg3 button.on.soon{ background:rgba(228,178,74,.16);
   color:#E4B24A }. C'est la couleur que la charte donne à « Bientôt » : on ne
   fait que l'appliquer là où elle manquait.

   Forme reprise de .adm-item .soon (admin-styles.css:35) : mono, majuscules,
   bordure, border-radius:100px. Seule la taille monte — .54rem (8,6 px) était
   invisible ; l'admin descend à .46rem mais sur une ligne de nav, pas sur une
   carte qu'on lit à distance. */
.comm.is-soon .act{
  font-size:.58rem;
  color:#E4B24A;
  border:1px solid rgba(228,178,74,.35);
  background:rgba(228,178,74,.10);
  padding:3px 8px;
  border-radius:100px;
}

/* Ce qu'on NE touche PAS, volontairement :
   · le titre et la description restent pleinement lisibles — on atténue la
     promesse d'accès, pas l'information. Le README §I interdit l'accès caché,
     et une description délavée serait une info cachée.
   · la bordure, le fond, le lift au survol. Les cartes sont des <div>, pas des
     liens — dans le prototype comme ici. Le survol ne promet aucune navigation. */


/* ──────────────────────────────────────────────────────────────
   2. BOUTON DÉSACTIVÉ

   Le prototype n'avait pas cet état : aucun de ses boutons n'était jamais
   désactivé — ils affichaient tous un toast « (démo) ».

   Chez nous, « Choisir Créateur » et « Choisir Pro » sont éteints tant que
   Stripe n'existe pas (Phase D). Mesuré avant correction : le bouton Créateur
   sortait en background:#E6FF00, cursor:pointer, opacity:1 — le bouton le plus
   visible de la page, désactivé mais peint comme l'appel à l'action principal.
   Un visiteur clique, rien ne se passe, il croit à un site cassé.

   Le vocabulaire existe déjà dans la charte, il n'était juste pas ici :
     .viewtabs button:disabled{ opacity:.35; cursor:not-allowed; }
     .cbox button:disabled{ opacity:.4; cursor:not-allowed; box-shadow:none; }
   On l'étend à .btn, sans rien inventer.
   ────────────────────────────────────────────────────────────── */

.btn[disabled],
.btn[aria-disabled="true"]{
  opacity:.4;
  cursor:not-allowed;
  box-shadow:none;
}

/* Le survol doit se taire aussi : un bouton éteint qui réagit reste une
   invitation. .btn:hover pose un translateY et un glow — on les annule. */
.btn[disabled]:hover,
.btn[aria-disabled="true"]:hover{
  transform:none;
  box-shadow:none;
  filter:none;
}

/* La pastille .tick perd le lime : elle est l'accent vivant du bouton. */
.btn[disabled] .tick,
.btn[aria-disabled="true"] .tick{ background:var(--muted-2); }


/* ──────────────────────────────────────────────────────────────
   3. GRILLE À COLONNES FIXES, PARTIELLEMENT REMPLIE

   Le prototype n'avait pas cet état : ses grilles étaient toujours pleines,
   parce que leur contenu était écrit en dur.

   .net-stats est une grille à 2 colonnes dont les FILETS sont dessinés par
   `gap:1px` sur un fond var(--line). Le prototype y mettait 4 stats → un 2×2
   propre. Il n'en reste qu'une : « Collaborations actives ». Les 3 autres sont
   parties parce qu'elles mentaient — 47 pays (incalculable : on stocke
   6 régions), 128k connexions (jamais défini), 24/7 (la promesse supprimée).

   Mesuré : 1 enfant dans une grille de 2 colonnes de 399 px = une cellule vide
   de 399 px, entourée de son filet. Un trou encadré.

   :has(> :only-child) — « la grille dont l'unique enfant est fils unique ».
   La règle se corrige d'elle-même le jour où une seconde stat devient
   calculable : rien à retoucher ici. */
.net-stats:has(> :only-child){ grid-template-columns:1fr; }


/* ──────────────────────────────────────────────────────────────
   4. MEMBRE SANS NOM

   Le prototype n'avait pas cet état : ses écrans affichent {m.name} sans
   filet, parce que son data.name est toujours une chaîne.

   Chez nous, members.name vaut NULL entre l'inscription et l'étape 01. Et
   l'abandon en cours d'onboarding — que le Super Admin veut EXPRESSÉMENT
   préserver — rend cet état PERMANENT : un membre peut vivre sans nom pour
   toujours, au Salon comme à l'admin.

   « Profil à compléter » ne doit pas se lire comme un nom. Sans peinture, la
   liste de l'admin donnerait :

       Naïka Étienne      @naika
       Profil à compléter @toto        ← se lit comme quelqu'un qui s'appelle ainsi

   C'est le même bug que la carte « Bientôt » : le DOM est juste, l'écran ment.

   ⚠️ La classe est posée par member_name_is_placeholder(), qui lit la DONNÉE,
   jamais par une comparaison du texte rendu. Rien n'empêche quelqu'un de se
   nommer littéralement « Profil à compléter » — la colonne accepte 80
   caractères libres. Celui-là s'affichera comme un vrai nom, parce que c'en
   est un.
   ────────────────────────────────────────────────────────────── */

/* ── Ce que la charte dit VRAIMENT, vérifié avant d'écrire ───────────────
   · `font-style:italic` : ZÉRO occurrence dans les 17 feuilles. J'avais failli
     l'ajouter en l'attribuant à la charte. C'est un geste que la marque
     n'utilise nulle part.
   · Les 22 déclarations de `.nm` sont unanimes : --f-display, font-weight:800,
     text-transform:uppercase. Un nom, chez KREYE, est une CAPITALE GRASSE.
   · --muted-2 (#5E5E5E) est la couleur des PLACEHOLDERS de la charte
     (admin-modules.css:20 — .mod-search input::placeholder). C'est la
     sémantique littérale de ce qu'on peint : un texte qui tient la place
     d'une valeur absente.

   ── Pourquoi c'est un ENFANT et pas une classe sur .nm ───────────────────
   Mesuré : `.recap .rc-id .nm` pèse (0,3,0), `.nameless` pèse (0,1,0). Posée
   SUR le .nm, la classe aurait perdu la cascade et n'aurait rien peint —
   states.css est chargée après, mais la spécificité ne se laisse pas
   convaincre par l'ordre. Le membre sans nom serait sorti en PROFIL À
   COMPLÉTER, capitale grasse, indiscernable d'un vrai nom.

   Le repli est donc un <span> À L'INTÉRIEUR du .nm : font-weight et
   text-transform sont hérités, et une règle directe bat toujours un héritage.
   Aucun !important, aucune guerre de sélecteurs.

   text-transform:none est le signal décisif : dans une liste où TOUS les vrais
   noms sont en capitales, une ligne en casse normale ne peut pas se lire comme
   un nom. C'est exactement la confusion que le Super Admin voulait éviter à
   l'admin. Et ce n'est pas un geste nouveau — c'est l'absence de geste. */
.nameless{
  color:var(--muted-2);
  font-weight:400;
  text-transform:none;
  letter-spacing:normal;
}


/* ──────────────────────────────────────────────────────────────
   5. CHAMP EN ERREUR

   Le prototype n'a AUCUN style d'erreur. Vérifié : ni `err`, ni `error`, ni
   `invalid` dans les 17 feuilles. C'est cohérent — il n'avait aucun formulaire
   qui puisse échouer. Ses champs acceptaient tout, ses boutons affichaient un
   toast « (démo) ».

   Le nôtre refuse : une adresse déjà prise, un mot de passe trop court. Sans
   peinture, le message sortait en texte courant sous un champ inchangé — le
   membre relit trois fois sans voir lequel des deux champs est en cause.

   La couleur n'est pas choisie : le Design System la documente sous le nom
   « Danger » — ["Danger","#FF6B5E","Actions lourdes"] (ds-app.jsx:20). Même
   cas que l'ambre « Bientôt » : la charte l'avait, le CSS ne l'avait pas.
   ────────────────────────────────────────────────────────────── */

.fld-err{
  margin-top:8px;
  font-family:var(--f-mono);
  font-size:.62rem;
  letter-spacing:.06em;
  color:#FF6B5E;
}

/* Le champ fautif porte la couleur, sinon le message flotte sans propriétaire.
   aria-invalid est déjà là pour le lecteur d'écran : on peint ce qu'il annonce. */
.fld input[aria-invalid="true"]{ border-color:#FF6B5E; }
.fld input[aria-invalid="true"]:focus{
  border-color:#FF6B5E;
  box-shadow:0 0 0 3px rgba(255,107,94,.12);
}


/* ──────────────────────────────────────────────────────────────
   6. BOUTON « REJOINDRE » ÉTEINT

   Le prototype n'a pas cet état : ses 6 communautés sont toutes ouvertes,
   toutes joignables. 4 des nôtres sur 8 sont fermées au lancement.

   .btn[disabled] (§2) ne couvre pas .joinb : ce n'est pas un .btn. Sans cette
   règle, le bouton d'une communauté fermée sortait EXACTEMENT comme celui d'une
   communauté ouverte — le bug des Tarifs, à l'identique.

   ⚠️ Ce bouton n'est PAS la garde. ob_save_step3() porte `state = 'live'` dans
   son WHERE : qui poste le slug d'une communauté fermée à la main n'y entre
   pas. Vérifié par le banc. Cacher un bouton n'a jamais protégé personne
   (README §6) — ceci ne fait que dire la vérité à l'œil.

   La RAISON est à côté du bouton, jamais un gris muet : la carte porte son
   badge ambre « Bientôt » (§1, .comm.is-soon .act, même couleur, même forme).
   Direction du Super Admin : « le bouton porte sa raison à côté de lui ».
   ────────────────────────────────────────────────────────────── */

.joinb[disabled],
.joinb[aria-disabled="true"]{
  opacity:.4;
  cursor:not-allowed;
  box-shadow:none;
}
.joinb[disabled]:hover,
.joinb[aria-disabled="true"]:hover{
  color:var(--muted);
  border-color:var(--line-2);
  transform:none;
}

/* Le badge « Bientôt » de la carte, dans la grille de l'onboarding.
   .comm.is-soon (§1) vise la Landing ; ici la classe porte sur .commcard. */
.commcard.is-soon .ic{ color:var(--muted-2); }
.commcard.is-soon .act{
  font-size:.58rem;
  font-family:var(--f-mono);
  text-transform:uppercase;
  letter-spacing:.1em;
  color:#E4B24A;
  border:1px solid rgba(228,178,74,.35);
  background:rgba(228,178,74,.10);
  padding:3px 8px;
  border-radius:100px;
  margin-right:8px;
}


/* ──────────────────────────────────────────────────────────────
   7. COMPTE NON VÉRIFIÉ  ·  MEMBRE SUSPENDU
      (la liste de l'admin)

   Le prototype n'a NI l'un NI l'autre : ses membres de démo sont tous actifs
   et tous vérifiés. Deux états, deux raisons de les peindre.

   ── Non vérifié ─────────────────────────────────────────────────────────
   C'est l'état de 100 % des comptes tant que le Mailer n'existe pas (B8) :
   rien n'envoie de lien, donc personne ne peut vérifier. Ce n'est PAS une
   alerte — c'est le normal du moment. D'où l'ambre, la couleur que la charte
   donne à « pas encore » (le badge « Bientôt », §1), et surtout PAS le rouge
   Danger : un cockpit qui inquiète sur un état normal apprend à ignorer ses
   propres signaux.

   ── Suspendu ────────────────────────────────────────────────────────────
   Là, le rouge est juste : #FF6B5E, que le Design System documente sous
   « Danger — actions lourdes et erreurs de saisie » (ds-app.jsx:20).

   ⚠️ Et cet état PEUT CHANGER SOUS LES YEUX DE L'ADMIN. auth_user() relit le
   statut en base à CHAQUE requête (A4) : un membre suspendu depuis un autre
   onglet apparaît suspendu au rechargement suivant, sans purge de session.
   La peinture dit donc un état vivant, pas un état figé au chargement — c'est
   pour ça qu'elle appelle l'œil au lieu de se fondre dans la ligne.

   Le badge n'existe QUE si le membre n'est pas actif : un « actif » explicite
   sur chaque ligne serait du bruit. L'absence de badge EST l'état normal.
   ────────────────────────────────────────────────────────────── */

.badge-verif,
.badge-statut{
  display:inline-flex;
  align-items:center;
  font-family:var(--f-mono);
  font-size:.5rem;
  letter-spacing:.1em;
  text-transform:uppercase;
  padding:3px 8px;
  border-radius:100px;
  border:1px solid transparent;
}

/* Non vérifié → ambre. Le « pas encore » de la charte. */
.badge-verif.is-none{
  color:#E4B24A;
  border-color:rgba(228,178,74,.35);
  background:rgba(228,178,74,.10);
}

/* Vérifié → le lime, qui veut dire vivant dans toute la charte. */
.badge-verif.is-base,
.badge-verif.is-id{
  color:var(--lime);
  border-color:rgba(230,255,0,.35);
  background:rgba(230,255,0,.08);
}

/* Suspendu ou banni → Danger. */
.badge-statut.is-suspended,
.badge-statut.is-banned{
  color:#FF6B5E;
  border-color:rgba(255,107,94,.4);
  background:rgba(255,107,94,.12);
}
