/*
 * services/pellicule — engagement 5 : aucun hexadecimal, replis compris.
 * Cadre sous .ivy-services--pellicule (PASSATION §3).
 *
 * TOUT ce qui suit est l'ETAT REPLIE, et il se lit seul. L'etat tenu vient
 * s'ajouter sous .ivy-scene-ready, la classe que le runtime pose quand il
 * tient la scene. L'ordre n'est pas un detail de style : ecrit dans l'autre
 * sens, une page sans JavaScript afficherait des services superposes et
 * masques. Lecon payee sur steps/scenes-masquees.
 */
.ivy-services--pellicule {
	/*
	 * Le decalage du pin. La declarer ICI n'est pas optionnel : le `max()`
	 * plus bas est INVALIDE AU CALCUL si l'une de ses deux variables ne
	 * resout rien, et c'est la declaration entiere qui tombe — pas seulement
	 * le centrage.
	 */
	--ivy-pellicule-top: 0px;

	position: relative;
	padding: clamp( 72px, 10vw, 144px ) clamp( 20px, 5vw, 72px );
	background: transparent;
	color: var( --ivy-section-color, rgb( 30 36 42 ) );
}

.ivy-services--pellicule .ivy-services__header { position: relative; z-index: 1; width: 100%; max-width: 760px; margin-bottom: clamp( 40px, 6vw, 72px ); }
.ivy-services--pellicule .ivy-services__eyebrow { display: block; margin-bottom: 14px; color: var( --ivy-eyebrow-color, rgb( 80 90 76 ) ); font-size: var( --ivy-font-label ); font-weight: 700; letter-spacing: .14em; text-transform: uppercase; }
.ivy-services--pellicule .ivy-services__title { margin: 0; color: var( --ivy-title-color, currentColor ); letter-spacing: -.03em; line-height: 1.02; }
.ivy-services--pellicule .ivy-services__text { max-width: 58ch; margin: 20px 0 0; color: var( --ivy-text-color, currentColor ); line-height: 1.65; }

/*
 * Les teintes ne se voient qu'a l'etat tenu. Replie, les quatre services sont
 * lisibles a la fois : quatre fonds superposes ne voudraient rien dire.
 */
.ivy-services--pellicule .ivy-services__tones { display: none; }

.ivy-services--pellicule .ivy-services__scene {
	/*
	 * VOLONTAIREMENT NON POSITIONNEE. La pile de teintes est son enfant — pour
	 * heriter de `--ivy-scene` — mais son `inset: 0` doit se resoudre contre la
	 * SECTION, seule boite positionnee, afin de couvrir l'en-tete aussi. Poser
	 * `position: relative` ici enfermerait le fond sous les deux colonnes.
	 *
	 * Les deux colonnes reprennent donc leur rang par `z-index` : il s'applique
	 * aux elements de grille sans qu'ils soient positionnes.
	 */
	display: grid;
	--ivy-gap: clamp( 40px, 6vw, 96px );
	column-gap: var( --ivy-gap );
	row-gap: var( --ivy-row-gap, clamp( 32px, 5vw, 64px ) );
	grid-template-columns:
		minmax( 0, calc( ( 100% - var( --ivy-gap ) ) * var( --ivy-columns, 45 ) / 100 ) )
		minmax( 0, 1fr );
	align-items: start;
}

/* Sans une seule image, il n'y a pas de seconde piste a reserver. */
.ivy-services--pellicule-static .ivy-services__scene { grid-template-columns: minmax( 0, 1fr ); }

/*
 * Image a gauche : les deux colonnes s'echangent, le DOM ne bouge pas.
 *
 * Le `:not()` n'est pas une precaution de style. Sans lui, la variante statique
 * placait son unique boite en COLONNE 2, ce qui cree une piste implicite : la
 * grille en gardait deux pour une seule boite, et le media absent laissait
 * exactement le trou que ce produit s'interdit. Mesure : deux pistes de 446 et
 * 463 px la ou une seule de 996 est attendue.
 */
.ivy-services--media-left.ivy-services--pellicule:not( .ivy-services--pellicule-static ) .ivy-services__steps { grid-column: 2; grid-row: 1; }
.ivy-services--media-left.ivy-services--pellicule:not( .ivy-services--pellicule-static ) .ivy-services__pin { grid-column: 1; grid-row: 1; }

.ivy-services--pellicule .ivy-services__steps { position: relative; z-index: 1; display: grid; row-gap: clamp( 40px, 7vw, 88px ); }
.ivy-services--pellicule .ivy-services__step { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; }
.ivy-services--pellicule .ivy-services__item-title { margin: 0; color: var( --ivy-item_title-color, currentColor ); letter-spacing: -.02em; line-height: 1.06; }
.ivy-services--pellicule .ivy-services__item-text { margin: 0; max-width: 46ch; color: var( --ivy-item_text-color, currentColor ); line-height: 1.6; }

.ivy-services--pellicule .ivy-services__includes { display: grid; row-gap: 10px; margin: 6px 0 0; padding: 0; list-style: none; }
.ivy-services--pellicule .ivy-services__include { display: flex; align-items: baseline; gap: 12px; margin: 0; color: var( --ivy-item_list_item-color, currentColor ); line-height: 1.5; }
/*
 * La puce prend sa couleur par `color` et se peint avec `currentColor` : la
 * famille « color » ecrit --ivy-<partie>-color, et c'est la propriete `color`
 * qui doit la lire pour que le reglage soit reellement mesurable sur
 * l'element de la partie.
 */
.ivy-services--pellicule .ivy-services__bullet { flex: 0 0 auto; width: 7px; aspect-ratio: 1; margin-top: .45em; border-radius: 50%; color: var( --ivy-item_bullet-color, currentColor ); background: currentColor; }
.ivy-services--pellicule .ivy-services__include-text { min-width: 0; }

.ivy-services--pellicule .ivy-services__item-cta { display: inline-flex; align-items: center; gap: 8px; margin-top: 6px; padding: 14px 22px; border-radius: var( --ivy-radius-action, 999px ); color: var( --ivy-item_cta-color, currentColor ); background: var( --ivy-item_cta-background-color, transparent ); box-shadow: inset 0 0 0 1px currentColor; font-size: var( --ivy-font-label ); font-weight: 600; text-decoration: none; transition: color 180ms ease, background-color 180ms ease; }
.ivy-services--pellicule .ivy-services__item-cta:hover { color: var( --ivy-item_cta-background-color, rgb( 255 255 255 ) ); background: var( --ivy-item_cta-color, currentColor ); }
.ivy-services--pellicule .ivy-services__item-cta:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }

/*
 * Le pin est collant PAR DEFAUT, et ce n'est pas un detail : le runtime decide
 * d'epingler en LISANT `position: sticky` dessus. Le rendre collant seulement
 * sous .ivy-scene-ready — la classe qu'il pose lui-meme — fermerait la boucle,
 * il n'aurait jamais rien tenu.
 *
 * Le pin se pose au MILIEU de la fenetre : --ivy-pin-lead est la moitie du
 * blanc, publiee par le runtime, et max() garde la place qu'un theme a barre
 * collante se reserve. Regle ecrite au long dans cards/rail, verifiee pour
 * toutes les compositions epinglees par tests/e2e/centrage.spec.ts.
 */
.ivy-services--pellicule .ivy-services__pin { z-index: 1; position: sticky; top: max( var( --ivy-pellicule-top ), var( --ivy-pin-lead, 0px ) ); display: grid; row-gap: clamp( 24px, 4vw, 40px ); }
.ivy-services--pellicule .ivy-services__media { margin: 0; overflow: hidden; border-radius: var( --ivy-radius-surface, 16px ); }
/* Replie, l'image garde son rapport d'origine : rien n'est recadre, et aucune
   hauteur n'est ecrite en dur. */
.ivy-services--pellicule .ivy-services__media img { display: block; width: 100%; height: auto; border-radius: inherit; }

/*
 * LE RATIO DE LA PHOTO, choisi au panneau (`media_ratio`). `auto` ne pose rien :
 * c'est le cadre d'avant — hauteur epinglee de min( 62vh, 560px ) et, replie, la
 * photo a son rapport d'origine. Les regles ne s'appliquent QUE SI une classe de
 * ratio explicite est presente, jamais par exclusion de `auto` : un HTML servi
 * sans classe (cache Elementor d'avant ce reglage) n'a pas les variables
 * `--ivy-pellicule-w` et `-h`, et `aspect-ratio` invalide laissait le cadre a
 * zero de haut — mesure : le pin epingle a 450 px au lieu de 171. Les cinq autres valeurs ecrivent DEUX nombres,
 * largeur et hauteur, parce qu'on lit le rapport de deux facons : en `aspect-ratio`,
 * et en calc() pour borner la largeur du cadre epingle.
 */
.ivy-services--pellicule.ivy-services--ratio-16-9 { --ivy-pellicule-w: 16; --ivy-pellicule-h: 9; }
.ivy-services--pellicule.ivy-services--ratio-4-3 { --ivy-pellicule-w: 4; --ivy-pellicule-h: 3; }
.ivy-services--pellicule.ivy-services--ratio-1-1 { --ivy-pellicule-w: 1; --ivy-pellicule-h: 1; }
.ivy-services--pellicule.ivy-services--ratio-3-4 { --ivy-pellicule-w: 3; --ivy-pellicule-h: 4; }
.ivy-services--pellicule.ivy-services--ratio-4-5 { --ivy-pellicule-w: 4; --ivy-pellicule-h: 5; }

/* Replie (petit ecran, mouvement reduit, sans JavaScript) : le ratio est porte par
   l'IMAGE, pas par son cadre — meme lecon que cards/eventail, sous WebKit un
   `aspect-ratio` pose sur un cadre etire sort 12,9 % trop haut. */
.ivy-services--pellicule:is( .ivy-services--ratio-16-9, .ivy-services--ratio-4-3, .ivy-services--ratio-1-1, .ivy-services--ratio-3-4, .ivy-services--ratio-4-5 ) .ivy-services__media img { aspect-ratio: var( --ivy-pellicule-w ) / var( --ivy-pellicule-h ); object-fit: cover; }

/*
 * ==========================================================================
 * L'ETAT TENU. Rien ici ne s'applique sans .ivy-scene-ready, que le runtime
 * pose quand il tient la scene — et qu'il ne pose ni sans JavaScript, ni sous
 * mouvement reduit, ni quand le CSS a decolle le pin.
 *
 * TOUTE l'apparence se derive d'UN SEUL nombre, `--ivy-local`, calcule depuis
 * la progression publiee par le runtime et l'index que le gabarit ecrit :
 *
 *   --ivy-local = clamp( 0, scene x span - index, 1 )
 *
 * Forme prouvee le 19 aout sur Chromium ET WebKit avant d'etre ecrite ici :
 * les deux bornes mordent, et le style calcule garde le POURCENTAGE au lieu de
 * le resoudre en pixels. `@property` rendait exactement les memes valeurs, il
 * n'aurait donc ete qu'un cout.
 * ==========================================================================
 */

/* Un service, un ecran : c'est cette regle qui rend la correspondance
   bloc <-> image lisible, et c'est elle que la reference applique aussi. */
.ivy-services--pellicule .ivy-services__scene.ivy-scene-ready .ivy-services__steps { row-gap: 0; }
/*
 * Le texte se centre sur la MEME bande que l'image. Sans la cale basse, le bloc
 * se centre dans son ecran entier (centre a 627 px dans une fenetre de 900)
 * quand le cadre epingle se centre a 450 : 177 px d'ecart mesures, constants.
 * La cale vaut deux fois `--ivy-pin-lead` — la moitie du blanc que le runtime
 * publie — ce qui remonte le contenu d'exactement un `pin-lead`.
 */
.ivy-services--pellicule .ivy-services__scene.ivy-scene-ready .ivy-services__step { min-height: 100vh; justify-content: center; padding-bottom: calc( var( --ivy-pin-lead, 0px ) * 2 ); }

/* Le pin devient une boite UNIQUE ou les images se superposent. */
.ivy-services--pellicule .ivy-services__scene.ivy-scene-ready .ivy-services__pin { row-gap: 0; height: min( 62vh, 560px ); }
/*
 * Etat tenu, ratio choisi : le cadre epingle prend la forme demandee. Sa largeur
 * est bornee pour que sa hauteur ne depasse jamais 80vh — un 3:4 dans une colonne
 * de 680 px ferait 906 px, plus haut que la fenetre, et l'image epinglee serait
 * rognee. On borne donc la LARGEUR, pas la hauteur : max-height casserait le
 * rapport, la boite restant aussi large. Centre dans sa colonne s'il est plus etroit.
 */
.ivy-services--pellicule:is( .ivy-services--ratio-16-9, .ivy-services--ratio-4-3, .ivy-services--ratio-1-1, .ivy-services--ratio-3-4, .ivy-services--ratio-4-5 ) .ivy-services__scene.ivy-scene-ready .ivy-services__pin {
	height: auto;
	aspect-ratio: var( --ivy-pellicule-w ) / var( --ivy-pellicule-h );
	inline-size: min( 100%, calc( 80vh * var( --ivy-pellicule-w ) / var( --ivy-pellicule-h ) ) );
	justify-self: center;
}
.ivy-services--pellicule .ivy-services__scene.ivy-scene-ready .ivy-services__media {
	--ivy-local: clamp( 0, calc( var( --ivy-scene, 0 ) * var( --ivy-span ) - var( --ivy-index ) ), 1 );

	position: absolute;
	inset: 0;
	/*
	 * L'EMPILEMENT DECROISSANT n'est pas cosmetique : effacer l'image du
	 * dessus ne decouvre rien si elle n'est pas au-dessus. Les deux moities du
	 * geste sont ici, et un test les mesure ensemble.
	 */
	z-index: calc( var( --ivy-span ) - var( --ivy-index ) + 1 );
	clip-path: inset( 0 0 calc( var( --ivy-local ) * 100% ) 0 );
}
/* La derive de l'image dans son cadre : object-position, jamais une
   transformation de boite — rien ne sort du cadre, rien ne se recalcule. */
.ivy-services--pellicule .ivy-services__scene.ivy-scene-ready .ivy-services__media img { height: 100%; object-fit: cover; object-position: 0 calc( 40% + var( --ivy-local ) * 20% ); }

/*
 * LES TEINTES. Meme progression, exprimee en services entiers : `--ivy-place`
 * vaut 0 sur le premier service, 1 sur le deuxieme, et ainsi de suite. Chaque
 * calque s'eteint a mesure qu'on s'en eloigne, donc deux voisins se croisent en
 * fondu au lieu de basculer.
 *
 * Ecrit avec min() et non avec abs() : abs() est trop recent pour etre pose
 * dans un socle qui vise aussi les navigateurs des clients.
 */
.ivy-services--pellicule .ivy-services__scene.ivy-scene-ready .ivy-services__tones {
	--ivy-place: calc( var( --ivy-scene, 0 ) * var( --ivy-span ) );

	display: block;
	position: absolute;
	inset: 0;
	z-index: 0;
	overflow: hidden;
}
.ivy-services--pellicule .ivy-services__scene.ivy-scene-ready .ivy-services__tone {
	position: absolute;
	inset: 0;
	background: var( --ivy-tone );
	opacity: clamp( 0, min( calc( var( --ivy-place ) - var( --ivy-index ) + 1 ), calc( var( --ivy-index ) - var( --ivy-place ) + 1 ) ), 1 );
}

/*
 * LE REPLI, aux deux conditions qui le declenchent — et une seule regle pour
 * les deux, la virgule valant « ou ». Sous la rupture le CSS decolle le pin,
 * le runtime le LIT et lache la scene ; sous mouvement reduit il ne la tient
 * pas davantage (engagement 8).
 *
 * `display: contents` entrelace images et textes sans toucher au DOM. C'est
 * pour lui que l'enveloppe des services n'est ni un <ol> ni un role="list" :
 * plusieurs moteurs retirent les semantiques de liste d'un element sans boite.
 */
@media ( max-width: 900px ), ( prefers-reduced-motion: reduce ) {
	.ivy-services--pellicule .ivy-services__scene { display: flex; flex-direction: column; gap: clamp( 20px, 5vw, 36px ); }
	.ivy-services--pellicule .ivy-services__steps,
	.ivy-services--pellicule .ivy-services__pin { display: contents; }
	.ivy-services--pellicule .ivy-services__step { order: calc( var( --ivy-index ) * 2 + 1 ); }
	.ivy-services--pellicule .ivy-services__media { order: calc( var( --ivy-index ) * 2 ); }
	.ivy-services--pellicule .ivy-services__pin { position: relative; top: auto; }
	.ivy-services--pellicule .ivy-services__item-cta { transition: none; }

	/*
	 * CEINTURE. Les regles de l'etat tenu portent `.ivy-scene-ready` en plus,
	 * donc un poids de selecteur SUPERIEUR a celui du repli : 0,3,0 contre
	 * 0,2,0. Le runtime retire bien la classe des qu'il lache la scene, mais
	 * il le fait a la mesure suivante — et une seule frame ou la classe
	 * survivrait a un redimensionnement suffirait a rendre des images
	 * superposees et masquees. Ces quatre lignes annulent l'etat tenu la ou il
	 * ne doit jamais s'appliquer, sans dependre de ce calendrier.
	 */
	.ivy-services--pellicule .ivy-services__scene.ivy-scene-ready .ivy-services__step { min-height: 0; }
	.ivy-services--pellicule .ivy-services__scene.ivy-scene-ready .ivy-services__pin { height: auto; }
	.ivy-services--pellicule .ivy-services__scene.ivy-scene-ready .ivy-services__media { position: relative; inset: auto; z-index: auto; clip-path: none; }
	.ivy-services--pellicule .ivy-services__scene.ivy-scene-ready .ivy-services__media img { height: auto; object-position: center; }
	.ivy-services--pellicule .ivy-services__scene.ivy-scene-ready .ivy-services__tones { display: none; }
}
