/* ---------------------------------------------------------------------------------------------------------------------------------
   LA FEUILLE COMMUNE — charte d'interface V1 (docs/CHARTE-INTERFACE-V1.md, validée par la Direction le 12/10/2026), lot H0.

   Chargée la PREMIÈRE par la coquille du bureau et par celle de l'espace membre : les jetons, la base du texte, et une seule
   définition de chaque composant de la charte. Les feuilles d'écran viennent après et ne gardent que la mise en page propre à leur
   écran (un sélecteur en contexte, « .ma-page .primary-button », y reste permis).
   Règles de la feuille (gardées par test/charte-gardien.test.mjs) :
   - une couleur ne s'écrit qu'en jeton, dans :root ; un composant n'écrit jamais une couleur en dur ;
   - une seule rupture « téléphone » : 760 px (charte § 3) ;
   - legibility.css et mobile.css n'existent plus : leurs règles communes sont ici (la taille de lecture de base et le plancher du
     téléphone), celles d'un écran sont à la fin de la feuille de cet écran.
   --------------------------------------------------------------------------------------------------------------------------------- */

/* § 1 et § 2 — LES JETONS. Les noms de styles.css sont gardés ; ✚ = nouveau avec la charte. */
:root {
  --navy: #173f4d;
  --navy2: #245866;
  --sea: #2f7f8d;
  --sea-strong: #276f7b; /* ✚ le survol du primaire */
  --sea-soft: #e3f5f4; /* ✚ fond teal léger, anneau de focus */
  --ink: #18343c;
  --muted: #5d7079; /* charte § 1 : 5,2 de contraste sur blanc (#6c8086 auparavant : 4,1) */
  --line: #dbe7e8;
  --line-strong: #a9bcc0; /* ✚ le bord du rond « ? » */
  --bg: #f4f8f8;
  --card: #ffffff; /* ✚ fond des cartes, champs, dialogues */
  --on-sea: #ffffff; /* ✚ le texte sur fond teal */
  --amber: #d89b34;
  --purple: #8066a6;
  --purple-soft: #efe8fa; /* ✚ */
  --coral: #d86d5e;
  --green: #2e8d68;
  --radius-card: 12px; /* ✚ cartes, dialogues, tuiles */
  --radius-control: 10px; /* ✚ boutons, champs, menus */
  --radius-pill: 999px; /* ✚ pastilles, puces */
  --shadow: 0 1px 2px rgba(22, 63, 77, .06), 0 4px 14px rgba(22, 63, 77, .05); /* l'ombre légère (0 12px 34px auparavant) */
  --shadow-dialog: 0 30px 90px rgba(13, 45, 54, .28); /* ✚ */
  --focus-ring: 0 0 0 3px var(--sea-soft); /* ✚ § 13 */
  --font-text: "Segoe UI", system-ui, -apple-system, sans-serif; /* ✚ § 4 : Segoe UI seule, Inter retirée (Direction 12/10, point 3) */
  --font-title: Georgia, serif; /* ✚ § 4 : Georgia écrite d'une seule façon */
  --dialog-s: 560px; /* ✚ § 11 : trois largeurs de dialogue */
  --dialog-m: 760px;
  --dialog-l: 940px;
  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 24px; --space-6: 32px; /* ✚ § 3 : l'échelle unique */

  /* § 2 — les états : le texte de la pastille dit l'état en mots, la couleur suit cette table (--state-* est retiré). */
  --pill-ok: #1d6b3a; --pill-ok-bg: #e4f4e9;
  --pill-watch: #7a4b00; --pill-watch-bg: #fff1d6;
  --pill-alert: #a33f35; --pill-alert-bg: #fde7e3; --pill-alert-line: #efb9b2;
  --pill-fact: #4f6166; --pill-fact-bg: #e9eeef;
  --pill-teal: #0f5e63; --pill-teal-bg: var(--sea-soft); /* ✚ la marque : élément choisi, filtre actif */
  --pill-purple: #5a3d8a; --pill-purple-bg: var(--purple-soft); /* ✚ le réservé : ressource virtuelle, cours au centre */

  /* Le bandeau « consultation seule » (cache hors ligne). */
  --offline-bg: #fff1c7; --offline-ink: #6a4a00; --offline-line: #d6a62f;
}

/* § 1 — LE SOMBRE, PRÉPARÉ ET NON ACTIVÉ (Direction 12/10, point 2) : aucune page ne pose data-theme="dark" ; un poste réglé en
   sombre voit les pages en clair, comme avant. L'activer sera un lot à part. */
:root[data-theme="dark"] {
  --navy: #0b1f26;
  --sea: #5fb8c5;
  --sea-soft: #153138;
  --ink: #e6eef1;
  --muted: #9fb3ba;
  --line: #26393f;
  --bg: #0f1b20;
  --card: #16262d;
  --shadow: none;
  --shadow-dialog: 0 30px 90px rgba(0, 0, 0, .6);
}

/* § 3 et § 4 — LA BASE : la boîte, le fond, le texte courant (14 px à l'écran, 16 px au téléphone). */
* { box-sizing: border-box; }
[hidden] { display: none !important; } /* hidden veut dire caché, même sur un bouton en inline-flex (0.50.075) */
html { background: var(--bg); }
body { margin: 0; color: var(--ink); background: var(--bg); font-family: var(--font-text); }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
@media screen {
  /* La fiche de sécurité garde, à l'impression, sa composition compacte : ces tailles ne valent qu'à l'écran. */
  body { font-size: 14px; line-height: 1.45; }
  button, input, select, textarea { font-size: 14px; }
}

/* § 5 — L'EN-TÊTE DE PAGE : sur-titre (la rubrique), titre (h1, Georgia), phrase ; les actions à droite. */
.page-heading { padding: 28px 30px 18px; display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; }
.page-heading h1 { margin: 0; font: 500 clamp(28px, 2.4vw, 32px)/1.15 var(--font-title); letter-spacing: -.02em; }
.eyebrow { margin: 0 0 7px; color: var(--sea); font-size: 12px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; }
/* (lot H1) le gabarit de la coquille (pageHeading) : le titre et sa bulle « ? » côte à côte (la bulle hors du h1, § 10) ; la phrase de F1,
   une ligne, --muted ; une valeur en cours (un compte, une date) sous la phrase ; les actions à droite, retour à la ligne. */
.page-heading-main { min-width: 0; }
.page-title { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.page-sentence { margin: 6px 0 0; max-width: 78ch; color: var(--muted); font-size: 14px; line-height: 1.45; }
.page-status { margin: 4px 0 0; color: var(--muted); font-size: 13px; }
.page-heading .heading-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--space-2); }

/* § 6 — LES BOUTONS : quatre rôles, une hauteur (40 px ; 44 px sous 760 px). */
.primary-button, .secondary-button, .danger-button {
  min-height: 40px; padding: 0 16px; display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  border: 0; border-radius: var(--radius-control); font-size: 14px; font-weight: 800;
}
.primary-button { color: var(--on-sea); background: var(--sea); }
.primary-button:hover { background: var(--sea-strong); }
.secondary-button { color: var(--navy); background: var(--card); border: 1px solid var(--line); }
.danger-button { color: var(--pill-alert); background: var(--card); border: 1px solid var(--pill-alert); } /* bordé (Direction 12/10, point 4) */
.danger-button:hover { background: var(--pill-alert-bg); }
.primary-button:disabled, .secondary-button:disabled, .danger-button:disabled { opacity: .55; cursor: not-allowed; }
.link-button { padding: 0; border: none; background: none; color: var(--sea); text-decoration: none; font-size: inherit; cursor: pointer; }
.link-button:hover { text-decoration: underline; }
/* (charte V1.1, petites suites 50) Le lien-bouton <a class="link-button"> se comporte comme un bouton : inline-flex, l'anneau de focus, et 44 px
   sous 760 px par la règle du téléphone (comme les boutons). */
a.link-button { display: inline-flex; align-items: center; }
a.link-button:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-control); }
/* Le raccourci dans le bouton : « Enregistrer F10 ». */
.key-hint, [data-key-hint]::after {
  display: inline-block; margin-left: 7px; padding: 2px 5px; border-radius: 4px; background: rgba(23, 63, 77, .08); color: inherit;
  font: 700 11px/1.2 var(--font-text); letter-spacing: .02em; opacity: .8; vertical-align: middle; white-space: nowrap;
}
[data-key-hint]::after { content: attr(data-key-hint); }
.primary-button[data-key-hint]::after { background: rgba(255, 255, 255, .22); }
@media (hover: none) and (pointer: coarse) {
  /* Pas de clavier sur un écran tactile : la pastille du raccourci se tait, même posée par une règle d'écran. */
  .key-hint { display: none !important; }
  [data-key-hint]::after { content: none !important; display: none !important; }
}

/* § 7 — CARTES ET TUILES. Une carte qui porte un état : un bord gauche de 4 px dans la couleur de la pastille. */
.card { padding: 16px; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--card); box-shadow: var(--shadow); }
.card.is-ok { border-left: 4px solid var(--pill-ok); }
.card.is-watch { border-left: 4px solid var(--pill-watch); }
.card.is-alert { border-left: 4px solid var(--pill-alert); }
/* (0.90.059, § 9) LE PIED DE FORMULAIRE D'UNE CARTE (maquette .form-foot) : un filet, l'action principale à droite, « Annuler » ou une action
   secondaire à gauche ; les boutons passent à la ligne au téléphone. */
.form-foot { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 10px; margin-top: var(--space-4); padding-top: 14px; border-top: 1px solid var(--line); }
.form-foot > .secondary-button:first-child { margin-right: auto; }
.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
.tile { display: grid; gap: 2px; padding: 14px 16px; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--card); color: var(--ink); text-align: left; }
.tile-value { font-size: 24px; font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums; }
.tile-label { color: var(--muted); font-size: 13px; }
.tile.is-ok .tile-value { color: var(--pill-ok); }
.tile.is-watch .tile-value { color: var(--pill-watch); }
.tile.is-alert .tile-value { color: var(--pill-alert); }
button.tile:hover { border-color: var(--sea); }
.tile.is-selected, .tile[aria-pressed="true"] { border-color: var(--sea); box-shadow: var(--focus-ring); }

/* § 8 — LES TABLEAUX : .sd-table, le tableau de la charte (celui de Paramètres › Assistant). Les tableaux existants (.data-table et
   ses variantes d'écran) gardent leur dessin jusqu'au lot de leur famille (H2-H8) ; la liste en cartes sous 760 px est un choix de
   l'écran (.is-stacked, chaque cellule portant data-label). */
.table-wrap { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.sd-table { width: 100%; border-collapse: collapse; }
.sd-table th { padding: 8px 10px; border-bottom: 1px solid var(--line); text-align: left; }
/* (tas 10, constat 9) le dessin d'en-tête de colonne (11 px, majuscules, grisé) vise les seuls th de thead : une ligne de groupe ou de total
   (th de tbody, tfoot : « Espèces · 3 », « Total ») garde la taille des cellules. */
.sd-table thead th { background: var(--card); color: var(--muted); font-size: 11px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.sd-table td { padding: 10px; border-bottom: 1px solid var(--line); }
.sd-table .num { text-align: right; font-variant-numeric: tabular-nums; }

/* § 9 — LES FORMULAIRES : le libellé au-dessus, un champ de 40 px (44 px sous 760 px), le focus teal. Les champs habillés par
   leur écran font déjà 40 px ; les champs natifs restants prennent ici le bord, le rayon et le fond de la charte (:where, sans
   spécificité : l'habillage d'un écran l'emporte) ; leur hauteur se règle avec le lot de leur famille (H2-H8). */
.form-grid { padding: 20px 24px; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
:where(input:not([type="checkbox"], [type="radio"], [type="file"], [type="range"], [type="color"], [type="hidden"], [type="image"], [type="submit"], [type="button"], [type="reset"]), select, textarea) {
  border: 1px solid var(--line); border-radius: var(--radius-control); background: var(--card);
}
:where(input:not([type="checkbox"], [type="radio"], [type="file"], [type="range"], [type="color"], [type="hidden"], [type="image"], [type="submit"], [type="button"], [type="reset"]), select, textarea):focus-visible {
  outline: none; border-color: var(--sea); box-shadow: var(--focus-ring);
}
.form-hint { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.5; }
.field-error { margin: 4px 0 0; color: var(--pill-alert); font-size: 12px; font-weight: 700; } /* (V1.3 A, § 18) 12 px, gras, le signe « ! » */
.field-error::before { content: "! "; font-weight: 800; }
/* (petites suites 92, R1) « Photo réduite : 0,6 Mo » sous le champ d'une pièce (public/pieces.js) : une information, jamais un blocage. */
.piece-note { display: block; margin: 4px 0 0; color: var(--muted); font-size: 12px; font-weight: 400; }
.is-invalid, [aria-invalid="true"] { border-color: var(--pill-alert); }
/* (charte H2, réflexion 13/10) le champ refusé garde son bord rouge au focus : l'erreur prime sur le teal (bord et anneau). */
:is(input, select, textarea):is(.is-invalid, [aria-invalid="true"]):is(:focus, :focus-visible) { outline: none; border-color: var(--pill-alert); box-shadow: 0 0 0 3px var(--pill-alert-bg); }
/* Les puces de filtre et les choix courts (2 à 5 valeurs). */
.chip { min-height: 32px; padding: 0 12px; display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--line); border-radius: var(--radius-pill); background: var(--card); color: var(--ink); font-size: 13px; font-weight: 700; }
.chip.is-active, .chip[aria-pressed="true"] { border-color: var(--sea); background: var(--sea-soft); color: var(--pill-teal); }
/* Le compteur − / + (nombre de places, de personnes). */
.stepper { display: inline-flex; align-items: center; border: 1px solid var(--line); border-radius: var(--radius-control); background: var(--card); }
.stepper button { width: 40px; min-height: 40px; border: 0; background: none; color: var(--navy); font-size: 18px; font-weight: 800; }
.stepper output, .stepper input { min-width: 40px; border: 0; text-align: center; font-variant-numeric: tabular-nums; }
/* (petites suites 49, premier dialogue sous la charte) le champ de la charte : .sd-field (libellé au-dessus, 13 px 700), le champ en
   pleine largeur à 40 px (44 px sous 760 px, par la règle du téléphone) ; .fields-row aligne des champs courts ; .stepper input sans
   flèches natives ; une puce qui porte une case cachée (.chip > input) ; une ligne de choix en carte (.choice-row) dans son groupe
   (.choice-group, legend = le titre). Les champs natifs des autres écrans ne changent pas (H2-H8). */
.sd-field { display: grid; gap: 6px; align-content: start; min-width: 0; color: var(--ink); font-size: 13px; font-weight: 700; }
.sd-field > :is(input, select, textarea) { width: 100%; min-height: 40px; padding: 0 10px; font-weight: 400; }
.sd-field > textarea { padding: 8px 10px; }
.sd-field > :is(input, textarea):disabled { background: var(--bg); color: var(--muted); cursor: not-allowed; } /* (tas 14, W1) le champ grisé (l'adresse masquée) */
.sd-field > .form-hint, .sd-field > .stepper { font-weight: 400; }
.sd-field > .stepper { justify-self: start; }
/* (petites suites 101, § 1) le libellé posé à part de son champ (`<label for>` puis le champ, dans un .sd-field) : au-dessus, la bulle « ? » à côté ;
   assez spécifique pour gagner sur l'ancienne règle « .form-grid label » (11 px, en colonne) quand le champ est dans une rangée de deux. */
.sd-field > label:not(.secondary-button) { display: inline-flex; flex-direction: row; flex-wrap: wrap; align-items: center; gap: 6px; color: inherit; font-size: inherit; font-weight: inherit; }
.form-grid label.sd-field { display: grid; flex-direction: initial; gap: 6px; align-content: start; color: var(--ink); font-size: 13px; font-weight: 700; } /* (petites suites 101) le champ de la charte gagne partout sur « .form-grid label » (la règle de .ref-dialog, H9, généralisée) */
fieldset.sd-field { margin: 0; padding: 0; border: 0; }
fieldset.sd-field > legend { margin-bottom: 6px; padding: 0; }
/* (petites suites 101, § 1 ; charte § 9) LE CHAMP FICHIER (filePickHtml, public/dialog-frame.mjs) : le champ natif caché garde le clavier ; un bouton
   secondaire « Choisir un fichier » et le nom du fichier choisi (ou « Aucun fichier »), tenu à jour par ui.js. */
.file-pick { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); min-width: 0; font-weight: 400; }
.file-pick > input[type="file"].visually-hidden { left: 0; top: 0; }
.file-pick > label.secondary-button { cursor: pointer; }
.file-pick:focus-within > label.secondary-button { border-color: var(--sea); box-shadow: var(--focus-ring); }
.field.is-error .file-pick > label.secondary-button { border-color: var(--pill-alert); }
.file-pick-name { min-width: 0; color: var(--muted); font-size: 13px; overflow-wrap: anywhere; }
.file-pick-name.is-chosen { color: var(--ink); font-weight: 700; }
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.fields-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
.stepper input { width: 48px; min-height: 40px; padding: 0; border-radius: 0; background: none; -moz-appearance: textfield; appearance: textfield; }
.stepper input::-webkit-inner-spin-button, .stepper input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.chip { cursor: pointer; }
.chip > input[type="checkbox"], .chip > input[type="radio"] { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; pointer-events: none; }
.chip:has(> input:focus-visible) { outline: 2px solid var(--sea); outline-offset: 2px; }
.choice-group { display: grid; gap: 6px; min-width: 0; margin: 0; padding: 0; border: 0; }
.choice-group + .choice-group, .choice-group + details { margin-top: 14px; }
.choice-group > legend { margin: 0 0 2px; padding: 0; color: var(--muted); font-size: 13px; font-weight: 700; }
.choice-row {
  display: grid; grid-template-columns: 18px minmax(0, 1fr) auto; gap: 10px; align-items: center; padding: 8px 12px;
  border: 1px solid var(--line); border-radius: var(--radius-control); background: var(--card); cursor: pointer;
}
.choice-row > input { width: 18px; height: 18px; margin: 0; accent-color: var(--sea); }
.form-grid .choice-row > input { width: 18px; min-height: 0; margin: 0; padding: 0; } /* (tas 14, W10) la ligne de choix dans une grille de formulaire : la case garde sa taille */
.form-grid label.choice-row { display: grid; grid-template-columns: 18px minmax(0, 1fr); flex-direction: initial; gap: 10px; align-items: center; color: var(--ink); font-size: 14px; font-weight: 400; text-align: left; } /* (tas 14, W10) la ligne de choix gagne sur « .form-grid label », comme le champ (petites suites 101) */
.form-grid label.choice-row small { font-weight: 400; }
.choice-row:has(> input:checked) { border-color: var(--sea); background: var(--sea-soft); }
.choice-row:has(> input:disabled) { opacity: .55; cursor: not-allowed; }
.choice-row b { display: block; font-weight: 700; }
.choice-row small { display: block; color: var(--muted); font-size: 12px; }
.choice-row > .status-pill { margin-top: 0; text-transform: none; letter-spacing: 0; white-space: nowrap; }
.choice-row small.cancel-scope-warning { margin-top: 2px; color: var(--pill-watch); font-weight: 700; } /* (petites suites 75) l'avertissement propre à un choix de suppression */

/* § 2 et § 7 — LES PASTILLES : une forme, six couleurs par jeton. */
.status-pill {
  display: inline-flex; align-items: center; width: max-content; margin-top: 4px; padding: 5px 9px; border-radius: var(--radius-pill);
  background: var(--pill-fact-bg); color: var(--pill-fact); font-weight: 900; text-transform: uppercase; letter-spacing: .06em;
  font-size: 11px !important; /* plancher de lecture : des règles d'écran plus précises posent 8 ou 9 px (legibility.css le relevait déjà ainsi) */
}
.status-pill.is-ok { background: var(--pill-ok-bg); color: var(--pill-ok); }
.status-pill.is-watch { background: var(--pill-watch-bg); color: var(--pill-watch); }
.status-pill.is-alert { background: var(--pill-alert-bg); color: var(--pill-alert); }
.status-pill.is-fact { background: var(--pill-fact-bg); color: var(--pill-fact); }
.status-pill.is-teal { background: var(--pill-teal-bg); color: var(--pill-teal); }
.status-pill.is-purple { background: var(--pill-purple-bg); color: var(--pill-purple); }

/* § 10 — L'AIDE EN BULLE : le rond « ? » (UI.helpIcon de ui.js) et sa bulle ; une seule définition. */
.help-icon {
  position: relative; display: inline-flex; align-items: center; justify-content: center; flex: none; width: 18px; height: 18px;
  min-width: 18px; min-height: 18px; margin: 0 0 0 6px; padding: 0; border: 1px solid var(--line-strong); border-radius: 50%;
  background: var(--card); color: var(--muted); font: 600 12px/1 var(--font-text); letter-spacing: 0; text-transform: none;
  vertical-align: middle; cursor: help; box-shadow: none; transition: border-color .15s, color .15s, box-shadow .15s;
}
.help-icon:hover, .help-icon:focus-visible, .help-icon[aria-expanded="true"] { border-color: var(--sea); color: var(--sea); outline: none; box-shadow: var(--focus-ring); }
.help-icon::after { content: ""; position: absolute; inset: -9px; border-radius: 50%; } /* la zone de toucher, invisible */
.help-bubble {
  position: absolute; z-index: 90; display: block; box-sizing: border-box; width: max-content; max-width: min(280px, calc(100vw - 32px));
  margin: 6px 0 0; padding: 9px 11px; border: 1px solid var(--line); border-radius: 8px; background: var(--card); color: var(--ink);
  box-shadow: 0 8px 24px rgba(22, 63, 77, .14); font: 400 13px/1.45 var(--font-text); letter-spacing: normal; text-transform: none;
  text-align: left; white-space: normal; overflow-wrap: anywhere; pointer-events: auto;
}

/* § 11 — LE DIALOGUE : <dialog> par showModal(), trois largeurs, rayon de carte, plein écran sous 760 px. */
dialog {
  width: min(720px, calc(100vw - 32px)); max-height: calc(100vh - 32px); padding: 0; border: 0; border-radius: var(--radius-card);
  color: var(--ink); background: var(--card); box-shadow: var(--shadow-dialog);
}
dialog::backdrop { background: rgba(16, 44, 52, .48); backdrop-filter: blur(3px); }
/* (lot H1) « html » : un cran au-dessus des largeurs propres d'un dialogue d'avant le gabarit (dialog.feedback-dialog, 0,1,1). */
html dialog.dialog-s { width: min(var(--dialog-s), calc(100vw - 32px)); }
html dialog.dialog-m { width: min(var(--dialog-m), calc(100vw - 32px)); }
html dialog.dialog-l { width: min(var(--dialog-l), calc(100vw - 32px)); }
/* (petites suites 49) la structure du dialogue : en-tête (sur-titre, titre, croix), corps qui défile, pied fixe — « Annuler » à gauche,
   les actions à droite (.dialog-foot-actions) : la principale PREMIÈRE dans le code (F10 de ui.js prend le premier bouton d'envoi),
   à droite à l'écran (row-reverse). La croix se règle sous .dialog-head : team.css, chargée partout, redessine .icon-button
   (26 px, bordé) — à reprendre avec sa famille. Le gabarit servi par ui.js viendra avec H1. */
.dialog-form { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; max-height: calc(100vh - 32px); margin: 0; }
.dialog-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 16px 20px 12px; border-bottom: 1px solid var(--line); }
.dialog-head .eyebrow { margin-bottom: 4px; }
.dialog-head h2 { margin: 0; font: 500 22px/1.2 var(--font-title); letter-spacing: -.01em; }
.dialog-body { display: grid; align-content: start; gap: 18px; padding: 16px 20px; overflow-y: auto; }
.dialog-body h3 { display: flex; align-items: center; margin: 0 0 10px; font-size: 16px; font-weight: 700; }
.dialog-body details > summary { cursor: pointer; color: var(--navy); font-weight: 700; }
.dialog-body details[open] > summary { margin-bottom: 10px; }
.dialog-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 12px 20px; border-top: 1px solid var(--line); background: var(--bg); }
/* (petites suites 58, § 0 point 5 ; charte § 11) PLUS DE TROIS ACTIONS : « Annuler » et le geste dangereux à gauche, les actions à droite, la principale
   (F10) la dernière à droite. Quand la largeur manque, les actions passent à la ligne EN GROUPE, alignées à droite (le pied se replie, le groupe garde
   sa ligne) — jamais un bouton seul rejeté sur une ligne ; à 375, une colonne dans l'ordre (règle du téléphone ci-dessous). */
.dialog-foot-actions { display: flex; flex-direction: row-reverse; flex: 0 1 auto; flex-wrap: wrap; justify-content: flex-start; gap: 10px; margin-left: auto; max-width: 100%; }
/* (petites suites 89 ; charte § 19, V1.4) « Plus » (`⋯`) : posé par ui.js dans un pied de plus de deux commandes ; il n'existe qu'au téléphone
   (règle sous 760 px plus bas) — à l'ordinateur, le pied garde tous ses boutons, rien ne change. */
.dialog-foot > .dialog-more { display: none; }
.dialog-head .icon-button { width: 36px; height: 36px; display: inline-flex; flex: none; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: var(--radius-control); background: none; color: var(--muted); font-size: 18px; line-height: 1; }
.dialog-head .icon-button:hover { background: var(--sea-soft); color: var(--navy); }
/* (lot H1) le gabarit de ui.js et du serveur (public/dialog-frame.mjs) : un cran de plus que les règles propres d'un dialogue
   (« .event-removal-dialog footer », 0,1,1), qui dataient d'avant le gabarit. Le corps porte la marge : la grille et l'erreur n'en ajoutent pas. */
:is(.dialog-s, .dialog-m, .dialog-l) > .dialog-form { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: 0; padding: 0; }
:is(.dialog-s, .dialog-m, .dialog-l) .dialog-head { display: flex; justify-content: space-between; margin: 0; padding: 16px 20px 12px; background: none; border-bottom: 1px solid var(--line); }
:is(.dialog-s, .dialog-m, .dialog-l) .dialog-foot { display: flex; justify-content: flex-start; flex-wrap: wrap; /* (petites suites 58) le groupe des actions passe à la ligne en entier */ margin: 0; padding: 12px 20px; border-top: 1px solid var(--line); background: var(--bg); position: static; }
.dialog-body > .form-grid { padding: 0; }
.dialog-body > .form-error { margin: 0; }
.dialog-body > :where(p, ul, ol):first-child { margin-top: 0; }
.confirm-text { margin: 0; line-height: 1.5; }
.dialog-body:empty { display: none; } /* une question courte : le titre suffit */

/* § 12 — L'ÉTAT VIDE et LA BARRE DE PROGRESSION. */
.empty-state { display: grid; justify-items: center; gap: 10px; padding: 24px 16px; color: var(--muted); text-align: center; }
.sd-bar, :where(progress) {
  display: block; width: 100%; height: 8px; margin-top: 8px; border: 0; border-radius: var(--radius-pill); background: var(--line);
  color: var(--sea); overflow: hidden; -webkit-appearance: none; appearance: none;
}
.sd-bar::-webkit-progress-bar, :where(progress)::-webkit-progress-bar { background: var(--line); border-radius: var(--radius-pill); }
.sd-bar::-webkit-progress-value, :where(progress)::-webkit-progress-value { background: var(--sea); border-radius: var(--radius-pill); }
.sd-bar::-moz-progress-bar, :where(progress)::-moz-progress-bar { background: var(--sea); border-radius: var(--radius-pill); }

/* § 14 — LES ONGLETS (charte V1.1, petites suites 50) : .tabs, le conteneur, qui passe à la ligne ; .tab, la puce-onglet, un lien vers l'adresse de
   l'onglet ; aria-selected="true" = l'onglet ouvert (les jetons de .chip.is-active). 44 px sous 760 px par la règle du téléphone. */
.tabs { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.tab { min-height: 32px; padding: 0 12px; display: inline-flex; align-items: center; border: 1px solid var(--line); border-radius: var(--radius-pill); background: var(--card); color: var(--ink); font-size: 13px; font-weight: 700; text-decoration: none; }
.tab:hover { border-color: var(--sea); }
.tab[aria-selected="true"] { border-color: var(--sea); background: var(--sea-soft); color: var(--pill-teal); }
.tab:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.page-heading .tabs { margin-top: var(--space-3); } /* les onglets d'une page, sous la phrase de l'en-tête */

/* § 13 — LE FOCUS VISIBLE PARTOUT (au clavier), jamais retiré sans remplacement. */
/* (lot H1) le texte lu par les lecteurs d'écran et par F1, invisible à l'écran : le h1 des pages qui gardent leur mise en page (C1, C2). */
.visually-hidden { position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
:focus-visible { outline: 2px solid var(--sea); outline-offset: 2px; }

/* La coquille : la barre du haut reste visible au défilement ; le bandeau de la consultation hors ligne. */
.topbar { position: sticky; top: 0; z-index: 11000; }
/* (charte V1.1, petites suites 50) Le filet de menu : au-dessus d'une entrée mise à part (« À propos » en bas de Paramètres) ; les menus sont sur fond --navy. */
.nav-divider { margin-top: var(--space-1); border-top: 1px solid var(--navy2); }
/* (petites suites 101, § 3) LA FLÈCHE DE RETOUR, à gauche de « Dashboard » (navBackHtml, src/views.mjs ; la règle : previousScreenOf, ui.js) : fond
   transparent, focus visible, 44 px de côté au téléphone ; désactivée (aria-disabled) sur la page d'accueil sans écran précédent, jamais absente.
   Le trait suit le texte de la barre du haut (--on-sea sur --navy), décision de la réflexion du 16/10 (--ink n’y est pas lisible). */
.topbar nav .nav-back { flex: none; align-self: center; width: 36px; height: 36px; margin: 0 4px 0 0; padding: 0; display: inline-flex; align-items: center; justify-content: center; border: 0; border-radius: var(--radius-control); background: transparent; color: var(--on-sea); font-size: 20px; line-height: 1; cursor: pointer; }
.topbar nav .nav-back:hover { background: color-mix(in srgb, var(--on-sea) 12%, transparent); }
.topbar nav .nav-back:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.topbar nav .nav-back[aria-disabled="true"] { color: color-mix(in srgb, var(--on-sea) 80%, var(--sea)); opacity: .55; cursor: default; background: transparent; } /* (réflexion 16/10) le ton des entrées inactives du menu, aucune couleur nouvelle */
.brand-logo { width: 38px; height: 38px; flex: 0 0 38px; object-fit: contain; border-radius: 50%; }
#offline-readonly-banner {
  position: sticky; top: 0; z-index: 10000; padding: 12px 20px; background: var(--offline-bg); color: var(--offline-ink);
  border-bottom: 2px solid var(--offline-line); font-size: 16px; font-weight: 800; text-align: center;
}
/* Le cache local ne sert qu'à la consultation : les gestes d'écriture du planning disparaissent (au-dessus de toute règle d'écran). */
.offline-readonly .outing-resize-handle, .offline-readonly .outing-delete, .offline-readonly .slot-add, .offline-readonly #new-outing { display: none !important; }
.offline-readonly [draggable="true"] { cursor: default !important; }

/* § 12 — LE TÉLÉPHONE : la rupture unique à 760 px. Une colonne, des cibles de 44 px, des dialogues plein écran, rien ne déborde.
   Les !important de ce bloc sont le plancher de lecture : les sélecteurs d'écran d'origine sont plus précis (.client-card small…)
   et descendent à 8 ou 9 px ; sous 16 px dans un champ, Safari iOS zoome la page à la prise de focus. */
@media (max-width: 760px) {
  body { font-size: 16px; line-height: 1.5; }
  small, em, .form-hint { font-size: 13px !important; line-height: 1.45; }
  input, select, textarea { font-size: 16px !important; }
  input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]), select, textarea { min-height: 44px; } /* un cran de plus que les champs d'écran (0,2,1) */
  textarea { min-height: 88px; }
  input[type="file"] { min-width: 0; width: 100%; max-width: 100%; }
  button, .primary-button, .secondary-button, .danger-button, .link-button { min-height: 44px; font-size: 15px; }
  .tab { min-height: 44px; font-size: 15px; }
  .topbar nav .nav-back { width: 44px; height: 44px; min-height: 44px; } /* (petites suites 101, § 3) la flèche de retour : 44 px au doigt */ /* § 14 : l'onglet, une cible de 44 px */

  .app-shell > section { margin-left: 16px; margin-right: 16px; } /* § 3 : 16 px de marge au téléphone */
  .app-shell > .page-heading { margin-left: 0; margin-right: 0; }
  .page-heading { padding: 22px 16px 14px; align-items: flex-start; flex-direction: column; }
  .page-heading h1 { font-size: 22px; }
  .form-grid { grid-template-columns: 1fr; gap: 12px; }
  :where(fieldset) { min-width: 0; }
  .card { padding: 14px; }
  .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .help-icon::after { inset: -13px; } /* 44 px de zone de toucher, le rond reste à 18 px (§ 10) */
  .brand-logo { width: 34px; height: 34px; flex-basis: 34px; }

  /* Le tableau devenu liste de cartes (choix de l'écran : .is-stacked). */
  .sd-table.is-stacked thead { display: none; }
  .sd-table.is-stacked tr { display: block; margin-bottom: 12px; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--card); }
  .sd-table.is-stacked td { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; border: 0; }
  .sd-table.is-stacked td::before { content: attr(data-label); color: var(--muted); font-size: 12px; font-weight: 700; }
  /* (tas 7, Caisse à 375) les cartes prennent toute la largeur de leur bloc ; le libellé garde la police du texte (une cellule .mono aussi). */
  .sd-table.is-stacked, .sd-table.is-stacked tbody, .sd-table.is-stacked tfoot { display: block; width: 100%; }
  .sd-table.is-stacked td::before { font-family: var(--font-text); }
  /* (tas 7, Caisse à 375) le pied d'un tableau empilé : une carte de totaux, chaque total avec son libellé ; les cases vides disparaissent. */
  .sd-table.is-stacked tfoot tr { display: block; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--bg); }
  .sd-table.is-stacked tfoot th { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; border: 0; }
  .sd-table.is-stacked tfoot th:empty { display: none; }
  .sd-table.is-stacked tfoot th[data-label]::before { content: attr(data-label); color: var(--muted); font-size: 12px; font-weight: 700; text-transform: none; letter-spacing: 0; }

  /* Le dialogue modal occupe tout l'écran (Direction 12/10, point 5) ; ses formulaires tiennent dans la largeur. */
  dialog:modal { width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh; margin: 0; border-radius: 0; }
  html dialog.dialog-s:modal, html dialog.dialog-m:modal, html dialog.dialog-l:modal { width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh; margin: 0; border-radius: 0; } /* (lot H1) au-dessus des trois largeurs */
  dialog form, dialog .form-grid { max-width: 100%; }
  dialog:modal .dialog-form { height: 100%; max-height: 100dvh; }
  .dialog-head, .dialog-body, .dialog-foot { padding-left: 16px; padding-right: 16px; }
  .dialog-foot, :is(.dialog-s, .dialog-m, .dialog-l) .dialog-foot { flex-direction: column-reverse; align-items: stretch; } /* pleine largeur : les actions en haut, Annuler en bas */
  :is(.dialog-s, .dialog-m, .dialog-l) .dialog-head, :is(.dialog-s, .dialog-m, .dialog-l) .dialog-foot { padding-left: 16px; padding-right: 16px; }
  .page-heading .heading-actions { justify-content: flex-start; width: 100%; }
  .dialog-foot-actions { flex-direction: column; align-items: stretch; width: 100%; margin-left: 0; }
  /* (lot H1) au téléphone, la principale sur toute la largeur, les actions secondaires deux par ligne : un pied de six boutons ne mange plus l'écran */
  :is(.dialog-s, .dialog-m, .dialog-l) .dialog-foot-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  :is(.dialog-s, .dialog-m, .dialog-l) .dialog-foot-actions > :first-child, :is(.dialog-s, .dialog-m, .dialog-l) .dialog-foot-actions > :only-child { grid-column: 1 / -1; }
  /* (petites suites 58, § 0 point 5) PLUS DE TROIS ACTIONS : une colonne dans l'ordre, chaque bouton sur toute la largeur (le geste dangereux aussi) */
  :is(.dialog-s, .dialog-m, .dialog-l) .dialog-foot-actions:has(> :not([hidden]) ~ :not([hidden]) ~ :not([hidden]) ~ :not([hidden])) { grid-template-columns: minmax(0, 1fr); }
  :is(.dialog-s, .dialog-m, .dialog-l) .dialog-foot > button { margin-right: 0; }
  /* (petites suites 89 ; charte § 19, V1.4) LE PIED TIENT SUR UNE LIGNE : « Annuler » à gauche, « Plus » au milieu, l'action primaire à droite
     (F10) ; les autres commandes (`data-in-more`, posé par ui.js selon SDDialogFrame.footPlan) passent dans la feuille « Plus ». Un état du pied
     (un compte, une ligne d'état) prend la ligne du dessus. Le contenu reprend la place : le pied ne mesure plus qu'un bouton et ses marges.
     Deux commandes (`is-one-line` sans `has-more`, contre-lecture du 14/10) : Annuler à gauche, l'action à droite, chacune la moitié. */
  dialog .dialog-foot.is-one-line { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 8px; }
  dialog .dialog-foot.is-one-line > :not(button, a, .dialog-foot-actions) { order: -1; flex: 1 0 100%; }
  dialog .dialog-foot.is-one-line > .dialog-foot-actions { display: flex; flex: 1 1 0; flex-direction: row-reverse; min-width: 0; width: auto; margin-left: 0; }
  dialog .dialog-foot.is-one-line > .dialog-foot-actions > * { flex: 1 1 0; min-width: 0; }
  dialog .dialog-foot.is-one-line > .dialog-foot-actions:not(:has(> :not([hidden], [data-in-more]))) { display: none; }
  dialog .dialog-foot.is-one-line:not(.has-more) { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); } /* deux moitiés exactes */
  dialog .dialog-foot.is-one-line:not(.has-more) > :not(button, a, .dialog-foot-actions) { grid-column: 1 / -1; }
  dialog .dialog-foot.is-one-line:not(.has-more):not(:has(> [data-dialog-close]:not([hidden]))) > .dialog-foot-actions { grid-column: 1 / -1; }
  dialog .dialog-foot.has-more > [data-in-more], dialog .dialog-foot.has-more > .dialog-foot-actions > [data-in-more] { display: none; }
  dialog .dialog-foot.has-more > :is(button, a) { flex: 0 0 auto; }
  dialog .dialog-foot.has-more :is(button, a) { padding-left: 12px; padding-right: 12px; } /* la place à l'action : un libellé long tient en deux lignes au plus */
  dialog .dialog-foot.has-more > .dialog-more { display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-width: 44px; }
  .dialog-head .icon-button { width: 44px; height: 44px; }
  .chip { min-height: 44px; }
  .fields-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* (H3) § 2 — LES CATÉGORIES : les couleurs des rôles (découverte, initiation, formation) et du débutant sont des catégories, pas des états
   (charte § 2 : « elles gardent leurs teintes, mais en jetons --cat-* ») ; les valeurs sont celles de la maquette des pastilles du 06/10. */
:root {
  --cat-discovery: #0e5a73; --cat-discovery-bg: #dcedf4;
  --cat-initiation: #7a4b1d; --cat-initiation-bg: #f7e7d3;
  --cat-training: #2f4a1a; --cat-training-bg: #e4f0d6;
  --cat-beginner: #5c4313; --cat-beginner-bg: #f6ead2;
}
/* (H3) § 6 — un lien en forme de bouton n'est pas souligné (audit A12 : « Météo », « Semaine Combo », « ← Planning »…) ; son libellé tient
   sur une ligne. */
a.primary-button, a.secondary-button, a.danger-button { text-decoration: none; }
.page-heading .heading-actions > :is(.primary-button, .secondary-button, .danger-button) { white-space: nowrap; }
@media screen and (max-width: 760px) { .page-heading .heading-actions > :is(.primary-button, .secondary-button, .danger-button) { white-space: normal; } }
/* (H3) § 8 — le tableau large d'une page de réglages défile DANS SON CADRE (.table-wrap) au téléphone, avec l'indication « ⟷ » (audit C11) :
   data-scroll-hint porte la phrase, collée au bord gauche du cadre pendant le défilement ; elle ne se montre que si le tableau déborde
   VRAIMENT (.is-overflowing, posé par ui.js : scrollWidth > clientWidth, recalculé au redimensionnement ; réflexion 13/10). */
@media screen and (max-width: 760px) {
  .table-wrap[data-scroll-hint].is-overflowing::before { content: "⟷ " attr(data-scroll-hint); position: sticky; left: 0; display: block; padding: var(--space-1) var(--space-2); color: var(--muted); font-size: 12px; font-weight: 700; }
}
/* (H6) Les variantes d'état qui manquaient à la carte et à la tuile (charte § 2 et § 7) : le gris (un fait) et le violet (le réservé : la vente à
   inscrire, le cours au centre), sur les jetons des pastilles. */
.card.is-fact { border-left: 4px solid var(--pill-fact); }
.card.is-purple { border-left: 4px solid var(--pill-purple); }
.tile.is-purple .tile-value { color: var(--pill-purple); }
/* (H6) Le sur-titre lien d'une sous-page (« Formation » au-dessus d'un dossier, d'une séance) : la couleur du sur-titre, souligné au survol (§ 4-5). */
.eyebrow a { color: inherit; text-decoration: none; }
.eyebrow a:hover { text-decoration: underline; }

/* (H7) LES ONGLETS NOMBREUX (charte § 14 ; audit C8 : les quatorze onglets des Référentiels empilés sur huit lignes à 375 px) : .tabs.is-scroll
   passe à la ligne à l'écran large et, sous 760 px, tient sur une ligne qui défile dans son cadre ; la page ne déborde pas. */
@media screen and (max-width: 760px) { /* « screen and » : le bloc du téléphone de H0 reste le dernier bloc de la rupture sans média */
  .tabs.is-scroll { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: thin; padding-bottom: var(--space-1); }
  .tabs.is-scroll > .tab { flex: none; white-space: nowrap; }
  .page-heading-main:has(> .tabs.is-scroll) { align-self: stretch; max-width: 100%; } /* l'en-tête en colonne : la ligne d'onglets prend la largeur de l'écran, pas celle de ses onglets */
}

/* (H4) LA LIGNE DES FAITS (la maquette du dossier élève, docs/maquettes/formation-sur-la-charte-2026-10-13.html, écran 2) : un fait = son
   nom en capitales 11 px --muted, sa valeur en gras dessous ; grille qui passe à la ligne (§ 7). (La carte « fait », .card.is-fact, est
   venue avec H6.) */
.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px 18px; margin: 0; }
.fact { min-width: 0; }
.fact > dt, .fact-key { margin: 0 0 4px; color: var(--muted); font-size: 11px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.fact > dd, .fact-value { margin: 0; color: var(--ink); font-weight: 700; overflow-wrap: anywhere; }
.fact .fact-amount, .fact-amount { font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------------------------------------------------------------------
   V1.3 A (charte § 18 ; maquette docs/maquettes/charte-v1-3-2026-10-13.html, écrans 3, 5 et 6) : le champ en erreur partout, le résumé des
   erreurs d'un formulaire public, les lignes d'articles en tableau (panier du comptoir, éditeur du dossier).
   --------------------------------------------------------------------------------------------------------------------------------- */
/* UN CHAMP EN ERREUR, PARTOUT (§ 9, § 18) : le champ d'un .field.is-error, ou le champ marqué lui-même (.is-invalid, aria-invalid) ; bord
   --pill-alert, halo --pill-alert-bg de 3 px, au repos comme au focus ; le libellé en --pill-alert. La force de la règle vient de
   « :not(#sd-champ):not(#sd-champ) » (un identifiant que rien ne porte, deux fois : spécificité (2,1,1) au moins) : elle passe au-dessus de
   toute règle d'écran, même portée par un #id (#counter-email-field input, #cruise-programme .cd-form input), sans !important.
   test/charte-v13-a-* refuse, dans toute feuille, une règle de champ aussi forte qui pose un bord ou un halo, et toute règle d'écran qui
   dessine un champ en erreur (plus jamais une correction locale comme celles des lots 62 et 63). */
.field.is-error :is(input, select, textarea):not(#sd-champ):not(#sd-champ),
:is(input, select, textarea):is(.is-invalid, [aria-invalid="true"]):not(#sd-champ):not(#sd-champ) {
  border-color: var(--pill-alert); box-shadow: 0 0 0 3px var(--pill-alert-bg);
}
.field.is-error:not(#sd-champ):not(#sd-champ), .field.is-error > label:not(#sd-champ):not(#sd-champ) { color: var(--pill-alert); }
.field.is-error .field-error { display: block; }

/* LE RÉSUMÉ EN TÊTE (§ 18, écran 5) : il nomme les champs à corriger (un lien par champ, qui y conduit) ; un refus sans champ (sortie
   complète, délai) y est écrit seul. */
.summary-err { margin: 0 0 12px; padding: 10px 12px; border: 1px solid var(--pill-alert-line); border-radius: var(--radius-control); background: var(--pill-alert-bg); color: var(--pill-alert); font-weight: 700; }
.summary-err:focus { outline: none; }
.summary-err:focus-visible { box-shadow: var(--focus-ring); }
.summary-err > p { margin: 0; }
.summary-err > ul { margin: 6px 0 0; padding-left: 18px; font-weight: 400; }
.summary-err > p + ul { margin-top: 6px; }
.summary-err a { color: inherit; text-decoration: underline; }

/* LES LIGNES D'ARTICLES EN TABLEAU (§ 8, § 18, écran 3) : .sd-table.is-lines — Article · Qté · P.U. · Remise · Total ; lignes de 44 px,
   nombres à droite en chiffres tabulaires, la quantité modifiable dans la ligne, « Retirer » en lien d'action, le total en pied sur
   --sea-soft. Une ligne = un tbody (la ligne et ses compléments : sortie, organisme, forfait). Sous 760 px (avec .is-stacked) : une carte
   par ligne, le nom en tête, chaque valeur sous son en-tête. */
.sd-table.is-lines th, .sd-table.is-lines td { padding: 6px 8px; }
.sd-table.is-lines td { height: 44px; vertical-align: middle; }
.sd-table.is-lines :is(th, td).num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.sd-table.is-lines tbody > tr:not(:last-child) > td { border-bottom: 0; }
.sd-table.is-lines tbody > tr.line-more > td { height: auto; padding-top: 0; }
.sd-table.is-lines .line-name { font-weight: 700; }
.sd-table.is-lines .line-detail { display: block; color: var(--muted); font-size: 12px; font-weight: 400; }
.sd-table.is-lines input.line-qty { width: 64px; min-height: 36px; height: 36px; padding: 0 8px; text-align: right; font-variant-numeric: tabular-nums; }
.sd-table.is-lines .line-total { font-weight: 700; }
.sd-table.is-lines tfoot td { border-bottom: 0; background: var(--sea-soft); font-weight: 700; }
@media screen and (max-width: 760px) { /* « screen and » : le bloc du téléphone de H0 reste le dernier bloc de la rupture sans média */
  .sd-table.is-lines.is-stacked tbody { display: block; margin-bottom: 10px; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--card); }
  .sd-table.is-lines.is-stacked tbody > tr { margin: 0; padding: 0; border: 0; border-radius: 0; background: none; }
  .sd-table.is-lines.is-stacked td { height: auto; min-height: 0; align-items: center; }
  .sd-table.is-lines.is-stacked td.line-article { display: block; }
  .sd-table.is-lines.is-stacked td.line-article::before, .sd-table.is-lines.is-stacked td:not([data-label])::before { content: none; }
  .sd-table.is-lines.is-stacked td:empty { display: none; }
  .sd-table.is-lines.is-stacked td.line-total { font-size: 15px; }
  .sd-table.is-lines.is-stacked td.line-remove { justify-content: flex-end; }
  .sd-table.is-lines.is-stacked tfoot { display: block; }
  .sd-table.is-lines.is-stacked tfoot tr { display: flex; justify-content: space-between; margin: 0; padding: 10px 12px; border: 0; border-radius: var(--radius-control); background: var(--sea-soft); }
}

/* V1.3 B — LE BOUTON « € » FLOTTANT (charte § 18, maquette charte-v1-3-2026-10-13.html écran 4) : rond 56 px --sea, « € » en 22 px, l'étiquette
   « ENCAISSER » dessous, le compte en pastille. Il n'existe qu'une fois : le lanceur du comptoir (#counter-fab) prend la classe .fab au
   téléphone sur l'écran d'une sortie (counter-launcher.js, launcherFormFor) ; ailleurs il garde sa forme. « button.fab » gagne sur la règle
   d'écran du lanceur (styles.css) sans !important. Un dialogue modal passe devant (couche du dessus). */
button.fab { position: fixed; right: 16px; bottom: 34px; width: 56px; height: 56px; padding: 0; border: 0; border-radius: var(--radius-pill); background: var(--sea); color: var(--on-sea); font: 700 22px/56px var(--font-text); box-shadow: var(--shadow); }
button.fab:hover, button.fab:focus-visible { background: var(--sea-strong); box-shadow: var(--focus-ring), var(--shadow); }
button.fab .fab-label { position: absolute; left: 50%; bottom: -20px; transform: translateX(-50%); color: var(--muted); font: 700 11px/1 var(--font-text); letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; }
button.fab .fab-label[hidden] { display: none; }
button.fab[data-key-hint]::after { content: none; display: none; }
button.fab.is-tucked .fab-label { visibility: hidden; } /* (V1.3 B) écarté contre le bord (il couvrirait un bouton de la page) : la languette seule, sans l'étiquette */
/* (petites suites 82) L'ENVOI PROGRAMMÉ : les deux choix du dialogue et la case de l'accusé (cases alignées sur le texte, 44 px au doigt),
   la liste de ce soir du signal du jour et ses deux gestes, la ligne « Envoi client » de la fiche. Jetons seulement. */
.scheduled-send-dialog .scheduled-send-choices { display: grid; gap: 4px; margin: 12px 0 4px; padding: 0; border: 0; }
.scheduled-send-dialog .check-line { display: flex; align-items: center; gap: 8px; min-height: 44px; font-weight: 400; color: var(--ink); }
.scheduled-send-dialog .check-line input { width: 18px; height: 18px; margin: 0; flex: none; }
.scheduled-send-dialog .sd-field { margin-top: 8px; }
.scheduled-send-tonight { margin: 6px 0 0; padding-left: 18px; }
.scheduled-send-tonight li { margin: 4px 0; }
.scheduled-send-actions { display: inline-flex; flex-wrap: wrap; gap: 4px 12px; }
.scheduled-send-actions .link-button { text-align: left; }
.record-scheduled-send { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.record-scheduled-send .scheduled-send-actions { gap: 6px 10px; }
.record-facts .fact:has(.record-scheduled-send) { grid-column: 1 / -1; } /* (petites suites 82) la ligne de l'envoi programmé et ses trois gestes, sur toute la largeur */
/* (contrat partenaire 0.90.019) LE CONTRAT SUR LA FICHE PARTENAIRE ET LA PAGE PUBLIQUE DE SIGNATURE : jetons et composants seulement (charte V1.4) ;
   la fiche : le statut (pastille), les gestes qui passent à la ligne, l'identité légale repliée derrière le triangle (<details>) ; la page : l'en-tête,
   le contrat qui défile dans sa carte, les deux colonnes de signature qui passent l'une sous l'autre sans rupture de média, le formulaire en colonne. */
.partner-contract .partner-contract-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 6px; }
.partner-contract .form-hint { margin: 4px 0; }
.partner-contract-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 4px; }
.partner-contract-transfer { color: var(--pill-watch); font-weight: 700; }
.partner-contract .partner-legal { margin-top: 12px; border-top: 1px solid var(--line); padding-top: 10px; }
.partner-contract .partner-legal > .form-grid { padding: 8px 0 0; }
.contract-sign-page { max-width: 1080px; margin: 0 auto; padding-inline: clamp(16px, 4vw, 30px); display: grid; gap: 12px; }
.contract-sign-page .page-heading { padding-left: 0; padding-right: 0; }
.contract-sign-toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 12px; }
.contract-text { max-height: 60vh; overflow-y: auto; padding: 4px 12px 4px 0; color: var(--ink); font-size: 14px; line-height: 1.55; }
.contract-text .contract-title { color: var(--sea); font-size: 18px; }
.contract-text h3 { margin: 16px 0 4px; font-size: 15px; color: var(--ink); }
.contract-text h4 { margin: 12px 0 4px; font-size: 14px; color: var(--sea); }
.contract-text p { margin: 0 0 8px; }
.contract-text .contract-break { margin: 18px 0; border: 0; border-top: 1px solid var(--line); }
.contract-signatures { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; margin: 12px 0; }
.contract-signatures > div { display: grid; gap: 2px; padding: 12px; border: 1px solid var(--line); border-radius: var(--radius-card); }
.contract-signatures span { color: var(--muted); font-size: 13px; }
.contract-sign-form { display: grid; gap: 12px; max-width: 560px; }
.contract-sign-form .field { display: grid; gap: 4px; }
.contract-sign-form .field > label { font-size: 13px; font-weight: 700; color: var(--ink); }
.contract-sign-form input:not([type="checkbox"]) { min-height: 44px; padding: 0 12px; font: inherit; }
.contract-sign-form .contract-sign-accept { display: flex; align-items: flex-start; gap: 10px; min-height: 44px; font-weight: 400; }
.contract-sign-form .contract-sign-accept input { width: 20px; height: 20px; margin: 2px 0 0; flex: none; }
.contract-sign-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.contract-sign-done h2 { margin: 10px 0 6px; }
.today-partner-contracts-signal ul { margin: 6px 0 0; padding-left: 18px; }
.partner-contract.profile-section > :not(legend) { grid-column: 1 / -1; } /* (contrat partenaire) le statut et l'identité légale sur toute la largeur de la fiche */
/* (contrat partenaire, famille C 0.90.024) LE BLOC « PERSONNEL D'UN PARTENAIRE » DE LA FICHE CLIENT : jetons et composants seulement (charte V1.4) ;
   l'état (pastille, gestes), les deux petits formulaires (champ au-dessus, erreur sous le champ), la liste du cercle familial, l'historique replié. */
.client-staff-block.profile-section > :not(legend) { grid-column: 1 / -1; }
.client-staff-block h4 { margin: 10px 0 6px; font-size: 14px; color: var(--sea); }
.client-staff-block .staff-link-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 4px; }
.client-staff-block .form-hint { margin: 4px 0; }
.client-staff-block .field { display: grid; gap: 4px; }
.client-staff-block .field > label { font-size: 13px; font-weight: 700; color: var(--ink); }
.client-staff-block .staff-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 4px; }
.client-staff-block .staff-family-form { margin-top: 12px; border-top: 1px solid var(--line); padding-top: 6px; }
.client-staff-block .staff-family-results { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.client-staff-block .staff-family-results small { display: block; color: var(--muted); font-weight: 400; }
.client-staff-block .staff-family-members { margin: 0; padding-left: 18px; display: grid; gap: 4px; }
.client-staff-block .staff-history { margin-top: 12px; border-top: 1px solid var(--line); padding-top: 8px; }
.client-staff-block .staff-history ul { margin: 6px 0 0; padding-left: 18px; display: grid; gap: 4px; font-size: 13px; color: var(--ink); }
.client-staff-block .staff-history-at { color: var(--muted); font-variant-numeric: tabular-nums; }
.partner-contract-staff { font-weight: 700; }
/* (fusion de fiches à l'écran, 0.90.052) « FUSIONNER AVEC… » DE LA FICHE CLIENT : jetons et composants seulement (charte V1.4, § 11 : dialog-m,
   plein écran sous 760 px par le gabarit ; § 7 cartes à bord d'état ; § 9 champ au-dessus) ; les deux fiches côte à côte passent l'une sous
   l'autre d'elles-mêmes (grille auto-fit, aucune rupture de média, aucune largeur au-delà de 375 px) ; une fiche réunie : le pied réduit à
   « Annuler », le bandeau en tête de la fiche. */
.client-merge-dialog .merge-candidates { display: grid; gap: 8px; margin: 8px 0 4px; }
.client-merge-dialog h4 { margin: 12px 0 6px; font-size: 14px; color: var(--sea); }
.client-merge-dialog .merge-candidate { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 10px; width: 100%; min-height: 44px; height: auto; padding: 8px 12px; text-align: left; white-space: normal; }
.client-merge-dialog .merge-candidate small { display: block; color: var(--muted); font-size: 12px; font-weight: 400; overflow-wrap: anywhere; }
.client-merge-dialog .merge-sides { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; }
.client-merge-dialog .merge-side { display: grid; gap: 10px; align-content: start; min-width: 0; }
.client-merge-dialog .merge-side .facts { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }
.client-merge-dialog .merge-families { margin: 0; padding-left: 18px; display: grid; gap: 4px; color: var(--ink); }
.client-merge-dialog .merge-warning { margin: 10px 0 0; padding: 10px 12px; color: var(--pill-watch); }
.client-merge-dialog .merge-warning p, .client-merge-banner p { margin: 0; }
.client-merge-dialog .merge-refusal { margin: 12px 0 0; }
.client-merge-dialog .merge-confirmation { margin: 12px 0 0; color: var(--ink); }
.client-merge-banner { display: grid; gap: 6px; margin: 0 0 12px; padding: 10px 12px; }
.client-merge-banner > .link-button { justify-self: start; }
.dialog-foot.is-merged-readonly > :not([data-dialog-close]) { display: none; }
