/* Utilitaires. Volontairement peu nombreux : tout le reste est nommé. */

.visuellement-cache {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* Lien d'évitement : premier élément focusable du document. */
.saut-contenu {
    position: fixed;
    inset-block-start: 0.75rem;
    inset-inline-start: 0.75rem;
    z-index: calc(var(--z-amorce) + 1);
    padding: 0.7rem 1.1rem;
    border-radius: var(--rayon-sm);
    background: var(--craie);
    color: var(--encre);
    font-weight: 600;
    transform: translateY(-200%);
    transition: transform var(--duree-courte) var(--ease-sortie);
}

.saut-contenu:focus-visible {
    transform: translateY(0);
}

.no-scroll {
    overflow: hidden;
}

/*
 * Grain. Une seule couche fixe pour tout le document : un data-URI SVG de bruit
 * fractal, mixé en overlay. Coût : une texture, zéro requête, pas de repeint au
 * scroll puisqu'elle est fixe et non animée.
 */
.grain {
    position: fixed;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    opacity: 0.32;
    mix-blend-mode: overlay;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}

@media (prefers-reduced-motion: reduce) {
    .grain {
        opacity: 0.18;
    }
}

/* Masque de fondu latéral, pour les rails horizontaux et les bandeaux. */
.fondu-lateral {
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.plein-ecran {
    block-size: var(--vh);
}

.centre {
    display: grid;
    place-items: center;
}

.sans-marge {
    margin: 0;
}
