/* ---------------------------------------------------------------------------
   Back-office de base nautique.

   Direction : le vocabulaire visuel du port plutôt que celui du SaaS. Fonds
   ardoise humide, jaune de pavillon Kilo réservé aux seules actions, et
   monospace partout où la donnée est un identifiant ou un montant — comme sur
   un registre de capitainerie, où l'alignement des chiffres est fonctionnel.
--------------------------------------------------------------------------- */

:root {
    --ink:       #0B1E26;
    --hull:      #14313D;
    --ycgc-blue: #1E7FB0;   /* bleu du logo YCGC */
    --slate:     #3C5A66;
    --fog:       #7B939C;
    --mist:      #E8EEEC;
    --paper:     #FBFCFC;
    --line:      #C9D6D3;
    --signal:    #F0AB21;   /* ambre du logo YCGC */
    --starboard: #0E8A6E;
    --port:      #B8352C;

    --display: "Archivo", system-ui, sans-serif;
    --body:    "IBM Plex Sans", system-ui, sans-serif;
    --mono:    "IBM Plex Mono", ui-monospace, monospace;

    --step: 0.5rem;
    --radius: 3px;

    /* Hauteur du bandeau. En variable parce qu'elle sert maintenant à trois endroits :
       le bandeau lui-même, et le décalage des éléments collants qui viennent se ranger
       dessous. Trois valeurs recopiées finiraient par diverger d'un pixel qu'on
       cherche longtemps. */
    --masthead-h: 56px;
}

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

body {
    margin: 0;
    font-family: var(--body);
    font-size: 15px;
    line-height: 1.5;
    color: var(--ink);
    background: var(--mist);
}

.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* --- Bandeau ------------------------------------------------------------ */
.masthead {
    display: flex;
    align-items: center;
    gap: calc(var(--step) * 4);
    padding: 0 calc(var(--step) * 3);
    height: var(--masthead-h);
    background: var(--ink);
    color: var(--paper);

    /* Collant au défilement. sticky et non fixed : le bandeau reste dans le flux, donc
       la page n'a pas besoin d'un padding compensatoire que chaque écran aurait pu
       oublier. Un fixed aurait fait passer la première ligne de chaque page dessous.
       Fond opaque obligatoire — c'est lui qui masque le contenu qui glisse derrière.

       z-index 30 : au-dessus des entêtes de tableau collants (3 à 5) et de la barre de
       sélection multiple (6), en dessous de la bulle d'aide (40) qui est un panneau
       flottant et doit rester au premier plan. */
    position: sticky;
    top: 0;
    z-index: 30;
}

.brand { display: flex; align-items: center; gap: var(--step); text-decoration: none; color: inherit; }

/* Marque YCGC : la voile, détourée du lockup. Hauteur calée sur la ligne de texte. */
.brand-mark { height: 34px; width: auto; display: block; }

.brand-text {
    font-family: var(--display); font-weight: 700; letter-spacing: -0.01em;
    line-height: 1.1;
}

.brand-sub {
    display: block;
    font-family: var(--mono); font-weight: 400; font-size: 10px;
    letter-spacing: .12em; text-transform: uppercase;
    color: var(--fog);
}

.nav { display: flex; gap: calc(var(--step) * 3); margin-left: auto; }

.nav a {
    font-family: var(--display);
    font-weight: 500;
    font-size: 14px;
    color: #A9C0C8;
    text-decoration: none;
    padding: 4px 0;
    border-bottom: 2px solid transparent;
}
.nav a:hover { color: var(--paper); }
.nav a.on { color: var(--paper); border-bottom-color: var(--signal); }

.who { display: flex; align-items: center; gap: calc(var(--step) * 2); font-size: 13px; }
.who a { color: var(--fog); text-decoration: none; }
.who a:hover { color: var(--paper); }

.who .logout {
    font-family: var(--display);
    font-weight: 500;
    padding: 3px 9px;
    border: 1px solid #2C4A54;
    border-radius: var(--radius);
}
.who .logout:hover { border-color: var(--signal); color: var(--signal); }

main { max-width: 1180px; margin: 0 auto; padding: calc(var(--step) * 4) calc(var(--step) * 3); }

.foot {
    max-width: 1180px; margin: 0 auto;
    padding: calc(var(--step) * 3);
    font-size: 12px; color: var(--fog);
}

/* Lockup complet réservé à la connexion : fond clair, donc le texte noir du logo
   reste lisible. */
.login-lockup { margin-bottom: calc(var(--step) * 3); }
.login-lockup img { height: 120px; width: auto; display: block; }

/* --- Titres ------------------------------------------------------------- */
h1 {
    font-family: var(--display);
    font-weight: 700;
    font-size: 26px;
    letter-spacing: -0.015em;
    margin: 0 0 var(--step);
}

.eyebrow {
    font-family: var(--mono);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--fog);
    margin-bottom: 2px;
}

.page-head {
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: calc(var(--step) * 2);
    margin-bottom: calc(var(--step) * 3);
    padding-bottom: calc(var(--step) * 2);
    border-bottom: 1px solid var(--line);
}

/* --- Panneaux ----------------------------------------------------------- */
.panel {
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius);
}

.panel + .panel { margin-top: calc(var(--step) * 3); }

.panel-head {
    padding: calc(var(--step) * 2) calc(var(--step) * 2.5);
    border-bottom: 1px solid var(--line);
    font-family: var(--display);
    font-weight: 600;
    font-size: 14px;
    display: flex; align-items: baseline; gap: var(--step);
}

.panel-body { padding: calc(var(--step) * 2.5); }

/* --- Tableaux ----------------------------------------------------------- */
table { width: 100%; border-collapse: collapse; }

th {
    text-align: left;
    font-family: var(--mono);
    font-size: 11px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--slate);
    padding: var(--step) calc(var(--step) * 1.5);
    border-bottom: 1px solid var(--line);
    white-space: nowrap;
}

td {
    padding: calc(var(--step) * 1.25) calc(var(--step) * 1.5);
    border-bottom: 1px solid var(--mist);
    vertical-align: top;
}

tbody tr:hover { background: #F4F8F7; }

td.num, th.num { text-align: right; font-family: var(--mono); }
td.ref { font-family: var(--mono); font-size: 13px; color: var(--hull); }

.empty { padding: calc(var(--step) * 6); text-align: center; color: var(--fog); }
.empty strong { display: block; font-family: var(--display); color: var(--slate); margin-bottom: 4px; }

/* --- Champs ------------------------------------------------------------- */
.field { margin-bottom: calc(var(--step) * 2.5); }

.field > label {
    display: block;
    font-weight: 500;
    font-size: 13px;
    margin-bottom: 4px;
}

.field .help { font-size: 12px; color: var(--fog); margin-top: 3px; }
.field .err  { font-size: 12px; color: var(--port); margin-top: 3px; }

input[type=text], input[type=number], input[type=date], input[type=password],
input[type=datetime-local], select, textarea {
    width: 100%;
    padding: 7px 9px;
    font-family: var(--body);
    font-size: 14px;
    color: var(--ink);
    background: #fff;
    border: 1px solid var(--line);
    border-radius: var(--radius);
}

input:focus-visible, select:focus-visible, textarea:focus-visible {
    outline: 2px solid var(--signal);
    outline-offset: 1px;
    border-color: var(--slate);
}

input:disabled, select:disabled, textarea:disabled {
    background: var(--mist);
    color: var(--slate);
    cursor: not-allowed;
}

.check { display: flex; align-items: center; gap: var(--step); }
.check input { width: auto; }

/* --- Attributs dynamiques ----------------------------------------------
   L'élément signature : un attribut dynamique se distingue visuellement
   d'une colonne réelle, et porte son contrat de type en clair. L'écran de
   saisie devient ainsi la documentation du paramétrage.
------------------------------------------------------------------------ */
.dyn-group { margin-bottom: calc(var(--step) * 3); }

.dyn-group > h3 {
    font-family: var(--mono);
    font-size: 11px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--slate);
    margin: 0 0 calc(var(--step) * 1.5);
    padding-bottom: 4px;
    border-bottom: 1px solid var(--line);
}

.dyn-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 0 calc(var(--step) * 3);
}

.field.dyn {
    padding-left: calc(var(--step) * 1.5);
    border-left: 2px solid var(--signal);
}

.field.dyn > label { display: flex; align-items: baseline; gap: var(--step); flex-wrap: wrap; }

.badge {
    font-family: var(--mono);
    font-size: 10px;
    font-weight: 400;
    color: var(--slate);
    background: var(--mist);
    border: 1px solid var(--line);
    border-radius: 2px;
    padding: 1px 5px;
    white-space: nowrap;
}

.req { color: var(--port); }

/* --- Actions ----------------------------------------------------------- */
.btn {
    display: inline-flex; align-items: center; gap: 6px;
    font-family: var(--display);
    font-weight: 600;
    font-size: 14px;
    padding: 8px 14px;
    border: 1px solid transparent;
    border-radius: var(--radius);
    cursor: pointer;
    text-decoration: none;
}

.btn-primary { background: var(--signal); color: var(--ink); }
.btn-primary:hover { background: #DCA400; }

.btn-quiet { background: #fff; color: var(--hull); border-color: var(--line); }
.btn-quiet:hover { border-color: var(--slate); }

.btn:disabled { opacity: 0.45; cursor: not-allowed; }

.actions { display: flex; gap: var(--step); align-items: center; }
.actions.end { justify-content: flex-end; margin-top: calc(var(--step) * 3);
               padding-top: calc(var(--step) * 2); border-top: 1px solid var(--line); }

/* --- Filtres ----------------------------------------------------------- */
.filters { display: flex; gap: var(--step); align-items: flex-end; flex-wrap: wrap; }
.filters .field { margin-bottom: 0; min-width: 160px; }

/* --- États ------------------------------------------------------------- */
.pill {
    font-family: var(--mono);
    font-size: 11px;
    padding: 2px 7px;
    border-radius: 10px;
    border: 1px solid;
}
.pill.on  { color: var(--starboard); border-color: #A5D6C6; background: #EAF6F2; }
.pill.off { color: var(--port);      border-color: #E3B5B1; background: #FBEEED; }
/* Troisième état, entre les deux : « à renouveler ». Un diplôme qui expire dans trois
   semaines n'est ni valable au sens où l'on peut l'oublier, ni échu au sens où il faut
   déprogrammer quelqu'un. Le rendre vert le ferait manquer, le rendre rouge ferait
   confondre l'urgence avec la panne — et ce qui crie tout le temps ne se lit plus. */
.pill.warn { color: #8A5A00; border-color: #EBD08A; background: #FDF6E3; }

.notice {
    padding: calc(var(--step) * 1.5) calc(var(--step) * 2);
    border-left: 3px solid var(--port);
    background: #FBEEED;
    font-size: 14px;
    margin-bottom: calc(var(--step) * 3);
}
.notice.ok { border-color: var(--starboard); background: #EAF6F2; }

.readonly-banner {
    display: flex; align-items: center; gap: var(--step);
    padding: calc(var(--step) * 1.5) calc(var(--step) * 2);
    background: var(--mist);
    border: 1px dashed var(--line);
    border-radius: var(--radius);
    font-size: 13px; color: var(--slate);
    margin-bottom: calc(var(--step) * 3);
}



/* Ligne hors circuit : un tarif remplacé reste lisible pour l'audit sans se
   confondre avec un prix applicable. */
tbody tr.row-off td { opacity: .55; }
tbody tr.row-off td:first-child { font-style: italic; }

td.actions-cell { display: flex; gap: var(--step); white-space: nowrap; }

/* ---------------------------------------------------------------------------
   Grille de planning.

   Colonne de gauche figée et défilement horizontal : sur une vue mensuelle il y a
   31 colonnes, on ne peut pas les faire tenir sans perdre le nom de la ligne.
   La pastille est réduite à l'essentiel — heure, occupation, barre de remplissage —
   le reste passe par l'infobulle.
--------------------------------------------------------------------------- */

.grid-toolbar {
    display: flex; align-items: center; justify-content: space-between;
    gap: calc(var(--step) * 2); flex-wrap: wrap;
}

.grid-toolbar .period {
    font-family: var(--display); font-weight: 700; font-size: 17px;
    letter-spacing: -0.01em;
}

/* Sélecteur segmenté : échelle et mode */
.seg { display: inline-flex; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }

.seg a {
    font-family: var(--display); font-weight: 500; font-size: 13px;
    padding: 6px 12px; text-decoration: none; color: var(--hull); background: #fff;
    border-right: 1px solid var(--line);
}
.seg a:last-child { border-right: 0; }
.seg a:hover { background: var(--mist); }
.seg a.on { background: var(--ink); color: var(--paper); }

.grid-scroll {
    /* Défilement sur les DEUX axes, et il faut l'assumer plutôt que le subir.
       « overflow-x: auto » avec un overflow-y laissé à « visible » n'existe pas : la
       spécification force alors le second à « auto ». Cet élément était donc déjà un
       conteneur de défilement vertical, ce qui a une conséquence que rien à l'écran
       n'annonçait — voir l'entête collant plus bas.

       La hauteur borne la grille sous le bandeau et la barre d'outils, et laisse la
       place de la légende. C'est elle qui rend le collant utile : sans hauteur, la
       boîte ne défile jamais et l'entête n'a rien à quoi rester accroché. */
    overflow: auto;
    /* 316px = bandeau (56) + barre d'outils, bascules et légende (260). Écrit en
       clair et non en var(--masthead-h) : la règle juste en dessous remet cette
       variable à zéro pour toute la boîte, et elle vaudrait zéro ici aussi. */
    max-height: calc(100vh - 316px);
    overscroll-behavior: contain;
}

/* Ceinture et bretelles, après une rechute.
   .grid-scroll est un conteneur de défilement : tout ce qui est collant à
   l'intérieur se règle par rapport à LUI, pas par rapport à la page. Un décalage
   exprimé en hauteur de bandeau n'y a donc aucun sens — il y vaut zéro.

   La variable est redéfinie à 0 pour toute la boîte plutôt que corrigée règle par
   règle : la prochaine règle collante écrite ici héritera du bon référentiel sans
   que son auteur ait à connaître cette histoire. C'est la seule forme de correctif
   qui survit à la personne qui l'a écrit. */
.grid-scroll { --masthead-h: 0px; }

table.grid { border-collapse: separate; border-spacing: 0; min-width: 100%; }

table.grid th, table.grid td {
    border-bottom: 1px solid var(--line);
    border-right: 1px solid var(--mist);
    padding: 0;
    vertical-align: top;
}

table.grid thead th {
    /* top: 0, et non la hauteur du bandeau.

       Le décalage précédent supposait un collant relatif à la PAGE : « reste sous le
       bandeau ». Il ne l'a jamais été depuis que .grid-scroll porte un overflow, qui
       en fait le conteneur de défilement de référence. La consigne se lisait alors
       « place-toi 56 px sous le haut de la grille », et le collant l'appliquait dès
       le premier rendu : l'entête descendait se poser sur la première ligne du corps,
       en laissant à sa place une bande vide. C'est ce qu'on voyait à l'écran.

       Le bandeau reste couvert, mais par la hauteur de la boîte ci-dessus et non par
       un décalage : la grille ne passe plus dessous, elle s'arrête avant.

       z-index 4, au-dessus des entêtes de LIGNE (3) : un entête de groupe, qui
       couvre toute la largeur, passait par-dessus les heures en glissant dessous.
       Reste sous la barre de sélection multiple (6). */
    position: sticky; top: 0; z-index: 4;
    background: var(--hull); color: var(--paper);
    font-family: var(--mono); font-size: 11px; font-weight: 500;
    text-transform: uppercase; letter-spacing: .05em;
    padding: 7px 8px; text-align: center; white-space: nowrap;
}

table.grid thead th.we { background: #0E252E; }
table.grid thead th.today { background: var(--signal); color: var(--ink); }

/* Colonne des lignes, figée horizontalement */
th.grid-row-head {
    position: sticky; left: 0; z-index: 3;
    background: var(--paper);
    text-align: left;
    padding: 6px 10px;
    /* 200px suffisent à « SUP-03 — Paddle nº3 ». La largeur était calée sur le pire
       cas, elle mangeait l'espace des colonnes de données dans tous les autres. */
    min-width: 200px; max-width: 200px;
    width: 200px;
    border-right: 1px solid var(--line);
}

thead th.grid-row-head { z-index: 5; background: var(--ink); }   /* le coin, au-dessus des deux */

th.grid-row-head .swatch { margin-right: 7px; }

/* Libellé tronqué, jamais replié. Le style de base des `th` fige déjà le texte sur
   une ligne, mais rien ne le retenait dans la colonne : « DER-DBL-01 — DÉRIVEUR
   DOUBLE Nº1 » passait par-dessus la case de 08H. Le replier aurait épaissi les
   lignes d'un tiers sur une grille qui en compte vingt — on préfère les points de
   suspension, l'intitulé complet restant disponible dans l'infobulle du `th`.

   Bloc en ligne : `text-overflow` ne s'applique qu'à un conteneur de bloc qui
   masque son débordement. La largeur laisse la place de la pastille et de sa
   marge (10 + 7). `vertical-align: middle` des deux côtés parce que la ligne de
   base d'un bloc en ligne à débordement masqué est son bord inférieur — alignée
   par défaut, la pastille se serait retrouvée en haut du libellé. */
th.grid-row-head > .swatch { vertical-align: middle; }
th.grid-row-head .rlabel {
    font-weight: 500; font-size: 13px;
    display: inline-block; vertical-align: middle;
    max-width: calc(100% - 17px);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
th.grid-row-head .rsub {
    display: block; font-family: var(--mono); font-size: 10px;
    color: var(--fog); margin-left: 17px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Le curseur signale qu'il y a quelque chose à survoler : une troncature sans
   indice se lit comme une information perdue. */
tbody th.grid-row-head[title] { cursor: help; }

table.grid tbody td { background: #fff; padding: 3px; min-width: 88px; }
table.grid tbody td.we { background: #F5F8F7; }
table.grid tbody td.today { background: #FFFBEF; }
table.grid tbody tr:hover th.grid-row-head { background: var(--mist); }

/* Pastille de créneau */
.chip {
    position: relative; display: block; overflow: hidden;
    background: var(--c); color: #fff; text-decoration: none;
    border-radius: 3px; padding: 3px 6px; margin-bottom: 3px;
    font-size: 11px; line-height: 1.35;
    box-shadow: inset 0 -1px 0 rgba(0,0,0,.18);
}
.chip:last-child { margin-bottom: 0; }
.chip:hover { filter: brightness(1.12); outline: 2px solid var(--ink); outline-offset: 1px; }

.chip-time { font-family: var(--mono); font-weight: 500; }
.chip-occ  { font-family: var(--mono); float: right; opacity: .85; }

/* Barre de remplissage, en bas de la pastille */
.chip-fill {
    position: absolute; left: 0; bottom: 0; height: 2px;
    background: rgba(255,255,255,.9);
}

/* Complet : trame diagonale, lisible même en niveaux de gris */
.chip.full {
    background-image: repeating-linear-gradient(45deg,
        rgba(0,0,0,.22) 0 3px, transparent 3px 7px);
}

/* Annulé : rayé, désaturé, sans être invisible */
.chip.off { opacity: .45; text-decoration: line-through; }

/* -------------------------------------------------------------------------
   Temps hors activité, sur le planning des salariés
   -------------------------------------------------------------------------
   Hachuré, et pas simplement d'une autre couleur. La couleur porte déjà la
   NATURE — congés en bleu, arrêt en rouge, réunion en terre — et lui faire
   dire en plus « ceci n'est pas une séance » lui demanderait deux messages à
   la fois. La trame est le second signal, lisible même sur une pastille de
   soixante pixels et même en niveaux de gris : ce n'est pas du temps
   d'encadrement.

   Trame plus serrée et plus claire que celle de « complet », qui rayait déjà
   les créneaux pleins : les deux ne se rencontrent jamais sur la même
   pastille — une absence n'a pas de places — mais elles se voisinent sur la
   même grille, et deux hachures identiques s'y liraient comme un seul état. */
.chip.away {
    background-image: repeating-linear-gradient(135deg,
        rgba(255,255,255,.38) 0 2px, transparent 2px 6px);
    font-style: italic;
}

/* Le libellé remplace l'heure sur une absence : il tient rarement en entier.
   Tronqué plutôt que replié, comme les entêtes de ligne — une pastille qui
   grandit décale toute la trame horaire de la journée. */
.chip.away .chip-time {
    display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.chip-add {
    display: block; text-align: center; color: var(--line);
    text-decoration: none; font-size: 15px; line-height: 22px;
    border: 1px dashed var(--line); border-radius: 3px;
    /* Maj + clic étend sinon la sélection de texte du navigateur : la grille se
       surligne en bleu d'un bout à l'autre, ce qui donne l'impression que le geste
       a fait autre chose que ce qu'on voulait. */
    user-select: none; -webkit-user-select: none;
}
.chip-add:hover { color: var(--ink); border-color: var(--signal); background: #FFFBEF; }

/* Mode sélection actif : la cible passe de la petite dièse à la cellule entière.
   Viser un « + » de 22 pixels vingt fois de suite est un travail de précision que
   la souris ne mérite pas. */
table.grid.picking td:has(.chip-add) { cursor: copy; }
table.grid.picking .chip-add { color: var(--slate); border-color: var(--slate); }

/* Vue mensuelle : 31 colonnes, tout se resserre */
table.grid.dense tbody td { min-width: 42px; padding: 2px; }
table.grid.dense .chip { padding: 2px 3px; font-size: 10px; }
table.grid.dense .chip-occ { display: none; }
/* En vue mensuelle, 31 colonnes : le bouton se réduit à une pastille de couleur,
   le symbole n'y tiendrait plus lisiblement. */
table.grid.dense .chip-pay { flex-basis: 12px; font-size: 0; }
table.grid.dense th.grid-row-head { min-width: 190px; max-width: 190px; }



/* ---------------------------------------------------------------------------
   Déplacement et redimensionnement des créneaux
--------------------------------------------------------------------------- */
.chip.movable { cursor: grab; }
.chip.movable:active { cursor: grabbing; }

.chip.dragging { opacity: .4; }

/* Cible de dépôt : liseré franc plutôt qu'un fond coloré, qui se confondrait avec
   la teinte des pastilles voisines. */
td.drop-target {
    outline: 2px dashed var(--signal);
    outline-offset: -2px;
    background: #FFFBEF !important;
}

/* Poignée d'étirement : élément frère de la pastille, jamais enfant. À l'intérieur
   d'un lien draggable, le navigateur démarre un glisser dès le premier mouvement et
   annule les événements de pointeur — l'étirement devenait aléatoire.

   9 pixels de large et un curseur explicite : une poignée de 7 pixels invisible se
   rate une fois sur deux. */
.chip-grip {
    flex: 0 0 9px;
    align-self: stretch;
    cursor: ew-resize;
    border-radius: 2px;
    background: var(--line);
    background-image: linear-gradient(
        to right, transparent 3px, var(--slate) 3px, var(--slate) 4px,
        transparent 4px, transparent 5px, var(--slate) 5px, var(--slate) 6px, transparent 6px);
    touch-action: none;   /* sinon le geste défile la grille au doigt */
}
.chip-grip:hover { background-color: var(--signal); }

.chip-row.resizing .chip { outline: 2px solid var(--ink); outline-offset: 1px; }

/* Aperçu de la nouvelle durée pendant l'étirement : l'utilisateur doit savoir ce
   qu'il obtiendra avant de relâcher, sinon il relâche et corrige. */
.chip-row { position: relative; }

.chip-row.grow::after {
    content: attr(data-preview);
    position: absolute; top: -19px; right: 0;
    background: var(--ink); color: var(--paper);
    font-family: var(--mono); font-size: 10px;
    padding: 2px 5px; border-radius: 2px;
    white-space: nowrap; z-index: 10;
}

/* Durée portée par la pastille, à droite de l'heure. Une pastille posée dans la
   colonne de son heure de début ne dit rien de son étendue : un créneau de 4h30
   ressemblait à un créneau d'une heure. */
.chip-span {
    float: right;
    font-family: var(--mono);
    opacity: .85;
    padding-left: 4px;
}

@media (prefers-reduced-motion: reduce) {
    .chip.dragging { opacity: .6; }
}

/* ---------------------------------------------------------------------------
   Vue jour : une colonne par heure.
--------------------------------------------------------------------------- */

/* La table ne s'étire plus : avec une seule colonne de données, elle occupait
   toute la largeur et la colonne des supports doublait de taille. */
table.grid.byhour { min-width: 0; width: auto; }

table.grid.byhour thead th.hour {
    font-size: 10px; padding: 6px 4px;
    min-width: 62px;
}

table.grid.byhour tbody td { min-width: 62px; padding: 2px; }

/* Tranche horaire : une teinte alternée toutes les deux heures aide à se repérer
   sur treize colonnes identiques.

   Classe posée d'après l'heure de la colonne, et non :nth-child : depuis que les
   pastilles s'étalent sur leur durée, une cellule peut valoir plusieurs colonnes.
   La parité de rang cessait donc de suivre la parité horaire, et la trame se
   décalait après chaque créneau long — elle indiquait le contraire de ce qu'elle
   sert à indiquer. */
table.grid.byhour tbody td.hodd { background: #FAFCFB; }
table.grid.byhour tbody td.we.hodd { background: #F1F6F5; }

table.grid.byhour .chip { font-size: 10px; padding: 2px 4px; }
table.grid.byhour .chip-occ { display: none; }
table.grid.byhour .chip-pay { flex-basis: 16px; font-size: 10px; }

/* ---------------------------------------------------------------------------
   Regroupement par catégorie
--------------------------------------------------------------------------- */
tr.group-row th {
    position: sticky; left: 0; z-index: 3;
    background: var(--mist);
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    padding: 0;
    /* Le colspan couvre toute la largeur : la largeur figée des autres entêtes de
       ligne ne s'applique pas ici. */
    min-width: 0; max-width: none; width: auto;
}

.group-toggle {
    display: flex; align-items: center; gap: var(--step);
    width: 100%; padding: 6px 10px;
    background: none; border: 0; cursor: pointer;
    font-family: var(--display); font-weight: 600; font-size: 13px;
    color: var(--hull); text-align: left;
}
.group-toggle:hover { background: #DFE8E6; }
.group-toggle:focus-visible { outline: 2px solid var(--signal); outline-offset: -2px; }

.group-toggle .caret {
    font-size: 11px; color: var(--slate); width: 10px;
}

/* Pastille de couleur */
.swatch {
    display: inline-block; width: 10px; height: 10px;
    border-radius: 2px; vertical-align: baseline;
}
.swatch.striped {
    background: var(--slate);
    background-image: repeating-linear-gradient(45deg,
        rgba(255,255,255,.5) 0 2px, transparent 2px 5px);
}
.swatch.faded { background: var(--slate); opacity: .4; }

.legend { display: flex; flex-wrap: wrap; gap: calc(var(--step) * 2.5); }
.legend-item {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 12px; color: var(--slate);
}


/* Créneau et encaissement côte à côte : la pastille dit quoi, le bouton dit où en
   est l'argent. */
.chip-row { display: flex; gap: 2px; margin-bottom: 3px; align-items: stretch; }
.chip-row:last-child { margin-bottom: 0; }
.chip-row .chip { flex: 1; margin-bottom: 0; min-width: 0; }

.chip-pay {
    flex: 0 0 20px;
    display: flex; align-items: center; justify-content: center;
    background: var(--p); color: #fff; text-decoration: none;
    border-radius: 3px;
    font-family: var(--mono); font-size: 12px; font-weight: 500;
    box-shadow: inset 0 -1px 0 rgba(0,0,0,.18);
}
.chip-pay:hover { filter: brightness(1.15); outline: 2px solid var(--ink); outline-offset: 1px; }
.chip-pay:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }


/* Code de mode de règlement, en pastille colorée : au comptoir on cherche « comment
   a-t-il payé » avant tout autre détail. */
.method-tag {
    display: inline-block; min-width: 2.6rem; text-align: center;
    padding: 2px 7px; border-radius: 3px;
    background: var(--c); color: #fff;
    font-family: var(--mono); font-size: 12px; font-weight: 500;
}

/* Modes de règlement */
.method-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
    gap: var(--step);
}

.method {
    position: relative; display: block; cursor: pointer;
    padding: 10px 12px 10px 14px;
    border: 1px solid var(--line); border-radius: var(--radius);
    background: #fff;
    border-left: 4px solid var(--c);
}
.method:hover { border-color: var(--slate); }

/* La case radio reste dans le flux pour l'accessibilité, mais hors écran :
   l'étiquette entière fait office de cible, plus large et plus sûre au doigt. */
.method input { position: absolute; opacity: 0; pointer-events: none; }
.method:has(input:checked) { border-color: var(--c); background: #FBFDFC; box-shadow: inset 0 0 0 1px var(--c); }
.method:has(input:focus-visible) { outline: 2px solid var(--signal); outline-offset: 2px; }

.method-code {
    display: block; font-family: var(--mono); font-weight: 500; font-size: 15px;
    color: var(--ink);
}
.method-label { display: block; font-size: 12px; color: var(--slate); }
.method-note {
    display: block; font-family: var(--mono); font-size: 10px;
    color: var(--fog); margin-top: 2px;
}

.section-label {
    font-family: var(--mono); font-size: 11px; text-transform: uppercase;
    letter-spacing: .09em; color: var(--slate); margin: 0 0 var(--step);
}

.totals {
    display: flex; gap: calc(var(--step) * 4); flex-wrap: wrap;
    font-size: 13px; color: var(--slate);
}
.totals strong { display: block; font-size: 17px; color: var(--ink); }
.totals .rest strong { color: var(--port); }

.legend-title {
    font-family: var(--mono); font-size: 10px; text-transform: uppercase;
    letter-spacing: .09em; color: var(--fog);
}
.legend-sep { width: 1px; align-self: stretch; background: var(--line); }


/* Effectifs de flotte : la première question sur une flotte est « combien », pas
   « lesquels ». On y répond avant la liste. */
.fleet-counts { display: flex; flex-wrap: wrap; gap: calc(var(--step) * 4); }

.fleet-count { font-size: 13px; color: var(--slate); }
.fleet-count strong {
    display: block; font-size: 22px; color: var(--ink);
    font-variant-numeric: tabular-nums;
}

/* Sélection des supports d'un créneau. Grille dense : une base compte des dizaines
   de supports, une liste verticale imposerait un défilement interminable. */
/* --- Liste clé / valeur ------------------------------------------------- */
/* <dl> et non un tableau : ce sont des paires libellé-valeur, pas des lignes
   comparables entre elles. La grille se replie en une colonne sur mobile, où
   deux colonnes rendraient les valeurs illisibles. */
dl.kv {
    display: grid;
    grid-template-columns: minmax(180px, auto) 1fr;
    gap: 6px calc(var(--step) * 3);
    margin: 0 0 calc(var(--step) * 2);
    font-size: 14px;
}
dl.kv dt { color: var(--slate); font-weight: 500; }
dl.kv dd { margin: 0; }
dl.kv dd .help { display: block; margin-top: 1px; }

@media (max-width: 700px) {
    dl.kv { grid-template-columns: 1fr; gap: 2px; }
    dl.kv dd { margin-bottom: var(--step); }
}

/* --- Sélection des supports d'un créneau -------------------------------- */
.resource-pool {
    max-height: 380px; overflow-y: auto;
    border: 1px solid var(--line); border-radius: var(--radius);
    transition: opacity .12s;
}
/* Recalcul en cours : l'affichage pâlit sans se vider. Une liste qui disparaît
   le temps d'une requête fait perdre la ligne qu'on visait. */
.resource-pool.loading { opacity: .5; }

.resource-group + .resource-group { border-top: 1px solid var(--line); }

.resource-group-head {
    display: flex; align-items: center; gap: var(--step);
    padding: 5px var(--step);
    background: var(--mist);
    position: sticky; top: 0; z-index: 1;
}
.resource-group-head .rg-label { font-weight: 600; font-size: 12px; }
.resource-group-head .rg-free { margin-left: auto; }

.resource-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: 2px calc(var(--step) * 2);
    padding: var(--step);
}

.resource-pick {
    display: flex; align-items: baseline; gap: var(--step);
    font-size: 13px; padding: 3px 5px; border-radius: 2px; cursor: pointer;
}
.resource-pick:hover { background: var(--mist); }
.resource-pick input { width: auto; align-self: center; }
.resource-pick .rp-ref { font-size: 11px; color: var(--slate); }
.resource-pick .rp-label { flex: 1; }
.resource-pick:has(input:checked) { background: #FFFBEF; font-weight: 500; }

/* Motif de refus, en clair : « pris » sans dire par quoi oblige à ouvrir le
   planning dans un autre onglet pour comprendre. */
.resource-pick .rp-why {
    flex-basis: 100%; margin-left: 22px;
    font-size: 10px; font-family: var(--mono); color: var(--port);
}

/* Absent, sur le sélecteur d'encadrants. Teinté sans être désactivé, et c'est
   la différence de fond avec un support pris : la base n'interdit que le
   doublon de responsable. Griser une case cochable ferait mentir l'écran sur
   ce qu'elle accepte — et l'opérateur, lui, sait qu'un moniteur peut couvrir
   deux groupes d'Optimist. On l'avertit, on ne l'empêche pas. */
/* -------------------------------------------------------------------------
   Matrice des droits : dérogations nominatives
   -------------------------------------------------------------------------
   La couleur ne dit pas « autorisé ou non » — la valeur du sélecteur le dit
   déjà, et cent cinquante cases coloriées seraient un damier. Elle signale la
   seule chose qu'on cherche à repérer d'un coup d'œil : les cases QUI SORTENT
   du rôle. Un compte sans dérogation affiche donc une matrice entièrement
   neutre, et c'est le résultat souhaité. */
select.grant { border-color: var(--starboard); background: #F0F8F4; font-weight: 600; }
select.deny  { border-color: var(--port); background: #FCF2F1; font-weight: 600; }

.resource-pick.away { background: #F2F7FB; }
.resource-pick.away .rp-why { color: var(--slate); font-weight: 600; }

.resource-pick.taken { color: var(--fog); cursor: not-allowed; }
.resource-pick.taken:hover { background: transparent; }
.resource-pick.taken .rp-ref { color: var(--fog); }

/* Déjà affecté ici, et pris ailleurs depuis. La case reste cochée et active :
   la désactiver la retirerait de la soumission et supprimerait l'affectation
   sans que personne ne l'ait décochée. */
.resource-pick.clash { background: #FDF1F0; }
.resource-pick.clash .rp-why { font-weight: 600; }

.conflict-list { margin: var(--step) 0 0; padding-left: 18px; font-size: 13px; }
.conflict-list li { margin-bottom: 2px; }

/* Mode sélection actif : le bouton doit se voir enfoncé, sinon rien à l'écran ne
   dit pourquoi un clic sélectionne au lieu d'ouvrir la fiche. Sur aria-pressed et
   non sur une classe posée par le script : l'état accessible et l'état visible
   sont alors le même, et ne peuvent pas se contredire. */
#multi-toggle[aria-pressed="true"] {
    background: var(--signal); border-color: var(--signal);
    color: var(--ink); font-weight: 600;
}

/* --- Sélection de plusieurs supports depuis la grille -------------------- */
.multi-bar {
    /* Même décalage : cette barre porte le compte des supports cochés et le bouton de
       validation, elle doit rester lisible sous le bandeau. */
    position: sticky; top: var(--masthead-h); z-index: 6;
    display: flex; align-items: center; gap: calc(var(--step) * 2);
    padding: var(--step) calc(var(--step) * 2);
    margin-bottom: calc(var(--step) * 2);
    background: var(--ink); color: var(--paper);
    border-radius: var(--radius);
}

/* Indispensable, et pas une redondance : une règle d'auteur qui pose « display »
   l'emporte sur la feuille du navigateur, quelle que soit la spécificité. Sans
   cette ligne, `display: flex` ci-dessus neutralise l'attribut hidden et la barre
   reste affichée en permanence, sélection vide et bouton mort. */
.multi-bar[hidden] { display: none; }
.multi-bar .mb-count strong { color: var(--signal); font-size: 16px; }
.multi-bar .mb-when { font-size: 13px; opacity: .85; }

/* La liste des supports cède la place avant tout le reste : les boutons doivent
   rester atteignables sur une sélection de vingt paddles. */
.multi-bar .mb-list {
    flex: 1; min-width: 0;
    font-size: 11px; opacity: .7;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.multi-bar .btn { flex: none; }

/* Case retenue : le « + » discret devient une cible pleine, pour qu'une sélection
   éparpillée sur vingt lignes se compte d'un coup d'œil. */
.chip-add.picked {
    color: var(--ink); border-style: solid;
    border-color: var(--signal); background: var(--signal);
    font-weight: 600;
}

/* Pastille d'un créneau à plusieurs supports */
.chip-multi {
    float: right; margin-left: 4px;
    font-family: var(--mono); font-size: 10px;
    padding: 0 3px; border-radius: 2px;
    background: rgba(255,255,255,.28);
}

/* Sous-menu de navigation */
.nav .group { position: relative; }

.nav .group > .sub {
    position: absolute; top: 100%; left: 0; z-index: 20;
    display: none; min-width: 190px;
    background: var(--ink);
    border: 1px solid #2C4A54; border-radius: var(--radius);
    padding: 4px 0;
}

/* focus-within et non seulement hover : le sous-menu reste atteignable au clavier */
.nav .group:hover > .sub, .nav .group:focus-within > .sub { display: block; }

.nav .group .sub a {
    display: block; padding: 6px 12px; border-bottom: 0; white-space: nowrap;
}
.nav .group .sub a:hover { background: var(--hull); color: var(--paper); }

/* -------------------------------------------------------------------------
   Rubrique à l'intérieur d'un déroulant
   -------------------------------------------------------------------------
   Un intertitre, et non un second niveau de déroulant. Le choix mérite d'être
   écrit, parce que le second niveau était la demande de départ.

   Ces menus s'ouvrent au survol, sans JavaScript. Un sous-déroulant impose
   alors de traverser en diagonale une zone étroite pour atteindre le libellé
   suivant : le pointeur sort du parent, le panneau se referme, et l'entrée
   visée disparaît sous le curseur. C'est le même défaut que celui déjà
   rencontré sur le lien parent d'Administration, dont le panneau s'ouvrait
   par-dessus. Au doigt, c'est pire : il n'y a pas de survol, et un premier
   appui sur « Salariés » suivrait le lien au lieu d'ouvrir quoi que ce soit.

   L'intertitre coûte deux lignes de CSS, se lit d'un coup d'œil, reste
   annonçable par un lecteur d'écran et fonctionne au clavier comme au doigt.
   Il regroupe sans rien cacher — or ce que l'on cherchait, c'est de ne plus
   voir sept entrées de même rang, pas d'en masquer trois. */
.nav .group .sub .sub-head {
    display: block; padding: 8px 12px 3px;
    font-family: var(--mono); font-size: 10px; font-weight: 500;
    text-transform: uppercase; letter-spacing: .08em;
    color: var(--fog);
    /* Filet de séparation en haut seulement : il annonce la rubrique, il ne
       l'encadre pas. Le premier intertitre du panneau n'en porte pas, sinon il
       doublerait la bordure du panneau lui-même. */
    border-top: 1px solid #2C4A54; margin-top: 4px;
}

.nav .group .sub .sub-head:first-child { border-top: 0; margin-top: 0; }

/* Décalage des entrées de la rubrique : c'est lui qui fait le regroupement,
   la couleur de l'intertitre ne suffirait pas sur un fond sombre. */
.nav .group .sub a.sub-item { padding-left: 24px; }

/* --- Aide --------------------------------------------------------------- */
/* Bulle contextuelle et fiches de la page /Aide.

   Construite sur <details> : l'ouverture, la fermeture et l'accès au clavier
   sont pris en charge par le navigateur. Le marqueur natif est masqué, mais
   l'élément reste focusable et annonçable — c'est ce qui distingue un
   <summary> stylé d'un <div> avec un gestionnaire de clic. */

.help-bubble { position: fixed; right: calc(var(--step) * 3); bottom: calc(var(--step) * 3);
               z-index: 40; }

.help-bubble > summary { list-style: none; cursor: pointer; }
.help-bubble > summary::-webkit-details-marker { display: none; }
.help-bubble > summary::marker { content: ""; }

.help-bubble-tab {
    display: inline-flex; align-items: center; gap: 6px;
    font-family: var(--display);
    font-weight: 600;
    font-size: 14px;
    color: var(--ink);
    background: var(--signal);
    border-radius: 999px;
    padding: 10px 16px;
    /* Ombre portée, seule de l'application : la bulle flotte au-dessus du contenu
       et doit se détacher d'un tableau dense sans recourir à une bordure épaisse. */
    box-shadow: 0 2px 10px rgba(11, 30, 38, 0.28);
}
.help-bubble-tab:hover { background: #DCA400; }
.help-bubble > summary:focus-visible .help-bubble-tab {
    outline: 2px solid var(--hull); outline-offset: 2px;
}

/* Onglet réduit au seul « ? » quand la bulle est ouverte : le mot ferait doublon
   avec le titre du panneau, juste au-dessus. */
.help-bubble[open] .help-bubble-word { display: none; }

.help-bubble-panel {
    position: absolute; right: 0; bottom: calc(100% + var(--step));
    width: min(420px, calc(100vw - var(--step) * 6));
    /* Plafonnée à la hauteur de la fenêtre et défilable : certaines fiches font
       six étapes, et un panneau plus haut que l'écran cacherait ses propres
       dernières lignes sans moyen de les atteindre. */
    max-height: min(70vh, 620px);
    overflow-y: auto;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: 0 4px 20px rgba(11, 30, 38, 0.22);
    padding: calc(var(--step) * 2);
}

.help-bubble-head {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: var(--step);
    font-family: var(--display);
    padding-bottom: var(--step);
    border-bottom: 1px solid var(--line);
    margin-bottom: var(--step);
}
.help-bubble-head a { font-size: 13px; }

.help-bubble-foot {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: var(--step);
    margin-top: calc(var(--step) * 2);
    padding-top: var(--step);
    border-top: 1px solid var(--line);
    font-size: 13px;
}

/* Fiche repliée dans la bulle. */
.help-topic { border-bottom: 1px solid var(--mist); padding: var(--step) 0; }
.help-topic:last-of-type { border-bottom: 0; }
.help-topic > summary { cursor: pointer; display: flex; flex-direction: column; gap: 2px; }
.help-topic > summary:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }
.help-topic-title { font-family: var(--display); font-weight: 600; font-size: 14px; }

/* Étapes numérotées. Le compteur est celui du navigateur : renuméroter à la main
   dans le texte se serait décalé à la première étape insérée. */
.help-steps { margin: var(--step) 0 0; padding-left: 1.4rem; font-size: 14px; }
.help-steps > li { margin-bottom: var(--step); }
.help-steps > li > .help { display: block; margin-top: 2px; }

.help-warning {
    font-size: 13px;
    padding: var(--step) calc(var(--step) * 1.5);
    border-left: 3px solid var(--signal);
    background: #FDF6E6;
    margin: var(--step) 0 0;
}

/* Sommaire de la page /Aide. */
.help-index { display: flex; flex-wrap: wrap; gap: var(--step); margin-top: var(--step); }
.help-index a {
    font-size: 13px;
    padding: 4px 10px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: #fff;
    text-decoration: none;
}
.help-index a:hover { border-color: var(--slate); }

/* Compense l'en-tête au moment d'un saut d'ancre : sans cela, le navigateur place
   la fiche sous le bandeau et sa première ligne reste invisible. Depuis que le bandeau
   est collant, la compensation doit inclure sa hauteur — auparavant il défilait hors
   de vue et seule une marge de confort suffisait. */
.help-card { scroll-margin-top: calc(var(--masthead-h) + var(--step) * 3); }

/* Toute cible d'ancre, pas seulement les fiches d'aide : un lien vers #section d'une
   page quelconque tombait sinon derrière le bandeau. */
:target { scroll-margin-top: calc(var(--masthead-h) + var(--step) * 3); }

@media (max-width: 700px) {
    th.grid-row-head { min-width: 150px; max-width: 150px; }
    .grid-toolbar { flex-direction: column; align-items: flex-start; }
    /* Cadre défilant imbriqué dans une page défilante : au pouce, on ne sait jamais
       lequel des deux on fait bouger. Sur téléphone la grille reprend donc toute sa
       hauteur et c'est la page qui défile. L'entête cesse d'être collant — même
       arbitrage que pour le bandeau juste en dessous : sur un écran court, voir la
       donnée compte plus que voir les titres. */
    .grid-scroll { max-height: none; }
    .nav .group > .sub { position: static; display: block; border: 0; padding: 0; }
    /* Panneau déplié en permanence sur écran étroit : l'intertitre y devient la
       seule chose qui distingue une rubrique de la précédente, d'où le filet
       conservé et le décalage maintenu. */
    .nav .group .sub .sub-head { border-top-color: #2C4A54; }
}

@media (max-width: 700px) {
    /* Sur téléphone, le bandeau passe sur deux rangées — marque, puis navigation en
       défilement horizontal. Le garder collant lui donnerait un tiers de l'écran en
       permanence, sur une hauteur déjà entamée par la barre du navigateur. On rend donc
       le défilement, et les éléments qui se décalaient de sa hauteur reviennent à zéro.

       C'est un arbitrage, pas un oubli : sur un écran court, voir la donnée compte plus
       que voir le menu. */
    .masthead { height: auto; flex-wrap: wrap; padding: var(--step) calc(var(--step) * 2);
                position: static; }
    .nav { margin-left: 0; width: 100%; overflow-x: auto; }

    :root { --masthead-h: 0px; }
    .dyn-grid { grid-template-columns: 1fr; }
    .page-head { flex-direction: column; align-items: flex-start; }

    /* Ancrée aux deux bords : le panneau prend la largeur utile au lieu de sortir
       de l'écran par la droite. La hauteur est aussi réduite, le clavier virtuel
       mangeant la moitié basse d'un téléphone. */
    .help-bubble { left: calc(var(--step) * 2); right: calc(var(--step) * 2); }
    .help-bubble > summary { display: flex; justify-content: flex-end; }
    .help-bubble-panel { width: auto; left: 0; right: 0; max-height: 60vh; }
}

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

/* ---------------------------------------------------------------------------
   Reçu fiscal — Cerfa 11580

   Un document, pas un écran. Il se lit sur papier, il se classe, il ressort
   trois ans plus tard devant un contrôle. D'où la sobriété : encre noire,
   pas de fond coloré à imprimer, et les montants en monospace parce que
   c'est là que l'œil vérifie.

   Aucune bibliothèque PDF dans le projet : le navigateur en fabrique un, et
   mieux — il connaît le format du papier et l'imprimante de l'utilisateur.
--------------------------------------------------------------------------- */

.receipt {
    background: #fff;
    border: 1px solid var(--line);
    padding: calc(var(--step) * 5);
    max-width: 780px;                /* proche d'un A4 utile, à l'écran comme au tirage */
    margin: calc(var(--step) * 3) 0;
    color: #000;
}

.receipt-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: calc(var(--step) * 3);
    border-bottom: 2px solid #000;
    padding-bottom: calc(var(--step) * 2);
}

.receipt-kicker {
    font-family: var(--display);
    font-size: 1.05rem;
    font-weight: 600;
    line-height: 1.3;
}

.receipt-legal { font-size: 0.8rem; color: #444; margin-top: 2px; }

.receipt-no { text-align: right; white-space: nowrap; }
.receipt-no strong { font-size: 1.15rem; display: block; }

.receipt-label {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: #444;
}

.receipt-block { margin-top: calc(var(--step) * 3); }
.receipt-org { margin: calc(var(--step) * 0.5) 0 0; line-height: 1.45; }
.receipt-purpose, .receipt-note { font-size: 0.85rem; color: #333; }
.receipt-note { line-height: 1.4; }

/* Le montant est ce que l'on cherche en premier sur un reçu : il occupe la
   place qui correspond. */
.receipt-amount {
    border: 1px solid #000;
    padding: calc(var(--step) * 2);
    margin-top: calc(var(--step) * 3);
}

.receipt-sum { margin: var(--step) 0 0; }
.receipt-sum strong { font-size: 1.6rem; }

.receipt-words {
    margin: var(--step) 0 0;
    font-style: italic;
    text-transform: lowercase;       /* la majuscule initiale vient du texte lui-même */
}

.receipt-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: calc(var(--step) * 3);
    margin-top: calc(var(--step) * 3);
}

.receipt-grid p { margin: 2px 0 0; }

.receipt-table { width: 100%; border-collapse: collapse; margin-top: var(--step); }

.receipt-table th, .receipt-table td {
    border-bottom: 1px solid var(--line);
    padding: 4px 6px;
    text-align: left;
    font-size: 0.85rem;
}

.receipt-table thead th { border-bottom: 1px solid #000; }
.receipt-table tfoot th { border-top: 1px solid #000; border-bottom: 0; }
.receipt-table .num { text-align: right; }

.receipt-waiver {
    border-left: 3px solid #000;
    padding-left: calc(var(--step) * 2);
    margin: var(--step) 0 0;
}

.receipt-foot {
    display: flex;
    justify-content: space-between;
    gap: calc(var(--step) * 4);
    margin-top: calc(var(--step) * 4);
    padding-top: calc(var(--step) * 2);
    border-top: 1px solid var(--line);
}

.receipt-sign { text-align: right; min-width: 200px; }

.receipt-sign-box {
    border: 1px solid #000;
    height: 70px;
    margin-top: var(--step);
    font-size: 0.72rem;
    color: #777;
    padding: 3px 5px;
}

/* ---------------------------------------------------------------------------
   Impression

   Ce qui n'appartient pas au document sort du papier : bandeau, menu, boutons,
   avertissements d'écran. Ce qui reste est le reçu, et rien d'autre — sinon on
   remet au bénévole une capture d'écran de logiciel.
--------------------------------------------------------------------------- */
@media print {
    .no-print, .masthead, .nav, .help-bubble, .notice, .actions { display: none !important; }

    body { background: #fff; font-size: 11pt; }
    main, .wrap { margin: 0; padding: 0; max-width: none; }

    .receipt {
        border: 0;
        padding: 0;
        margin: 0;
        max-width: none;
    }

    /* Le tableau des frais ne doit pas se couper au milieu d'une ligne : une
       ligne à cheval sur deux pages se relit mal et se conteste. */
    .receipt-table tr { page-break-inside: avoid; }
    .receipt-block, .receipt-amount, .receipt-foot { page-break-inside: avoid; }

    /* Le pied porte la signature : il reste avec ce qui précède plutôt que de
       partir seul sur une deuxième page. */
    .receipt-foot { page-break-before: avoid; }

    a[href]::after { content: ""; }   /* pas d'URL imprimée derrière les liens */
}

@page { margin: 18mm 16mm; }

/* ---------------------------------------------------------------------------
   Éphéméride du bandeau
   ---------------------------------------------------------------------------
   À droite du lockup, avant la navigation. Séparée du logo par un filet plutôt que
   par un simple écart : sans lui, la date se lisait comme un sous-titre du nom du
   club.

   Masquée sous 1100 px. Ce n'est pas de la place gagnée pour rien : en dessous, la
   navigation passe déjà à l'étroit, et un agrément ne doit jamais pousser un menu
   hors de l'écran. La date reste accessible partout ailleurs dans l'application. */
.ephemeris {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: .1rem;
    margin-left: 1.1rem;
    padding-left: 1.1rem;
    border-left: 1px solid rgba(255, 255, 255, .18);
    line-height: 1.25;
    /* cursor: help plutôt que default : c'est ce qui signale qu'une infobulle attend
       le survol. Sans lui, la citation ne serait jamais découverte. */
    cursor: help;
}

.ephemeris-date {
    font-size: .78rem;
    color: rgba(255, 255, 255, .82);
    /* Première lettre en capitale : « samedi 5 septembre » et non « Samedi », le
       français ne capitalise pas les jours. C'est le CSS qui s'en charge pour que le
       libellé reste correct partout où il est réutilisé. */
    text-transform: none;
}

.ephemeris-note {
    font-size: .72rem;
    color: rgba(255, 255, 255, .55);
}

/* Les rendez-vous nautiques ressortent : c'est le bandeau d'une base nautique, et la
   Journée mondiale de l'océan y mérite plus qu'un gris.

   --signal, l'ambre du logo, et non une couleur inventée : c'est déjà la teinte des
   actions du thème, et en poser une seconde aurait fait deux ambres légèrement
   différents à quelques centimètres l'un de l'autre. */
.ephemeris-note.on {
    color: var(--signal);
}

@media (max-width: 1100px) {
    .ephemeris { display: none; }
}

/* ---------------------------------------------------------------------------
   Consigne du club, sous une fiche d'aide
   ---------------------------------------------------------------------------
   Visuellement DISTINCTE de la fiche, et c'est le point : les deux textes n'ont pas le
   même statut. La fiche est vérifiée au build par make check-help ; la consigne est
   saisie depuis l'interface et ne l'est pas. Les présenter à l'identique aurait laissé
   croire que le logiciel garantit la seconde.

   Un filet à gauche plutôt qu'un fond coloré : la page d'aide en affiche déjà plusieurs
   par écran, et autant de pavés teintés auraient fait un damier. Le filet marque sans
   peser. */
.club-note {
    margin: .8rem 0 0;
    padding: .55rem 0 .55rem .9rem;
    border-left: 3px solid var(--ycgc-blue);
    background: transparent;
}

.club-note-head {
    display: block;
    font-family: var(--mono);
    font-size: .68rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ycgc-blue);
    margin-bottom: .2rem;
}

.club-note p {
    margin: 0;
    font-size: .92rem;
    /* white-space: pre-line — une consigne se saisit dans un textarea, et les retours
       à la ligne qu'on y met sont voulus. Sans cela, deux règles écrites sur deux
       lignes se colleraient en un paragraphe. */
    white-space: pre-line;
}

/* ---------------------------------------------------------------------------
   Rappel d'audit de sécurité
   ---------------------------------------------------------------------------
   Au-dessus de la navigation, affiché seulement quand un audit est dû.

   Ambre et non rouge, contrairement au bandeau d'horloge simulée. La distinction est
   voulue : l'horloge signale que l'application MENT sur la date, ce qui fausse tout ce
   qu'on observe à l'instant même ; l'audit signale une échéance. Crier pendant douze
   mois userait l'alerte bien avant qu'elle serve, et le jour où un point critique est
   vraiment ouvert plus personne ne la verrait. */
.audit-banner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: calc(var(--step) * 2);
    padding: .4rem calc(var(--step) * 3);
    background: var(--signal);
    color: var(--ink);
    font-size: .8rem;
    line-height: 1.4;
    position: relative;
    z-index: 55;
}

.audit-banner strong { font-weight: 600; }
.audit-banner .mono { opacity: .75; }

.audit-banner a {
    margin-left: auto;
    color: var(--ink);
    font-weight: 600;
    text-decoration: underline;
}

/* La commande à copier, dans le tableau des points. Pré-formatée pour que les espaces
   soient sans ambiguïté — une commande recopiée de travers ne rend pas le bon résultat,
   et on met du temps à comprendre pourquoi. */
.panel pre.mono {
    margin: 0;
    padding: .4rem .5rem;
    background: var(--mist);
    border-radius: var(--radius);
    font-size: .74rem;
    line-height: 1.45;
    white-space: pre-wrap;
    word-break: break-all;
    max-width: 26rem;
}
