/* GÉNÉRÉ depuis _commun/assets/css/base.css — ne pas éditer ici, éditer la source puis relancer tools/build.php */
/* =====================================================================
   base.css — socle commun aux vitrines MentalSense
   ---------------------------------------------------------------------
   Chargé AVANT forme.css. Il ne porte que ce qui ne dépend d'aucune
   forme : polices, remise à zéro, corps de page, révélation au scroll,
   panneau du menu mobile, mécanique des formulaires, réglage de la
   taille du texte. Tout ce qui se voit — en-tête, héros, boutons,
   cartes, accordéons, pied de page, pages de texte — est dans forme.css.

   Ce fichier ne DÉFINIT aucune couleur. Comme forme.css, il ne fait que
   CONSOMMER le contrat de tokens ci-dessous, que chaque site pose dans
   son site.css à partir de la palette de son app :

     Encre        --ink --ink-2 --on-ink --on-ink-mid --on-ink-dim
     Accent       --accent --accent-lift --accent-deep --accent-soft --accent-line
     Contrepoint  --alt --alt-deep --alt-lift --on-alt --on-alt-mid --alt-line
     Surfaces     --ground --paper --parchment --sunken
     Texte        --text --text-mid --text-muted --line --line-strong
     Chrome       --chrome --chrome-line --chrome-blur
     États        --danger --danger-soft --ok
     Formes       --radius --radius-sm --radius-lg
     Élévation    --elev-1 --elev-2 --elev-3
     Typo         --font-sans --font-serif
     Hero         --hero-texture

   Conséquence : un hex écrit ici serait un bug d'identité. Il n'y en a
   aucun, à l'exception du noir pur du voile.
   ===================================================================== */

/* ── Polices ────────────────────────────────────────────────────────── */
/* Figtree en fabrique VARIABLE : 63 Ko couvrent les graisses 100 à 900,
   contre 18 Ko pour la seule Light. Les 45 Ko de plus achètent un vrai
   gras — sans quoi <strong> ne serait qu'une graisse synthétique, ou
   devrait se replier sur un artifice de couleur. */
@font-face {
    font-family: 'Figtree';
    src: url('../fonts/figtree.ttf') format('truetype-variations');
    font-weight: 100 900; font-style: normal; font-display: swap;
}
@font-face {
    font-family: 'RL Limo';
    src: url('../fonts/RLLimoTRIAL-Regular.woff2') format('woff2'),
         url('../fonts/RLLimoTRIAL-Regular.woff')  format('woff');
    font-weight: 400; font-style: normal; font-display: swap;
}

/* ── Reset ──────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
img, picture, video, svg { max-width: 100%; display: block; }
input, button, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
a { color: inherit; }
ul, ol { list-style: none; }
/* L'emphase force le contraste : dans un paragraphe en --text-mid, c'est
   le passage à --text qui la rend visible autant que la graisse (posée
   par forme.css). Les deux balises sont traitées ensemble — ne couvrir
   que <strong> laisserait les <b> à la couleur du paragraphe. */
strong, b { color: var(--text); }

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

/* Graisse, taille, interligne et fond du corps : forme.css. */
body {
    font-family: var(--font-sans);
    color: var(--text);
    overflow-x: hidden;
    -webkit-font-smoothing: antialiased;
}

/* ── Helpers ────────────────────────────────────────────────────────── */
.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── Barre de progression de lecture ────────────────────────────────── */
#progress {
    position: fixed; inset: 0 auto auto 0; height: 2px; width: 0;
    background: linear-gradient(90deg, var(--accent-deep), var(--accent-lift));
    z-index: 200; transition: width .1s linear;
}

/* ── Menu mobile ────────────────────────────────────────────────────── */
/* Le panneau et son voile. Le bouton (.burger) vit dans l'en-tête en
   pilule : il est dans forme.css, qui règle aussi les espacements du
   panneau. */
.mnav {
    position: fixed; inset: 0 0 0 auto; width: min(340px, 84vw); z-index: 190;
    display: flex; flex-direction: column;
    background: var(--ink); color: var(--on-ink);
    transform: translateX(100%); transition: transform .42s cubic-bezier(.22,1,.36,1);
}
.mnav.open { transform: none; }
.mnav a {
    font-family: var(--font-serif);
    text-decoration: none; border-bottom: 1px solid var(--on-ink-dim);
}
.veil {
    position: fixed; inset: 0; z-index: 180; background: rgba(0,0,0,.5);
    opacity: 0; visibility: hidden; transition: opacity .35s, visibility .35s;
}
.veil.open { opacity: 1; visibility: visible; }

/* ── Révélation au scroll ───────────────────────────────────────────── */
/* Le masquage est conditionné à la classe `js`, posée très tôt par
   fontscale.js : sans elle, aucun masquage. Un script qui ne s'exécute
   pas ne doit jamais vider la page de son contenu. */
.js .reveal { opacity: 0; transform: translateY(34px);
          transition: opacity .8s cubic-bezier(.22,1,.36,1), transform .8s cubic-bezier(.22,1,.36,1); }
.js .reveal.seen { opacity: 1; transform: none; }
.d1 { transition-delay: .08s; } .d2 { transition-delay: .16s; }
.d3 { transition-delay: .24s; } .d4 { transition-delay: .32s; }
.d5 { transition-delay: .40s; } .d6 { transition-delay: .48s; }

/* ── Formulaire ─────────────────────────────────────────────────────── */
/* La mécanique : grilles, champs, états. Hauteurs, bords et espacements
   sont dans forme.css. */
.form { display: grid; }
.form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); }
.field { display: flex; flex-direction: column; gap: .45rem; }
.field .req { color: var(--accent-deep); }
.input {
    width: 100%;
    background: var(--paper); color: var(--text);
    transition: border-color .25s, box-shadow .25s;
}
.input:focus-visible { outline: none; border-color: var(--accent); }
.input.bad { border-color: var(--danger); background: var(--danger-soft); }
textarea.input { resize: vertical; }
.field-err { font-size: .8rem; color: var(--danger); min-height: 1em; }

.consent { display: flex; gap: .7rem; align-items: flex-start; color: var(--text-mid); }
.consent input { margin-top: .25rem; accent-color: var(--accent); }

/* Le honeypot doit être invisible pour l'humain sans être `display:none` :
   certains robots ignorent précisément les champs masqués ainsi. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* L'erreur porte sa propre couleur : un message en teinte de marque ne se
   lit pas comme une erreur, quelle que soit la palette du site. */
.form-msg { font-size: .9rem; min-height: 1.4em; color: var(--danger); }
.form-msg.ok { color: var(--ok); }
.btn.loading { opacity: .6; pointer-events: none; }
.btn.loading::after {
    content: ''; width: .85em; height: .85em; border-radius: 50%;
    border: 2px solid currentColor; border-top-color: transparent;
    animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ── Réglage typographique (fontscale) ──────────────────────────────── */
.fs {
    display: flex; align-items: center; gap: .25rem;
    padding: .2rem .35rem; border-radius: 100vw; border: 1px solid var(--line-strong);
}
.fs button {
    width: 1.7rem; height: 1.7rem; border-radius: 50%; line-height: 1;
    font-size: .78rem; color: inherit; transition: background-color .2s;
}
.fs button:hover { background: var(--accent-soft); }
.fs button[aria-pressed="true"] { background: var(--accent); color: var(--ink); }

/* ── Mouvement réduit ───────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: .001ms !important; animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
    .reveal { opacity: 1; transform: none; }
}
