/* =============================================================================
 *  Socle visuel — identique d'une église à l'autre.
 *  Les couleurs et les rythmes sont pilotés par les variables ci-dessous.
 * ========================================================================== */

:root {
	--slate:        #2f3b4a;   /* bandeau de titre, texte fort */
	--slate-soft:   #45566b;
	--accent:       #405ca3;   /* bleu des pastilles, liens */
	--paper:        #faf8f5;   /* fond de la fiche */
	--ink:          #23262b;   /* texte courant */
	--ink-soft:     #6b7280;   /* légendes */
	--rule:         rgba(47, 59, 74, .14);

	--radius:       14px;

	/* Zone réservée en haut à gauche à la croix « quitter » que l'app native dessine
	 * PAR-DESSUS la page : rien de lisible ne doit s'y trouver. Largeur mesurée
	 * depuis le bord gauche de l'écran. */
	--native-close-zone: 60px;
	--shadow:       0 18px 45px rgba(0, 0, 0, .35);

	/* Marge latérale de la fiche : respire sur mobile, se cale sur grand écran */
	--gutter:       clamp(18px, 6vw, 56px);
	--text:         clamp(16px, 4.1vw, 19px);
	--text-title:   clamp(21px, 5.4vw, 27px);
}

/* Chiffres des pastilles. Police choisie pour ses chiffres ALIGNÉS (lining
 * figures) : ne pas la remplacer par Georgia, Palatino ou IM Fell, dont les
 * chiffres elzéviriens paraissent décentrés (cf. CLAUDE.md). */
@font-face {
	font-family: "Libre Baskerville";
	src: url("fonts/LibreBaskerville-Bold.ttf") format("truetype");
	font-weight: 700;
	font-style: normal;
	font-display: block;
}

* { box-sizing: border-box; }

html, body {
	width: 100%;
	height: 100%;
	margin: 0;
	padding: 0;
	overflow: hidden;
	background: #11161d;
	color: var(--ink);
	font-family: Georgia, "Book Antiqua", "Palatino Linotype", "Times New Roman", serif;
	-webkit-text-size-adjust: 100%;
}

#renderCanvas {
	display: block;
	width: 100%;
	height: 100%;
	touch-action: none;
	outline: none;
	background: radial-gradient(ellipse at 50%, rgb(219, 210, 210), rgb(43, 41, 41));
}

/* =============================================================================
 *  Bascule gyroscope / doigt — pilule compacte en bas au centre
 * ========================================================================== */

.view-toggle {
	position: fixed;
	left: 50%;
	bottom: calc(18px + env(safe-area-inset-bottom));
	transform: translateX(-50%);
	z-index: 900;

	display: inline-flex;
	align-items: center;
	gap: .55em;
	padding: .6em 1.1em .6em .95em;

	border: 1px solid rgba(255, 255, 255, .28);
	border-radius: 999px;
	background: rgba(24, 31, 41, .62);
	-webkit-backdrop-filter: blur(10px);
	backdrop-filter: blur(10px);
	box-shadow: 0 6px 22px rgba(0, 0, 0, .35);

	color: #fff;
	font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
	font-size: clamp(13px, 3.6vw, 16px);
	letter-spacing: .01em;
	cursor: pointer;
	-webkit-tap-highlight-color: transparent;
	transition: background .2s ease, transform .12s ease, opacity .3s ease;
}

.view-toggle:active { transform: translateX(-50%) scale(.96); }

.view-toggle__icon {
	width: 1.45em;
	height: 1.45em;
	flex: none;
	fill: none;
	stroke: currentColor;
	stroke-width: 1.7;
	stroke-linecap: round;
	stroke-linejoin: round;
}

/* Une seule des deux icônes est visible, selon le mode courant */
.view-toggle .icon-hand { display: none; }
.view-toggle.is-manual .icon-gyro { display: none; }
.view-toggle.is-manual .icon-hand { display: inline; }

/* La pilule s'efface quand la fiche est ouverte */
.sheet-open .view-toggle { opacity: 0; pointer-events: none; }

/* =============================================================================
 *  Fiche d'un point d'intérêt
 * ========================================================================== */

.sheet {
	position: fixed;
	inset: 0;
	z-index: 1000;
	display: flex;
	background: rgba(9, 12, 17, .55);
	-webkit-backdrop-filter: blur(3px);
	backdrop-filter: blur(3px);
	opacity: 0;
	transition: opacity .28s ease;
}

.sheet[hidden] { display: none; }
.sheet.is-open { opacity: 1; }

.sheet__panel {
	position: relative;
	display: flex;
	flex-direction: column;
	width: 100%;
	max-width: 860px;
	margin: 0 auto;
	background: var(--paper);
	box-shadow: var(--shadow);
	transform: translateY(14px);
	transition: transform .28s cubic-bezier(.2, .7, .3, 1);
}

.sheet.is-open .sheet__panel { transform: translateY(0); }

@media (min-width: 900px) {
	.sheet { padding: 3.5vh 0; }
	.sheet__panel { border-radius: var(--radius); overflow: hidden; }
}

/* Titre centré entre deux colonnes de même largeur : à gauche une colonne vide,
 * sous la croix native ; à droite notre bouton de fermeture. Même sur deux
 * lignes, le titre ne peut pas passer sous la croix native. */
.sheet__header {
	--side: max(2.4em, calc(var(--native-close-zone) - var(--gutter)));
	display: grid;
	grid-template-columns: var(--side) 1fr var(--side);
	align-items: center;
	column-gap: .6em;
	padding: calc(.85em + env(safe-area-inset-top)) var(--gutter) .85em;
	background: linear-gradient(180deg, var(--slate-soft), var(--slate));
	color: #fff;
}

.sheet__header::before { content: ""; }   /* colonne gauche : place de la croix native */

.sheet__header h2 {
	margin: 0;
	text-align: center;
	text-wrap: balance;                      /* deux lignes équilibrées plutôt qu'une veuve */
	font-size: var(--text-title);
	font-weight: 600;
	line-height: 1.25;
	letter-spacing: .005em;
}

.sheet__close {
	justify-self: end;
	width: 2.4em;
	height: 2.4em;
	display: grid;
	place-items: center;
	padding: 0;
	border: 1px solid rgba(255, 255, 255, .3);
	border-radius: 50%;
	background: rgba(255, 255, 255, .08);
	color: #fff;
	cursor: pointer;
	-webkit-tap-highlight-color: transparent;
	transition: background .18s ease, transform .12s ease;
}

.sheet__close svg {
	width: 1.05em;
	height: 1.05em;
	fill: none;
	stroke: currentColor;
	stroke-width: 2;
	stroke-linecap: round;
}

.sheet__close:active { transform: scale(.92); background: rgba(255, 255, 255, .18); }

.sheet__body {
	flex: 1;
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
	overscroll-behavior: contain;
	padding: clamp(1.4em, 4vw, 2.4em) var(--gutter) calc(2.6em + env(safe-area-inset-bottom));
	font-size: var(--text);
	line-height: 1.62;
}

.sheet__body > :first-child,
.sheet__body .pswp-gallery > :first-child { margin-top: 0; }

.sheet__body p { margin: 0 0 1.15em; }

/* Intertitre à l'intérieur d'une fiche ({ heading: "…" } dans content.js) */
.sheet__subtitle {
	margin: 1.9em 0 .7em;
	padding-bottom: .35em;
	border-bottom: 1px solid var(--rule);
	color: var(--slate);
	font-size: 1.12em;
	font-weight: 600;
	line-height: 1.3;
}

.sheet__body ul {
	margin: 0 0 1.15em;
	padding-left: 1.1em;
}

.sheet__body li { margin-bottom: .2em; }
.sheet__body li p { margin-bottom: .6em; }
.sheet__body li::marker { color: var(--accent); }

/* Lettrine discrète sur le premier paragraphe : la touche « fiche de musée » */
.sheet__body .pswp-gallery > p:first-of-type::first-letter {
	float: left;
	margin: .06em .12em 0 0;
	color: var(--slate);
	font-size: 3.1em;
	line-height: .82;
	font-weight: 600;
}

/* --- Photos de la fiche ---------------------------------------------------- */

.picture-container {
	display: block;
	margin: 1.6em auto 2em;
	text-decoration: none;
	color: inherit;
	cursor: zoom-in;
}

.picture-container img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 8px;
	box-shadow: 0 10px 26px rgba(20, 24, 31, .18);
	transition: transform .25s ease, box-shadow .25s ease;
}

.picture-container:active img {
	transform: scale(.99);
	box-shadow: 0 6px 16px rgba(20, 24, 31, .16);
}

/* Les portraits ne prennent pas toute la largeur : ils resteraient démesurés */
.picture-container.modal-image-portrait { max-width: min(68%, 380px); }

.picture-container span {
	display: block;
	margin-top: .7em;
	color: var(--ink-soft);
	font-size: .84em;
	font-style: italic;
	line-height: 1.45;
	text-align: center;
}

/* =============================================================================
 *  Chargement
 * ========================================================================== */

/* Seuil d'entrée — occupe la place de l'ancien écran de chargement.
 *
 * Le fond est la photo de l'église, FLOUTÉE ET ASSOMBRIE À L'EXPORT
 * (img/seuil.webp, 3 Ko). Aucun filtre CSS, donc aucune passe GPU : un
 * `backdrop-filter` au-dessus du canvas WebGL serait recalculé à chaque image.
 * Le fondu de sortie n'est alors pas un rideau qui s'ouvre sur autre chose,
 * mais la même vue qui se précise — une mise au point, pas une porte. */
.loader {
	position: fixed;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	background: #0b0d10 url("img/seuil.webp") center / cover no-repeat;
	z-index: 9999;
	opacity: 0;
	pointer-events: none;
	transition: opacity .6s ease;
	cursor: pointer;
	-webkit-tap-highlight-color: transparent;
}

.loader.visible { opacity: 1; pointer-events: auto; }

/* Assombrissement uniforme — pas de vignette : le dégradé radial trahit
 * l'écran posé par-dessus et casse l'immersion. */
.loader::before {
	content: "";
	position: absolute;
	inset: 0;
	background: rgba(10, 12, 16, .42);
}

.seuil__texte {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: clamp(12px, 3.2vh, 30px);
	text-align: center;
	color: #fff;
	/* La croix native « quitter » est dessinée en haut à gauche PAR-DESSUS la
	 * page : on garde ses 60 px dégagés. */
	padding: max(var(--native-close-zone), 7vh) clamp(22px, 7vw, 64px) 7vh;
	font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

.seuil__lieu {
	margin: 0;
	font-size: clamp(11px, 1.5vh, 13px);
	letter-spacing: .2em;
	text-transform: uppercase;
	opacity: .66;
}

/* Libre Baskerville : la police du parc, déjà chargée pour les pastilles. */
.seuil__titre {
	margin: 0;
	font-family: "Libre Baskerville", Georgia, serif;
	font-weight: 700;
	font-size: clamp(27px, 5.6vh, 50px);
	line-height: 1.12;
	text-shadow: 0 2px 26px rgba(0, 0, 0, .5);
}

.seuil__invite {
	margin: 0;
	max-width: 50ch;      /* assez large pour que chaque phrase tienne sur sa ligne */
	white-space: pre-line;          /* le \n de content.js fait le retour */
	font-size: clamp(14px, 2.2vh, 19px);
	line-height: 1.5;
	opacity: .9;
	text-shadow: 0 1px 14px rgba(0, 0, 0, .45);
}

/* Pictogramme : le téléphone bascule, un arc accompagne le geste. */
.seuil__geste {
	width: clamp(46px, 7.5vh, 76px);
	height: auto;
	fill: none;
	stroke: #fff;
	stroke-width: 2.2;
	opacity: .9;
}

/* L'appareil décrit un cône : il tourne à gauche et à droite, puis s'incline
 * vers le haut et vers le bas. Le geste du gyroscope n'est pas seulement
 * horizontal — montrer les deux axes évite que le visiteur ne pense qu'à
 * pivoter sur lui-même, et oublie de lever la tête vers les voûtes.
 * `perspective()` donne la profondeur ; sans elle, rotateX/rotateY ne font
 * qu'aplatir le dessin. */
.seuil__appareil {
	transform-box: fill-box;
	transform-origin: 50% 74%;
	animation: seuil-sonde 5s ease-in-out infinite;
}

.seuil__ecran { opacity: .5; }

/* Trace au sol : une ellipse, pas un arc — elle vaut pour les deux axes. */
.seuil__orbite { stroke-dasharray: 3 5; opacity: .45; stroke-width: 2; }

/* Perspective courte (150px pour un dessin de ~70px) et angles francs : à cette
 * taille, une rotation discrète ne change pas assez la silhouette pour se lire.
 * Essayé d'abord à 320px / 24° — le mouvement était invisible sur quatre images. */
/* Le déplacement fait le gros du travail. À 70 px, une rotation seule ne change
 * pas assez la silhouette : le dessin paraissait immobile sur quatre images
 * figées, alors que les transformations étaient bien appliquées. Quelques
 * unités de translation rendent le balayage évident. */
@keyframes seuil-sonde {
	0%, 100% { transform: perspective(150px) translateY(-3px) rotateX(-26deg); }
	25%      { transform: perspective(150px) translateX(4px)  rotateY(40deg); }
	50%      { transform: perspective(150px) translateY(3px)  rotateX(24deg); }
	75%      { transform: perspective(150px) translateX(-4px) rotateY(-40deg); }
}

/* L'appel : une phrase qui respire, pas un bouton.
 *
 * Toute la surface est tapable — un bouton dessiné désignerait une cible et
 * ferait croire qu'il faut l'atteindre, alors qu'un toucher n'importe où suffit.
 * Une lueur qui va et vient appelle le geste sans prétendre le contenir. */
.seuil__appel {
	font-size: clamp(12px, 1.8vh, 15px);
	letter-spacing: .16em;
	text-transform: uppercase;
	animation: seuil-lueur 3.2s ease-in-out infinite;
}

@keyframes seuil-lueur {
	0%, 100% {
		opacity: .5;
		/* Lueur froide reprise de --accent : le même bleu que les pastilles. */
		text-shadow: 0 0 10px rgba(255, 255, 255, .12);
	}
	50% {
		opacity: 1;
		text-shadow: 0 0 20px rgba(255, 255, 255, .5),
		             0 0 44px rgba(128, 160, 230, .32);
	}
}

/* Le spinner ne reparaît que si la photo se fait attendre. */
.loader-spinner[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
	.seuil__appareil, .seuil__appel { animation: none; opacity: .9; }
}

.loader-spinner {
	width: 42px;
	height: 42px;
	margin: 0 auto;
	border: 3px solid rgba(255, 255, 255, .25);
	border-top-color: #fff;
	border-radius: 50%;
	animation: spin 1s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

/* =============================================================================
 *  Outil de placement des pastilles (config.js : marker_picker = true)
 * ========================================================================== */

#markerPicker {
	position: fixed;
	top: 12px;
	right: 12px;
	z-index: 2000;
	display: flex;
	flex-direction: column;
	gap: 10px;
	width: min(340px, calc(100vw - 24px));
	max-height: calc(100vh - 110px);
	padding: 12px;
	border-radius: 12px;
	background: rgba(17, 22, 29, .92);
	box-shadow: 0 10px 30px rgba(0, 0, 0, .4);
	color: #fff;
	font: 13px/1.35 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

.picker__head strong { display: block; font-size: 14px; }
.picker__head span { color: rgba(255, 255, 255, .65); font-size: 12px; }

.picker__list {
	margin: 0;
	padding: 0;
	list-style: none;
	overflow-y: auto;
	min-height: 60px;
}

.picker__list li {
	display: grid;
	grid-template-columns: 1.8em 1fr auto;
	align-items: center;
	gap: 6px;
	padding: 5px 6px;
	border-radius: 6px;
	cursor: pointer;
}

.picker__list li:hover { background: rgba(255, 255, 255, .07); }
.picker__list li.is-current { background: var(--accent); }
.picker__list li b { text-align: center; }
.picker__list li.is-moved b::after { content: " ✓"; color: #9be29b; font-weight: 400; }
.picker__name { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.picker__list code { font: 12px ui-monospace, SFMono-Regular, Menlo, monospace; opacity: .8; }

.picker__out {
	margin: 0;
	max-height: 24vh;
	overflow: auto;
	padding: 8px;
	border-radius: 6px;
	background: rgba(255, 255, 255, .06);
	font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
	user-select: all;
}

.picker__copy {
	padding: 8px;
	border: 0;
	border-radius: 6px;
	background: #fff;
	color: var(--slate);
	font: 600 13px system-ui, sans-serif;
	cursor: pointer;
}

/* Visionneuse PhotoSwipe : son compteur « 1 / 3 » est lui aussi en haut à gauche */
.pswp__counter { margin-inline-start: max(20px, var(--native-close-zone)); }

@media (prefers-reduced-motion: reduce) {
	* { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}
