/* ============================================================================
   SAWAKONEKT — HABILLAGE DES ÉCRANS DE RÔLE.  T7, 2026-09-01.

   DA SAWAKONEKT, PAS LA DA COCKPIT. Safou · teal · Sora (titres) + Inter (texte) —
   les valeurs se lisent aux tokens `--safou`, `--teal`, `--f-t`, `--f-b` d'app.css,
   et ne sont pas recopiées ici : une couleur citée survit au retrait de sa source. Aucune valeur n'est écrite ici : tout passe par les tokens de
   `app.css`, qui porte déjà cette charte AVEC ses rangs de contraste calculés
   (--encre-safou tient sur tout le domaine clair, --line-fort satisfait 1.4.11).
   Réécrire un hex ici ouvrirait une seconde vérité de couleur — le mode d'échec
   que ce dépôt a déjà payé ailleurs. Un seul fichier décide, celui-ci s'en sert.

   La DA « cockpit » (VOID/ABYSS/IRON, Newsreader/Spectral) appartient à Helix et
   aux tableaux de bord du Régent. Elle n'a rien à faire dans le produit : ce sont
   deux publics, deux promesses, et les mélanger ferait passer une place de marché
   ouest-africaine pour un terminal de renseignement.
   ============================================================================ */
.ecran{max-width:820px;margin:0 auto;padding:20px 16px 76px;display:flex;flex-direction:column;gap:16px}
@media (min-width:640px){ .ecran{padding:34px 24px 92px;gap:20px} }

.entete{display:flex;flex-direction:column;gap:8px}
.entete h1{margin:0;font-family:var(--f-t);font-size:1.55rem;line-height:1.16;color:var(--ink);letter-spacing:-.01em}
@media (min-width:640px){ .entete h1{font-size:2rem} }
.entete p{margin:0;font-size:.95rem;color:var(--ink-soft);line-height:1.55;max-width:62ch}
.jeton{display:inline-flex;align-items:center;align-self:flex-start;gap:7px;font-size:.75rem;font-weight:700;
       letter-spacing:.08em;text-transform:uppercase;padding:5px 12px;border-radius:99px;
       background:var(--teal-wash);color:var(--teal-700);border:1.5px solid var(--teal-700)}
/* `--safou-wash` EXISTE dans app.css et il est calculé pour porter
   --encre-safou. J'avais écrit un `rgba(255,107,53,.12)` à la place — un lavis
   FABRIQUÉ, dans le fichier dont l'en-tête promet qu'aucune valeur n'y est
   écrite. Deux fautes en une : une seconde vérité de couleur, et une opacité
   employée comme atténuation, qui laisse le contraste dépendre du fond situé
   dessous au lieu de le fixer. */
.jeton[data-ton="safou"]{background:var(--safou-wash);color:var(--encre-safou);border-color:var(--encre-safou)}
.jeton[data-inconnu]{background:var(--rouge-wash);color:var(--encre-err);border-color:var(--encre-err);border-style:dashed}

.bloc{background:var(--surface);border:1px solid var(--line-carte);border-radius:var(--radius-lg);
      padding:18px 16px;display:flex;flex-direction:column;gap:12px}
.bloc__quoi{font-size:.73rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--encre-neutre)}
.bloc h2{margin:0;font-family:var(--f-t);font-size:1.08rem;font-weight:700;color:var(--ink)}
.ligne{font-size:.9rem;color:var(--ink-soft);line-height:1.58;margin:0}
.ligne b{color:var(--ink)}

.champ{display:flex;flex-direction:column;gap:6px}
.champ label{font-size:.86rem;font-weight:600;color:var(--ink)}
.champ input,.champ select,.champ textarea{width:100%;min-height:48px;padding:12px 13px;border-radius:var(--radius-sm);
  font-family:var(--f-b);font-size:1rem;color:var(--ink);background:var(--surface);border:1.5px solid var(--line-fort)}
.champ textarea{min-height:120px;resize:vertical;line-height:1.5}
.champ input:focus-visible,.champ select:focus-visible,.champ textarea:focus-visible{
  outline:2px solid var(--teal-700);outline-offset:1px;border-color:var(--teal-700)}
.aide{font-size:.83rem;color:var(--encre-neutre);line-height:1.5;margin:2px 0 0}

.bouton{min-height:48px;padding:13px 20px;border-radius:var(--radius-sm);font-family:var(--f-b);
        font-size:1rem;font-weight:700;cursor:pointer;background:var(--safou);color:var(--ink);
        border:1.5px solid var(--safou-600)}
.bouton:hover{background:var(--safou-600)}
.bouton:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
.bouton[disabled]{cursor:progress;opacity:.72}
.bouton--calme{background:var(--sable);color:var(--ink);border-color:var(--line-fort)}
.bouton--calme:hover{background:var(--sable);border-color:var(--teal-700)}

/* ── LES TROIS ÉTATS D'UN MESSAGE, ET ILS SE DISTINGUENT SANS LA COULEUR ────
   Trois encres ET trois formes de bord : un lecteur pressé lit la forme, un
   daltonien lit les deux. Le trait plein dit « abouti », le tireté « en attente »,
   le plein rouge « refusé » — jamais la seule teinte. */
.dit{font-size:.9rem;line-height:1.6;padding:14px 15px;border-radius:var(--radius-lg);display:none}
.dit[data-etat]{display:block}
.dit[data-etat="ok"]{background:var(--teal-wash);border:1.5px solid var(--teal-700);color:var(--teal-700)}
.dit[data-etat="attente"]{background:var(--gold-wash);border:1.5px dashed var(--encre-warn);color:var(--encre-warn)}
.dit[data-etat="refus"]{background:var(--rouge-wash);border:1.5px solid var(--encre-err);color:var(--encre-err)}
.dit b{font-weight:700}

.grille{display:grid;grid-template-columns:1fr;gap:12px}
@media (min-width:560px){ .grille{grid-template-columns:1fr 1fr} }

.carte{display:flex;flex-direction:column;gap:8px;background:var(--surface);border:1px solid var(--line-carte);
       border-left:5px solid var(--teal-700);border-radius:var(--radius-lg);padding:16px;text-decoration:none}
.carte[data-ton="safou"]{border-left-color:var(--safou)}
.carte__haut{display:flex;gap:9px;align-items:baseline;flex-wrap:wrap;justify-content:space-between}
.carte__nom{font-family:var(--f-t);font-size:1.04rem;font-weight:700;color:var(--ink)}
.carte__chiffre{font-family:var(--f-t);font-size:1.9rem;font-weight:700;color:var(--ink);
                font-variant-numeric:tabular-nums;line-height:1}

/* Un état vient de l'ATTRIBUT, jamais d'un texte posé à côté : un rendu ne peut pas
   inscrire « livré » sur une ligne que la base a marquée « en cours ». Et un état
   NON DÉCLARÉ se peint en rouge et se nomme — il ne se tait pas, il ne prend pas
   par défaut la valeur la plus flatteuse. */
/* ── UN ÉTAT SE PEINT DEPUIS SON ATTRIBUT, ET L'INCONNU SE VOIT ────────────
   DÉFAUT MESURÉ le 2026-09-01 : mes sélecteurs portaient `installe` et `occupied`.
   Les vraies valeurs de la base sont ACCENTUÉES et françaises — `installé`,
   `occupé`, `libre`, `potentiel`, `hors_service` — tandis que `parcels.status`
   est en anglais (`deposited`, `collected`…). Deux conventions coexistent dans le
   même schéma, et j'avais deviné la mauvaise pour la moitié.

   LA STRUCTURE EST INVERSÉE POUR QUE L'ERREUR SE VOIE. Avant, une valeur non
   prévue ne déclenchait AUCUNE règle : la pastille sortait sans fond ni bord,
   c'est-à-dire indistinguable d'un oubli de style. Désormais le défaut de `.etat`
   EST l'alerte, et seules les valeurs connues l'éteignent. Une valeur nouvelle
   apparaît donc en rouge — bruyante, datée, imputable — au lieu de se fondre.
   Même principe que la RLS : ne pas déclarer ne doit jamais être plus permissif
   que déclarer. */
.etat{font-size:.74rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;padding:3px 10px;
      border-radius:99px;white-space:nowrap;
      background:var(--rouge-wash);color:var(--encre-err);border:1.5px solid var(--encre-err)}
.etat:not([data-etat])::before{content:"état non déclaré"}
.etat[data-etat=""]::after{content:" — valeur vide"}

/* ATTENTE — le trait tireté dit « pas encore », sans dépendre de la teinte. */
.etat[data-etat="potentiel"],
.etat[data-etat="libre"],
.etat[data-etat="ouvert"],
.etat[data-etat="attente"],
.etat[data-etat="awaiting_pickup"]{
  background:var(--gold-wash);color:var(--encre-warn);border:1.5px dashed var(--encre-warn)}

/* EN COURS — trait plein teal : quelque chose est en service. */
.etat[data-etat="actif"],
.etat[data-etat="installé"],
.etat[data-etat="occupé"],
.etat[data-etat="en_cours"],
.etat[data-etat="deposited"]{
  background:var(--teal-wash);color:var(--teal-700);border:1.5px solid var(--teal-700)}

/* CLOS — sable neutre : l'affaire est terminée, elle n'appelle plus de geste. */
.etat[data-etat="livre"],
.etat[data-etat="collected"],
.etat[data-etat="returned"],
.etat[data-etat="expired"],
.etat[data-etat="clos"],
.etat[data-etat="resolu"]{
  background:var(--sable);color:var(--encre-neutre);border:1.5px solid var(--line-fort)}

/* PANNE — rouge assumé, distinct du rouge « inconnu » par son libellé, pas par sa
   couleur : ici l'état EST déclaré, et il est mauvais. */
.etat[data-etat="hors_service"]{
  background:var(--rouge-wash);color:var(--encre-err);border:1.5px solid var(--encre-err)}

/* ── LES PIÈCES ────────────────────────────────────────────────────────────── */
.piece{display:flex;flex-direction:column;gap:7px;padding:14px;border-radius:var(--radius-lg);
       background:var(--sable);border:1.5px dashed var(--line-fort)}
.piece[data-verdict="ok"]{border-style:solid;border-color:var(--teal-700);background:var(--teal-wash)}
.piece[data-verdict="refus"]{border-style:solid;border-color:var(--encre-err);background:var(--rouge-wash)}
.piece__nom{font-weight:700;font-size:.92rem;color:var(--ink)}
.piece__pourquoi{font-size:.85rem;color:var(--encre-neutre);line-height:1.5}
.piece__requis{font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--encre-warn)}
.piece input[type=file]{font-family:var(--f-b);font-size:.88rem;color:var(--ink);min-height:44px}
.piece__verdict{font-size:.85rem;line-height:1.5}

.liens{display:flex;flex-wrap:wrap;gap:9px;padding-top:4px}
.liens a{min-height:44px;display:inline-flex;align-items:center;padding:9px 15px;border-radius:var(--radius-sm);
         font-size:.9rem;font-weight:700;text-decoration:none;color:var(--ink);background:var(--sable);
         border:1.5px solid var(--line-fort)}
.liens a:hover{border-color:var(--teal-700)}
.liens a[data-primaire]{background:var(--safou);border-color:var(--safou-600)}

.bascule{display:flex;align-items:center;gap:12px;justify-content:space-between}
.bascule__etat{font-family:var(--f-t);font-weight:700;font-size:1.05rem;color:var(--ink)}

/* Détail technique d'un refus — replié par défaut.
   L'article « refus ≠ absence » exige que la RAISON soit rendue ; il n'exige pas
   qu'elle soit criée au client. Le sqlstate, la table et le message du serveur
   sont ici, atteignables en un geste par qui répare, invisibles pour qui attend
   sa commande. Un refus reste DÉCLARÉ — il cesse d'être un rapport d'incident. */
.dit__tech{margin-top:8px;font-size:.82rem}
.dit__tech summary{cursor:pointer;color:var(--encre-neutre);min-height:24px;
  display:inline-flex;align-items:center}
.dit__tech code{font-family:ui-monospace,monospace;font-size:.8rem}
