/*
 * steps/cadran — engagement 5 : aucun hexadecimal, replis compris.
 * Cadre sous .ivy-steps--cadran (PASSATION §3).
 *
 * TOUT ce qui suit part de l'etat REPLIE et l'enrichit sous
 * .ivy-scene-ready, la classe que le runtime pose sur la SCENE quand il
 * tient le geste. L'ordre n'est pas un detail de style : ecrit dans l'autre
 * sens, une page sans JavaScript afficherait des photos superposees et
 * masquees. Lecon payee sur steps/scenes-masquees.
 *
 * UNE REGLE DE SPECIFICITE, ET ELLE VAUT POUR TOUT LE FICHIER. Les feuilles
 * de composition sont mises en file AU RENDU, donc imprimees dans le PIED :
 * elles passent APRES la CSS qu'Elementor emet pour l'instance. A specificite
 * egale, la feuille gagne — et le reglage du panneau devient muet. Les
 * proprietes que le panneau ecrit AUSSI en dur — `height` (famille `size`),
 * `border-radius` et `box-shadow` (famille `border`) — sont donc posees dans
 * un `:where()`, qui ne compte pour rien : n'importe quelle regle d'Elementor
 * l'emporte, et le defaut tient tant que l'editeur n'a rien regle. Les
 * couleurs et la typographie n'ont pas ce probleme, le panneau ecrivant pour
 * elles une propriete personnalisee que la feuille LIT.
 */
.ivy-steps--cadran {
	/*
	 * 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.
	 */
	--ivy-cadran-top: 0px;

	/*
	 * Le pas angulaire est FIXE, jamais 360deg / n : a cinq etapes cette
	 * formule-la donnerait 72deg d'ecart et un cadran vide. Raison au long
	 * dans la fiche R-10.
	 */
	--ivy-pitch: 11deg;
	--ivy-radius: clamp( 520px, 64vw, 1500px );
	/* Ce que le disque laisse voir du bas du cadre. */
	--ivy-arc: clamp( 210px, 34vh, 380px );

	position: relative;
	padding: clamp( 64px, 10vw, 144px ) clamp( 20px, 5vw, 72px );
	background: transparent;
	/*
	 * L'encre suit le kit du site, avec un repli SOMBRE. Le piege est celui que
	 * navbar/pilule paie encore : une encre calcaire par defaut suppose un fond
	 * sombre et rend le texte invisible sur une page claire — 1,04:1 mesure sur
	 * l'atelier avant correction. Ici l'en-tete et TOUT l'etat replie vivent sur
	 * le fond de page ; seul le texte pose DANS le disque est calcaire, et son
	 * fond est garanti sombre par le defaut du disque.
	 */
	color: var( --ivy-section-color, var( --ivy-ink, rgb( 30 36 42 ) ) );
}

.ivy-steps--cadran .ivy-steps__header { max-width: 780px; margin: 0 0 clamp( 32px, 5vw, 64px ); }
.ivy-steps--cadran .ivy-steps__eyebrow { display: block; margin-bottom: 14px; color: var( --ivy-eyebrow-color, var( --ivy-muted, rgb( 96 104 112 ) ) ); font-size: var( --ivy-font-label ); font-weight: 700; letter-spacing: .16em; text-transform: uppercase; }
.ivy-steps--cadran .ivy-steps__title { margin: 0; color: var( --ivy-title-color, currentColor ); font-size: var( --ivy-font-h2 ); line-height: 1.03; letter-spacing: -.035em; text-wrap: balance; }
.ivy-steps--cadran .ivy-steps__text { max-width: 58ch; margin: 18px 0 0; color: var( --ivy-text-color, var( --ivy-muted, rgb( 88 96 104 ) ) ); line-height: 1.6; }

/*
 * ==========================================================================
 * L'ETAT REPLIE. Une suite d'etapes ordinaires : chaque photo au-dessus de
 * son texte, aucun cadran, aucune superposition. C'est ce que rend une page
 * sans JavaScript, un mouvement reduit, et tout ecran sous 900 px.
 * ==========================================================================
 */
.ivy-steps--cadran .ivy-steps__scene { display: flex; flex-direction: column; gap: clamp( 24px, 5vw, 44px ); }

/*
 * Collant PAR DEFAUT — le runtime decide d'epingler en LISANT `position:
 * sticky` dessus — et pose au milieu de la fenetre par --ivy-pin-lead. Les
 * deux regles sont ecrites au long dans cards/rail ; centrage.spec.ts les
 * verifie pour toutes les compositions epinglees.
 */
.ivy-steps--cadran .ivy-steps__pin { position: sticky; top: max( var( --ivy-cadran-top ), var( --ivy-pin-lead, 0px ) ); }
.ivy-steps--cadran .ivy-steps__spacer { height: var( --ivy-scene-distance, 0px ); }

/* Replie, les photos gardent leur rapport d'origine : rien n'est recadre, et
   aucune hauteur n'est ecrite en dur. */
.ivy-steps--cadran .ivy-steps__frames { display: grid; row-gap: clamp( 24px, 5vw, 44px ); }
.ivy-steps--cadran .ivy-steps__media { position: relative; margin: 0; overflow: hidden; }
.ivy-steps--cadran :where( .ivy-steps__media ) { border-radius: var( --ivy-radius-surface, 20px ); }
/* `border-radius: inherit` : le rayon vit sur la figure (famille `border`), et
   sans lui un `img { border-radius }` de kit de site rend le reglage muet. */
.ivy-steps--cadran .ivy-steps__media img { display: block; width: 100%; height: auto; border-radius: inherit; }

/* Le cadran n'existe qu'a l'etat tenu : replie, toutes les etapes sont
   lisibles a la fois, et un cadran ne designerait rien. */
.ivy-steps--cadran .ivy-steps__dial { display: none; }
/*
 * L'AIGUILLE prend sa couleur par `color` sur le repere, et ses deux morceaux
 * se peignent avec `currentColor` : la famille « color » ecrit
 * --ivy-<partie>-color sur l'element de la partie, et c'est `color` qui doit la
 * lire pour que le reglage soit mesurable la. Declaree hors de l'etat tenu,
 * parce que couleur.spec.ts mesure la partie aux DEUX tailles et que l'etat
 * tenu n'existe pas sous la rupture.
 */
.ivy-steps--cadran .ivy-steps__mark { color: var( --ivy-needle-color, rgb( 245 243 240 ) ); }

.ivy-steps--cadran .ivy-steps__copies { display: grid; row-gap: clamp( 24px, 5vw, 44px ); }
.ivy-steps--cadran .ivy-steps__copy { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.ivy-steps--cadran .ivy-steps__marker { color: var( --ivy-item_number-color, var( --ivy-accent, rgb( 138 106 48 ) ) ); font-size: var( --ivy-font-label ); font-weight: 700; letter-spacing: .18em; text-transform: uppercase; }
.ivy-steps--cadran .ivy-steps__item-title { margin: 0; color: var( --ivy-item_title-color, currentColor ); font-size: var( --ivy-font-h3 ); line-height: 1.06; letter-spacing: -.03em; }
.ivy-steps--cadran .ivy-steps__item-text { margin: 0; max-width: 52ch; color: var( --ivy-item_text-color, var( --ivy-muted, rgb( 88 96 104 ) ) ); line-height: 1.6; }

/*
 * LA VARIANTE STATIQUE — sans une photo par etape, pas de geste a porter (note
 * 4 du gabarit). Elle entrelace quand meme photos et textes A TOUTES LES
 * LARGEURS : deux piles l'une apres l'autre ne se lisent pas.
 */
.ivy-steps--cadran-static .ivy-steps__frames,
.ivy-steps--cadran-static .ivy-steps__copies { display: contents; }
.ivy-steps--cadran-static .ivy-steps__pin { display: contents; }
.ivy-steps--cadran-static .ivy-steps__media { order: calc( var( --ivy-index ) * 2 ); }
.ivy-steps--cadran-static .ivy-steps__copy { order: calc( var( --ivy-index ) * 2 + 1 ); }

/*
 * ==========================================================================
 * L'ETAT TENU. Rien ici ne s'applique sans .ivy-scene-ready, que le runtime
 * pose sur la scene quand il tient le geste — 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-place`, et de l'index
 * que le gabarit ecrit :
 *
 *   --ivy-place = scene x ( items - 0,4 )     0 au depart, items - 0,4 a la fin
 *   --ivy-d     = place - index               position dans l'ecran de l'etape
 *
 * UNE ETAPE VAUT UN ECRAN de defilement (a `rail_pace` 1), et son ecran se
 * decoupe ainsi :
 *
 *   d de 0,15 a 0,35   le texte monte en fondu
 *   d de 0,35 a 0,70   PALIER : l'etape se lit, rien ne bouge
 *   d de 0,70 a 0,85   le texte redescend et s'efface
 *   d de 1,00 a 1,25   la photo est balayee de droite a gauche
 *
 * Les deux bornes comptent autant que le milieu. `- 0,4` sur la course fait
 * finir la derniere etape EN PLEIN PALIER : sans ce retrait, la course
 * s'achevait pendant le dernier balayage — la derniere photo ne se refermait
 * jamais et son texte disparaissait au moment ou le pin se decolle. Mesure
 * faite sur maquette avant d'ecrire ce fichier.
 * ==========================================================================
 */
.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready {
	--ivy-place: calc( var( --ivy-scene, 0 ) * ( var( --ivy-items ) - .4 ) );

	display: block;
}

.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__pin { overflow: hidden; }
.ivy-steps--cadran :where( .ivy-steps__scene.ivy-scene-ready .ivy-steps__pin ) { height: 100vh; border-radius: var( --ivy-radius-surface, 0px ); }

/*
 * La pile de photos occupe tout le cadre. `z-index: 1` sur l'enveloppe n'est
 * pas un rang, c'est un CONTEXTE D'EMPILEMENT : les photos montent jusqu'a
 * `items` — 5 sur la fixture — et sans ce contexte la premiere passerait
 * au-dessus du cadran (2) et du texte (3). Aucun test de style ne voit un
 * ordre de peinture ; seul un rendu le montre.
 */
.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__frames { display: block; position: absolute; inset: 0; z-index: 1; row-gap: 0; }
.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__media {
	--ivy-d: calc( var( --ivy-place ) - var( --ivy-index ) );
	--ivy-local: clamp( 0, calc( ( var( --ivy-d ) - 1 ) / .25 ), 1 );

	position: absolute;
	inset: 0;
	/* Empilement DECROISSANT : effacer la photo du dessus ne decouvre rien si
	   elle n'est pas au-dessus. Un test mesure les deux moities ensemble. */
	z-index: calc( var( --ivy-items ) - var( --ivy-index ) );
	/* Le balayage : l'encoche de DROITE grandit, la photo se retire vers la
	   gauche, et celle du dessous apparait par le bord droit. */
	clip-path: inset( 0 calc( var( --ivy-local ) * 100% ) 0 0 );
}
.ivy-steps--cadran :where( .ivy-steps__scene.ivy-scene-ready .ivy-steps__media ) { border-radius: 0; }
/* La derive de la photo dans son cadre : object-position, jamais une
   transformation de boite — rien ne sort du cadre, rien ne se recalcule. */
.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__media img { height: 100%; object-fit: cover; object-position: calc( 50% - var( --ivy-local ) * 6% ) center; }

/*
 * LE CADRAN. Un disque immense dont seul l'arc superieur entre dans le cadre,
 * et qui tourne d'un pas par etape. `- 0,6` cale son sommet sur le PALIER de
 * lecture : le repere courant arrive en haut pendant que son texte se lit,
 * et le cadran voyage entre deux reperes pendant le balayage.
 */
.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__dial {
	display: block;
	position: absolute;
	left: 50%;
	top: calc( 100% - var( --ivy-arc ) );
	z-index: 2;
	width: calc( var( --ivy-radius ) * 2 );
	height: calc( var( --ivy-radius ) * 2 );
	margin-left: calc( var( --ivy-radius ) * -1 );
	background: var( --ivy-dial-background-color, rgb( 18 19 22 ) );
	transform: rotate( calc( ( var( --ivy-place ) - .6 ) * var( --ivy-pitch ) * -1 ) );
}
.ivy-steps--cadran :where( .ivy-steps__scene.ivy-scene-ready .ivy-steps__dial ) { border-radius: 50%; box-shadow: 0 -1px 0 rgb( 245 243 240 / 14% ); }

.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__mark {
	--ivy-d: calc( var( --ivy-place ) - var( --ivy-index ) );
	/* Plein a moins de 0,4 ecran du sommet, eteint au dela de 0,8. */
	--ivy-near: clamp( 0, calc( min( calc( var( --ivy-d ) + .2 ), calc( 1.4 - var( --ivy-d ) ) ) / .4 ), 1 );
	/* Les reperes lointains s'effacent, sinon ils croisent le texte. */
	--ivy-far: clamp( 0, calc( min( calc( var( --ivy-d ) + 2.2 ), calc( 3.4 - var( --ivy-d ) ) ) / 1.3 ), 1 );

	position: absolute;
	inset: 0;
	opacity: var( --ivy-far );
	/* Le repere prend sa place sur la jante ; le disque, lui, tourne. */
	transform: rotate( calc( var( --ivy-index ) * var( --ivy-pitch ) ) );
}
/*
 * La croissance du point actif passe par `scale`, PAS par sa largeur : la
 * largeur est ce que le panneau ecrit (famille `size`), et l'animer ici
 * rendrait le reglage muet. Le defaut de 8 px est donc dans un `:where()`, et
 * la croissance s'applique par-dessus, quelle que soit la taille choisie.
 */
.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__dot { position: absolute; left: 50%; top: 0; aspect-ratio: 1; border-radius: 50%; transform: translate( -50%, -50% ) scale( calc( 1 + var( --ivy-near ) * .75 ) ); background: currentColor; opacity: calc( .3 + var( --ivy-near ) * .7 ); }
.ivy-steps--cadran :where( .ivy-steps__scene.ivy-scene-ready .ivy-steps__dot ) { width: 8px; }
.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__thread { position: absolute; left: 50%; top: 0; width: 2px; transform: translate( -50%, 6px ) scaleY( var( --ivy-near ) ); transform-origin: top center; background: currentColor; }
.ivy-steps--cadran :where( .ivy-steps__scene.ivy-scene-ready .ivy-steps__thread ) { height: 30px; }
/*
 * Le libelle reste DROIT — nacelle de grande roue : il annule sa rotation ET
 * celle du disque. Le `- 0,6` s'y retrouve : sans lui, les libelles penchent
 * de quelques degres a chaque palier (mesure de la maquette).
 */
.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__mark .ivy-steps__marker {
	position: absolute;
	left: 50%;
	top: clamp( 28px, 3.4vh, 44px );
	opacity: calc( .34 + var( --ivy-near ) * .66 );
	white-space: nowrap;
	transform: translate( -50%, 0 ) rotate( calc( ( var( --ivy-place ) - .6 - var( --ivy-index ) ) * var( --ivy-pitch ) ) );
}
/* A l'etat tenu, le numero du repli est celui que porte la jante. */
.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__marker--stacked { display: none; }

/*
 * LE TEXTE, dans le disque. Il n'est jamais sur la photo : le disque est une
 * surface opaque, donc le contraste est acquis par construction et non par un
 * voile de plus.
 */
.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__copies {
	display: block;
	position: absolute;
	left: 50%;
	top: calc( 100% - var( --ivy-arc ) + clamp( 88px, 11vh, 148px ) );
	z-index: 3;
	width: min( 620px, 78vw );
	row-gap: 0;
	transform: translateX( -50% );
	text-align: center;
}
/*
 * Le texte du disque, et lui seul, prend l'encre calcaire : son fond est celui
 * du disque, sombre par defaut. Le reglage du panneau est lu EN PREMIER dans
 * les deux etats, donc une couleur choisie gouverne partout — c'est le repli
 * seul qui change de camp.
 */
.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__copies { color: rgb( 245 243 240 ); }
.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__mark .ivy-steps__marker { color: var( --ivy-item_number-color, rgb( 245 243 240 ) ); }

.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__copy {
	--ivy-d: calc( var( --ivy-place ) - var( --ivy-index ) );
	/*
	 * Fenetre SERREE, lecon de la maquette : avec le fondu croise de
	 * services/pellicule, deux textes se superposaient a mi-opacite et
	 * devenaient illisibles — un fond supporte le croisement, du texte non.
	 * Au milieu du balayage, il n'y a AUCUN texte.
	 */
	--ivy-show: clamp( 0, min( calc( ( var( --ivy-d ) - .15 ) / .2 ), calc( ( .85 - var( --ivy-d ) ) / .15 ) ), 1 );

	position: absolute;
	inset-inline: 0;
	top: 0;
	display: block;
	opacity: var( --ivy-show );
}
/* Le fondu vient DU BAS, et par etages : le titre monte de 28 px, le texte de
   40, ce qui donne le decalage sans qu'aucune duree ne soit ecrite — le
   defilement fait le temps. */
.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__item-title { transform: translateY( calc( ( 1 - var( --ivy-show ) ) * 28px ) ); }
.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__item-text { max-width: none; margin: 12px auto 0; color: var( --ivy-item_text-color, rgb( 245 243 240 / 78% ) ); transform: translateY( calc( ( 1 - var( --ivy-show ) ) * 40px ) ); opacity: clamp( 0, calc( ( var( --ivy-show ) - .25 ) / .75 ), 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).
 * ==========================================================================
 */
@media ( max-width: 900px ), ( prefers-reduced-motion: reduce ) {
	/* Le pin cesse d'etre collant : le runtime le LIT et lache la scene. */
	.ivy-steps--cadran .ivy-steps__pin { position: relative; top: auto; display: contents; }
	.ivy-steps--cadran .ivy-steps__frames,
	.ivy-steps--cadran .ivy-steps__copies { display: contents; }
	.ivy-steps--cadran .ivy-steps__media { order: calc( var( --ivy-index ) * 2 ); }
	.ivy-steps--cadran .ivy-steps__copy { order: calc( var( --ivy-index ) * 2 + 1 ); }

	/*
	 * CEINTURE : l'etat tenu porte un selecteur plus lourd que le repli, et le
	 * runtime ne retire sa classe qu'a la mesure suivante. Ces lignes
	 * l'annulent la ou il ne doit jamais s'appliquer, sans dependre de ce
	 * calendrier. Ecrite au long dans services/pellicule.
	 */
	.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready { display: flex; }
	.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__pin { overflow: visible; }
	.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__frames,
	.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__copies { display: contents; position: static; inset: auto; width: auto; transform: none; text-align: inherit; color: inherit; }
	.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__media { position: relative; inset: auto; z-index: auto; clip-path: none; }
	.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__media img { height: auto; object-position: center; }
	.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__dial { display: none; }
	.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__copy { position: relative; inset: auto; display: flex; opacity: 1; }
	.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__marker--stacked { display: inline; }
	.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__item-title { transform: none; }
	/* `color` aussi : l'encre calcaire du disque n'a rien a faire sur le fond de
	   page, et c'est le cas meme que ce produit a paye a 1,04:1. */
	.ivy-steps--cadran .ivy-steps__scene.ivy-scene-ready .ivy-steps__item-text { max-width: 52ch; margin: 0; transform: none; opacity: 1; color: var( --ivy-item_text-color, var( --ivy-muted, rgb( 88 96 104 ) ) ); }
}
