/* all */
*{
    box-sizing: border-box;
}
@font-face {
    font-family: 'FuturaPTDHeavy';
    src: url('./fonts/FuturaPTHeavy.otf') format('opentype');
    font-weight: normal;
    font-style: normal;
}
@font-face {
    font-family: 'FuturaPTDemi';
    src: url('./fonts/FuturaPTDemi.otf') format('opentype');
    font-weight: normal;
    font-style: normal;
}
@font-face {
    font-family: 'FuturaPTBook';
    src: url('./fonts/FuturaPTBook.otf') format('opentype');
    font-weight: normal;
    font-style: normal;
}

/* UNE ESPACE INSÉCABLE A EFFACÉ CETTE COULEUR PENDANT TOUT CE TEMPS.
   L'octet entre `color:` et la valeur était U+00A0, pas une espace : la
   déclaration était invalide, donc SILENCIEUSEMENT jetée par le navigateur.
   L'application entière tournait sur le #212529 de Bootstrap pendant que la
   feuille croyait imposer son gris. Une seule occurrence dans les quatre
   feuilles, invisible à l'œil — la §16 de tests/regression.sh en refuse
   désormais toute réapparition. */
body {
    font-family: 'FuturaPTBook', sans-serif;
    align-items: center;
    margin: 0;
    background-color: white;
    color: #424242;
}
/* `p { font-size: 16px !important }` a été retiré. Il ne posait RIEN — 16 px
   est déjà la taille du corps de page — mais son `!important` battait toutes
   les règles plus précises écrites ensuite : la note en italique du
   questionnaire (`.text_info`, 14 px) et la note d'un champ (`.dad-note-champ`,
   0.85 rem) s'affichaient l'un et l'autre à 16 px. Une
   déclaration qui n'ajoute rien et qui gagne contre tout le monde ne laisse
   que des dégâts. */
h1, h2, h3, h4, h5, h6 {
    font-family: 'FuturaPTDHeavy', sans-serif;
    color:#144466;
}
ul{
    list-style-type: none;
    padding: 0;
}
i{
    color: #2096d7;
}
i:hover{
    color: #1278b7;
}
a{
    text-decoration: none;
    color: #2096d7;
}
a:hover{
    text-decoration: underline;
    color: #2096d7;
}
/* DES COULEURS QUE PLUS AUCUN GABARIT NE DEMANDE.
   `.textTitle`, `.textError`, `.textLink`, `.mainColorIcon` et
   `.secondaryColorIcon` n'étaient posées nulle part — ni dans `app/`, ni dans
   un script. Les rôles qu'elles nommaient sont tenus par `.icone-accent`,
   `.icone-alerte`, `.lien-dad` et `.texte-encre`, écrites depuis. Seule
   `.textMainLabeur` a encore des porteurs. */
.textMainLabeur{
    color: #424242 !important;
}
/* custom components */
.icon-size {
    font-size: 20px;
    width: 20px;
    height: 20px;
}
.big-icon-size {
    font-size: 30px;
    width: 30px;
    height: 30px;
}
.small-icon-size {
    font-size: 15px;
    width: 15px;
    height: 15px;
}



/* checkbox */
/* La case native est masquée UNIQUEMENT lorsqu'un label .custom-checkbox prend
   le relais et la redessine en ::before. La règle visait auparavant toutes les
   .form-check-input : les contrôles qui n'ont pas de label personnalisé — la
   bascule « Journée entière » et la bascule « TU » des deux formulaires de
   demande — étaient donc rendus en opacity: 0, présents et cliquables mais
   parfaitement invisibles. */
.form-check-input:has(+ .custom-checkbox) {
    position: absolute;
    opacity: 0;
    cursor: pointer;
}

/* Styliser le label pour simuler la checkbox */
.custom-checkbox {
    position: relative;
    padding-left: 30px;
    cursor: pointer;
    font-size: 1rem;
}

/* Ajouter un carré personnalisé avant le label */
.custom-checkbox::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 20px;
    height: 20px;
    border: 2px solid rgb(32, 150, 215)!important;
    border-radius: 4px;
    background-color: white;
}

/* Ajouter une coche lorsque la checkbox est cochée */
.form-check-input:checked + .custom-checkbox::before {
    background-color: #2096d7!important;
    border-color: #2096d7!important;
}

.form-check-input:checked + .custom-checkbox::after {
    content: '\2713'; /* Symbole de coche */
    position: absolute;
    left: 5px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 1rem;
    color: white;
}

/* --- Dans un menu de cases à cocher, c'est la CASE qui répond ------------- */
/* Ces libellés sont des `.dropdown-item` : Bootstrap leur pose un fond gris
 * pleine largeur au survol et un fond bleu au clic. Sur une ligne de case à
 * cocher, ce bandeau désigne la ligne entière alors que le geste porte sur la
 * case — et il entre en concurrence avec le bleu de la case cochée. On rend
 * donc le libellé transparent, et on déplace le retour visuel sur le carré.
 * La ligne entière reste cliquable : c'est le confort d'un `<label for>`. */
.dropdown-menu .custom-checkbox:hover,
.dropdown-menu .custom-checkbox:focus,
.dropdown-menu .custom-checkbox:active {
    background-color: transparent;
    /* La couleur de repos, explicitement : Bootstrap passe le texte en blanc
       sur `:active`, ce qui le rendrait invisible une fois le fond bleu retiré. */
    color: var(--bs-dropdown-link-color);
}

/* Un halo pâle autour du carré, qui se lit aussi bien sur la case vide que sur
 * la case pleine — contrairement à un changement de fond. */
.dropdown-menu .custom-checkbox:hover::before {
    box-shadow: 0 0 0 3px var(--dad-bleu-pale);
}

/* La case native est en `opacity: 0` : sans cette règle, le focus clavier
 * n'aurait plus AUCUN repère une fois le fond du libellé retiré. */
.form-check-input:focus-visible + .custom-checkbox::before {
    outline: 2px solid var(--dad-bleu-fonce);
    outline-offset: 2px;
}

/* Components */
footer{
    color: #424242;
}
.footer p,
.footer a,
.footer ul,
.footer li,
.footer span {
    font-size: 0.85rem; /* Ajustez selon vos besoins */
}
.footer-social-links {
    display: flex;
    flex-direction: column;
    align-items: center;
}

/* LE PIED DE PAGE N'EST PAS UNE BARRE DE NAVIGATION.
 *
 * Ses liens portent pourtant `.nav-link` — la classe Bootstrap d'une entrée de
 * barre. Tant que le style du bandeau était écrit sur `.nav-link` nu, ils en
 * héritaient par accident ; rendu au bandeau, il les a laissés nus. Mesuré :
 * le bleu de la charte est devenu celui de Bootstrap (#0d6efd), les icônes
 * sociales sont repassées en `inline` et leur rangée a grandi de quinze
 * pixels, et le lien de copyright a perdu ses gouttières — sur TOUTES les
 * pages, côté client comme côté administration.
 *
 * Le pied de page dit maintenant lui-même ce qu'il veut, au lieu de vivre du
 * débordement d'une règle écrite pour quelqu'un d'autre. */
.footer .nav-link {
    display: flex;
    align-items: center;
    padding-left: 1rem;
    padding-right: 1rem;
    color: var(--dad-bleu-fonce);
}

.footer .nav-link:hover {
    color: var(--dad-bleu-fonce);
}

/* Mentions légales du pied de page (remplace un attribut style= en ligne). */
.footer-legal {
    position: relative;
    right: 10px;
    text-align: right;
}

/* SOUS 768 PX, LES TROIS BLOCS DU PIED DE PAGE NE TIENNENT PLUS CÔTE À CÔTE.
   Ils restaient pourtant sur une seule ligne : l'adresse se coupait en plein
   mot, et « 2025 NUMTECH - Tous droits réservés » s'empilait sur quatre lignes
   dans une colonne de cent pixels. Ils passent l'un sous l'autre. */
@media (max-width: 767.98px) {
    .footer > .container {
        flex-wrap: wrap;
        justify-content: center;
        gap: 1.5rem;
        text-align: center;
    }

    .footer-adresse,
    .footer-legal {
        right: 0;
        left: 0;
        text-align: center;
    }
}

/* ==========================================================================
   LA LIGNE DE PARTAGE EST SECTION CONTRE SITE
   --------------------------------------------------------------------------
   Bootstrap donne la même classe `.nav-link` à six barres qui n'ont RIEN à
   voir entre elles, et deux corrections successives se sont trompées de
   frontière.

   Écrire le style du bandeau sur `.nav-link` nu le donnait à TOUT LE MONDE :
   la vague de `underline.png` se posait sous les onglets de site, dans les
   cartes, où le texte est petit et où elle débordait. C'est ce que le client
   a demandé de retirer.

   Le scoper à `.navbar` l'a retiré à tout ce qui n'est pas la barre — dont
   « nouveaux devis / devis envoyés / devis annulés », qui n'ont jamais été
   visés. C'est ce que le client a redemandé.

   La frontière n'est donc PAS « le bandeau contre le reste ». Elle est :

   1. LES ONGLETS QUI DÉCOUPENT UN ÉCRAN EN SECTIONS.
      Le bandeau (`.navbar`), et les rangées qui changent de section de page
      (`.dad-onglets-section`) : « nouveaux devis / devis envoyés / devis
      annulés », « nouvelles commandes / en cours / finalisées / annulées ».
      Elles ne sont pas DANS la barre, mais elles font la même chose qu'elle.
      Futura, bleu de la charte, et la VAGUE sous la section courante.
      app/user/_navbar.php, app/admin/_navbar.php,
      app/admin/activite/activite.php

      Une CLASSE, pas `#requestTabs` : un identifiant ne se partage pas, et
      cette famille attend son équivalent côté client.

   2. LES ONGLETS QUI DÉCOUPENT UN CONTENU.
      Les sites d'une demande, les volets d'une modale : ils ouvrent un volet
      DANS l'écran. Petit texte, pas de
      vague — ce sont les onglets sobres de Bootstrap, et le cadre que la
      rangée laisse ouvert est refermé par `.dad-onglets-sites-contenu`
      (pages.css), des DEUX côtés depuis que le client l'a redemandé.
      app/utils/_onglets_sites_debut.php, app/admin/activite/_carte_demande.php,
      app/user/nouvelle_demande/demande_formulaire.php, app/utils/modale.php

   La règle de lecture : si le sélecteur ne dit pas s'il parle de sections ou
   de contenu, il est faux. La section 11 de `tests/regression.sh` l'exige.
   ========================================================================== */

.navbar-brand span {
    font-size: 1.2rem;
}

/* Famille 1 : le bandeau et les onglets de section. */
.navbar .nav-link,
.dad-onglets-section .nav-link {
    font-family: 'FuturaPTDHeavy', sans-serif;
    font-size: 1.125rem;
    color: #2096d7 !important;
    transition: color 0.2s ease;
    display: flex;
    align-items: center;
    position: relative;
}

.navbar .nav-link:hover,
.dad-onglets-section .nav-link:hover {
    color: #2096d7 !important;
}

.navbar .nav-link.active,
.dad-onglets-section .nav-link.active {
    font-weight: bold;
    color: #2096d7 !important;
    border-radius: 0;
}

/* LE TRAIT DE SOULIGNEMENT N'EST PAS POUR « ACTIVITÉ ».
 *
 * `::after` est déjà pris sur une entrée à menu déroulant : c'est le chevron
 * de Bootstrap. Cette règle l'écrasait, et « Activité » — la seule entrée du
 * bandeau qui déroule — récoltait les deux moitiés d'un accident : le
 * `border-top` du chevron, étiré sur les 94 px imposés par `left/right: 0`,
 * BARRAIT le mot ; et l'image, contenue dans un carré de 500 px devenu plus
 * étroit que haut, posait son trait bien plus bas que sur les autres entrées.
 * Le chevron, lui, avait disparu.
 *
 * Le souligné saute donc `::after` sur les entrées à menu, qui gardent leur
 * chevron — mais il ne les PRIVE PLUS de vague : « Activité » est une entrée
 * comme les autres. Elle prend `::before`, que le chevron n'utilise pas. */
.navbar .nav-link.active:not(.dropdown-toggle)::after,
.navbar .nav-link.active.dropdown-toggle::before,
.dad-onglets-section .nav-link.active::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 20px;
    height: 114px;
    background: url('../img/underline.png') no-repeat center;
    background-size: contain;
    pointer-events: none;
}

/* SOUS 992 PX, LE BANDEAU SE REPLIE EN LISTE VERTICALE : la vague, haute de
   114 px et posée en absolu, se serait couchée en travers des entrées
   suivantes. Les onglets de navigation, eux, restent une rangée à toute
   largeur — ils gardent donc leur vague. */
@media (max-width: 992px) {
    .navbar .nav-link.active:not(.dropdown-toggle)::after,
    .navbar .nav-link.active.dropdown-toggle::before {
        display: none;
    }
}

/* La rangée et le cadre de l'onglet courant viennent de `.nav-tabs`, que le
   gabarit pose déjà : rien à redire ici, seulement la famille à nommer. */

.navbar-toggler {
    border: none;
    color: #2096d7 !important;
}

.navbar-toggler-icon {
    background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba%28209, 150, 215, 1%29' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E");
}

.dropdown-menu {
    border-radius: 0.5rem;
}

/* Note d'accompagnement d'un champ ou d'une section du questionnaire. */
.text_info {
    font-size: 0.875rem;
    font-style: italic;
}

/* CE QUI MANQUE SE DIT SOUS LE CHAMP.
 *
 * Le questionnaire disait ses refus dans un rectangle rouge en haut de page —
 * « Site 1 : Format de sortie est obligatoire » — à plusieurs écrans du champ
 * en cause. La note reprend le ton de celle des coordonnées, qui est celle que
 * le client a désignée : petite, en italique, au fil du formulaire. Seule la
 * couleur change, parce qu'elle demande une correction et non un contrôle.
 *
 * `--dad-rouge` est la teinte d'alerte déjà en usage : rien de nouveau. */
.dad-note-champ {
    display: block;
    margin-top: 0.25rem;
    font-size: 0.875rem;
    font-style: italic;
    color: var(--dad-rouge, #b21e4b);
}
/* UN INTITULÉ DE CHAMP A UNE SEULE TAILLE, DANS TOUTE L'APPLICATION.
 *
 * Il y en avait quatre, et deux se côtoyaient dans la même modale : « Numéro
 * de devis* » (`.label_devis`, sans aucune règle, donc 1 rem) tenait au-dessus
 * de « Numéro de contrat* » (`.label_contrat`, 12 px) — un tiers plus gros que
 * son voisin de ligne, sans que rien ne le distingue. Le questionnaire posait
 * `.label_title` à 11 px, `.request_label` 10 px, et les 126 `.form-label`
 * restants gardaient le défaut de Bootstrap.
 *
 * Une seule règle : `.request_label` disparaît — aucun gabarit ne la pose.
 *
 * MAIS 12 PX ÉTAIT LA MAUVAISE TAILLE COMMUNE.
 *
 * Unifier était juste ; s'aligner sur la PLUS PETITE des quatre ne l'était pas.
 * « Adresse », « Entrez une adresse », « Numéro de devis », « Coût total »,
 * « Commentaire (visible par le client) » — la moitié des intitulés du
 * questionnaire et de toutes les modales — se lisaient mal, côté client comme
 * côté administration. En `rem`, la taille suit désormais le réglage du
 * navigateur, ce qu'une valeur en pixels ne faisait pas. */
.form-label,
.label_contrat,
.label_devis,
.label_title {
    font-size: 0.9375rem;
    color: #144466;
}

/* CE QUI ACCOMPAGNE LE CHAMP SUIT SON INTITULÉ.
 *
 * La valeur saisie, l'invite qui l'attend et la note d'aide en dessous se
 * lisaient toutes plus petit que l'étiquette au-dessus. `form-control-sm` est
 * posé sur trois écrans pour sa HAUTEUR — Bootstrap y attache aussi une taille
 * de texte, et c'est elle qui rendait « Entrez une adresse » illisible. On garde
 * la hauteur, on rend la taille. */
.form-control,
.form-select,
.form-control-sm,
.form-select-sm {
    font-size: 0.9375rem;
}

.form-text {
    font-size: 0.875rem;
}

.popover-header {
    background-color: #007bff;
    color: white;
    font-weight: bold;
}

.popover-body {
    font-size: 0.9rem;
}

/* UNE SEULE DÉFINITION. `.custom-switch` était écrite ici EN `inline-flex` et
   une seconde fois dans `demandes.css` en `flex` ; la seconde feuille étant
   chargée après, c'est elle qui gagnait, et l'intention écrite ici n'a jamais
   rien produit. Les deux sont réunies, la valeur retenue est celle qui
   s'appliquait réellement. */
.custom-switch {
    position: relative;
    display: flex;
    align-items: center;
    cursor: pointer;
}

.custom-switch input {
    opacity: 0;
    width: 0;
    height: 0;
}

.slider {
    position: relative;
    display: inline-block;
    width: 60px;
    height: 34px;
    background-color: #ccc;
    border-radius: 34px;
    transition: .4s;
}

.slider:before {
    position: absolute;
    content: "";
    height: 26px;
    width: 26px;
    left: 4px;
    bottom: 4px;
    background-color: white;
    border-radius: 50%;
    transition: .4s;
}

input:checked+.slider {
    background-color: #2196F3;
}

input:checked+.slider:before {
    transform: translateX(26px);
}

.label-text {
    margin-left: 10px;
}

.info-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background-color: #fb8c00;
    color: white;
    font-style: normal;
    font-weight: bold;
    font-size: 0.875rem;
    margin-left: 10px;
    cursor: pointer;

}

.switch-info {
    display: block;
    margin-top: 10px;
    font-size: 0.875rem;
    font-style: italic;
    color: #666;
}
/* ==========================================================================
   Suggestions d'adresse — une liste ancrée sous son champ
   --------------------------------------------------------------------------
   `position: absolute` avec `left: 0; right: 0` se résout sur le PREMIER
   ANCÊTRE POSITIONNÉ. Sans lui, ce n'est pas le champ que la liste épouse,
   c'est la fenêtre : mesurée sur le questionnaire, elle s'ouvrait à 1440 px
   sous un champ de 350 px — « toute la largeur de l'écran ».

   Cela avait déjà été corrigé, en posant `.position-relative` autour de chaque
   champ d'adresse dans `_bloc_localisation.php`. Ce fichier a disparu quand le
   questionnaire est passé au registre, et l'enveloppe avec lui : la liste est
   désormais insérée par `multisite_tabs.js` à côté du champ, dans une colonne
   de grille que personne ne pense à positionner.

   La règle ne dépend donc plus d'une classe que le prochain remaniement
   oubliera : c'est LA PRÉSENCE DE LA LISTE qui positionne son conteneur. Un
   `:has()` à combinateur enfant ne touche que les éléments qui en portent une
   — le dépôt s'en sert déjà pour le masquage des cases natives.
   ========================================================================== */
:has(> .autocomplete-items) {
    position: relative;
}

/* UNE COLONNE DE GRILLE N'A PAS LA LARGEUR DE SON CHAMP.
   Un bloc en position absolue se cale sur la boîte de PADDING de son repère,
   et une colonne Bootstrap porte une demi-gouttière de chaque côté : la liste
   ressortait de douze pixels à gauche et à droite du champ qu'elle prolonge.
   On lui rend les deux gouttières — les mêmes que Bootstrap calcule, et
   seulement là où il y en a. */
[class*="col-"]:has(> .autocomplete-items) > .autocomplete-items,
.col:has(> .autocomplete-items) > .autocomplete-items {
    left: calc(var(--bs-gutter-x, 1.5rem) * .5);
    right: calc(var(--bs-gutter-x, 1.5rem) * .5);
}

/* Vide, elle ne doit rien dessiner : avec une bordure et un fond, un div en
   `position: absolute` sans enfant se voyait comme un trait horizontal juste
   sous le champ adresse. */
.autocomplete-items:empty {
    display: none;
}

/* L'enveloppe d'un `.dropdown-menu` : c'est un menu, il doit en avoir l'air. */
.autocomplete-items {
    position: absolute;
    z-index: 99;
    left: 0;
    right: 0;
    margin-top: 2px;
    background-color: #ffffff;
    border: 1px solid rgba(0, 0, 0, .15);
    border-radius: .375rem;
    /* Au-delà de six lignes environ, la liste défile au lieu de recouvrir la
       moitié du formulaire. En `rem`, la limite suit le réglage du navigateur
       en même temps que la hauteur des lignes. */
    max-height: 17rem;
    overflow-y: auto;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

/* Les trois sources qui remplissent cette liste — `autocomplete.js`,
   `clients.js`, `multisite_tabs.js` — posent toutes `.autocomplete-item` sur
   leurs lignes. Le sélecteur les nomme plutôt que de parier sur `div`. */
.autocomplete-items .autocomplete-item,
.autocomplete-items > div {
    padding: .5rem .625rem;
    cursor: pointer;
    /* La taille d'une suggestion est celle du champ qu'elle remplit. */
    font-size: 0.9375rem;
    line-height: 1.4;
    border-bottom: 1px solid #f1f1f1;
    color: #144466;
}

.autocomplete-items .autocomplete-item:last-child,
.autocomplete-items > div:last-child {
    border-bottom: none;
}

.autocomplete-items .autocomplete-item:hover,
.autocomplete-items > div:hover {
    background-color: #f1f8fe;
    color: var(--dad-bleu-fonce, #2096d7);
}

/* La ligne choisie au clavier, quand le script en pose une. */
.autocomplete-items .autocomplete-active,
.autocomplete-items > div.autocomplete-active {
    background-color: var(--dad-bleu-fonce, #2096d7);
    color: #fff;
}
/* badge */
.badge {
    font-size: 0.85rem;
    padding: 0.3em 0.6em;
}
.bg-contract{
    background-color: #F2C36B;
    color: #032340;
    font-weight: 400;
}
.bg-out-contract{
    background-color: #F2865E;
    color: #032340;
    font-weight: 400;
}
.bg-status{
    background-color: #CAD959;
    color: #032340;
    font-weight: 400;
}
/* Le rouge de la charte, celui des actions destructrices : une demande annulée
 * se voit d'un coup d'oeil, y compris dans l'onglet qui ne contient qu'elles. */
.bg-annule{
    background-color: #b21e4b;
    color: #ffffff;
    font-weight: 400;
}
.badge.bg-primary { background-color: #007bff; color: white; }
.badge.bg-success { background-color: #28a745; color: white; }
.badge.bg-danger{ background-color: #dc3545; color: white; }

.transition-card:hover {
    transform: scale(1.02);
    transition: all 0.3s ease-in-out;
}

/* LES CINQ COULEURS DU TABLEAU DE BORD — LISIBLES, CETTE FOIS.
 *
 * Elles distinguent les cinq cartes de l'écran d'accueil de l'équipe : devis,
 * commandes, commandes en cours, comptes à activer, bons de commande. Le client
 * les veut, et elles font lire l'écran d'un coup d'œil.
 *
 * TROIS PORTAIENT DU BLANC SUR UN FOND TROP CLAIR POUR LUI. Mesuré : 2,01:1
 * pour la menthe, 1,96:1 pour l'or, 2,45:1 pour le bleu de la charte — le seuil
 * du texte courant est 4,5:1. La framboise (4,61:1) et le marine (8,54:1)
 * passaient déjà et n'ont pas bougé ; les trois autres sont assombries dans la
 * même famille, sans changer de teinte.
 *
 * Les ratios sont tenus par `tests/verifier_contraste.php` : une teinte
 * éclaircie fera tomber la suite au lieu de rendre un titre invisible. */
.bg-gradient-primary {
    background: linear-gradient(45deg, #C94378, #A13260);
}

.bg-gradient-secondary {
    background: linear-gradient(45deg, #2E7D63, #24634E);
}

.bg-gradient-accent {
    background: linear-gradient(45deg, #2D4A8A, #1E3366);
}

.bg-gradient-warning {
    background: linear-gradient(45deg, #8A6A16, #71570F);
}

.bg-gradient-info {
    background: linear-gradient(45deg, #1B6FA8, #15597F);
}

/* Un compteur reprend la teinte de sa carte, dans sa version foncée : c'est
   celle qui se lit sur blanc. Les quatre chiffres de 40 px étaient peints en
   `.text-warning` (#ffc107) à 1,63:1 et `.text-info` (#0dcaf0) à 1,96:1 — le
   seuil du grand texte est 3:1, celui du texte courant 4,5:1. */
.dad-compteur-devis     { color: #A13260; }
.dad-compteur-commandes { color: #24634E; }
.dad-compteur-cours     { color: #71570F; }
.dad-compteur-comptes   { color: #15597F; }

/* Rangée d'actions en bas des cartes admin : identique à tous les statuts. */
.card-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    gap: 0.5rem;
    margin-top: 1rem;
}

/* Boutons de bas de carte : une hauteur uniforme, contenu centré.
 *
 * LE TEXTE D'ATTENTE EST DE LA RANGÉE, LUI AUSSI. « Demande reçue par l'équipe
 * DAD, création du devis en cours. » est un simple `<span>` posé entre les
 * boutons. Étiré par `align-items: stretch`, il calait sa ligne en HAUT de la
 * rangée pendant que les boutons centraient la leur : mesuré au navigateur,
 * sept pixels d'écart entre deux textes censés se lire côte à côte. */
.card-actions > .btn,
.card-actions > a.btn,
.card-actions > span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Carte des formulaires de demande : une seule hauteur pour les deux parcours. */
.carte-site {
    height: 70vh;
    min-height: 300px;
}

/* ==========================================================================
   Charte des boutons — trois rôles, une seule famille
   --------------------------------------------------------------------------
   L'application mélangeait douze variantes Bootstrap (primary, success, dark,
   info, warning, secondary, light, danger, leurs déclinaisons outline) et trois
   classes maison (mainButton, dangerButton, button — cette dernière sans aucune
   règle CSS). Le même geste ne portait pas la même couleur d'un écran à l'autre.

   Désormais un bouton dit ce qu'il fait, pas de quelle couleur il est :
     .btn-dad         l'action attendue de l'écran (Enregistrer, Envoyer, Valider)
     .btn-dad-neutre  le retrait ou une action secondaire (Annuler, Fermer, Voir)
     .btn-dad-danger  une action destructrice (Supprimer, Refuser)

   Même forme pour les trois, seule la teinte change : ils se lisent comme une
   famille, et le client comme l'administration partagent la même charte.
   ========================================================================== */
:root {
    --dad-bleu: #46AFE8;
    --dad-bleu-fonce: #2096d7;
    --dad-encre: #192d52;
    --dad-gris: #6c757d;
    --dad-rouge: #b21e4b;
    --dad-bleu-pale: #e3f2fd;
    /* Fond d'un volet d'onglets de contenu, et de l'onglet qui l'ouvre. */
    --dad-onglet-fond: #fcfdfe;
}

.btn-dad,
.btn-dad-neutre,
.btn-dad-danger {
    background-color: #fff;
    border: solid 1px currentColor;
    font-weight: 600;
    transition: background-color .2s ease, color .2s ease;
}

.btn-dad { color: var(--dad-encre); border-color: var(--dad-bleu); }
.btn-dad:hover,
.btn-dad:focus { background-color: var(--dad-bleu-fonce); border-color: var(--dad-bleu-fonce); color: #fff; }

.btn-dad-neutre { color: var(--dad-gris); border-color: var(--dad-gris); }
.btn-dad-neutre:hover,
.btn-dad-neutre:focus { background-color: var(--dad-gris); border-color: var(--dad-gris); color: #fff; }

.btn-dad-danger { color: var(--dad-rouge); border-color: var(--dad-rouge); }
.btn-dad-danger:hover,
.btn-dad-danger:focus { background-color: var(--dad-rouge); border-color: var(--dad-rouge); color: #fff; }

/* Une icône dans un bouton prend la couleur du bouton : la règle globale
   « i { color: #2096d7 } » peignait en bleu jusqu'aux icônes des boutons de
   suppression, qui affichaient donc une corbeille bleue sur un cadre rouge. */
.btn i,
.btn .bi,
.btn .fa { color: inherit; }

/* Un bouton désactivé garde son rôle, simplement atténué. Bootstrap applique
   sa propre teinte grise via .btn:disabled (deux niveaux de spécificité) : on
   repasse devant avec .btn.btn-dad:disabled plutôt qu'avec un !important. */
.btn.btn-dad:disabled,
.btn.btn-dad-neutre:disabled,
.btn.btn-dad-danger:disabled,
.btn.btn-dad.disabled,
.btn.btn-dad-neutre.disabled,
.btn.btn-dad-danger.disabled {
    background-color: #fff;
    opacity: .45;
}
.btn.btn-dad:disabled, .btn.btn-dad.disabled { color: var(--dad-encre); border-color: var(--dad-bleu); }
.btn.btn-dad-neutre:disabled, .btn.btn-dad-neutre.disabled { color: var(--dad-gris); border-color: var(--dad-gris); }
.btn.btn-dad-danger:disabled, .btn.btn-dad-danger.disabled { color: var(--dad-rouge); border-color: var(--dad-rouge); }

/* ==========================================================================
   Coquille de page — une seule façon d'ouvrir un écran
   --------------------------------------------------------------------------
   Chaque page ouvrait son conteneur à sa manière : « container » ici,
   « container-fluid » pour l'administration (seule page à occuper toute la
   largeur, 1440 px contre 1320 ailleurs, sans la moindre gouttière), un
   min-height écrit de quatre façons différentes en style inline, mt-5 ou my-5
   selon l'humeur, et parfois un second « container » imbriqué dans une carte
   qui ajoutait une gouttière de plus.

   Désormais : <div class="container dad-page"> et rien d'autre.
   ========================================================================== */
.dad-page {
    min-height: 75vh;
    margin-top: 3rem;
    margin-bottom: 3rem;
}

/* --------------------------------------------------------------------------
   `.container` REDEVIENT CELUI DE BOOTSTRAP.

   Une règle le forçait ici en `max-width: none` avec douze pixels de gouttière,
   pour que les listes prennent toute la largeur. Deux écrans l'ont démentie :
   l'en-tête d'accueil, un `space-between` entre un texte et une illustration,
   les écartait de plus de mille deux cents pixels ; la barre de filtres, dont
   les champs sont en `flex: 1 1 12rem`, s'étirait jusqu'au bord.

   Bootstrap borne par paliers — 1140 px à partir de 1200, 1320 au-delà — et
   centre. C'est ce que faisait la version servie, et c'est ce que le client a
   redemandé, sur toutes les pages : client comme administration. La barre de
   navigation et le pied emploient le même `.container`, donc tout s'aligne.

   `.container-fluid` retrouve aussi son sens : les trois écrans de connexion
   s'en servent pour occuper la fenêtre entière, ce que l'override rendait
   indistinct de `.container`.
   -------------------------------------------------------------------------- */


/* ==========================================================================
   Couleurs de contenu — sorties des styles inline
   --------------------------------------------------------------------------
   129 couleurs étaient écrites en dur dans le markup, dont deux bleus presque
   identiques employés pour la même chose : #44b1e9 (76 fois) et #46AFE8
   (20 fois). Ils convergent vers --dad-bleu, comme la charte des boutons.
   ========================================================================== */
.icone-accent      { color: var(--dad-bleu); }
.icone-alerte      { color: #fb8c00; }
.icone-commentaire { color: #e94468; }

/* En-tête de carte : le bleu pâle était répété huit fois en style inline. */
.dad-carte-entete { background-color: var(--dad-bleu-pale); }

/* Mention discrète accompagnant une donnée (statut, précision de format). */
.mention-donnee {
    color: var(--dad-bleu-fonce);
    font-style: italic;
    font-size: 1em;
}
/* Icône d'aide cliquable. */
.icone-aide {
    cursor: pointer;
    color: #fb8c00;
}

/* ------------------------------------------------------------------ *
 * Motifs qui vivaient en style inline
 *
 * 84 attributs style= décoratifs restaient dans les pages, dont neuf
 * couleurs en dur qu'aucune n'empruntait à la charte. Trois d'entre eux
 * étaient des déclarations mortes.
 * ------------------------------------------------------------------ */

/* Liste à puces des paramètres sélectionnés.
   La puce s'écrivait « background- border-radius: 50% » : le nom de
   propriété est incomplet, le navigateur jetait la déclaration entière — et
   le border-radius avec. Il restait un carré de 8px sans fond, donc rien à
   l'écran. */
.dad-liste-puces {
    list-style: none;
    padding-left: 0;
    margin-bottom: 0;
}
.dad-liste-puces li {
    display: flex;
    align-items: center;
    margin-bottom: 0.3rem;
}
.dad-puce {
    flex: none;
    width: 0.5rem;
    height: 0.5rem;
    margin-right: 0.5rem;
    border-radius: 50%;
    background-color: var(--dad-bleu);
}

/* Œil « afficher le mot de passe ».
   Il était positionné à la main sur chaque page — top 70%, 71%, 73%, 28px,
   30px — donc à une hauteur différente selon l'écran. Ancré sur le bas du
   groupe, il tombe juste quelle que soit la hauteur du libellé. */
.dad-oeil-mdp {
    position: absolute;
    right: 0;
    bottom: 0;
    height: calc(2.25rem + 2px);
    display: flex;
    align-items: center;
    border: 0;
    background: none;
    color: var(--dad-gris);
}
.dad-oeil-mdp:hover,
.dad-oeil-mdp:focus {
    color: var(--dad-encre);
}

/* Aligner un contrôle sur la hauteur d'un .form-control. */
.dad-hauteur-champ {
    height: calc(2.25rem + 2px);
}

/* Séparateur à l'intérieur d'une carte : c'était un <hr> « dotted blue »,
   le bleu brut du navigateur, hors charte. */
.dad-separateur {
    border: 0;
    border-top: 1px dotted var(--dad-bleu);
    opacity: 0.6;
}

/* Couleurs de texte : #007bff, blue, #144466, #11517b, #666, #555 et #333
   étaient posés en dur. */
.lien-dad {
    color: var(--dad-bleu-fonce);
    text-decoration: underline;
    font-weight: bold;
}
.texte-encre {
    color: var(--dad-encre);
}
.texte-discret {
    color: var(--dad-gris);
}

/* Icône des cartes « type de demande ». */
.icone-choix {
    font-size: 2.5rem;
}

/* Élément cliquable qui n'est pas un bouton (label d'un input fichier). */
.curseur-main {
    cursor: pointer;
}

/* Adresse du pied de page (déplacée depuis un style inline). */
.footer-adresse {
    position: relative;
    left: 10px;
    font-size: 0.85rem;
    line-height: 14px;
}

/* ---------------------------------------------------------------------------
   Pages d'authentification (connexion, mot de passe, inscription, confirmation).
   Ces règles vivaient en attributs style= et dans un <style> de
   confirm_registration.php (standards §7). Celui-ci restylait des sélecteurs
   globaux (h1, p, .btn) : elles sont scopées sous la classe de la page. */
.page-auth {
    height: 87vh;
}

.carte-auth {
    border-radius: 15px;
    max-width: 500px;
}

.illustration-connexion {
    max-height: 20vh;
}

.logo-reinitialisation {
    max-height: 300px;
}

.texte-justifie {
    text-align: justify;
}

.page-confirmation {
    height: 70vh;
}

.page-confirmation .container {
    max-width: 500px;
    background-color: #ffffff;
    padding: 20px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
    border-radius: 10px;
    text-align: center;
}

.page-confirmation h1 {
    color: #007bff;
    margin-bottom: 20px;
}

.page-confirmation p {
    margin-bottom: 20px;
    color: #333;
}

.page-confirmation .btn {
    display: inline-block;
    padding: 10px 20px;
    background-color: #007bff;
    color: #fff;
    text-decoration: none;
    border-radius: 5px;
    font-size: 1rem;
    transition: background-color 0.3s;
}

.page-confirmation .btn:hover {
    background-color: #0056b3;
}

/* ---------------------------------------------------------------------------
   Accueil client et profil. Ces règles vivaient en attributs style=
   (standards §7) ; le reste des cas est couvert par les utilitaires
   Bootstrap (text-start, lh-base, w-auto). */
.zone-accueil {
    min-height: 75vh;
}


.illustration-accueil {
    max-width: 170px;
}

.carte-profil {
    max-width: 500px;
    width: 100%;
    border-radius: 15px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.avatar-profil {
    max-height: 20vh;
    border-radius: 50%;
}

/* Texte stocké avec ses retours à la ligne (commentaires de demande). */
.texte-multiligne {
    white-space: pre-line;
}


/* ==========================================================================
   Pagination — la même partout, sur UNE ligne
   --------------------------------------------------------------------------
   « Précédente », le compte, « Suivante » : trois frères, une rangée. La règle
   disait `flex-direction: column` et les empilait — les deux boutons tombaient
   au-dessus et au-dessous de « Page 1 sur 2 » au lieu de l'encadrer.

   C'était le reste d'un balisage précédent : une liste de numéros de page
   surmontée de son compte, pour laquelle la colonne avait un sens.
   `app/utils/_pagination.php` n'émet plus que ces trois éléments, et les
   soixante lignes qui habillaient la liste de numéros — `-liens`, `-lien`,
   `-active`, `-inerte`, `-saut` — sont parties avec elle. Vérifié avant de les
   retirer : aucune n'apparaissait plus dans app/ ni dans public/.

   Les deux côtés prennent la même largeur (`flex: 1 1 0`) et poussent leur
   bouton vers le centre. Le compte reste donc exactement centré, qu'il y ait
   deux boutons, un seul, ou aucun — sans quoi la ligne sauterait d'une page à
   l'autre, ce que l'ancienne règle évitait avec une classe `-inerte`.
   ========================================================================== */
.dad-pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: .5rem 1rem;
    margin: 2rem 0 1rem;
}

.dad-pagination > div {
    display: flex;
    flex: 1 1 0;
    min-width: 0;
}

.dad-pagination > div:first-of-type { justify-content: flex-end; }
.dad-pagination > div:last-of-type  { justify-content: flex-start; }

.dad-pagination-compte {
    margin: 0;
    flex: 0 0 auto;
    font-size: .875rem;
    color: var(--dad-gris);
    white-space: nowrap;
}

/* Sur un écran étroit, les boutons se resserrent plutôt que de passer à la
   ligne : « Page 1 sur 2 » doit rester lisible entre les deux. */
@media (max-width: 480px) {
    .dad-pagination { gap: .5rem; }
    .dad-pagination .btn { padding: .35rem .5rem; }
}

/* Le filtre du tableau de bord : trois éléments sur une ligne, qui tombent
   proprement. Il tenait dans une carte à en-tête « Filtrer » — un cadre et un
   titre pour deux menus déroulants. */
.dad-filtre {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 1rem;
}

.dad-filtre-champ {
    display: flex;
    flex-direction: column;
    min-width: 12rem;
    flex: 1 1 12rem;
}

.dad-filtre-boutons {
    display: flex;
    gap: .5rem;
}

/* UNE CASE À COCHER GARDE SA TAILLE DANS UNE RANGÉE SOUPLE.
 *
 * `.form-check.d-flex` : Bootstrap donne à `.form-check-input` un `float:left`
 * et une marge négative prévus pour un bloc, pas pour un enfant de flexbox.
 * Dans la modale de validation du devis, la case se faisait écraser à 7 px de
 * large par le paragraphe voisin — un trait vertical dont on ne pouvait pas
 * voir l'état, alors qu'elle est obligatoire et que le serveur refuse sans
 * elle. Le libellé, lui, prend la place qui reste. */
.form-check.d-flex .form-check-input {
    flex: 0 0 auto;
    float: none;
    margin-left: 0;
    margin-right: .6rem;
}

.form-check.d-flex .form-check-label {
    flex: 1 1 auto;
}

/* La graisse est commune aux quatre compteurs ; la teinte, elle, vient de la
   carte (voir `.dad-compteur-*` plus haut). */
.dad-compteur-devis,
.dad-compteur-commandes,
.dad-compteur-cours,
.dad-compteur-comptes {
    font-weight: 700;
}

/* L'en-tête de carte porte l'encre, pas du blanc : `--dad-bleu-pale` est un
   fond clair, et c'est sur lui que se lisait le mieux le texte des quatre
   autres écrans de l'équipe. */
.dad-carte-entete {
    color: var(--dad-encre);
    font-weight: 600;
}

/* L'ASTÉRISQUE D'UN CHAMP OBLIGATOIRE, PARTOUT LA MÊME.
 *
 * L'inscription portait onze champs `required` sans en signaler un seul :
 * l'utilisateur découvrait l'obligation au refus du formulaire, un champ à la
 * fois. Les modales de l'équipe écrivaient déjà « Nom * » — la marque devient
 * une classe pour qu'elle se lise de la même façon des deux côtés. */
.dad-requis {
    color: var(--dad-rouge);
    font-weight: 700;
}

/* Le logo de l'inscription : il occupait une colonne pleine hauteur sans
   `.row` parent, ce qui poussait la page à défiler latéralement. */
.dad-logo-inscription {
    max-height: 22vh;
}

/* ==========================================================================
   Récapitulatif avant envoi
   --------------------------------------------------------------------------
   TROIS TAILLES, TROIS COULEURS, PAS UNE DE PLUS.
   La fenêtre en comptait le double : un titre bleu, des sections grises en
   capitales, des valeurs en encre, un avertissement en petit gris, et cinq
   niveaux de titres repris du formulaire. Tout criait, donc plus rien ne
   ressortait.

   Ce qui reste :
     — le NOM DU SITE, seule chose colorée, parce que c'est l'entrée de
       lecture : on cherche « Thiers » avant de chercher ce qu'il contient ;
     — les GROUPES, en petites capitales d'encre : « Général » et un par type
       de données demandé. Ils rangent, ils n'attirent pas ;
     — les LIGNES, libellé en gris, valeur en encre — la valeur est ce qu'on
       vient vérifier, elle doit gagner contre son étiquette.

   La couleur ne hiérarchise plus, la taille et la graisse s'en chargent.
   ========================================================================== */

/* L'avertissement reprend le bandeau du formulaire ; il ne lui manquait que
   d'être lisible. */
.dad-recap-avertissement {
    font-size: 1rem;
    margin-bottom: 1.25rem;
}

.dad-recap-site + .dad-recap-site {
    margin-top: 1.5rem;
    padding-top: 1.25rem;
    border-top: solid 1px var(--bs-border-color, #dee2e6);
}

.dad-recap-titre {
    margin: 0 0 .75rem;
    color: var(--dad-bleu-fonce);
    font-size: 1.125rem;
}

/* LE SÉLECTEUR PORTE SON PARENT, ET CE N'EST PAS DE LA COQUETTERIE.
   `pages.css` déclare `body.page-new_request h6 { font-size: 1.1rem }` — une
   classe et deux éléments, qui l'emportent sur une classe seule. Sans le
   parent, la taille ne passait pas et le groupe restait plus gros que les
   valeurs qu'il annonce ; mesuré au navigateur, 17.6px au lieu de 12. Deux
   classes suffisent à reprendre la main, sans `!important` qui ne se retire
   jamais. Le nom du site échappe au piège : c'est un `h5`. */
.dad-recap-site .dad-recap-groupe {
    margin: 1rem 0 .4rem;
    color: var(--dad-encre);
    font-size: .75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .05em;
}

.dad-recap-site .dad-recap-groupe:first-of-type {
    margin-top: 0;
}

.dad-recap-liste {
    margin: 0;
    font-size: .875rem;
}

.dad-recap-liste dt {
    font-weight: 400;
    color: var(--dad-gris);
}

.dad-recap-liste dd {
    margin-bottom: .3rem;
    color: var(--dad-encre);
}

.dad-recap-commentaire,
.dad-recap-vide {
    margin: 0;
    font-size: .875rem;
    color: var(--dad-encre);
}

.dad-recap-vide {
    color: var(--bs-danger, #dc3545);
}
