/* Feuille de style principale du site.
   Organisée en sections : HEADER, DROPDOWN, RANDOM GRID, MAIN, ARTICLES.
   Les valeurs de couleurs/tailles viennent de variables.css. */

/* Le padding et la bordure sont comptés DANS la largeur annoncée. Sans cela,
   un bloc en `max-width: 570px` avec du padding fait en réalité plus de
   570px et déborde de sa colonne. */
*,
*::before,
*::after {
    box-sizing: border-box;
}

body {
    font-family: var(--font-body);
    /* Graisse, interlignage et interlettrage repris de NEWS (voir
       variables.css). La graisse 300 ne touche que le texte courant : les
       titres et les <strong> gardent le gras du navigateur, exactement
       comme dans NEWS, qui ne redefinit la graisse nulle part ailleurs. */
    font-weight: var(--font-weight-body);
    line-height: var(--line-height-body);
    letter-spacing: var(--letter-spacing-body);
    margin: 0;
    min-height: 100vh;
    text-align: left;

    /* Sans ces deux lignes, un navigateur réglé en mode sombre peint un fond
       sombre derrière un texte resté noir : la page devient illisible. */
    color: var(--color-text);
    background: var(--color-background);

    display: flex;
    flex-direction: column;
}

ul {
    margin:0;
    padding:0;
}

/* Tous les liens du site, menu compris (voir variables.css). */
a {
    color: var(--color-link);
    text-decoration: none;
    transition: color 0.2s ease;
}

a:hover,
a:active {
    color: var(--color-link-hover);
}


/* Le splash reprend le fond bleu de l'ancien index.php. La classe est posée
   sur <body> dans index.html : c'est la seule page concernée, toutes les
   autres gardent le fond blanc du site. */
body.page-splash {
    background: var(--color-splash-background);
}

#splash #splash-link {
    position: absolute;
    transform: translate(-50%, -50%);
    left: 50%;
    top: 50%;
}

/* L'image du splash est tirée au hasard parmi les articles récents : elle
   peut aussi bien être un paysage de 600x400 qu'un portrait de 918x1618.
   Sans plafond de hauteur, les portraits débordaient de l'écran.

   La deuxième déclaration `dvh` n'est pas un doublon : sur mobile, `100vh`
   vaut la hauteur de l'écran barre d'URL *masquée*, donc plus que la zone
   réellement visible — c'est la cause classique du « il reste un peu de
   scroll ». Les navigateurs qui ignorent `dvh` gardent la ligne `vh`. */
#splash #splash-image {
    /* `block` n'est pas cosmétique : une image reste `inline` par défaut et
       sa boîte de ligne réserve la place des jambages sous elle. Ces ~4px
       fantômes suffisent à faire réapparaître une barre de défilement quand
       l'image occupe exactement la hauteur disponible. */
    display: block;
    max-width: calc(100vw - 16px);
    max-height: 100vh;
    max-height: 100dvh;
}

@media (min-width: 769px) {
    /* 600px en desktop, sans jamais dépasser la fenêtre pour autant : une
       fenêtre plus basse que 600px se remettrait à défiler. */
    #splash #splash-image {
        max-height: min(600px, 100vh);
    }
}


/** HEADER **/
/* Le sticky est posé sur le custom element (enfant direct de body, sur
   toute la hauteur de page) et non sur .site-header : sinon son parent
   immédiat (le wrapper) ferait la même hauteur que lui et le sticky
   n'aurait aucune marge pour "coller". */
site-header {
    display: block;
    position: sticky;
    top: 0;
    z-index: 1001;
    background: var(--color-background);
}

.site-header {
    padding: 20px 8px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    max-width: 1000px;
    margin: auto

}

.site-title {
    text-decoration: none;
    color: var(--color-menu-link);
}

.site-title:hover {
    color: var(--color-menu-link-hover);
}

.site-nav {
    display: flex;
    gap: var(--spacing-lg);
}

.site-nav a {
    text-decoration: none;
    color: var(--color-menu-link);
}

.site-nav a:hover {
    color: var(--color-menu-link-hover);
}

/** DROPDOWN PAR CATEGORIE **/
.nav-item {
    position: relative;
}

.nav-dropdown {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    background: var(--color-background);
    border: 1px solid var(--color-border);
    padding: var(--spacing-sm) var(--spacing-md);
    min-width: 220px;
    max-height: 60vh;
    overflow-y: auto;
    z-index: 1000;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.nav-dropdown a {
    display: block;
    padding: 2px 0;
    font-size: var(--font-size-sm);
}

.nav-dropdown-year {
    margin: var(--spacing-sm) 0 0;
    font-weight: bold;
    color: var(--color-text-secondary);
}

.nav-dropdown-year:first-child {
    margin-top: 0;
}

.has-dropdown:hover > .nav-dropdown {
    display: block;
}

@media (max-width: 768px) {
    .site-header {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--spacing-sm);
    }

    .site-nav {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: var(--spacing-sm) var(--spacing-md);
        width: 100%;
    }

    .has-dropdown:hover > .nav-dropdown {
        display: none;
    }
}


.submenu-next {
    align-self: flex-end;
}


.submenu-nav {
    display: flex;
    justify-content: space-between;
}
.submenu-nav:not(:has(.submenu-prev)) {
    justify-content: flex-end;
}
/** RANDOM GRID **/
.random-grid {
    display: grid;
    grid-template-columns: repeat(var(--cols, 5), 1fr);
    gap: 4px;
    padding: 20px 0;
}

.random-cell {
    display: block;
    line-height: 0;
}

.random-cell img {
    width: 100%;
    height: auto;
    display: block;
}

/** MAIN **/

.main-body {
    max-width: 1000px;
    margin: 0 auto;
}

.section-listing, .site-submenu, .article-layout, .projects-list {
    max-width: 1000px;
    margin: 0 auto;
    padding: 0 8px;
}

/* Même remarque que pour site-header : sticky sur le custom element,
   pas sur .site-submenu, sinon le wrapper n'a pas de marge de manœuvre. */
site-submenu {
    display: block;
    position: sticky;
    top: var(--header-height, 60px);
    z-index: 999;
    background: var(--color-background);
}

.site-submenu {
    padding-top: var(--spacing-sm);
    padding-bottom: var(--spacing-sm);
}

/** ARTICLES **/
/* Le vocabulaire de classes ci-dessous (contentexpo, titre, content, texte,
   legende, eng, colonne...) vient de l'ancien site PHP (/css/style.css) : les
   article.html migrés le portent déjà tel quel, il n'avait simplement jamais
   été stylé ici. Les largeurs reprennent les valeurs d'origine.
   Ces classes sont documentées pour les non-devs dans AJOUTER-UN-ARTICLE.md. */

/* Conteneur racine d'un article : une largeur par section, comme avant.
   `flow-root` contient les flottants de .colonne, y compris quand ceux-ci
   sont imbriqués dans un <div> sans classe (cas de works/1998bannieres) —
   évite d'avoir à ajouter un clearfix dans le HTML des articles. */
.contentexpo,
.contentwork,
.contentedition {
    display: flow-root;
    margin: var(--spacing-lg) auto;
}

.contentexpo    { max-width: 575px; }
.contentwork    { max-width: 700px; }
.contentedition { max-width: 600px; }

/* .content / #content ne sont que des wrappers de structure : pas de style,
   comme dans l'ancien site. */

/* Les images remplissent la largeur du conteneur : c'est ce qui donne la
   colonne régulière caractéristique de l'ancien site. Le max-width en px
   par conteneur reprend les valeurs de /css/style.css. */
.article-layout img {
    display: block;
    width: 100%;
    height: auto;
    max-width: 570px; /* repli pour un article sans conteneur racine */
    margin: 0 auto var(--spacing-md);
}

.contentexpo img { max-width: 570px; }
.contentwork img { max-width: 695px; }

/* Les éditions gardaient leur taille naturelle, bornée en hauteur.
   `max-width:100%` plutôt que `600px` : comme .contentedition fait elle-même
   600px au plus, cela donne bien 600px en desktop, mais contraint aussi
   l'image à la largeur du conteneur sur mobile — avec une valeur en pixels,
   une image large débordait de l'écran. */
.contentedition img {
    width: auto;
    max-width: 100%;
    max-height: 500px;
}

/* Modifieur : image dont le fichier source est trop petit pour remplir la
   colonne sans devenir floue. Elle garde sa taille d'origine au lieu d'être
   agrandie. Remplace les anciens style="width:...px" écrits en dur. */
.article-layout img.petit {
    width: auto;
    max-width: 100%;
}

/* Deux images côte à côte. Repasse en pleine largeur sur mobile.
   Écrit `.article-layout .colonne` et non `.colonne` tout court : la classe
   est posée tantôt sur le <p> englobant, tantôt directement sur l'<img>
   (cas de works/2000album), et dans ce dernier cas `.article-layout img`
   ci-dessus (spécificité 0,1,1) l'emporterait sur `.colonne` seul (0,1,0)
   et rendrait l'image pleine largeur au lieu de 48%. */
.article-layout .colonne {
    float: left;
    width: 48%;
    margin: 3px;
    text-align: left;
    font-size: var(--font-size-xs);
}

@media (max-width: 768px) {
    .article-layout .colonne {
        float: none;
        width: 100%;
        margin: 0 0 var(--spacing-md);
    }
}

.article-layout video {
    display: block;
    width: 100%;
    max-width: 570px;
    height: auto;
    margin: 0 auto var(--spacing-md);
}

/* Lecteur audio (l'édition Undead est un disque vinyle). */
.article-layout audio {
    display: block;
    width: 100%;
    max-width: 570px;
    margin: 0 auto var(--spacing-md);
}

.article-layout iframe {
    display: block;
    width: 100%;
    max-width: 570px;
    height: 80vh;
    min-height: 500px;
    margin: 0 auto;
    border: none;
}

/* Carousel d'images (voir js/carousel.js). Sans JavaScript, la liste reste
   affichée telle quelle : les images s'empilent, rien n'est perdu. C'est la
   classe `slider-pret`, posée par le JS, qui déclenche le masquage. */
.slider {
    list-style: none;
    margin: 0;
    padding: 0;
}

.slider-pret li {
    display: none;
}

.slider-pret li.slider-actif {
    display: block;
}

.slider-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-md);
    margin: 0 auto var(--spacing-md);
    max-width: 570px;
    font-size: var(--font-size-xs);
}

.slider-nav button {
    font-family: inherit;
    font-size: inherit;
    color: var(--color-menu-link);
    background: none;
    border: none;
    padding: var(--spacing-xs);
    cursor: pointer;
}

.slider-nav button:hover {
    color: var(--color-menu-link-hover);
}

.slider-compteur {
    color: var(--color-text-secondary);
}

/* Bloc titre en tête d'article */
.titre {
    margin-bottom: var(--spacing-xl);
}

.titre h1 {
    font-size: var(--font-size-sm);
    margin: 0;
}

.titre h2 {
    font-size: var(--font-size-xs);
    font-weight: normal;
    margin: var(--spacing-xs) 0 0;
}

/* Corps de texte. Aligné à gauche (choix v2) et non justifié comme avant. */
.texte {
    margin: var(--spacing-md) 0 var(--spacing-lg);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-loose);
}

/* Légende sous un média : même largeur que l'image qu'elle accompagne.
   L'opacité la distingue du corps de texte sans la rapetisser davantage. */
.legende {
    max-width: 570px;
    margin: 0 auto var(--spacing-md);
    padding: var(--spacing-sm);
    font-size: var(--font-size-xs);
    line-height: var(--line-height-tight);
    text-align: left;
    opacity: 0.85;
}

.contentwork .legende    { max-width: 695px; }
.contentedition .legende { max-width: 600px; }

/* L'ancien site centrait aussi par l'attribut HTML align="center" (67
   éléments dans les articles migrés : 51 div, 15 p, 1 table). Ce n'est pas
   un style en ligne mais un « presentational hint », de priorité inférieure
   à toute règle d'auteur : une règle suffit donc à le neutraliser, sans
   avoir à retoucher les 65 article.html. Le drapeau `i` couvre les deux
   graphies présentes, "center" et "Center". */
.article-layout [align="center" i] {
    text-align: left;
}

.credit {
    text-align: left;
    font-size: var(--font-size-xs);
}

/* Passages en anglais (l'ancien site les mettait en bleu). L'italique et
   l'opacité les font passer au second plan par rapport au texte français.
   L'opacité coûte du contraste : 3,9:1 sur fond blanc, sous le seuil de
   lisibilité recommandé (4,5:1). Acceptable pour quelques mots au fil du
   texte ; si un paragraphe entier en anglais devient pénible à lire
   (cas de projects/devore), monter cette valeur à 0.85 rend 5,4:1. */
.eng {
    color: var(--color-eng);
    font-style: italic;
    opacity: 0.7;
}

/* Bande horizontale — utilisée uniquement par « Les Maisons de mes rêves »,
   où chaque sous-page présente une série de vues alignées côte à côte à
   hauteur constante, et non empilées.

   Portage de css/style.css (ancien site) : h1.horizontal, #contenthorizontal,
   .horizon img, #legendehorizontale, .texte2. Les deux id d'origine sont
   devenus des classes de même nom : article.html est un fragment injecté et
   recopié d'une page à l'autre, un id n'y a plus de raison d'être unique.

   Le débordement est la seule vraie différence avec l'original : l'ancien
   site laissait le cadre (frameset, scrolling=auto) fournir la barre de
   défilement horizontale. Sans cadre, c'est le conteneur lui-même qui doit
   défiler — sinon la bande pousse le <body> et c'est la page entière qui
   part en travers. */
h1.horizontal {
    font-size: var(--font-size-sm);
    font-weight: bold;
    text-align: left;
    margin: 0 0 var(--spacing-xl);
}

.contenthorizontal {
    overflow-x: auto;
    overflow-y: hidden;
    margin-bottom: var(--spacing-lg);
    -webkit-overflow-scrolling: touch;
}

.horizon {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-sm);
    width: max-content;
}

/* La hauteur fixe est ce qui fait la bande : les images gardent leur
   proportion et c'est leur largeur qui varie. Écrit avec .horizon devant
   pour repasser devant `.article-layout img` (0,1,1), qui les mettrait
   sinon en display:block pleine largeur, une par ligne. */
.horizon img {
    display: block;
    width: auto;
    max-width: none;
    height: 500px;
    margin: 0;
}

/* Sur mobile, 500px de haut donnaient des images de 675px de large (la
   plupart sont au ratio 1,35) : plus larges que l'écran, donc coupées, sans
   rien qui laisse deviner qu'il y en a d'autres à côté — et 500px de hauteur
   pour n'en montrer que la moitié.

   La hauteur se cale donc sur la largeur de l'écran, puisque c'est elle qui
   contraint ici : 60vw donne une image à environ 80% de la largeur visible,
   ce qui en montre une entière tout en laissant dépasser un morceau de la
   suivante — le seul indice que la bande défile. La valeur rejoint presque
   les 500px d'origine à la bascule (461px à 768px), sans rupture visible. */
@media (max-width: 768px) {
    .horizon img {
        height: 60vw;
    }
}

.legendehorizontale {
    max-width: 600px;
}

/* Variante de .texte, plus petite, propre à ces pages. */
.texte2 {
    margin: var(--spacing-md) 0 var(--spacing-lg);
    font-size: var(--font-size-xs);
    line-height: var(--line-height-normal);
}

/* Sur mobile, la base typo du site est réduite à 87.5% (voir variables.css),
   ce qui rendait tous les textes d'article trop petits pour être lus
   confortablement (corps à 12,25px, légendes et sous-titres à 10,5px).

   Chaque texte d'article monte donc d'un cran de token, ce qui revient très
   exactement à lui rendre sa taille de bureau : la réduction de 87.5% ne
   s'applique plus au contenu des articles, seulement au reste du site (menu,
   sous-navigation), qui lui est bien dimensionné.

   Ces règles doivent rester APRÈS celles qu'elles corrigent : une media query
   n'ajoute aucune spécificité, donc placées plus haut dans le fichier elles
   seraient écrasées par les règles .texte / .legende / .titre ci-dessus. */
@media (max-width: 768px) {
    .texte {
        font-size: var(--font-size-md); /* 14px, comme en desktop */
    }

    .legende,
    .texte2,
    .titre h2 {
        font-size: var(--font-size-sm); /* ~12px, comme en desktop */
    }

    .titre h1 {
        font-size: var(--font-size-md); /* 14px, comme en desktop */
    }
}

/** PROJETS : liste des sous-catégories (équivalent de l'ancienne navbar
    latérale du projet, mais dans le flux normal de la page, pas en
    sidebar, pour rester responsive/mobile-friendly) **/
.project-subcategories {
    /* Même boîte que .article-layout (1000px centré, padding 8px) pour que
       le bord gauche de la liste s'aligne exactement sur celui du
       paragraphe d'intro au-dessus, au lieu d'être centrée indépendamment. */
    max-width: 1000px;
    margin: var(--spacing-xl) auto 0;
    padding: var(--spacing-lg) 8px 0;
    border-top: 1px solid var(--color-border);
    text-align: left;
}

.project-subcategories ul {
    list-style: none;
    margin: 0;
}

/* Intertitre d'année, comme les séparateurs du menu de l'ancien site. */
.project-year {
    margin: var(--spacing-lg) 0 var(--spacing-xs);
    font-size: var(--font-size-xs);
    color: var(--color-text-secondary);
}

.project-year:first-child {
    margin-top: 0;
}

.project-subcategories li {
    padding: var(--spacing-sm) 0;
}

.project-subcategory-link {
    display: inline-block;
}

.main-accueil {
    flex: 1;
    display: flex;
    align-items: center;
}

/* Même tirage aléatoire que le splash, mêmes portraits qui débordaient —
   à ceci près qu'ici le header occupe déjà le haut de l'écran : la hauteur
   disponible est ce qui reste en dessous. `--header-height` est posée par
   site-header.js, qui mesure sa hauteur réelle (deux lignes en mobile) et
   la recalcule au redimensionnement. */
.main-accueil #splash-image {
    display: block; /* même raison que #splash-image : voir plus haut */
    max-width: calc(100vw - 16px);
    max-height: calc(100vh - var(--header-height, 60px));
    max-height: calc(100dvh - var(--header-height, 60px));
}

@media (min-width: 769px) {
    .main-accueil #splash-image {
        max-height: min(600px, calc(100vh - var(--header-height, 60px)));
    }
}