/* =========================================================================
   Magda Platform · back-office EXS.
   Direction artistique appliquee le 25/08/2026 :
   « Un outil, pas un site » (exs-plataforma-direction, EXS, 25/08/2026),
   version claire du systeme de l'app membre « La plaque, pas la tuile ».

   CSS ecrit a la main, proprietes personnalisees, aucune dependance, aucune
   etape de build, aucun appel reseau sortant. Polices vendorisees sous
   /static/fonts/ (SOURCES.md, empreintes verifiees par
   tests/test_fonts_vendored.py).

   Trois regles de la direction, elles decident du reste :
   01  le titre n'est pas le contenu : l'identite passe dans l'onglet actif
       et un repere en mono, la premiere chose lisible est le chiffre ou la
       ligne a traiter ;
   02  un etat n'est jamais une action : l'etat vit dans sa colonne, en mono
       avec un carre de couleur, l'action reste a droite ;
   03  la lecture seule se voit : ce qui vient de l'OVG porte trame et filet
       ocre, sans paragraphe d'explication.

   Une couleur par sens : moss = confirme, ocre = en attente ou sous-rempli,
   rouge = refus. Le bleu a disparu, il ne voulait rien dire ; l'action est
   noire sur papier.
   ========================================================================= */

/* --- Polices vendorisees --------------------------------------------------
   Archivo porte le texte ET l'affichage (la DA n'a qu'une famille de texte),
   Archivo Expanded porte les grands chiffres (la DA demande wdth 110-114 :
   la build variable n'existe qu'en ttf, les coupes Expanded statiques font
   le meme travail), Azeret Mono porte les reperes, etats, codes et meta.   */

@font-face {
  font-family: "Archivo";
  src: url("/static/fonts/archivo/Archivo-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Archivo";
  src: url("/static/fonts/archivo/Archivo-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Archivo";
  src: url("/static/fonts/archivo/Archivo-SemiBold.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Archivo Expanded";
  src: url("/static/fonts/archivo/ArchivoExpanded-SemiBold.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Archivo Expanded";
  src: url("/static/fonts/archivo/ArchivoExpanded-Bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Azeret Mono";
  src: url("/static/fonts/azeret-mono/AzeretMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Azeret Mono";
  src: url("/static/fonts/azeret-mono/AzeretMono-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* --- Jetons ---------------------------------------------------------------
   Palette de la direction : 6 valeurs, 3 sens. Les anciens noms (cal, ferro,
   cobalto, oxido, grafite, branco) restent definis comme ALIAS vers les
   nouveaux : les sections d'ecran non encore migrees les lisent toujours, et
   le bleu y devient l'encre, comme la DA l'exige.                            */

:root {
  --paper: #e9eae6;      /* fond, gris tiede, ni creme ni blanc */
  --paper-2: #f2f2ef;    /* survol de ligne, tiroir, surface de saisie */
  --ink: #151917;        /* texte, bouton primaire : le noir porte l'action */
  --ink-2: #3e453f;
  --muted: #6e756f;
  --line: #c9cdc6;       /* filet structurel */
  --line-2: #dcdfd8;     /* filet de ligne de tableau */

  --moss: #2e5e4c;       /* confirme, envoye, present */
  --moss-tint: #dce5df;
  --ochre: #8a6512;      /* en attente, sous-rempli, lecture seule */
  --ochre-tint: #efe7d2;
  /* L'ocre de la DA fait 4,39:1 sur papier : bon pour un filet (3:1), pas
     pour du texte a 11 px (4,5:1). Le texte ocre prend ce ton profond,
     6,06:1, meme teinte. */
  --ochre-deep: #6f510e;
  --red: #9e3227;        /* refus, annulation, dormant critique */
  --red-tint: #efdcd8;

  /* Alias de compatibilite, sections non migrees. Le bleu (ex-cobalto)
     devient l'encre : l'action est noire, la confirmation est moss, et les
     classes a semantique « ok » sont re-ciblees plus bas. */
  --cal: var(--paper);
  --branco: var(--paper-2);
  --ferro: var(--ink);
  --grafite: var(--ink-2);
  --cobalto: var(--ink);
  --oxido: var(--red);
  --brand-accent: var(--ink);

  --dev-amarelo: #f5c400; /* hors palette produit, bandeau de chantier */

  /* Echelle d'espacement conservee. */
  --e1: 4px;
  --e2: 8px;
  --e3: 12px;
  --e4: 16px;
  --e5: 24px;
  --e6: 32px;
  --e7: 48px;
  --e8: 64px;

  --face-display: "Archivo", "Segoe UI", Arial, sans-serif;
  --face-texte: "Archivo", "Segoe UI", Arial, sans-serif;
  --face-wide: "Archivo Expanded", "Archivo", "Segoe UI", Arial, sans-serif;
  --face-mono: "Azeret Mono", ui-monospace, Consolas, monospace;

  /* Rayon de la DA : 2 px partout ou il y a un rayon. */
  --raio: 2px;

  /* Cible tactile minimale, usage debout a l'accueil. */
  --alvo: 44px;

  --largura-max: 1240px;
}

/* --- Socle ---------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  font-size: 100%;
}

/* `min-height: 100vh` + `flex-direction: column`, `.app-main` en `flex: 1` :
   sur un ecran court en contenu (ecran de connexion), la barre d'etat
   (.statusbar) reste ancree en bas de la fenetre au lieu de flotter au
   milieu, juste sous le contenu, avec un vide en dessous. Sur un ecran
   long, rien ne change : `.app-main` grandit deja plus que necessaire. */
body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--cal);
  color: var(--ferro);
  font-family: var(--face-texte);
  font-size: 0.9375rem; /* 15px : la direction est dense, le socle suit */
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}

h1,
h2,
h3 {
  font-family: var(--face-display);
  font-weight: 600;
  margin: 0;
}

/* Regle 01 de la direction : le titre n'est pas le contenu. Le H1 n'est
   plus un grand titre, c'est un repere de section : mono, petit, en
   capitales, ferme par un filet encre. La premiere chose lisible de l'ecran
   redevient le chiffre ou la ligne a traiter. La hierarchie HTML ne bouge
   pas, seul le costume change. */

h1 {
  font-family: var(--face-mono);
  font-weight: 500;
  font-size: 0.6875rem; /* 11px */
  line-height: 1.4;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-2);
  padding-bottom: var(--e2);
  border-bottom: 1px solid var(--ink);
}

/* Repere secondaire : meme registre, filet plus leger. */

h2 {
  font-family: var(--face-mono);
  font-weight: 500;
  font-size: 0.6875rem; /* 11px */
  line-height: 1.4;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-2);
  padding-bottom: var(--e2);
  border-bottom: 1px solid var(--line);
  margin-top: var(--e6);
}

p {
  margin: 0;
}

.lead {
  color: var(--grafite);
  max-width: 62ch;
  margin: var(--e2) 0 0;
}

/* DA EXS 25/08 (.guard) : une mise en garde porte le filet ocre de
   l'attente, jamais un aplat. Le mot la porte aussi, pas la couleur seule. */

.hint {
  border-left: 2px solid var(--ochre);
  padding: var(--e2) 0 var(--e2) var(--e3);
  color: var(--grafite);
  font-size: 0.8125rem; /* 13px */
  line-height: 1.5;
  max-width: 62ch;
}

code {
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.875em;
  color: var(--grafite);
}

/* --- Liens et focus -------------------------------------------------------
   Anneau 2 px Cobalto decale de 2 px sur TOUT element actionnable, blocs de
   seance compris. Jamais d'outline supprimee sans remplacante.              */

a {
  color: var(--cobalto);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}

/* Correction P0 C4. Ce garde-fou existe pour empecher le violet par defaut des
   navigateurs sur un lien deja visite. Ecrit `a:visited`, il pesait plus lourd
   (0,1,1) qu'une classe de composant (0,1,0) et gagnait donc partout : un bloc
   de seance deja consulte passait de Cal sur Ferro a Cobalto sur Ferro, deux
   couleurs sombres, et devenait illisible.

   `:where()` a une specificite NULLE : la regle continue de remplacer le violet
   sur un lien ordinaire, et cede devant n'importe quelle regle de composant.
   Corrige la classe entiere du defaut, pas seulement les blocs de seance. */

:where(a:visited) {
  color: var(--cobalto);
}

/* Ceinture et bretelles sur les blocs de seance, qui sont le cas ou le defaut
   se voyait : leur couleur ne depend d'aucun etat de visite. Depuis la grille
   de la direction EXS (25/08), un bloc est une plaque paper-2 a texte encre,
   plus un aplat encre a texte papier. */

a.bloco__corpo,
a.bloco__corpo:visited,
.bloco__accionavel > summary:visited {
  color: var(--ferro);
}

a:hover {
  text-decoration-thickness: 2px;
}

:focus-visible {
  outline: 2px solid var(--cobalto);
  outline-offset: 2px;
  border-radius: var(--raio);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ferro);
  color: var(--cal);
  padding: var(--e3) var(--e4);
  z-index: 10;
}

.skip-link:focus {
  left: var(--e4);
  top: var(--e2);
}

/* --- Bandeau de developpement --------------------------------------------
   Ce n'est pas le produit. Pleine largeur, police systeme, jaune de chantier,
   pose AU-DESSUS de l'en-tete et non dedans : un outil pose sur l'ecran.
   Ferro sur jaune signal, 9,30:1.                                           */

.dev-actor {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e3);
  padding: var(--e2) var(--e4);
  background: var(--dev-amarelo);
  color: var(--ferro);
  font-family: system-ui, sans-serif;
  font-size: 0.8125rem;
  border-bottom: 2px solid var(--ferro);
}

.dev-actor__badge {
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.dev-actor label {
  font-family: system-ui, sans-serif;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: normal;
  text-transform: none;
  color: var(--ferro);
  margin-bottom: 0;
}

.dev-actor__empty {
  font-weight: 400;
}

.dev-actor select {
  font-family: system-ui, sans-serif;
  font-size: 0.8125rem;
  padding: var(--e1) var(--e2);
  border: 1px solid var(--ferro);
  background: var(--branco);
  color: var(--ferro);
}

.dev-actor .btn {
  min-height: auto;
  padding: var(--e1) var(--e3);
  font-family: system-ui, sans-serif;
  font-size: 0.8125rem;
  /* Hors palette produit, comme le reste du bandeau : le bleu d'action
     appartient a l'interface, pas a l'outil de chantier pose dessus. */
  color: var(--ferro);
  background: var(--branco);
  border-color: var(--ferro);
  border-radius: 0;
}

.dev-actor .btn:hover {
  color: var(--branco);
  background: var(--ferro);
  border-color: var(--ferro);
}

/* --- En-tete --------------------------------------------------------------
   Le nom du studio est l'identite principale. "Magda Platform" est secondaire.
   C'est l'inverse de l'ecran d'avant, et c'est ce qui rend la revente possible
   sans refonte.                                                             */

.app-header {
  border-bottom: 1px solid var(--ferro);
  background: var(--cal);
}

.app-header__row {
  max-width: var(--largura-max);
  margin: 0 auto;
  padding: var(--e3) var(--e5);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--e5);
}

/* Lot P4 : en-tete en DEUX rangees (neuf ecrans depassent la largeur d'une
   seule rangee partagee avec le bloc identite a 1366 px comme a 1024 px).
   Rangee 1 : logo + organisation a gauche, identite a droite (regle
   inchangee de .app-header__row). Rangee 2 : la nav des ecrans seule,
   alignee a gauche, separee par le filet qui portait deja le bas de
   .app-header. */
.app-header__row--nav {
  justify-content: flex-start;
  padding-top: var(--e2);
  padding-bottom: var(--e2);
  border-top: 1px solid var(--line);
}

.app-header__identity {
  display: flex;
  align-items: center;
  gap: var(--e3);
  min-width: 0;
}

/* Logo de l'operateur. Aplat encre, jamais le metal brosse d'origine : il
   lirait a peine sur Cal et jurerait avec le socle plat. La marque garde sa
   lettre, elle prend l'encre du produit. */

.app-header__logo {
  height: 34px;
  width: auto;
  flex: 0 0 auto;
  display: block;
}

/* Filet identitaire : separe le logo de l'operateur du nom de
   l'organisation. Un filet de structure, plus une couleur de marque. */

.app-header__rule {
  flex: 0 0 auto;
  width: 1px;
  align-self: stretch;
  min-height: 32px;
  background: var(--line);
}

.app-header__names {
  min-width: 0;
}

.app-header__orgname {
  display: flex;
  align-items: center;
  min-width: 0;
}

.app-header__brand {
  display: inline;
  font-family: var(--face-display);
  font-weight: 600;
  font-size: 0.9375rem; /* 15px */
  line-height: 1.2;
  letter-spacing: -0.015em;
  color: var(--ferro);
  overflow-wrap: anywhere;
  margin: 0;
}

/* Ecrans. L'actif se dit par la graisse et l'encre, jamais par un
   soulignement d'onglet, qui est le tic le plus repandu du gabarit SaaS. */

.app-header__screens {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
}

.app-header__screen {
  font-family: var(--face-mono);
  font-weight: 500;
  font-size: 0.6875rem; /* 11px */
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
  text-decoration: none;
  padding: var(--e2) var(--e3);
  border: 1px solid transparent;
  border-radius: var(--raio);
  min-height: var(--alvo);
  display: inline-flex;
  align-items: center;
}

.app-header__screen:hover {
  color: var(--ink);
}

.app-header__screen--active {
  color: var(--ink);
  border-color: var(--line);
  background: var(--paper-2);
}

/* Selecteur d'organisation : l'identite EST le bouton (DA .orgbtn). Un
   `details` natif, aucun JavaScript ; le menu se pose au-dessus de la page
   sans la pousser. */

.app-header__orgbtn {
  position: relative;
  min-width: 0;
}

.app-header__orgbtn > summary {
  list-style: none;
  cursor: pointer;
  display: block;
  min-height: var(--alvo);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
}

.app-header__orgbtn > summary::-webkit-details-marker {
  display: none;
}

.app-header__orglabel {
  display: block;
  font-family: var(--face-mono);
  font-size: 0.5625rem; /* 9px */
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.app-header__caret {
  font-style: normal;
  font-size: 0.5625rem;
  color: var(--ink-2);
  margin-left: var(--e2);
}

.app-header__orgmenu {
  position: absolute;
  left: 0;
  top: calc(100% + var(--e1));
  z-index: 20;
  min-width: 260px;
  background: var(--paper);
  border: 1px solid var(--ink);
  padding: var(--e1) 0;
  display: flex;
  flex-direction: column;
}

.app-header__org {
  color: var(--ink-2);
  text-decoration: none;
  padding: var(--e2) var(--e4);
  min-height: var(--alvo);
  display: inline-flex;
  align-items: center;
}

.app-header__org:hover {
  color: var(--ink);
  background: var(--paper-2);
}

.app-header__org--active {
  color: var(--ink);
  font-weight: 600;
}

/* Bloc identite (chantier "chaque personne a des droits differents") : qui
   est connecte, a droite de la barre. Le nom porte la graisse du produit
   (meme famille que .app-header__brand), le role reste une etiquette
   discrete dessous -- meme registre que .app-header__orglabel, jamais une
   pilule ni un fond colore. */

.app-header__identidade {
  display: flex;
  align-items: center;
  gap: var(--e3);
}

.app-header__identidade-texto {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  text-align: right;
}

.app-header__identidade-nome {
  font-family: var(--face-display);
  font-weight: 600;
  font-size: 0.8125rem;
  line-height: 1.2;
  color: var(--ink);
}

.app-header__identidade-papel {
  font-family: var(--face-mono);
  font-size: 0.625rem; /* 10px */
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-2);
}

/* Barre d'etat (DA .statusbar) : l'identite du produit vit ici, plus dans
   l'en-tete. Rien d'invente : produit a gauche, ambiente a droite. */

.statusbar {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--e2) var(--e4);
  border-top: 1px solid var(--line);
  padding: var(--e2) var(--e5);
  margin: 0;
  font-family: var(--face-mono);
  font-size: 0.625rem; /* 10px */
  letter-spacing: 0.06em;
  color: var(--ink-2);
}

/* --- Corps ---------------------------------------------------------------- */

.app-main {
  max-width: var(--largura-max);
  margin: 0 auto;
  padding: var(--e5) var(--e5) var(--e8);
  flex: 1 0 auto;
  width: 100%;
}

/* --- Messages -------------------------------------------------------------
   Un filet epais a gauche, jamais un aplat colore sur toute la surface : le
   message se signale, il ne crie pas.                                       */

.flash-wrap {
  max-width: var(--largura-max);
  margin: 0 auto;
  padding: var(--e5) var(--e5) 0;
}

.flash {
  border-left: 4px solid var(--grafite);
  padding: var(--e3) var(--e4);
  margin: 0;
  background: var(--branco);
}

.flash--success {
  border-left-color: var(--moss);
  background: var(--moss-tint);
}

.flash--error {
  border-left-color: var(--red);
  color: var(--red);
  background: var(--red-tint);
}

.flash--info {
  border-left-color: var(--grafite);
}

.readonly-banner {
  border-left: 3px solid var(--ochre);
  padding: var(--e3) var(--e4);
  margin: var(--e4) 0 var(--e5);
  color: var(--ink-2);
  background-color: var(--ochre-tint);
  background-image: repeating-linear-gradient(
    45deg,
    transparent,
    transparent 5px,
    rgba(21, 25, 23, 0.05) 5px,
    rgba(21, 25, 23, 0.05) 6px
  );
  max-width: 68ch;
}

/* --- Marque des deux mondes -------------------------------------------
   La plateforme porte deux mondes, l'ambiente de demonstracao et la
   producao en lecture seule : la coherence ne vient pas de les fondre,
   elle vient de les nommer. Discrete et constante, meme registre que
   .status-text, alignee sur la meme gouttiere horizontale que
   .app-header__row pour que la marque s'aligne sur le reste de la page. */

.ambiente {
  margin: 0;
  padding: 4px var(--e5);
  font-family: var(--face-mono);
  font-size: 0.6875rem; /* 11px */
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-align: right;
  border-bottom: 1px solid var(--line-2);
}

.ambiente--demonstracao {
  color: var(--ink-2);
}

.ambiente--producao {
  color: var(--moss);
}

/* Etat de transition : le vrai centre et les organisations de demonstration
   sur le meme serveur. Couleur d'alerte SANS gras ni bordure -- le bandeau
   reste discret, et la phrase porte deja l'information a elle seule (la
   couleur n'est jamais le seul signal, WCAG 1.4.1). */
.ambiente--misto {
  color: var(--oxido);
}

.empty-state {
  color: var(--grafite);
  padding: var(--e5) 0;
  max-width: 62ch;
}

/* --- Decomptes ------------------------------------------------------------ */

.counts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e6);
  margin: var(--e5) 0;
}

.count-card {
  border-left: 2px solid var(--line);
  padding-left: var(--e4);
}

.count-card--rouge {
  border-left-color: var(--oxido);
}

.count-card--laranja {
  border-left-color: var(--ochre);
}

.count-card__label {
  font-family: var(--face-mono);
  font-size: 0.625rem; /* 10px */
  color: var(--ink-2);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.count-card__value {
  font-family: var(--face-wide);
  font-weight: 700;
  font-size: 2.5rem; /* 40px : le chiffre est la premiere chose lisible */
  line-height: 1.06;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  margin-top: var(--e1);
}

.count-card__hint {
  font-size: 0.8125rem;
  color: var(--grafite);
  margin-top: var(--e1);
}

/* --- Tableaux -------------------------------------------------------------
   Les separations se font par l'espace. Un seul filet, sous l'en-tete, parce
   qu'il porte un point de structure et non une grille.                       */

.table-scroll {
  overflow-x: auto;
}

table {
  border-collapse: collapse;
  width: 100%;
}

caption {
  text-align: left;
}

th,
td {
  text-align: left;
  padding: var(--e3) var(--e4) var(--e3) 0;
  vertical-align: baseline;
  /* DA 25/08 : Archivo a des chiffres proportionnels par defaut ; dans un
     tableau, les colonnes de nombres doivent s'empiler. La fonte porte la
     feature tnum, la feuille l'active (verify_d3_render C1/C2). */
  font-variant-numeric: tabular-nums;
}

thead th {
  font-family: var(--face-mono);
  font-weight: 400;
  font-size: 0.6875rem; /* 11px */
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-2);
  border-bottom: 1px solid var(--ferro);
  padding-bottom: var(--e2);
}

tbody th {
  font-weight: 600;
}

tbody tr + tr th,
tbody tr + tr td {
  border-top: 1px solid var(--line-2);
}

tbody tr:hover th,
tbody tr:hover td {
  background: var(--paper-2);
}

/* --- Statuts, sans pastille ----------------------------------------------
   Un carre plein de 8 px, puis le mot. Le carre est un marqueur, pas un
   conteneur : le texte n'est jamais enferme dans une forme. L'information
   n'est jamais portee par la seule couleur, le mot la porte aussi.          */

.badge,
.status-text {
  display: inline-flex;
  align-items: baseline;
  gap: var(--e2);
  font-family: var(--face-mono);
  font-size: 0.6875rem; /* 11px */
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--grafite);
  background: none;
  border: 0;
  border-radius: 0;
  padding: 0;
}

.badge::before,
.status-text::before {
  content: "";
  width: var(--e2);
  height: var(--e2);
  flex: 0 0 auto;
  background: currentColor;
  transform: translateY(-0.05em);
}

.badge--rouge {
  color: var(--oxido);
}

.badge--laranja {
  color: var(--ochre-deep);
}

.badge--verde {
  color: var(--moss);
}

.status-text--ok {
  color: var(--moss);
}

.status-text--draft {
  color: var(--grafite);
}

/* DA EXS 25/08 : l'attente est ocre (rascunho en attente d'approbation). */

.status-text--espera {
  color: var(--ochre-deep);
}

/* --- Boutons et actions ---------------------------------------------------
   Le bouton plein est reserve a l'action qui engage. Tout le reste est un
   lien : l'ecran de retention repetait 51 boutons bleus pleins qui pesaient
   plus lourd que l'information qu'ils accompagnaient.                       */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--alvo);
  padding: var(--e2) var(--e4);
  border: 1px solid transparent;
  border-radius: var(--raio);
  font-family: var(--face-mono);
  font-size: 0.6875rem; /* 11px */
  font-weight: 500;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  line-height: 1.3;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 150ms ease, color 150ms ease;
}

.btn--primary {
  background: var(--ink);
  color: var(--paper);
}

.btn--primary:hover {
  background: #000;
}

.btn--secondary {
  background: none;
  color: var(--ink);
  border-color: var(--line);
}

.btn--secondary:hover {
  border-color: var(--ferro);
  color: var(--ferro);
}

.btn--confirm {
  background: var(--ink);
  color: var(--paper);
}

.btn--confirm:hover {
  background: #000;
}

/* --- Formulaires ---------------------------------------------------------
   Branco signale une surface de saisie, et rien d'autre : ce n'est pas un
   mecanisme de profondeur, le pas Cal/Branco ne vaut que 1,10:1.            */

fieldset {
  border: 0;
  margin: 0;
  padding: 0;
}

legend {
  font-family: var(--face-mono);
  font-weight: 500;
  font-size: 0.6875rem; /* 11px */
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-2);
  padding: 0;
  margin-bottom: var(--e3);
}

label {
  display: inline-block;
  font-family: var(--face-mono);
  font-weight: 500;
  font-size: 0.6875rem; /* 11px */
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin-bottom: var(--e2);
}

select,
textarea,
input[type="text"],
input[type="date"],
input[type="time"],
input[type="number"],
input[type="email"],
input[type="password"] {
  font-family: var(--face-texte);
  font-size: 1rem;
  line-height: 1.5;
  color: var(--ferro);
  background: var(--branco);
  border: 1px solid var(--muted);
  border-radius: var(--raio);
  padding: var(--e2) var(--e3);
  min-height: var(--alvo);
  max-width: 100%;
}

textarea {
  display: block;
  width: 100%;
  min-height: 14rem;
  resize: vertical;
}

textarea:focus-visible {
  outline: 2px solid var(--cobalto);
  outline-offset: 2px;
}

.radio-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e5);
  margin-bottom: var(--e4);
}

.radio-row label {
  display: inline-flex;
  align-items: center;
  gap: var(--e2);
  min-height: var(--alvo);
  margin-bottom: 0;
  font-family: var(--face-texte);
  font-size: 0.9375rem;
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
  color: var(--ferro);
  cursor: pointer;
}

.radio-row input[type="radio"] {
  width: var(--e4);
  height: var(--e4);
  accent-color: var(--ink);
}

/* --- Fiches et citations -------------------------------------------------- */

.member-facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e5) var(--e6);
  margin: var(--e4) 0 var(--e5);
}

.member-facts dt {
  font-family: var(--face-mono);
  font-size: 0.625rem; /* 10px */
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.member-facts dd {
  margin: var(--e1) 0 0;
  font-weight: 600;
}

/* Le message est cite, jamais enferme dans une boite. */

.body-preview {
  border-left: 3px solid var(--grafite);
  padding-left: var(--e4);
  margin: var(--e4) 0 var(--e5);
  max-width: 62ch;
}

.body-preview p + p {
  margin-top: var(--e3);
}

/* --- Barre de commandes de l'agenda (DA .agbar) ---------------------------
   Unites a gauche, vue / date / navigation a droite, un filet encre dessous.
   Un segment est du meme registre qu'un onglet : mono, capitales, l'actif
   porte cadre et fond.                                                      */

.agbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--e3) var(--e5);
  margin: var(--e4) 0 0;
  padding-bottom: var(--e3);
  border-bottom: 1px solid var(--ink);
}

.segs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px;
}

.seg {
  font-family: var(--face-mono);
  font-weight: 500;
  font-size: 0.65625rem; /* 10.5px */
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-2);
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: var(--raio);
  padding: var(--e2) var(--e3);
  min-height: var(--alvo);
  display: inline-flex;
  align-items: center;
  gap: var(--e2);
  background: none;
}

.seg:hover {
  color: var(--ink);
}

.seg[aria-current="page"] {
  color: var(--ink);
  border-color: var(--line);
  background: var(--paper-2);
}

/* Sous-etiquette d'un segment d'unite : OVG · leitura ou plataforma. */

.seg em {
  font-style: normal;
  font-size: 0.5625rem; /* 9px */
  letter-spacing: 0.1em;
  color: var(--grafite);
}

.agnav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e2) var(--e3);
}

.agdate {
  font-family: var(--face-mono);
  font-size: 0.6875rem; /* 11px */
  letter-spacing: 0.1em;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  margin: 0;
}

/* --- Deplacement de seance ------------------------------------------------ */

.coach-move summary {
  cursor: pointer;
  color: var(--cobalto);
  min-height: var(--alvo);
  display: inline-flex;
  align-items: center;
}

.coach-move summary::-webkit-details-marker {
  display: none;
}

.coach-move__form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--e3);
  margin-top: var(--e3);
}

.coach-move__form label {
  display: block;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--grafite);
  font-weight: 600;
}

.coach-move__form input {
  display: block;
}

/* =========================================================================
   La grille d'agenda (DA .ag) : les heures vides se replient.

   Une rangee par heure OCCUPEE ; entre deux heures occupees, une bande
   hachuree dit combien de temps elle couvre. La journee entiere tient sans
   defilement, et le vide reste une information : la bande le nomme.

   Le taux de remplissage est un filet de 2 px sous chaque bloc, lisible en
   diagonale ; le compteur passe en ocre sous 50 %, ce qui donne la lecture
   de la semaine en une seconde : ou sont les places a vendre. L'unite en
   lecture OVG porte le pointille, double par le bandeau en tete d'ecran :
   aucune information n'est portee par la seule couleur.
   ========================================================================= */

.ag {
  --ag-dias: 7;
  margin: var(--e4) 0 var(--e7);
}

.ag--day {
  --ag-dias: 1;
}

.aghead {
  display: grid;
  grid-template-columns: 58px repeat(var(--ag-dias), minmax(0, 1fr));
  border-bottom: 1px solid var(--line);
}

.aghead > div {
  padding: var(--e3) var(--e2);
  font-family: var(--face-mono);
  font-size: 0.625rem; /* 10px */
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.aghead > .aghead__hoje {
  color: var(--ink);
  border-bottom: 2px solid var(--ink);
  margin-bottom: -1px;
}

.aghead b {
  display: block;
  font-family: var(--face-texte);
  font-weight: 600;
  font-size: 0.9375rem; /* 15px */
  letter-spacing: -0.01em;
  color: var(--ferro);
  margin-top: 3px;
  font-variant-numeric: tabular-nums;
}

.agrow {
  display: grid;
  grid-template-columns: 58px repeat(var(--ag-dias), minmax(0, 1fr));
  border-bottom: 1px solid var(--line-2);
  min-height: 62px;
}

.agrow--salto {
  display: block;
  min-height: 0;
}

.agtime {
  font-family: var(--face-mono);
  font-size: 0.625rem; /* 10px */
  color: var(--ink-2);
  padding: var(--e2) var(--e2) 0 0;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.agcell {
  border-left: 1px solid var(--line-2);
  padding: 6px;
  min-width: 0;
}

.agcell__sessoes {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--e2);
}

/* Le pli : la bande dit exactement le temps qu'elle couvre. */

.salto {
  margin: 0;
  padding: 7px var(--e2) 7px 58px;
  font-family: var(--face-mono);
  font-size: 0.625rem; /* 10px */
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
  background: repeating-linear-gradient(
    45deg,
    transparent,
    transparent 5px,
    rgba(21, 25, 23, 0.03) 5px,
    rgba(21, 25, 23, 0.03) 6px
  );
}

/* --- Un bloc, une seance (DA .blk) ---------------------------------------
   Une plaque paper-2 cadree line, texte encre. Le contour pointille est le
   code de la lecture seule OVG. Le filet de 2 px porte le remplissage.     */

.bloco {
  position: relative;
  min-width: 0;
}

.bloco__corpo {
  display: block;
  padding: 7px var(--e2);
  background: var(--paper-2);
  color: var(--ferro);
  border: 1px solid var(--line);
  border-radius: var(--raio);
  text-decoration: none;
  min-height: var(--alvo);
  transition: border-color 150ms ease;
}

a.bloco__corpo:hover,
.bloco__accionavel > summary.bloco__corpo:hover {
  border-color: var(--ink);
}

.bloco--leitura .bloco__corpo {
  border-style: dashed;
  background: transparent;
}

.bloco__linha {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--e2);
  min-width: 0;
  font-family: var(--face-mono);
  font-size: 0.65625rem; /* 10.5px */
  letter-spacing: 0.04em;
  color: var(--ink-2);
}

.bloco__hora,
.bloco__ocupacao {
  flex: 0 0 auto;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.bloco__ocupacao {
  font-weight: 500;
  color: var(--ferro);
}

.bloco__nome {
  display: block;
  font-size: 0.8125rem; /* 13px */
  font-weight: 500;
  letter-spacing: -0.01em;
  margin: 4px 0 6px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bloco__barra {
  display: block;
  height: 2px;
  background: var(--line);
}

.bloco__barra i {
  display: block;
  height: 2px;
  background: var(--ink);
}

/* Sous 50 % : le compteur ET le filet passent en ocre, le mot reste. */

.bloco--baixa .bloco__ocupacao {
  color: var(--ochre-deep);
}

.bloco--baixa .bloco__barra i {
  background: var(--ochre);
}

/* Annulee : l'etat remplace le compteur, en rouge, et il n'y a pas de
   filet de remplissage a promettre. */

.bloco__estado {
  font-family: var(--face-mono);
  font-size: 0.625rem; /* 10px */
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--red);
}


/* --- Espace coach ---------------------------------------------------------
   Les actions d'une seance pendent sous son bloc, dans un panneau `details`
   natif, sans une ligne de JavaScript. Depuis la grille de la direction, le
   panneau n'est plus en position absolue : la rangee de la grille grandit
   pour le loger, rien ne se recouvre.
   ------------------------------------------------------------------------- */

.bloco__accionavel > summary {
  cursor: pointer;
  list-style: none;
}

.bloco__accionavel > summary::-webkit-details-marker,
.bloco__accionavel > summary::marker {
  display: none;
  content: "";
}

.bloco__accao-marca {
  display: block;
  margin-top: var(--e2);
  font-family: var(--face-mono);
  font-size: 0.625rem; /* 10px */
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.bloco__painel {
  margin-top: var(--e2);
  padding: var(--e4);
  background: var(--paper);
  border: 1px solid var(--ferro);
  border-radius: var(--raio);
  color: var(--ferro);
}

.bloco__cancelar {
  display: inline-block;
  margin-top: var(--e4);
  color: var(--oxido);
  min-height: var(--alvo);
  line-height: var(--alvo);
}

.coach-move__form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--e3);
}

.coach-move__form label {
  display: block;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--grafite);
  font-weight: 600;
}

/* L'indicateur d'occupation vit dans la barre de commandes : c'est un chiffre
   de lecture, pas un titre. */

.count-card--ocupacao {
  border-left: 3px solid var(--cobalto);
  padding-left: var(--e3);
  max-width: 22rem;
}

.count-card--ocupacao .count-card__value {
  font-size: 1.25rem;
}

.count-card--ocupacao .count-card__hint {
  font-size: 0.75rem;
}

/* --- Painel (lot P4) -------------------------------------------------------
   Memes count-card que la retention (reutilises tels quels dans le bloc
   Retencao). Grille de deux colonnes a 1366 px, une seule sous 900 px --
   seuil demande explicitement par la mission, distinct du seuil general de
   860 px de la section Adaptation plus bas.                                */

.painel-grelha {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--e6);
  margin-top: var(--e5);
  align-items: start;
}

@media (max-width: 900px) {
  .painel-grelha {
    grid-template-columns: 1fr;
  }
}

.painel-bloco {
  border-top: 1px solid var(--line);
  padding-top: var(--e4);
}

.painel-bloco__resumo {
  color: var(--grafite);
  margin-top: var(--e2);
}

.painel-bloco__link {
  margin-top: var(--e4);
}

.painel-lista {
  list-style: none;
  margin: var(--e4) 0 0;
  padding: 0;
}

.painel-lista__item + .painel-lista__item {
  border-top: 1px solid var(--line-2);
}

.painel-lista__item a {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--e3);
  padding: var(--e2) 0;
  color: var(--ink);
  text-decoration: none;
}

.painel-lista__item a:hover .painel-lista__detalhe {
  color: var(--ink);
  text-decoration: underline;
}

.painel-lista__hora {
  font-family: var(--face-mono);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  flex: 0 0 auto;
}

.painel-lista__detalhe {
  color: var(--ink-2);
  flex: 1 1 auto;
  min-width: 0;
}

.painel-lista__ocupacao {
  font-family: var(--face-mono);
  font-variant-numeric: tabular-nums;
  flex: 0 0 auto;
  color: var(--ink-2);
}

/* --- Acessos : codigo gerado (lot P4) --------------------------------------
   Le code n'apparait qu'UNE FOIS, en grand, pour qu'il se lise et se recopie
   sans erreur depuis l'autre bout d'un comptoir d'accueil. */

.codigo-gerado {
  font-family: var(--face-wide);
  font-weight: 700;
  font-size: 4rem;
  line-height: 1.1;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  margin: var(--e5) 0;
}

.form-nova-sessao {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--e4);
  margin: var(--e4) 0 var(--e3);
}

.form-nova-sessao label {
  display: block;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--grafite);
}

.form-nova-sessao input[type="text"] {
  width: 7rem;
}

/* --- Liste simple : un nom, une action ------------------------------------ */

.lista-simples {
  list-style: none;
  margin: var(--e5) 0 0;
  padding: 0;
  max-width: 44rem;
}

.lista-simples > li + li {
  border-top: 1px solid rgba(73, 82, 90, 0.25);
}

.lista-simples a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e4);
  min-height: var(--alvo);
  padding: var(--e3) 0;
  text-decoration: none;
  color: var(--ferro);
}

.lista-simples a:hover .lista-simples__accao {
  text-decoration: underline;
  text-underline-offset: 4px;
}

.lista-simples__nome {
  font-weight: 600;
}

.lista-simples__accao {
  color: var(--cobalto);
}

/* Repli hors faixa : les blocs y sont poses dans le flux, pas a l'echelle. */

.bloco--fora {
  position: static;
  width: auto;
  height: auto;
  margin-bottom: var(--e2);
}

.bloco--fora .bloco__corpo {
  height: auto;
  padding: var(--e2) var(--e3);
}

/* --- Retencao -------------------------------------------------------------
   Le nombre de jours se lit en premier, le nom ensuite, l'action en dernier :
   c'est l'ordre dans lequel quelqu'un decide s'il faut agir.

   L'action est un lien et non un bouton plein. L'ecran d'avant repetait
   51 boutons bleus pleins, qui pesaient plus lourd que l'information qu'ils
   accompagnaient : le bouton plein est reserve a l'action qui engage, une fois,
   a la fin d'un parcours.
   ------------------------------------------------------------------------- */

/* La table ne s'etire pas sur toute la largeur disponible : etiree, elle
   ecarte l'action du nom de plusieurs centimetres et oblige l'oeil a traverser
   l'ecran pour relier deux informations qui vont ensemble. */

/* --- Filtro de retencao ---------------------------------------------------
   Une bande delimitee par deux filets : chercher un membre par nom ou par
   unite. Aide d'affichage, sans JavaScript, un seul bouton. Les decomptes du
   haut ne bougent pas, seule la liste se restreint.                          */

.filtro {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--e3) var(--e4);
  margin: var(--e5) 0 var(--e4);
  padding-bottom: var(--e4);
  border-bottom: 1px solid var(--line);
}

.filtro__campo {
  display: flex;
  flex-direction: column;
  gap: var(--e1);
}

.filtro__campo label {
  margin-bottom: 0;
}

/* DA EXS 25/08 (.fld) : une surface de saisie de filtre est un simple trait
   sous le texte, pas une boite. La boite reste aux formulaires qui engagent
   (redaction, nouvelle seance) ; le filtre ne fait que restreindre. */

.filtro__campo input[type="text"],
.filtro__campo select {
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--ink);
  border-radius: 0;
  padding: var(--e2) 2px;
}

.filtro__campo input[type="text"] {
  width: 18rem;
  max-width: 100%;
}

.filtro__campo input[type="text"]::placeholder {
  color: var(--muted);
}

.filtro__limpar {
  color: var(--grafite);
  min-height: var(--alvo);
  display: inline-flex;
  align-items: center;
}

.filtro__limpar:hover {
  color: var(--ferro);
}

.filtro-resumo {
  color: var(--grafite);
  font-size: 0.8125rem;
  margin: var(--e2) 0 var(--e3);
}

.retencao {
  max-width: 56rem;
}

.retencao__chave-cabecalho {
  text-align: right;
}

.retencao__chave {
  font-family: var(--face-display);
  font-weight: 600;
  font-size: 1.5625rem; /* 25px */
  line-height: 1.1;
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--ferro);
  padding-right: var(--e5);
}

/* Une date n'est pas une quantite : elle ne se lit pas d'un coup d'oeil comme
   un nombre de jours, et la grossir mentirait sur son importance. */

.retencao__chave--data {
  font-family: var(--face-texte);
  font-size: 1rem;
  font-weight: 600;
}

.retencao__nome {
  font-weight: 600;
}

.retencao__unidade {
  color: var(--grafite);
}

.retencao__accao {
  text-align: right;
  white-space: nowrap;
}

.accao-principal,
.accao-secundaria {
  display: inline-flex;
  align-items: center;
  min-height: var(--alvo);
}

.accao-principal {
  color: var(--cobalto);
  font-weight: 600;
}

.accao-secundaria {
  color: var(--grafite);
}

.accao-secundaria:hover {
  color: var(--ferro);
}

.retencao tbody tr:hover .retencao__nome {
  text-decoration: underline;
  text-underline-offset: 3px;
}

@media (max-width: 860px) {
  .retencao__chave {
    padding-right: var(--e4);
    font-size: 1.25rem;
  }
}

/* --- Redaction et approbation ---------------------------------------------
   L'ecran qui porte la promesse : Magda redige, un humain valide.

   Deux actions, deux endroits. « Guardar alterações » appartient a l'editeur,
   c'est le geste de travail, on le repete autant qu'on veut. « Remeter para
   envio » vit dans un bloc separe, c'est le geste qui engage. Les distinguer
   par la seule couleur d'un bouton ne suffirait pas : on les distingue par la
   place, par le poids et par la langue.
   ------------------------------------------------------------------------- */

.app-main h2 {
  margin: var(--e6) 0 var(--e3);
}

.estado-final__titulo {
  margin-top: 0;
}

/* La preuve de la validation humaine se lit en clair. Ce n'est pas une
   metadonnee grise : c'est la garantie que le client vient juger. */

.prova {
  color: var(--ferro);
  margin: var(--e3) 0;
  max-width: 62ch;
}

.prova__acto {
  font-weight: 600;
}

.edicao__accao {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e4);
  margin-top: var(--e3);
}

/* Le bloc d'approbation est une porte, pas un bouton de plus au fil du texte. */

.aprovacao {
  border-left: 4px solid var(--cobalto);
  background: var(--branco);
  padding: var(--e4) var(--e5);
  margin: var(--e6) 0;
  max-width: 62ch;
}

.aprovacao h2 {
  margin-top: 0;
}

.aprovacao p {
  margin-bottom: var(--e4);
}

/* Etat final. « Aprovado » seul serait lu comme « partie » : la phrase qui
   suit dit ce qui n'a PAS eu lieu, et elle est aussi lisible que le mot. */

/* DA EXS 25/08 : le confirme est moss, jamais l'encre ; l'encre porte
   l'action, moss porte l'etat acquis. */

.estado-final {
  border-left: 4px solid var(--moss);
  background: var(--moss-tint);
  padding: var(--e4) var(--e5);
  margin: var(--e5) 0;
  max-width: 62ch;
}

.estado-final__titulo {
  display: flex;
  align-items: baseline;
  gap: var(--e3);
  color: var(--moss);
  font-family: var(--face-mono);
  font-size: 0.6875rem; /* 11px */
  font-weight: 500;
  letter-spacing: 0.13em;
}

.estado-final__marca {
  width: var(--e3);
  height: var(--e3);
  flex: 0 0 auto;
  background: currentColor;
}

.estado-final__marca--neutra {
  background: var(--grafite);
}

/* Etat non confirme : tout le bloc reste neutre, moss ne dit qu'une chose. */

.estado-final--neutro {
  border-left-color: var(--grafite);
  background: var(--paper-2);
}

.estado-final--neutro .estado-final__titulo {
  color: var(--grafite);
}

.estado-final__frase {
  margin-top: var(--e2);
  color: var(--ferro);
}

/* --- Lane W8 : ecran de connexion -----------------------------------------
   Seule regle CSS nouvelle de cette lane (W8-SPEC C4, justifiee au rapport) :
   centrer le formulaire de connexion, avec les jetons existants. Tout le
   reste de l'ecran (.btn, .btn--primary, .flash, .flash--error, label,
   input, form) reutilise les regles deja en place.                         */

.login-form {
  max-width: 420px;
  margin: var(--e8) auto;
}

.login-form__intro {
  margin: 0 0 var(--e5);
  color: var(--ink-2);
}

.login-form__entrar {
  width: 100%;
}

.login-form__ajuda {
  margin: var(--e5) 0 0;
  font-size: 0.8125rem;
  color: var(--ink-2);
}

/* Le champ de connexion reprend le patron de champ deja en place dans le
   depot, `.filtro__campo` : etiquette au-dessus, en petite capitale grise,
   champ pleine largeur en dessous. Sans cela, etiquette et champ restaient
   cote a cote a leur largeur intrinseque et l'ecran sortait en escalier, ce
   qui ne se voit pas dans le code et se voit tout de suite au rendu. */

.login-form__campo {
  display: flex;
  flex-direction: column;
  gap: var(--e2);
  margin-bottom: var(--e4);
}

.login-form__campo label {
  margin-bottom: 0;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--grafite);
}

.login-form__campo input {
  width: 100%;
}

.confirmacao {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e5);
  margin-top: var(--e5);
}

.accoes {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e5);
  margin-top: var(--e4);
}

/* Action a consequence, separee de l'action ordinaire par de l'ESPACE et un
   filet, jamais par une couleur d'alerte : le bouton ne fait rien tout seul,
   il mene a une confirmation qui nomme ce qui va partir. Le crier ici
   apprendrait a l'oeil a ignorer le rouge, qui doit rester rare. */
.accao-perigosa {
  margin-top: var(--e6);
  padding-top: var(--e5);
  border-top: 1px solid var(--line-2);
}

.saida {
  margin-top: var(--e6);
}

/* --- Refus ----------------------------------------------------------------
   Un refus est une reponse, pas un accident. Meme forme que l'etat final d'une
   mensagem approuvee, autre couleur : ce sont deux issues d'un parcours, et
   elles se lisent de la meme facon.
   ------------------------------------------------------------------------- */

.recusa {
  border-left: 4px solid var(--red);
  background: var(--red-tint);
  padding: var(--e5);
  margin: var(--e5) 0;
  max-width: 62ch;
}

/* Meme registre que .estado-final__titulo : deux issues d'un parcours, une
   seule facon de les lire. */

.recusa__titulo {
  display: flex;
  align-items: baseline;
  gap: var(--e3);
  color: var(--red);
  font-family: var(--face-mono);
  font-size: 0.6875rem; /* 11px */
  font-weight: 500;
  letter-spacing: 0.13em;
  line-height: 1.4;
}

.recusa__marca {
  width: var(--e3);
  height: var(--e3);
  flex: 0 0 auto;
  background: currentColor;
}

.recusa__mensagem {
  margin-top: var(--e3);
  color: var(--ferro);
}

.recusa__saida {
  margin-top: var(--e4);
}

/* --- Respostas da Magda ---------------------------------------------------
   L'ecran rend le registre des motifs, il n'en cree pas un second. La PHRASE
   est la matiere principale, en pleine encre : c'est elle que Magda dit. Le
   code technique reste lisible mais en second plan, et la nature
   confirmation/refus suit la regle des statuts sans pastille (section 7 de
   la direction artistique) : un carre, un mot, jamais un conteneur.
   ------------------------------------------------------------------------- */

.respostas {
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: 62rem;
}

/* DA EXS 25/08 (.rrow) : code | phrase | nature. Le code est la cle de
   recherche, il ouvre la ligne ; la nature ferme la ligne, a droite. */

.resposta {
  display: grid;
  grid-template-columns: 18rem minmax(0, 1fr) auto;
  gap: var(--e1) var(--e4);
  padding: var(--e3) 0;
  align-items: baseline;
}

.resposta:hover {
  background: var(--paper-2);
}

.respostas__conta {
  color: var(--grafite);
}

.respostas > .resposta + .resposta {
  border-top: 1px solid var(--line-2);
}

.resposta__natureza {
  display: inline-flex;
  align-items: baseline;
  gap: var(--e2);
  font-family: var(--face-mono);
  font-size: 0.6875rem; /* 11px */
  font-weight: 500;
  letter-spacing: 0.13em;
  text-transform: uppercase;
}

.resposta__natureza::before {
  content: "";
  width: var(--e2);
  height: var(--e2);
  flex: 0 0 auto;
  background: currentColor;
  transform: translateY(-0.05em);
}

/* DA EXS 25/08 : le confirme est moss. */

.resposta__natureza--confirmacao {
  color: var(--moss);
}

.resposta__natureza--recusa {
  color: var(--oxido);
}

.resposta__frase {
  color: var(--ferro);
}

.resposta__codigo {
  font-family: var(--face-mono);
  font-size: 0.71875rem; /* 11.5px : un code est un code, il s'ecrit en mono */
  letter-spacing: 0.02em;
  color: var(--ferro);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

@media (max-width: 860px) {
  .resposta {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* --- Utilitaires ---------------------------------------------------------- */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --- Adaptation -----------------------------------------------------------
   Cibles : portable 13 pouces (1280) et tablette posee a l'accueil (834). Le
   telephone n'est pas la cible mais ne doit rien casser.                     */

@media (max-width: 860px) {
  .app-header__row {
    padding: var(--e4) var(--e4) var(--e3);
    gap: var(--e4);
  }

  .app-header__orgs {
    padding: 0 var(--e4) var(--e3);
  }

  .app-header__screens {
    gap: var(--e4);
  }

  /* Sous 860 px, un menu ouvert sous un groupe proche du bord droit
     deborderait de l'ecran : il prend toute la largeur disponible plutot que
     de suivre son resume. La largeur minimale de 260 px est neutralisee ici,
     sinon elle rouvrirait le debordement sur les petits telephones. */
  .app-header__grupo > .app-header__orgmenu {
    left: 0;
    right: 0;
    min-width: 0;
  }

  .app-main {
    padding: var(--e5) var(--e4) var(--e7);
  }
}

/* --- Mouvement ------------------------------------------------------------
   Aucune animation au-dela de 200 ms, uniquement sur des transitions d'etat,
   jamais l'ornement.                                                        */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- Planeamento (wagon W3, EXS-SCHED-02) ---------------------------------
   Additif uniquement : ne touche a aucune regle existante. Reutilise les
   memes tokens (--e*, --cobalto, --ferro) que le reste du registre. */

.plano-coach {
  margin: var(--e5) 0 0;
  max-width: 44rem;
}

.plano-coach h3 {
  margin: 0;
}

.plano-lista {
  list-style: none;
  margin: var(--e2) 0 var(--e5);
  padding: 0;
}

.plano-lista > li {
  padding: var(--e2) 0;
  border-top: 1px solid var(--line-2);
}

.plano-lista__vazio {
  color: var(--grafite);
}

/* Ecran de confirmation d'ausencia (EXS-SCHED-02 D3) : chaque impact est
   NOMME, jamais un decompte -- la liste est volontairement une liste, pas un
   nombre. */

.impacto {
  list-style: none;
  margin: var(--e4) 0 var(--e5);
  padding: 0;
  max-width: 44rem;
}

.impacto__item {
  padding: var(--e3) 0;
  border-top: 1px solid var(--line-2);
}

/* --- Grille de planeamento (EXS-SCHED-02, refonte du 28/08/2026) -----------
   Additif : ne touche a aucune regle existante. Memes jetons que le reste du
   registre, meme geometrie de colonnes que la grille d'agenda (.agrow).

   Difference ASSUMEE avec la grille d'agenda : ici les heures vides ne se
   replient PAS. Le vide est justement ce sur quoi on appuie pour creer ; une
   bande « sem sessoes » n'offrirait rien a selectionner. L'agenda, lui, est un
   ecran de lecture et garde son pli. */

.plano-grelha {
  --plano-dias: 7;
  /* hauteur d'une HEURE (pas de 30 minutes depuis le 31/08/2026, lot
     "feuille du client" -- une demi-heure fait donc --plano-h / 2). Toute la
     geometrie en decoule -- --bloco-topo/--bloco-dur restent en MINUTES
     BRUTES (gabarit inchange), seuls les elements par PAS (cellules,
     etiquettes d'heure, hauteur du jour) comptent desormais des demi-heures.
     56px : le nom de l'eleve tenait a 52px sur un bloc d'une heure (lot
     varios alunos, 28/08/2026), 64px evitait de tronquer Mover/Cancelar --
     devenu sans objet, ces deux liens vivent desormais sur l'ecran de
     l'occurrence, plus sur la carte. */
  --plano-h: 56px;
  margin: var(--e4) 0 var(--e6);
  border-top: 1px solid var(--line);
  user-select: none;
  touch-action: pan-y;
}

.plano-cab {
  display: grid;
  /* Colonne d'heures des DEUX cotes (feuille du client : "les heures
     repetees a GAUCHE ET A DROITE") -- 58px final pour aligner .plano-cab
     sur .plano-corpo (58px + N jours + 58px). */
  grid-template-columns: 58px repeat(var(--plano-dias), minmax(0, 1fr)) 58px;
  border-bottom: 1px solid var(--line);
}

/* En-tete COLLANT (retour de Baptiste, style Google Agenda : "garder la
   fluidite et l'ergonomie des grosses app") -- les jours restent lisibles
   pendant le defilement d'une longue journee. Toujours posee (jamais
   conditionnelle), z-index au-dessus des blocs (position: absolute, sans
   z-index propre -> empilement par defaut). */
.plano-cab--colante {
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--paper);
}

.plano-cab > div {
  padding: var(--e3) var(--e2);
  font-family: var(--face-mono);
  font-size: 0.625rem; /* 10px */
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.plano-cab > .plano-cab--hoje {
  color: var(--ink);
  border-bottom: 2px solid var(--ink);
  margin-bottom: -1px;
}

.plano-cab b {
  display: block;
  font-family: var(--face-texte);
  font-weight: 600;
  font-size: 0.9375rem; /* 15px */
  letter-spacing: -0.01em;
  color: var(--ink);
}

/* Corps : meme geometrie de colonnes que .plano-cab (58px + N jours). Chaque
   jour est un conteneur `position: relative` de hauteur FIXE (nh heures) --
   les cellules de selection s'y EMPILENT en flux normal (contrat inchange,
   le script de selection en depend), les blocs s'y POSITIONNENT en absolu
   par-dessus, en minutes (--bloco-topo/--bloco-dur), jamais un calcul de
   pixels dans le gabarit (retour utilisateur : "la duree deborde du
   cadre" -- un calendrier montre la duree par la HAUTEUR). */
.plano-corpo {
  display: grid;
  grid-template-columns: 58px repeat(var(--plano-dias), minmax(0, 1fr)) 58px;
}

.plano-horas {
  border-right: 1px solid var(--line-2);
}

/* Colonne d'heures de DROITE (feuille du client) : meme contenu que
   .plano-horas, juste apres la derniere colonne jour -- bordure a GAUCHE au
   lieu de a droite, seule difference. */
.plano-horas--fim {
  border-left: 1px solid var(--line-2);
}

.plano-hora {
  height: calc(var(--plano-h) / 2);
  box-sizing: border-box;
  font-family: var(--face-mono);
  font-size: 0.625rem; /* 10px */
  color: var(--ink-2);
  padding: var(--e2) var(--e2) 0 0;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.plano-dia {
  position: relative;
  /* --plano-nh est un nombre de PAS de 30 minutes (lot 31/08/2026, plus des
     heures) : la hauteur du jour compte donc des demi-pas de --plano-h. */
  height: calc(var(--plano-h) / 2 * var(--plano-nh));
  border-left: 1px solid var(--line-2);
}

.plano-cel {
  height: calc(var(--plano-h) / 2);
  box-sizing: border-box;
  border-bottom: 1px solid var(--line-2);
  cursor: cell;
}

/* Hierarchie de la feuille du client : le BLANC est le temps ouvert, le gris
   est le temps ferme, et la couleur n'appartient qu'aux seances. Une trame
   sur les heures ouvertes rivalisait avec les blocs et faisait un ecran
   charge -- constate sur capture reelle. Le disponible se lit donc par son
   calme, pas par un motif. */
.plano-cel--livre {
  background: var(--paper-2);
}

/* Plage FERMEE (feuille du client) : aucun coach de l'unite disponible sur
   cette demi-heure -- gris PLEIN, trame differente de .plano-cel--livre
   (disponible), jamais la meme lecture. Additive, comme --livre : les deux
   ne coexistent jamais (fechado = l'inverse exact de livre, cote serveur). */
.plano-cel--fechado {
  /* Assez present pour dire « personne ici », assez discret pour ne pas
     devenir le sujet de l'ecran : les seances restent ce qu'on regarde. */
  background: color-mix(in srgb, var(--line-2) 55%, var(--paper));
}

.plano-cel--sel {
  background: var(--moss-tint);
  box-shadow: inset 0 0 0 1px var(--moss);
}

.plano-cel--alvo {
  box-shadow: inset 0 0 0 2px var(--ink);
}

/* Repere "maintenant" (retour de Baptiste, style Google Agenda) : un trait
   fin sur toute la largeur de la colonne du jour, positionne en MINUTES
   depuis --plano-h0 (meme unite que --bloco-topo). Jamais interactif : un
   repere ne doit jamais intercepter un glisser ou un clic sous lui. */
.plano-agora {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--plano-h) * var(--agora) / 60);
  height: 0;
  border-top: 1px solid var(--ink);
  pointer-events: none;
  z-index: 2;
}

/* Marqueur plein a gauche (feuille de route Google Agenda) : un carre, pas
   un cercle -- ce depot n'arrondit jamais que --raio (2px), aucun element
   circulaire ailleurs, un cercle isole romprait ce registre. */
.plano-agora::before {
  content: "";
  position: absolute;
  left: -3px;
  top: -3px;
  width: 6px;
  height: 6px;
  background: var(--ink);
}

/* Largeur/hauteur proportionnelles : --bloco-topo/--bloco-dur en MINUTES
   depuis --plano-h0, --bloco-faixa/--bloco-faixas partagent la largeur entre
   blocs qui se chevauchent (couloirs calcules COTE SERVEUR, par groupe de
   chevauchement -- jamais le nombre global du jour, deux blocs sans rapport
   restent pleine largeur). */
.plano-bloco {
  position: absolute;
  top: calc(var(--plano-h) * var(--bloco-topo) / 60);
  height: calc(var(--plano-h) * var(--bloco-dur) / 60);
  left: calc(var(--bloco-faixa) * 100% / var(--bloco-faixas));
  width: calc(100% / var(--bloco-faixas));
  box-sizing: border-box;
  display: block;
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-left: 2px solid var(--moss);
  border-radius: var(--raio);
  padding: 3px 5px;
  font-size: 0.75rem; /* 12px */
  line-height: 1.25;
  color: var(--ink);
  cursor: grab;
  overflow: hidden;
}

.plano-bloco--serie {
  border-left-color: var(--ochre-deep);
}

/* Nature CHOISIE a l'ecran (PA/PT, retour de Baptiste du 31/08/2026) : un
   trait EN TIRETS, pas une couleur -- la nature ne doit jamais se lire a la
   seule couleur (WCAG 1.4.1), le marqueur texte .plano-bloco__natureza reste
   la source. Additif a border-left-color (moss pour un bloc, ochre pour une
   occurrence de serie) : seul le style du trait change. */
.plano-bloco--pt {
  border-left-style: dashed;
}

/* Couleur STABLE par coach (feuille du client, 31/08/2026 : "une couleur
   par coach, stable, qui permet de retrouver son coach instantanement") --
   8 teintes DISCRETES derivees du registre existant (paper-2, moss-tint,
   ochre-tint, red-tint, quelques gris trames en diagonale) : aucune couleur
   saturee, aucune palette IA. --bloco-cor (1..8, gabarit) pose la classe
   plano-bloco--cor-N que ces regles consomment -- une classe plutot qu'une
   indirection CSS par variable, la seule facon fiable de choisir entre 8
   teintes discretes a partir d'un entier sans JavaScript. APRES
   .plano-bloco--serie dans le fichier : a specificite egale, la couleur du
   coach gagne le bord gauche -- la nature (PT) reste au trait tirete
   ci-dessus, jamais a une couleur, WCAG 1.4.1. */
.plano-bloco--cor-1 {
  background: var(--moss-tint);
  border-left-color: var(--moss);
}

.plano-bloco--cor-2 {
  background: var(--ochre-tint);
  border-left-color: var(--ochre-deep);
}

.plano-bloco--cor-3 {
  background: var(--red-tint);
  border-left-color: var(--red);
}

.plano-bloco--cor-4 {
  background: var(--paper-2);
  border-left-color: var(--ink-2);
}

.plano-bloco--cor-5 {
  background: repeating-linear-gradient(135deg, var(--paper-2) 0 6px, var(--moss-tint) 6px 12px);
  border-left-color: var(--moss);
}

.plano-bloco--cor-6 {
  background: repeating-linear-gradient(135deg, var(--paper-2) 0 6px, var(--ochre-tint) 6px 12px);
  border-left-color: var(--ochre-deep);
}

.plano-bloco--cor-7 {
  background: repeating-linear-gradient(135deg, var(--paper-2) 0 6px, var(--red-tint) 6px 12px);
  border-left-color: var(--red);
}

.plano-bloco--cor-8 {
  background: repeating-linear-gradient(135deg, var(--paper-2) 0 6px, var(--line-2) 6px 12px);
  border-left-color: var(--muted);
}

.plano-bloco--arrasto {
  opacity: 0.5;
  cursor: grabbing;
}

/* Pendant un glisser actif (script), les blocs ne doivent plus intercepter
   elementFromPoint -- sinon la cellule cible sous le pointeur reste
   introuvable des qu'on survole un AUTRE bloc, et le glisser perd sa cible. */
.plano-grelha--arrastando .plano-bloco {
  pointer-events: none;
}

/* Poignee de redimensionnement (retour de Baptiste, style Google Agenda) :
   discrete au repos, visible au survol ou au clavier -- jamais un second
   glisser qui se devine. Uniquement sur un BLOC (_plano_grelha.html), le
   curseur ns-resize annonce le geste avant meme le clic. */
.plano-bloco__puxador {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 6px;
  cursor: ns-resize;
  background: transparent;
}

.plano-bloco:hover .plano-bloco__puxador,
.plano-bloco__puxador:focus-visible {
  background: var(--ink-2);
}

.plano-bloco__hora {
  font-family: var(--face-mono);
  font-size: 0.625rem; /* 10px */
  letter-spacing: 0.06em;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

.plano-bloco__nome {
  display: block;
  font-weight: 600;
}

.plano-bloco__membro {
  display: block;
  color: var(--ink-2);
  /* UN OU PLUSIEURS eleves (migrations/017) : plusieurs noms sur UNE seule
     ligne avec ellipsis -- la liste complete reste lisible via `title=` sur
     l'article (_plano_grelha.html), jamais tronquee silencieusement. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Bloc COURT (< 60 min, pas de 30 minutes -- feuille du client, 31/08/2026) :
   pas la place pour heure + nature + nom + eleves. Le nom des eleves
   disparait, le `title=` sur l'article garde la liste complete au survol,
   jamais perdue. */
.plano-bloco--curto .plano-bloco__membro {
  display: none;
}

/* Heure et nature partagent la premiere ligne : chaque ligne gagnee est une
   ligne que le cadre d'un bloc d'une heure ne tronque pas. Les deux gestes
   d'une serie doivent rester visibles et atteignables au clavier, meme la. */
.plano-bloco__linha {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--e1);
}

.plano-bloco__natureza {
  font-family: var(--face-mono);
  font-size: 0.5625rem; /* 9px */
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
}

/* Le corps d'un bloc EST son lien d'edition (un clic ouvre le bloc, comme
   dans un calendrier) : il porte la couleur du texte, jamais celle d'un lien,
   et son soulignement n'apparait qu'au survol ou au clavier. */
.plano-bloco__corpo {
  display: block;
  color: inherit;
  text-decoration: none;
}

.plano-bloco__corpo:hover,
.plano-bloco__corpo:focus-visible {
  text-decoration: underline;
}

.plano-bloco__gestos {
  display: block;
  font-family: var(--face-mono);
  font-size: 0.5625rem; /* 9px */
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Fenetre de creation. Sans JavaScript, ce meme formulaire reste en bas de
   page, ordinaire et complet : la classe flottante n'est posee que par le
   script. */

.plano-criar {
  border: 1px solid var(--line);
  background: var(--paper-2);
  padding: var(--e4);
  max-width: 22rem;
}

.plano-criar--flutuante {
  position: absolute;
  z-index: 20;
  width: 20rem;
  box-shadow: 0 1px 0 var(--ink);
}

.plano-criar label {
  display: block;
  font-family: var(--face-mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: var(--e3) 0 var(--e1);
}

.plano-criar input,
.plano-criar select {
  width: 100%;
}

.plano-criar__linha {
  display: flex;
  gap: var(--e2);
}

.plano-conflitos {
  margin: var(--e3) 0 0;
  padding: var(--e2) var(--e3);
  border-left: 2px solid var(--ochre-deep);
  color: var(--ochre-deep);
  font-size: 0.8125rem;
}

.plano-legenda {
  font-family: var(--face-mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  margin: var(--e2) 0 0;
}

/* Raccourcis declares (retour de Baptiste, style Google Agenda : "garder la
   fluidite et l'ergonomie des grosses app") -- meme registre que
   .plano-legenda, pour qui ne les devine pas. */
.plano-atalhos {
  font-family: var(--face-mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  margin: var(--e1) 0 0;
}

@media (max-width: 60rem) {
  .plano-grelha {
    overflow-x: auto;
  }

  .plano-cab,
  .plano-corpo {
    min-width: 46rem;
  }
}

/* Confirmacao de presenca pelo coach (retour do client, chantier "objectif
   production", lot 1/5, 01/09/2026) : "os treinadores marcam os seus
   treinos la, mas ficam registados como tarefa e o treinador depois
   confirma a presença do aluno". */

/* Marque DISCRETE "toutes les presencas confirmadas" -- jamais a la seule
   couleur (title= le dit aussi, _plano_grelha.html, WCAG 1.4.1) : un fin
   encadre interieur, meme teinte que la confirmation ailleurs dans l'appli
   (var(--moss)), rien qui rivalise avec la couleur STABLE du coach. */
.plano-bloco--confirmado {
  box-shadow: inset 0 0 0 1px var(--moss);
}

/* Section "Presenças" de l'ecran d'edition d'un bloc PASSE
   (planeamento_bloco_editar.html). */
.plano-presencas {
  margin: var(--e4) 0;
}

.plano-presencas__lista {
  list-style: none;
  margin: var(--e2) 0 0;
  padding: 0;
}

.plano-presencas__item {
  display: flex;
  align-items: center;
  gap: var(--e2);
  padding: var(--e2) 0;
  border-bottom: 1px solid var(--line-2);
}

.plano-presencas__item form {
  margin: 0;
}

.plano-presencas__nome {
  flex: 1;
}

.plano-presencas__marca {
  font-family: var(--face-mono);
  font-size: 0.6875rem; /* 11px */
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--moss);
}

/* Presence d'un eleve qui ne fait PLUS partie du bloc. Meme registre que la
   marque ci-dessus, couleur d'alerte : c'est une ligne a traiter, pas un etat
   normal. La phrase porte l'information a elle seule, la couleur ne fait que
   la seconder (WCAG 1.4.1). */
.plano-presencas__orfa {
  font-family: var(--face-mono);
  font-size: 0.6875rem; /* 11px */
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--oxido);
}

/* --- CRM de leads (lote A2) ------------------------------------------------
   Trois ecrans : le portefeuille, la fiche, et les deux vues commerciales.
   Aucune couleur neuve : les trois situations reprennent les teintes deja
   posees plus haut (--moss-tint, --ochre-tint, --red-tint), les memes qui
   servent deja aux etats ailleurs dans la feuille. La couleur ne porte jamais
   seule l'information : la colonne « Situação » l'ecrit aussi (WCAG 1.4.1).  */

/* Un bouton desactive doit SE VOIR desactive. Premier du depot (aucun autre
   gabarit n'en portait), et la raison est toujours la meme ici : le canal
   d'envoi n'existe pas avant le lot A5. Un bouton noir plein qui ne repond
   pas au clic fait croire a une panne. */

.btn:disabled {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--line);
  cursor: not-allowed;
}

.btn:disabled:hover {
  background: transparent;
  color: var(--muted);
}

/* Groupe « Comercial » de la navigation. Meme mecanique que le selecteur
   d'organisation : `details` natif, zero JavaScript.

   Le menu deroulant se pose par rapport a la RANGEE de navigation, pas par
   rapport a son bouton -- c'est la seule difference avec le selecteur
   d'organisation, et elle est mesuree. Ancre au bouton (`position: relative`
   sur le groupe, `left: 0` sur le menu), le menu partait vers la droite
   depuis un bouton qui se trouve en fin de barre : ouvert a 1024 px, la page
   passait de 1024 a 1082 de large, soit 58 px de defilement horizontal sur un
   ecran qui n'en a aucun ailleurs. Le selecteur d'organisation, lui, est
   ancre a gauche de la barre et n'a jamais deborde : le defaut n'etait pas
   dans le procede, il etait dans le point d'ancrage.

   Pose sur la rangee et cale a droite, le menu ne peut plus sortir : sa borne
   droite est le bord de contenu de la rangee, et sa borne gauche reste dans
   l'ecran tant que la rangee est plus large que ses 260 px (elle l'est des
   360 px de large). Il descend sous la barre au lieu de la recouvrir, ce qui
   est aussi ce qu'on attend d'un menu de navigation. */

.app-header__row--nav {
  position: relative;
}

/* CHAQUE GROUPE EST SON PROPRE REPERE. Tant qu'il n'y avait qu'un groupe
   (« Comercial »), et qu'il etait le DERNIER de la barre, le menu pouvait etre
   pose a droite de la rangee : ca tombait juste par coincidence. Depuis la
   navigation par familles (09/09/2026) il y a cinq groupes, et cette regle
   ouvrait les cinq menus au meme endroit, a l'extreme droite -- constate sur
   une capture du rendu reel, invisible dans le code. Le menu s'ouvre desormais
   SOUS son propre resume. */
.app-header__grupo {
  position: relative;
}

.app-header__grupo > .app-header__orgmenu {
  left: 0;
  right: auto;
}

.app-header__grupo > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--e1);
}

.app-header__grupo > summary::-webkit-details-marker,
.app-header__grupo > summary::marker {
  display: none;
  content: "";
}

.app-header__grupo > summary::before {
  content: none;
}

.app-header__grupo[open] > .app-header__orgmenu {
  display: flex;
}

/* Tableau du portefeuille. */

.leads {
  min-width: 58rem;
}

.leads__linha--verde th,
.leads__linha--verde td {
  background: var(--moss-tint);
}

.leads__linha--amarelo th,
.leads__linha--amarelo td {
  background: var(--ochre-tint);
}

.leads__linha--vermelho th,
.leads__linha--vermelho td {
  background: var(--red-tint);
}

.leads th,
.leads td {
  padding-right: var(--e3);
  vertical-align: top;
}

.leads__ordenar {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.leads__ordenar:hover {
  border-bottom-color: var(--ink);
}

.leads__ordenar--activa {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

.leads__nome a {
  font-weight: 600;
}

.leads__empresa,
.leads__detalhe,
.leads__tentativas {
  display: block;
  font-family: var(--face-mono);
  font-size: 0.625rem; /* 10px */
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.leads__data--criacao {
  color: var(--muted);
}

.leads__observacoes {
  max-width: 18rem;
}

.marca-svg {
  vertical-align: -1px;
  color: var(--ink-2);
}

.leads__novo {
  margin-left: auto;
}

.paginacao {
  display: flex;
  align-items: center;
  gap: var(--e4);
  margin: var(--e4) 0 var(--e6);
}

.paginacao__estado {
  font-family: var(--face-mono);
  font-size: 0.6875rem; /* 11px */
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Bloc « Análise do mês ». Replie par defaut : c'est un complement du
   portefeuille, pas sa raison d'etre. */

.analise {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: var(--e3) 0;
  margin: var(--e5) 0;
}

.analise__resumo {
  cursor: pointer;
  font-family: var(--face-mono);
  font-size: 0.6875rem; /* 11px */
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.analise__titulo {
  font-size: 0.875rem;
}

.analise__fontes {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--e4);
  max-width: 26rem;
}

.analise__fontes > li {
  display: flex;
  justify-content: space-between;
  gap: var(--e4);
  padding: var(--e2) 0;
  border-bottom: 1px solid var(--line-2);
}

.analise__fonte {
  color: var(--ink-2);
}

.analise__n {
  font-family: var(--face-wide);
  font-variant-numeric: tabular-nums;
}

.count-card--verde {
  border-left-color: var(--moss);
}

.filtro--analise {
  border-bottom: 0;
  margin-top: var(--e3);
}

/* Fiche de lead. */

.voltar {
  margin: 0 0 var(--e3);
}

.ficha {
  border-left: 3px solid var(--line);
  padding-left: var(--e4);
  margin-bottom: var(--e5);
}

.ficha--verde {
  border-left-color: var(--moss);
}

.ficha--amarelo {
  border-left-color: var(--ochre);
}

.ficha--vermelho {
  border-left-color: var(--red);
}

.ficha__empresa {
  color: var(--ink-2);
  margin: var(--e2) 0 0;
}

.ficha__factos {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e3) var(--e6);
  margin: var(--e4) 0 0;
}

.ficha__factos dt {
  font-family: var(--face-mono);
  font-size: 0.625rem; /* 10px */
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--muted);
}

.ficha__factos dd {
  margin: var(--e1) 0 0;
}

.ficha__perda {
  color: var(--red);
  margin-top: var(--e3);
}

.ficha__colunas {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--e6);
}

.ficha__coluna > h2:first-child {
  margin-top: 0;
}

/* Entonnoir a quatre etapes. Quatre et non neuf : les neuf etats servent le
   travail, les quatre pas servent l'oeil. */

.funil {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--e2);
  margin: 0 0 var(--e5);
}

.funil__passo {
  border-top: 3px solid var(--line);
  padding-top: var(--e2);
}

.funil__passo--feito {
  border-top-color: var(--moss);
}

.funil__titulo {
  font-family: var(--face-mono);
  font-size: 0.6875rem; /* 11px */
  letter-spacing: 0.13em;
  text-transform: uppercase;
  margin: 0;
}

.funil__data {
  margin: var(--e1) 0 0;
  color: var(--muted);
}

.funil__passo--feito .funil__data {
  color: var(--ink-2);
}

.cronologia {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--e5);
}

.cronologia__linha {
  border-left: 1px solid var(--line);
  padding: 0 0 var(--e3) var(--e4);
}

.cronologia__quando,
.cronologia__que,
.cronologia__resumo {
  margin: 0;
}

.cronologia__quando {
  font-family: var(--face-mono);
  font-size: 0.625rem; /* 10px */
  letter-spacing: 0.08em;
  color: var(--muted);
}

.cronologia__tipo {
  font-weight: 600;
}

/* Formulaire empile : une etiquette, son champ, dessous. Le formulaire de
   seance existant (.form-nova-sessao) aligne ses champs sur une rangee, ce qui
   convient a trois champs courts et devient illisible a huit : l'oeil ne relie
   plus une etiquette a son champ. Mesure faite sur le rendu reel a 1280 px. */

.forma-lead {
  max-width: 26rem;
  margin: var(--e4) 0 var(--e5);
}

.forma-lead label {
  display: block;
  margin: var(--e3) 0 var(--e1);
  font-family: var(--face-mono);
  font-size: 0.625rem; /* 10px */
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--muted);
}

.forma-lead input[type="text"],
.forma-lead input[type="datetime-local"],
.forma-lead select {
  width: 100%;
  min-height: var(--alvo);
}

.forma-lead > button {
  margin-top: var(--e4);
}

.forma-lead__confirmacao {
  display: flex;
  align-items: center;
  gap: var(--e2);
  margin: var(--e4) 0 0;
  font-family: var(--face-texte);
  font-size: 0.9375rem;
  letter-spacing: normal;
  text-transform: none;
  color: var(--ink);
}

.ficha__factos--largo {
  gap: var(--e4) var(--e5);
}

.ficha__factos--largo dd {
  font-weight: 600;
}

.gesto-unico {
  display: flex;
  align-items: center;
  gap: var(--e3);
  flex-wrap: wrap;
  margin-bottom: var(--e4);
}

.duplicados {
  border-left: 3px solid var(--ochre);
  padding-left: var(--e4);
  margin-bottom: var(--e5);
}

.dormentes__forma {
  margin-bottom: var(--e6);
}

.agenda-dia {
  font-family: var(--face-mono);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  color: var(--ink-2);
}

.agenda-dia--hoje {
  color: var(--ink);
}

/* --- CRM sur telephone ----------------------------------------------------
   Le commercial travaille au telephone : la liste et la fiche doivent tenir a
   390 px SANS defilement horizontal. Le tableau se replie donc en fiches
   empilees, chaque cellule reprenant son intitule par `data-etiqueta`. Point
   de rupture existant (860 px), aucun point neuf.                            */

@media (max-width: 860px) {
  .leads {
    min-width: 0;
  }

  .leads thead {
    display: none;
  }

  .leads,
  .leads tbody,
  .leads th,
  .leads td {
    display: block;
    width: auto;
  }

  /* Deux colonnes et non une : empilee sur une seule colonne, une ficha de
     douze champs mesure six cents pixels de haut, et dix-huit leads font une
     page de dix mille. Mesure faite sur le rendu reel a 390 px. Le nom garde
     toute la largeur, c'est lui qu'on cherche en balayant du pouce. */
  .leads tr {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--e1) var(--e3);
    border-bottom: 1px solid var(--line);
    padding: var(--e3) 0;
  }

  .leads__nome {
    grid-column: 1 / -1;
  }

  .leads tbody tr + tr th,
  .leads tbody tr + tr td {
    border-top: 0;
  }

  .leads th,
  .leads td {
    padding: var(--e1) 0;
  }

  .leads td[data-etiqueta]::before {
    content: attr(data-etiqueta) " ";
    display: block;
    font-family: var(--face-mono);
    font-size: 0.625rem; /* 10px */
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--muted);
  }

  .leads__observacoes {
    max-width: none;
  }

  .ficha__colunas {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--e5);
  }

  .funil {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .ficha__factos {
    gap: var(--e3) var(--e5);
  }

  .filtro__campo input[type="text"] {
    width: 100%;
  }
}

/* --- « Hoje », la page de travail du commercial (lot A3) ------------------
   TELEPHONE D'ABORD, et litteralement : ces regles-ci sont celles du petit
   ecran, sans media query, et c'est la LARGEUR qui ajoute des colonnes plus
   bas. Le reste de la feuille fait l'inverse (bureau d'abord, repli a 860 px)
   parce que ses ecrans sont ouverts sur un poste de reception. Celui-ci ne
   l'est pas : il est ouvert dans une main, entre deux appels.

   Aucune couleur ne porte seule une information : le retard a son filet ocre
   ET le mot « Em atraso », la priorite a sa pastille ET sa lettre (WCAG
   1.4.1). Aucun degrade, aucune ombre portee, aucun arrondi decoratif : la
   direction artistique du 25/08/2026 tient ici comme ailleurs.            */

.hoje__carteira {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e2);
  margin: var(--e4) 0 var(--e5);
  padding-bottom: var(--e4);
  border-bottom: 1px solid var(--line);
}

.hoje__carteira label {
  font-family: var(--face-mono);
  font-size: 0.6875rem; /* 11px */
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--muted);
}

.hoje__indice {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e2);
  margin-bottom: var(--e6);
}

/* Les quatre reperes du haut sont des liens d'ancrage, pas des chiffres
   decoratifs : sur un ecran de 390 px, la page fait plusieurs hauteurs
   d'ecran, et savoir ce qui vient sans faire defiler est la seule facon de
   choisir par ou commencer. */
.hoje__indice a {
  display: inline-flex;
  align-items: baseline;
  gap: var(--e2);
  padding: var(--e2) var(--e3);
  border: 1px solid var(--line);
  font-family: var(--face-mono);
  font-size: 0.6875rem; /* 11px */
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
  text-decoration: none;
}

.hoje__indice a:hover {
  border-color: var(--ink);
  color: var(--ink);
}

.hoje__conta {
  font-family: var(--face-wide);
  font-size: 0.875rem; /* 14px */
  font-weight: 700;
  color: var(--ink);
}

.hoje__bloco {
  margin-bottom: var(--e7);
  scroll-margin-top: var(--e4);
}

.hoje__explicacao {
  max-width: 44rem;
  margin: 0 0 var(--e4);
  color: var(--ink-2);
}

.hoje__lista {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--e3);
}

.hoje__ficha {
  border: 1px solid var(--line);
  border-left: 2px solid var(--line);
  background: var(--paper-2);
  padding: var(--e3) var(--e4) var(--e4);
}

/* Le retard se voit AVANT d'etre lu : filet ocre a gauche, trame ocre. Le mot
   « Em atraso » reste ecrit dans la ligne, la couleur ne porte rien seule. */
.hoje__ficha--atraso {
  border-left-color: var(--ochre);
  background: var(--ochre-tint);
}

.hoje__topo {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--e3);
  margin: 0 0 var(--e2);
}

.hoje__nome {
  font-family: var(--face-display);
  font-size: 1.0625rem; /* 17px */
  font-weight: 600;
  color: var(--ink);
}

.hoje__quando,
.hoje__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--e1) var(--e3);
  margin: 0 0 var(--e2);
  font-family: var(--face-mono);
  font-size: 0.6875rem; /* 11px */
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.hoje__hora,
.hoje__dia,
.hoje__idade {
  color: var(--ink);
}

.hoje__atraso {
  color: var(--ochre-deep);
  border-bottom: 1px solid var(--ochre);
}

.hoje__tentativas {
  color: var(--ink-2);
}

.hoje__obs {
  margin: 0 0 var(--e2);
  color: var(--ink-2);
}

.hoje__obs--vazia {
  color: var(--muted);
}

.hoje__tel {
  margin: 0 0 var(--e3);
}

/* Le numero est un lien d'appel : c'est le seul geste de cette page que le
   telephone fait mieux que la plateforme, et le faire recopier a la main est
   la facon la plus sure de composer un chiffre de travers. */
.hoje__tel a {
  font-family: var(--face-mono);
  font-size: 0.9375rem; /* 15px */
  color: var(--ink);
}

/* Trois boutons cote a cote sur une ligne de 390 px : ils se partagent la
   largeur et gardent 44 px de haut, la cible de toucher recommandee. Le
   premier porte l'action attendue (noir), les deux autres sont secondaires. */
.hoje__gestos {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e2);
  margin: 0;
}

.hoje__gestos .btn {
  flex: 1 1 6rem;
  min-height: 44px;
  justify-content: center;
}

.hoje__proxima {
  display: grid;
  gap: var(--e1);
  margin-top: var(--e3);
  padding-top: var(--e3);
  border-top: 1px solid var(--line);
}

.hoje__proxima-titulo {
  margin: 0;
  font-family: var(--face-mono);
  font-size: 0.6875rem; /* 11px */
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--muted);
}

.hoje__proxima label {
  font-size: 0.8125rem; /* 13px */
  color: var(--ink-2);
}

.hoje__proxima input,
.hoje__proxima select {
  width: 100%;
  min-height: 44px;
}

.hoje__proxima .btn {
  min-height: 44px;
  margin-top: var(--e2);
}

/* Ecran large : deux colonnes de cartes. Le point de rupture est celui de la
   feuille (860 px), aucun point neuf -- un second point de rupture serait un
   second endroit ou la mise en page peut diverger. */
@media (min-width: 861px) {
  .hoje__lista {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--e4);
  }

  .hoje__proxima {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    column-gap: var(--e3);
  }

  .hoje__proxima-titulo,
  .hoje__proxima .btn,
  .hoje__proxima .hint {
    grid-column: 1 / -1;
  }
}

/* Origine d'une reservation (agenda). La colonne `booking.origin` existait
   depuis le premier jour et aucun ecran ne la lisait : au 09/09/2026, 419
   reservations venaient d'OVG, 255 de la reception et 4 de Magda, sans qu'une
   seule page ne le dise. La marque reste DISCRETE : elle qualifie une ligne,
   elle ne la remplace pas. */
.bloco__origem {
  display: block;
  font-size: 0.75rem;
  color: var(--ink-2);
  letter-spacing: 0.02em;
}

.origem--magda {
  font-weight: 600;
}

.agresumo {
  margin: 0 0 var(--e4);
  color: var(--ink-2);
}

/* Le detail sous un chiffre, sur sa propre ligne. Entre parentheses et sur la
   meme ligne, « (1 de 7) » se coupait au milieu de la parenthese des que la
   colonne se resserrait : constate sur la capture de l'ecran Conversao. */
.hint--bloco {
  display: block;
}
