/* ============================================================================
   OCEALIZ — feuille de style unique du front de pilotage courtiers.
   Couloir A1 (socle). Ecrite a la main, AUCUN build, AUCUN CDN, AUCUNE requete
   sortante (CONTRAT-REFONTE-UI §2.1 et correction M2).

   POURQUOI PAS TAILWIND COMPILE
   -----------------------------
   La maquette Stitch charge Tailwind depuis un CDN avec une config inline. La
   reproduire "compilee" imposait au depot un pipeline Node (package.json,
   tailwind.config, une commande de build a rejouer avant chaque commit) et un
   artefact genere de plusieurs milliers de lignes que personne ne relit. Le
   perimetre visuel reel du projet est FERME : dix ecrans, huit composants, une
   palette figee dans DESIGN.md. Un CSS artisanal de ~600 lignes couvre cette
   surface, se relit, se diffe, et ne peut pas se desynchroniser d'une chaine de
   build absente de l'image Docker en boucle fermee.

   PALETTE
   -------
   Les jetons `--ocz-*` reprennent EXACTEMENT les valeurs de
   `professional_enterprise_dashboard/DESIGN.md`. Les couleurs semantiques que la
   maquette ecrivait en dur (#10B981, #F59E0B, #EF4444) sont declinees en trois
   crans : `-texte` (assez sombre pour WCAG AA sur fond clair, correction M6),
   `-accent` (aplats, jauges, pastilles) et `-fond` / `-bordure`. La maquette
   posait par exemple le KPI « 2 154 » en #F59E0B, soit 2.1:1 sur blanc : illisible.
   ========================================================================== */

/* ── Polices locales ─────────────────────────────────────────────────────── */

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;         /* fichier variable : un seul telechargement */
  font-display: swap;
  src: url('../fonts/Inter-variable.woff2') format('woff2');
}

/* ── Jetons ──────────────────────────────────────────────────────────────── */

:root {
  /* Surfaces (DESIGN.md) */
  --ocz-surface: #f7f9fb;
  --ocz-surface-container-lowest: #ffffff;
  --ocz-surface-container-low: #f2f4f6;
  --ocz-surface-container: #eceef0;
  --ocz-surface-container-high: #e6e8ea;
  --ocz-surface-variant: #e0e3e5;

  /* Textes */
  --ocz-on-surface: #191c1e;
  --ocz-on-surface-variant: #44474d;

  /* Traits */
  --ocz-outline: #74777e;
  /* RELEVE DE 1,71:1 A 3,32:1 — mesure, pas gout. Ce jeton dessine la bordure de
     `.ocz-champ`, et sur un champ de saisie la bordure est SEULE PORTEUSE : rien
     d'autre ne dit ou commence la zone qu'on peut remplir. Sous 3:1, un contour
     porteur de sens n'est pas conforme, et surtout il ne se voit pas.
     Releve par le juge d'apparence du round 2, sur 40 occurrences — UN jeton.
     Il sert aussi la pastille « a venir » du fil (3,14:1 sur le fond de page) et
     les filets de tableau : tout monte ensemble, sans toucher a la hierarchie
     puisque les etats actifs gardent leurs teintes propres. */
  --ocz-outline-variant: #8a8d96;
  --ocz-bordure-carte: #e2e8f0;   /* DESIGN.md, « Elevation & Depth » */

  /* Marque */
  --ocz-primary: #000f23;
  --ocz-primary-container: #0f253e;   /* navy de la sidebar */
  --ocz-on-primary-container: #788dab;
  --ocz-primary-fixed-dim: #b3c8e8;
  --ocz-secondary: #0061a5;
  --ocz-secondary-container: #66affe;
  --ocz-secondary-fixed: #d2e4ff;
  --ocz-on-secondary-fixed-variant: #00497e;

  /* Semantique — succes */
  --ocz-succes-texte: #047857;
  --ocz-succes-accent: #10b981;
  --ocz-succes-fond: #ecfdf5;
  --ocz-succes-bordure: #a7f3d0;

  /* Semantique — avertissement */
  --ocz-avertissement-texte: #b45309;
  --ocz-avertissement-accent: #f59e0b;
  --ocz-avertissement-fond: #fffbeb;
  --ocz-avertissement-bordure: #fde68a;

  /* Semantique — danger */
  --ocz-error: #ba1a1a;
  --ocz-danger-texte: #b3261e;
  --ocz-danger-accent: #ef4444;
  --ocz-danger-fond: #fef2f2;
  --ocz-danger-bordure: #fecaca;

  /* Semantique — info */
  --ocz-info-texte: #00497e;
  --ocz-info-accent: #0061a5;
  --ocz-info-fond: #eff6ff;
  --ocz-info-bordure: #bfdbfe;

  /* Semantique — neutre */
  --ocz-neutre-texte: #44474d;
  --ocz-neutre-fond: #f1f3f5;
  --ocz-neutre-bordure: #c4c6ce;

  /* Rythme (DESIGN.md « spacing ») */
  --ocz-largeur-sidebar: 240px;
  --ocz-padding-conteneur: 1.5rem;
  --ocz-ecart-cartes: 1rem;
  --ocz-marge-section: 2rem;

  /* Formes (DESIGN.md « Shapes ») */
  --ocz-rayon-carte: 0.5rem;
  --ocz-rayon-controle: 0.25rem;
  --ocz-rayon-pill: 9999px;

  --ocz-ombre-carte: 0 1px 2px rgba(0, 0, 0, 0.03);
  --ocz-ombre-action: 0 2px 4px rgba(0, 0, 0, 0.05);

  --ocz-police: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto,
                'Helvetica Neue', Arial, sans-serif;
}

/* ── Remise a zero minimale ──────────────────────────────────────────────── */

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--ocz-police);
  font-size: 14px;
  line-height: 20px;
  color: var(--ocz-on-surface);
  background: var(--ocz-surface);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; }
p { margin: 0 0 0.75rem; }
ul, ol { margin: 0; padding-left: 1.25rem; }
a { color: var(--ocz-secondary); }
button { font: inherit; }

/* ── Echelle typographique (DESIGN.md « typography ») ────────────────────── */

.ocz-display-lg      { font-size: 32px; line-height: 40px; font-weight: 700; }
.ocz-headline-md     { font-size: 24px; line-height: 32px; font-weight: 600; }
.ocz-headline-sm     { font-size: 18px; line-height: 24px; font-weight: 600; }
.ocz-body-lg         { font-size: 16px; line-height: 24px; font-weight: 400; }
.ocz-body-md         { font-size: 14px; line-height: 20px; font-weight: 400; }
.ocz-body-sm         { font-size: 12px; line-height: 16px; font-weight: 400; }
.ocz-label-md        { font-size: 12px; line-height: 16px; font-weight: 600;
                       letter-spacing: 0.02em; }
.ocz-kpi-valeur      { font-size: 28px; line-height: 34px; font-weight: 700; }

.ocz-muet   { color: var(--ocz-on-surface-variant); }

/* DEUX CLASSES DE CHIFFRES, ET ELLES NE SONT PAS JUMELLES (arbitrage du round 4).
   `.ocz-nombre` habille un nombre EN LIGNE, dans du texte ; `.ocz-cellule-nombre`
   (bas de feuille) habille une CELLULE de tableau, et c'est elle qui porte le
   `nowrap` — une colonne de chiffres ne se coupe pas. La distinction est voulue et
   documentee dans `dossiers.html` ; elle n'est PAS fusionnee ici. Un montant qui
   se coupait le faisait parce que sa cellule prenait la mauvaise classe, pas
   parce qu'il manquait une regle. */
.ocz-nombre { font-variant-numeric: tabular-nums; }

/* Un sous-libelle POSE DANS une cellule de chiffres est du texte courant, pas un
   nombre : il reprend le repli normal, sinon le `nowrap` de la cellule fige
   aussi sa legende (« 12 mises en demeure » sur une seule ligne, qui elargit la
   colonne pour rien). */
.ocz-cellule-nombre .ocz-body-sm { white-space: normal; }

/* Alignement a droite des colonnes de chiffres. Trois orthographes du meme
   `text-align: right` circulaient en attribut `style=` — dont une hors de la
   liste que la garde `test_styles_en_ligne.py` surveille : elle gardait donc
   deux ecritures sur trois. Une classe, une orthographe, une garde qui voit. */
.ocz-droite { text-align: right; }

/* Lu par les lecteurs d'ecran, invisible a l'oeil. */
.ocz-invisible {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── Accessibilite : focus visible partout (correction M6) ───────────────── */

:focus-visible {
  outline: 2px solid var(--ocz-secondary);
  outline-offset: 2px;
  border-radius: var(--ocz-rayon-controle);
}

.ocz-sidebar :focus-visible { outline-color: var(--ocz-secondary-container); }

.ocz-saut-contenu {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ocz-primary-container); color: #fff;
  padding: 0.75rem 1rem; border-radius: 0 0 var(--ocz-rayon-controle) 0;
}
.ocz-saut-contenu:focus { left: 0; }

/* ── Ossature ────────────────────────────────────────────────────────────── */

.ocz-page { min-height: 100vh; }

.ocz-sidebar {
  position: fixed; inset: 0 auto 0 0; z-index: 40;
  width: var(--ocz-largeur-sidebar);
  display: flex; flex-direction: column;
  background: var(--ocz-primary-container);
  color: var(--ocz-primary-fixed-dim);
  overflow-y: auto;
}

.ocz-marque {
  display: flex; flex-direction: column; gap: 0.125rem;
  padding: 1.5rem var(--ocz-padding-conteneur) 1.25rem;
}
.ocz-marque__ligne { display: flex; align-items: center; gap: 0.5rem; }
.ocz-marque__icone { color: var(--ocz-secondary-fixed); flex: none; }
.ocz-marque__nom {
  font-size: 26px; line-height: 32px; font-weight: 700;
  letter-spacing: -0.02em; color: #fff;
}
.ocz-marque__baseline {
  font-size: 12px; line-height: 16px; margin-left: 2rem;
  color: rgba(179, 200, 232, 0.75);
}

.ocz-nav { flex: 1; padding: 0 0.75rem 1rem; }
/* OPACITE 0,70 — CALCULEE, PAS CHOISIE. A 0,60 le libelle de section rendait
   4,21:1 sur le navy de la barre : sous le seuil de 4,5:1, et il s'agit de texte
   de 10 px. Releve du round 1, verifie au calcul : 0,65 donne 4,69:1 (marge de
   0,19, trop mince pour du 10 px), 0,70 donne 5,20:1.
   ON NE MONTE PAS PLUS HAUT, et c'est la vraie contrainte : les entrees de
   navigation sont a 0,85 et l'entree active a du blanc plein. Une section trop
   contrastee viendrait concurrencer ce qu'elle est censee coiffer — la
   hierarchie est aussi une information. */
.ocz-nav__section {
  margin: 1.25rem 0 0.5rem; padding-left: 0.75rem;
  font-size: 10px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: rgba(179, 200, 232, 0.7);
}

.ocz-nav__lien {
  display: flex; align-items: center; gap: 0.75rem;
  padding: 0.625rem 1rem; margin-bottom: 0.125rem;
  border-left: 4px solid transparent;
  border-radius: 0 var(--ocz-rayon-controle) var(--ocz-rayon-controle) 0;
  color: rgba(179, 200, 232, 0.85);
  font-size: 12px; line-height: 16px; font-weight: 600; letter-spacing: 0.02em;
  text-decoration: none;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.ocz-nav__lien:hover { background: rgba(179, 200, 232, 0.12); color: #fff; }
.ocz-nav__lien--actif {
  background: rgba(102, 175, 254, 0.18);
  border-left-color: var(--ocz-secondary-container);
  color: #fff;
}
.ocz-nav__icone { flex: none; }
.ocz-nav__libelle { flex: 1; }
.ocz-nav__pastille {
  background: var(--ocz-succes-accent); color: #06251b;
  font-size: 10px; font-weight: 700; padding: 0.125rem 0.375rem;
  border-radius: var(--ocz-rayon-controle);
}

.ocz-sidebar__pied {
  padding: 1rem 0.75rem;
  border-top: 1px solid rgba(196, 198, 206, 0.15);
}
.ocz-sidebar__deconnexion {
  display: flex; align-items: center; gap: 0.75rem; width: 100%;
  padding: 0.5rem 1rem; background: none; border: 0; cursor: pointer;
  color: rgba(179, 200, 232, 0.85);
  font-size: 12px; font-weight: 600; letter-spacing: 0.02em; text-align: left;
  border-radius: var(--ocz-rayon-controle);
}
.ocz-sidebar__deconnexion:hover { background: rgba(179, 200, 232, 0.12); color: #fff; }

.ocz-corps {
  margin-left: var(--ocz-largeur-sidebar);
  display: flex; flex-direction: column; min-height: 100vh;
  /* `min-width: 0` — sans lui, un enfant garde sa largeur INTRINSEQUE et refuse
     de retrecir : un tableau large pousse alors toute la colonne, et la PAGE
     deborde horizontalement malgre l'enveloppe defilante du tableau. Constate
     sur l'ecran des contacts en 390 px : 790 px de large pour 390 visibles. */
  min-width: 0;
}

.ocz-topbar {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  height: 64px; padding: 0 var(--ocz-padding-conteneur);
  background: var(--ocz-surface);
  border-bottom: 1px solid var(--ocz-outline-variant);
}
.ocz-topbar__titre { font-size: 24px; line-height: 32px; font-weight: 600; }
.ocz-topbar__actions { display: flex; align-items: center; gap: 1rem; }


.ocz-identite {
  display: flex; align-items: center; gap: 0.75rem;
  padding-left: 1rem; border-left: 1px solid var(--ocz-outline-variant);
}
.ocz-identite__avatar {
  width: 36px; height: 36px; flex: none;
  display: flex; align-items: center; justify-content: center;
  background: var(--ocz-primary-container); color: #fff;
  font-size: 13px; font-weight: 700; border-radius: var(--ocz-rayon-pill);
}
.ocz-identite__nom { font-size: 12px; font-weight: 600; letter-spacing: 0.02em; }
.ocz-identite__role { font-size: 10px; color: var(--ocz-on-surface-variant); }

.ocz-contenu {
  flex: 1; padding: var(--ocz-padding-conteneur);
  display: flex; flex-direction: column; gap: var(--ocz-ecart-cartes);
  min-width: 0;                          /* meme raison que `.ocz-corps` */
}
/* Les enfants d'un conteneur en colonne ont `min-width: auto` par defaut : ils
   ne descendent pas sous la largeur de leur contenu. C'est ce qui transforme un
   tableau defilant en debordement de page. */
.ocz-contenu > *, .ocz-carte { min-width: 0; }

/* ── Grille 12 colonnes (DESIGN.md « Layout ») ───────────────────────────── */

.ocz-grille {
  display: grid; gap: var(--ocz-ecart-cartes);
  grid-template-columns: repeat(12, minmax(0, 1fr));
}
.ocz-col-2  { grid-column: span 2; }
.ocz-col-3  { grid-column: span 3; }
.ocz-col-4  { grid-column: span 4; }
.ocz-col-6  { grid-column: span 6; }
.ocz-col-8  { grid-column: span 8; }
.ocz-col-9  { grid-column: span 9; }
.ocz-col-12 { grid-column: span 12; }

/* ── Carte ───────────────────────────────────────────────────────────────── */

.ocz-carte {
  background: var(--ocz-surface-container-lowest);
  border: 1px solid var(--ocz-bordure-carte);
  border-radius: var(--ocz-rayon-carte);
  box-shadow: var(--ocz-ombre-carte);
  display: flex; flex-direction: column;
}
.ocz-carte__entete {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 1rem 1rem 0;
}
.ocz-carte__titre { font-size: 12px; font-weight: 600; letter-spacing: 0.02em; }
.ocz-carte__corps { padding: 1rem; }

/* AMENDEMENT 17.3 — sur ecran etroit, le titre passe AU-DESSUS de son action.
   `space-between` sur une seule ligne partage une largeur qui n'existe plus :
   sur `/contacts` en 390 px, le nom du cabinet tombait a 154 px et se brisait
   sur trois lignes contre le bouton d'enregistrement. En autorisant le retour a
   la ligne et en donnant au titre la largeur entiere, il repasse a 324 px sur
   deux lignes et l'action prend la sienne.
   POURQUOI UNE LARGEUR ICI, alors que la regle des 44 px se declenche sur
   `pointer: coarse` : les deux contraintes ne sont pas de meme nature. La cible
   tactile depend du DOIGT — une tablette large est tactile, un poste etroit ne
   l'est pas. Le retour a la ligne, lui, depend de la PLACE DISPONIBLE, et une
   fenetre de bureau retrecie a le meme probleme qu'un telephone. Chaque regle se
   declenche donc sur ce qui la cause reellement. */
@media (max-width: 640px) {
  .ocz-carte__entete { flex-wrap: wrap; }
  .ocz-carte__entete > .ocz-carte__titre { flex: 1 1 100%; }
}

/* ── Carte KPI ───────────────────────────────────────────────────────────── */

.ocz-kpi {
  background: var(--ocz-surface-container-lowest);
  border: 1px solid var(--ocz-bordure-carte);
  border-radius: var(--ocz-rayon-carte);
  box-shadow: var(--ocz-ombre-carte);
  padding: 1rem;
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; text-align: center; gap: 0.25rem;
}
.ocz-kpi__valeur {
  font-size: 28px; line-height: 34px; font-weight: 700;
  font-variant-numeric: tabular-nums; color: var(--ocz-primary-container);
  white-space: nowrap;                 /* « 284 427,49 € » d'un seul tenant */
}
.ocz-kpi__libelle { font-size: 12px; line-height: 16px; color: var(--ocz-on-surface-variant); }
.ocz-kpi__sous-libelle { font-size: 11px; line-height: 15px; color: var(--ocz-on-surface-variant); }

.ocz-kpi--succes        .ocz-kpi__valeur { color: var(--ocz-succes-texte); }
.ocz-kpi--avertissement .ocz-kpi__valeur { color: var(--ocz-avertissement-texte); }
.ocz-kpi--danger        .ocz-kpi__valeur { color: var(--ocz-danger-texte); }
.ocz-kpi--info          .ocz-kpi__valeur { color: var(--ocz-info-texte); }
.ocz-kpi--neutre        .ocz-kpi__valeur { color: var(--ocz-on-surface); }

/* ── Badge (pill) ────────────────────────────────────────────────────────── */

.ocz-badge {
  display: inline-flex; align-items: center; gap: 0.25rem;
  padding: 0.125rem 0.625rem;
  font-size: 11px; line-height: 18px; font-weight: 700;
  border-radius: var(--ocz-rayon-pill); border: 1px solid transparent;
  white-space: nowrap;
}
.ocz-badge--succes {
  color: var(--ocz-succes-texte); background: var(--ocz-succes-fond);
  border-color: var(--ocz-succes-bordure);
}
.ocz-badge--avertissement {
  color: var(--ocz-avertissement-texte); background: var(--ocz-avertissement-fond);
  border-color: var(--ocz-avertissement-bordure);
}
.ocz-badge--danger {
  color: var(--ocz-danger-texte); background: var(--ocz-danger-fond);
  border-color: var(--ocz-danger-bordure);
}
.ocz-badge--info {
  color: var(--ocz-info-texte); background: var(--ocz-info-fond);
  border-color: var(--ocz-info-bordure);
}
.ocz-badge--neutre {
  color: var(--ocz-neutre-texte); background: var(--ocz-neutre-fond);
  border-color: var(--ocz-neutre-bordure);
}

/* ── Stepper ─────────────────────────────────────────────────────────────── */

.ocz-stepper { display: flex; align-items: flex-start; padding: 0.5rem 0; }
.ocz-etape {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  gap: 0.5rem; position: relative; text-align: center;
}
/* Le trait de liaison part du pastillon precedent. */
.ocz-etape + .ocz-etape::before {
  content: ''; position: absolute; top: 16px; right: 50%; left: -50%;
  height: 2px; background: var(--ocz-outline-variant);
}
.ocz-etape--termine::before,
.ocz-etape--courant::before { background: var(--ocz-succes-accent); }

.ocz-etape__pastille {
  position: relative; z-index: 1;
  width: 32px; height: 32px; flex: none;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--ocz-rayon-pill); border: 2px solid var(--ocz-outline-variant);
  background: var(--ocz-surface-container-lowest);
  color: var(--ocz-on-surface-variant);
  font-size: 13px; font-weight: 700;
}
.ocz-etape__libelle { font-size: 12px; font-weight: 600; letter-spacing: 0.02em; }
.ocz-etape__etat { font-size: 10px; color: var(--ocz-on-surface-variant); }

.ocz-etape--termine .ocz-etape__pastille {
  border-color: var(--ocz-succes-accent); color: var(--ocz-succes-texte);
}
.ocz-etape--courant .ocz-etape__pastille {
  border-color: var(--ocz-secondary); background: var(--ocz-secondary);
  color: #fff; box-shadow: 0 0 0 4px rgba(0, 97, 165, 0.14);
}
.ocz-etape--a_venir .ocz-etape__libelle { color: var(--ocz-on-surface-variant); }

/* ETAPE BLOQUEE — la pastille prenait la teinte NEUTRE, donc une validation
   refusee se dessinait comme une etape « a venir ». Le mot « Bloque » et le
   triangle le disaient ; la pastille disait le contraire, et c'est elle qu'on
   voit en premier en balayant le fil. Un fil qui contredit son propre libelle est
   le defaut G sous une autre forme.
   La couleur SEULE ne porte jamais l'information (AMENDEMENT 9.2) : le triangle
   et le mot restent, l'ambre ne fait que cesser de mentir. Cran assombri, jamais
   la teinte vive — la pastille porte du texte. */
.ocz-etape--bloque .ocz-etape__pastille {
  /* CRAN ASSOMBRI POUR LA BORDURE, mesure et non choisi : la teinte vive rendait
     2,03:1 sur le fond de page, sous le seuil de 3:1 d'un contour porteur de
     sens. Le cran assombri rend 4,76:1. C'est l'AMENDEMENT 9.2 applique au
     contour et pas seulement au texte — cette pastille porte un glyphe. */
  border-color: var(--ocz-avertissement-texte);
  color: var(--ocz-avertissement-texte);
  background: var(--ocz-avertissement-fond);
}

/* ── Tableau ─────────────────────────────────────────────────────────────── */

/* `position: relative` N'EST PAS DECORATIF ICI — c'est ce qui rend l'enveloppe
   BLOC CONTENEUR, et sans quoi son defilement ne retient pas tout.
   Un descendant en `position: absolute` se place par rapport au premier ancetre
   POSITIONNE, pas par rapport au premier ancetre qui defile. Faute d'ancetre
   positionne, les libelles `.ocz-invisible` — le texte reserve aux lecteurs
   d'ecran, pose en absolu a l'interieur d'un tableau de 1 116 px — se
   rattachaient au document et l'etiraient a 790 px pour 390 visibles, EN
   TRAVERSANT une enveloppe qui defilait pourtant correctement (356 px de large,
   1 116 px de contenu). D'ou l'enquete : le corps de page mesurait 390, la
   racine 790 — donc rien dans le flux ne debordait, et le coupable etait hors
   flux. L'enveloppe, longtemps soupconnee, etait innocente. */
.ocz-tableau-enveloppe { width: 100%; overflow-x: auto; position: relative; }

/* AFFORDANCE DE DEFILEMENT — un ombrage au bord droit tant qu'il reste du
   contenu. Sans lui, rien ne distingue un tableau complet d'un tableau dont 68 %
   est hors champ : le lecteur ne sait pas qu'il ne voit pas tout, ce qui est pire
   que de le voir mal. La classe est posee par le socle UNIQUEMENT quand la
   region deborde reellement (voir `static/js/ocealiz.js`), donc elle disparait
   d'elle-meme sur un ecran large ou apres rotation.
   Le contour de focus reste visible : cette region est un arret de tabulation. */
.ocz-tableau-enveloppe--defile {
  background-image: linear-gradient(to left,
    rgba(17, 24, 39, 0.10), rgba(17, 24, 39, 0));
  background-position: right center;
  background-size: 1.75rem 100%;
  background-repeat: no-repeat;
  background-attachment: local, scroll;
}
.ocz-tableau-enveloppe:focus-visible {
  outline: 2px solid var(--ocz-secondary);
  outline-offset: 2px;
}
.ocz-tableau { width: 100%; border-collapse: collapse; font-size: 13px; }
.ocz-tableau th {
  padding: 0.5rem 0.75rem; text-align: left;
  font-size: 11px; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--ocz-on-surface-variant);
  background: var(--ocz-surface-container-low);
  border-bottom: 1px solid var(--ocz-outline-variant);
  white-space: nowrap;
}
/* TABLEAU DENSE — modificateur du socle, et non une surcharge de page.
   Deux ecrans a huit et neuf colonnes portaient EXACTEMENT les memes deux regles
   dans leur propre bloc de style : en-tetes qui reviennent a la ligne, cellules
   resserrees. Deux redactions de la meme intention finissent par diverger, et la
   divergence se lit a l'ecran sans qu'on sache pourquoi deux tableaux ne se
   ressemblent plus. Le besoin est reel — le socle le sert donc, une fois. */
.ocz-tableau--dense thead th { white-space: normal; }
.ocz-tableau--dense td,
.ocz-tableau--dense tbody th { padding: 0.5rem; }

/* Un statut ne se coupe jamais en deux lignes : « En attente » sur deux lignes
   se lit comme deux informations. Ecrit dans deux gabarits, donc ici. */
.ocz-cellule-statut { white-space: nowrap; }

.ocz-tableau td {
  padding: 0.625rem 0.75rem;
  border-bottom: 1px solid rgba(196, 198, 206, 0.35);
}
.ocz-tableau tbody tr:last-child td { border-bottom: 0; }
.ocz-tableau tbody tr:hover { background: var(--ocz-surface-container-low); }
.ocz-tableau__vide {
  padding: 1.5rem 0.75rem; text-align: center;
  color: var(--ocz-on-surface-variant);
}

/* ── Alerte ──────────────────────────────────────────────────────────────── */

.ocz-alerte {
  display: flex; gap: 0.75rem; padding: 0.875rem 1rem;
  border: 1px solid transparent; border-left-width: 4px;
  border-radius: var(--ocz-rayon-carte);
}
.ocz-alerte__icone { flex: none; margin-top: 1px; }
.ocz-alerte__titre { font-size: 13px; font-weight: 700; margin-bottom: 0.25rem; }
.ocz-alerte__corps { font-size: 13px; line-height: 19px; }
.ocz-alerte__corps > p:last-child { margin-bottom: 0; }
.ocz-alerte__action { margin-top: 0.625rem; }

.ocz-alerte--info {
  background: var(--ocz-info-fond); border-color: var(--ocz-info-bordure);
  border-left-color: var(--ocz-info-accent); color: var(--ocz-info-texte);
}
.ocz-alerte--succes {
  background: var(--ocz-succes-fond); border-color: var(--ocz-succes-bordure);
  border-left-color: var(--ocz-succes-accent); color: var(--ocz-succes-texte);
}
.ocz-alerte--avertissement {
  background: var(--ocz-avertissement-fond); border-color: var(--ocz-avertissement-bordure);
  border-left-color: var(--ocz-avertissement-accent); color: var(--ocz-avertissement-texte);
}
.ocz-alerte--danger {
  background: var(--ocz-danger-fond); border-color: var(--ocz-danger-bordure);
  border-left-color: var(--ocz-danger-accent); color: var(--ocz-danger-texte);
}

/* ── Alerte ecartable ───────────────────────────────────────────────────────
   ECARTER REPLIE, N'EFFACE PAS. Le bandeau ecarte garde sa ligne de titre et un
   bouton « Reafficher » : un motif de blocage reste signale, et il est a un clic.
   Sans cela, un avertissement qui est en realite un refus (cf. « Lancement
   indisponible ») pourrait disparaitre completement de l'ecran. */

.ocz-alerte__texte { flex: 1 1 auto; min-width: 0; }

.ocz-alerte__fermer,
.ocz-alerte__rouvrir {
  flex: none; align-self: flex-start; margin-left: auto;
  background: none; border: 0; color: inherit; cursor: pointer;
  border-radius: var(--ocz-rayon-controle);
  /* 44 px, LA REGLE QUE LE PRODUIT S'EST DONNEE A LUI-MEME — « sous le minimum
     de 44px, on clique l'une pour l'autre ». Premiere version livree a 36x36 :
     la suite mobile l'a attrapee sur quatre ecrans. La cible grandit, PAS le
     dessin : la croix reste a 16 px, les marges negatives rendent a la boite la
     place que le remplissage lui prend. Une commande discrete doit rester
     atteignable au doigt ; discret ne veut pas dire petit. */
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px;
}
.ocz-alerte__fermer { margin: -0.75rem -0.75rem -0.75rem auto; line-height: 0; }
.ocz-alerte__fermer:hover, .ocz-alerte__rouvrir:hover { opacity: 0.7; }

.ocz-alerte__rouvrir {
  display: none; font: inherit; font-size: 12px; text-decoration: underline;
  padding: 0 0.25rem; margin: -0.625rem -0.5rem -0.625rem auto;
}
.ocz-alerte__trace { display: none; font-size: 13px; font-weight: 700; }

.ocz-alerte--ecartee { padding-top: 0.5rem; padding-bottom: 0.5rem; }
.ocz-alerte--ecartee .ocz-alerte__corps,
.ocz-alerte--ecartee .ocz-alerte__action,
.ocz-alerte--ecartee .ocz-alerte__fermer { display: none; }
.ocz-alerte--ecartee .ocz-alerte__rouvrir { display: inline-flex; }
.ocz-alerte--ecartee .ocz-alerte__trace { display: block; }
.ocz-alerte--ecartee .ocz-alerte__titre { margin-bottom: 0; }

/* ── Zone de depot ───────────────────────────────────────────────────────── */

.ocz-depot {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.5rem; padding: 2.5rem 1.5rem; text-align: center;
  border: 2px dashed var(--ocz-outline-variant);
  border-radius: var(--ocz-rayon-carte);
  background: #f5f9ff;   /* bleu tres clair, DESIGN.md « File Upload Zones » */
  transition: border-color 0.15s ease, background-color 0.15s ease;
}
.ocz-depot:hover,
.ocz-depot--survol {
  border-color: var(--ocz-secondary-container);
  background: var(--ocz-secondary-fixed);
}
.ocz-depot__pastille {
  width: 48px; height: 48px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--ocz-rayon-pill);
  background: var(--ocz-secondary-fixed);
  color: var(--ocz-on-secondary-fixed-variant);
  margin-bottom: 0.5rem;
}
.ocz-depot__titre { font-size: 18px; line-height: 24px; font-weight: 600; }
.ocz-depot__sous-titre { font-size: 12px; color: var(--ocz-on-surface-variant); }
.ocz-depot__champ { display: none; }

/* ── Etat vide ───────────────────────────────────────────────────────────── */

.ocz-etat-vide {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.75rem; padding: 2.5rem 1.5rem; text-align: center;
  color: var(--ocz-on-surface-variant);
}
.ocz-etat-vide__icone {
  width: 56px; height: 56px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--ocz-rayon-pill);
  background: var(--ocz-surface-container);
  color: var(--ocz-outline);
}
.ocz-etat-vide__message { font-size: 14px; }

/* ── Boutons et champs ───────────────────────────────────────────────────── */

.ocz-bouton {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  padding: 0.625rem 1.25rem; border-radius: var(--ocz-rayon-controle);
  border: 1px solid transparent; cursor: pointer; text-decoration: none;
  font-size: 13px; font-weight: 600; letter-spacing: 0.01em;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
.ocz-bouton--principal {
  background: var(--ocz-primary-container); color: #fff;
  box-shadow: var(--ocz-ombre-action);
}
.ocz-bouton--principal:hover { background: #16375c; }
.ocz-bouton--secondaire {
  background: var(--ocz-surface-container-lowest);
  border-color: var(--ocz-outline-variant); color: var(--ocz-on-surface);
}
.ocz-bouton--secondaire:hover { background: var(--ocz-surface-container-low); }
.ocz-bouton--danger { background: var(--ocz-error); color: #fff; }
.ocz-bouton[disabled],
.ocz-bouton[aria-disabled='true'] { opacity: 0.5; cursor: not-allowed; }

/* LE VOILE EST MASQUE PAR DEFAUT, ET C'EST LA REGLE QUI MANQUAIT.
   Son `display: none` vivait DANS la requete media du mobile : au-dela de
   1280 px, la regle ne s'appliquait pas, donc le bouton existait — invisible mais
   ATTEIGNABLE AU CLAVIER, avec son etiquette « Fermer le menu » alors qu'aucun
   menu n'est ouvert. Quatorze pages avec un arret de tabulation qui ment.
   Une regle ecrite dans une requete media ne protege que la largeur qu'elle
   nomme : ce qui doit valoir PARTOUT se declare a la racine. Releve par le juge
   d'apparence du round 2. */
.ocz-voile { display: none; }

/* ── Case a cocher — la cible grandit AU DOIGT, jamais au poste fixe ────────── */
/*
   POURQUOI CETTE CLASSE EXISTE. La case « Envoyer ? » de l'ecran des resultats
   mesurait 13x13 px, avec une etiquette reduite a 1x1 (texte pour lecteurs
   d'ecran). Or c'est LE controle qui decide qui recoit un email : le plus
   consequent de l'application apres l'echappatoire, et le plus petit.
   La regle des 44 px du socle (AMENDEMENT 17.3) ne le couvrait pas — elle nomme
   des boutons, des liens et des entrees de navigation, pas les cases. Neuvieme
   fois aujourd'hui qu'une regle protege ce qu'elle nomme au lieu de son
   invariant : ici l'invariant est « toute cible d'un geste consequent ».

   CE QUE CETTE REGLE COUTE, ET POURQUOI C'EST LE BON ARBITRAGE. Sous pointeur
   grossier, la case occupe 44 px : c'est visiblement gros dans un tableau dense.
   L'alternative — garder 18 px et etendre la zone cliquable par un
   pseudo-element — est fragile sur un `input`, dont le rendu des pseudo-elements
   varie selon les moteurs. Entre une cible sure et un peu grande, et une cible
   elegante qui depend du navigateur, on prend la sure : ce controle envoie des
   courriels a des cabinets.
   Au pointeur fin, rien ne change : la souris n'a pas ce probleme, et grossir la
   case abimerait la densite d'un tableau de huit colonnes pour personne.
*/
.ocz-case {
  width: 1.125rem; height: 1.125rem; flex: none;
  accent-color: var(--ocz-secondary);
  cursor: pointer;
}

/* L'ETIQUETTE QUI PORTE UNE CASE — la case, puis son texte, sur une ligne.
   Elle etait ECRITE sans etre DEFINIE : `resultats.html` posait deja
   `.ocz-case__etiquette` sur ses labels d'envoi, et aucune regle du socle ne lui
   repondait. Faute de quoi, un gabarit qui voulait ce comportement mettait
   `.ocz-case` — la regle de l'INPUT — sur le <label> : le libelle heritait alors
   d'une boite de 18x18 px et son texte debordait par-dessus le paragraphe
   suivant. Constate a l'ecran sur le choix du marche, sur les deux ecrans qui
   lancent. */
.ocz-case__etiquette {
  display: flex; gap: 0.625rem; align-items: flex-start;
  margin: 0.375rem 0; cursor: pointer;
}

/* Le groupe de marches du lancement. Un <fieldset> apporte sa bordure et son
   retrait par defaut : ils sont remis a zero, la carte qui l'entoure porte deja
   le cadre. La <legend> reprend `.ocz-filtre__etiquette`, l'etiquette courte du
   socle, plutot qu'une seconde ecriture de la meme chose. */
.ocz-portee { border: 0; margin: 0 0 0.5rem; padding: 0; min-width: 0; }


.ocz-champ {
  width: 100%; padding: 0.5rem 0.75rem; font: inherit;
  color: var(--ocz-on-surface);
  background: var(--ocz-surface-container-lowest);
  border: 1px solid var(--ocz-outline-variant);
  border-radius: var(--ocz-rayon-controle);
}
.ocz-champ:focus { border-color: var(--ocz-secondary); }
.ocz-etiquette {
  display: block; margin-bottom: 0.25rem;
  font-size: 12px; font-weight: 600; letter-spacing: 0.02em;
}

/* ── Choix d'un cabinet : recherche greffee sur un select natif ───────────────

   Le `<select>` natif reste dans le document — masque, il porte toujours la
   valeur soumise. Ce qui suit n'habille QUE la greffe posee par le socle
   (`static/js/ocealiz.js`). Sans script, aucune de ces regles ne s'applique a
   quoi que ce soit : l'ecran garde le champ d'avant.

   POURQUOI LA LISTE SORT DU FLUX. Inseree dans le flux, elle pousserait toute
   la carte vers le bas a chaque frappe : le texte qu'on lisait descend sous le
   curseur, et l'apercu du message saute de 200 px pendant qu'on cherche. Elle
   flotte donc au-dessus, et c'est aussi la raison du `z-index` : sans lui, la
   carte suivante de la grille passe par-dessus les dernieres entrees. */

/* Le champ et son bouton sur une rangee. PAS `.ocz-ligne-actions`, qui centre
   verticalement : le bouton s'y alignerait sur le milieu du bloc etiquette +
   champ, donc a cheval sur l'etiquette. Ici les deux posent sur la meme ligne
   de base. */
.ocz-combo-ligne {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem;
  margin-top: 0.25rem;
}
.ocz-combo-ligne .ocz-combo { flex: 1 1 18rem; }

.ocz-combo__zone { position: relative; }

/* La greffe reprend `.ocz-champ` : meme bordure, meme rayon, meme cible
   tactile. Un champ de recherche qui ne ressemblerait pas aux autres controles
   de l'ecran se lirait comme un element etranger. */
.ocz-combo__saisie { width: 100%; }

.ocz-combo__liste {
  position: absolute; top: calc(100% + 2px); left: 0; right: 0; z-index: 20;
  margin: 0; padding: 0.25rem; list-style: none;
  /* 17rem : environ six entrees visibles. Assez pour juger d'un coup d'oeil si
     la recherche a mordu, jamais assez pour couvrir la carte entiere. */
  max-height: 17rem; overflow-y: auto;
  background: var(--ocz-surface-container-lowest);
  border: 1px solid var(--ocz-outline-variant);
  border-radius: var(--ocz-rayon-controle);
  box-shadow: var(--ocz-ombre-action);
}

.ocz-combo__option {
  display: flex; align-items: center;
  padding: 0.5rem 0.625rem;
  border-radius: var(--ocz-rayon-controle);
  color: var(--ocz-on-surface); cursor: pointer;
}
.ocz-combo__option:hover { background: var(--ocz-surface-container-low); }

/* L'ENTREE ACTIVE SE VOIT SANS LE FOCUS. Au clavier, le focus reste dans le
   champ de saisie : rien dans le dessin natif ne dirait quelle entree Entree
   va choisir. Un aplat porteur, pas un simple gris — c'est l'information la
   plus importante de la liste. */
.ocz-combo__option--actif {
  background: var(--ocz-primary-container); color: #ffffff;
}

.ocz-combo__vide {
  position: absolute; top: calc(100% + 2px); left: 0; right: 0; z-index: 20;
  margin: 0; padding: 0.625rem;
  background: var(--ocz-surface-container-lowest);
  border: 1px solid var(--ocz-outline-variant);
  border-radius: var(--ocz-rayon-controle);
  color: var(--ocz-on-surface-variant); font-size: 13px;
}

/* ── Page de connexion ───────────────────────────────────────────────────── */

.ocz-connexion {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: 1.5rem; background: var(--ocz-primary-container);
}
.ocz-connexion__panneau {
  width: 100%; max-width: 380px; padding: 2rem;
  background: var(--ocz-surface-container-lowest);
  border-radius: var(--ocz-rayon-carte);
  box-shadow: 0 12px 32px rgba(0, 15, 35, 0.35);
}
.ocz-connexion__marque {
  display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.25rem;
  color: var(--ocz-primary-container);
  font-size: 26px; font-weight: 700; letter-spacing: -0.02em;
}

/* ── Bouton de repli de la sidebar (< 1024px) ────────────────────────────── */

.ocz-bascule-nav { display: none; }

@media (max-width: 1024px) {
  .ocz-bascule-nav {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; padding: 0; cursor: pointer;
    background: none; border: 1px solid var(--ocz-outline-variant);
    border-radius: var(--ocz-rayon-controle); color: var(--ocz-on-surface);
  }
  .ocz-sidebar {
    transform: translateX(-100%);
    transition: transform 0.2s ease;
    box-shadow: 0 0 40px rgba(0, 15, 35, 0.4);
  }
  .ocz-page--nav-ouverte .ocz-sidebar { transform: translateX(0); }
  .ocz-corps { margin-left: 0; }
  .ocz-voile {
    position: fixed; inset: 0; z-index: 35;
    background: rgba(0, 15, 35, 0.45); border: 0;
  }
  .ocz-page--nav-ouverte .ocz-voile { display: block; }
  .ocz-grille > [class*='ocz-col-'] { grid-column: span 6; }
  /* ... SAUF CE QUI EST DEJA PLEINE LARGEUR (defaut UI 2 du round 4).
     Le selecteur d'attribut ci-dessus ramenait TOUTES les colonnes a la moitie,
     `ocz-col-12` comprise : a 768 px de fenetre, la grille des envois de
     `/resultats` vivait dans 318 px et cachait 69 % de sa largeur — non par
     manque de place, mais par choix de gabarit. Une colonne qui occupait deja
     toute la grille n'a rien a reduire ; les grandes (8 et 9) passent pleine
     largeur plutot qu'a la moitie, sinon on economise sur celles qui ont le plus
     de contenu. */
  .ocz-grille > .ocz-col-8,
  .ocz-grille > .ocz-col-9,
  .ocz-grille > .ocz-col-12 { grid-column: span 12; }
  .ocz-identite__textes { display: none; }
}

@media (max-width: 640px) {
  .ocz-grille > [class*='ocz-col-'] { grid-column: span 12; }
  .ocz-contenu { padding: 1rem; }
  .ocz-topbar__titre { font-size: 16px; line-height: 22px; }
  .ocz-stepper { flex-direction: column; align-items: stretch; gap: 0.75rem; }
  .ocz-etape { flex-direction: row; text-align: left; gap: 0.75rem; }
  .ocz-etape + .ocz-etape::before { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}

/* ── Utilitaires de la page de demonstration ─────────────────────────────── */

.ocz-demo__section { margin-bottom: var(--ocz-marge-section); }
.ocz-demo__titre {
  font-size: 18px; font-weight: 600; margin-bottom: 0.75rem;
  padding-bottom: 0.5rem; border-bottom: 1px solid var(--ocz-outline-variant);
}
.ocz-demo__rangee { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }

/* ============================================================================
   COMPOSANTS PROMUS DEPUIS LES ECRANS
   ----------------------------------------------------------------------------
   Sept ecrans metier avaient redefini, chacun dans son bloc <style> local, les
   MEMES classes : `.ocz-entete-ecran` (17 usages), `.ocz-pagination` (20),
   `.ocz-interrupteur` (10), `.ocz-squelette` (9), `.ocz-filtres` (9),
   `.ocz-jauge` (7), `.ocz-marche` (5), `.ocz-groupe` (5), `.ocz-segments` (4),
   `.ocz-provenance` (4), `.ocz-kpi--accent` (4). Quand tous les ecrans
   redefinissent la meme chose, ce n'est pas un besoin particulier : c'est un
   manque du socle.

   REGLE DE REPRISE : les selecteurs et la structure de balisage ci-dessous sont
   ceux que les pages ecrivent DEJA. La passe de cablage doit pouvoir supprimer
   un bloc <style> local sans toucher a une seule ligne de HTML. Quand deux pages
   divergeaient, la forme la plus riche est retenue et l'ecart est note en
   commentaire.

   COULEURS : aucun jeton invente. Seuls les `--ocz-*` existants sont employes,
   et le blanc pur pour du texte sur aplat navy. Les jetons `-accent` (dont
   l'orange #f59e0b de la maquette, 2,15:1 sur blanc) ne portent JAMAIS de texte
   (AMENDEMENT 9.2) ; `--ocz-outline` (4,48:1 sur blanc) ne sert qu'aux traits.
   ========================================================================== */

/* ── En-tete d'ecran ─────────────────────────────────────────────────────────
   Le compteur d'elements vit dans le SOUS-TITRE, jamais dans la barre
   superieure (AMENDEMENT 3.4).

   DIVERGENCE ARBITREE — titre : cinq ecrans ecrivent `ocz-entete-ecran__titre`,
   deux emploient l'echelle `ocz-headline-md`. Les deux restent valides.
   DIVERGENCE ARBITREE — sous-titre : cinq ecrans ecrivent
   `ocz-entete-ecran__sous-titre`, deux `ocz-sous-titre`. Les deux sont tenus.
   DIVERGENCE ARBITREE — alignement : deux ecrans demandaient `flex-end`. Retenu
   `flex-start` : avec `flex-end`, un sous-titre sur deux lignes fait descendre
   le bouton d'action au bas du bloc, loin de son titre.  */

.ocz-entete-ecran {
  display: flex; flex-wrap: wrap;
  align-items: flex-start; justify-content: space-between;
  gap: 1rem; margin: 0 0 var(--ocz-ecart-cartes);
}
.ocz-entete-ecran__titre {
  font-size: 24px; line-height: 32px; font-weight: 700; margin: 0;
}
.ocz-entete-ecran__sous-titre,
.ocz-sous-titre {
  margin: 0.25rem 0 0; font-size: 13px; line-height: 18px;
  color: var(--ocz-on-surface-variant);
}
.ocz-entete-ecran__actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem;
}

/* ── Pagination ──────────────────────────────────────────────────────────────
   DIVERGENCE ARBITREE : deux ecrans nomment la liste `__pages`, deux la nomment
   `__liste` et ajoutent `__ellipse`. Les deux noms partagent la meme regle : ni
   les uns ni les autres n'ont a changer leur HTML.
   Cible tactile portee de 32px a 44px (correction M6) : 2rem etait sous le
   seuil, sur un ecran ou l'on change de page a repetition.  */

.ocz-pagination {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 0.75rem;
  padding: 0.75rem 1rem;
  border-top: 1px solid var(--ocz-bordure-carte);
}
.ocz-pagination__resume { margin: 0; }
.ocz-pagination__pages,
.ocz-pagination__liste {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem;
  list-style: none; margin: 0; padding: 0;
}
.ocz-pagination__lien {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px; padding: 0 0.5rem;
  border-radius: var(--ocz-rayon-controle);
  border: 1px solid var(--ocz-outline-variant);
  color: var(--ocz-on-surface); text-decoration: none;
  font-weight: 600; font-variant-numeric: tabular-nums;
}
.ocz-pagination__lien:hover { background: var(--ocz-surface-container-low); }
.ocz-pagination__lien[aria-current='page'] {
  background: var(--ocz-primary-container);
  border-color: var(--ocz-primary-container);
  color: #fff;
}
.ocz-pagination__ellipse {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px;
  color: var(--ocz-on-surface-variant);
}

/* ── Rangee de cartes d'indicateur ───────────────────────────────────────────
   La grille 12 colonnes ne tombe pas juste a CINQ cartes : `span 2` laisse un
   trou, `span 3` renvoie la cinquieme seule a la ligne. Un flex qui s'etire
   rend des cartes d'egale largeur quel qu'en soit le nombre.  */

.ocz-rangee-kpi {
  display: flex; flex-wrap: wrap; gap: var(--ocz-ecart-cartes);
}
.ocz-rangee-kpi > * { flex: 1 1 160px; min-width: 0; }

/* ── Tuile d'indicateur cliquable ────────────────────────────────────────────
   Le survol seul ne suffit pas : au clavier comme au tactile il n'existe pas.
   D'ou un focus visible et une hauteur de cible d'au moins 44px.  */

.ocz-kpi--lien {
  min-height: 44px; text-decoration: none; color: inherit; cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease,
              box-shadow 0.15s ease;
}
.ocz-kpi--lien:hover {
  border-color: var(--ocz-secondary);
  background: var(--ocz-surface-container-low);
  box-shadow: var(--ocz-ombre-action);
}
.ocz-kpi--lien:focus-visible {
  outline: 2px solid var(--ocz-secondary); outline-offset: 2px;
}

/* Accent lateral d'une carte d'indicateur. Il DOUBLE une information deja
   portee par le libelle : la couleur n'est jamais le seul porteur de sens. */
.ocz-kpi--accent {
  align-items: flex-start; text-align: left;
  border-left: 4px solid var(--ocz-outline-variant);
}
.ocz-kpi--accent.ocz-kpi--succes        { border-left-color: var(--ocz-succes-accent); }
.ocz-kpi--accent.ocz-kpi--avertissement { border-left-color: var(--ocz-avertissement-accent); }
.ocz-kpi--accent.ocz-kpi--danger        { border-left-color: var(--ocz-danger-accent); }
.ocz-kpi--accent.ocz-kpi--info          { border-left-color: var(--ocz-info-accent); }

/* ── Progression et jauge ────────────────────────────────────────────────────
   Deux ecrans employaient `<progress>` nu, faute de classe partagee : la barre
   gardait alors l'apparence du systeme d'exploitation, hors charte. Les regles
   de moteur sont obligatoires — sans elles, `background` n'a aucun effet.  */

progress.ocz-progression {
  -webkit-appearance: none; appearance: none;
  display: block; width: 100%; height: 8px; border: 0;
  border-radius: var(--ocz-rayon-pill);
  background: var(--ocz-surface-container);
  overflow: hidden;
}
progress.ocz-progression::-webkit-progress-bar {
  background: var(--ocz-surface-container);
  border-radius: var(--ocz-rayon-pill);
}
progress.ocz-progression::-webkit-progress-value {
  background: var(--ocz-secondary); border-radius: var(--ocz-rayon-pill);
}
progress.ocz-progression::-moz-progress-bar {
  background: var(--ocz-secondary); border-radius: var(--ocz-rayon-pill);
}
progress.ocz-progression--succes::-webkit-progress-value { background: var(--ocz-succes-accent); }
progress.ocz-progression--succes::-moz-progress-bar      { background: var(--ocz-succes-accent); }
progress.ocz-progression--danger::-webkit-progress-value { background: var(--ocz-danger-accent); }
progress.ocz-progression--danger::-moz-progress-bar      { background: var(--ocz-danger-accent); }

/* Jauge en ligne : meme lecture, mais dans une cellule de tableau, ou un
   `<progress>` serait trop haut et trop bavard pour le lecteur d'ecran (la
   valeur est deja ecrite en toutes lettres a cote). */
.ocz-jauge {
  display: block; position: relative; height: 6px; margin-top: 0.25rem;
  border-radius: var(--ocz-rayon-pill);
  background: var(--ocz-surface-container);
  overflow: hidden;
}
.ocz-jauge__barre {
  display: block; height: 100%; max-width: 100%;
  border-radius: var(--ocz-rayon-pill);
  background: var(--ocz-secondary);
}
.ocz-jauge__barre--succes        { background: var(--ocz-succes-accent); }
.ocz-jauge__barre--info          { background: var(--ocz-info-accent); }
.ocz-jauge__barre--avertissement { background: var(--ocz-avertissement-accent); }
.ocz-jauge__barre--danger        { background: var(--ocz-danger-accent); }
.ocz-jauge__barre--neutre        { background: var(--ocz-outline); }

.ocz-mesure { min-width: 116px; }
.ocz-mesure__valeur { font-weight: 600; font-variant-numeric: tabular-nums; }

/* ── Bascule Actif / Inactif ─────────────────────────────────────────────────
   Un couloir l'a constatee COUPEE a 1280px. Trois causes ecartees ici :
   1. la piste ne se comprime plus (`flex: none`) quel que soit l'espace ;
   2. ses dimensions sont en PIXELS, pas en rem : la course du bouton
      (3 + 16 + 18 = 37px pour une piste de 40px) ne depend plus de l'arrondi
      d'un rem herite d'un conteneur ;
   3. aucune requete de media ne la redimensionne — elle est identique de 390px
      a 1920px, et c'est verifie par un test.
   La zone cliquable couvre toute l'etiquette et fait au moins 44px de haut. */

.ocz-interrupteur {
  position: relative; display: inline-flex; align-items: center; gap: 0.5rem;
  min-height: 44px; cursor: pointer; -webkit-user-select: none; user-select: none;
  font-size: 13px; line-height: 18px; color: var(--ocz-on-surface);
}
.ocz-interrupteur input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; margin: 0; cursor: pointer;
}
.ocz-interrupteur__piste {
  flex: none; position: relative; width: 40px; height: 22px;
  border-radius: var(--ocz-rayon-pill);
  background: var(--ocz-outline);
  transition: background-color 0.15s ease;
}
.ocz-interrupteur__piste::after {
  content: ''; position: absolute; top: 3px; left: 3px;
  width: 16px; height: 16px; border-radius: var(--ocz-rayon-pill);
  background: #fff; transition: transform 0.15s ease;
}
.ocz-interrupteur input:checked + .ocz-interrupteur__piste {
  background: var(--ocz-secondary);
}
.ocz-interrupteur input:checked + .ocz-interrupteur__piste::after {
  transform: translateX(18px);
}
.ocz-interrupteur input:focus-visible + .ocz-interrupteur__piste {
  outline: 2px solid var(--ocz-secondary); outline-offset: 2px;
}
.ocz-interrupteur__libelle { white-space: nowrap; }

/* ── Provenance (AMENDEMENT 4.2) ─────────────────────────────────────────────
   Badge + phrase datee. Cinq valeurs, et elles seules : Referentiel, Fichier,
   Mixte, Historique, Aucune.  */

.ocz-provenance {
  display: inline-flex; align-items: center; gap: 0.35rem; flex-wrap: wrap;
  vertical-align: middle;
}
.ocz-provenance__texte {
  font-size: 12px; line-height: 16px; color: var(--ocz-on-surface-variant);
}
/* Sous un champ de saisie, la provenance passe a la ligne : elle qualifie la
   valeur du dessus, elle ne la prolonge pas. */
td > .ocz-provenance { display: flex; margin-top: 0.3rem; }

/* ── Marche a suivre numerotee (friction F1) ─────────────────────────────────
   Numerotation « 1. » « 2. » portee par un compteur CSS. Les chiffres cercles
   sont abandonnes (AMENDEMENT 9.1) : ils ne figurent pas dans le sous-ensemble
   latin de la police embarquee et s'afficheraient en carre de repli.  */

.ocz-marche { counter-reset: etape; list-style: none; margin: 0; padding: 0; }
.ocz-marche > li {
  counter-increment: etape; position: relative; padding: 0 0 1rem 2.25rem;
}
.ocz-marche > li:last-child { padding-bottom: 0; }
.ocz-marche > li::before {
  content: counter(etape) '.';
  position: absolute; left: 0; top: 0;
  width: 1.6rem; height: 1.6rem; border-radius: var(--ocz-rayon-pill);
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 700;
  color: #fff; background: var(--ocz-primary-container);
}
.ocz-marche__titre { display: block; font-weight: 600; }
.ocz-marche__detail {
  margin: 0.15rem 0 0; font-size: 13px; line-height: 18px;
  color: var(--ocz-on-surface-variant);
}

/* ── Barres de filtres ───────────────────────────────────────────────────────
   DIVERGENCE ARBITREE : deux ecrans employaient une grille `auto-fit
   minmax(190px, 1fr)`, quatre un flex avec un champ de recherche etire. Retenu
   le flex : il reproduit le comportement de la grille (`flex: 1 1 190px`) TOUT
   en laissant un champ demander plus de place, ce que la grille interdisait.
   `.ocz-filtre` au singulier est la variante a un seul choix (journal).  */

.ocz-filtres {
  display: flex; flex-wrap: wrap; gap: 1rem; align-items: flex-end;
  margin: 0 0 var(--ocz-ecart-cartes);
}
.ocz-filtres > * { flex: 1 1 190px; min-width: 0; }
.ocz-filtres label { display: block; }
.ocz-filtres .ocz-champ { width: 100%; }
.ocz-filtres__recherche { flex: 1 1 18rem; min-width: 12rem; }

.ocz-filtre {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem;
}
.ocz-filtre__etiquette {
  display: block; margin-bottom: 0.25rem;
  font-size: 12px; line-height: 16px; font-weight: 600;
  color: var(--ocz-on-surface-variant);
}
.ocz-filtre__choix {
  font-family: var(--ocz-police); font-size: 14px;
  padding: 0.45rem 0.6rem;
  min-width: min(18rem, 100%); max-width: 100%;
  border: 1px solid var(--ocz-bordure-carte);
  border-radius: var(--ocz-rayon-controle);
  background: var(--ocz-surface-container-lowest);
  color: var(--ocz-on-surface);
}

/* ── Etat de chargement (correction M5) ──────────────────────────────────────
   DIVERGENCE ARBITREE, la plus delicate du lot : cinq ecrans emploient
   `.ocz-squelette` comme UNE barre (`<div class="ocz-squelette" style="width:
   60%">`), deux comme un CONTENEUR de `.ocz-squelette__ligne`. Les deux formes
   doivent tenir sans que personne ne retouche son HTML : `:has()` distingue le
   conteneur de la barre. A defaut de `:has()`, un navigateur ancien rendrait le
   conteneur comme une barre — degradation lisible, jamais une page cassee.  */

.ocz-squelette {
  height: 0.9rem; margin: 0.6rem 0;
  border-radius: var(--ocz-rayon-controle);
  background: var(--ocz-surface-container);
  animation: ocz-pulsation 1.4s ease-in-out infinite;
}
.ocz-squelette:has(> .ocz-squelette__ligne) {
  height: auto; display: grid; gap: 0.5rem;
  background: none; animation: none;
}
.ocz-squelette__ligne {
  height: 42px; border-radius: var(--ocz-rayon-controle);
  background: var(--ocz-surface-container-low);
  animation: ocz-pulsation 1.4s ease-in-out infinite;
}
@keyframes ocz-pulsation {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}

/* ── Zone « copier » ─────────────────────────────────────────────────────────
   Le contenu prêt a coller dans Claude.ai (friction F1). Le retour apres copie
   est un TEXTE, pas une couleur : il est lu par `role="status"`. Le repli quand
   l'API de presse-papier est absente vit dans `static/js/ocealiz.js`.  */

.ocz-copie { display: block; }
.ocz-copie__texte,
.ocz-consigne {
  width: 100%; min-height: 9rem;
  font-family: var(--ocz-police); font-size: 13px; line-height: 1.5;
  padding: 0.75rem; resize: vertical;
  border: 1px solid var(--ocz-bordure-carte);
  border-radius: var(--ocz-rayon-controle);
  background: var(--ocz-surface-container-lowest);
  color: var(--ocz-on-surface);
}
.ocz-copie__actions,
.ocz-ligne-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem;
  margin-top: 0.6rem;
}
.ocz-copie__etat {
  font-size: 12px; line-height: 16px; color: var(--ocz-on-surface-variant);
}
.ocz-copie__etat--fait { color: var(--ocz-succes-texte); font-weight: 600; }

/* ── Cadre d'apercu de document ──────────────────────────────────────────────
   Le corps d'un email est un document ETRANGER : ses styles ne doivent pas se
   meler a ceux de l'application, et il n'a droit ni au script, ni au
   formulaire, ni a la navigation, ni a l'origine partagee (`sandbox` nu).  */

.ocz-apercu__cadre {
  display: block; width: 100%; max-width: 100%; height: 22rem;
  border: 1px solid var(--ocz-bordure-carte);
  border-radius: var(--ocz-rayon-controle);
  background: #fff;
}

/* ── Coupe de l'apercu — un ESTOMPAGE, jamais le seul indice ────────────────── */
/*
   Le cadre de l'apercu tranche la derniere ligne au milieu des glyphes : le
   lecteur ne sait pas s'il manque un mot ou trois paragraphes. Cette enveloppe
   estompe la coupe au lieu de la trancher.

   POURQUOI UNE ENVELOPPE ET PAS LE CADRE LUI-MEME : un `iframe` ne porte pas de
   pseudo-element. Le voile ne peut donc pas vivre sur le cadre — c'est une
   contrainte du navigateur, pas un choix d'architecture.

   ⚠️ CETTE CLASSE EST UN AGREMENT, ET ELLE NE DOIT JAMAIS DEVENIR LE PORTEUR.
   Un degrade n'est pas lisible pour qui ne distingue pas les nuances, disparait
   en contraste force, et ne se lit pas du tout par un lecteur d'ecran. L'ecran
   qui l'emploie porte donc l'information ailleurs — une PHRASE sous le cadre, un
   bouton principal pour ouvrir le message entier, un attribut de titre. C'est
   l'arbitrage rendu par le juge d'apparence du round 2 : la couleur seule ne
   porte jamais l'information. Le couloir qui a demande cette classe l'avait deja
   prevu, et a rendu son ecran correct SANS elle.

   `pointer-events: none` : le voile ne doit intercepter aucun clic — il flotte
   au-dessus d'une zone qui peut contenir des liens.
*/
.ocz-apercu-coupe { position: relative; }

.ocz-apercu-coupe::after {
  content: ''; position: absolute; inset: auto 1px 1px 1px;
  height: 3.5rem; pointer-events: none;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #fff 85%);
  border-radius: 0 0 var(--ocz-rayon-controle) var(--ocz-rayon-controle);
}

/* EN CONTRASTE FORCE, LE VOILE DISPARAIT. Le systeme y remplace les couleurs :
   un degrade devient un aplat opaque, qui masquerait le texte au lieu de
   l'estomper. L'agrement s'efface, la phrase et le bouton restent. */
@media (forced-colors: active) {
  .ocz-apercu-coupe::after { display: none; }
}
.ocz-apercu__meta {
  display: grid; grid-template-columns: max-content 1fr;
  gap: 0.35rem 0.75rem; margin: 0 0 0.75rem; font-size: 14px;
}
.ocz-apercu__meta dt { color: var(--ocz-on-surface-variant); font-weight: 600; }
.ocz-apercu__meta dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.ocz-piece-jointe {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem;
  padding: 0.6rem 0.75rem; margin-bottom: 0.75rem;
  border: 1px dashed var(--ocz-outline-variant);
  border-radius: var(--ocz-rayon-controle);
  background: var(--ocz-surface-container-low);
}
/* L'action se pose a droite sur large, et passe A LA LIGNE sur etroit plutot
   que de deborder : `flex-wrap` ci-dessus la fait descendre, `margin-left:auto`
   ne la pousse a droite que tant qu'il reste de la place. */
.ocz-piece-jointe__action { margin-left: auto; flex-shrink: 0; }

/* ── Groupes, onglets segmentes et menus fins ────────────────────────────── */

.ocz-groupe { margin-bottom: 1.25rem; }
.ocz-groupe:last-child { margin-bottom: 0; }
.ocz-groupe__entete {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.6rem;
  padding: 0 0 0.5rem;
}
.ocz-groupe__titre { margin: 0; font-size: 15px; line-height: 20px; font-weight: 600; }
.ocz-groupe__identifiant {
  font-size: 12px; line-height: 16px; font-variant-numeric: tabular-nums;
  color: var(--ocz-on-surface-variant);
}

.ocz-segments { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.ocz-segments__onglet {
  display: inline-flex; align-items: center; gap: 0.35rem;
  min-height: 36px; padding: 0.375rem 0.875rem;
  border-radius: var(--ocz-rayon-pill);
  border: 1px solid var(--ocz-outline-variant);
  background: var(--ocz-surface-container-lowest);
  color: var(--ocz-on-surface); text-decoration: none;
  font-size: 13px; font-weight: 600;
}
.ocz-segments__onglet:hover { background: var(--ocz-surface-container-low); }
.ocz-segments__onglet[aria-selected='true'] {
  background: var(--ocz-primary-container);
  border-color: var(--ocz-primary-container);
  color: #fff;
}

.ocz-note {
  margin: 0.75rem 0 0; font-size: 13px; line-height: 18px;
  color: var(--ocz-on-surface-variant);
}
.ocz-lien-discret { color: var(--ocz-info-texte); font-weight: 600; }
/* Les actions d'une ligne restent VISIBLES : revelees au survol, elles
   n'existeraient ni au clavier ni au tactile. */
.ocz-actions-ligne { display: inline-flex; flex-wrap: wrap; gap: 0.25rem; }
/* LA classe protectrice : `nowrap` tient « 284 427,49 € » d'un seul tenant, ses
   deux espaces ordinaires comprises. C'est elle que prend une CELLULE de chiffres
   — voir la note de `.ocz-nombre` en haut de feuille pour la distinction. */
.ocz-cellule-nombre { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Le meme `nowrap`, pour un montant EN LIGNE — texte courant, titre — la ou
   `.ocz-cellule-nombre` serait un contresens (pas une cellule) et `.ocz-nombre`
   ne protege pas (repli normal voulu). Poses sur les 2 derniers porteurs du
   symbole € orphelin (precontentieux, round 4 — mini-passe d'integration). */
.ocz-insecable { white-space: nowrap; font-variant-numeric: tabular-nums; }
.ocz-cellule-champ { min-width: 8.5rem; max-width: 13rem; }

/* CELLULE DE MOTIF — une phrase dans une colonne de tableau (defaut UI 2).
   Le motif d'ecart (« Aucune adresse email pour ce cabinet… ») est une PHRASE,
   pas une donnee courte. Serree par les sept autres colonnes, elle se repliait
   sur huit lignes et dictait a la LIGNE ENTIERE une hauteur de 401 px dont 320
   de vide — le cabinet le plus important flottait dans du blanc, et la phrase
   qui causait cela etait hors champ.
   La cellule plafonne donc sa largeur, et le motif est borne a DEUX lignes avec
   le meme signe de troncature que `.ocz-cellule-champ` plus haut : les points de
   suspension avouent qu'il en reste. Rien n'est perdu — la phrase entiere est
   portee par `title` dans le gabarit, et la troncature est purement visuelle,
   donc le lecteur d'ecran lit le texte complet. */
/* LA LARGEUR MINIMALE EST MESUREE, PAS CHOISIE. A 12rem, la table debordait
   encore de 4 px a 1440 px : un defilement de quatre pixels, donc un arret de
   tabulation, pour rien. A 11rem elle tient exactement. En dessous, la phrase
   passe sous deux lignes utiles et la troncature mange le motif. */
.ocz-cellule-motif { min-width: 11rem; max-width: 24rem; }
.ocz-motif-borne {
  display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 2; line-clamp: 2;
  overflow: hidden; text-overflow: ellipsis;
}
/* ELARGIE — une adresse coupee SANS SIGNE se lit comme une adresse complete, et
   l'on valide alors un envoi vers une adresse qu'on n'a jamais vue en entier.
   Mesure de 22rem : « prenom.nom@cabinet-quelque-chose.fr » tient, ce qui couvre
   la forme courante de l'annuaire. */
.ocz-cellule-champ--large { min-width: 14rem; max-width: 22rem; }
.ocz-cellule-champ .ocz-champ { width: 100%; }

/* LE SIGNE DE TRONCATURE, sur le champ lui-meme. `text-overflow` s'applique bien
   a un `input` : le navigateur affiche les points de suspension quand la valeur
   deborde ET que le champ n'a pas le focus — il les retire des qu'on clique
   dedans, ou le defilement natif prend le relais. On ne perd donc AUCUNE
   information : on gagne l'aveu qu'il en reste.
   La valeur entiere est par ailleurs portee par `title` (pose dans le gabarit),
   pour qui survole. Le signe visuel, lui, ne depend d'aucun survol — il faut
   qu'un ecran tactile le montre aussi. */
.ocz-cellule-champ .ocz-champ { text-overflow: ellipsis; }
.ocz-bouton--compact { padding: 0.375rem 0.75rem; white-space: nowrap; }

/* En-tete de LIGNE (`scope="row"`, qui donne au lecteur d'ecran le nom de la
   ligne a chaque cellule). `.ocz-tableau th` est taille pour un en-tete de
   COLONNE : capitales, 11px, fond gris. Applique a une ligne, il criait les
   noms en capitales et grisait la colonne entiere.
   DIVERGENCE ARBITREE : un ecran demandait `nowrap` (numeros de police), un
   autre `normal` (noms de cabinets, qui doivent pouvoir se replier). Retenu
   `normal` ; une cellule de chiffres ajoute `ocz-cellule-nombre`. */
.ocz-tableau tbody th {
  padding: 0.625rem 0.75rem; vertical-align: top;
  font-size: 13px; font-weight: 600; letter-spacing: 0; text-transform: none;
  white-space: normal; color: var(--ocz-on-surface); background: transparent;
  border-bottom: 1px solid rgba(196, 198, 206, 0.35);
}
.ocz-tableau tbody tr:last-child th { border-bottom: 0; }

/* ── Pied de page (AMENDEMENT 9.4) ───────────────────────────────────────────
   Discret, pas un bandeau : texte secondaire sur le fond de la page, separe par
   un simple trait. Il porte le seul acces a `/technique`, volontairement absente
   de la barre laterale. La cible du lien fait 44px de haut malgre sa discretion
   — « discret » qualifie le contraste percu, jamais la taille de la cible.  */

.ocz-pied {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 0.5rem 1rem;
  padding: 0.5rem var(--ocz-padding-conteneur) 1rem;
  border-top: 1px solid var(--ocz-outline-variant);
  margin-top: auto;
}
.ocz-pied__mention {
  margin: 0; font-size: 12px; line-height: 16px;
  color: var(--ocz-on-surface-variant);
}
.ocz-pied__lien {
  display: inline-flex; align-items: center; min-height: 44px;
  font-size: 12px; line-height: 16px; font-weight: 600;
  color: var(--ocz-info-texte);
}

/* ── Cibles tactiles (correction M6) ─────────────────────────────────────────
   Mesure faite sur un viewport tactile de 390x844 : `.ocz-bouton` tombait a
   42px, la bascule de navigation a 40px, la cloche a 38px, la deconnexion a
   36px. Sous le minimum de 44px, on clique l'une pour l'autre.

   POURQUOI `(pointer: coarse)` ET PAS UNE LARGEUR : la contrainte vient du
   DOIGT, pas de l'ecran. Une tablette large est tactile, un portable etroit ne
   l'est pas. Grossir tous les boutons sous 640px aurait abime la densite
   d'information sur un poste fixe redimensionne, sans rien regler sur une
   tablette de 1024px.

   POURQUOI `min-height` ET PAS DU REMPLISSAGE : le remplissage se fait ecraser
   par un contenu court (« OK », une icone seule). `min-height` tient quel que
   soit le contenu. */

/* Etiquette d'echappatoire : la case et sa phrase forment UNE seule cible. Le
   `for` relie les deux, la mise en page vient d'ici plutot que d'un style en
   ligne — une regle de presentation dans un gabarit echappe au socle, et c'est
   ainsi que sept pages avaient fini par redefinir les memes classes. */
.ocz-echappatoire__etiquette {
  display: flex; gap: 0.625rem; align-items: flex-start; margin: 1rem 0;
  cursor: pointer;
}
.ocz-echappatoire__etiquette input { margin-top: 0.25rem; }

@media (pointer: coarse) {
  .ocz-bouton,
  .ocz-bouton--compact,
  .ocz-sidebar__deconnexion,
  .ocz-nav__lien,
  .ocz-segments__onglet,
  .ocz-champ,
  .ocz-filtre__choix,
  /* Les etapes du parcours sont des LIENS : 15 px de haut sur cinq ecrans,
     parce que la regle visait les boutons et la navigation, pas le stepper.
     Meme motif que les gardes de ce projet — une regle protege ce qu'elle
     nomme. */
  .ocz-etape__libelle,
  /* L'etiquette de l'echappatoire : 40 px, quatre de trop peu. C'est la cible
     la plus consequente de l'application — celle qui autorise un traitement sur
     des donnees declarees inexploitables. */
  .ocz-echappatoire__etiquette,
  /* La saisie de recherche et les entrees de sa liste. L'entree de liste est la
     cible la plus exposee du composant : on y designe le cabinet a qui un
     courriel nominatif partira, et deux entrees de 32 px se choisissent l'une
     pour l'autre au doigt. */
  .ocz-combo__saisie,
  /* L'etiquette d'une case : au doigt, on vise le texte, pas la case. Sans
     hauteur, deux marches empiles se choisissent l'un pour l'autre — et le
     marche choisi decide a QUELS cabinets les envois partiront. */
  .ocz-case__etiquette,
  .ocz-combo__option { min-height: 44px; }

  /* Un lien reste en ligne : lui poser une hauteur ne suffit pas, il faut qu'il
     puisse la porter. */
  .ocz-etape__libelle,
  .ocz-echappatoire__etiquette { display: inline-flex; align-items: center; }

  /* 44 px est une SURFACE, pas une hauteur. « Depot », le plus court des libelles
     d'etape, mesurait 36x44 : conforme sur un axe, hors regle sur l'autre — et un
     doigt ne vise pas une ligne. La largeur d'un lien suit son texte, donc la
     regle doit la contraindre explicitement, comme elle le fait deja pour la
     bascule de navigation et la cloche. */
  .ocz-etape__libelle { min-width: 44px; justify-content: center; }

  .ocz-bascule-nav { min-width: 44px; min-height: 44px; }

  /* La case d'envoi rejoint le bloc EXISTANT plutot que d'ouvrir un second :
     deux blocs pour la meme requete media, et la garde du socle ne lit que le
     premier — elle aurait certifie dix regles absentes. Trouve en rouge. */
  .ocz-case { width: 44px; height: 44px; }

  /* Un lien de tableau est du texte en ligne : sans boite, sa cible se limite
     a la hauteur de la ligne. */
  .ocz-lien-discret,
  .ocz-pied__lien {
    display: inline-flex; align-items: center; min-height: 44px;
  }

  /* Deux cibles voisines dans la barre superieure : la cloche et l'identite
     sont l'endroit le plus expose du socle. */
  .ocz-topbar__actions { gap: 1.25rem; }
  .ocz-actions-ligne { gap: 0.5rem; }
}

/* ── Replis ────────────────────────────────────────────────────────────────── */

@media (max-width: 640px) {
  .ocz-entete-ecran__titre { font-size: 20px; line-height: 26px; }
  .ocz-apercu__meta { grid-template-columns: 1fr; }
  .ocz-apercu__cadre { height: 16rem; }
  .ocz-pagination { justify-content: flex-start; }
  .ocz-cellule-champ,
  .ocz-cellule-champ--large { min-width: 7rem; max-width: none; }
}
