Site personnel courcellematthi.eu

This commit is contained in:
lrdlg
2026-08-05 22:40:03 +02:00
commit df12d21165
39 changed files with 4503 additions and 0 deletions
+330
View File
@@ -0,0 +1,330 @@
/* ==========================================================================
layout.css — Structure de page
--------------------------------------------------------------------------
Conteneurs, en-tête collant, navigation, sections, grilles, pied de page.
Ce fichier positionne ; components.css habille.
========================================================================== */
@layer layout {
/* ======================================================================
CONTENEUR
Un seul conteneur réutilisé partout : la largeur de contenu est décidée
à un seul endroit.
====================================================================== */
.container {
inline-size: 100%;
max-inline-size: var(--width-content);
margin-inline: auto;
padding-inline: var(--gutter);
}
/* ======================================================================
LIEN D'ÉVITEMENT
Premier élément focusable de la page. Permet à un utilisateur au
clavier ou au lecteur d'écran de sauter la navigation pour atteindre
directement le contenu. Critère WCAG 2.4.1 (Contourner des blocs).
Masqué visuellement hors focus, mais jamais display:none — sinon il
ne serait pas focusable.
====================================================================== */
.skip-link {
position: fixed;
inset-block-start: var(--space-xs);
inset-inline-start: var(--space-xs);
z-index: var(--z-skip-link);
padding: var(--space-xs) var(--space-md);
background-color: var(--color-ink);
color: var(--color-ink-inverse);
font-family: var(--font-mono);
font-size: var(--text-sm);
text-decoration: none;
border-radius: var(--radius-sm);
transform: translateY(-200%);
transition: transform var(--transition-fast);
}
.skip-link:focus {
transform: translateY(0);
color: var(--color-ink-inverse);
}
/* ======================================================================
EN-TÊTE COLLANT
====================================================================== */
.site-header {
position: sticky;
inset-block-start: 0;
z-index: var(--z-sticky);
background-color: var(--color-bg-translucent);
border-block-end: 1px solid var(--color-line);
/* Flou d'arrière-plan : le contenu qui défile dessous reste deviné
sans nuire à la lisibilité du menu. Dégradation propre si non
supporté (le fond translucide suffit). */
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
.site-header__inner {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-md);
min-block-size: var(--header-height);
}
.site-header__brand {
display: inline-flex;
align-items: center;
gap: var(--space-xs);
font-family: var(--font-mono);
font-size: var(--text-sm);
font-weight: var(--weight-bold);
color: var(--color-ink);
text-decoration: none;
letter-spacing: -0.01em;
white-space: nowrap;
}
.site-header__brand:hover { color: var(--color-ink); }
.site-header__logo {
inline-size: 1.6rem;
block-size: 1.6rem;
flex-shrink: 0;
}
/* ======================================================================
NAVIGATION PRINCIPALE
====================================================================== */
.site-nav__list {
display: flex;
align-items: center;
gap: var(--space-lg);
list-style: none;
margin: 0;
padding: 0;
}
.site-nav__link {
display: inline-block;
font-family: var(--font-mono);
font-size: var(--text-sm);
color: var(--color-ink-faint);
text-decoration: none;
padding-block: var(--space-2xs);
border-block-end: 2px solid transparent;
transition: color var(--transition-fast), border-color var(--transition-fast);
}
.site-nav__link:hover { color: var(--color-ink); }
/* Section courante. aria-current n'est pas qu'un sélecteur pratique :
il annonce la position aux lecteurs d'écran. Le repère visuel repose
sur la couleur ET sur une bordure — jamais sur la couleur seule
(WCAG 1.4.1, information non véhiculée par la couleur uniquement). */
.site-nav__link[aria-current="true"] {
color: var(--color-ink);
border-block-end-color: var(--color-accent);
}
/* ======================================================================
BOUTON MENU (mobile)
====================================================================== */
.nav-toggle {
display: none; /* Affiché uniquement sous le point de rupture */
align-items: center;
gap: var(--space-xs);
min-block-size: var(--tap-target);
padding-inline: var(--space-xs);
font-family: var(--font-mono);
font-size: var(--text-sm);
color: var(--color-ink-soft);
}
.nav-toggle__icon {
inline-size: 1.15rem;
block-size: 1.15rem;
stroke: currentcolor;
stroke-width: 2;
fill: none;
}
/* Les deux tracés de l'icône se transforment en croix à l'ouverture */
.nav-toggle__line {
transform-origin: center;
transition: transform var(--transition-base), opacity var(--transition-fast);
}
.nav-toggle[aria-expanded="true"] .nav-toggle__line--top { transform: translateY(5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__line--middle { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__line--bottom { transform: translateY(-5px) rotate(-45deg); }
/* ======================================================================
RÉGIONS DE CONTENU
====================================================================== */
.masthead {
padding-block: var(--space-3xl) var(--space-2xl);
border-block-end: 1px solid var(--color-line);
}
.section {
padding-block: var(--space-3xl);
border-block-start: 1px solid var(--color-line);
}
/* ======================================================================
GRILLE AUTO-ADAPTATIVE
auto-fit + minmax : le nombre de colonnes s'ajuste seul à la largeur
disponible, sans media query. Le min() interne évite le débordement
sur les très petits écrans (une colonne ne peut pas être plus large
que son conteneur).
====================================================================== */
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(17.5rem, 100%), 1fr));
gap: var(--space-md);
}
.grid--wide {
grid-template-columns: repeat(auto-fit, minmax(min(22rem, 100%), 1fr));
}
/* Empilement vertical régulier */
.stack > * + * { margin-block-start: var(--space-md); }
/* ======================================================================
PIED DE PAGE
====================================================================== */
.site-footer {
border-block-start: 1px solid var(--color-line);
padding-block: var(--space-xl) var(--space-2xl);
}
.site-footer__inner {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
gap: var(--space-sm) var(--space-lg);
font-family: var(--font-mono);
font-size: var(--text-sm);
color: var(--color-ink-faint);
}
.site-footer__links {
display: flex;
flex-wrap: wrap;
gap: var(--space-md);
list-style: none;
margin: 0;
padding: 0;
}
/* ======================================================================
BOUTON RETOUR EN HAUT
====================================================================== */
.to-top {
position: fixed;
inset-block-end: var(--space-lg);
inset-inline-end: var(--space-lg);
z-index: var(--z-overlay);
display: grid;
place-items: center;
inline-size: var(--tap-target);
block-size: var(--tap-target);
background-color: var(--color-surface);
border: 1px solid var(--color-line-strong);
border-radius: var(--radius-full);
box-shadow: var(--shadow-md);
color: var(--color-ink-soft);
/* Masqué par défaut : révélé par JS après défilement.
visibility (et non display) pour permettre la transition. */
opacity: 0;
visibility: hidden;
transform: translateY(0.5rem);
transition: opacity var(--transition-base),
transform var(--transition-base),
visibility var(--transition-base);
}
.to-top[data-visible="true"] {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.to-top:hover {
color: var(--color-accent-dark);
border-color: var(--color-accent);
}
/* ======================================================================
POINT DE RUPTURE MOBILE
Une seule media query pour toute la mise en page : le reste est fluide.
Écrite en syntaxe de plage (width <= 46rem), lisible et sans le
traditionnel « max-width: 45.999rem ».
====================================================================== */
@media (width <= 46rem) {
.nav-toggle { display: inline-flex; }
.site-header__inner { position: relative; }
/* Le menu devient un panneau déroulant sous l'en-tête */
.site-nav {
position: absolute;
inset-block-start: 100%;
inset-inline: calc(var(--gutter) * -1);
display: none;
background-color: var(--color-surface);
border-block-end: 1px solid var(--color-line);
box-shadow: var(--shadow-md);
}
.site-nav[data-open="true"] { display: block; }
.site-nav__list {
flex-direction: column;
align-items: stretch;
gap: 0;
padding: var(--space-xs) var(--gutter) var(--space-md);
}
.site-nav__link {
/* Hauteur de cible tactile conforme (44px minimum) */
display: flex;
align-items: center;
min-block-size: var(--tap-target);
padding-inline-start: var(--space-xs);
border-block-end: 1px solid var(--color-line);
border-inline-start: 2px solid transparent;
}
/* Le repère de section active passe du bas au côté */
.site-nav__link[aria-current="true"] {
border-block-end-color: var(--color-line);
border-inline-start-color: var(--color-accent);
background-color: var(--color-accent-glow);
}
.masthead { padding-block: var(--space-2xl) var(--space-xl); }
.section { padding-block: var(--space-2xl); }
.to-top {
inset-block-end: var(--space-md);
inset-inline-end: var(--space-md);
}
}
}