/* ==========================================================================
   ZONETANA — Habillage des formulaires OpForPro
   --------------------------------------------------------------------------
   Deux formulaires passent par ici, et ils doivent se ressembler : celui
   d'INSCRIPTION dans la modale d'essai (campagne m7wgz) et celui de
   CONNEXION sur /connexion (campagne 3mXES). Tous deux sont injectés par le
   même moteur, avec le même gabarit « iron » — un seul habillage suffit donc
   aux deux, et c'est la seule façon de garantir qu'ils ne divergeront pas.

   L'ENVELOPPE À POSER est `<div id="zt-opf-form" class="trial-form">` autour
   du conteneur que le widget vise. Sans elle, le formulaire sort en gabarit
   d'origine : champs blancs, bouton rouge sombre, liens bleus soulignés.

   Le widget charge SA feuille via un <link> ajouté au <head> en JavaScript :
   https://c.opforpro.com/8/css/contents/registerform/iron.css

   DEUX CONSÉQUENCES, qui expliquent la forme de ce fichier.

   1. Sa feuille arrive APRÈS les nôtres. À spécificité égale, elle gagne.
   2. Elle habille les champs ainsi (relevé dans iron.css) :

        .ptprelinker-contents-register-form-iron
        .ptprelinker-content .ptprelinker-content-inner
        .ptprelinker-register-form .ptprelinker-input
            { border: 2px solid #acacac !important;
              border-radius: 0 32px 32px 0 !important;
              border-left: 0 !important;
              height: 52px !important }

      Cinq classes ET !important. Entre deux !important, c'est la spécificité
      qui départage : aucune règle en `.trial-form input` ne peut passer
      devant, quel que soit le nombre de !important qu'on y ajoute. D'où
      l'identifiant `#zt-opf-form`, posé sur l'enveloppe dans
      components/register-trial-modal.blade.php et dans auth/login.blade.php :
      un ID pèse plus que n'importe quel empilement de classes. C'est la
      raison d'être du préfixe qu'on retrouve sur chaque règle ci-dessous.
      Il est donc UNIQUE PAR PAGE : aucune page ne porte à la fois la modale
      d'essai et le formulaire de connexion.

   On cible ses classes internes (`ptprelinker-*`), relevées sur le DOM réel,
   mais elles peuvent changer côté régie sans préavis : si l'habillage saute
   d'un coup sans qu'on ait touché au site, c'est ici qu'il faut regarder.

   Servi en statique comme fan.css : modifiable sans rebuild Vite. Les
   valeurs viennent des tokens (resources/css/tokens.css).
   ========================================================================== */

/* ------------------------------------------------ conteneur et espacements --- */

/* Le gabarit pose son propre fond et son propre cadre ; la modale a déjà les
   siens, et deux cadres imbriqués font bricolage. */
#zt-opf-form [class*="ptprelinker-contents-"],
#zt-opf-form [class*="ptprelinker-themes-"],
#zt-opf-form .ptprelinker-content,
#zt-opf-form .ptprelinker-content-inner {
    background: transparent !important;
    border: 0 !important;
    box-shadow: none !important;
    padding: 0 !important;
}

/* 1,5 rem entre deux champs : calibré pour une page entière, beaucoup trop
   dans une modale où le bouton doit rester au-dessus de la ligne de
   flottaison sur téléphone. */
#zt-opf-form .ptprelinker-input-group {
    margin-bottom: 10px !important;
}

/* ------------------------------------------------------- pastilles d'icône --- */

/* Le gabarit « iron » colle à gauche de chaque champ une pastille grise
   (#e5e5e5) portant une icône. Sur fond noir, ces quatre blocs clairs sont
   ce qui se voit en premier du formulaire — avant les champs eux-mêmes.
   On les retire complètement plutôt que de les recolorer : elles ne portent
   aucune information que le placeholder ne donne déjà. */
#zt-opf-form .ptprelinker-input-group-prepend,
#zt-opf-form .ptprelinker-input-group-text,
#zt-opf-form [class*="ptprelinker-icon-"] {
    display: none !important;
}

/* Étiquettes vides laissées par le gabarit (le champ e-mail en porte une) :
   sans contenu mais pas sans hauteur. */
#zt-opf-form label.ptprelinker-label:empty {
    display: none !important;
}

/* ---------------------------------------------------------- champs de saisie --- */

/* Mêmes valeurs que `.sn-input` (app.css). Le rayon est rétabli sur les
   QUATRE coins et la bordure gauche restaurée : le gabarit les supprimait
   pour souder le champ à la pastille d'icône, qui n'existe plus ci-dessus. */
#zt-opf-form .ptprelinker-input,
#zt-opf-form .ptprelinker-select,
#zt-opf-form input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="hidden"]),
#zt-opf-form select {
    width: 100% !important;
    flex: 1 1 auto !important;
    height: auto !important;
    min-height: 46px !important;
    padding: 11px 14px !important;
    background-color: rgb(var(--sn-bg-200)) !important;
    background-image: none !important;
    /* Longhands explicites et non le raccourci `border` : le gabarit annule
       la bordure gauche par une déclaration `border-left: 0 !important`
       distincte, qu'un raccourci ne recouvre pas toujours de façon lisible
       une fois les deux feuilles empilées. */
    border-width: 1px !important;
    border-style: solid !important;
    border-color: rgb(var(--sn-gray-400)) !important;
    border-left-width: 1px !important;
    border-left-style: solid !important;
    border-left-color: rgb(var(--sn-gray-400)) !important;
    border-radius: var(--sn-radius-lg) !important;
    color: rgb(var(--sn-gray-1000)) !important;
    font-family: var(--sn-font-sans) !important;
    font-weight: var(--sn-weight-medium) !important;
    /* 16 px : en dessous, iOS zoome à la sélection du champ et laisse la
       modale de travers. */
    font-size: 16px !important;
    line-height: 1.3 !important;
    box-shadow: none !important;
    transition: border-color var(--sn-duration-fast) var(--sn-ease),
                background-color var(--sn-duration-fast) var(--sn-ease) !important;
}

/* Le gabarit remet un rayon nul et un halo au focus : on rétablit le nôtre,
   une bordure accent, cohérent avec tous les champs du site.

   Les `:not()` de la règle des champs sont repris ici pour la même raison que
   plus bas sur le remplissage automatique : sans eux, `#zt-opf-form
   input:focus` (1,1,1) passe SOUS la règle des champs (1,4,1), dont le
   `border-color !important` gagne — et la bordure accent ne s'affichait
   jamais. */
#zt-opf-form .ptprelinker-input:focus,
#zt-opf-form .ptprelinker-select:focus,
#zt-opf-form input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="hidden"]):focus,
#zt-opf-form select:focus {
    outline: none !important;
    border-color: rgb(var(--sn-accent)) !important;
    border-radius: var(--sn-radius-lg) !important;
    background-color: rgb(var(--sn-gray-200)) !important;
    box-shadow: none !important;
}

/* Champ rempli par le gestionnaire de mots de passe du navigateur. Chrome et
   Safari repeignent alors le fond en bleu très clair et ignorent
   `background-color` : la SEULE prise est une ombre interne assez épaisse
   pour couvrir le champ entier.

   D'où le sélecteur, qui recopie les quatre `:not()` de la règle ci-dessus.
   Ce n'est pas de la superstition : chaque `:not([type="…"])` pèse autant
   qu'une classe, la règle des champs pose donc (1,4,1) et son
   `box-shadow: none !important` écrase tout sélecteur plus léger — y compris
   un `#zt-opf-form input:-webkit-autofill` (1,1,1), pourtant écrit plus bas.
   Entre deux `!important`, seule la spécificité tranche. Avec les mêmes
   `:not()` plus la pseudo-classe, on passe à (1,5,1) et l'ombre s'applique.

   Sans elle : champ blanc, et texte blanc par-dessus, donc illisible — c'est
   le premier champ de la page de connexion. */
#zt-opf-form .ptprelinker-input:-webkit-autofill,
#zt-opf-form .ptprelinker-input:-webkit-autofill:hover,
#zt-opf-form .ptprelinker-input:-webkit-autofill:focus,
#zt-opf-form .ptprelinker-input:-webkit-autofill:active,
#zt-opf-form input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="hidden"]):-webkit-autofill,
#zt-opf-form input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="hidden"]):-webkit-autofill:hover,
#zt-opf-form input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="hidden"]):-webkit-autofill:focus,
#zt-opf-form input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="hidden"]):-webkit-autofill:active {
    -webkit-box-shadow: 0 0 0 1000px rgb(var(--sn-bg-200)) inset !important;
    box-shadow: 0 0 0 1000px rgb(var(--sn-bg-200)) inset !important;
    -webkit-text-fill-color: rgb(var(--sn-gray-1000)) !important;
    caret-color: rgb(var(--sn-gray-1000)) !important;
    /* Firefox n'écoute pas l'ombre interne : lui répond à ces deux-là, que
       les autres navigateurs ignorent. */
    filter: none !important;
    background-color: rgb(var(--sn-bg-200)) !important;
    background-image: none !important;
    /* Le navigateur rejoue sa transition de fond au remplissage : on la
       repousse hors de portée plutôt que de la subir. */
    transition: background-color 9999s ease-in-out 0s !important;
}

/* La pseudo-classe standard, pour les navigateurs qui ne répondent pas au
   préfixe. Elle vit dans SA PROPRE règle : un sélecteur qu'un navigateur ne
   comprend pas invalide toute la liste où il se trouve, et on ne veut pas
   qu'une pseudo-classe encore jeune emporte l'ombre interne ci-dessus. */
#zt-opf-form input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="hidden"]):autofill {
    background-color: rgb(var(--sn-bg-200)) !important;
    -webkit-text-fill-color: rgb(var(--sn-gray-1000)) !important;
    color: rgb(var(--sn-gray-1000)) !important;
}

/* Les gestionnaires tiers (1Password, Bitwarden) marquent le champ par un
   attribut à eux et ne déclenchent aucune des deux pseudo-classes. */
#zt-opf-form input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="hidden"])[data-com-onepassword-filled] {
    background-color: rgb(var(--sn-bg-200)) !important;
    -webkit-text-fill-color: rgb(var(--sn-gray-1000)) !important;
    color: rgb(var(--sn-gray-1000)) !important;
}

/* Palier 800 et non 700 comme le reste du site : sur le fond très sombre des
   champs, le gris tertiaire tombe à ~2,6:1, sous le minimum lisible. Le
   palier au-dessus remonte à ~6,8:1 tout en restant nettement en retrait du
   blanc pur de la valeur saisie — un placeholder illisible dans une modale
   d'inscription, c'est un champ qu'on ne sait pas quoi remplir. */
#zt-opf-form ::placeholder {
    color: rgb(var(--sn-gray-800)) !important;
    opacity: 1 !important;
}

/* Les listes déroulantes arrivent avec la couleur du placeholder même une
   fois renseignées, et une flèche grise posée en image de fond — que la
   règle ci-dessus efface. On remet un chevron, au trait du site. */
#zt-opf-form .ptprelinker-select,
#zt-opf-form select {
    -webkit-appearance: none !important;
    -moz-appearance: none !important;
    appearance: none !important;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23b2b2be' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") !important;
    background-repeat: no-repeat !important;
    background-position: right 12px center !important;
    background-size: 16px 16px !important;
    /* Redit après background-image : le gabarit peint le fond des listes avec
       le raccourci `background`, qui remet la couleur à blanc au passage. */
    background-color: rgb(var(--sn-bg-200)) !important;
    padding-right: 38px !important;
    /* Blanc plein pour les DEUX listes, choisies ou non. Les griser tant que
       rien n'est sélectionné ne marcherait que sur la première : l'option par
       défaut de la liste d'âge porte son libellé comme valeur (« Age »), donc
       le champ n'est jamais `:invalid` et resterait blanc. Une invite grise
       au-dessus d'une invite blanche est pire que deux invites blanches. */
    color: rgb(var(--sn-gray-1000)) !important;
}

/* Le menu déroulant lui-même est dessiné par le système : sans couleur
   explicite, certains navigateurs affichent du texte blanc sur blanc.

   `.ptprelinker--box` couvre le formulaire d'INSCRIPTION (campagne rhpBg,
   gabarit « fullpage ») : celui-là s'ajoute de lui-même en fin de <body>,
   sans conteneur à envelopper, donc aucune règle `#zt-opf-form` ne
   l'atteint. Son habillage sombre d'origine convient, sauf ici : il peint
   la valeur en blanc et le menu natif, lui, reste sur le fond clair du
   système — blanc sur blanc, les options ne se lisent qu'au survol. C'est
   la même classe que celle guettée par partials/opf-repli, posée quel que
   soit le type de conteneur. */
#zt-opf-form option,
.ptprelinker--box option {
    background-color: rgb(var(--sn-bg-200)) !important;
    color: rgb(var(--sn-gray-1000)) !important;
}

/* `option` ne suffit pas partout : le menu natif est un widget du système,
   qui sur plusieurs navigateurs ignore la couleur de fond des options et ne
   lit que le thème déclaré. Sans cette ligne, Chromium rouvre un menu clair
   avec, par-dessus, notre texte blanc. Posé sur le champ et pas sur la
   page : on ne bascule que le menu, le reste du site a déjà son thème. */
#zt-opf-form select,
.ptprelinker--box select {
    color-scheme: dark !important;
}

/* ------------------------------------------------------------------ bouton --- */

/* Copie de `.sn-button--filled` : aplat accent, texte NOIR — le rouge de
   marque est trop clair pour porter du blanc lisible — et pilule pleine.
   C'est l'élément le plus gros du bloc, celui qu'on cherche du regard une
   fois les champs remplis. */
#zt-opf-form .ptprelinker-button,
#zt-opf-form input[type="submit"],
#zt-opf-form button {
    /* SURTOUT PAS de `display` ici. Le widget garde plusieurs boutons d'état
       dans le DOM — « Envoyé ! », erreurs — et les masque en `display: none`.
       Un `display: block !important` passait devant et les allumait tous en
       même temps : c'est ce qui empilait deux pilules rouges sous le champ du
       mot de passe oublié. Un <button> est `inline-block`, `width: 100%` suffit
       à l'étendre, et `vertical-align` supprime l'espace de ligne qui reste
       sinon sous un inline. */
    vertical-align: middle !important;
    width: 100% !important;
    max-width: 100% !important;
    min-height: 50px !important;
    margin-top: 4px !important;
    padding: 13px 18px !important;
    background: rgb(var(--sn-accent)) !important;
    background-image: none !important;
    border: 0 !important;
    border-radius: var(--sn-radius-full) !important;
    color: rgb(var(--sn-black)) !important;
    font-family: var(--sn-font-sans) !important;
    font-size: 15.5px !important;
    font-weight: var(--sn-weight-bold) !important;
    letter-spacing: 0 !important;
    line-height: 1.2 !important;
    box-shadow: var(--sn-shadow-accent) !important;
    cursor: pointer !important;
    transition: background-color var(--sn-duration-fast) var(--sn-ease) !important;
}

#zt-opf-form .ptprelinker-button:hover,
#zt-opf-form input[type="submit"]:hover {
    background: rgb(var(--sn-accent-hover)) !important;
}

#zt-opf-form .ptprelinker-button:active,
#zt-opf-form input[type="submit"]:active {
    background: rgb(var(--sn-accent-500)) !important;
}

/* ------------------------------------------- mot de passe oublié (connexion) --- */

/* Le formulaire de CONNEXION (campagne 3mXES, gabarit `loginform/default`)
   cache sous « Mot de passe oublié ? » une bulle en `position: absolute` :

     .ptprelinker-login-form
       a.ptprelinker-forgotten-link      le lien qui l'ouvre
       .ptprelinker-forgotten-form.show  la bulle, flèche en ::before
         .ptprelinker-forgotten-label > input   le champ e-mail
         .ptprelinker-buttons > button          « Mot de passe perdu »
         .ptprelinker-forgotten-success         « Envoyé ! », par-dessus

   Sa bulle, sa flèche et son bandeau de succès prennent leur fond dans les
   variables de thème du widget (`--ptprelinker-css-bg-popup`), que notre
   intégration ne définit pas : la bulle sortait donc TRANSPARENTE, posée sur
   le formulaire de connexion qu'on lisait au travers. On repeint ici ce que
   ces variables auraient donné, aux tokens du site. */
#zt-opf-form .ptprelinker-forgotten-form {
    /* Un cran plus clair que les champs : la bulle doit se détacher du
       formulaire qu'elle recouvre, pas s'y fondre. */
    background-color: rgb(var(--sn-gray-200)) !important;
    border: 1px solid rgb(var(--sn-gray-500)) !important;
    border-radius: var(--sn-radius-lg) !important;
    box-shadow: var(--sn-shadow-lg) !important;
    color: rgb(var(--sn-gray-1000)) !important;
    padding: 12px 14px !important;
    gap: 10px !important;
    z-index: 999 !important;
}

/* La flèche qui rattache la bulle au lien : un triangle dessiné en bordures,
   dont seule la couleur du bas se voit. */
#zt-opf-form .ptprelinker-forgotten-form::before {
    border-bottom-color: rgb(var(--sn-gray-500)) !important;
}

/* Le bandeau de confirmation recouvre la bulle entière : sans fond opaque,
   « Envoyé ! » se lisait par-dessus le bouton resté visible dessous. */
#zt-opf-form .ptprelinker-forgotten-success {
    background-color: rgb(var(--sn-gray-200)) !important;
    border: 1px solid rgb(var(--sn-gray-500)) !important;
    border-radius: var(--sn-radius-lg) !important;
    color: rgb(var(--sn-gray-1000)) !important;
    font-weight: var(--sn-weight-bold) !important;
}

/* Dans la bulle, le champ et le bouton sont CÔTE À CÔTE (flex row) et la
   bulle se dimensionne sur son contenu. Les largeurs pleines héritées des
   règles générales l'étiraient hors de l'écran et repoussaient le bouton
   sous le champ. */
#zt-opf-form .ptprelinker-forgotten-form .ptprelinker-input,
#zt-opf-form .ptprelinker-forgotten-form input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="hidden"]) {
    width: auto !important;
    min-width: 200px !important;
    max-width: 100% !important;
    flex: 0 1 auto !important;
    margin-bottom: 0 !important;
}

#zt-opf-form .ptprelinker-forgotten-form .ptprelinker-button,
#zt-opf-form .ptprelinker-forgotten-form button {
    width: auto !important;
    min-width: 0 !important;
    margin-top: 0 !important;
    padding: 10px 16px !important;
    font-size: 14px !important;
    white-space: nowrap !important;
}

/* Le libellé du champ dans la bulle (« E-mail »), et le titre qu'elle porte
   parfois : ils héritaient du blanc des titres du site sur un fond qui,
   transparent, laissait passer le hero. Ils redeviennent lisibles une fois la
   bulle opaque, mais leur taille reste à recaler. */
#zt-opf-form .ptprelinker-forgotten-label {
    margin: 0 !important;
    color: rgb(var(--sn-gray-900)) !important;
    font-size: 13px !important;
}

/* Sur téléphone, la bulle passe en colonne (le gabarit le prévoit) : tout
   reprend alors la pleine largeur, sinon le champ devient minuscule. */
@media (max-width: 575px) {
    #zt-opf-form .ptprelinker-forgotten-form .ptprelinker-input,
    #zt-opf-form .ptprelinker-forgotten-form input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="hidden"]),
    #zt-opf-form .ptprelinker-forgotten-form .ptprelinker-button,
    #zt-opf-form .ptprelinker-forgotten-form button {
        width: 100% !important;
        min-width: 0 !important;
    }
}

/* ------------------------------------------------- case à cocher et mentions --- */

/* `:not([style*="none"])` n'est pas une précaution de style : le formulaire
   contient une SECONDE case, sur les données sensibles, que le widget garde
   masquée par un style en ligne et ne révèle que si l'on choisit « Couple ».
   Un `display: flex !important` sans cette exclusion passe devant le style
   en ligne et l'affiche en permanence — y compris sa mention juridique, hors
   contexte. Le test d'attribut suit aussi le widget quand il la rouvre. */
#zt-opf-form .ptprelinker-checkbox:not([style*="none"]) {
    display: flex !important;
    align-items: flex-start !important;
    gap: 0.6rem !important;
    margin: 2px 0 10px !important;
}

/* La case visible n'est PAS la case du formulaire. Le gabarit met celle-ci en
   `opacity: 0` et dessine le carré en pseudo-élément sur l'étiquette :
   `accent-color` n'a donc aucun effet ici, et la couleur vient de sa propre
   variable de marque. C'est le pseudo-élément qu'il faut peindre. On laisse
   en revanche la géométrie de la vraie case intacte — elle est positionnée
   sous le carré dessiné et porte la zone de clic. */
#zt-opf-form .ptprelinker-input-checkbox,
#zt-opf-form input[type="checkbox"] {
    min-height: 0 !important;
    padding: 0 !important;
    background: none !important;
    border: 0 !important;
    border-radius: 0 !important;
    accent-color: rgb(var(--sn-accent)) !important;
    cursor: pointer !important;
}

/* Case au repos : le même creux que les champs de saisie. */
#zt-opf-form .ptprelinker-input-checkbox + .ptprelinker-label-checkbox::before {
    border: 1px solid rgb(var(--sn-gray-500)) !important;
    border-radius: var(--sn-radius-sm) !important;
    background-color: rgb(var(--sn-bg-200)) !important;
    /* La coche est un glyphe de police, pas un tracé : elle se colore par
       `color`. Noire sur l'accent, comme le libellé du bouton — le rouge de
       marque est trop clair pour porter du blanc lisible (≈2,9:1 contre
       ≈5:1 en noir). */
    color: rgb(var(--sn-black)) !important;
    transition: background-color var(--sn-duration-fast) var(--sn-ease),
                border-color var(--sn-duration-fast) var(--sn-ease) !important;
}

/* Case cochée : l'aplat du bouton. */
#zt-opf-form .ptprelinker-input-checkbox:checked + .ptprelinker-label-checkbox::before {
    border-color: rgb(var(--sn-accent)) !important;
    background-color: rgb(var(--sn-accent)) !important;
    color: rgb(var(--sn-black)) !important;
}

/* La mention d'âge et les CGU sont une obligation, pas un argument : elles
   se lisent sans capter l'œil avant le bouton. */
#zt-opf-form .ptprelinker-label-checkbox,
#zt-opf-form .ptprelinker-checkbox label {
    margin: 0 !important;
    color: rgb(var(--sn-gray-900)) !important;
    font-family: var(--sn-font-sans) !important;
    font-size: 12.5px !important;
    font-weight: var(--sn-weight-normal) !important;
    line-height: 1.35 !important;
    cursor: pointer !important;
}

/* Les liens CGUV / vie privée arrivent encadrés de pointillés rouges : même
   traitement que tous les liens du site. */
#zt-opf-form .ptprelinker-cgu-link,
#zt-opf-form a {
    color: rgb(var(--sn-accent)) !important;
    text-decoration: underline !important;
    border: 0 !important;
    outline: 0 !important;
}

#zt-opf-form a:hover {
    color: rgb(var(--sn-accent-hover)) !important;
}

/* Message d'erreur du widget (champ manquant, e-mail déjà pris) : rouge
   d'état du site, pas celui de la marque, qu'on réserve aux actions. */
#zt-opf-form .error-register {
    margin-bottom: 8px !important;
    color: rgb(var(--sn-danger)) !important;
    font-size: 13px !important;
}

/* Anneau de focus unique du site : le parcours au clavier ne doit pas
   changer d'aspect en entrant dans le formulaire. Les champs sont nommés
   séparément, sans quoi le `box-shadow: none !important` de la règle des
   champs, plus spécifique, effacerait l'anneau sur eux seuls — c'est-à-dire
   là où il sert. */
#zt-opf-form :focus-visible,
#zt-opf-form .ptprelinker-input:focus-visible,
#zt-opf-form input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="hidden"]):focus-visible,
#zt-opf-form select:focus-visible {
    box-shadow: var(--sn-focus-ring) !important;
}

/* Sur téléphone, la modale entière doit tenir sans défilement jusqu'au
   bouton : on resserre, comme le fait fan.css sur les pages fan. */
@media (max-width: 480px) {
    #zt-opf-form .ptprelinker-input,
    #zt-opf-form .ptprelinker-select,
    #zt-opf-form input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="hidden"]),
    #zt-opf-form select {
        min-height: 42px !important;
        padding: 9px 13px !important;
    }

    #zt-opf-form .ptprelinker-input-group {
        margin-bottom: 8px !important;
    }

    #zt-opf-form .ptprelinker-button,
    #zt-opf-form input[type="submit"] {
        min-height: 46px !important;
        padding: 11px 16px !important;
    }
}

/* ------------------------------------------------------------- patienteur --- */

/* Affiché dans le conteneur que le widget remplace : il vit donc exactement
   le temps du chargement, sans script pour le retirer. Hauteur voisine de
   celle du formulaire attendu, pour que la modale ne saute pas à l'arrivée
   des champs. */
#zt-opf-form .zt-trial-wait {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    min-height: 210px;
    padding: 16px;
    text-align: center;
}

#zt-opf-form .zt-trial-wait__spinner {
    width: 28px;
    height: 28px;
    border: 2.5px solid rgb(var(--sn-gray-400));
    /* Un seul segment coloré : c'est lui qui rend la rotation lisible. */
    border-top-color: rgb(var(--sn-accent));
    border-radius: var(--sn-radius-full);
    animation: zt-trial-spin 700ms linear infinite;
}

@keyframes zt-trial-spin {
    to { transform: rotate(360deg); }
}

#zt-opf-form .zt-trial-wait__label {
    color: rgb(var(--sn-gray-800));
    font-size: 13px;
}

/* Le message d'échec ne prend la place qu'une fois le délai écoulé. */
#zt-opf-form .zt-trial-wait__failed {
    display: none;
    max-width: 320px;
    color: rgb(var(--sn-gray-900));
    font-size: 13px;
    line-height: 1.45;
}

#zt-opf-form .zt-trial-wait--failed .zt-trial-wait__spinner,
#zt-opf-form .zt-trial-wait--failed .zt-trial-wait__label {
    display: none;
}

#zt-opf-form .zt-trial-wait--failed .zt-trial-wait__failed {
    display: block;
}

/* La règle globale de `prefers-reduced-motion` (app.css) ramène toutes les
   animations à 0,01 ms : le disque s'immobiliserait, sans rien indiquer.
   On le remplace par un battement d'opacité, perceptible sans rotation. */
@media (prefers-reduced-motion: reduce) {
    #zt-opf-form .zt-trial-wait__spinner {
        animation: zt-trial-pulse 1.6s ease-in-out infinite !important;
        animation-duration: 1.6s !important;
        border-top-color: rgb(var(--sn-accent));
    }

    @keyframes zt-trial-pulse {
        0%, 100% { opacity: 0.35; }
        50%      { opacity: 1; }
    }
}
