/*
Theme Name:   Nitchaeff
Theme URI:    https://nitchaeff.com
Author:       Pascal Bernheim
Description:  Thème de l'artiste Alain Nitchaeff. Thème classique (PHP), bâti par-dessus le plugin sam-moteur qui fournit les spectacles, les dates et l'agenda. Le moteur tient le fonctionnement, ce thème tient le graphisme.
Version:      0.6.1
Requires PHP: 8.0
Requires at least: 6.4
License:      GPL-2.0-or-later
License URI:  https://www.gnu.org/licenses/gpl-2.0.html
Text Domain:  nitchaeff
Tags:         one-column, custom-menu, translation-ready
*/

/* ==========================================================================
   Thème Nitchaeff — feuille de style
   --------------------------------------------------------------------------
   C'est ici que va le graphisme. Le moteur n'en livre aucun : il émet un
   balisage nu, aux classes stables, que ce fichier habille.

   La liste complète des classes émises est dans CONTRAT-MOTEUR.md. Les styler
   suffit dans l'immense majorité des cas — surcharger un gabarit PHP dans
   sam/ ne se justifie que si la STRUCTURE du HTML doit changer, pas son
   apparence.

   Sections ci-dessous : dans l'ordre où on les rencontre.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Fondations — variables, remise à zéro, typographie
   -------------------------------------------------------------------------- */

:root {

	/* --- Couleurs ---------------------------------------------------------
	   Un fond presque noir mais chaud, un blanc cassé, un or mat pour tout ce
	   qui se clique ou se signale. Rien d'autre : pas de rouge d'erreur, pas
	   de gris bleuté. Les nuances se font à l'opacité du texte, pas en
	   ajoutant des teintes. */

	--n-fond:            #0e0e0d;
	--n-fond-pied:       #0b0b0a;
	--n-texte:           #f2efe9;
	--n-accent:          oklch(0.72 0.13 88);
	--n-accent-survol:   oklch(0.80 0.13 88);

	/* La seule couleur en plus de l'or, et elle ne sert qu'à une chose :
	   dire qu'une date n'est plus disponible. Assez sombre pour porter le
	   texte clair sans le faire vibrer. */
	--n-complet:         oklch(0.48 0.17 27);
	/* Le même rouge, mais assez clair pour être lu sur le fond sombre :
	   --n-complet est un aplat derrière du texte clair, pas une encre. */
	--n-alerte:          oklch(0.74 0.15 27);

	--n-texte-doux:      rgba(242, 239, 233, 0.74);
	--n-texte-discret:   rgba(242, 239, 233, 0.60);
	--n-texte-mineur:    rgba(242, 239, 233, 0.45);

	--n-filet:           rgba(242, 239, 233, 0.16);
	--n-filet-doux:      rgba(242, 239, 233, 0.12);

	/* --- Polices ----------------------------------------------------------
	   Quatre familles, chacune à un poste précis. Ne pas les intervertir :
	   c'est ce partage qui tient le graphisme, plus que la palette.

	     titre    Bodoni Moda    grandes tailles, l'italique pour l'accent
	     texte    Spectral 300   les paragraphes, jamais les libellés
	     ui       Work Sans      navigation, boutons, noms de lieux
	     mono     JetBrains Mono libellés capitales, dates, mentions */

	--n-titre: "Bodoni Moda", Didot, "Times New Roman", serif;

	/* Bodoni Moda est une Didone à axe optique. Par défaut le navigateur
	   accorde l'axe au corps : à 78 px il sert la coupe d'affiche, la plus
	   contrastée — donc aux déliés les plus fins. On le bloque bas pour
	   demander la coupe « petit corps », moins contrastée, puis on l'agrandit.
	   C'est ce réglage, plus que la graisse, qui épaissit les déliés.
	   Ces deux valeurs se changent ici et nulle part ailleurs. */
	--n-titre-opsz: 14;
	--n-titre-graisse: 500;
	--n-texte-police: "Spectral", Georgia, "Times New Roman", serif;
	--n-ui: "Work Sans", system-ui, -apple-system, sans-serif;
	--n-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

	/* --- Échelle ----------------------------------------------------------
	   Deux registres qui ne se croisent pas : les titres tombent d'un coup
	   de 78 à 26 px, les libellés vivent tous entre 10 et 13 px. L'entre-deux
	   est vide, volontairement. */

	--n-t1: clamp(2.75rem, 6vw, 4.875rem);   /* 44 → 78 px */
	--n-t2: clamp(2rem, 3.4vw, 2.75rem);     /* 32 → 44 px */
	--n-t3: 1.625rem;                        /* 26 px */
	--n-corps: 1.1875rem;                    /* 19 px, interligne 1.6 */
	--n-libelle: 0.6875rem;                  /* 11 px, capitales espacées */

	--n-interlettre-libelle: 0.16em;

	/* --- Rythme -----------------------------------------------------------
	   Une seule marge latérale pour toute la page, une seule respiration
	   entre sections. Tout le reste s'aligne dessus. */

	--n-marge: clamp(1.5rem, 5vw, 3.5rem);   /* 24 → 56 px */
	--n-section: clamp(3rem, 8vw, 5.25rem);  /* 48 → 84 px */

	/* Cadrage de la photo d'accueil.
	   Une bande large recadre forcément une photo de scène. Ancrée en haut,
	   elle ne sacrifie que le plancher — les visages sont toujours dans le
	   tiers supérieur d'une photo de concert. À ajuster ici, et nulle part
	   ailleurs, si une autre photo tombe mal. */
	--n-une-cadrage: 50% 0%;
}

/* Angles vifs, filets d'un pixel, aucune ombre : le graphisme ne repose que
   sur la typographie et le vide. Ne pas introduire de border-radius. */

*,
*::before,
*::after {
	box-sizing: border-box;
}

body {
	margin: 0;
	background: var(--n-fond);
	color: var(--n-texte);
	font-family: var(--n-ui);
	font-size: 1rem;
	line-height: 1.5;
	-webkit-font-smoothing: antialiased;
}

a {
	color: var(--n-accent);
	text-decoration: none;
}

a:hover,
a:focus-visible {
	color: var(--n-accent-survol);
}

::selection {
	background: var(--n-accent);
	color: var(--n-fond);
}

img,
video {
	max-width: 100%;
	height: auto;
}

/* --------------------------------------------------------------------------
   2. Gabarit général — en-tête, navigation, pied de page
   -------------------------------------------------------------------------- */

.site-evitement {
	position: absolute;
	left: -9999px;
}

.site-evitement:focus {
	position: static;
	display: inline-block;
	padding: 0.75rem 1rem;
	background: var(--n-accent);
	color: var(--n-fond);
}

/* L'en-tête reste visible : sur une page de spectacle longue, revenir à
   l'agenda ne doit pas demander de remonter. */
.site-entete {
	position: sticky;
	top: 0;
	z-index: 20;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1.25rem;
	flex-wrap: wrap;
	padding: 1.25rem var(--n-marge);
	background: color-mix(in srgb, var(--n-fond) 88%, transparent);
	backdrop-filter: blur(14px);
	border-bottom: 1px solid var(--n-filet-doux);
}

.site-nom {
	margin: 0;
	font-family: var(--n-ui);
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	white-space: nowrap;
}

.site-nom a {
	color: var(--n-texte);
}

.site-nav ul {
	display: flex;
	align-items: center;
	gap: 1.375rem;
	flex-wrap: wrap;
	margin: 0;
	padding: 0;
	list-style: none;
}

.site-nav a {
	font-size: 0.75rem;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--n-texte-discret);
}

.site-nav a:hover,
.site-nav .current-menu-item > a {
	color: var(--n-texte);
}

.site-contenu {
	padding: var(--n-section) var(--n-marge);
}

.site-pied {
	padding: var(--n-section) var(--n-marge) 2rem;
	background: var(--n-fond-pied);
	border-top: 1px solid var(--n-filet-doux);
}

.site-pied__mention {
	margin: 0;
	font-family: var(--n-mono);
	font-size: 0.625rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--n-texte-mineur);
}

/* --------------------------------------------------------------------------
   2 bis. Accueil — front-page.php
   Le prochain spectacle, ses dates dessous. Une affiche, pas un article.
   -------------------------------------------------------------------------- */

/* L'accueil tient dans un écran, pied de page compris : personne ne doit
   défiler pour découvrir que la page est finie. Le corps devient une colonne,
   la bande du spectacle absorbe la place restante, le pied vient buter en
   bas. Les autres pages ne sont pas concernées — elles, elles défilent. */
.home {
	min-height: 100vh;
	min-height: 100dvh;
	display: flex;
	flex-direction: column;
}

/* Le rembourrage vertical du gabarit général coûterait ici deux hauteurs de
   section et repousserait le pied hors de l'écran ; le cadrage latéral, lui,
   reste — c'est lui qui aligne la bande sur le reste du site. Le repli sans
   moteur porte son propre `.site-contenu` et garde donc ses marges. */
.home > .site-contenu {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	padding-top: 0;
	padding-bottom: 0;
}

/* Sur l'accueil le pied ne ménage plus de transition : il clôt. */
.home .site-pied {
	padding-top: 2.5rem;
}

.accueil-une {
	position: relative;
	display: flex;
	align-items: flex-end;
	/* Une hauteur plancher, pas une hauteur fixe : la bande s'étire pour
	   prendre ce que les dates et le pied de page laissent, et rétrécit sur
	   un écran court plutôt que de les pousser dehors. */
	flex: 1 1 auto;
	min-height: min(50vh, 30rem);
	padding: var(--n-section) var(--n-marge) 2.25rem;
	overflow: hidden;
}

.accueil-une__visuel {
	position: absolute;
	inset: 0;
	z-index: 0;
}

.accueil-une__visuel img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: var(--n-une-cadrage);
}

/* Un voile, pas un assombrissement uniforme. La moitié haute reste
   intacte — c'est là qu'est la photo, et la voiler ne servait qu'à
   l'éteindre. Le fondu ne commence qu'à mi-hauteur, où le texte arrive, et
   n'atteint le fond opaque qu'en bas. Déplacer le premier 50 % remonte ou
   descend le début de l'ombre. */
.accueil-une::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	background: linear-gradient(
		to bottom,
		transparent 0%,
		transparent 50%,
		color-mix(in srgb, var(--n-fond) 45%, transparent) 70%,
		color-mix(in srgb, var(--n-fond) 85%, transparent) 88%,
		var(--n-fond) 100%
	);
}

.accueil-une__texte {
	position: relative;
	z-index: 2;
	display: flex;
	flex: 1 1 auto;
	flex-wrap: wrap;
	align-items: flex-end;
	justify-content: space-between;
	gap: 1.25rem 2.5rem;
}

/* Le titre garde sa largeur de lecture ; c'est le bloc, pas la bande, qui
   est bridé — sinon le bouton se collerait au texte au lieu d'aller à la
   marge opposée. */
.accueil-une__propos {
	max-width: 44rem;
}

.accueil-une__surtitre {
	margin: 0 0 1.25rem;
	font-family: var(--n-mono);
	font-size: var(--n-libelle);
	letter-spacing: var(--n-interlettre-libelle);
	text-transform: uppercase;
	color: var(--n-accent);
}

.accueil-une__titre {
	margin: 0;
	font-size: var(--n-t1);
	line-height: 0.98;
	letter-spacing: -0.02em;
	text-wrap: balance;
}

.accueil-une__sous-titre {
	margin: 1rem 0 0;
	font-family: var(--n-texte-police);
	font-weight: 300;
	font-style: italic;
	font-size: 1.375rem;
	color: var(--n-texte-doux);
}

.accueil .sam-agenda__section {
	max-width: 64rem;
	margin: 0 auto;
}

/* Les dates suivent le titre de près : l'espace d'une section entière entre
   les deux laissait croire à deux blocs sans rapport. */
.accueil {
	padding-top: 1.75rem;
	padding-bottom: 2.5rem;
}

/* La rangée d'actions vit dans la bande, à hauteur du titre. Ailleurs elle
   arrivait après les dates, c'est-à-dire après l'endroit où l'on clique. */
.accueil-une__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.75rem;
	margin: 0;
}

.accueil__bouton {
	display: inline-block;
	padding: 0.9375rem 1.75rem;
	font-family: var(--n-ui);
	font-size: 0.75rem;
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

.accueil__bouton--principal {
	border: 1px solid rgba(242, 239, 233, 0.35);
	color: var(--n-texte);
}

.accueil__bouton--principal:hover {
	border-color: var(--n-accent);
	color: var(--n-accent);
}

/* Complet et annulé se lisent à la taille d'un bouton, à côté de « Info ».
   Ce ne sont pas des liens — ni curseur, ni survol : rien ne s'y clique. */
.accueil__etat {
	display: inline-block;
	padding: 0.9375rem 1.75rem;
	font-family: var(--n-ui);
	font-size: 0.75rem;
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	cursor: default;
}

.accueil__etat--complet {
	background: var(--n-complet);
	border: 1px solid var(--n-complet);
	color: var(--n-texte);
}

.accueil__etat--annule {
	border: 1px solid rgba(242, 239, 233, 0.35);
	color: var(--n-texte-discret);
	text-decoration: line-through;
}

/* La note de la date — « report au 12 novembre », « pas d'autre date ».
   Affichée en clair plutôt qu'en info-bulle : une info-bulle n'existe pas
   au doigt, et c'est justement sur téléphone qu'on lit un agenda. */
.accueil__precision {
	flex-basis: 100%;
	margin: 0.25rem 0 0;
	font-family: var(--n-texte-police);
	font-weight: 300;
	font-size: 1rem;
	color: var(--n-texte-discret);
}

/* --------------------------------------------------------------------------
   3. Agenda — [sam_agenda]
   -------------------------------------------------------------------------- */

/* Les conteneurs racines fixent la largeur de lecture. L'agenda peut aller
   plus large que la prose : ce sont des lignes, pas des paragraphes. */
.sam-agenda {
	max-width: 64rem;
	margin: 0 auto;
}

.sam-spectacles {
	max-width: 72rem;
	margin: 0 auto;
}

.sam-spectacles__entete,
.sam-spectacle__entete,
.sam-redaction__entete {
	margin-bottom: var(--n-section);
}

/* Tout ce qui est composé en Bodoni passe par ce réglage. */
.sam-agenda__titre,
.sam-spectacles__titre,
.sam-spectacle__section-titre,
.sam-spectacle__titre,
.sam-carte__titre,
.sam-redaction__titre,
.sam-redaction__section-titre,
.article__titre,
.accueil__titre,
.modale__titre {
	font-family: var(--n-titre);
	font-weight: var(--n-titre-graisse);
	font-optical-sizing: none;
	font-variation-settings: "opsz" var(--n-titre-opsz);
}

.sam-agenda__titre,
.sam-spectacles__titre,
.sam-spectacle__section-titre {
	margin: 0 0 1.5rem;
	font-size: var(--n-t2);
	line-height: 1;
}

.sam-agenda__section + .sam-agenda__section {
	margin-top: var(--n-section);
}

/* Sur la page d'agenda, « À venir » ne dit rien que la page ne dise déjà.
   Le titre des archives reste : lui marque une frontière.
   Portée volontairement étroite — sur une fiche de spectacle la même section
   s'appelle « Prochaines dates » et doit rester visible. */
.sam-agenda > .sam-agenda__section--avenir > .sam-agenda__titre {
	display: none;
}

/* Les archives comptent moins que ce qui vient : elles s'effacent d'un ton
   sans disparaître. */
.sam-agenda__section--archives {
	color: var(--n-texte-discret);
}

.sam-agenda__liste {
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Une date est une ligne souple, pas une grille : les éléments sont tous
   facultatifs côté moteur — pas d'heure, pas de prix, pas de réservation —
   et une grille à colonnes fixes se décalerait dès qu'il en manque un.
   L'ordre visuel est rétabli par « order », le DOM reste celui du moteur. */
.sam-agenda__liste .sam-date {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.375rem 1.375rem;
	padding: 1.125rem 0;
	border-top: 1px solid var(--n-filet);
}

.sam-date__jour {
	order: 1;
	font-family: var(--n-mono);
	font-size: 0.75rem;
	color: var(--n-accent);
	white-space: nowrap;
}

.sam-date__heure {
	order: 2;
	font-family: var(--n-mono);
	font-size: 0.75rem;
	color: var(--n-texte-mineur);
	white-space: nowrap;
}

/* Le lieu porte le poids de la ligne : c'est ce qu'on cherche des yeux. */
.sam-date__lieu {
	order: 3;
	flex: 1 1 12rem;
	min-width: 0;
	font-size: 1.0625rem;
	font-weight: 500;
}

.sam-date__ville {
	order: 4;
	font-size: 0.8125rem;
	color: var(--n-texte-discret);
}

.sam-date__spectacle {
	order: 5;
	font-family: var(--n-texte-police);
	font-weight: 300;
	font-size: 0.9375rem;
	color: var(--n-texte-discret);
}

.sam-date__spectacle a {
	color: inherit;
}

.sam-date__spectacle a:hover {
	color: var(--n-accent);
}

/* Le statut et le prix disent l'état de la date ; la réservation est l'action.
   Le moteur les distingue — un spectacle peut être complet ET garder un lien
   de billetterie — et le graphisme doit garder cette distinction lisible. */
.sam-date__statut {
	order: 7;
	font-family: var(--n-mono);
	font-size: 0.6875rem;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	white-space: nowrap;
}

.sam-date__prix {
	order: 8;
	font-family: var(--n-mono);
	font-size: 0.6875rem;
	color: var(--n-texte-mineur);
	white-space: nowrap;
}

.sam-date__reservation {
	order: 9;
	font-size: 0.75rem;
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	white-space: nowrap;
}

/* La note passe à la ligne : c'est une précision, pas une colonne. */
.sam-date__note {
	order: 10;
	flex-basis: 100%;
	font-family: var(--n-texte-police);
	font-weight: 300;
	font-size: 0.9375rem;
	color: var(--n-texte-discret);
}

/* Une date annulée se barre, une date complète se signale. Aucune ligne de
   PHP : le statut est déjà sur le <li>. */
.sam-date--annule {
	color: var(--n-texte-mineur);
}

.sam-date--annule .sam-date__lieu,
.sam-date--annule .sam-date__jour {
	text-decoration: line-through;
}

.sam-date--annule .sam-date__statut {
	color: var(--n-texte-mineur);
}

/* Même langage que sur l'accueil : le rouge dit l'indisponibilité, partout. */
.sam-date--complet .sam-date__statut {
	padding: 0.25rem 0.5rem;
	background: var(--n-complet);
	color: var(--n-texte);
}

.sam-date--normal .sam-date__statut {
	color: var(--n-accent);
}

.sam-agenda__vide,
.sam-spectacles__vide,
.sam-redaction__vide,
.sam-redaction__connexion,
.article__vide {
	font-family: var(--n-texte-police);
	font-weight: 300;
	font-size: var(--n-corps);
	color: var(--n-texte-discret);
}

/* --------------------------------------------------------------------------
   4. Fiche d'un spectacle — .sam-spectacle__*
   -------------------------------------------------------------------------- */

.sam-spectacle {
	max-width: 60rem;
	margin: 0 auto;
}

.sam-spectacle__titre {
	margin: 0;
	font-size: var(--n-t1);
	line-height: 0.98;
	letter-spacing: -0.02em;
	text-wrap: balance;
}

.sam-spectacle__sous-titre {
	margin: 1rem 0 0;
	font-family: var(--n-texte-police);
	font-weight: 300;
	font-style: italic;
	font-size: 1.5rem;
	color: var(--n-texte-doux);
}

/* Année et durée : les seuls repères chiffrés de la fiche. Public et jauge
   n'existent pas dans le moteur, et c'est délibéré (voir CLAUDE.md). */
.sam-spectacle__infos {
	display: flex;
	flex-wrap: wrap;
	gap: 1.75rem;
	margin: 1.75rem 0 0;
	padding: 1.125rem 0;
	border-top: 1px solid var(--n-filet);
	border-bottom: 1px solid var(--n-filet);
	list-style: none;
	font-family: var(--n-mono);
	font-size: var(--n-libelle);
	letter-spacing: var(--n-interlettre-libelle);
	text-transform: uppercase;
	color: var(--n-texte-mineur);
}

.sam-spectacle__info--prochaine {
	color: var(--n-accent);
}

.sam-spectacle__visuel {
	margin: var(--n-section) 0 0;
}

.sam-spectacle__credit-photo {
	margin-top: 0.75rem;
	font-family: var(--n-mono);
	font-size: 0.625rem;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--n-texte-mineur);
}

/* Le pitch est une phrase d'accroche, pas un paragraphe : il se lit grand. */
.sam-spectacle__pitch {
	margin-top: var(--n-section);
	font-family: var(--n-texte-police);
	font-weight: 300;
	font-size: clamp(1.375rem, 2.4vw, 1.75rem);
	line-height: 1.5;
	color: var(--n-texte);
	text-wrap: pretty;
}

/* Marges par le haut seulement : deux paragraphes voisins ne peuvent plus
   fusionner leurs marges, et l'écart se règle depuis un seul endroit. */
.sam-spectacle__pitch > * {
	margin: 0;
}

.sam-spectacle__pitch > * + * {
	margin-top: 0.9em;
}

/* Quand le pitch compte plusieurs paragraphes, le dernier est la signature
   de la citation qui précède — auteur, publication, date. Elle se range à
   droite, juste dessous, en petit : c'est une mention, pas une suite du
   texte. Un pitch d'un seul paragraphe n'est pas concerné.
   Corollaire à respecter en rédigeant : dans un pitch qui cite, la source
   se met en dernier et seule sur sa ligne. */
.sam-spectacle__pitch > p:last-child:not(:only-child) {
	margin-top: 0.4rem;
	font-size: 1rem;
	line-height: 1.5;
	text-align: right;
	color: var(--n-texte-discret);
}

.sam-spectacle__texte {
	margin-top: 2.5rem;
	max-width: 42rem;
	font-family: var(--n-texte-police);
	font-weight: 300;
	font-size: var(--n-corps);
	line-height: 1.65;
	color: var(--n-texte-doux);
	text-wrap: pretty;
}

.sam-spectacle__video {
	margin-top: var(--n-section);
}

.sam-spectacle__video iframe {
	display: block;
	width: 100%;
	aspect-ratio: 16 / 9;
	height: auto;
	border: 0;
}

/* La façade qui tient la place du lecteur YouTube tant que personne n'a
   cliqué. Même cadre que l'iframe qu'elle remplace : le passage de l'une à
   l'autre ne doit pas faire sauter la page. Voir functions.php. */

.video-facade {
	position: relative;
	aspect-ratio: 16 / 9;
	background: var(--n-fond-pied);
	overflow: hidden;
}

.video-facade__lien {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	text-decoration: none;
	color: var(--n-texte);
}

.video-facade__image {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* L'affiche n'est pas le sujet : elle situe la vidéo, le bouton appelle
	   le clic. Assombrie, elle laisse passer l'un et l'autre. */
	filter: brightness(0.55);
	transition: filter 0.25s ease;
}

.video-facade__lien:hover .video-facade__image,
.video-facade__lien:focus-visible .video-facade__image {
	filter: brightness(0.72);
}

/* Le triangle est dessiné en bordures : pas d'image, pas de police d'icônes,
   et il reste net à toutes les tailles. */
.video-facade__jouer {
	position: absolute;
	top: 50%;
	left: 50%;
	width: 4.5rem;
	height: 4.5rem;
	transform: translate(-50%, -50%);
	border-radius: 50%;
	background: rgba(14, 14, 13, 0.66);
	border: 1px solid var(--n-accent);
	transition: background 0.25s ease, transform 0.25s ease;
}

.video-facade__jouer::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 54%;
	transform: translate(-50%, -50%);
	border-style: solid;
	border-width: 0.7rem 0 0.7rem 1.15rem;
	border-color: transparent transparent transparent var(--n-accent);
}

.video-facade__lien:hover .video-facade__jouer,
.video-facade__lien:focus-visible .video-facade__jouer {
	background: rgba(14, 14, 13, 0.82);
	transform: translate(-50%, -50%) scale(1.06);
}

.video-facade__intitule {
	position: relative;
	padding: var(--n-interligne, 1rem);
	font-family: var(--n-mono);
	font-size: var(--n-libelle);
	letter-spacing: var(--n-interlettre-libelle);
	text-transform: uppercase;
	color: var(--n-texte-doux);
	background: linear-gradient(transparent, rgba(11, 11, 10, 0.85));
}

.video-facade__lien:focus-visible {
	outline: 2px solid var(--n-accent);
	outline-offset: -2px;
}

/* Une fois le lecteur posé, la façade n'est plus qu'un cadre. */
.video-facade--ouverte iframe {
	display: block;
	width: 100%;
	height: 100%;
	border: 0;
}

@media (prefers-reduced-motion: reduce) {
	.video-facade__image,
	.video-facade__jouer {
		transition: none;
	}

	.video-facade__lien:hover .video-facade__jouer,
	.video-facade__lien:focus-visible .video-facade__jouer {
		transform: translate(-50%, -50%);
	}
}

.sam-spectacle__credits,
.sam-spectacle__galerie,
.sam-spectacle .sam-agenda__section,
.sam-spectacle__dossier {
	margin-top: var(--n-section);
}

/* La distribution nomme les instruments. C'est la source qui a évité qu'une
   kora devienne un djembé dans une description d'image : elle se lit, elle
   ne se relègue pas en bas de page en petits caractères. */
/* On lit d'abord qui, ensuite quoi. Le moteur émet forcément le rôle avant
   le nom — <dl> l'impose — alors la grille les remet dans l'ordre voulu :
   le nom en première colonne, le rôle en seconde.

   `dense` n'est pas décoratif. Sans lui, le placement automatique n'écrit
   que vers l'avant : le nom, assigné à la colonne 1 après un rôle déjà posé
   en colonne 2, sauterait à la ligne suivante et chaque paire se
   disloquerait. Avec lui, chaque élément retombe dans le premier trou libre
   de sa colonne, et les paires tiennent. Ne pas retirer ce mot. */
.sam-credits {
	display: grid;
	grid-auto-flow: row dense;
	grid-template-columns: max-content minmax(0, 1fr);
	gap: 0;
	margin: 0;
}

/* Les filets doivent rester d'un seul tenant d'une colonne à l'autre :
   c'est pourquoi on ne cale pas les lignes de base avec `align-items`, qui
   décalerait la boîte du rôle — son filet avec elle. Le rembourrage, lui,
   descend le texte sans toucher au filet. D'où ces deux valeurs hautes
   dissemblables : elles compensent l'écart d'ascendante entre le mono à
   11 px et la sans à 17 px. À revoir si l'une des deux polices change. */
.sam-credits__nom {
	grid-column: 1;
	margin: 0;
	padding: 0.85rem 2rem 0.85rem 0;
	border-top: 1px solid var(--n-filet-doux);
	font-size: 1.0625rem;
	color: var(--n-texte);
}

.sam-credits__role {
	grid-column: 2;
	padding: 1.15rem 0 0.85rem;
	border-top: 1px solid var(--n-filet-doux);
	font-family: var(--n-mono);
	font-size: var(--n-libelle);
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--n-texte-mineur);
}

.sam-galerie {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
	gap: 0.875rem;
}

.sam-galerie__element {
	margin: 0;
}

.sam-galerie__element img {
	display: block;
	width: 100%;
	aspect-ratio: 3 / 2;
	object-fit: cover;
}

.sam-spectacle__dossier a,
.sam-carte__lien {
	display: inline-block;
}

.sam-spectacle__dossier a {
	padding: 0.8125rem 1.375rem;
	border: 1px solid rgba(242, 239, 233, 0.35);
	font-size: 0.75rem;
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--n-texte);
}

.sam-spectacle__dossier a:hover {
	border-color: var(--n-accent);
	color: var(--n-accent);
}

/* --------------------------------------------------------------------------
   5. Liste des spectacles — .sam-spectacles__*, .sam-carte__*
   Elle doit tenir debout avec six cartes : la grille s'adapte au nombre.
   -------------------------------------------------------------------------- */

.sam-spectacles__description {
	max-width: 40rem;
	margin: 1.5rem 0 0;
	font-family: var(--n-texte-police);
	font-weight: 300;
	font-size: var(--n-corps);
	line-height: 1.6;
	color: var(--n-texte-doux);
	text-wrap: pretty;
}

/* Défilement horizontal, quatre cartes visibles. Pas de boucle : on bute aux
   deux extrémités, et les flèches disparaissent quand il n'y a plus rien de
   ce côté-là.

   Sans JavaScript, la bande reste défilable au doigt et au pavé tactile :
   les flèches sont un confort, pas la seule voie d'accès. */
.sam-spectacles__liste {
	--n-cartes: 4;
	--n-ecart: 1.125rem;

	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: calc(
		(100% - (var(--n-cartes) - 1) * var(--n-ecart)) / var(--n-cartes)
	);
	gap: var(--n-ecart);
	margin: var(--n-section) 0 0;
	padding: 0 0 0.5rem;
	list-style: none;

	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	scrollbar-width: none;
}

.sam-spectacles__liste::-webkit-scrollbar {
	display: none;
}

@media (max-width: 68rem) { .sam-spectacles__liste { --n-cartes: 3; } }
@media (max-width: 52rem) { .sam-spectacles__liste { --n-cartes: 2; } }
@media (max-width: 34rem) { .sam-spectacles__liste { --n-cartes: 1; } }

@media (prefers-reduced-motion: reduce) {
	.sam-spectacles__liste { scroll-behavior: auto; }
}

.sam-spectacles__liste > .sam-carte {
	scroll-snap-align: start;
}

/* --- Les flèches, ajoutées par carrousel.js -------------------------- */

.carrousel {
	position: relative;
}

.carrousel__fleche {
	position: absolute;
	top: 38%;
	z-index: 5;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 2.75rem;
	height: 2.75rem;
	padding: 0;
	border: 1px solid rgba(242, 239, 233, 0.35);
	background: color-mix(in srgb, var(--n-fond) 82%, transparent);
	backdrop-filter: blur(8px);
	color: var(--n-texte);
	font-family: var(--n-ui);
	font-size: 1rem;
	line-height: 1;
	cursor: pointer;
	transition: opacity 0.18s, border-color 0.18s, color 0.18s;
}

.carrousel__fleche:hover {
	border-color: var(--n-accent);
	color: var(--n-accent);
}

.carrousel__fleche--prec { left: -0.75rem; }
.carrousel__fleche--suiv { right: -0.75rem; }

/* Rien avant, rien après : la flèche s'efface et cesse d'être atteignable
   au clavier. « hidden » plutôt que « disabled » — une flèche grisée
   laisserait croire qu'il reste du contenu. */
.carrousel__fleche[hidden] {
	display: none;
}

@media (max-width: 34rem) {
	.carrousel__fleche { display: none; }
}

.sam-carte {
	display: flex;
	flex-direction: column;
	border: 1px solid var(--n-filet-doux);
}

.sam-carte:hover {
	border-color: var(--n-accent);
}

.sam-carte__lien {
	display: block;
	color: inherit;
}

.sam-carte__visuel img {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
}

.sam-carte__titre {
	display: block;
	padding: 1.375rem 1.375rem 0;
	font-size: var(--n-t3);
	line-height: 1.1;
}

.sam-carte__sous-titre {
	display: block;
	padding: 0.5rem 1.375rem 0;
	font-family: var(--n-texte-police);
	font-weight: 300;
	font-style: italic;
	font-size: 0.9375rem;
	color: var(--n-texte-discret);
}

.sam-carte__pitch {
	margin: 0.75rem 0 0;
	padding: 0 1.375rem;
	font-family: var(--n-texte-police);
	font-weight: 300;
	font-size: 0.9375rem;
	line-height: 1.5;
	color: var(--n-texte-discret);
	text-wrap: pretty;
}

.sam-carte__prochaine {
	margin: 1.125rem 0 0;
	padding: 0 1.375rem 1.375rem;
	font-family: var(--n-mono);
	font-size: 0.625rem;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--n-accent);
}

/* --------------------------------------------------------------------------
   6. Page de rédaction — .sam-redaction__*
   Réservée aux personnes connectées, mais elle mérite le même soin : c'est
   l'écran qu'Alain voit le plus souvent.
   -------------------------------------------------------------------------- */

.sam-redaction {
	max-width: 52rem;
	margin: 0 auto;
}

.sam-redaction__titre {
	margin: 0;
	font-size: var(--n-t2);
	line-height: 1;
}

.sam-redaction__note,
.sam-redaction__intro {
	max-width: 36rem;
	font-family: var(--n-texte-police);
	font-weight: 300;
	font-size: 1.0625rem;
	line-height: 1.6;
	color: var(--n-texte-discret);
	text-wrap: pretty;
}

.sam-redaction__retour,
.sam-redaction__raccourci {
	font-family: var(--n-mono);
	font-size: var(--n-libelle);
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

.sam-redaction__section + .sam-redaction__section {
	margin-top: var(--n-section);
}

.sam-redaction__section-titre {
	margin: 0 0 1rem;
	font-size: 1.75rem;
}

.sam-redaction__liste {
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Une ligne de la liste : le nom, puis les actions poussées à droite. Le
   bouton de bascule est un <form>, donc un bloc — sans « display:flex » sur
   le conteneur, il tomberait seul à la ligne. */
.sam-redaction__element {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.5rem 1.125rem;
	padding: 0.9375rem 0;
	border-top: 1px solid var(--n-filet);
}

.sam-redaction__lien {
	flex: 1 1 12rem;
	min-width: 0;
	font-size: 1.0625rem;
	font-weight: 500;
}

.sam-redaction__complement,
.sam-redaction__statut {
	font-family: var(--n-mono);
	font-size: 0.6875rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--n-texte-mineur);
}

.sam-redaction__element--brouillon .sam-redaction__lien {
	color: var(--n-texte-discret);
}

.sam-redaction__actions {
	display: flex;
	align-items: baseline;
	gap: 0.875rem;
	flex-wrap: wrap;
}

.sam-redaction__bascule {
	margin: 0;
}

/* Le bouton ressemble à un lien : publier n'est pas une action dangereuse,
   elle se défait d'un clic. */
.sam-redaction__bascule-bouton,
.sam-redaction__dupliquer,
.sam-redaction__voir {
	padding: 0;
	border: 0;
	background: none;
	font-family: var(--n-ui);
	font-size: 0.75rem;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--n-accent);
	cursor: pointer;
}

.sam-redaction__bascule-bouton:hover {
	color: var(--n-accent-survol);
}

.sam-redaction__ajouter {
	margin-top: 1.5rem;
}

.sam-redaction__ajouter a {
	display: inline-block;
	padding: 0.8125rem 1.375rem;
	background: var(--n-texte);
	color: var(--n-fond);
	font-size: 0.75rem;
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

.sam-redaction__ajouter a:hover {
	background: var(--n-accent);
	color: var(--n-fond);
}

.sam-redaction__message {
	padding: 1rem 1.25rem;
	border: 1px solid var(--n-accent);
	font-family: var(--n-mono);
	font-size: 0.75rem;
	letter-spacing: 0.06em;
	color: var(--n-accent);
}

.sam-redaction__separateur {
	margin: var(--n-section) 0;
	border: 0;
	border-top: 1px solid var(--n-filet);
}

/* --------------------------------------------------------------------------
   7. Articles et pages du thème — le repli d'index.php
   -------------------------------------------------------------------------- */

.article__titre {
	margin: 0 0 1.5rem;
	font-size: var(--n-t2);
	line-height: 1;
}

.article__contenu {
	max-width: 42rem;
	font-family: var(--n-texte-police);
	font-weight: 300;
	font-size: var(--n-corps);
	line-height: 1.65;
	color: var(--n-texte-doux);
	text-wrap: pretty;
}

.article__pages {
	margin-top: var(--n-section);
	font-family: var(--n-mono);
	font-size: var(--n-libelle);
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   8. Modales — boîte de contact, visionneuse de la galerie
   -------------------------------------------------------------------------- */

/* <dialog> apporte l'essentiel et gratuitement : la superposition, le piège à
   tabulation, la fermeture par Échap, le retour du focus là où on l'avait
   laissé. Il ne reste qu'à défaire son habillage de navigateur.

   Aucune règle `display` ici : le navigateur affiche un dialog ouvert et
   masque un dialog fermé, et lui forcer la main l'afficherait tout le temps.
   Les mises en page sont donc sous [open]. */
.modale,
.visionneuse {
	max-width: none;
	max-height: none;
	padding: 0;
	border: 0;
	background: transparent;
	color: var(--n-texte);
}

.modale::backdrop,
.visionneuse::backdrop {
	background: color-mix(in srgb, var(--n-fond) 88%, transparent);
	backdrop-filter: blur(6px);
}

/* La page ne défile plus derrière la boîte : autrement, la molette emporte
   ce qu'on ne regarde pas. */
body:has(dialog[open]) {
	overflow: hidden;
}

.modale__boite {
	position: relative;
	width: min(34rem, calc(100vw - 2 * var(--n-marge)));
	max-height: calc(100dvh - 3rem);
	overflow-y: auto;
	padding: clamp(1.75rem, 4vw, 2.75rem);
	background: var(--n-fond-pied);
	border: 1px solid var(--n-filet);
}

.modale__titre {
	margin: 0 0 1.75rem;
	font-size: var(--n-t3);
	line-height: 1.1;
	letter-spacing: -0.01em;
}

.modale__fermer,
.visionneuse__fermer {
	position: absolute;
	top: 0.375rem;
	right: 0.375rem;
	width: 2.75rem;
	height: 2.75rem;
	padding: 0;
	font-family: var(--n-ui);
	font-size: 1.5rem;
	line-height: 1;
	color: var(--n-texte-discret);
	background: none;
	border: 0;
	cursor: pointer;
}

.modale__fermer:hover,
.visionneuse__fermer:hover {
	color: var(--n-accent);
}

/* --- Le formulaire, rendu par le moteur ------------------------------- */

.sam-contact__champ {
	display: flex;
	flex-direction: column;
	gap: 0.4375rem;
	margin: 0 0 1.25rem;
}

.sam-contact__label {
	font-family: var(--n-mono);
	font-size: var(--n-libelle);
	letter-spacing: var(--n-interlettre-libelle);
	text-transform: uppercase;
	color: var(--n-texte-discret);
}

/* border-radius et appearance : sans eux, iOS arrondit les champs et leur
   pose un dégradé intérieur, seul endroit du site où il y aurait un angle
   mou. */
.sam-contact__saisie {
	width: 100%;
	padding: 0.75rem 0.875rem;
	font-family: var(--n-texte-police);
	font-weight: 300;
	font-size: 1rem;
	color: var(--n-texte);
	background: color-mix(in srgb, var(--n-texte) 5%, transparent);
	border: 1px solid var(--n-filet);
	border-radius: 0;
	-webkit-appearance: none;
	appearance: none;
}

.sam-contact__saisie:focus-visible {
	border-color: var(--n-accent);
	outline: 1px solid var(--n-accent);
	outline-offset: -2px;
}

.sam-contact__zone {
	min-height: 8rem;
	line-height: 1.55;
	resize: vertical;
}

.sam-contact__champ--erreur .sam-contact__saisie {
	border-color: var(--n-alerte);
}

.sam-contact__erreur {
	font-family: var(--n-ui);
	font-size: 0.8125rem;
	color: var(--n-alerte);
}

.sam-contact__avis {
	margin: 0 0 1.5rem;
	padding: 0.875rem 1rem;
	font-family: var(--n-texte-police);
	font-size: 1rem;
	color: var(--n-texte);
	background: color-mix(in srgb, var(--n-accent) 12%, transparent);
	border-left: 2px solid var(--n-accent);
}

.sam-contact__avis--erreur {
	background: color-mix(in srgb, var(--n-alerte) 12%, transparent);
	border-left-color: var(--n-alerte);
}

.sam-contact__actions {
	margin: 1.75rem 0 0;
}

.sam-contact__envoi {
	padding: 0.9375rem 1.75rem;
	font-family: var(--n-ui);
	font-size: 0.75rem;
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--n-fond);
	background: var(--n-accent);
	border: 1px solid var(--n-accent);
	cursor: pointer;
}

.sam-contact__envoi:hover {
	background: var(--n-accent-survol);
	border-color: var(--n-accent-survol);
}

/* --- La visionneuse, ajoutée par galerie.js --------------------------- */

/* Une grille de trois colonnes, et non une rangée souple : la colonne du
   milieu est déclarée `minmax(0, 1fr)`, ce qui l'autorise à devenir plus
   étroite que la photo qu'elle contient. En flex, une image garde pour
   largeur minimale sa taille intrinsèque — une photo en paysage poussait
   donc les flèches hors de l'écran.

   Deux rangées : la photo prend ce qui reste, la légende sa hauteur propre.
   Le `minmax(0, …)` de la première vaut pour la hauteur ce qu'il vaut pour
   la largeur — sans lui, une photo en portrait chasserait la légende. */
.visionneuse[open] {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;
	grid-template-rows: minmax(0, 1fr) auto;
	align-items: center;
	justify-items: center;
	gap: clamp(0.25rem, 2vw, 1.5rem);
	inset: 0;
	width: 100vw;
	height: 100dvh;
	margin: 0;
	padding: clamp(0.75rem, 4vw, 3rem);
}

.visionneuse__image {
	grid-column: 2;
	grid-row: 1;
	max-width: 100%;
	max-height: 100%;
	object-fit: contain;
}

.visionneuse__pas--precedent {
	grid-column: 1;
	grid-row: 1;
}

.visionneuse__pas--suivant {
	grid-column: 3;
	grid-row: 1;
}

/* La légende sous la photo, dans la colonne de la photo : alignée sur elle
   et jamais plus large que le regard ne peut suivre. */
.visionneuse__legende {
	grid-column: 2;
	grid-row: 2;
	max-width: 44rem;
	margin: 0;
	padding-top: 0.25rem;
	text-align: center;
	text-wrap: pretty;
}

.visionneuse__legende[hidden] {
	display: none;
}

.visionneuse__legende .sam-galerie__titre,
.visionneuse__legende .sam-galerie__description,
.visionneuse__legende .sam-galerie__credit {
	display: block;
}

.visionneuse__legende .sam-galerie__titre {
	font-family: var(--n-ui);
	font-size: 0.9375rem;
	font-weight: 500;
	letter-spacing: 0.02em;
	color: var(--n-texte);
}

.visionneuse__legende .sam-galerie__description {
	margin-top: 0.25rem;
	font-family: var(--n-texte-police);
	font-weight: 300;
	font-size: 1rem;
	line-height: 1.5;
	color: var(--n-texte-doux);
}

.visionneuse__legende .sam-galerie__credit {
	margin-top: 0.5rem;
	font-family: var(--n-mono);
	font-size: var(--n-libelle);
	letter-spacing: var(--n-interlettre-libelle);
	text-transform: uppercase;
	color: var(--n-texte-mineur);
}

.visionneuse__pas {
	flex: 0 0 auto;
	width: 3rem;
	height: 3rem;
	padding: 0;
	font-family: var(--n-ui);
	font-size: 1.75rem;
	line-height: 1;
	color: var(--n-texte-discret);
	background: none;
	border: 1px solid transparent;
	cursor: pointer;
}

.visionneuse__pas:hover {
	color: var(--n-texte);
	border-color: var(--n-filet);
}

.visionneuse__pas[hidden] {
	display: none;
}

/* Sous les vignettes, la légende ne s'affiche que si le script n'a pas pris
   la main : il la porte alors dans la visionneuse, et la mosaïque redevient
   une mosaïque. C'est galerie.js qui pose la classe. */
.sam-galerie--enrichie .sam-galerie__legende {
	display: none;
}

.sam-galerie__legende {
	margin-top: 0.5rem;
	font-family: var(--n-texte-police);
	font-weight: 300;
	font-size: 0.9375rem;
	line-height: 1.5;
	color: var(--n-texte-discret);
}

.sam-galerie__legende .sam-galerie__titre,
.sam-galerie__legende .sam-galerie__description,
.sam-galerie__legende .sam-galerie__credit {
	display: block;
}

.sam-galerie__legende .sam-galerie__credit {
	font-family: var(--n-mono);
	font-size: var(--n-libelle);
	letter-spacing: var(--n-interlettre-libelle);
	text-transform: uppercase;
	color: var(--n-texte-mineur);
}

/* La vignette annonce qu'elle s'ouvre. */
.sam-galerie__lien {
	display: block;
	cursor: zoom-in;
}

.sam-galerie__lien img {
	transition: opacity 0.2s;
}

.sam-galerie__lien:hover img {
	opacity: 0.82;
}
