/* ─── WTS — Animation Tokens (parité FWC) ─── */
/* Importer ce fichier en tête de app.css via @import './_anim-tokens.css'; */

:root {
    /* ── Easings ── */
    --ease-out-soft: cubic-bezier(0.22, 1, 0.36, 1);
    --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
    --ease-in-out-soft: cubic-bezier(0.65, 0, 0.35, 1);

    /* ── Durées ── */
    --anim-fast: 200ms;
    --anim-base: 650ms;
    --anim-slow: 950ms;
    --anim-stagger: 110ms;
}

/* ── Classe de base reveal ── */
.reveal {
    opacity: 0;
    transform: translateY(16px);
    transition:
        opacity var(--anim-base) var(--ease-out-soft) var(--reveal-delay, 0ms),
        transform var(--anim-base) var(--ease-out-soft) var(--reveal-delay, 0ms);
    will-change: opacity, transform;
}

.reveal.is-visible {
    opacity: 1;
    transform: none;
}

.reveal--scale {
    transform: scale(0.94);
}

.reveal--blur {
    filter: blur(6px);
    transition:
        opacity var(--anim-base) var(--ease-out-soft),
        transform var(--anim-base) var(--ease-out-soft),
        filter var(--anim-base) var(--ease-out-soft);
}

.reveal.is-visible.reveal--blur {
    filter: none;
}

/* ── Stagger via custom property --stagger en style inline ── */
.reveal[style*='--stagger'] {
    transition-delay: var(--stagger, 0ms);
}

/* ── Variantes directionnelles — amplitudes plus généreuses ── */
.reveal--up {
    transform: translateY(36px);
}
.reveal--down {
    transform: translateY(-24px);
}
.reveal--left {
    transform: translateX(-36px);
}
.reveal--right {
    transform: translateX(36px);
}

/* ── Cleanup will-change après la transition ── */
.reveal.is-revealed {
    will-change: auto;
}

/* ── Text-split animation ── */
.split-word {
    display: inline-block;
    opacity: 0;
    transform: translateY(0.5em);
    transition:
        opacity 750ms var(--ease-out-soft),
        transform 750ms var(--ease-out-soft);
    transition-delay: var(--stagger, 0ms);
}

[data-controller~='text-split'].is-split-ready .split-word,
[data-controller~='text-split'].is-visible .split-word {
    opacity: 1;
    transform: none;
}

/* ── Fallback no-JS / FOUC ── */
html:not(.js-ready) .reveal,
html:not(.js-ready) .split-word {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    transition: none !important;
}

/* ── Reduced motion : désactive tout ── */
@media (prefers-reduced-motion: reduce) {
    .reveal,
    .reveal--blur {
        opacity: 1 !important;
        transform: none !important;
        filter: none !important;
        transition: none !important;
    }

    .split-word {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }
}

/* assets/styles/_variables.css */
/* Tokens WTS en CSS Custom Properties — source de vérité unique des couleurs,
   espacements, rayons et de l'échelle typographique. */
/* Règle charte : l'orange (--wts-color-orange) est réservé aux titres/accents,
   jamais au corps de texte. Les nuances (opacités) servent à l'interface
   (bordures, fonds, états hover/disabled) ; la couleur pleine porte l'identité. */

:root {
    /* ── Couleurs de marque ── */
    --wts-color-orange: #ff8146;
    --wts-color-black: #000000;
    --wts-color-white: #ffffff;
    --wts-color-silver: #c6ccce;

    /* ── Déclinaisons d'opacité — orange (rgb 255, 129, 70) ── */
    --wts-color-orange-80: rgba(255, 129, 70, 0.8);
    --wts-color-orange-60: rgba(255, 129, 70, 0.6);
    --wts-color-orange-40: rgba(255, 129, 70, 0.4);
    --wts-color-orange-20: rgba(255, 129, 70, 0.2);

    /* ── Déclinaisons d'opacité — silver (rgb 198, 204, 206) ── */
    --wts-color-silver-80: rgba(198, 204, 206, 0.8);
    --wts-color-silver-60: rgba(198, 204, 206, 0.6);
    --wts-color-silver-40: rgba(198, 204, 206, 0.4);
    --wts-color-silver-20: rgba(198, 204, 206, 0.2);

    /* ── Déclinaisons d'opacité — noir ── */
    --wts-color-black-80: rgba(0, 0, 0, 0.8);
    --wts-color-black-60: rgba(0, 0, 0, 0.6);
    --wts-color-black-40: rgba(0, 0, 0, 0.4);
    --wts-color-black-20: rgba(0, 0, 0, 0.2);

    /* ── Déclinaisons d'opacité — blanc ── */
    --wts-color-white-80: rgba(255, 255, 255, 0.8);
    --wts-color-white-60: rgba(255, 255, 255, 0.6);
    --wts-color-white-40: rgba(255, 255, 255, 0.4);
    --wts-color-white-20: rgba(255, 255, 255, 0.2);

    /* ── Couleurs sémantiques — feedback (story 1-3) ── */
    --wts-color-success: #22c55e;
    --wts-color-error: #ef4444;

    /* ── Teinte claire de l'orange — bordure du bouton primaire (maquette Figma) ── */
    --wts-color-orange-light: #fd9f72;

    /* ── Orange brûlé — contour de la forme flottante de la FAQ sur fond noir (cf. _faq.css).
       Volontairement sourd : le trait doit exister sans venir concurrencer l'aplat orange
       qu'il entoure. Choisi par l'utilisateur. ── */
    --wts-color-orange-burnt: #413028;

    /* ── Polices ── */
    --wts-font-display: 'Frick', 'Arial Black', sans-serif;
    --wts-font-sans: 'Outfit', system-ui, -apple-system, sans-serif;

    /* ── Échelle typographique (rem, base 16px) ── */
    --wts-font-size-xs: 0.75rem;
    --wts-font-size-sm: 0.875rem;
    --wts-font-size-base: 1rem;
    --wts-font-size-lg: 1.25rem;
    --wts-font-size-xl: 1.5rem;
    --wts-font-size-2xl: 2rem;
    --wts-font-size-3xl: 2.5rem;
    --wts-font-size-4xl: 3.5rem;

    /* ── Espacements (échelle base 4px) ── */
    --wts-space-1: 0.25rem;
    --wts-space-2: 0.5rem;
    --wts-space-3: 0.75rem;
    --wts-space-4: 1rem;
    --wts-space-6: 1.5rem;
    --wts-space-8: 2rem;
    --wts-space-12: 3rem;
    --wts-space-16: 4rem;

    /* ── Rayons ── */
    --wts-radius-sm: 4px;
    --wts-radius-md: 8px;
    --wts-radius-lg: 16px;
    --wts-radius-full: 9999px;

    /* ── Bandeau réservé au header fixe ──
       Ses deux marges verticales plus la hauteur de la capsule (59px). C'est la place que
       `#main-content` réserve en haut de page pour que le contenu ne passe pas sous le
       header (cf. app.css) — et donc ce que doit ANNULER une section qui, elle, veut
       occuper toute la fenêtre et laisser le header flotter par-dessus (cf. .home-hero).
       Les deux endroits doivent forcément lire la même valeur : d'où le token. */
    --wts-header-band: calc(2 * var(--wts-space-6) + 59px);
}

/* assets/styles/_components.css */
/* Styles des atoms & molecules (story 1-3). Toutes les couleurs viennent des tokens
   --wts-* (assets/styles/_variables.css), sauf card-project qui ne consomme que
   --project-* (variables injectées par le thème du projet, cf. DCT §3.3). */

/* ── Icon ── */
.icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.icon svg {
    width: 100%;
    height: 100%;
}

.icon--sm {
    width: 1rem;
    height: 1rem;
}

.icon--md {
    width: 1.25rem;
    height: 1.25rem;
}

.icon--lg {
    width: 1.5rem;
    height: 1.5rem;
}

/* ── Button — pill par défaut (charte WTS, cf. maquette Figma) ── */
.btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--wts-space-2);
    /* 2.75rem = les 44px du touch-target minimum tant que le rem vaut 16px, mais la hauteur
       suit ensuite l'échelle fluide (cf. app.css) : en px, le bouton restait figé pendant
       que son libellé grandissait, et le texte finissait à l'étroit dans la pilule. La
       valeur ne peut pas passer SOUS 44px, le rem ne descendant jamais en dessous de 16px. */
    min-height: 2.75rem;
    padding: var(--wts-space-2) var(--wts-space-6);
    border: 1px solid transparent;
    border-radius: var(--wts-radius-full);
    background: none;
    font-family: var(--wts-font-sans);
    font-size: var(--wts-font-size-base);
    font-weight: 400;
    line-height: 1;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--anim-fast) var(--ease-out-soft), color var(--anim-fast) var(--ease-out-soft), border-color var(--anim-fast) var(--ease-out-soft);
}

/* Anneau intérieur (pas une bordure sur le bord) : pseudo-élément inset, cf. maquette Figma. */
.btn--primary {
    background-color: var(--wts-color-orange);
    color: var(--wts-color-white);
}

.btn--primary::after {
    content: '';
    position: absolute;
    inset: var(--wts-space-2);
    border: 1px solid var(--wts-color-orange-light);
    border-radius: var(--wts-radius-full);
    pointer-events: none;
}

.btn--primary:hover:not(:disabled) {
    animation: wts-pulse 1.6s ease-out infinite;
}

/* Anneau qui grandit en continu tout en s'estompant (0 → 100 %, sans palier
   intermédiaire) : la boucle redémarre sans à-coup puisque l'anneau est déjà
   invisible (spread au max, couleur transparente) au moment du reset.
   Pas de transform ici : un scale() reviendrait brutalement à sa taille de
   départ à chaque boucle (contrairement à l'ombre, rien ne l'estompe). */
@keyframes wts-pulse {
    0% {
        box-shadow: 0 0 0 0 var(--wts-color-orange-40);
    }
    100% {
        box-shadow: 0 0 0 14px transparent;
    }
}

@media (prefers-reduced-motion: reduce) {
    .btn--primary:hover:not(:disabled) {
        animation: none;
    }
}

.btn--secondary {
    background-color: var(--wts-color-white-20);
    color: var(--wts-color-white);
}

.btn--secondary:hover:not(:disabled) {
    background-color: var(--wts-color-white-40);
}

.btn--outline {
    border-color: var(--wts-color-silver-40);
    color: var(--wts-color-white);
}

.btn--outline:hover:not(:disabled) {
    border-color: var(--wts-color-orange);
    color: var(--wts-color-orange);
}

.btn:disabled,
.btn[aria-disabled='true'] {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

/* ── Badge ── */
.badge {
    display: inline-flex;
    align-items: center;
    padding: var(--wts-space-1) var(--wts-space-3);
    border-radius: var(--wts-radius-full);
    font-size: var(--wts-font-size-xs);
    font-weight: 600;
}

.badge--accent {
    background-color: var(--wts-color-orange-20);
    color: var(--wts-color-orange);
}

.badge--neutral {
    background-color: var(--wts-color-silver-20);
    color: var(--wts-color-silver);
}

.badge--success {
    background-color: color-mix(in srgb, var(--wts-color-success) 20%, transparent);
    color: var(--wts-color-success);
}

.badge--error {
    background-color: color-mix(in srgb, var(--wts-color-error) 20%, transparent);
    color: var(--wts-color-error);
}

/* ── Tag ── */
.tag {
    display: inline-flex;
    align-items: center;
    padding: var(--wts-space-1) var(--wts-space-2);
    border: 1px solid var(--wts-color-silver-40);
    border-radius: var(--wts-radius-sm);
    color: var(--wts-color-silver);
    font-size: var(--wts-font-size-xs);
}

/* ── Champs de formulaire (input / textarea) — fill semi-transparent + backdrop-filter.
   NB : la capsule de nav portait le même duo, mais elle est repassée en aplat opaque
   (elle traverse des fonds de couleurs différentes au scroll, cf. app.css) ; les champs,
   eux, vivent sur un fond maîtrisé et gardent l'effet verre.
   Anneau de focus repris du bouton primaire (anneau intérieur en pseudo-élément,
   cf. .btn--primary), décliné en orange (focus) ou rouge (erreur). */
.field-control {
    display: block;
    width: 100%;
    min-height: 2.75rem;
    padding: var(--wts-space-3) var(--wts-space-4);
    border: 1px solid var(--wts-color-silver-40);
    border-radius: var(--wts-radius-md);
    background-color: color-mix(in srgb, var(--wts-color-white) 8%, transparent);
    backdrop-filter: blur(14px) saturate(1.6);
    -webkit-backdrop-filter: blur(14px) saturate(1.6);
    box-shadow: inset 0 1px 0 var(--wts-color-white-20);
    color: var(--wts-color-white);
    font-family: var(--wts-font-sans);
    font-size: var(--wts-font-size-base);
    transition:
        border-color var(--anim-fast) var(--ease-out-soft),
        background-color var(--anim-fast) var(--ease-out-soft),
        box-shadow var(--anim-fast) var(--ease-out-soft);
}

.field-control::placeholder {
    color: var(--wts-color-silver-60);
}

.field-control--textarea {
    resize: vertical;
    line-height: 1.5;
}

.field-control:hover:not(:disabled):not(:focus) {
    border-color: var(--wts-color-silver-60);
}

.field-control:focus {
    outline: none;
    border-color: var(--wts-color-orange);
    background-color: color-mix(in srgb, var(--wts-color-white) 12%, transparent);
    box-shadow:
        inset 0 1px 0 var(--wts-color-white-20),
        0 0 0 3px var(--wts-color-orange-20);
}

.field-control.is-error {
    border-color: var(--wts-color-error);
}

.field-control.is-error:focus {
    box-shadow:
        inset 0 1px 0 var(--wts-color-white-20),
        0 0 0 3px color-mix(in srgb, var(--wts-color-error) 25%, transparent);
}

.field-control:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

@media (prefers-reduced-motion: reduce) {
    .field-control {
        transition: none;
    }
}

/* ── Loader ── */
.loader {
    display: inline-flex;
    align-items: center;
    gap: var(--wts-space-2);
    font-size: var(--wts-font-size-base);
}

.loader--loading .icon {
    animation: wts-spin 900ms linear infinite;
}

.loader--success .icon {
    color: var(--wts-color-success);
}

.loader--error .icon {
    color: var(--wts-color-error);
}

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

@media (prefers-reduced-motion: reduce) {
    .loader--loading .icon {
        animation: none;
    }
}

/* ── Scroll to top ── */
.scroll-to-top {
    position: fixed;
    right: var(--wts-space-6);
    bottom: var(--wts-space-6);
    z-index: 40;
    display: none;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border: none;
    border-radius: var(--wts-radius-full);
    background-color: var(--wts-color-orange);
    color: var(--wts-color-black);
    opacity: 0;
    cursor: pointer;
    transition: opacity var(--anim-fast) var(--ease-out-soft);
}

.scroll-to-top.is-visible {
    display: flex;
    opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
    .scroll-to-top {
        transition: none;
    }
}

/* ── Form field (molecule) ── */
.form-field {
    display: flex;
    flex-direction: column;
    gap: var(--wts-space-1);
}

.form-field__label {
    font-size: var(--wts-font-size-sm);
    font-weight: 600;
}

.form-field__required {
    color: var(--wts-color-orange);
    margin-left: var(--wts-space-1);
}

.form-field__error {
    padding: var(--wts-space-2) var(--wts-space-3);
    border-left: 2px solid var(--wts-color-error);
    border-radius: var(--wts-radius-sm);
    background-color: color-mix(in srgb, var(--wts-color-error) 12%, transparent);
    color: var(--wts-color-error);
    font-size: var(--wts-font-size-sm);
}

.form-field__error ul {
    margin: 0;
    padding-left: var(--wts-space-4);
}

.form-field__help {
    color: var(--wts-color-silver);
    font-size: var(--wts-font-size-xs);
    margin: 0;
}

/* ── Nav item (molecule) ── */
/* Figma utilise Outfit Light (300) pour l'état inactif ; seuls Regular (400) et SemiBold (600)
   sont self-hosted depuis la story 1-2 — repli sur Regular en attendant (cf. Dev Notes 1-3). */
.nav-item {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: var(--wts-space-1) var(--wts-space-2);
    color: var(--wts-color-silver-60);
    text-decoration: none;
    font-weight: 400;
    white-space: nowrap;
    transition: color var(--anim-fast) var(--ease-out-soft);
}

.nav-item:hover {
    color: var(--wts-color-white);
}

.nav-item.is-current {
    color: var(--wts-color-orange);
    font-weight: 600;
}

/* ── Nav item group — capsule pill réutilisable autour de plusieurs nav-item ──
   Pur CSS (border + border-radius complet) : s'adapte automatiquement à l'ajout d'un lien,
   contrairement à l'illustration "Ellipse 3" de la maquette (non utilisable telle quelle). */
.nav-item-group {
    display: inline-flex;
    align-items: center;
    gap: var(--wts-space-1);
    border: 1px solid var(--wts-color-silver-20);
    border-radius: var(--wts-radius-full);
    padding: var(--wts-space-1) var(--wts-space-3);
}

.nav-item-group .nav-item + .nav-item {
    border-left: 1px solid var(--wts-color-silver-20);
    padding-left: var(--wts-space-3);
    margin-left: var(--wts-space-2);
}

/* ── FAQ accordion item (molecule) — carte claire flottante, conforme à la maquette Figma ── */
.faq-item {
    background-color: var(--wts-color-white);
    color: var(--wts-color-black);
    border-radius: var(--wts-radius-sm);
    box-shadow: 0 24px 32px -14px rgba(149, 149, 149, 0.25);
}

.faq-item + .faq-item {
    margin-top: var(--wts-space-4);
}

.faq-item__heading {
    margin: 0;
}

.faq-item__trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--wts-space-4);
    width: 100%;
    min-height: 2.75rem;
    padding: var(--wts-space-6);
    border: none;
    background: none;
    color: inherit;
    font-family: var(--wts-font-sans);
    font-size: var(--wts-font-size-lg);
    font-weight: 600;
    text-align: left;
    cursor: pointer;
}

.faq-item__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: var(--wts-radius-full);
    background-color: var(--wts-color-black);
    color: var(--wts-color-white);
    transition: transform var(--anim-fast) var(--ease-out-soft);
}

.faq-item__trigger[aria-expanded='true'] .faq-item__icon {
    transform: rotate(45deg);
}

.faq-item__panel {
    display: grid;
    grid-template-rows: 1fr;
    opacity: 1;
    transition:
        grid-template-rows var(--anim-base) var(--ease-out-soft),
        opacity var(--anim-fast) var(--ease-out-soft);
}

.faq-item__panel--collapsed {
    grid-template-rows: 0fr;
    opacity: 0;
}

.faq-item__panel-inner {
    overflow: hidden;
    min-height: 0;
    padding: 0 var(--wts-space-6) var(--wts-space-6);
}

.faq-item__panel p {
    margin: 0;
    color: var(--wts-color-black-80);
}

@media (prefers-reduced-motion: reduce) {
    .faq-item__icon,
    .faq-item__panel {
        transition: none;
    }
}

/* ── Card project (molecule) — thème data-driven, --project-* exclusivement ──
   Ligne d'accordéon "index projets" : repliée par défaut (titre + icône +), se déploie au
   survol/focus — image en pleine hauteur, résumé, CTA, icône + -> − (cf. header.html.twig
   pour le détail des nodes Figma). Les séparateurs utilisent color-mix() sur
   --project-secondary pour rester 100% thémés (ThemeExtension ne définit pas de variable
   de bordure dédiée, cf. DCT §3.3).

   `.card-project--open` (prop `is_open`) force l'état déployé, sans JS : l'index projets
   s'en sert pour ouvrir sa première ligne par défaut. Il accompagne donc :hover et
   :focus-within partout où l'état déployé est décrit. */
.card-project {
    position: relative;
    display: flex;
    align-items: flex-end;
    gap: var(--wts-space-6);
    padding: var(--wts-space-6) 0;
    border-top: 1px solid color-mix(in srgb, var(--project-secondary) 50%, transparent);
    border-bottom: 1px solid color-mix(in srgb, var(--project-secondary) 50%, transparent);
    color: var(--project-secondary);
}

/* Repliée : titre/icône collés au bord bas (cf. maquette Figma, fermé) ; déployée : titre
   aligné en haut avec le reste du contenu qui se déploie (cf. maquette Figma, ouvert) —
   deux comportements différents selon l'état, pas juste une histoire d'espacement. */
.card-project:hover,
.card-project:focus-within,
.card-project--open {
    align-items: flex-start;
}

/* La case s'ÉTIRE sur la hauteur de la ligne (`align-self: stretch`) et le visuel la remplit
   en `contain`. C'est ce qui fait grandir le logo au déploiement : la ligne ouverte est bien
   plus haute que la ligne repliée, le logo suit donc cette hauteur au lieu de rester la
   vignette qu'il était. Un logo carré ou portrait va jusqu'à toucher le haut et le bas ; un
   logo très large, lui, reste borné par la largeur de la case — d'où l'élargissement de
   celle-ci au déploiement (cf. plus bas), qui le fait grossir malgré tout.

   `stretch` dans les DEUX états, et pas seulement à l'ouverture : la hauteur de la ligne
   repliée est justement dictée par la hauteur naturelle du logo, la case étirée y vaut donc
   exactement cette hauteur et le rendu replié est inchangé. En n'appliquant `stretch` qu'à
   l'ouverture, le logo aurait sauté d'un état à l'autre au lieu de suivre la transition.

   Le garde-fou de hauteur est passé sur la CASE : c'est elle qui est étirée, un `max-height`
   resté sur l'image ne l'aurait plus bornée. */
.card-project__visual {
    flex-shrink: 0;
    align-self: stretch;
    width: 13.75rem;
    max-height: 23.75rem;
    overflow: hidden;
    border-radius: var(--wts-radius-sm);
    transition: width var(--anim-base) var(--ease-out-soft);
}

/* Aucun fond : les visuels sont des logos, souvent détourés sur transparent. L'aplat teinté
   qui remplissait la case se voyait alors tout autour d'eux comme une boîte grise rapportée
   (retour utilisateur). Il ne reste que sur la case VIDE ci-dessous, seul cas où il a une
   raison d'être — il n'y a rien d'autre à montrer. */
.card-project__visual-media {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* Projet sans aucun asset : l'aplat n'a pas de hauteur naturelle, on lui donne au minimum
   celle que la maquette donnait à la case repliée, et il remplit la case au déploiement. */
.card-project__visual-media--empty {
    min-height: 8.125rem;
    background-color: color-mix(in srgb, var(--project-secondary) 20%, transparent);
}

.card-project__body {
    display: flex;
    flex-direction: column;
    flex: 1;
    gap: var(--wts-space-4);
    min-width: 0;
}

.card-project__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--wts-space-4);
}

.card-project__title {
    font-family: var(--project-font-heading);
    font-size: var(--wts-font-size-3xl);
    color: var(--project-primary);
    margin: 0;
}

.card-project__title-sub {
    display: block;
    font-size: var(--wts-font-size-sm);
    font-weight: 400;
    letter-spacing: 0;
    opacity: 0.6;
}

/* Le titre est le seul lien de la ligne, mais la ligne entière est cliquable : le ::after
   recouvre toute la carte. Rien d'interactif ne vit dessous (le CTA est un repère visuel,
   pas un lien), donc aucune cible n'est masquée — et le survol de n'importe quel point de la
   carte est aussi un survol du lien, ce qui garde le comportement du curseur cohérent. */
.card-project__link {
    color: inherit;
    text-decoration: none;
}

.card-project__link::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: var(--wts-radius-sm);
}

/* Focus clavier : l'anneau se dessine sur toute la ligne, pas seulement autour du mot du
   titre — la zone annoncée correspond alors à la zone réellement cliquable. */
.card-project__link:focus-visible {
    outline: none;
}

.card-project__link:focus-visible::after {
    outline: 2px solid var(--project-accent);
    outline-offset: 4px;
}

/* Icône +/− en badge circulaire (même idiome que .faq-item__icon), thémé --project-* :
   la barre verticale du "+" (premher <line> de plus.svg) se réduit à rien au survol/focus,
   ne laissant que la barre horizontale — un vrai "−", pas une rotation en croix. */
.card-project__toggle-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--wts-radius-full);
    border: 1px solid color-mix(in srgb, var(--project-secondary) 50%, transparent);
    color: var(--project-secondary);
}

.card-project__toggle-icon svg line:first-child {
    transition: transform var(--anim-fast) var(--ease-out-soft);
    transform-origin: center;
}

.card-project:hover .card-project__toggle-icon svg line:first-child,
.card-project:focus-within .card-project__toggle-icon svg line:first-child,
.card-project--open .card-project__toggle-icon svg line:first-child {
    transform: scaleY(0);
}

/* Résumé/tags/CTA : cachés par défaut, révélés au survol/focus via le même mécanisme
   grid-template-rows 0fr -> 1fr que .faq-item__panel (cf. _components.css plus haut). */
.card-project__details {
    display: grid;
    grid-template-rows: 0fr;
    opacity: 0;
    transition:
        grid-template-rows var(--anim-base) var(--ease-out-soft),
        opacity var(--anim-fast) var(--ease-out-soft);
}

.card-project:hover .card-project__details,
.card-project:focus-within .card-project__details,
.card-project--open .card-project__details {
    grid-template-rows: 1fr;
    opacity: 1;
}

/* Deux moitiés égales : le texte à gauche, les chiffres clés à droite. Base 0 et même
   facteur de croissance des deux côtés — c'est ce qui fait que les chiffres OCCUPENT
   l'espace libre au lieu d'être repoussés contre le bord par un `space-between`, qui
   laissait un grand vide entre le résumé (plafonné à 42rem) et une pile étroite collée à
   droite. Sans chiffres, le texte reprend simplement toute la largeur.
   `overflow: hidden` est ce qui permet au parent en grid 0fr -> 1fr de l'écraser : c'est
   donc bien ICI que les chiffres doivent vivre, sinon ils resteraient affichés ligne
   repliée — alors que toute la demande est qu'ils apparaissent au déploiement. */
.card-project__details-inner {
    display: flex;
    align-items: flex-start;
    gap: var(--wts-space-12);
    overflow: hidden;
}

.card-project__details-main {
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--wts-space-4);
    min-width: 0;
}

/* Bandeau de chiffres, en RANGÉE et non en pile : trois chiffres l'un sous l'autre
   rallongeaient la ligne bien au-delà de son texte. Côte à côte, ils tiennent dans la
   hauteur du résumé et se répartissent sur toute la moitié droite (`1fr` par chiffre).
   `auto-fit` + plancher de 7rem : si un projet en a plus que la place n'en permet, ils
   passent à la ligne au lieu de se comprimer jusqu'à couper un libellé.

   Étiré sur toute la hauteur du bloc déployé (`align-self: stretch`) pour que le filet de
   gauche courre du haut du résumé jusqu'au bas du CTA : c'est lui qui sépare nettement
   « ce que c'est » de « ce que ça donne », les chiffres restant, eux, calés en haut. */
.card-project__stats {
    display: grid;
    flex: 1 1 0;
    align-self: stretch;
    align-content: start;
    grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
    gap: var(--wts-space-6);
    min-width: 0;
    margin: 0;
    padding-left: var(--wts-space-8);
    border-left: 1px solid color-mix(in srgb, var(--project-secondary) 25%, transparent);
}

.card-project__stat {
    display: flex;
    flex-direction: column;
    gap: var(--wts-space-2);
    min-width: 0;
}

/* Le chiffre reprend la police de titre du thème projet : c'est un repère visuel, pas une
   donnée de texte courant, et il doit tenir tête au titre de la ligne. Chiffres tabulaires :
   sans eux, la largeur du nombre saute à chaque incrément pendant le décompte et tout le
   bandeau tremble. */
.card-project__stat-value {
    display: flex;
    align-items: baseline;
    gap: 0.1em;
    font-family: var(--project-font-heading);
    font-size: var(--wts-font-size-3xl);
    line-height: 1;
    font-variant-numeric: tabular-nums;
    color: var(--project-accent);
}

/* L'unité ne fait pas partie du nombre : plus petite, elle se lit comme ce qu'elle est. */
.card-project__stat-suffix {
    font-size: 0.55em;
}

.card-project__stat-label {
    margin: 0;
    font-family: var(--project-font-body);
    font-size: var(--wts-font-size-xs);
    line-height: 1.35;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--project-secondary) 75%, transparent);
}

.card-project__summary {
    font-family: var(--project-font-body);
    font-size: var(--wts-font-size-lg);
    max-width: 42rem;
    margin: 0;
}

.card-project__tags {
    display: flex;
    flex-wrap: wrap;
    gap: var(--wts-space-2);
    list-style: none;
    margin: 0;
    padding: 0;
}

/* Fond légèrement teinté en plus de la bordure : un simple contour 1px se perd trop
   facilement sur fond sombre, ce qui donnait l'impression que le texte "flottait",
   mal aligné avec le reste (retour utilisateur). */
.card-project__cta {
    display: inline-flex;
    align-items: center;
    gap: var(--wts-space-2);
    padding: var(--wts-space-2) var(--wts-space-6);
    border: 1px solid var(--project-accent);
    border-radius: var(--wts-radius-full);
    background-color: color-mix(in srgb, var(--project-accent) 12%, transparent);
    color: var(--project-secondary);
    font-weight: 400;
}

/* Pas d'état de survol propre : le CTA n'est plus un lien (c'est la ligne entière qui l'est),
   et il n'est visible que lorsque la ligne est déjà survolée ou focalisée — un :hover ici
   serait donc soit impossible à déclencher, soit allumé en permanence. */

.card-project__cta-icon {
    display: inline-flex;
    transform: rotate(-45deg);
}

/* Pointeur grossier (tactile) : il n'y a pas de survol, et rien à replier/déplier puisque
   la ligne entière est un lien — un tap navigue. Les lignes sont donc toutes déployées, et
   l'icône +/− disparaît : elle promettait une bascule que le doigt ne pouvait pas obtenir
   (seule la première ligne, ouverte par `is_open`, montrait quoi que ce soit). Le logo, lui,
   reste rogné : c'est un aplat de couleur tant qu'aucun visuel projet n'existe, l'étirer sur
   380px de haut mangerait l'écran à chaque ligne. */
@media (hover: none) {
    .card-project {
        align-items: flex-start;
    }

    .card-project__details {
        grid-template-rows: 1fr;
        opacity: 1;
    }

    .card-project__toggle-icon {
        display: none;
    }
}

/* Case ÉLARGIE au déploiement, en plus de son étirement en hauteur. Sans elle, un logo large
   (la majorité : ce sont des logos posés en bandeau) restait borné par les 13,75rem de la
   case repliée et ne grossissait pas d'un pixel, alors que la ligne, elle, avait triplé de
   hauteur. Avec elle, il grandit dans les deux sens.

   Sous 769px, la case passe en pleine largeur et la carte s'empile en colonne (cf. plus
   bas) : l'élargir n'aurait aucun sens, et sa spécificité plus forte l'emporterait sur la
   règle mobile. D'où le `min-width` ici plutôt qu'une surcharge là-bas. */
@media (min-width: 769px) {
    .card-project:hover .card-project__visual,
    .card-project:focus-within .card-project__visual,
    .card-project--open .card-project__visual {
        /* Un cran au-dessus des 13,75rem de la ligne repliée, pas davantage : l'agrandissement
           doit se voir sans que la case prenne le pas sur la ligne — au-delà, le logo pesait
           plus lourd que le titre du projet. L'essentiel du grossissement vient de toute
           façon de la HAUTEUR, la case étant étirée sur celle de la ligne déployée.
           Valeur fixe et non fluide : à cet écart-là, la case reste assez étroite pour ne
           jamais comprimer le résumé, même juste au-dessus du point de bascule mobile. */
        width: 16rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .card-project__toggle-icon svg line:first-child,
    .card-project__details,
    .card-project__visual {
        transition: none;
    }
}

@media (max-width: 768px) {
    .card-project {
        flex-direction: column;
        align-items: flex-start;
    }

    .card-project__visual {
        width: 100%;
    }

    /* Plus de place pour deux moitiés : le bandeau repasse SOUS le texte, sur toute la
       largeur. Le filet de séparation passe donc de sa gauche à son dessus. `flex: none` sur
       les deux blocs : la base 0 du desktop, en colonne et à hauteur libre, les écraserait. */
    .card-project__details-inner {
        flex-direction: column;
        align-items: stretch;
        gap: var(--wts-space-6);
    }

    .card-project__details-main,
    .card-project__stats {
        flex: none;
    }

    .card-project__stats {
        grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr));
        padding-left: 0;
        padding-top: var(--wts-space-6);
        border-left: 0;
        border-top: 1px solid color-mix(in srgb, var(--project-secondary) 25%, transparent);
    }

    .card-project__stat-value {
        font-size: var(--wts-font-size-2xl);
    }
}

/* ── Release item (molecule) — changelog "index releases", conforme à la maquette Figma :
   date à gauche (colonne fixe, police mono système — aucune mono self-hébergée dans le
   projet, cf. DCT §7.2 fonts, un empilement système reste conforme à la CSP font-src 'self'
   puisqu'aucun fichier n'est chargé), badges module/version, titre, résumé, changements à
   puce "+" orange. ── */
.release-item {
    display: flex;
    gap: var(--wts-space-8);
    padding: var(--wts-space-8) 0;
    border-bottom: 1px solid var(--wts-color-silver-20);
}

.release-item__date {
    flex-shrink: 0;
    width: 5.625rem;
    color: var(--wts-color-silver);
    font-family: ui-monospace, 'Cascadia Code', 'Roboto Mono', 'SFMono-Regular', Consolas, monospace;
    font-size: var(--wts-font-size-sm);
    letter-spacing: 0.02em;
    line-height: 1.6;
}

.release-item__body {
    display: flex;
    flex-direction: column;
    gap: var(--wts-space-3);
    min-width: 0;
}

.release-item__meta {
    display: flex;
    align-items: center;
    gap: var(--wts-space-2);
}

.release-item__module,
.release-item__version {
    display: inline-flex;
    align-items: center;
    padding: var(--wts-space-1) var(--wts-space-2);
    border-radius: var(--wts-radius-sm);
    font-family: ui-monospace, 'Cascadia Code', 'Roboto Mono', 'SFMono-Regular', Consolas, monospace;
    font-size: var(--wts-font-size-xs);
    text-transform: uppercase;
}

.release-item__module {
    border: 1px solid var(--wts-color-silver-40);
    color: var(--wts-color-white);
}

.release-item__version {
    background-color: var(--wts-color-orange-20);
    color: var(--wts-color-orange);
}

.release-item__title {
    font-size: var(--wts-font-size-2xl);
    margin: 0;
}

.release-item__title a {
    color: inherit;
    text-decoration: none;
}

.release-item__title a:hover {
    color: var(--wts-color-orange);
}

.release-item__summary {
    color: var(--wts-color-silver);
    margin: 0;
}

.release-item__changes {
    display: flex;
    flex-direction: column;
    gap: var(--wts-space-2);
    list-style: none;
    margin: 0;
    padding: 0;
}

.release-item__changes li {
    display: flex;
    align-items: flex-start;
    gap: var(--wts-space-2);
    color: var(--wts-color-white);
}

.release-item__change-icon {
    display: inline-flex;
    flex-shrink: 0;
    margin-top: 0.2em;
    color: var(--wts-color-orange);
}

/* Épinglage (story 4-2) : décision de modération, elle se voit d'un coup d'œil sans rien
   déplacer dans la colonne. Filet vertical orange + léger retrait, pas de fond coloré — la
   note qui suit doit rester la chose la plus lisible de l'entrée. */
.release-item--pinned {
    border-left: 2px solid var(--wts-color-orange);
    padding-left: var(--wts-space-6);
}

.release-item__pin {
    display: inline-flex;
    align-items: center;
    gap: var(--wts-space-1);
    padding: var(--wts-space-1) var(--wts-space-2);
    border-radius: var(--wts-radius-sm);
    background-color: var(--wts-color-orange-20);
    color: var(--wts-color-orange);
    font-size: var(--wts-font-size-xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* « il y a 5 jours » : l'information de fraîcheur, celle qui prouve que l'application est
   vivante. Elle est repoussée en fin de ligne de méta — la date exacte reste dans la
   colonne de gauche, et dans l'attribut `datetime` pour les machines. */
.release-item__relative {
    margin-left: auto;
    color: var(--wts-color-silver-60);
    font-size: var(--wts-font-size-sm);
    white-space: nowrap;
}

.release-item__notes {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--wts-space-3);
}

/* Repli : hauteur bornée et dégradé de disparition, pour qu'une note coupée se lise comme
   une note coupée et non comme une note finie. `mask-image` plutôt qu'un cache posé
   par-dessus : le fond du site n'est pas uniforme sous cette page (halo radial), un
   rectangle dégradé opaque s'y verrait. */
.release-notes--collapsed {
    max-height: 14rem;
    overflow: hidden;
    mask-image: linear-gradient(to bottom, var(--wts-color-black) 60%, transparent 100%);
    -webkit-mask-image: linear-gradient(to bottom, var(--wts-color-black) 60%, transparent 100%);
}

.release-item__toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--wts-space-2);
    padding: var(--wts-space-2) var(--wts-space-4);
    border: 1px solid var(--wts-color-white-20);
    border-radius: var(--wts-radius-full);
    background: none;
    color: var(--wts-color-silver);
    font-family: inherit;
    font-size: var(--wts-font-size-sm);
    line-height: 1;
    cursor: pointer;
    transition:
        border-color var(--anim-fast) var(--ease-out-soft),
        color var(--anim-fast) var(--ease-out-soft);
}

/* `hidden` doit l'emporter sur le `display` ci-dessus. L'attribut ne tient que par une règle
   de la feuille du navigateur (`[hidden] { display: none }`), que n'importe quelle règle
   d'auteur écrase — sans cette ligne, le bouton s'affichait sur les notes courtes, où il n'a
   rien à replier, et le contrôleur n'a jamais eu l'occasion de l'activer. */
.release-item__toggle[hidden] {
    display: none;
}

.release-item__toggle:hover {
    border-color: var(--wts-color-orange);
    color: var(--wts-color-white);
}

.release-item__toggle:focus-visible {
    outline: 2px solid var(--wts-color-orange);
    outline-offset: 3px;
}

/* Le chevron pointe vers le bas quand il reste quelque chose à déplier, vers le haut quand
   le bouton referme. L'état source est `aria-expanded` — l'attribut que lit l'assistance
   technique —, jamais une classe posée en plus : deux sources d'état finiraient par se
   contredire. */
.release-item__toggle-icon {
    display: inline-flex;
    transition: transform var(--anim-fast) var(--ease-out-soft);
}

.release-item__toggle[aria-expanded='true'] .release-item__toggle-icon {
    transform: rotate(180deg);
}

@media (prefers-reduced-motion: reduce) {
    .release-item__toggle-icon {
        transition: none;
    }
}

/* ── Notes de release rendues depuis le Markdown (story 4-2) ──
   Le HTML de ce bloc vient de l'extérieur (notes GitHub) : il est assaini côté PHP, mais
   sa STRUCTURE reste imprévisible. Les règles ci-dessous couvrent donc tout ce que le
   Markdown GitHub peut produire — titres, listes, tableaux, code, citations —, aucune ne
   suppose un balisage particulier, et aucune ne se contente d'un enfant direct : une note
   peut imbriquer ce qu'elle veut. */
.release-notes {
    max-width: 72ch;
    color: var(--wts-color-silver);
    line-height: 1.7;
}

.release-notes > *:first-child {
    margin-top: 0;
}

.release-notes > *:last-child {
    margin-bottom: 0;
}

/* Les titres d'une note commencent en h4 (décalés côté PHP pour ne pas concurrencer le plan
   de la page) : ils doivent donc se lire comme des intertitres, pas comme des titres de
   section. */
.release-notes :is(h4, h5, h6) {
    margin: var(--wts-space-6) 0 var(--wts-space-2);
    color: var(--wts-color-white);
    font-family: var(--wts-font-sans);
    font-size: var(--wts-font-size-base);
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}

.release-notes p {
    margin: 0 0 var(--wts-space-3);
}

.release-notes :is(ul, ol) {
    margin: 0 0 var(--wts-space-3);
    padding-left: var(--wts-space-6);
}

.release-notes li {
    margin-bottom: var(--wts-space-1);
}

.release-notes li::marker {
    color: var(--wts-color-orange);
}

.release-notes a {
    color: var(--wts-color-white);
    text-decoration: underline;
    text-decoration-color: var(--wts-color-orange);
    text-underline-offset: 0.2em;
}

.release-notes a:hover {
    color: var(--wts-color-orange);
}

.release-notes code {
    padding: 0.1em 0.35em;
    border-radius: var(--wts-radius-sm);
    background-color: var(--wts-color-white-20);
    color: var(--wts-color-white);
    font-family: ui-monospace, 'Cascadia Code', 'Roboto Mono', 'SFMono-Regular', Consolas, monospace;
    font-size: 0.9em;
}

/* Un bloc de code ne se replie pas sur lui-même : il défile dans sa propre boîte plutôt que
   d'élargir la page. Sans cela, une ligne de log un peu longue pousserait toute la mise en
   page vers la droite. */
.release-notes pre {
    margin: 0 0 var(--wts-space-4);
    padding: var(--wts-space-4);
    border: 1px solid var(--wts-color-white-20);
    border-radius: var(--wts-radius-md);
    background-color: var(--wts-color-black-40);
    overflow-x: auto;
}

.release-notes pre code {
    padding: 0;
    background: none;
    font-size: var(--wts-font-size-sm);
    line-height: 1.6;
}

.release-notes blockquote {
    margin: 0 0 var(--wts-space-4);
    padding-left: var(--wts-space-4);
    border-left: 2px solid var(--wts-color-orange-40);
    color: var(--wts-color-silver-80);
    font-style: italic;
}

/* Même raison que pour `pre` : un tableau de notes de version (« ancien champ / nouveau
   champ ») dépasse vite la largeur de la colonne. */
.release-notes table {
    display: block;
    max-width: 100%;
    overflow-x: auto;
    border-collapse: collapse;
    margin: 0 0 var(--wts-space-4);
}

.release-notes :is(th, td) {
    padding: var(--wts-space-2) var(--wts-space-3);
    border: 1px solid var(--wts-color-white-20);
    text-align: left;
}

.release-notes th {
    color: var(--wts-color-white);
    font-weight: 600;
}

.release-notes hr {
    margin: var(--wts-space-6) 0;
    border: none;
    border-top: 1px solid var(--wts-color-white-20);
}

/* Listes de tâches GitHub (`- [x] …`) : la case reste visible et non cliquable, comme sur
   GitHub — elle rend compte d'un état, elle n'en propose pas la modification. */
.release-notes input[type='checkbox'] {
    margin-right: var(--wts-space-2);
    accent-color: var(--wts-color-orange);
}

@media (max-width: 768px) {
    .release-item {
        flex-direction: column;
        gap: var(--wts-space-3);
    }

    .release-item__date {
        width: auto;
    }

    .release-item--pinned {
        padding-left: var(--wts-space-4);
    }

    /* La ligne de méta passe sur deux lignes en petite largeur : la date relative ne doit
       plus être repoussée à droite, elle suivrait le badge de version dans le vide. */
    .release-item__meta {
        flex-wrap: wrap;
    }

    .release-item__relative {
        margin-left: 0;
    }
}

/* ── Pagination (molecule, story 4-2) ── */
.pagination {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--wts-space-2) var(--wts-space-4);
    padding-top: var(--wts-space-8);
}

.pagination__step,
.pagination__page {
    display: inline-flex;
    align-items: center;
    gap: var(--wts-space-2);
    padding: var(--wts-space-2) var(--wts-space-4);
    border: 1px solid var(--wts-color-white-20);
    border-radius: var(--wts-radius-full);
    color: var(--wts-color-silver);
    font-size: var(--wts-font-size-sm);
    line-height: 1;
    text-decoration: none;
    transition:
        border-color var(--anim-fast) var(--ease-out-soft),
        background-color var(--anim-fast) var(--ease-out-soft),
        color var(--anim-fast) var(--ease-out-soft);
}

.pagination__pages {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--wts-space-2);
    list-style: none;
    margin: 0;
    padding: 0;
}

.pagination__page {
    min-width: 2.5rem;
    justify-content: center;
    font-variant-numeric: tabular-nums;
}

.pagination__step:hover,
.pagination__page:hover {
    border-color: var(--wts-color-orange);
    color: var(--wts-color-white);
}

.pagination__step:focus-visible,
.pagination__page:focus-visible {
    outline: 2px solid var(--wts-color-orange);
    outline-offset: 3px;
}

.pagination__page.is-current {
    border-color: var(--wts-color-orange);
    background-color: var(--wts-color-orange-20);
    color: var(--wts-color-orange);
}

/* Extrémités de la barre : le contrôle reste en place pour que les numéros ne bougent pas
   d'une page à l'autre, mais il est visiblement hors service. */
.pagination__step--disabled {
    opacity: 0.35;
}

.pagination__status {
    width: 100%;
    margin: 0;
    text-align: center;
    color: var(--wts-color-silver-60);
    font-size: var(--wts-font-size-sm);
}

/* ── Page /dev/components (story 1-3, pas un composant — mise en page de la démo) ── */
.dev-demo {
    max-width: 960px;
    margin: 0 auto;
    padding: var(--wts-space-8) var(--wts-space-6);
    display: flex;
    flex-direction: column;
    gap: var(--wts-space-8);
}

.dev-demo__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--wts-space-4);
    margin-bottom: var(--wts-space-6);
}

/* Colonne pleine largeur (release-item, card-project…) — pas de style= inline possible,
   la CSP du site est stricte (style-src 'self', sans unsafe-inline, cf.
   SecurityHeadersSubscriber), qui bloquerait silencieusement l'attribut. */
.dev-demo__row--full {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
}

.dev-demo__row--stack {
    flex-direction: column;
    align-items: stretch;
    max-width: 28rem;
}

/* Thème --project-* de démo, en classe externe (pas de style= inline possible, cf.
   .dev-demo__row--full plus haut) — sans ça les variables ne sont jamais définies :
   var(--project-accent) invalide fait retomber border/background-color à "aucun", ce qui a
   fait longtemps croire à un CTA sans bordure au lieu d'un thème jamais appliqué. */
.dev-demo__project-theme {
    width: 100%;
    --project-primary: var(--wts-color-orange);
    --project-secondary: var(--wts-color-white);
    --project-bg: var(--wts-color-white-20);
    --project-accent: var(--wts-color-orange);
    --project-font-heading: var(--wts-font-display);
    --project-font-body: var(--wts-font-sans);
}

/* assets/styles/_fonts.css */
/* Polices auto-hébergées — Frick (titres/accents) + Outfit (corps). Extrait en partial
   partagé pour être importé à la fois par app.css (site public) et admin.css (préviz
   thème projet dans le back office, story 2-3) sans dupliquer les @font-face. */

/* Frick 0.3 ne fournit qu'une seule graisse (regular), en deux chasses : normale et condensée. */
@font-face {
    font-family: 'Frick';
    src: url('/build/fonts/frick-regular.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Frick';
    src: url('/build/fonts/frick-condensed.woff2') format('woff2');
    font-weight: 400;
    font-stretch: condensed;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Outfit';
    src: url('/build/fonts/outfit-regular.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Outfit';
    src: url('/build/fonts/outfit-semibold.woff2') format('woff2');
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}

