/**
 * Advanced Photo Suite — styles publics.
 *
 * PHILOSOPHIE
 * -----------
 * Ce fichier ne définit AUCUNE couleur, police ou apparence de bouton en dur.
 * Il ne s'occupe que de mise en page (grille, positions, superpositions).
 *
 * Tout ce qui relève de l'apparence est délégué au thème actif :
 *   - les boutons portent la classe `wp-element-button`, stylée par theme.json ;
 *   - les couleurs proviennent des variables `--wp--preset--color--*` ;
 *   - les espacements de `--wp--preset--spacing--*` et `--wp--style--block-gap` ;
 *   - la typographie est simplement héritée (aucun font-family ici).
 *
 * Chaque `var()` possède une valeur de repli, pour que les thèmes classiques
 * dépourvus de theme.json restent parfaitement fonctionnels.
 *
 * Pour personnaliser sans toucher au plugin, redéfinissez les variables
 * `--aps-*` depuis le CSS additionnel de votre thème.
 */

/* --------------------------------------------------------------------------
   Variables — toutes rattachées au thème, avec repli neutre
   -------------------------------------------------------------------------- */

.aps-gallery {
	/* Espacements : suivent le rythme vertical du thème. */
	--aps-row-gap: var(--wp--style--block-gap, 1.5rem);
	--aps-block-gap: var(--wp--style--block-gap, 1.25rem);
	--aps-grid-gap: var(--wp--preset--spacing--20, 0.75rem);

	/* Couleurs : héritées du thème, jamais imposées. */
	--aps-fg: currentColor;
	--aps-muted-fg: currentColor;

	/* Surfaces translucides : fonctionnent sur fond clair comme sur fond sombre. */
	--aps-overlay-bg: rgba(0, 0, 0, 0.55);
	--aps-overlay-fg: #fff;
	--aps-scrim: rgba(0, 0, 0, 0.92);

	/* Rayon : reprend celui du thème s'il en définit un. */
	--aps-radius: var(--wp--custom--border-radius, 0px);

	/* Hauteur de rangée de la grille, pilotée par le réglage de la galerie. */
	--aps-row-height: 260px;
}

/* La hauteur de rangée est désormais portée par la grille elle-même,
   voir la section « Grille de photos » plus bas. */

/* --------------------------------------------------------------------------
   Structure — rangées et colonnes de la disposition
   -------------------------------------------------------------------------- */

/*
 * Notre conteneur interne occupe toujours toute la largeur du bloc.
 *
 * Les règles de mise en page du cœur de WordPress
 * (`:where(.is-layout-constrained) > *`) plafonnent tout enfant direct à la
 * largeur de contenu du thème et le centrent. Appliqué à `.aps-app`, cela
 * ramenait une galerie « large » à la largeur d'un paragraphe, entre deux
 * marges épaisses. On lève ce plafond sur nos conteneurs à nous, sans toucher
 * à ceux du thème.
 */
.aps-gallery > .aps-app {
	margin-inline: 0;
	max-width: none;
	width: auto;
}

.aps-row {
	display: grid;
	gap: var(--aps-block-gap);
	margin-block-end: var(--aps-row-gap);
}

.aps-row:last-child { margin-block-end: 0; }

.aps-row-cols-1 { grid-template-columns: 1fr; }
.aps-row-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.aps-row-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.aps-row-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 782px) {
	.aps-row-cols-2,
	.aps-row-cols-3,
	.aps-row-cols-4 { grid-template-columns: 1fr; }
}

.aps-col { min-width: 0; }

.aps-block + .aps-block { margin-block-start: var(--aps-block-gap); }

/* Alignements : on réutilise les classes de WordPress. */
.has-text-align-left   { text-align: left; }
.has-text-align-center { text-align: center; }
.has-text-align-right  { text-align: right; }

/* --------------------------------------------------------------------------
   Titre, métadonnées, image à la une
   -------------------------------------------------------------------------- */

/* Aucune taille ni couleur : `wp-block-post-title` est stylé par le thème. */
.aps-title { margin-block: 0 0.5em; }

.aps-meta { opacity: 0.8; }

.aps-expiry { margin-block: 0; opacity: 0.8; }

.aps-featured { margin: 0; }

.aps-featured img {
	display: block;
	height: auto;
	max-width: 100%;
	border-radius: var(--aps-featured-radius, var(--aps-radius));
}

.aps-featured.has-shadow img { box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15); }

.aps-featured-small  img { max-width: min(420px, 100%); margin-inline: auto; }
.aps-featured-medium img { max-width: min(780px, 100%); margin-inline: auto; }
.aps-featured-large  img { max-width: min(1100px, 100%); margin-inline: auto; }
.aps-featured-full   img { width: 100%; }

/* --------------------------------------------------------------------------
   Barre d'outils et filtres
   -------------------------------------------------------------------------- */

.aps-toolbar,
.aps-filters {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--aps-grid-gap);
}

/* --------------------------------------------------------------------------
   Interrupteur
   -------------------------------------------------------------------------- */

.aps-switch {
	align-items: center;
	cursor: pointer;
	display: inline-flex;
	gap: 0.55em;
	user-select: none;
}

/* La case reste présente pour le clavier et les lecteurs d'écran. */
.aps-switch input {
	block-size: 1px;
	inline-size: 1px;
	opacity: 0;
	position: absolute;
}

.aps-switch-track {
	background: color-mix(in srgb, currentColor 22%, transparent);
	border-radius: 999px;
	block-size: 22px;
	display: inline-block;
	flex: 0 0 auto;
	inline-size: 40px;
	position: relative;
	transition: background-color 0.2s ease;
}

.aps-switch-thumb {
	background: currentColor;
	border-radius: 50%;
	block-size: 16px;
	inline-size: 16px;
	inset-block-start: 3px;
	inset-inline-start: 3px;
	position: absolute;
	transition: transform 0.2s ease;
}

.aps-switch input:checked + .aps-switch-track {
	background: color-mix(in srgb, currentColor 55%, transparent);
}

.aps-switch input:checked + .aps-switch-track .aps-switch-thumb {
	transform: translateX(18px);
}

.aps-switch input:focus-visible + .aps-switch-track {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}

.aps-switch-count {
	background: color-mix(in srgb, currentColor 16%, transparent);
	border-radius: 999px;
	font-size: 0.8em;
	padding: 0.1em 0.55em;
}

.aps-switch-count[hidden] { display: none !important; }

/* --------------------------------------------------------------------------
   En-tête de galerie
   -------------------------------------------------------------------------- */

.aps-gallery-head {
	align-items: center;
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	justify-content: space-between;
	margin-block-end: 0.75rem;
}

.aps-head-start { margin-inline-end: auto; }
.aps-head-end { margin-inline-start: auto; }

/* Bouton compact : icône + libellé, pour ne pas alourdir le haut de grille. */
.aps-button-compact {
	align-items: center;
	display: inline-flex;
	gap: 0.45em;
}

.aps-button-compact .aps-icon { block-size: 1em; inline-size: 1em; }

/*
 * Appel du pack photo : intitulé et décompte dans un même bouton, pour que
 * le client sache ce qu'il lui reste sans rien ouvrir.
 */
.aps-trigger {
	align-items: center;
	display: inline-flex;
	gap: 0.55em;
}

.aps-trigger-count {
	background: color-mix(in srgb, currentColor 20%, transparent);
	border-radius: 999px;
	font-size: 0.85em;
	font-variant-numeric: tabular-nums;
	padding: 0.1em 0.6em;
}

.aps-trigger-count[hidden] { display: none !important; }

.aps-trigger[aria-expanded="true"] { outline: 2px solid currentColor; outline-offset: 2px; }

.aps-trigger[disabled] { cursor: not-allowed; opacity: 0.6; }

/* Barre de service : réglages invités et déconnexion. */
.aps-servicebar {
	align-items: center;
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
}

.aps-servicebar-message {
	flex-basis: 100%;
	margin: 0;
	border-inline-start: 3px solid currentColor;
	padding-inline-start: 0.7em;
	font-size: 0.92em;
}

.aps-servicebar-message[hidden] { display: none !important; }

.has-text-align-center .aps-toolbar,
.has-text-align-center .aps-filters { justify-content: center; }

.has-text-align-right .aps-toolbar,
.has-text-align-right .aps-filters { justify-content: flex-end; }

/*
 * Les filtres s'empilent en colonne (catégories, puis traitement).
 *
 * `flex-wrap: nowrap` est indispensable : en colonne, une enveloppe autorisée
 * fait naître une seconde colonne et la largeur de la rangée se cale alors sur
 * son contenu au lieu de celle du bloc. La rangée débordait au lieu de
 * défiler, ce qui écrasait la mise en page sur mobile.
 */
.aps-filters {
	align-items: stretch;
	flex-direction: column;
	flex-wrap: nowrap;
}

.aps-filter-row {
	display: flex;
	flex-wrap: wrap;
	gap: var(--aps-grid-gap);
	justify-content: inherit;
}

/*
 * Les boutons portent `wp-element-button` : leur fond, leur texte, leur rayon
 * et leurs états proviennent intégralement du thème. On n'ajuste ici que
 * l'état « actif » d'un filtre, en réutilisant les couleurs déjà en place.
 */
.aps-button { cursor: pointer; }

.aps-filter[aria-pressed="true"] {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}

/*
 * Couleur / Noir & blanc portent sur le traitement, pas sur le sujet :
 * on les présente en retrait des catégories, plus discrets et plus petits.
 */
.aps-filter-row-tone { margin-block-start: 0.15rem; }

.aps-filter-tone {
	font-size: 0.82em;
	opacity: 0.8;
	padding-block: 0.35em;
	padding-inline: 0.85em;
}

.aps-filter-tone[aria-pressed="true"] { opacity: 1; }

.aps-quota-info { opacity: 0.8; }

.aps-badge-role {
	border: 1px solid currentColor;
	border-radius: var(--aps-radius);
	opacity: 0.7;
	padding: 0.15em 0.6em;
}

.aps-logout {
	margin-inline-start: auto;
	opacity: 0.7;
}

/* --------------------------------------------------------------------------
   Formulaire d'accès
   -------------------------------------------------------------------------- */

.aps-gate {
	margin-inline: auto;
	max-width: min(420px, 100%);
	text-align: start;
}

.has-text-align-center .aps-gate { text-align: center; }

.aps-field { margin-block-end: 1rem; }

.aps-field label { display: block; margin-block-end: 0.35em; }

/*
 * Le champ hérite volontairement de la mise en forme des champs du thème.
 * On ne fixe que la largeur, pour éviter un champ minuscule sur mobile.
 */
.aps-input {
	box-sizing: border-box;
	max-width: 100%;
	width: 100%;
}

.aps-field-note { font-size: 0.875em; opacity: 0.7; }

.aps-error {
	border-inline-start: 3px solid currentColor;
	padding-inline-start: 0.75em;
}

/*
 * Présentation de la galerie. Aucune couleur ni police déclarée : le texte
 * hérite entièrement de la typographie du thème, comme le contenu d'une page.
 */
.aps-description > :first-child { margin-block-start: 0; }
.aps-description > :last-child { margin-block-end: 0; }

.aps-description img {
	height: auto;
	max-width: 100%;
}

/*
 * Boutons insérés dans la présentation.
 *
 * La classe `wp-element-button` porte déjà toute l'apparence, fournie par le
 * thème. On ne règle ici que ce qui relève de la mise en page : un lien reste
 * en ligne par défaut, il faut lui rendre ses marges de bouton.
 */
.aps-description .wp-element-button {
	display: inline-block;
	margin-block: 0.35em;
	text-decoration: none;
}

.aps-description .aps-buttons {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75em;
}

.aps-description .aps-buttons.has-text-align-center { justify-content: center; }
.aps-description .aps-buttons.has-text-align-right { justify-content: flex-end; }

/* Le bloc de présentation reste lisible même en pleine largeur. */
.aps-block-description .aps-description {
	margin-inline: auto;
	max-width: var(--wp--style--global--content-size, 65ch);
}

.has-text-align-center .aps-description { text-align: center; }
.has-text-align-right .aps-description { text-align: right; }

.aps-notice { text-align: center; }

.aps-empty { opacity: 0.7; text-align: center; }

/* --------------------------------------------------------------------------
   Grille de photos — quatre dispositions
   --------------------------------------------------------------------------

   data-grid="rows"    Mosaïque en lignes : proportions d'origine conservées,
                       lecture de gauche à droite. L'ordre chronologique reste
                       évident, ce qui compte pour un reportage.
   data-grid="columns" Mosaïque en colonnes : lecture de haut en bas.
   data-grid="grid"    Grille régulière : toutes les cellules au même format.
   data-grid="cards"   Grille régulière + bloc titre / légende.

   `--aps-gap`, `--aps-radius`, `--aps-cols`, `--aps-ratio`, `--aps-shadow`
   et les variables de bordure sont injectées par PHP depuis les réglages.
   -------------------------------------------------------------------------- */

.aps-grid {
	--aps-gap: var(--aps-grid-gap);
	--aps-cols: 3;
	--aps-ratio: 3 / 2;
	--aps-shadow: none;
}

.aps-item {
	margin: 0;
	position: relative;
}

/*
 * Masquage des photos filtrées.
 *
 * L'attribut `hidden` n'est appliqué que par la feuille de style du
 * navigateur : la moindre règle de thème posant un `display` sur `figure`
 * la neutralise, et les photos filtrées restaient visibles. On réaffirme
 * donc le masquage depuis notre propre feuille.
 */
.aps-item[hidden],
.aps-grid .aps-item[hidden] {
	display: none !important;
}

.aps-thumb {
	display: block;
	/* Neutralise les décorations de lien du thème sur une vignette. */
	box-shadow: none;
	text-decoration: none;
}

.aps-item img {
	display: block;
	width: 100%;
	border-radius: var(--aps-radius);
	box-shadow: var(--aps-shadow);
}

/*
 * Bordures et ombres — uniquement sur l'image.
 *
 * Les conteneurs sont explicitement remis à zéro : les variables de bordure
 * étant héritées par tous les descendants, un thème utilisant les mêmes noms
 * dessinait un cadre autour du bloc entier.
 */
.aps-gallery,
.aps-app,
.aps-grid,
.aps-item,
.aps-thumb {
	border: 0;
	box-shadow: none;
}

.aps-grid[data-border="light"] .aps-item img,
.aps-grid[data-border="dark"] .aps-item img,
.aps-grid[data-border="custom"] .aps-item img {
	border: var(--aps-border-width, 1px) solid var(--aps-border-color, #fff);
}

/* --- Mosaïque en lignes ---------------------------------------------------- */

/*
 * Mosaïque justifiée : chaque vignette occupe une largeur proportionnelle à
 * ses propres proportions (`--aps-ar`, fourni par PHP). Toutes les photos
 * d'une même ligne atteignent ainsi la hauteur de rangée SANS recadrage :
 * un portrait devient étroit, un panoramique devient large.
 *
 * `flex-basis` donne la largeur idéale, `flex-grow` répartit l'espace restant
 * dans la même proportion — c'est ce qui préserve le cadrage d'origine.
 */
.aps-grid[data-grid="rows"] {
	display: flex;
	flex-wrap: wrap;
	gap: var(--aps-gap);
}

/*
 * Repli sans JavaScript : largeur EXACTEMENT proportionnelle aux
 * proportions d'origine (`--aps-ar`, fourni par PHP), sans étirement.
 * Aucun recadrage, au prix d'un bord droit irrégulier.
 *
 * Pourquoi ne pas justifier en CSS pur ? Parce que la hauteur d'une ligne
 * dépend de la somme des proportions des photos qui y tombent, et flexbox
 * n'expose pas ses retours à la ligne. Avec `flex-grow`, la ligne s'élargit
 * sans grandir en hauteur : les images deviennent plus larges que leur ratio
 * réel, et c'est précisément ce qui produisait le recadrage.
 *
 * Le script prend ensuite le relais pour justifier chaque ligne (voir
 * `justifyRows` dans gallery.js) : il calcule la hauteur exacte de la ligne
 * et pose des dimensions en pixels. Les proportions restent intactes.
 */
.aps-grid[data-grid="rows"] .aps-item {
	flex: 0 0 auto;
	height: var(--aps-row-height);
	width: calc(var(--aps-ar, 1.5) * var(--aps-row-height));
	max-width: 100%;
}

.aps-grid[data-grid="rows"] .aps-thumb { height: 100%; }

.aps-grid[data-grid="rows"] .aps-item img {
	height: 100%;
	object-fit: cover;
}

/*
 * Une fois la ligne justifiée, les dimensions viennent du style en ligne.
 * `max-width` doit être levé : le script pose déjà des largeurs qui tiennent
 * dans le conteneur, et le plafond hérité écrasait la largeur sans toucher à
 * la hauteur — c'est-à-dire qu'il recadrait la photo.
 */
.aps-grid[data-grid="rows"].is-justified .aps-item {
	height: auto;
	max-width: none;
	width: auto;
}

.aps-grid[data-row-size="small"]  { --aps-row-height: 180px; }
.aps-grid[data-row-size="medium"] { --aps-row-height: 260px; }
.aps-grid[data-row-size="large"]  { --aps-row-height: 380px; }

@media (max-width: 600px) {
	.aps-grid[data-grid="rows"]:not(.is-justified) .aps-item {
		height: auto;
		width: 100%;
	}

	.aps-grid[data-grid="rows"]:not(.is-justified) .aps-item img {
		height: auto;
		object-fit: contain;
	}
}

/* --- Mosaïque en colonnes -------------------------------------------------- */

/*
 * `columns` laisse chaque photo à ses proportions naturelles. Les éléments
 * ne doivent pas être coupés entre deux colonnes.
 */
.aps-grid[data-grid="columns"] {
	column-count: var(--aps-cols);
	column-gap: var(--aps-gap);
	display: block;
}

.aps-grid[data-grid="columns"] .aps-item:not([hidden]) {
	break-inside: avoid;
	display: inline-block;
	margin-block-end: var(--aps-gap);
	width: 100%;
}

.aps-grid[data-grid="columns"] .aps-item img { height: auto; }

@media (max-width: 900px) {
	.aps-grid[data-grid="columns"] { column-count: min(var(--aps-cols), 2); }
}

@media (max-width: 600px) {
	.aps-grid[data-grid="columns"] { column-count: 1; }
}

/* --- Grille régulière et cartes -------------------------------------------- */

/*
 * Souple plutôt que grille CSS : avec des colonnes en fractions, une ligne
 * incomplète laisse toujours ses vignettes calées à gauche, sans possibilité
 * de les centrer. En flex, la largeur d'une vignette est calculée pour
 * reproduire exactement la même grille, mais `justify-content` reprend la
 * main dès qu'une ligne n'est pas pleine.
 */
.aps-grid[data-grid="grid"],
.aps-grid[data-grid="cards"] {
	display: flex;
	flex-wrap: wrap;
	gap: var(--aps-gap);
	justify-content: var(--aps-justify, flex-start);
}

.aps-grid[data-grid="grid"] .aps-item,
.aps-grid[data-grid="cards"] .aps-item {
	flex: 0 0 calc((100% - (var(--aps-cols) - 1) * var(--aps-gap)) / var(--aps-cols));
	max-width: calc((100% - (var(--aps-cols) - 1) * var(--aps-gap)) / var(--aps-cols));
}

.aps-grid[data-grid="grid"] .aps-item img,
.aps-grid[data-grid="cards"] .aps-item img {
	aspect-ratio: var(--aps-ratio);
	height: auto;
	object-fit: cover;
}

@media (max-width: 900px) {
	.aps-grid[data-grid="grid"] .aps-item,
	.aps-grid[data-grid="cards"] .aps-item {
		--aps-cols: 2;
	}
}

@media (max-width: 600px) {
	.aps-grid[data-grid="grid"] .aps-item,
	.aps-grid[data-grid="cards"] .aps-item {
		--aps-cols: 1;
	}
}

/* --- Alignement des lignes incomplètes -------------------------------------- */

.aps-grid[data-align="left"]   { --aps-justify: flex-start; }
.aps-grid[data-align="center"] { --aps-justify: center; }
.aps-grid[data-align="right"]  { --aps-justify: flex-end; }

.aps-grid[data-grid="rows"] { justify-content: var(--aps-justify, flex-start); }

/* En colonnes, c'est le flux typographique qui gouverne : on centre le bloc. */
.aps-grid[data-grid="columns"][data-align="center"] { margin-inline: auto; }

/* --- Contenu des cartes ---------------------------------------------------- */

.aps-card-body {
	display: flex;
	flex-direction: column;
	gap: 0.15em;
	padding: var(--aps-card-padding, 12px) calc(var(--aps-card-padding, 12px) / 2);
}

.aps-card-caption { font-size: 0.875em; opacity: 0.75; }

/*
 * Fond de carte : teintes neutres translucides, lisibles aussi bien sur un
 * thème clair que sombre, sans imposer de couleur de marque.
 */
.aps-grid[data-card-bg="light"] .aps-item,
.aps-grid[data-card-bg="dark"] .aps-item {
	border-radius: var(--aps-radius);
	overflow: hidden;
}

.aps-grid[data-card-bg="light"] .aps-item { background: rgba(255, 255, 255, 0.08); }
.aps-grid[data-card-bg="dark"] .aps-item { background: rgba(0, 0, 0, 0.06); }

.aps-grid[data-card-bg="light"] .aps-item img,
.aps-grid[data-card-bg="dark"] .aps-item img { border-radius: 0; }

/* --- Effets au survol ------------------------------------------------------ */

.aps-grid[data-hover]:not([data-hover="none"]) .aps-thumb {
	display: block;
	overflow: hidden;
	border-radius: var(--aps-radius);
}

.aps-grid[data-hover]:not([data-hover="none"]) .aps-item img {
	transition: transform 0.35s ease, opacity 0.25s ease, filter 0.25s ease;
}

.aps-grid[data-hover="zoom"] .aps-item:hover img { transform: scale(1.05); }

.aps-grid[data-hover="lift"] .aps-item {
	transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.aps-grid[data-hover="lift"] .aps-item:hover { transform: translateY(-4px); }

.aps-grid[data-hover="fade"] .aps-item:hover img { opacity: 0.75; }

.aps-grid[data-hover="reveal"] .aps-item:hover img { filter: brightness(0.72); }

/* --- États ----------------------------------------------------------------- */

/* --- Réorganisation animée au filtrage -------------------------------------- */

/*
 * La classe est posée par le script juste avant de relâcher la vignette vers
 * sa nouvelle position ; la durée reste courte pour que le filtrage garde
 * l'impression d'être immédiat.
 */
.aps-item.is-reflowing {
	transition: transform 380ms cubic-bezier(0.22, 0.61, 0.36, 1);
	will-change: transform;
}

.aps-item.is-appearing {
	animation: aps-appear 320ms ease both;
}

@keyframes aps-appear {
	from { opacity: 0; transform: scale(0.94); }
	to   { opacity: 1; transform: scale(1); }
}

/*
 * Photo masquée pour les invités.
 *
 * Un repère d'angle plutôt qu'un grisage : le client garde une galerie
 * parfaitement lisible tout en repérant d'un coup d'œil ce qu'il a soustrait
 * à ses invités. La pastille reste discrète mais lisible sur n'importe quelle
 * photo grâce à son propre fond.
 */
.aps-hidden-badge {
	align-items: center;
	background: var(--aps-overlay-bg);
	border-radius: 999px;
	color: var(--aps-overlay-fg);
	display: flex;
	inset-block-end: 8px;
	inset-inline-end: 8px;
	justify-content: center;
	padding: 5px;
	pointer-events: none;
	position: absolute;
	z-index: 2;
}

.aps-hidden-badge[hidden] { display: none !important; }

/* En configuration invités, le repère s'affirme : c'est le sujet du moment. */
.aps-app[data-mode="guests"] .aps-item.is-hidden-guest img { opacity: 0.55; }
.aps-app[data-mode="guests"] .aps-hidden-badge { padding: 7px; }

.aps-item.is-picked { outline: 3px solid currentColor; outline-offset: 2px; }

/* --------------------------------------------------------------------------
   Commandes superposées aux vignettes
   -------------------------------------------------------------------------- */

/*
 * Ces boutons flottent sur la photo : ils ont besoin d'un contraste garanti
 * quel que soit le cliché. C'est le seul endroit où une couleur est fixée,
 * et elle reste surchargeable via --aps-overlay-bg / --aps-overlay-fg.
 */
.aps-icon-button {
	align-items: center;
	background: var(--aps-overlay-bg);
	border: 0;
	border-radius: 999px;
	color: var(--aps-overlay-fg);
	cursor: pointer;
	display: flex;
	height: 34px;
	inset-block-start: 8px;
	inset-inline-end: 8px;
	justify-content: center;
	opacity: 0;
	position: absolute;
	transition: opacity 0.15s ease;
	width: 34px;
}

.aps-item:hover .aps-icon-button,
.aps-item:focus-within .aps-icon-button { opacity: 1; }

.aps-icon-button:focus-visible { opacity: 1; outline: 2px solid var(--aps-overlay-fg); }

.aps-pick-wrap {
	inset-block-start: 8px;
	inset-inline-start: 8px;
	position: absolute;
	z-index: 2;
}

.aps-pick { cursor: pointer; height: 22px; width: 22px; }

.aps-visibility {
	inset-block-end: 8px;
	inset-inline-start: 8px;
	position: absolute;
	z-index: 2;
}

/* En mode configuration invités, on inverse les commandes affichées. */
.aps-app[data-mode="guests"] .aps-dl-one { display: none; }
.aps-app[data-mode="mine"] .aps-visibility { display: none; }

/* Protection contre le glisser-déposer. */
.aps-protected img { -webkit-user-drag: none; user-select: none; }

/* --------------------------------------------------------------------------
   Console de sélection — fixée à l'écran
   --------------------------------------------------------------------------
   Elle accompagne le client pendant qu'il choisit ses photos : décompte,
   jauge, tri de la sélection et actions restent visibles quel que soit le
   défilement.

   C'est une surface flottante : à la différence du reste du plugin, elle a
   besoin d'un fond opaque garanti. On emprunte les couleurs du thème quand
   il les expose (`base` / `contrast`, conventions des thèmes de blocs) avec
   un repli neutre, et tout reste redéfinissable via les variables `--aps-*`.
   -------------------------------------------------------------------------- */

.aps-console {
	--aps-console-bg: var(--wp--preset--color--base, #fff);
	--aps-console-fg: var(--wp--preset--color--contrast, #16181c);

	background: var(--aps-console-bg);
	border-radius: calc(var(--aps-radius) + 10px);
	bottom: max(1rem, env(safe-area-inset-bottom));
	box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.10), 0 12px 40px rgba(0, 0, 0, 0.22);
	color: var(--aps-console-fg);
	inset-inline: 1rem;
	margin-inline: auto;
	max-width: 720px;
	opacity: 0;
	position: fixed;
	transform: translateY(1rem);
	transition: opacity 0.22s ease, transform 0.22s ease;
	z-index: 9999;
}

.aps-console.is-visible { opacity: 1; transform: translateY(0); }

.aps-console[hidden] { display: none !important; }

.aps-console-inner {
	display: grid;
	gap: 0.85rem 1.25rem;
	grid-template-areas:
		"status only"
		"actions actions"
		"message message";
	grid-template-columns: minmax(0, 1fr) auto;
	padding: 1rem 1.25rem;
}

@media (max-width: 600px) {
	.aps-console-inner {
		grid-template-areas: "status" "only" "actions" "message";
		grid-template-columns: 1fr;
	}
}

.aps-console-status { grid-area: status; }

.aps-console-count {
	font-variant-numeric: tabular-nums;
	font-weight: 600;
	margin: 0 0 0.4rem;
}

.aps-console.is-confirming .aps-console-count { font-weight: 700; }

/* Jauge : apparence native neutralisée, très variable d'un navigateur à l'autre. */
.aps-console-meter {
	appearance: none;
	background: color-mix(in srgb, currentColor 14%, transparent);
	block-size: 6px;
	border: 0;
	border-radius: 999px;
	inline-size: 100%;
}

.aps-console-meter::-webkit-progress-bar {
	background: color-mix(in srgb, currentColor 14%, transparent);
	border-radius: 999px;
}

.aps-console-meter::-webkit-progress-value {
	background: currentColor;
	border-radius: 999px;
	opacity: 0.8;
	transition: inline-size 0.25s ease;
}

.aps-console-meter::-moz-progress-bar {
	background: currentColor;
	border-radius: 999px;
	opacity: 0.8;
}

.aps-console-only { grid-area: only; align-self: center; }

.aps-console-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	grid-area: actions;
	justify-content: flex-end;
}

@media (max-width: 600px) {
	.aps-console-actions { justify-content: stretch; }
	.aps-console-actions .aps-button { flex: 1 1 auto; }
}

.aps-console-actions .aps-button[disabled] { cursor: not-allowed; opacity: 0.45; }

.aps-console-message {
	border-inline-start: 3px solid currentColor;
	font-size: 0.92em;
	grid-area: message;
	margin: 0;
	padding-inline-start: 0.7em;
}

.aps-console-message[hidden] { display: none !important; }
.aps-console-message[data-tone="error"] { font-weight: 600; }
.aps-console-message[data-tone="success"],
.aps-console-message[data-tone="info"] { opacity: 0.8; }

/* Dégage le bas de page pour que la console ne masque pas les dernières photos. */
body.aps-console-open { padding-block-end: 9rem; }

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

/* --------------------------------------------------------------------------
   Visionneuse
   -------------------------------------------------------------------------- */

/*
 * `--aps-lb-scrim` et `--aps-lb-speed` sont posées par le script d'après les
 * réglages de la galerie (couleur, opacité, durée).
 */
.aps-lightbox {
	--aps-lb-scrim: rgba(0, 0, 0, 0.92);
	--aps-lb-speed: 300ms;

	align-items: center;
	background: var(--aps-lb-scrim);
	display: none;
	flex-direction: column;
	inset: 0;
	justify-content: center;
	position: fixed;
	z-index: 100000;
}

.aps-lightbox.is-open { display: flex; }

/*
 * Fermeture : on réaffirme le masquage de trois façons.
 *
 * Une couche invisible mais toujours cliquable restait sur la page après
 * fermeture, bloquant toute navigation. L'attribut `hidden` seul ne suffit
 * pas (il vient de la feuille du navigateur, que la moindre règle de thème
 * neutralise), d'où la classe ET l'attribut ET la neutralisation des
 * événements.
 */
.aps-lightbox[hidden],
.aps-lightbox:not(.is-open) {
	display: none !important;
	pointer-events: none !important;
	visibility: hidden !important;
}

.aps-lb-frame {
	align-items: center;
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
	margin: 0;
	max-height: 94vh;
}

.aps-lb-stage {
	max-height: 88vh;
	max-width: 92vw;
	position: relative;
}

.aps-lb-stage img {
	display: block;
	max-height: 84vh;
	max-width: 92vw;
	object-fit: contain;
}

/* --- Transitions d'une photo à l'autre ------------------------------------- */

.aps-lightbox[data-transition="fade"] .aps-lb-stage img.is-entering {
	animation: aps-lb-fade var(--aps-lb-speed) ease both;
}

.aps-lightbox[data-transition="zoom"] .aps-lb-stage img.is-entering {
	animation: aps-lb-zoom var(--aps-lb-speed) ease both;
}

.aps-lightbox[data-transition="slide"] .aps-lb-stage img.is-entering.from-right {
	animation: aps-lb-slide-right var(--aps-lb-speed) ease both;
}

.aps-lightbox[data-transition="slide"] .aps-lb-stage img.is-entering.from-left {
	animation: aps-lb-slide-left var(--aps-lb-speed) ease both;
}

@keyframes aps-lb-fade {
	from { opacity: 0; }
	to   { opacity: 1; }
}

@keyframes aps-lb-zoom {
	from { opacity: 0; transform: scale(0.86); }
	to   { opacity: 1; transform: scale(1); }
}

/* Amplitude franche : à 6 % le glissement se confondait avec un fondu. */
@keyframes aps-lb-slide-right {
	from { opacity: 0; transform: translateX(18%); }
	to   { opacity: 1; transform: translateX(0); }
}

@keyframes aps-lb-slide-left {
	from { opacity: 0; transform: translateX(-18%); }
	to   { opacity: 1; transform: translateX(0); }
}

/*
 * Commandes de la visionneuse.
 *
 * La visionneuse est injectée à la racine du document, hors du conteneur de
 * la galerie : elle ne peut hériter d'aucune variable de couleur, et elle ne
 * doit surtout pas hériter de celles du thème — un thème clair donnerait des
 * commandes sombres sur un fond noir, donc invisibles.
 *
 * Le contraste est donc décidé ici, d'après `data-ui` calculé côté serveur
 * à partir de la couleur de fond retenue.
 */
.aps-lightbox {
	--aps-lb-fg: #fff;
	--aps-lb-btn: rgba(255, 255, 255, 0.14);
	--aps-lb-btn-hover: rgba(255, 255, 255, 0.28);
}

.aps-lightbox[data-ui="on-light"] {
	--aps-lb-fg: #111;
	--aps-lb-btn: rgba(0, 0, 0, 0.10);
	--aps-lb-btn-hover: rgba(0, 0, 0, 0.20);
}

.aps-lightbox button {
	align-items: center;
	background: var(--aps-lb-btn);
	border: 0;
	border-radius: 999px;
	color: var(--aps-lb-fg);
	cursor: pointer;
	display: flex;
	height: 46px;
	justify-content: center;
	padding: 0;
	position: absolute;
	transition: background-color 0.15s ease, transform 0.15s ease;
	width: 46px;
}

.aps-lightbox button:hover { background: var(--aps-lb-btn-hover); }

.aps-lightbox button:focus-visible {
	outline: 2px solid var(--aps-lb-fg);
	outline-offset: 2px;
}

.aps-lightbox .aps-icon { pointer-events: none; }

/* Les commandes du haut sont regroupées, ce qui évite de les positionner
   une par une et garde l'espacement cohérent. */
.aps-lb-controls {
	display: flex;
	gap: 10px;
	inset-block-start: 16px;
	inset-inline-end: 16px;
	position: absolute;
	z-index: 2;
}

.aps-lb-controls button { position: static; }

/*
 * Les flèches sont écrites AVANT la photo dans le document, et la scène
 * (`.aps-lb-stage`) est positionnée : elle passait donc systématiquement
 * par-dessus. Sur grand écran la photo laisse des marges, le défaut ne se
 * voyait pas ; sur mobile elle occupe toute la largeur et les flèches
 * devenaient inatteignables. Un plan explicite règle le problème.
 */
.aps-lb-prev,
.aps-lb-next {
	inset-block-start: 50%;
	transform: translateY(-50%);
	z-index: 3;
}

.aps-lb-prev { inset-inline-start: 16px; }
.aps-lb-next { inset-inline-end: 16px; }

.aps-lb-prev:hover,
.aps-lb-next:hover { transform: translateY(-50%) scale(1.08); }

@media (max-width: 600px) {
	.aps-lightbox button { height: 40px; width: 40px; }
	.aps-lb-controls { gap: 6px; }

	/*
	 * Écran tactile : les flèches se posent sur la photo. On les rend
	 * discrètes et on les colle aux bords — le geste de glissement et
	 * l'appui sur les moitiés gauche/droite restent les commandes
	 * principales (voir initLightbox dans gallery.js).
	 */
	.aps-lb-prev { inset-inline-start: 6px; }
	.aps-lb-next { inset-inline-end: 6px; }
}

.aps-lb-caption,
.aps-lb-counter {
	color: var(--aps-lb-fg);
	margin: 0;
	opacity: 0.85;
	padding-inline: 1rem;
	text-align: center;
}

.aps-lb-caption {
	margin-inline: auto;
	max-width: 80ch;
}

/*
 * Compteur centré : `inset-inline: 0` seul le laissait calé à gauche dès
 * qu'une largeur maximale s'appliquait. On le centre explicitement.
 */
.aps-lb-counter {
	inset-block-end: 16px;
	inset-inline: 0;
	margin-inline: auto;
	position: absolute;
	width: fit-content;
}

.aps-lb-caption[hidden],
.aps-lb-counter[hidden] { display: none !important; }

.aps-lb-watermark {
	/* Suit le contraste des commandes plutôt que celui du thème.
	   La première valeur sert de repli aux navigateurs sans color-mix(). */
	color: rgba(255, 255, 255, 0.28);
	color: color-mix(in srgb, var(--aps-lb-fg) 30%, transparent);
	font-size: clamp(18px, 4vw, 42px);
	inset: 0;
	align-items: center;
	display: flex;
	justify-content: center;
	pointer-events: none;
	position: absolute;
	user-select: none;
}

/* --------------------------------------------------------------------------
   Accessibilité et préférences système
   -------------------------------------------------------------------------- */

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

	/* Les transitions de la visionneuse sont neutralisées, quel que soit le
	   réglage choisi : la préférence du visiteur prime. */
	.aps-lb-stage img.is-entering { animation: none !important; }

	.aps-grid[data-hover] .aps-item,
	.aps-grid[data-hover] .aps-item img { transition: none !important; }

	.aps-grid[data-hover="zoom"] .aps-item:hover img,
	.aps-grid[data-hover="lift"] .aps-item:hover { transform: none; }

	.aps-item.is-reflowing { transition: none !important; }
	.aps-item.is-appearing { animation: none !important; }
}

/* Sur écran tactile, les commandes restent visibles (pas de survol). */
@media (hover: none) {
	.aps-icon-button { opacity: 1; }
}

/* --------------------------------------------------------------------------
   Écrans étroits — galeries
   --------------------------------------------------------------------------

   Deux corrections indépendantes du thème :

   1. Largeur utile. Le bloc galerie est posé dans le conteneur du thème, qui
      applique déjà ses marges internes et sa largeur de contenu. Certains
      thèmes les appliquent une seconde fois à nos conteneurs intermédiaires
      (règles de mise en page « constrained » du cœur de WordPress, marges
      globales) : la grille se retrouvait enserrée entre deux marges épaisses
      et ne disposait plus d'assez de place pour organiser les vignettes.
      On neutralise ces héritages sur nos propres conteneurs uniquement.

   2. Filtres. Voir plus bas : bande défilante plutôt qu'empilement.
   -------------------------------------------------------------------------- */

@media (max-width: 782px) {
	.aps-gallery > .aps-app,
	.aps-gallery .aps-row,
	.aps-gallery .aps-col,
	.aps-gallery .aps-grid {
		max-width: none;
		width: auto;
	}

	/* Le conteneur du thème fournit déjà la marge latérale. */
	.aps-gallery > .aps-app { margin-inline: 0; }
}

/* --------------------------------------------------------------------------
   Écrans étroits — confort tactile
   --------------------------------------------------------------------------

   Les commandes de la console et de l'en-tête de galerie passent à 42 px de
   haut : c'est la taille minimale confortable pour un doigt. Sur la console,
   les actions se répartissent sur toute la largeur plutôt que de s'aligner en
   une ligne trop serrée.
   -------------------------------------------------------------------------- */

@media (max-width: 600px) {
	.aps-console button,
	.aps-servicebar button,
	.aps-gallery-head .aps-button,
	.aps-trigger {
		min-height: 42px;
	}

	.aps-console-actions {
		display: flex;
		flex-wrap: wrap;
		gap: 0.5rem;
	}

	.aps-console-actions button { flex: 1 1 8rem; }

	.aps-trigger {
		justify-content: center;
		width: 100%;
	}

	/* L'en-tête passe en colonne : le bouton du pack mérite toute la largeur. */
	.aps-gallery-head {
		align-items: stretch;
		flex-direction: column;
	}

	.aps-head-start,
	.aps-head-end { width: 100%; }
}

/* --------------------------------------------------------------------------
   Filtres — boutons sur écran large, menu déroulant sur mobile
   --------------------------------------------------------------------------

   Les deux présentations du filtre de catégorie sont présentes dans la page ;
   une seule est visible à la fois, et le script les tient synchronisées (voir
   initFilters dans gallery.js). Couleur et noir & blanc restent des boutons
   dans les deux cas : ils se cumulent avec la catégorie.
   -------------------------------------------------------------------------- */

.aps-filter-select {
	align-items: center;
	display: none;
	gap: 0.6em;
	margin: 0;
}

.aps-filter-select label { white-space: nowrap; }

.aps-select-shell {
	display: inline-flex;
	flex: 1 1 auto;
	position: relative;
}

/*
 * Le menu reprend la typographie et la couleur du thème ; seul le cadre est
 * dessiné ici, en `currentColor`, pour rester lisible sur fond clair comme
 * sur fond sombre.
 */
.aps-filter-menu {
	-webkit-appearance: none;
	appearance: none;
	background: transparent;
	border: 1px solid currentColor;
	border-radius: 999px;
	color: inherit;
	cursor: pointer;
	font: inherit;
	min-height: 44px;
	padding-block: 0.5em;
	padding-inline: 1em 2.6em;
	width: 100%;
}

.aps-filter-menu:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}

/* Chevron dessiné en CSS : aucune image, aucune couleur imposée. */
.aps-select-shell::after {
	border-block-end: 2px solid currentColor;
	border-inline-end: 2px solid currentColor;
	content: "";
	height: 0.5em;
	inset-block-start: calc(50% - 0.4em);
	inset-inline-end: 1.15em;
	pointer-events: none;
	position: absolute;
	transform: rotate(45deg);
	width: 0.5em;
}

@media (max-width: 782px) {
	/* Le menu remplace la rangée de boutons et son « Tout afficher ». */
	.aps-filter-all,
	.aps-filter-row-cats { display: none; }

	.aps-filter-select { display: flex; }

	.aps-filter-row-tone .aps-filter-tone {
		border-radius: 999px;
		font-size: 0.85em;
		min-height: 40px;
		padding-inline: 1.1em;
	}
}

/* --------------------------------------------------------------------------
   Marges latérales maîtrisées
   --------------------------------------------------------------------------

   Réglage « Marges » de la page Disposition. Le bloc s'affranchit du
   conteneur du thème et occupe toute la largeur de la fenêtre ; la marge
   choisie est ensuite appliquée sur le conteneur interne, dont le bloc de
   référence est justement cette pleine largeur — un pourcentage posé sur le
   bloc extérieur se serait calculé sur la largeur du thème, pas sur celle de
   l'écran.

   `--aps-viewport` est posée par le script : `100vw` inclut la barre de
   défilement et déborderait sur ordinateur. La valeur de repli reste `100vw`
   si le script n'a pas encore tourné.
   -------------------------------------------------------------------------- */

.aps-gallery.aps-has-margins {
	margin-inline: calc(50% - var(--aps-viewport, 100vw) / 2);
	max-width: none;
	width: var(--aps-viewport, 100vw);
}

.aps-gallery.aps-has-margins > .aps-app {
	box-sizing: border-box;
	padding-inline: var(--aps-side-margin, 0%);
}
