@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,400;0,500;0,600;0,700;0,800;0,900;1,500;1,700;1,800;1,900&display=swap');

/* ============================================================
   INSCRIPT - Refonte UI/UX des pages d'inscription (flux public)
   ------------------------------------------------------------
   IMPORTANT - Branding dynamique par smartlink :
   Les COULEURS, la POLICE et le RADIUS des boutons sont injectes
   au runtime par app_commun.js (_assignerCSSPage) en !important,
   selon la table CSS_SMARTLINK. On ne code donc JAMAIS la couleur
   de marque en dur ici : ce fichier ne fournit que la STRUCTURE,
   les FORMES, les ESPACEMENTS, l'echelle TYPO, les OMBRES et les
   ETATS, dans une palette neutre que le branding vient recouvrir.

   Hooks a NE PAS renommer (utilises par l'injection / le JS) :
     #mainDiv #div-main-form #div-header #div-top #steplist
     .btn1 .btn2 .button .separateur .divBarreBouton
     .divChangementLangue .divControl .titre-question .selection
     .ligne-enfant .wdgt-receipt .qte-field .price-field .extra-text
     .child-hidden .child-visible .overlay .popup #wg-loader
   ============================================================ */

:root {
    --noir:        #1B1B1B;
    --encre:       #242424;
    --encre-2:     #52584F;
    --gris:        #D2D2D2;
    --gris-doux:   #EFF1EF;
    --bord:        #E2E5E2;
    --surface:     #F5F7F5;
    --blanc:       #FFFFFF;
    --rouge:       #C8401E;
    --vert-ok:     #2E7D32;

    /* Accent neutre : sert aux etats (focus, selection) quand le
       branding smartlink ne fournit pas de couleur exploitable. */
    --accent:      #1B1B1B;

    --rayon:       14px;
    --rayon-sm:    10px;
    --rayon-pill:  99px;

    --ombre:       0 1px 2px rgba(27,27,27,.05), 0 8px 24px rgba(27,27,27,.07);
    --ombre-haute: 0 2px 4px rgba(27,27,27,.06), 0 16px 48px rgba(27,27,27,.14);

    --transition:  .2s cubic-bezier(.4,0,.2,1);

    --gap:         18px;
    --cadre-max:   1180px;
}

/* ============================================================
   1. RESET / BASE
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    min-height: 100%;
    /* Les bandes pleine largeur (topbar, stepper, bandeaux) utilisent le full-bleed
       margin: 0 calc(50% - 50vw). Comme 100vw inclut la scrollbar verticale alors que
       50% ne l'inclut pas, elles depassent d'environ la largeur de la scrollbar et
       creent un ascenseur horizontal. overflow-x: clip rogne ce debord SANS creer de
       conteneur de defilement -> le position: sticky de la topbar reste fonctionnel
       (contrairement a overflow-x: hidden qui le casserait). */
    overflow-x: clip;
}

html {
    font-size: 16px;
    /* Police par defaut ; remplacee par l'injection smartlink si configuree. */
    font-family: 'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    color: var(--encre);
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
}

body {
    background-color: var(--surface);     /* fond exterieur ; surcharge possible par smartlink */
    color: var(--encre);
    font-size: 0.9375rem;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

img { max-width: 100%; }

p, th, td, label, legend, span { font-size: 1rem; }

::selection { background: var(--gris); color: var(--noir); }

:focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 2px;
    border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ============================================================
   2. GRILLE (sous-ensemble Foundation re-implemente)
   Les templates Handlebars emettent .row / .columns / .column,
   des fractions .small-N/.medium-N et des blocs .X-up-N.
   ============================================================ */
.row {
    display: block;
    position: relative;
    max-width: none;
    margin: 0 0 var(--gap) 0;
}
.row::after { content: ""; display: table; clear: both; }

.columns, .column {
    width: 100%;
    padding: 0;
}

/* Fractions sur 12 (les templates n'utilisent que 3/4/6/12). */
.small-12, .medium-12, .large-12 { width: 100%; }
.small-6  { width: 50%; }
.small-4  { width: 33.3333%; }
.small-3  { width: 25%; }

/* Block grid .small-up-N / .medium-up-N / .large-up-N :
   parent en flex, enfants .column de largeur egale (robuste pour tout N). */
[class*="small-up-"], [class*="medium-up-"], [class*="large-up-"] {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}
[class*="small-up-"] > .column,
[class*="medium-up-"] > .column,
[class*="large-up-"] > .column { flex: 1 1 0; min-width: 0; }

/* Utilitaires Foundation conserves. */
.text-center { text-align: center; }
.text-right  { text-align: right; }
.text-left   { text-align: left; }
.float-right { float: right; }
.end         { }
.div-flex    { display: flex; gap: 10px; align-items: flex-start; }

/* ============================================================
   3. GABARIT GENERAL
   ============================================================ */
#mainDiv {
    max-width: var(--cadre-max);
    margin: 0 auto;
    padding: 0 16px 20px;
}

header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    padding: 18px 4px 14px;
}

#lblTimer {
    font-size: 0.95rem;
    font-weight: 700;
    white-space: nowrap;
    color: var(--encre);
}

@media screen and (max-width: 800px) {
    #lblTimer {
        font-size: 0.90rem;
    }
}

#lblVisiteurInfoHeader {
    border: none;
    box-shadow: none;
    text-align: left;
    align-self: center;
    color: var(--encre);
    font-weight: 600;
}

.divChangementLangue {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    margin: 0;
}
#changementLangue {
    width: auto;
    min-width: 130px;
    height: 38px;
}
#changementLangueLabel { color: var(--encre); }

#div-header, #div-header-petit {
    margin: 0 0 0px;
    border-radius: var(--rayon);
    overflow: hidden;
}
#div-header img {
    width: 100%;
    display: block;
    border-radius: var(--rayon);
}

#div-header-petit img { max-height: 180px; width: 100%; display: block; }
#div-top div-top { width: 100%; display: block; }

/* Maquette : PAS de carte englobante. Le fond gris du body ressort ; ce sont les
   questions (.divControl) qui sont les cartes blanches qui flottent dessus.
   (COULEUR_FOND_INTERIEUR surcharge le fond si l'evenement le configure.) */
#div-main-form {
    background-color: transparent;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    padding: 0;
    margin: 0;
    overflow: visible;
}

/* Espace au-dessus ET en dessous du bandeau image du client (#div-top), dans tous les cas. */
#div-top { margin-top: 20px; margin-bottom: 20px; }

/* ============================================================
   4. STEPPER / BARRE D'ETAPES (look maquette : ronds numerotes + liaison)
   Couleurs pilotees par CSS_SMARTLINK (BARRE_STEP_*), injectees sur :
     .step.actif .rond   <- COULEUR_BARRE_STEP_COURANT     (fond)
     .step.fait  .rond   <- COULEUR_BARRE_STEP_PRINCIPALE  (fond)
     .step .nom/.rond    <- COULEUR_TEXTE_BARRE_STEP        (texte)
   Ici : STRUCTURE + repli neutre (surcharge par l'injection).
   ============================================================ */
/* Barre de steps : bande BLANCHE pleine largeur (full-bleed), contenu centre ~1180px, facon maquette. */
#steplist {
    background: var(--blanc);
    border: 0;
    /*border-bottom: 1px solid var(--gris-doux);*/
    box-shadow: none;
    /*margin: 0 calc(50% - 50vw) 26px;*/
    margin-bottom: 20px;
    /* Padding FIXE, surtout pas en vw : #steplist n'est plus full-bleed (voir la marge negative
       commentee ci-dessus), il est contraint par #mainDiv dont la largeur est plafonnee en px.
       Un padding en 50vw grossissait donc avec le viewport sans que le conteneur suive : a fort
       dezoom il atteignait son maximum (400px de chaque cote) et ecrasait le stepper au centre,
       noms superposes. */
    padding: 18px 20px;
    /* Reste visible (collee) juste sous la topbar, comme l'entete. --topbar-h = hauteur
       reelle de la topbar, fixee par inscript_topbar.js (repli 62px). z-index < topbar (60). */
    position: sticky;
    top: var(--topbar-h, 62px);
    z-index: 50;
    border-radius: var(--rayon);
}
/* Tant que la barre de steps n'est pas remplie par le JS, on ne montre PAS la bande blanche pleine
   largeur (sinon, au 1er paint, un bandeau blanc apparait sous la topbar avant le contenu). */
#steplist:empty { display: none; }
/* Bandeaux systeme pleine largeur (full-bleed) : mode backend (vert) et inscription pas encore ouverte (rouge).
   Remplacent l'ancien encadre vert autour du formulaire (disparu avec la refonte) et le carre rouge inline. */
.bandeau-systeme {
    margin: 0 calc(50% - 50vw) 0px;
    padding: 12px clamp(20px, calc(50vw - 579px), 400px);
    text-align: center;
    color: #fff;
    font-weight: 600;
    font-size: 1.15rem;
}
.bandeau-systeme.bandeau-vert  { background: #00c700; }
.bandeau-systeme.bandeau-rouge { background: #ff0000; }
.stepper { display: flex; align-items: flex-start; }
.stepper .step {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    position: relative;
    text-align: center;
    min-width: 0;
}
/* Ligne de liaison entre les ronds. */
.stepper .step::before {
    content: "";
    position: absolute;
    top: 15px;
    left: -50%;
    width: 100%;
    height: 2px;
    background: var(--gris);
    z-index: 0;
}
.stepper .step:first-child::before { display: none; }
.stepper .step .rond {
    position: relative;
    z-index: 1;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    border: 2px solid var(--gris);
    background: var(--blanc);
    color: var(--encre-2);
    font-weight: 800;
    font-size: .9rem;
    transition: var(--transition);
}
.stepper .step .nom {
    font-size: .8rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    /* Neutre (facon maquette) : !important pour battre l'injection span { color: PRINCIPALE }. */
    color: var(--encre-2) !important;
    line-height: 1.2;
}
/* Etape faite : rond plein (repli ; surcharge BARRE_STEP_PRINCIPALE). */
.stepper .step.fait .rond { background: var(--noir); border-color: transparent; color: var(--blanc); }
.stepper .step.fait::before { background: var(--noir); }
/* Etape courante : rond accent + halo (repli ; surcharge BARRE_STEP_COURANT). */
.stepper .step.actif .rond { background: var(--noir); border-color: transparent; color: var(--blanc); box-shadow: 0 0 0 5px rgba(27,27,27,.12); }
.stepper .step.actif::before { background: var(--noir); }
.stepper .step.actif .nom { color: var(--noir) !important; }

@media screen and (max-width: 800px) {
    .stepper .step .nom { display: none; }
    /* ...sauf s'il y a 2 steps ou moins (pas de 3e step) : la place suffit, on affiche le nom. */
    .stepper:not(:has(.step:nth-child(3))) .step .nom { display: block; }
    .stepper .step .rond { width: 28px; height: 28px; }
}

/* ============================================================
   5. TYPOGRAPHIE DE CONTENU
   ============================================================ */
h1, h2, h3, h4, h5 { color: var(--noir); line-height: 1.2; margin: 0 0 .4em; }
h1 { font-weight: 900; font-style: italic; font-size: 1.9rem; letter-spacing: -.01em; }
h2 { font-weight: 800; font-size: 1.45rem; }
h3 { font-weight: 800; font-size: 1.30rem; }
h4 { font-weight: 800; font-size: 1.15rem; }
h5 { font-weight: 800; font-size: 1rem; }

a {
    color: var(--noir);
    text-decoration: underline;
    text-underline-offset: 2px;
    transition: color var(--transition);
}
a:hover, a:focus { opacity: .8; }

.red { color: var(--rouge); }
.no_bold { font-weight: normal !important; }

/* En-tete de step (index) : Titre + Description facon maquette.
   MOBILE UNIQUEMENT : en desktop, la barre de steps porte deja le nom de l'etape
   (.stepper .step .nom), l'entete ferait doublon. En mobile ce nom est masque
   (sauf a 2 steps ou moins), et l'entete prend le relais pour situer l'utilisateur. */
.form-entete { display: none; margin: 24px 0 22px; }

@media screen and (max-width: 800px) {
    .form-entete { display: block; }
}
.form-entete .titre {
    font-weight: 900;
    font-style: italic;
    font-size: clamp(1.6rem, 3vw, 2.3rem);
    line-height: 1.12;
    letter-spacing: -.01em;
    margin: 0 0 8px;
    /* Compense le jambage gauche du titre italique pour aligner avec le texte droit. */
    text-indent: -0.1em;
    color: var(--noir);
}
.form-entete .sous-titre {
    color: var(--encre-2);
    font-size: .95rem;
    line-height: 1.6;
    max-width: 85ch;
    margin: 0;
}
/* Tag "Etape X de Y . Nom du step" (au-dessus du titre). */
.form-entete .etape-tag {
    display: block;
    font-size: .9rem;
    font-weight: 800;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--encre-2);
    margin-bottom: 10px;
}
.form-entete .etape-tag:empty { display: none; }

.titre-question {
    display: block;
    font-weight: 700;
    font-size: 1rem;
    letter-spacing: .02em;
    color: var(--encre);
    margin: 0 0 7px;
}
fieldset legend.titre-question,
legend.titre-question { font-size: 1rem; padding: 0; }

/* ============================================================
   6. CARTE DE CONTROLE (.divControl)
   Chaque question generee = une carte posee sur la surface.
   ============================================================ */
.form .divControl,
.divControl {
    background: var(--blanc);
    border: 1px solid var(--gris-doux);
    border-radius: var(--rayon);
    box-shadow: var(--ombre);
    padding: 18px 20px;
    margin: 0 0 16px;
    max-width: none;
}
.divControl > .columns,
.divControl > .column,
.divControl > fieldset { padding: 0; }

/* Le separateur de questions n'est pas une carte (voir section dediee). */
.divControl.separateur { background: none; border: 0; box-shadow: none; padding: 0; }

fieldset {
    border: 0;
    padding: 0;
    margin: 0;
    min-width: 0;
}
fieldset .row { margin-bottom: .25rem; }

@media screen and (max-width: 800px) {
    .divControl {
        padding: 15px 11px !important;
    }
}

/* ============================================================
   7. CHAMPS DE FORMULAIRE
   ============================================================ */
input[type=text],
input[type=password],
input[type=email],
input[type=tel],
input[type=number],
input.email,
input.phone,
input.extension,
input.countrycode,
input.cc_number,
input.date_expiration,
input.datepicker,
input.timepicker,
select,
textarea,
.multiline {
    font-family: inherit;
    font-size: 0.9375rem;
    color: var(--encre);
    background-color: var(--blanc);
    border: 1.5px solid var(--gris);
    border-radius: var(--rayon-sm);
    padding: 10px 12px;
    margin: 0 0 0 0;
    width: 100%;
    max-width: 100%;
    height: auto;
    box-shadow: none;
    -webkit-appearance: none;
    appearance: none;
    outline: none;
    transition: border-color var(--transition), box-shadow var(--transition);
}

textarea, .multiline {
    max-width: 100%;
    min-height: 110px;
    line-height: 1.5;
    resize: vertical;
}

select {
    padding-right: 2rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%2352584F' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    cursor: pointer;
}

input[type=text]:hover,
input[type=email]:hover,
select:hover,
textarea:hover,
.multiline:hover { border-color: var(--encre-2); }

input[type=text]:focus,
input[type=password]:focus,
input[type=email]:focus,
input[type=tel]:focus,
input.email:focus,
input.phone:focus,
input.extension:focus,
input.countrycode:focus,
input.datepicker:focus,
input.timepicker:focus,
select:focus,
textarea:focus,
.multiline:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 4px rgba(27,27,27,.10);
}

/* Datepicker en lecture seule (jQuery UI ajoute la classe .hasDatepicker) : le readonly
   sert UNIQUEMENT a empecher la saisie clavier ; l'input doit garder une apparence
   NORMALE et cliquable (pas grise) car on clique dessus pour choisir une date. */
input.hasDatepicker[readonly],
input.datepicker[readonly] {
    background-color: var(--blanc) !important;
    color: var(--encre);
    border-color: var(--gris);
    cursor: pointer;
}

input:not([type=button]):disabled,
/* Les datepickers sont [readonly] par conception (on saisit via le calendrier, pas au clavier) :
   ils ne doivent PAS prendre l'apparence "desactive". On les exclut ici au lieu de compter sur
   l'ordre des regles : la regle datepicker ci-dessus a exactement la meme specificite (0,2,1) --
   le :not([type=button]) compte celle de son argument -- donc, a egalite, c'est la derniere
   declaree qui gagnait, et c'etait celle-ci. Un datepicker :disabled reste grise, lui. */
input:not([type=button]):not(.hasDatepicker):not(.datepicker)[readonly],
select:disabled,
textarea:disabled,
textarea[readonly] {
    background-color: var(--gris-doux) !important;
    color: var(--encre-2);
    cursor: not-allowed;
    border-color: var(--bord);
    box-shadow: none;
}

/* Le calendrier jQuery UI doit s'afficher AU-DESSUS de la topbar (z-index 60) et du
   steplist (50), tous deux sticky ; jQuery UI lui assigne un z-index dynamique trop bas. */
.ui-datepicker { z-index: 1000 !important; }

::placeholder { color: #9aa09a; opacity: 1; }

/* Cases a cocher / boutons radio. */
input[type=checkbox],
input[type=radio] {
    width: 18px;
    height: 18px;
    min-width: 18px;
    margin: 4px 8px 0 0;
    accent-color: var(--accent);
    cursor: pointer;
    vertical-align: top;
}

input[type=file] { margin: 6px 0; }

/* Ligne enfant : un choix (case/radio + libelle) au sein d'un groupe. */
.ligne-enfant:not(tr) {
    display: flex;
    align-items: flex-start;
    gap: 4px;
    padding: 6px 0;
}
.ligne-enfant label { font-weight: normal; margin: 0; }
/* Libelles d'une option : libelle principal + 2e libelle (gris) EMPILES, facon maquette
   (ex. "Membre" / "Tarif preferentiel..."). */
.opt-libelles { display: flex; flex-direction: column; min-width: 0; }
.opt-libelles:has(.option-label2) > label { font-weight: 600; }
.option-label2 { display: block; color: var(--encre-2); font-size: .85rem; line-height: 1.3; margin: 1px 0 0; }
/* Places restantes (option facturation), discret sous le libelle. La couleur SIGNALE le stock :
   gris (ok) par defaut, orange (bas), rouge (critique). !important pour passer devant la couleur
   de texte injectee par le branding (COULEUR_TEXTE_PRINCIPALE). */
.places-restantes { display: block; font-size: .8rem; font-weight: 600; line-height: 1.3; margin: 3px 0 0; color: var(--encre-2) !important; }
.places-restantes.places-critique { color: var(--rouge) !important; }
/* Sous-titre de question (Label1/Label2 du groupe) facon maquette : gris, plus petit, sous le titre. */
.sous-titre-question { color: var(--encre-2); font-size: .9rem; font-weight: 400; line-height: 1.4; margin: 2px 0 12px; }
.form fieldset label,
table.wdgt-receipt label { font-weight: normal; margin-top: 1px; }

/* Champ texte additionnel accole a une option (ex: "Autre : ___"). */
.extra-text {
    display: inline-block;
    width: auto;
    max-width: 300px;
    height: 2.1rem;
    margin: 0 0 0 10px !important;
    padding: 6px 10px;
}

/* Option (radio/checkbox) AVEC champ "Preciser" : le champ reste en ligne sur
   desktop, mais passe SOUS l'option des que l'espace manque (mobile) au lieu de
   comprimer le libelle sur 2 lignes. Radio + libelle restent alignes (centres). */
.ligne-enfant:has(.extra-text) {
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
}
.ligne-enfant:has(.extra-text) > input[type=radio],
.ligne-enfant:has(.extra-text) > input[type=checkbox] { margin: 0; flex: 0 0 auto; }
.ligne-enfant:has(.extra-text) > label { margin: 0; flex: 0 1 auto; }
.ligne-enfant:has(.extra-text) > .opt-libelles { margin: 0; flex: 0 1 auto; }
.ligne-enfant:has(.extra-text) > .extra-text {
    flex: 1 1 240px;   /* grandit en ligne ; sous 240px de place dispo -> passe a la ligne (pleine largeur) */
    width: auto;
    min-width: 0;
    max-width: 100%;
    margin: 0 !important;
}

/* ============================================================
   TYPES RAD2 (radio) et CHK2 (checkbox) : options en PASTILLES (look maquette "Restrictions
   alimentaires"). Meme comportement que RADB / CHKB ; seul le RENDU change. L'input (data-datatype
   'RAD2' ou 'CHK2') est rendu transparent et etale sur toute la pastille -> tout le bouton est
   cliquable. Selectionne = couleurs du BOUTON de l'evenement (injection ; repli noir/blanc).
   ============================================================ */
.ligne-enfant:has(> input[data-datatype='RAD2']),
.ligne-enfant:has(> input[data-datatype='CHK2']) {
    position: relative;
    display: inline-flex;
    align-items: center;
    width: auto !important;                 /* le template met width:X% -> pastilles compactes */
    border: 1.5px solid var(--gris);
    border-radius: var(--rayon-pill);
    background: var(--blanc);
    padding: 8px 18px;
    margin: 0 8px 8px 0;
    cursor: pointer;
    transition: var(--transition);
    -webkit-tap-highlight-color: transparent;   /* mobile : pas de carre bleu au tap */
}
.ligne-enfant:has(> input[data-datatype='RAD2']) > input,
.ligne-enfant:has(> input[data-datatype='CHK2']) > input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    min-width: 0;
    margin: 0;
    opacity: 0;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;   /* mobile : pas de carre bleu au tap */
}
.ligne-enfant:has(> input[data-datatype='RAD2']) label,
.ligne-enfant:has(> input[data-datatype='CHK2']) label { cursor: pointer; font-weight: 600; margin: 0; }
/* Survol (pastille NON selectionnee) : teinte pale de la couleur du bouton (via injection ;
   repli neutre gris ici). */
.ligne-enfant:has(> input[data-datatype='RAD2']:not(:checked):not(:disabled)):hover,
.ligne-enfant:has(> input[data-datatype='CHK2']:not(:checked):not(:disabled)):hover {
    background: var(--gris-doux);
    border-color: var(--gris);
}
/* Selectionne : prend les COULEURS DU BOUTON de l'evenement (fond COULEUR_BOUTON1 + texte
   COULEUR_TEXTE_BOUTON1) via l'injection CSS_SMARTLINK (comme .btn1). Repli neutre (noir/blanc)
   sans branding. Bordure transparente -> le fond remplit toute la pastille. */
.ligne-enfant:has(> input[data-datatype='RAD2']:checked),
.ligne-enfant:has(> input[data-datatype='CHK2']:checked) {
    background: var(--noir);
    border-color: transparent;
}
.ligne-enfant:has(> input[data-datatype='RAD2']:checked) label,
.ligne-enfant:has(> input[data-datatype='RAD2']:checked) .opt-libelles,
.ligne-enfant:has(> input[data-datatype='RAD2']:checked) .option-label2,
.ligne-enfant:has(> input[data-datatype='CHK2']:checked) label,
.ligne-enfant:has(> input[data-datatype='CHK2']:checked) .opt-libelles,
.ligne-enfant:has(> input[data-datatype='CHK2']:checked) .option-label2 { color: #fff !important; }
.ligne-enfant:has(> input[data-datatype='RAD2']:disabled),
.ligne-enfant:has(> input[data-datatype='CHK2']:disabled) { opacity: .55; cursor: not-allowed; }

/* Telephone : largeurs fixes specifiques. */
input.phone       { width: 150px !important; max-width: none !important; min-width: 0 !important; margin-right: 10px; }
input.extension   { width: 90px  !important; max-width: none !important; min-width: 0 !important; }
input.countrycode { width: 64px  !important; max-width: none !important; min-width: 0 !important; margin-right: 10px; }

/* ============================================================
   8. CHAMPS DERREUR
   ============================================================ */
.form .border-error,
.error-champ {
    border: 2px solid var(--rouge) !important;
}
table.error-champ tbody { border: 1px solid var(--rouge); }

.error-champ-msg {
    display: block;
    color: var(--rouge);
    font-size: .85rem;
    font-weight: 600;
    margin-top: 6px;
}

.msgerror {
    border: 1.5px solid var(--rouge);
    border-radius: var(--rayon-sm);
    background: rgba(200,64,30,.06);
    padding: 14px 16px;
    margin-top: 20px;
}
.msgerror, .msgerror font, .msgerror p {
    color: var(--rouge) !important;
    font-size: .95rem;
    margin: 2px 0;
}
.msgerror font b { font-weight: 700; }
.line-error { margin: 0; }

/* ============================================================
   8b. PAGES D'ETAT (delai expire, erreur technique, ferme)
   Carte centree autonome, reutilisable par les pages standalone
   (delaisExpire.aspx, erreur.aspx). Ne depend d'aucune topbar :
   position fixe + fond propre -> rendu identique partout.
   ============================================================ */
.page-etat {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: var(--surface);
    overflow-y: auto;
    visibility: hidden;               /* revele par JS une fois le texte pose (anti-FOUC) */
}
.page-etat.pret { visibility: visible; }

.page-etat .etat-carte {
    background: var(--blanc);
    border: 1px solid var(--bord);
    border-radius: var(--rayon);
    box-shadow: var(--ombre-haute);
    padding: 44px 40px;
    max-width: 480px;
    width: 100%;
    text-align: center;
    animation: etatApparition .35s cubic-bezier(.4, 0, .2, 1) both;
}
@keyframes etatApparition {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

.page-etat .etat-icone {
    width: 78px;
    height: 78px;
    margin: 0 auto 24px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Etat par defaut = neutre (informatif). La variante .etat-erreur passe au rouge. */
    background: var(--gris-doux);
    color: var(--encre-2);
}
.page-etat .etat-icone svg {
    width: 40px;
    height: 40px;
    display: block;
}
.page-etat.etat-erreur .etat-icone {
    background: color-mix(in srgb, var(--rouge) 12%, #fff);
    color: var(--rouge);
}

.page-etat .etat-titre {
    font-size: 1.3rem;
    font-weight: 700;
    color: var(--encre);
    margin: 0 0 10px;
    line-height: 1.3;
}
.page-etat .etat-message {
    font-size: 1rem;
    line-height: 1.55;
    color: var(--encre-2);
    margin: 0;
}
.page-etat .etat-action {
    margin-top: 28px;
    text-decoration: none;
}

@media screen and (max-width: 800px) {
    .page-etat .etat-carte { padding: 34px 22px; }
    .page-etat .etat-icone { width: 68px; height: 68px; margin-bottom: 20px; }
    .page-etat .etat-icone svg { width: 34px; height: 34px; }
    .page-etat .etat-titre { font-size: 1.18rem; }
}

/* ============================================================
   9. SEPARATEUR (titre de section)
   L'injection smartlink peut colorer fond + texte (comme .btn1).
   ============================================================ */
.separateur {
    background-color: var(--noir);
    color: var(--blanc) !important;
    border: 0;
    border-radius: var(--rayon-sm);
    padding: 12px 18px !important;
    margin: 28px 0 16px !important;
    text-align: left !important;
    font-weight: 800;
    letter-spacing: .01em;
}
.separateur > .columns { padding: 0; }
.separateur p, .separateur div { margin: 0; }

/* Message libre (DataType MESS). */
.divControl > .columns > [data-datatype="MESS"] { line-height: 1.55; }

/* ============================================================
   10. CARTES DE SELECTION (.selection) - DataType SELE/SELF
   ============================================================ */
.enteteSelection {
    display: flex;
    gap: 10px;
    margin-bottom: 10px;
    font-weight: 700;
    color: var(--encre-2);
    text-transform: uppercase;
    font-size: .72rem;
    letter-spacing: .06em;
}
.labelEntete { padding: 0 4px; }

.selection {
    position: relative;
    display: flex;
    flex-direction: column;
    border: 1.5px solid var(--bord);
    border-radius: var(--rayon);
    background: var(--blanc);
    padding: 18px !important;
    box-shadow: var(--ombre);            /* ombre douce permanente -> cartes qui "flottent" */
    transition: var(--transition);
    -webkit-tap-highlight-color: transparent;   /* mobile : pas de carre bleu au tap (herite -> label + boutons) */
}
.selection:hover:not(.disabled) {
    border-color: var(--gris);
    box-shadow: var(--ombre-haute);
    transform: translateY(-2px);         /* lift subtil au survol */
}

/* Le libelle de l'option remplit toute la hauteur de la carte : le contenu injecte
   pousse le bouton d'etat en bas. Combine a l'etirement des cartes dans la rangee
   (flex-wrap, align-items:stretch), tous les boutons d'une rangee s'alignent. */
.selection > label:not(.price-field) {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    gap: 14px;
    margin: 0;
    cursor: pointer;
}
.selection > label:not(.price-field) > :first-child { flex: 1 1 auto; }

.selection.selection_checked {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(27,27,27,.12);
}
.selection.disabled { opacity: .7; background: var(--surface); box-shadow: none; cursor: not-allowed; }

/* Coche sur la carte selectionnee : badge rond en coin, coche blanche.
   Fond neutre par defaut (--accent), RECOLORE par le branding : le selecteur
   .selection.selection_checked::after est ajoute a l'injection COULEUR_BOUTON1. */
.selection.selection_checked::after {
    content: "";
    position: absolute;
    top: -10px;
    right: -10px;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background-color: var(--accent);
    background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20fill='none'%20stroke='%23fff'%20stroke-width='3'%20stroke-linecap='round'%20stroke-linejoin='round'%20d='M5%2013l4%204L19%207'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 15px;
    box-shadow: 0 2px 6px rgba(27, 27, 27, .25);
    z-index: 2;
    animation: cocheSelection .18s cubic-bezier(.4, 0, .2, 1) both;
}
@keyframes cocheSelection {
    from { transform: scale(.4); opacity: 0; }
    to   { transform: scale(1);  opacity: 1; }
}

/* Hierarchie du contenu injecte dans la carte (sur-titre / salle+duree / titre).
   STRUCTURE et ECHELLE seulement : on ne touche PAS aux couleurs du contenu client.
   Les <br> du gabarit sont neutralises au profit d'un empilement en blocs regulier. */
.selection .boite_grise_conf br { display: none; }
.selection .theme {
    display: block;
    font-size: 1rem;
    font-weight: 700;
    line-height: 1.3;
    opacity: .7;
}
.selection .salle {
    display: block;
    font-size: .92rem;
    font-weight: 600;
    line-height: 1.4;
    margin-top: 3px;
}
.selection .duree { font-weight: 700; }
.selection .titre_1 {
    display: block;
    font-size: 1.08rem;
    font-weight: 700;
    line-height: 1.3;
    margin-top: 3px;
}

/* Contenu structure d'une option a partir des 3 libelles (FID_VALEUR / _2 / _3) :
   desc1 = titre en gras, desc2 et desc3 empiles en dessous, plus petits. Les libelles
   peuvent contenir du HTML (rendu brut) qui peut surcharger ces valeurs par defaut. */
.selection .opt-carte {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.selection .opt-desc1 {
    font-size: 1.05rem;
    font-weight: 700;
    line-height: 1.3;
    color: var(--encre);
}
.selection .opt-desc2,
.selection .opt-desc3 {
    font-size: .95rem;
    line-height: 1.35;
    color: var(--encre-2);
}

/* Places restantes : puce discrete AU-DESSUS du bouton (nudge de rarete au moment du CTA).
   La COULEUR du texte vient de .places-restantes (base = gris / injectee = marque ;
   .places-critique = rouge). La puce se colore d'elle-meme a partir de currentColor :
   fond = teinte legere, pastille + texte = couleur pleine du niveau. */
.selection .places-restantes {
    align-self: center;                 /* puce centree, sous le contenu, au-dessus du bouton */
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin: 0;
    padding: 5px 13px;
    border-radius: var(--rayon-pill);
    background: color-mix(in srgb, currentColor 12%, var(--blanc));
    font-size: .78rem;
    font-weight: 700;
    line-height: 1.2;
    white-space: nowrap;
}
.selection .places-restantes::before {
    content: "";
    flex: 0 0 auto;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
}
/* En COMPLET ou CONFLIT, la banniere suffit : on masque la puce (evite "0 places restantes"
   redondant, et l'indispo par conflit n'est pas une question de capacite). */
.selection:is(:has(input[data-complet="true"]), :has(> label > .Inactif:not([style*="display: none"]))) .places-restantes {
    display: none;
}

/* Boutons d'etat d'une carte de selection. */
.Choisir, .choisir,
.Annuler, .annuler,
.Inactif, .inactif,
.Complet, .complet,
.Desactive, .desactive {
    display: inline-block;
    border: 0;
    border-radius: var(--rayon-pill);
    padding: 11px 20px;
    font-weight: 800;
    font-size: .88rem;
    text-align: center;
    text-transform: uppercase;
    color: var(--blanc);
    cursor: pointer;
    transition: var(--transition);
    -webkit-appearance: none;
    appearance: none;
    letter-spacing: 0.8px;
}
.Choisir, .choisir { background-color: var(--noir); }
.Choisir:hover, .choisir:hover { background-color: #000; }
.Annuler, .annuler { background-color: var(--blanc); color: var(--noir); border: 1.5px solid var(--gris); }
.Annuler:hover, .annuler:hover { border-color: var(--noir); }
.Inactif, .inactif,
.Complet, .complet,
.Desactive, .desactive { background-color: var(--gris); color: var(--encre-2); cursor: not-allowed; }

/* Etat COMPLET : pas un bouton, mais une banniere pleine largeur facon "carte epuisee".
   Surcharge la base (pastille) via une specificite plus forte (.selection .Complet), sans
   toucher au JS : la visibilite reste pilotee par .show()/.hide(). Rayures diagonales
   discretes + cadenas (masque SVG qui suit currentColor -> aucune couleur codee en dur). */
.selection .Complet,
.selection .complet {
    width: 100%;
    box-sizing: border-box;
    margin-top: 2px;
    padding: 12px 16px;
    border: 0;
    border-radius: var(--rayon-sm);
    background-color: var(--gris-doux);
    background-image: repeating-linear-gradient(135deg, transparent 0 11px, rgba(0, 0, 0, .04) 11px 22px);
    color: var(--encre-2);
    font-weight: 800;
    font-size: .78rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    text-align: center;
    cursor: not-allowed;
}
.selection .Complet::before,
.selection .complet::before {
    content: "";
    display: inline-block;
    width: 16px;
    height: 16px;
    margin-right: 8px;
    vertical-align: -2px;
    background-color: currentColor;
    -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M12%201a5%205%200%200%200-5%205v3H6a2%202%200%200%200-2%202v9a2%202%200%200%200%202%202h12a2%202%200%200%200%202-2v-9a2%202%200%200%200-2-2h-1V6a5%205%200%200%200-5-5zm3%208H9V6a3%203%200%200%201%206%200v3z'/%3E%3C/svg%3E") center / contain no-repeat;
            mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M12%201a5%205%200%200%200-5%205v3H6a2%202%200%200%200-2%202v9a2%202%200%200%200%202%202h12a2%202%200%200%200%202-2v-9a2%202%200%200%200-2-2h-1V6a5%205%200%200%200-5-5zm3%208H9V6a3%203%200%200%201%206%200v3z'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* Etat CONFLIT / INACTIF : pas un bouton non plus, mais une INFO qui explique POURQUOI
   l'option n'est pas selectionnable (libelle libre : "Conflit d'horaire", "Inactif", ...).
   Meme esprit que COMPLET, avec une pastille d'info (i) au lieu du cadenas. La visibilite
   reste pilotee par le JS (.show()/.hide()). */
.selection .Inactif,
.selection .inactif {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    box-sizing: border-box;
    margin-top: 2px;
    padding: 11px 14px;
    border: 0;
    border-radius: var(--rayon-sm);
    background-color: #737373;
    color: #ffffff;
    font-weight: 700;
    font-size: .80rem;
    text-transform: uppercase;
    text-align: center;
    line-height: 1.25;
    cursor: not-allowed;
}
    .selection .Inactif::before,
    .selection .inactif::before {
        content: "";
        flex: 0 0 auto;
        width: 20px;
        height: 20px;
        background-color: currentColor;
        -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20fill-rule='evenodd'%20d='M12%202a10%2010%200%201%201%200%2020%2010%2010%200%200%201%200-20zm-1.25%205.5v2.5h2.5V7.5h-2.5zm0%204v5h2.5v-5h-2.5z'/%3E%3C/svg%3E") center / contain no-repeat;
        mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20fill-rule='evenodd'%20d='M12%202a10%2010%200%201%201%200%2020%2010%2010%200%200%201%200-20zm-1.25%205.5v2.5h2.5V7.5h-2.5zm0%204v5h2.5v-5h-2.5z'/%3E%3C/svg%3E") center / contain no-repeat;
    }

/* La carte (HTML injecte dans le libelle de l'option) passe en "epuise/indisponible" :
   grisee + attenuee, pour COMPLET (data-complet) comme pour CONFLIT (.Inactif visible).
   On cible les enfants du label QUI NE SONT PAS les boutons d'etat, pour ne pas ternir
   la banniere (qui vit dans le meme label). */
.selection:is(:has(input[data-complet="true"]), :has(> label > .Inactif:not([style*="display: none"]))) > label > :not(.Choisir):not(.choisir):not(.Annuler):not(.annuler):not(.Inactif):not(.inactif):not(.Complet):not(.complet) {
    filter: grayscale(1);
    opacity: .55;
}

/* ============================================================
   11. FACTURATION (.wdgt-receipt) - RADF / CBOF -> options en CARTES (maquette)
   La table est passee en blocs/flex : chaque ligne-enfant devient une carte
   (bordure arrondie), libelle en gras, prix en texte gras a droite (pas de boite),
   option cochee = carte surlignee, en-tete de section en gras simple (sans soulignement).
   ============================================================ */
table.wdgt-receipt { display: block; width: 100%; border-collapse: collapse; }
table.wdgt-receipt thead,
table.wdgt-receipt tbody,
table.wdgt-receipt tfoot { display: block; border: none; }
table.wdgt-receipt thead tr,
table.wdgt-receipt tbody tr { display: block; }

/* En-tete de section (ex. "Activites sociales") : gras simple, sans majuscules ni soulignement. */
table.wdgt-receipt thead th.title1 {
    display: block;
    width: auto;
    text-align: left;
    font-size: 1rem;
    font-weight: 700;
    text-transform: none;
    letter-spacing: 0;
    color: var(--encre);
    background: transparent;
    border: 0;
    padding: 0 0 12px;
}

/* Chaque option = une carte. */
table.wdgt-receipt tbody tr.ligne-enfant {
    display: flex;
    align-items: center;
    gap: 14px;
    border: 1.5px solid var(--gris-doux);
    border-radius: var(--rayon-sm);
    background: var(--blanc);
    padding: 14px 18px;
    margin: 0 0 12px;
    transition: var(--transition);
    cursor: pointer;
}
/* Champ quantite editable : garder le curseur texte (pas le pointeur de la carte). */
table.wdgt-receipt tbody tr.ligne-enfant .qte-field { cursor: text; }
table.wdgt-receipt tbody tr.ligne-enfant:hover { border-color: var(--gris); }
/* Option cochee (radio/checkbox) = carte surlignee. */
table.wdgt-receipt tbody tr.ligne-enfant:has(input:checked) {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(27,27,27,.12);
}

/* Cellules -> elements de flex. */
table.wdgt-receipt tbody tr.ligne-enfant td { display: block; border: 0; padding: 0; }
table.wdgt-receipt tbody tr.ligne-enfant td:first-child {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    gap: 12px;
}
table.wdgt-receipt tbody tr.ligne-enfant td.title2,
table.wdgt-receipt tbody tr.ligne-enfant td.title3 {
    flex: 0 0 auto;
    width: auto;
    text-align: right;
    white-space: nowrap;
}
/* Libelle d'option en gras. */
table.wdgt-receipt tbody tr.ligne-enfant td:first-child label { font-weight: 700; margin: 0; cursor: pointer; }

/* Case a cocher / radio : un peu plus grandes. */
table.wdgt-receipt tbody tr.ligne-enfant input[type=checkbox],
table.wdgt-receipt tbody tr.ligne-enfant input[type=radio] {
    width: 22px;
    height: 22px;
    min-width: 22px;
    margin: 0;
    flex: 0 0 auto;
    accent-color: var(--accent);
}

/* Quantite : petit champ compact. */
.qte-field, .qte-field-acco { width: 72px !important; text-align: center; padding: 6px 8px; }

/* --- Cartes facturation : quantite CACHEE tant que l'option n'est pas cochee --- */
/* La quantite n'a de sens qu'une fois l'item choisi : on masque tout le stepper sinon. */
table.wdgt-receipt tbody tr.ligne-enfant:not(:has(input:checked)) .qte-stepper { display: none; }

/* Stepper +/- (option cochee) facon maquette. */
.qte-stepper { display: inline-flex; align-items: center; border: 1.5px solid var(--gris); border-radius: var(--rayon-sm); overflow: hidden; vertical-align: middle; }
.qte-stepper > button {
    width: 30px; height: 32px; border: 0; background: var(--blanc);
    font-size: 17px; font-weight: 800; line-height: 1; color: var(--noir);
    padding: 0; cursor: pointer; transition: var(--transition);
}
.qte-stepper > button:hover { background: var(--gris-doux); }
table.wdgt-receipt tbody tr.ligne-enfant:has(input:checked) .qte-stepper input.qte-field {
    width: 42px !important;
    border: 0 !important;
    background: var(--blanc) !important;
    text-align: center;
    padding: 6px 0 !important;
}

/* Prix : texte gras a droite, jamais une boite (meme quand c'est un input desactive). */
.price-field { white-space: nowrap; font-variant-numeric: tabular-nums; font-weight: 600; }
table.wdgt-receipt .price-field { font-weight: 800; font-size: .95rem; text-align: right; }
table.wdgt-receipt input.price-field,
table.wdgt-receipt input.price-field:disabled {
    /* Largeur = CONTENU (field-sizing), pas de px fixe : la colonne grandit si le prix est plus
       long. Le cadre (bordure + padding + radius) est present dans LES DEUX etats, mais en
       transparent tant que c'est decoche -> seules la couleur de bordure et le fond changent au
       coche, donc memes dimensions et aucun decalage d'ecran entre coche/decoche. */
    field-sizing: content;
    width: auto !important;
    min-width: 4ch;
    max-width: 100%;
    box-sizing: border-box;
    background: transparent !important;
    border: 1.5px solid transparent !important;
    box-shadow: none !important;
    border-radius: var(--rayon-sm);
    padding: 6px 8px !important;
    color: var(--encre) !important;
    text-align: right;
}
.price-field-rabais { color: var(--rouge); }

/* Prix MODIFIABLE : devient un vrai champ (cadre visible + fond blanc) une fois l'option cochee,
   pour montrer qu'on peut le modifier. Seules la couleur de bordure et le fond changent. */
table.wdgt-receipt tbody tr.ligne-enfant:has(input:checked) input.price-field {
    background: var(--blanc) !important;
    border-color: var(--gris) !important;
}

/* --- Symbole monetaire (CAD, toujours $) UNIQUEMENT pour le prix MODIFIABLE (input) : sa value
   ne contient pas le "$" (contrairement aux prix fixes formates par le serveur, ex. "0,02 $"),
   sinon on aurait un "$" en double. Pose sur la cellule (pas dans la value -> n'affecte pas la
   soumission). Positionne selon la langue portee par <html lang> : EN avant ($0.02), FR/ES apres
   avec espace insecable (0.02 $). --- */
html[lang^="en"] table.wdgt-receipt tbody tr.ligne-enfant td.title3:has(input.price-field)::before {
    content: "$"; font-weight: 800; font-size: .95rem; color: var(--noir); margin-right: 4px;
}
html:not([lang^="en"]) table.wdgt-receipt tbody tr.ligne-enfant td.title3:has(input.price-field)::after {
    content: "$"; font-weight: 800; font-size: .95rem; color: var(--noir); margin-left: 4px;
}

/* --- Cartes facturation en MOBILE : le libelle prend toute la largeur ; le stepper (quantite) et
   le prix passent DESSOUS, empiles a droite, au lieu d'etre des colonnes fixes qui etranglent le
   libelle (1 mot par ligne). --- */
@media screen and (max-width: 800px) {
    /* Libelle pleine largeur (ligne 1) ; en dessous, le stepper (quantite) et le prix reviennent
       sur la MEME ligne, a leur largeur naturelle, alignes a droite (stepper a gauche du prix). */
    table.wdgt-receipt tbody tr.ligne-enfant { flex-wrap: wrap; row-gap: 10px; justify-content: flex-end; }
    table.wdgt-receipt tbody tr.ligne-enfant td:first-child { flex: 1 1 100%; }
    /* Decochee : pas de cellule vide a la place du stepper absent. */
    table.wdgt-receipt tbody tr.ligne-enfant:not(:has(input:checked)) td.title2 { display: none; }
}

/* ============================================================
   12. APERCU PANIER / RESUME (.cart-preview)
   ============================================================ */
table.cart-preview {
    width: 100%;
    border-collapse: collapse;
    font-size: .95rem;
}
table.cart-preview thead, table.cart-preview tbody, table.cart-preview tfoot {
    border: none;
    background: transparent;
}

/* ---------- SECTION 1 : LES ARTICLES (en-tete + lignes d'items) ----------
   Largeurs AUTO (plus de table-layout:fixed) : la DESCRIPTION prend la place restante et passe a
   la ligne ; QTE / PRIX / TOTAL restent compacts (nowrap). En mobile, chaque article devient un
   bloc empile (regles plus bas). */
table.cart-preview th {
    font-size: .72rem;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--encre-2);
    background: transparent;
    border: 0;
    border-bottom: 2px solid var(--noir);
    padding: 10px 8px;
    text-align: right;
    white-space: nowrap;
}
table.cart-preview th.titleCol1 { width: 55%; text-align: left; }

table.cart-preview tbody tr.cart-item > td {
    border: 0;
    border-bottom: 1px solid var(--gris-doux);
    padding: 11px 8px;
    font-variant-numeric: tabular-nums;
    vertical-align: top;
}
/* Pas de bordure sous le DERNIER article (le separateur de section suit juste apres). */
table.cart-preview tbody tr.cart-item:has(+ tr:not(.cart-item)) > td { border-bottom: 0; }
table.cart-preview tbody tr.cart-item > td:first-child { color: var(--noir); }
table.cart-preview tbody tr.cart-item > td.qte,
table.cart-preview tbody tr.cart-item > td.price { text-align: right; white-space: nowrap; }
table.cart-preview tbody tr.cart-item > td.price:last-child { font-weight: 700; }
/* Article avec rabais : on enleve la bordure du bas pour coller la ligne de rabais juste dessous. */
table.cart-preview tbody td.rabaisItem { border-bottom: none; }

/* ---------- SECTION 2 : TAXES + TOTAUX (et lignes de rabais) ----------
   Lignes de tableau classiques (table-layout:fixed est supprime -> plus de chevauchement) : le
   LIBELLE occupe les 3 premieres colonnes, aligne a DROITE avec un ecart ; le MONTANT est dans la
   4e colonne -> il se cale tout seul SOUS la colonne TOTAL des articles. */
table.cart-preview tbody td.subtotal,
table.cart-preview tbody tr.ligneRabais td {
    border: 0;
    padding: 5px 8px;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
/* Libelle (gris, semi-gras) a droite, avec de l'air avant le montant. */
table.cart-preview tbody td.subtotal.description,
table.cart-preview tbody tr.ligneRabais td:first-child {
    text-align: right;
    font-weight: 600;
    color: var(--encre-2);
    padding-right: 24px;
}
/* ":" entre le libelle et le montant dans le bas (taxes + totaux). */
table.cart-preview tbody td.subtotal.description:not(:empty)::after { content: " :"; }
/* Code promo : de l'air autour (le trait de separation articles/totaux passe AU-DESSUS via
   tr.cart-sep, deplace dans le markup avant #rabais -> un seul trait, pas deux). */
table.cart-preview tbody tr#rabais > td { padding: 6px 0 18px !important; }
/* Montant (gras), aligne sous la colonne TOTAL. */
table.cart-preview tbody td.subtotal.price,
table.cart-preview tbody tr.ligneRabais td[data-type-nominatif] {
    text-align: right;
    font-weight: 700;
}
/* Separateur NET entre la SECTION 1 (articles) et la SECTION 2 (taxes/totaux) : trait pleine
   largeur + de l'air de chaque cote. Ligne dediee (tr.cart-sep) -> toujours a la frontiere, peu
   importe les lignes de totaux masquees. */
table.cart-preview tbody tr.cart-sep td {
    border: 0;
    border-top: 2px solid var(--noir);
    padding: 0;
    height: 12px;
}
/* La ligne TOTAL ressort, avec un trait de separation pleine largeur au-dessus. */
/* Le trait + l'espace au-dessus du Total n'apparaissent QUE si une ligne taxes/sous-total
   (STO/TPS/TVQ/INT) est visible au-dessus. Le JS masque ces lignes avec style="display:none"
   quand elles sont vides. */
table.cart-preview tbody:has(tr.STO:not([style*="none"]), tr.TPS:not([style*="none"]), tr.TVQ:not([style*="none"]), tr.INT:not([style*="none"])) tr.TOT {
    border-top: 1px solid #a3a1a1;
    padding-top: 12px;
    margin-top: 4px;
}
table.cart-preview tbody tr.TOT td.subtotal { font-size: 1.1rem; font-weight: 800; color: var(--noir); }
/* "Solde / Montant a payer" mis en evidence. */
table.cart-preview tbody tr.SOL td.subtotal { font-size: 1.1rem; font-weight: 800; color: var(--noir); }

/* --- Resume : champ "code promo" facon maquette (bordure douce, coins arrondis). --- */
#txtCodeRabais {
    border: 1.5px solid var(--gris) !important;
    border-radius: var(--rayon-sm);
    padding: 10px 14px;
    height: auto;
    font-weight: 600 !important;
}

/* --- Resume : choix de paiement en CARTES (facon maquette "Mode de paiement").
   Chaque option (#modePaiement .ligne-enfant = radio + libelle) devient une carte ;
   la carte selectionnee est surlignee. La couleur de marque (selection / pastille radio)
   vient de l'injection CSS_SMARTLINK ; ici palette neutre de repli. --- */
#modePaiement .ligne-enfant:not(tr) {
    position: relative;                          /* ancre le ::after du label (carte cliquable) */
    display: flex;
    align-items: center;
    gap: 14px;
    border: 1.5px solid var(--gris-doux);
    border-radius: var(--rayon-sm);
    background: var(--blanc);
    padding: 16px 18px;
    margin: 0 0 12px;
    cursor: pointer;
    transition: var(--transition);
    -webkit-tap-highlight-color: transparent;    /* mobile : pas de carre bleu au tap */
}
#modePaiement .ligne-enfant:not(tr):hover { border-color: var(--gris); }
#modePaiement .ligne-enfant:not(tr):has(input:checked) {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(27,27,27,.12);
}
#modePaiement .ligne-enfant:not(tr) > input[type=radio] {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    margin: 0;
}
#modePaiement .ligne-enfant:not(tr) > label {
    font-weight: 700;
    margin: 0;
    cursor: pointer;
}
/* TOUTE la carte est cliquable (le cursor:pointer le laissait deja croire, mais seul le texte
   du libelle l'etait). On etale la zone cliquable du <label> sur la carte entiere via un ::after.
   Ici le radio doit rester VISIBLE : on ne peut donc pas etaler l'input transparent comme pour
   les pastilles RAD2/CHK2. Cliquer n'importe ou dans la carte active le label, qui coche le
   radio grace au couple id/for. */
#modePaiement .ligne-enfant:not(tr) > label::after {
    content: "";
    position: absolute;
    inset: 0;
}

/* --- Resume : en-tetes de colonnes + styles des totaux -> definis dans la SECTION 1/2 plus haut
   (refonte en deux sections distinctes). --- */

/* --- Resume : modes de paiement en grille 2 colonnes (desktop) / 1 colonne (mobile). --- */
#modePaiement .modes-paiement {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
    margin-bottom: 12px;
}
#modePaiement .modes-paiement .ligne-enfant:not(tr) { margin: 0; }
@media screen and (max-width: 800px) {
    #modePaiement .modes-paiement { grid-template-columns: 1fr; }
}

/* --- Resume : titre de carte ("Détail de la commande" / "Mode de paiement"), facon maquette. --- */
.carte-titre {
    font-size: 1.1rem;
    font-weight: 800;
    color: var(--noir);
    margin: 0 3px 16px;
}

/* --- Resume : note de securite sous le paiement (cadenas + fond doux), facon maquette.
   Vide -> masquee. --- */
.securite {
    margin-top: 18px;
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: .8rem;
    color: var(--encre-2);
    background: var(--surface);
    border-radius: var(--rayon-sm);
    padding: 12px 16px;
}
.securite::before { content: "\01F512"; font-size: .95rem; }
.securite:empty { display: none; }

/* --- Page de fin : entete de confirmation (crochet + titre), facon maquette. Le rond prend la
   COULEUR de l'evenement (via injection CSS_SMARTLINK sur .confirmation-check) ; le crochet prend
   la couleur de texte-bouton (contraste garanti). Repli neutre ici. --- */
/* Invisible tant que le branding + le contenu ne sont pas prets (revele en JS a la fin du build) :
   evite le flash du rond en couleur de repli puis sa recoloration. */
.confirmation-entete { text-align: center; margin: 8px 0 35px; visibility: hidden; }
.confirmation-entete.pret { visibility: visible; }

/* Meme principe pour le tableau du RESUME : sa structure statique (trait, code promo, lignes de
   totaux) se peint avant que le JS ne le remplisse (le loader, place apres #mainDiv, arrive trop
   tard). On le garde invisible jusqu'a ce que le JS l'ait construit (.pret). */
table.cart-preview.resume { visibility: hidden; }
table.cart-preview.resume.pret { visibility: visible; }
.confirmation-check {
    width: 88px; height: 88px; border-radius: 50%;
    background: var(--vert-ok);      /* repli ; surcharge = COULEUR_BOUTON1 (couleur de l'evenement) */
    color: var(--noir);              /* repli du crochet ; surcharge = COULEUR_TEXTE_BOUTON1 */
    margin: 6px auto 22px;
    display: flex; align-items: center; justify-content: center;
}
.confirmation-check svg { width: 52px; height: 52px; display: block; }
.confirmation-titre {
    font-size: clamp(1.6rem, 4vw, 2.1rem);
    font-weight: 800; font-style: italic; line-height: 1.15;
    margin: 0; text-align: center;
}
.confirmation-titre:empty { display: none; }

/* --- Resume : mise en evidence SOL / espacement STO -> definis dans la SECTION 2 plus haut. --- */

@media screen and (min-width: 800px) {
    /* --- Resume : champ code promo (responsive : ne deborde pas en mobile). --- */
    #txtCodeRabais { width: clamp(150px, 45vw, 240px) !important; max-width: 100%; }
}

/* --- Resume MOBILE : articles empiles (la description ne s'etrangle plus en colonnes etroites),
   totaux compacts, code promo pleine largeur. --- */
@media screen and (max-width: 800px) {
    /* En-tetes de colonnes inutiles une fois les articles empiles. */
    table.cart-preview tr.titreCol { display: none; }

    /* Chaque article = un bloc : description pleine largeur (ligne 1), puis "Qte x PrixUnitaire"
       a gauche et le TOTAL a droite (ligne 2). */
    table.cart-preview tbody tr.cart-item {
        display: flex;
        flex-wrap: wrap;
        align-items: baseline;
        column-gap: 6px;
        padding: 12px 2px;
        border-bottom: 1px solid var(--gris-doux);
    }
    table.cart-preview tbody tr.cart-item:has(+ tr:not(.cart-item)) { border-bottom: 0; }
    table.cart-preview tbody tr.cart-item > td { border: 0; padding: 0; }
    table.cart-preview tbody tr.cart-item > td:first-child {
        flex: 1 1 100%;
        font-weight: 700;
        color: var(--noir);
        margin-bottom: 4px;
        white-space: normal;
    }
    table.cart-preview tbody tr.cart-item > td.qte { order: 2; color: var(--encre-2); }
    table.cart-preview tbody tr.cart-item > td.qte::after { content: " \00D7"; }   /* x (multiplie) */
    table.cart-preview tbody tr.cart-item > td.price:nth-child(3) { order: 3; color: var(--encre-2); font-weight: 400; }
    table.cart-preview tbody tr.cart-item > td.price:last-child { order: 4; margin-left: auto; font-weight: 800; color: var(--noir); }

    /* Totaux en FLEX sur mobile UNIQUEMENT : ainsi le tableau n'impose plus de grille de colonnes,
       et les articles (eux aussi en flex) reprennent toute la largeur. Chaque total = libelle +
       montant cale a droite. (Sur desktop, les totaux restent des lignes de tableau alignees sous
       la colonne TOTAL.) */
    table.cart-preview tbody tr.STO,
    table.cart-preview tbody tr.TPS,
    table.cart-preview tbody tr.TVQ,
    table.cart-preview tbody tr.INT,
    table.cart-preview tbody tr.TOT,
    table.cart-preview tbody tr.TRE,
    table.cart-preview tbody tr.SOL,
    table.cart-preview tbody tr.ligneRabais {
        display: flex;
        justify-content: flex-end;
        align-items: baseline;
        gap: 16px;
    }
    table.cart-preview tbody td.subtotal,
    table.cart-preview tbody tr.ligneRabais td { padding: 4px 0; }
    table.cart-preview tbody td.subtotal.description,
    table.cart-preview tbody tr.ligneRabais td:first-child { padding-right: 0; }
    table.cart-preview tbody td.subtotal.price,
    table.cart-preview tbody tr.ligneRabais td[data-type-nominatif] { min-width: 84px; }

    /* Code promo : prend toute la largeur, ne deborde plus. */
    #rabais td > div { float: none !important; width: 100%; }
    #txtCodeRabais { width: 100% !important; flex: 1 1 auto; min-width: 0; }
}

/* --- Sceau VikingCloud (carte d'assurance, script tiers sysnetgs) : il flotte et chevauche
   le contenu sur petit ecran -> on le masque en mobile. Selecteurs cibles sur le vendeur
   (faible risque). S'il persiste, son conteneur a un autre id/classe -> me le donner. --- */
@media screen and (max-width: 800px) {
    .ac-widget,
    #widget-preview { display: none !important; }
}

/* Paiement (table secondaire). */
table.wdgt-payement2 { width: 100%; border-collapse: collapse; }
table.wdgt-payement2 .title { font-weight: 700; }
table.wdgt-payement2 .hd { background-color: var(--noir); color: var(--blanc); font-weight: 700; }
table.wdgt-payement2 .hd1 { width: 70%; }
table.wdgt-payement2 .hd2 { width: 30%; text-align: right; }

.info-paiement { margin-bottom: 0; padding: .3rem 0; }
.info-paiement span { font-weight: 700; }

/* ============================================================
   13. HEBERGEMENT (tableauHebergement)
   ============================================================ */
table.tableauHebergement.wdgt-receipt thead,
table.tableauHebergement.wdgt-receipt tbody,
table.tableauHebergement.wdgt-receipt tfoot { border: none; }
table.tableauHebergement tbody tr:nth-child(even) { background-color: transparent; }
table.tableauHebergement tbody td,
table.tableauHebergement tbody th { font-size: .8rem; }
table.tableauHebergement tbody th {
    border: 0;
    border-bottom: 2px solid var(--noir);
    text-align: left;
    text-transform: uppercase;
    letter-spacing: .04em;
    font-size: .72rem;
    color: var(--encre-2);
    padding: 10px 8px;
}
table.tableauHebergement tbody td { border-bottom: 1px solid var(--gris-doux); }
table.tableauHebergement.wdgt-receipt .title2,
table.tableauHebergement.wdgt-receipt .title3,
table.tableauHebergement.wdgt-receipt tbody td { width: auto; text-align: left; }
table.tableauHebergement.wdgt-receipt th.title2 { width: 25px; }
table.tableauHebergement.wdgt-receipt th.title3 { width: 90px; }
table.tableauHebergement.wdgt-receipt tbody td:first-child { padding: .5rem .6rem .6rem 0; }
table.tableauHebergement.wdgt-receipt tbody td:first-child label { display: none; }
table.tableauHebergement.wdgt-receipt tbody td label { line-height: 1.3; }
table.tableauHebergement input.qte-field-acco { width: 40px !important; }

/* ============================================================
   14. UPLOAD DE FICHIER (custom-file-input)
   ============================================================ */
.custom-file-input-wrapper { position: relative; width: 100%; max-width: 360px; }
.custom-file-input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.custom-file-label {
    display: inline-flex;
    align-items: center;
    border-radius: var(--rayon-pill);
    padding: 9px 20px;
    font-size: .9rem;
    font-weight: 700;
    cursor: pointer;
    margin-bottom: 4px;
    text-transform: none;
}
.file-selected-label { display: inline-block; margin-left: 10px; color: var(--encre-2); font-size: .85rem; }
.clear-file-input { cursor: pointer; }

/* ============================================================
   15. RABAIS / CODE PROMO (DataType RABA)
   ============================================================ */
#validerRabais { margin: 0 0 0 8px !important; }
.btnSupprimerCodePromo { background: none; border: 0; padding: 0; cursor: pointer; }
.rabaisValide { color: var(--vert-ok); font-weight: 600; }
.erreurRabais { color: var(--rouge); font-weight: 600; }

/* ============================================================
   16. BOUTONS
   .btn1 = action principale, .btn2 = action secondaire.
   L'injection smartlink peut surcharger fond/texte/hover/radius.
   ============================================================ */
.button,
input.button,
input[type=button].button {
    display: inline-block;
    border: 0;
    border-radius: var(--rayon-pill);
    font-family: inherit;
    font-size: 1rem;
    font-weight: 600;
    letter-spacing: .01em;
    text-transform: uppercase;
    padding: 12px 26px;
    margin: 0px;
    cursor: pointer;
    line-height: 1.2;
    transition: var(--transition);
    -webkit-appearance: none;
    appearance: none;
}
/* Survol : leger assombrissement via filter -> fonctionne PAR-DESSUS n'importe quel fond,
   y compris COULEUR_BOUTON1 injecte en !important (que background-color:hover ne pourrait pas
   surcharger). Si COULEUR_HOVER_BOUTON1 est defini, il s'applique aussi (le filtre le nuance). */
.button:hover { transform: translateY(-1px); filter: brightness(1.07); }
.button:disabled { opacity: .45; cursor: not-allowed; transform: none; }

/* Primaire : fond fonce, texte clair (defauts surchargeables). */
input.button.btn1, .button.btn1 {
    background-color: var(--noir);
    color: var(--blanc);
}
input.button.btn1:hover, .button.btn1:hover { background-color: #000; }

/* Secondaire : contour. */
input.button.btn2, .button.btn2 {
    background-color: var(--blanc);
    color: var(--noir);
    border: 1.5px solid var(--gris);
}
input.button.btn2:hover, .button.btn2:hover { border-color: var(--noir); background-color: var(--blanc); }

/* Bouton-lien (texte seul). */
input.button.lien {
    background: none;
    border: 0;
    box-shadow: none;
    padding: 0;
    margin: 0;
    color: var(--noir);
    font-weight: 700;
    text-transform: none;
    text-decoration: underline;
}
input.button.lien:hover { box-shadow: none; transform: none; opacity: .8; }

/* Variantes nommees historiques. */
.btnvert, input.button.confirmerpopupbtn { background-color: var(--noir); color: var(--blanc); }
.btngris, input.button.cancelpopupbtn { background-color: var(--blanc); color: var(--noir); border: 1.5px solid var(--gris); }

/* Barre de boutons de navigation. */
.divBarreBouton {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: center;
    justify-content: flex-end;
    margin-top: 28px;
}
.barreBoutonFixe {
    position: sticky;
    bottom: 0;
    z-index: 40;
    padding: 10px 0;
    background: transparent;
}

/* ============================================================
   17. POPUPS / OVERLAYS
   ============================================================ */
.overlay {
    position: fixed;
    inset: 0;
    background-color: rgba(27,27,27,.55);
    z-index: 1000;
    display: none;
}
.popup {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 70%;
    max-width: 640px;
    max-height: 90%;
    background-color: var(--blanc);
    border-radius: var(--rayon);
    box-shadow: var(--ombre-haute);
    padding: 26px 28px;
    overflow-y: auto;
}
.popup.petit { min-width: 320px; max-width: 460px; }
.popuplignebouton { display: flex; gap: 10px; justify-content: flex-end; height: auto; }
.popupTexte { font-size: 1.05rem; }

#popupOverlay {
    position: fixed;
    inset: 0;
    background: rgba(27,27,27,.55);
    z-index: 1098;
    display: none;
}
/* Popup paiement Authorize.Net. */
#divAuthorizeNetPopup {
    position: fixed;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: 1099;
    max-height: 100vh;
    opacity: 0;
}
#divAuthorizeNetPopup.show { opacity: 1; }
#iframeAuthorizeNet { width: 350px; height: 85vh; border: none; }

/* ============================================================
   18. LOADER + BOITES D'ALERTE
   ============================================================ */
#wg-loader.on {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(255,255,255,.92);
    z-index: 999;
}
#wg-loader #loadimagem {
    width: 96px;
    height: 96px !important;
    position: absolute;
    left: 50%;
    top: 50%;
    margin: -48px 0 0 -48px;
}
#wg-loader.off, #wg-loader.off img { display: none; height: 0; position: absolute; }
#wg-loader p.error { color: var(--rouge); font-weight: 700; position: absolute; }

.alert-box {
    border-radius: var(--rayon);
    text-align: center;
    font-size: 1.1rem;
    font-weight: 700;
    padding: 20px;
    position: absolute;
    margin: auto;
    top: 25%; right: 0; left: 0;
    max-width: 500px; width: 100%;
    box-shadow: var(--ombre-haute);
}
.alert-box span { font-weight: 700; text-transform: uppercase; }
.error   { background-color: #FBE3DC; border: 1px solid #F0B6A6; color: var(--rouge); }
.success { background-color: #E2F5E2; border: 1px solid #A9D7A9; color: var(--vert-ok); }
.warning { background-color: #FBEFC9; border: 1px solid #EBD487; color: #8A6D1B; }

.compteurClignotant { animation: clignoter .8s infinite; }
@keyframes clignoter { 0%{color:var(--encre)} 40%{color:var(--rouge)} 100%{color:var(--encre)} }

/* ============================================================
   19. CLASSES ENFANTS (visibilite conditionnelle) - NE PAS TOUCHER
   ============================================================ */
.child-hidden { display: none !important; }
/* Apparition EN DOUCEUR des elements de retroaction : une @keyframes se joue automatiquement quand
   l'element passe de display:none (child-hidden) a affiche (child-visible). Fiable sur tous les
   navigateurs, sans toucher au display ni au JS. Coupe par le bloc prefers-reduced-motion global.
   La disparition reste instantanee. */
.child-visible:not(tr) {
    display: flex !important;
    animation: retroApparition .4s ease;
}
/* Exception : un .divControl (le CONTENEUR d'une question) revele ne doit pas devenir flex-row.
   La regle ci-dessus, pensee pour les lignes d'options (.ligne-enfant : case + libelle en ligne),
   mettait sinon le fieldset et le message d'erreur (.error-champ-msg) COTE A COTE au lieu de l'un
   sous l'autre. On restaure le display block normal du conteneur ; ses .ligne-enfant internes
   gardent leur flex, et l'animation retroApparition (heritee de la regle ci-dessus) joue toujours. */
.divControl.child-visible { display: block !important; }
tr.child-visible { animation: retroApparitionTr .4s ease; }
@keyframes retroApparition {
    from { opacity: 0; transform: translateY(-20px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes retroApparitionTr {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* ============================================================
   20. TABLEAUX DE BORD / RESULTATS (recherche, tableau groupe)
   ============================================================ */
.ligne-titre { padding: .2rem 0; margin: 0; font-weight: 700; }
.dashboard-table-container {
    border: 1px solid var(--bord);
    border-radius: var(--rayon-sm);
    padding: 12px;
    margin-bottom: 20px;
}
.dashboard-table { background-color: var(--surface); border: 1px solid var(--bord); border-radius: var(--rayon-sm); }
.dashboard-table .btn { margin: 0 .2rem; display: inline-block; position: relative; text-indent: -9999px; height: auto; width: 30px; max-width: 100px; cursor: pointer; }
.dashboard-table .btn:first-child { margin-left: 0; }
.dashboard-table .btn:last-child { margin-right: 0; }
.dashboard-table .disabled { opacity: .2; cursor: default; }
.dashboard-table .resume { content: url("../../images/resume.png"); }
.dashboard-table .consulter { content: url("../img/edit.png"); }
.dashboard-table .supprimer { content: url("../img/delete.jpg"); }

table.tableau-bord, table.resultat-recherche { width: 100%; margin-bottom: 0; border-collapse: collapse; }
table.tableau-bord thead, table.tableau-bord tbody,
table.resultat-recherche thead, table.resultat-recherche tbody { border: none; }
table.tableau-bord th, table.tableau-bord td,
table.resultat-recherche th, table.resultat-recherche td {
    padding: .5rem 10px;
    border-bottom: 1px solid var(--gris-doux);
}
table.tableau-bord th, table.resultat-recherche th {
    text-align: left;
    border-bottom: 2px solid var(--noir);
    background: transparent;
    text-transform: uppercase;
    font-size: .72rem;
    letter-spacing: .04em;
    color: var(--encre-2);
}
table.tableau-bord .ca, table.tableau-bord .cs { width: 1%; text-align: center; white-space: nowrap; }
table.tableau-bord tbody tr:nth-child(even),
table.resultat-recherche tbody tr:nth-child(even) { background-color: var(--surface); }

/* ============================================================
   21. RESPONSIVE
   ============================================================ */
@media screen and (max-width: 800px) {
    #mainDiv { padding: 0 10px 20px; }
    #div-main-form { padding: 0px 3px 0px; }
    header { padding: 14px 0 10px; }

    p, th, td, label { font-size: .95rem; }

    /* Barre de boutons empilee, ordre logique conserve. */
    .divBarreBouton { flex-direction: column-reverse; align-items: stretch; }
    .divBarreBouton .button { width: 100%; text-align: center; margin: 0; }
    .barreBoutonFixe { position: sticky; bottom: 0; background: var(--surface); padding: 12px 0 18px; }

    .small-6, .small-4, .small-3 { width: 100%; }
    .ligne-enfant:not(tr) { width: 100% !important; }

    #steplist > .columns { flex-wrap: wrap; }
    #steplist #lblSteplist { display: none; }
    #steplist #lblSteplistShort { display: block; }

    .extra-text { width: 180px; max-width: 100%; }
    /* Champ "Preciser" : toujours sous l'option en mobile, aligne avec le libelle
       (decalage = largeur du radio 18px + gap 10px = 28px) et flush a droite.
       margin-left en !important pour battre le margin !important de la regle .extra-text ;
       max-width:none pour ne PAS couper a droite ; flex 1 1 100% pour remplir la ligne. */
    .ligne-enfant:has(.extra-text) > .extra-text {
        flex: 1 1 100%;
        width: auto;
        max-width: none;
        margin-left: 28px !important;
    }
    .placesRestante { visibility: hidden; height: 0; margin: 0; padding: 0; }
    .popup { width: 92%; }
    .dashboard-table-container { border: 0; }
    .input-autocomplete, input.phone { max-width: 100%; }
}

@media screen and (min-width: 801px) and (max-width: 1200px) {
    .placesRestante { margin-bottom: 0px; margin-right: 15px; }
    .largeur20Pourcent { width: 20%; }
}

@media screen and (min-width: 1201px) {
    .placesRestante { margin-bottom: 0px; margin-right: 15px; }
    .largeur20Pourcent { width: 20%; }
}

/* ============================================================
   22. TOPBAR / ENTETE (look maquette)
   COULEURS DE MARQUE : pilotees par _assignerCSSPage (CSS_SMARTLINK),
   JAMAIS codees ici. L'injection ajoute la topbar dans ses listes :
     - fond du bandeau = COULEUR_BOUTON1        (header.topbar)
     - texte/icones    = COULEUR_TEXTE_BOUTON1  (selecteurs .topbar ...)
   Ici : STRUCTURE + valeurs de REPLI (memes defauts que .btn1), que
   l'injection surcharge. Le texte/les bordures heritent (inherit /
   currentColor) pour suivre COULEUR_TEXTE_BOUTON1. Seuls la pastille
   langue ACTIVE et le PANIER sont en blanc/noir neutres (demande client).
   Ids conserves (#lblTimer #changementLangue #changementLangueLabel
   #lblVisiteurInfoHeader .divChangementLangue) pour ne rien casser.
   ============================================================ */
header.topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 7px;
    /* Repli = defauts de .btn1 ; surcharges par COULEUR_BOUTON1 / _TEXTE_BOUTON1. */
    background: var(--noir);
    color: var(--blanc);
    /* Pleine largeur VIEWPORT (full-bleed) avec contenu centre ~1180px, facon maquette.
       calc(50% - 50vw) sort la barre du conteneur centre #mainDiv jusqu'aux bords. */
    margin: 0 calc(50% - 50vw) 0;
    padding: 12px clamp(20px, calc(50vw - 579px), 400px);
    position: sticky;
    top: 0;
    z-index: 60;
}
.topbar-session { display: flex; align-items: center; min-width: 0; }
.topbar-outils { display: flex; align-items: center; gap: 36px; flex-wrap: wrap; justify-content: flex-end; }

/* Mode "simple" (window.TOPBAR_SIMPLE, pages hors flux : calendrier, presence, acces...) :
   header = uniquement le switch de langue, sans timer de session ni panier. */
.topbar.topbar-simple .session-pill,
.topbar.topbar-simple .panier { display: none !important; }

@media screen and (max-width: 800px) {
    .topbar-outils {
        gap: 12px;
    }
}

/* Session pill : contour + texte = couleur texte-bouton (heritee). Cachee si minuteur vide. */
.session-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border: 1px solid currentColor;
    border-radius: var(--rayon-pill);
    padding: 6px 14px;
    font-size: .8rem;
    font-weight: 700;
    color: inherit;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    opacity: .92;
}
.session-pill #lblTimer { color: inherit; font-weight: 800; }
.session-pill:has(#lblTimer:empty) { display: none; }
/* Le libelle "Temps :" / "Time :" n'apparait qu'en ordi ; en mobile on garde juste le temps (peu de place). */
@media screen and (max-width: 800px) { #lblTimer .timer-label { display: none; } }

/* Repli : nom de l'evenement (zone gauche) affiche quand timer + panier + langue sont tous absents
   (sinon la topbar serait presque vide). Couleur = texte topbar herite (surcharge par
   COULEUR_TEXTE_BOUTON1 via l'injection). Affiche/masque par le JS (attribut hidden). */
.topbar-event {
    color: inherit;
    font-weight: 700;
    font-size: 1rem;
    line-height: 1.2;
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Desktop : nom COMPLET ; mobile (<=800px) : version TRONQUEE a 40 caracteres (geree en JS). */
.topbar-event .evt-court { display: none; }
.topbar-event .evt-complet { display: inline; }
@media screen and (max-width: 800px) {
    .topbar-event .evt-complet { display: none; }
    .topbar-event .evt-court { display: inline; }
}

/* Panier : chip blanc/noir NEUTRE (demande client), force pour lisibilite. */
.panier {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    background: #ffffff !important;
    color: #1B1B1B !important;
    border-radius: var(--rayon-pill);
    padding: 6px 15px;
    font-size: .9rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

@media screen and (max-width: 800px) {
    .panier {
        padding: 6px 11px 6px 5px;
    }
}

.panier[hidden] { display: none; }
.panier b { color: #1B1B1B !important; font-weight: 800; }
.panier .panier-ico { font-size: .95rem; line-height: 1; }
/* Total + petite mention "hors taxes" empiles dans la pastille. */
.panier .panier-txt { display: inline-flex; flex-direction: column; align-items: flex-start; line-height: 1.05; }
.panier .panier-note { font-size: .71rem; font-weight: 600; opacity: .75; text-transform: none; letter-spacing: 0; color: #1B1B1B; }

/* Aide : cercle (contour + ? = couleur texte-bouton heritee) + bulle blanche. */
.aide { position: relative; display: inline-flex; }
.aide[hidden] { display: none; }
.aide-btn {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: 2px solid currentColor;
    background: transparent;
    color: inherit;
    font-weight: 600;
    font-size: 1.4rem;
    line-height: 1;
    display: grid;
    place-items: center;
    cursor: pointer;
    transition: var(--transition);
}
.aide-btn:hover { background: #ffffff !important; color: #1B1B1B !important; border-color: #ffffff; }
.aide-bulle {
    position: absolute;
    top: calc(100% + 12px);
    right: 0;
    width: 420px;
    max-width: 78vw;
    background: #fff;
    color: var(--encre);
    border: 1px solid var(--bord);
    border-radius: 12px;
    padding: 14px 16px;
    box-shadow: var(--ombre-haute);
    font-size: .8rem;
    font-weight: 500;
    line-height: 1.5;
    text-align: left;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: var(--transition);
    z-index: 70;
}
.aide:hover .aide-bulle,
.aide:focus-within .aide-bulle { opacity: 1; visibility: visible; transform: none; }

/* ---------------------------------------------------------------------------
   Bulle d'aide d'une QUESTION (FID_VALEUR_AIDE) : meme composant que l'aide de
   la topbar, mais en ligne au bout du titre. Trois differences imposees par le
   contexte :
     - fond clair (la topbar est foncee) -> le :hover blanc du bouton y serait
       invisible, on l'inverse ;
     - pastille plus petite, pour ne pas dominer le libelle ;
     - bulle ancree a GAUCHE : la question commence a gauche de l'ecran, alors
       que l'aide de la topbar est collee au bord droit.
   --------------------------------------------------------------------------- */
/* Fin de titre insecable : dernier mot du libelle + asterisque + icone d'aide, colles ensemble
   par le helper titreQuestion. Empeche l'asterisque et/ou l'icone de basculer SEULS sur la ligne
   suivante. Si l'ensemble ne rentre pas, c'est le groupe COMPLET (dernier mot inclus) qui passe a
   la ligne : jamais un orphelin. */
.titre-fin { white-space: nowrap; }

.aide-question { vertical-align: middle; margin-left: 6px; margin-bottom: 2px; }
.aide-question .aide-btn {
    width: 19px;
    height: 19px;
    /* Le "?" et le contour suivent la couleur du texte : COULEUR_TEXTE_PRINCIPALE quand elle est
       injectee (elle vise label/span en !important, et le bouton en herite), sinon la couleur de
       texte par defaut du titre. Aucune couleur codee en dur ici. */
    color: inherit;
    border-color: currentColor;
    /* padding: 0 + line-height: 1 : sans ca le padding par defaut du <button> decale le "?"
       dans la pastille, malgre le place-items: center. */
    padding: 0;
    line-height: 1;
    font-size: .85rem;
    font-weight: 700;
}
.aide-question .aide-btn:hover,
.aide-question .aide-btn:focus {
    /* REPLI seulement (aucun branding) : voile neutre. Des que COULEUR_BOUTON1 est definie,
       _assignerCSSPage injecte a la place un voile pale de cette couleur
       -- color-mix(in srgb, COULEUR_BOUTON1 14%, #fff) -- comme le survol des .ligne-enfant.
       !important : necessaire pour battre le :hover blanc du composant .aide-btn de la topbar. */
    background: rgba(0, 0, 0, .08) !important;
    color: inherit !important;
    border-color: currentColor;
}
.aide-question .aide-bulle {
    left: 0;
    right: auto;
    width: 340px;
    font-weight: 400;
    /* Le titre de question est gras/en majuscules selon le gabarit : on remet
       une typo de texte courant dans la bulle. */
    text-transform: none;
    letter-spacing: 0;
    white-space: normal;
}
/* Question en fin de ligne : on evite que la bulle deborde a droite. */
.aide-question .aide-bulle { max-width: min(78vw, 340px); }

/* Info visiteur (backend) : couleur texte-bouton (heritee). */
.topbar-visiteur { color: inherit; font-size: .8rem; font-weight: 600; align-self: center; border: 0; box-shadow: none; }

/* Switch langue FR/EN (pastilles) facon maquette.
   Inactif = couleur texte-bouton (heritee). Actif = blanc/noir neutre (demande client). */
.topbar .divChangementLangue { margin: 0; display: flex; align-items: center; }
.lang-switch {
    display: inline-flex;
    border: 1px solid currentColor;
    border-radius: var(--rayon-pill);
    overflow: hidden;
    color: inherit;
}
.lang-switch button {
    background: transparent;
    color: inherit;
    border: 0;
    font-family: inherit;
    font-weight: 700;
    font-size: .85rem;
    letter-spacing: .06em;
    padding: 11px 16px;
    cursor: pointer;
    transition: var(--transition);
}

@media screen and (max-width: 800px) {
    .lang-switch button {
        padding: 11px 14px;
    }
}

.lang-switch button:hover { background: rgba(127,127,127,.18); }
.topbar .lang-switch button.actif { background: #ffffff !important; color: #1B1B1B !important; }
.topbar #changementLangueLabel { color: inherit; font-size: .8rem; margin: 0; }

/* Le <select> natif est TOUJOURS masque dans la topbar : la seule UI est les boutons .lang-switch
   construits par inscript_topbar.js. Le cacher en CSS (et non seulement via JS au window.load) evite
   le FOUC : sinon, entre le retrait du loader et le window.load -- fenetre qui s'allonge sur un poste
   ou une ressource tarde a charger -- le select natif s'affichait en clair (surtout au reload apres
   changement de langue, ou il est deja peuple). La topbar etant elle-meme injectee par JS, une page
   qui l'affiche execute forcement le JS : masquer le select ne prive jamais du selecteur. */
.topbar #changementLangue { display: none !important; }

@media screen and (max-width: 800px) {
    header.topbar { padding: 10px 8px; }
    .topbar-visiteur { display: none; }
    .session-pill { padding: 9px 10px; }
}

/* Tres petit ecran : on resserre encore (paddings/gaps/police du switch) pour garder la topbar sur
   UNE ligne le plus longtemps possible, meme avec 3 langues + note plus longue. Au-dela, flex-wrap
   la fait passer proprement sur 2 lignes -> jamais coupee. */
@media screen and (max-width: 390px) {
    header.topbar { padding: 9px 6px; gap: 6px; }
    .topbar-outils { gap: 7px; }
    .session-pill { padding: 6px 8px; }
    .panier { padding: 4px 9px; }
    .lang-switch button { padding: 9px 14px; font-size: .80rem; letter-spacing: .02em; }
    .aide-btn { width: 27px; height: 27px; font-size:1.1rem;}
}


/* ============================================================
   AVERTISSEMENT D'EXPIRATION DE SESSION (modal hybride)
   Injecte par app_commun.js sur index / pageResume / pageHebergement.
   .btn1 / .btn2 heritent du branding smartlink (assignerCSSPage).
   ============================================================ */
body.session-modal-ouvert { overflow: hidden; }

.session-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 3000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 22px;
    background: color-mix(in srgb, #0a0c10 55%, transparent);
    -webkit-backdrop-filter: blur(2px);
            backdrop-filter: blur(2px);
    animation: sessionScrimIn .22s ease both;
}
.session-modal-overlay[hidden] { display: none; }
@keyframes sessionScrimIn { from { opacity: 0; } to { opacity: 1; } }

.session-modal {
    width: 100%;
    max-width: 400px;
    background: var(--blanc);
    border: 1px solid var(--bord);
    border-radius: var(--rayon);
    box-shadow: var(--ombre-haute);
    padding: 30px 28px 24px;
    text-align: center;
    animation: sessionModalIn .3s cubic-bezier(.32, .72, .32, 1.1) both;
}
@keyframes sessionModalIn {
    from { opacity: 0; transform: translateY(10px) scale(.975); }
    to   { opacity: 1; transform: none; }
}

.session-modal-ring {
    --pct: 100;
    width: 112px;
    height: 112px;
    margin: 0 auto 18px;
    position: relative;
}
.session-modal-ring::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: conic-gradient(var(--rouge) calc(var(--pct) * 1%), var(--gris-doux) 0);
    -webkit-mask: radial-gradient(farthest-side, transparent 61%, #000 62%);
            mask: radial-gradient(farthest-side, transparent 61%, #000 62%);
    transition: background .95s linear;
}
.session-modal-count {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.8rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--encre);
}
.session-modal.pulse .session-modal-count { animation: sessionPulse 1s ease-in-out infinite; }
@keyframes sessionPulse { 0%, 100% { color: var(--encre); } 50% { color: var(--rouge); } }

.session-modal-titre {
    font-size: 1.22rem;
    font-weight: 700;
    color: var(--encre);
    margin: 0 0 9px;
    line-height: 1.3;
    text-wrap: balance;
}
.session-modal-msg {
    font-size: .95rem;
    line-height: 1.55;
    color: var(--encre-2);
    margin: 0 auto;
    max-width: 32ch;
}
.session-modal-actions {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-top: 22px;
}
.session-modal-actions .button { width: 100%; }

@media screen and (max-width: 800px) {
    .session-modal { padding: 26px 20px 20px; }
    .session-modal-ring { width: 100px; height: 100px; }
}
@media (prefers-reduced-motion: reduce) {
    .session-modal-overlay, .session-modal { animation: none; }
    .session-modal-ring::before { transition: none; }
    .session-modal.pulse .session-modal-count { animation: none; }
}
