*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{background:#F5F0E8;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased}
/* Sous 820px le cadre est mis à l'échelle par `zoom` (voir relayout dans
   app.js) : le texte y est mis en page à sa taille réelle, souvent minuscule
   (20px de maquette -> ~5px). Sans ce verrou, l'ajustement automatique d'iOS
   gonflerait ces textes et romprait la maquette. Sans effet en mode transform,
   où le texte n'est que projeté. */
/* Verrou anti-inflation renforcé : en mode zoom (bucket de test v4), Safari iOS
   voulait regonfler les textes devenus petits. On coupe l'ajustement
   automatique sur la racine ET sur tout le cadre, en !important, pour qu'aucune
   heuristique de lisibilité ne contredise l'échelle. Sans effet en transform. */
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}
.or-framescale,.or-framescale *{-webkit-text-size-adjust:none!important;text-size-adjust:none!important}
a{text-decoration:none}
#app{min-height:100vh}
/* Le fond est OPAQUE par défaut, le flou réservé aux grands écrans.
   `backdrop-filter` sur un en-tête collant oblige le navigateur à prélever puis
   flouter, à chaque image de défilement, la zone du cadre située derrière — un
   cadre qui monte à 1512x11729px sur mobiles.html. Sur iPhone ce coût par frame
   s'ajoutait au reste jusqu'à faire tuer l'onglet.
   L'écart visuel est nul : le fond valait déjà rgba(245,240,232,.96).
   Seuil aligné sur mqMobile d'app.js. */
.or-header{position:sticky;top:0;z-index:500;border-bottom:1px solid rgba(0,0,0,.09)}
/* Fond porté par la rangée d'onglets (et non le header) : la sous-nav en verre
   teinté peut ainsi laisser voir le contenu de la page derrière elle. Opaque par
   défaut, flou réservé aux grands écrans (cf. note ci-dessus). */
.or-navscroll{display:flex;align-items:center;gap:9px;padding:10px 16px;overflow-x:auto;white-space:nowrap;scrollbar-width:none;justify-content:center;justify-content:safe center;background:#F5F0E8}
@media (min-width:821px){
  .or-navscroll{background:rgba(245,240,232,.96);-webkit-backdrop-filter:blur(9px);backdrop-filter:blur(9px)}
}
.or-navscroll::-webkit-scrollbar{height:0;display:none}
.or-logo{display:flex;align-items:center;gap:10px;flex:0 0 auto;padding-right:4px;color:#000}
.or-logo img{width:44px;height:44px;display:block}
.or-logo span{font-weight:700;font-size:14px;line-height:1.05}
.or-pill{flex:0 0 auto;font-weight:700;font-size:14px;padding:10px 15px;border-radius:24px;color:#000;box-shadow:inset 0 0 0 2px #FF7900;transition:background .15s,color .15s,transform .15s}
.or-pill:hover{background:rgba(255,121,0,.13);transform:scale(1.06)}
.or-pill.active{background:#FF7900;color:#fff;box-shadow:none}
/* Rubrique « Retour sur Orange.re » : à la suite des autres rubriques (pas de
   margin auto, elle suit simplement le flux). Bordure orange comme les autres,
   avec une petite icône maison orange à gauche du libellé. */
.or-backorange{flex:0 0 auto;display:flex;align-items:center;gap:7px;padding:10px 15px 10px 12px;border-radius:24px;color:#000;font-weight:700;font-size:14px;box-shadow:inset 0 0 0 2px #FF7900;transition:background .15s,transform .15s;white-space:nowrap}
.or-backorange svg{width:16px;height:16px;display:block;flex:0 0 auto}
.or-backorange:hover{background:rgba(255,121,0,.13);transform:scale(1.06)}

/* ---- Sous-nav des pages à sous-rubriques (2e rangée du header) --------------
   Rangée « verre teinté » sombre sous les onglets : fond noir translucide, texte
   blanc, sous-rubrique active en orange, et une fine barre de progression de
   lecture orange en bas (::after, pilotée par --or-progress depuis app.js).
   Le flou (liquid glass) est RÉSERVÉ au desktop : sous 821px, aucun
   backdrop-filter — au défilement, il faisait tuer l'onglet iPhone (même raison
   que le header, cf. note plus haut). Le fond du header ayant été déplacé sur
   .or-navscroll, cette rangée laisse voir le contenu de la page derrière elle.
   Les libellés défilent dans une piste interne .or-subnav-scroll : la barre de
   progression, elle, reste fixe (elle n'est pas dans la piste). La sous-nav reste
   toujours affichée : on ne la masque pas au défilement, sinon la barre de
   progression disparaîtrait avec elle. */
.or-subnav{position:relative;height:40px;overflow:hidden;background:rgba(0,0,0,.92);box-shadow:inset 0 1px 0 rgba(255,255,255,.12)}
/* barre de progression de lecture (bas de la sous-nav) */
.or-subnav::after{content:"";position:absolute;left:0;bottom:0;width:100%;height:3px;background:#FF7900;transform:scaleX(var(--or-progress,0));transform-origin:left;transition:transform .1s linear;pointer-events:none}
.or-subnav-scroll{display:flex;align-items:center;gap:6px;height:100%;padding:0 16px;overflow-x:auto;overflow-y:hidden;white-space:nowrap;scrollbar-width:none;justify-content:center;justify-content:safe center}
.or-subnav-scroll::-webkit-scrollbar{height:0;display:none}
.or-subnav-link{flex:0 0 auto;font-family:inherit;font-weight:600;font-size:13px;line-height:1;padding:7px 12px;border:none;border-radius:16px;background:none;color:rgba(255,255,255,.82);white-space:nowrap;cursor:pointer;transition:color .15s,background .15s}
.or-subnav-link:hover{color:#fff;background:rgba(255,255,255,.14)}
.or-subnav-link.is-current{color:#FF7900;background:rgba(255,121,0,.16)}
.or-subnav-link:focus-visible{outline:2px solid #FF7900;outline-offset:2px}
@media (min-width:821px){
  .or-subnav{background:rgba(0,0,0,.85);-webkit-backdrop-filter:blur(16px) saturate(1.3);backdrop-filter:blur(16px) saturate(1.3)}
}
/* ---- Header compact en vue mobile -----------------------------------------
   Sous 820px, on resserre le header pour qu'il mange moins de hauteur : logo
   (image + « Rentrée des classes ») plus petit, rubriques (.or-pill) et
   sous-rubriques (.or-subnav) réduites. Seuil aligné sur mqMobile d'app.js. */
@media (max-width:820px){
  .or-navscroll{gap:7px;padding:6px 12px}
  .or-logo{gap:7px;padding-right:2px}
  .or-logo img{width:32px;height:32px}
  .or-logo span{font-size:11px}
  .or-pill{font-size:12px;padding:6px 11px;border-radius:18px}
  .or-backorange{gap:6px;padding:6px 11px 6px 9px;font-size:12px;border-radius:18px}
  .or-backorange svg{width:14px;height:14px}
  .or-subnav{height:32px}
  .or-subnav-scroll{gap:5px;padding:0 12px}
  .or-subnav-link{font-size:11.5px;padding:5px 10px}
}
.or-stage{width:100%;margin:0 auto;position:relative}
.or-frameclip{overflow:hidden;width:100%}
/* flow-root : empêche la marge négative du crop de s'échapper du cadre.
   Sans ça le crop vaut 150px d'écran (donc 150/échelle px de design) au lieu de 150px de design. */
.or-framescale{width:1512px;transform-origin:top left;display:flow-root}
/* Cartes de l'accueil (créées par app.js) : le lien est un calque transparent,
   le zoom porte sur .or-cardzoom qui regroupe les éléments de la carte.
   Volontairement sans changement de couleur : seul un léger agrandissement. */
.or-cardlink{display:block;cursor:pointer}
/* Le zoom passe par --fx-zoom et non par un `transform` propre : la carte porte
   aussi .or-fx (apparition, parallaxe), et deux règles `transform` sur le même
   élément s'écraseraient. Voir le socle .or-fx plus bas. */
.or-cardzoom{transition:transform .28s cubic-bezier(.22,.61,.36,1);will-change:transform}
.or-cardzoom.is-hover{--fx-zoom:1.04}
@media (prefers-reduced-motion:reduce){.or-cardzoom{transition:none}}
.or-videoslot{background:#EAE2D3!important;cursor:pointer}
.or-videoslot::before{content:"";position:absolute;inset:16px;border:2px dashed rgba(0,0,0,.18);border-radius:18px}
.or-videoslot::after{content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:128px;height:128px;border-radius:50%;background:#FF7900 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M8 5v14l11-7z'/%3E%3C/svg%3E") no-repeat center/44px;box-shadow:0 12px 34px rgba(255,121,0,.45);transition:transform .2s}
.or-videoslot:hover::after{transform:translate(-50%,-50%) scale(1.09)}
/* Emplacement à la demande (VIDEOS_CLIC) : l'image fixe du film est déjà posée,
   on garde le bouton ▶ mais on retire le cadre pointillé, qui signale un
   emplacement vide. */
.or-videoslot.or-vidprete::before{display:none}
.or-videoslot.or-vidprete:focus-visible{outline:3px solid #FF7900;outline-offset:3px}
/* ---- Carrousels de section (mobile, voir CARROUSELS dans app.js) -----------
   Rail à défilement horizontal avec calage : une diapo fait 1512px de maquette,
   soit exactement la largeur de l'écran une fois le cadre mis à l'échelle.
   La barre de défilement est masquée, les pastilles servent de repère. */
/* Pas de -webkit-overflow-scrolling:touch : hérité d'avant iOS 13, où il
   fallait le demander ; depuis, tout défilement est accéléré d'office et la
   propriété ne fait que forcer une couche composite supplémentaire par rail. */
.or-rail{display:flex;overflow-x:auto;overflow-y:hidden;scroll-snap-type:x mandatory;
  scrollbar-width:none}
.or-rail::-webkit-scrollbar{height:0;display:none}
.or-rail>*{scroll-snap-align:start;scroll-snap-stop:always}

/* --or-inv est l'inverse de l'échelle du cadre, posé par relayout(). Sans lui
   ces pastilles seraient réduites avec le reste du plan et tomberaient à ~4px
   de haut sur un téléphone. */
.or-railpuces{display:flex;justify-content:center;align-items:center;
  gap:calc(9px * var(--or-inv,1));padding-top:calc(16px * var(--or-inv,1))}
.or-railpuce{flex:0 0 auto;padding:0;border:none;cursor:pointer;background:rgba(0,0,0,.22);
  width:calc(9px * var(--or-inv,1));height:calc(9px * var(--or-inv,1));border-radius:50%;
  transition:background .2s,transform .2s}
.or-railpuce.is-current{background:#FF7900;transform:scale(1.35)}

/* Flèches : sans geste de balayage, rien n'indiquerait sur ordinateur que le
   rail défile. Inutiles au doigt, elles disparaissent sous 820px. */
.or-railfleche{position:absolute;z-index:2;display:flex;align-items:center;justify-content:center;
  width:calc(46px * var(--or-inv,1));height:calc(46px * var(--or-inv,1));
  font-size:calc(20px * var(--or-inv,1));line-height:1;
  border:none;border-radius:50%;cursor:pointer;font-family:inherit;
  background:rgba(0,0,0,.55);color:#fff;
  box-shadow:0 calc(4px * var(--or-inv,1)) calc(14px * var(--or-inv,1)) rgba(0,0,0,.28);
  transition:background .18s,opacity .18s}
.or-railfleche--prec{left:calc(14px * var(--or-inv,1))}
.or-railfleche--suiv{right:calc(14px * var(--or-inv,1))}
.or-railfleche:hover{background:#FF7900}
.or-railfleche:disabled{opacity:.25;cursor:default}
.or-railfleche:focus-visible{outline:calc(3px * var(--or-inv,1)) solid #FF7900;
  outline-offset:calc(3px * var(--or-inv,1))}
@media (max-width:820px){ .or-railfleche{display:none} }
.or-railpuce:focus-visible{outline:calc(2px * var(--or-inv,1)) solid #FF7900;
  outline-offset:calc(3px * var(--or-inv,1))}
@media (prefers-reduced-motion:reduce){
  .or-rail{scroll-behavior:auto}
  .or-railpuce{transition:none}
}

/* ---- Bouton « haut de page » (retour en haut) ------------------------------
   Présent sur les SIX pages, en bas à droite. Invisible tant que la page n'a
   pas défilé (opacity/pointer-events pilotés par la classe .is-visible depuis
   app.js). Sur les pages à sous-rubriques, la sous-nav du header le complète. */
.or-backtop{position:fixed;z-index:400;right:20px;bottom:20px;width:50px;height:50px;border-radius:50%;border:none;cursor:pointer;background:#000;color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 8px 24px rgba(0,0,0,.32);opacity:0;pointer-events:none;transition:opacity .25s,transform .18s}
.or-backtop svg{display:block}
.or-backtop:hover{background:#FF7900;transform:scale(1.08)}
.or-backtop.is-visible{opacity:1;pointer-events:auto}

/* Retrait après quelques secondes d'inactivité (minuteur dans app.js) : le
   bouton s'estompe sans disparaître ni cesser de répondre, et redevient net au
   moindre défilement, survol, toucher ou passage du focus. */
.or-backtop.is-visible.is-idle{opacity:.25}
.or-backtop.is-visible.is-idle:hover{opacity:1}

@media (prefers-reduced-motion:reduce){
  .or-subnav,.or-subnav::after,.or-subnav-link,.or-backtop{transition:none}
}
.or-legal{padding:28px 26px 96px;max-width:1180px;margin:0 auto}
.or-rule{height:1px;background:rgba(0,0,0,.1);margin-bottom:16px}
.or-legal p{font-size:14px;line-height:1.55;color:rgba(0,0,0,.55);white-space:pre-wrap;margin:0}
/* Mentions légales de la page (construites par app.js). Hors du cadre Figma,
   donc en pixels réels : elles restent lisibles quelle que soit la largeur. */
/* marge basse généreuse : les mentions doivent respirer nettement au-dessus des
   liens légaux du portail, sinon les deux blocs se lisent comme un seul. */
.or-ml{margin-bottom:52px}
.or-ml h2{font-size:16px;font-weight:700;color:rgba(0,0,0,.65);margin:0 0 10px}
.or-ml p + p{margin-top:.55em}
.or-ml a{color:inherit;text-decoration:underline;transition:color .15s}
.or-ml a:hover{color:#FF7900}
/* Exposants posés sur les prix dans le cadre (app.js). nowrap : sans lui, le
   prix des blocs les plus étroits (129€ dans 230px) passe à la ligne. */
.or-sup{font-size:.42em;vertical-align:super;line-height:0;white-space:nowrap}
/* Le ** du bandeau « avec Avantage Famille » est posé sur un texte déjà petit
   (22px) : à .42em il devenait illisible, on le remonte à .7em. */
.or-sup-lg{font-size:.7em}
/* Liens légaux du footer : même taille que les mentions au-dessus (14px, gris),
   accent orange au survol. */
.or-legal-links{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;text-align:center;gap:9px 18px;font-size:14px;line-height:1.5}
.or-legal-links a{color:rgba(0,0,0,.55);text-decoration:none;transition:color .15s}
.or-legal-links a:hover{color:#FF7900;text-decoration:underline}
.or-legal-links b{font-weight:700}
.or-legal-links .or-copyright{color:rgba(0,0,0,.4)}
/* ---- Récapitulatif texte des références (bloc .or-seo des .html) -----------
   Remonté dans le pied de page par app.js, au-dessus des mentions légales.
   Même discrétion typographique que .or-ml : c'est un récapitulatif de fin de
   page, pas un second contenu qui viendrait concurrencer la maquette.
   white-space:normal annule le pre-wrap de « .or-legal p », prévu pour les
   mentions légales : sans lui, l'indentation du HTML source serait rendue. */
.or-seo{margin-bottom:52px;color:rgba(0,0,0,.55);font-size:14px;line-height:1.55;overflow-wrap:break-word}
.or-seo h1{font-size:18px;font-weight:700;color:rgba(0,0,0,.65);margin:0 0 10px}
.or-seo h2{font-size:16px;font-weight:700;color:rgba(0,0,0,.65);margin:22px 0 8px}
.or-seo p{white-space:normal;margin:0 0 8px}
.or-seo ul{margin:0 0 8px;padding-left:1.3em}
.or-seo li{margin-bottom:.4em}
.or-seo strong{font-weight:700;color:rgba(0,0,0,.7)}
.or-seo a{color:inherit;text-decoration:underline;transition:color .15s}
.or-seo a:hover{color:#FF7900}
.or-seo .or-seo-note{color:rgba(0,0,0,.45)}

/* ============================================================================
   ANIMATIONS D'APPARITION
   ============================================================================
   Le cadre Figma est peint d'un seul tenant : sans rien, la page se lit comme
   une image fixe qu'on fait défiler. On généralise ici l'idiome déjà employé
   pour le « 4ème accessoire à 1€ » (.or-add-item, custom-assets.css) à
   l'ensemble des blocs, en veillant à trois choses :

   1. l'état masqué n'est JAMAIS posé par la CSS seule — c'est app.js qui ajoute
      les classes. Sans JavaScript, ou sans IntersectionObserver, la page reste
      intégralement visible ;
   2. aucun élément du cadre n'est enveloppé : app.js retrouve ses blocs par
      leurs coordonnées de maquette parmi frame.children (parTop/parPosition) ;
   3. un seul `transform` par élément, composé par variables — voir ci-dessous.

   ---- Socle : transform composé -------------------------------------------
   Trois effets veulent bouger les mêmes éléments : l'apparition (--fx-y), le
   parallaxe (--fx-para) et le zoom au survol des cartes (--fx-zoom). Trois
   règles `transform` s'écraseraient l'une l'autre ; on n'en déclare donc
   qu'une, qui lit les trois variables. Chaque effet ne touche que la sienne. */
.or-fx{transform:translate3d(0,calc(var(--fx-y,0px) + var(--fx-para,0px)),0)
                scale(var(--fx-zoom,1))}
/* Sous 820px, translate 2D au lieu de translate3d : le `translate3d` promeut
   CHAQUE élément .or-fx en couche de composition à vie, rastérisée à la
   résolution retina par WebKit iOS — des dizaines de couches produit qui
   s'additionnent jusqu'à faire tuer l'onglet (mesuré via l'arbre des couches).
   Sur mobile le parallaxe est coupé et le zoom au survol n'existe pas : au
   repos le transform est identité, donc en 2D l'élément n'est pas promu et se
   peint dans le backing store du cadre. Desktop garde translate3d (parallaxe
   fluide sur GPU). */
@media (max-width:820px){
  .or-fx{transform:translate(0,calc(var(--fx-y,0px) + var(--fx-para,0px)))
                  scale(var(--fx-zoom,1))}
}

/* ---- Apparition au défilement ---------------------------------------------
   Fondu + montée de 20px.

   La `transition` n'est déclarée QUE sur l'état d'arrivée (.is-in). C'est
   indispensable : une transition est évaluée sur le style d'APRÈS changement,
   donc si .or-rev portait la transition, la simple pose de la classe par app.js
   ferait fondre toute la page vers l'invisible avant de la ramener. Sur .is-in,
   seul le trajet retour (0 -> 1) est animé, l'état masqué est pris d'emblée.

   Pas de `will-change` : une page en compte plusieurs centaines, la promotion
   systématique en couche graphique coûterait plus qu'elle ne rapporterait.
   app.js retire d'ailleurs les classes une fois la transition terminée. */
.or-rev{opacity:0;--fx-y:20px}
.or-rev.is-in{opacity:1;--fx-y:0px;
  transition:opacity .55s ease,transform .55s cubic-bezier(.2,.7,.3,1)}

/* ---- Titres de section ----------------------------------------------------
   Le texte se dévoile de bas en haut. clip-path plutôt qu'un masque : les
   blocs de titre sont des <span> absolus de la maquette, on ne peut ni les
   envelopper ni leur donner un overflow. Transition sur .is-in, même raison
   que ci-dessus. */
.or-revtitre{opacity:0;clip-path:inset(0 0 100% 0)}
.or-revtitre.is-in{opacity:1;clip-path:inset(0 0 0 0);
  transition:opacity .5s ease,clip-path .7s cubic-bezier(.2,.7,.3,1)}

/* ---- Dossiers orange ------------------------------------------------------
   Les calques décoratifs en forme de dossier (fig-asset-345c3b10bc488c48)
   dépassent du bord du cadre ou de derrière une photo produit. Ils entrent en
   glissant depuis le bord dont ils sortent — le dossier se pose sur la page
   plutôt que d'y être déjà.

   Leur transform est posé EN LIGNE par l'export Figma (une matrice de rotation
   et de position) : une règle de classe ne pourrait pas le battre. C'est donc
   app.js qui compose le déplacement avec cette matrice ; on ne déclare ici que
   la durée, et seulement sur l'état d'arrivée (même raison que .or-rev). */
.or-revdossier{opacity:0}
.or-revdossier.is-in{opacity:1;
  transition:opacity .6s ease,transform .85s cubic-bezier(.2,.7,.3,1)}

/* ---- Entrée du header au chargement ---------------------------------------
   Le logo puis les onglets, en cascade. Le délai est posé par app.js. */
.or-navscroll .or-revnav{opacity:0;transform:translateY(-6px)}
.or-navscroll .or-revnav.is-in{opacity:1;transform:none;
  transition:opacity .4s ease,transform .4s cubic-bezier(.2,.7,.3,1)}

/* ---- Transition entre les pages du mini-site -------------------------------
   Pas de @view-transition : le cadre est peint par JavaScript après l'analyse
   du document, la capture inter-documents donnerait un flash de page vide. On
   fond donc #app à la main, à la sortie comme à l'arrivée. La classe est posée
   sur <html> : #app n'existe pas encore au moment où app.js démarre.
   Seul #app est concerné — le fond de page reste peint, la bascule d'une page
   à l'autre ne passe pas par un écran blanc. */
html.or-nav-in #app{opacity:0;transform:translateY(8px)}
html.or-nav-ready #app{opacity:1;transform:none;
  transition:opacity .26s ease,transform .26s cubic-bezier(.2,.7,.3,1)}
html.or-nav-out #app{opacity:0;transform:translateY(-8px);
  transition:opacity .18s ease,transform .18s ease}

/* Sous 820px, le fondu passe par un VOILE fixe de la taille de l'écran (posé
   par app.js dans <body>), et #app n'est plus touché : une transition
   opacity+transform sur #app oblige WebKit à promouvoir toute la page — cadre
   géant compris — en couche composite, pile au chargement et à chaque
   navigation. Sur iPhone, cette allocation participait à faire tuer le
   processus de rendu de l'onglet. Le voile borne la couche à un écran (~12 Mo
   à DPR 3) et elle disparaît une fois le fondu terminé.
   Même chorégraphie que #app : couvrant à l'arrivée (or-nav-in), fondu à
   l'ouverture (or-nav-ready), recouvrant à la sortie (or-nav-out — déclaré
   après ready, il l'emporte à spécificité égale). */
@media (max-width:820px){
  html.or-nav-in #app,html.or-nav-ready #app,html.or-nav-out #app{
    opacity:1;transform:none;transition:none}
  .or-voile{position:fixed;inset:0;z-index:600;background:#F5F0E8;
    pointer-events:none;opacity:1}
  html.or-nav-ready .or-voile{opacity:0;transition:opacity .3s ease}
  html.or-nav-out .or-voile{opacity:1;transition:opacity .18s ease}
}
@media (min-width:821px){.or-voile{display:none}}

@media (prefers-reduced-motion:reduce){
  /* On neutralise les DÉPLACEMENTS, pas le zoom au survol des cartes : un
     agrandissement instantané au pointeur n'est pas du mouvement subi. */
  .or-fx{--fx-y:0px;--fx-para:0px}
  .or-rev,.or-rev.is-in{opacity:1;transition:none}
  .or-revtitre,.or-revtitre.is-in{opacity:1;clip-path:none;transition:none}
  .or-revdossier,.or-revdossier.is-in{opacity:1;transition:none}
  .or-navscroll .or-revnav{opacity:1;transform:none;transition:none}
  html.or-nav-in #app,html.or-nav-ready #app,html.or-nav-out #app{
    opacity:1;transform:none;transition:none}
  html.or-nav-ready .or-voile,html.or-nav-out .or-voile{transition:none}
}

/* ---- Animations décoratives bridées sur téléphone --------------------------
   Une animation infinie promeut son élément en couche graphique à vie,
   repeinte à chaque image ; or-bg-pulse, or-sway et or-spin couvraient à elles
   seules 18 des 20 Mpx animés en permanence, sur les plus grands visuels de la
   page. C'est ce qui restait à payer pendant les défilements rapides, quand
   WebKit élargit sa zone de rastérisation à proportion de la vitesse, et c'est
   ce qui participait à faire tuer l'onglet par iOS.

   Trois régimes :
   - or-bg-pulse et or-spin (auréoles, anneaux) : COUPÉES — à l'échelle 0,26
     leur battement vaut 2px, imperceptible ;
   - or-sway (balancier des produits) : CONSERVÉ à la demande du client, mais
     figé par défaut et animé seulement à l'écran (voir app.js) ;
   - les clignotements commerciaux (pastilles de remise, « Découvrir ici »,
     carte KomZot) : CONSERVÉS tels quels — 2 Mpx, et ils portent un prix.

   Sélecteurs repris mot pour mot de custom-assets.css : à spécificité égale,
   c'est la position dans la cascade qui départage, et app.css vient après.
   Bornes de la requête identiques à mobile-assets.css. */
@media (max-width: 820px), (max-height: 520px) and (pointer: coarse) {
  /* Balancier or-sway des PRODUITS : conservé sur mobile (demande client),
     mais figé par défaut — app.js ne fait tourner que ceux présents dans
     l'écran (2-3 couches GPU actives à la fois au lieu de la page entière).
     Visuellement identique : une animation hors écran ne se voit pas. */
  .fig-asset-5bd670845e7ec725{ animation-play-state: paused }
  .fig-asset-bb56912dd51de4fb-46035770{ animation-play-state: paused }
  .fig-asset-7028ccd9c8132a99{ animation-play-state: paused }
  .fig-asset-785539f4b694622a-b40651f7{ animation-play-state: paused }
  .fig-asset-052c3d67f301a4b3[style*="721.857px"]{ animation-play-state: paused }
  .fig-asset-ce3174d6c3e2c696-c6f13d53{ animation-play-state: paused }
  .fig-asset-06e325ae3dbe73c3[style*="698.544px"]{ animation-play-state: paused }
  .fig-asset-d60804b24f3f0a3a[style*="matrix"]{ animation-play-state: paused }
  .fig-asset-71f3557fdd790d20[style*="462.344px"]{ animation-play-state: paused }
  .fig-asset-c1b627339d252f23[style*="422.567px"][style*="matrix"]{ animation-play-state: paused }
  .fig-asset-356ebbfb5a77b79d-c9da8ab8{ animation-play-state: paused }
  .fig-asset-4b20c06b2b7adb47{ animation-play-state: paused }
  .fig-asset-47598c1a1bb3bbeb[style*="top: 813px"]{ animation-play-state: paused }
  .fig-asset-ce3174d6c3e2c696{ animation-play-state: paused }
  .fig-asset-29a87b1a6c630dcb:not([style*="741px"]), .fig-asset-7dd09b8477e2b613:not([style*="676px"]), .fig-asset-fb908d497dffc0eb, .fig-asset-fb908d497dffc0eb-ea7b79fa{ animation: none }
  /* Balancement or-spin* de l'accueil : c'est le MÊME balancier de produits
     que or-sway, sous un autre nom — les visuels des quatre cartes (mobiles,
     accessoires, box, photo famille) oscillent de ±3°. Conservé à la demande
     du client, même régime que or-sway : figé par défaut, animé à l'écran par
     app.js.

     Deux cas particuliers :
     - la photo famille (c893…) : sa position d'origine vit dans la MATRICE
       transform en ligne de l'export Figma, que les keyframes rotate-only
       d'or-spin écrasent — d'où son repositionnement en left/top !important
       par custom-assets.css. `animation:none` lui rendrait la matrice et
       l'enverrait au double de sa position : elle reste donc TOUJOURS en
       animation (paused/running), jamais coupée ;
     - le dossier orange (345c…541.732px) : le client a demandé des dossiers
       immobiles sur mobile — coupé net, lui. */
  .fig-asset-c893338796b8d91a{ animation-play-state: paused }
  .fig-asset-c1b627339d252f23[style*="256.998px"]{ animation-play-state: paused }
  .fig-asset-06e325ae3dbe73c3[style*="450.048px"]{ animation-play-state: paused }
  .fig-asset-bb56912dd51de4fb-15edc61f{ animation-play-state: paused }
  .fig-asset-71f3557fdd790d20[style*="267.365px"]{ animation-play-state: paused }
  .fig-asset-052c3d67f301a4b3[style*="380.684px"]{ animation-play-state: paused }
  .fig-asset-345c3b10bc488c48[style*="541.732px"]{ animation: none }
  .fig-asset-356ebbfb5a77b79d-d4dd711b{ animation-play-state: paused }
  .fig-asset-f9ee286f4e3a1ef3{ animation-play-state: paused }
  .fig-asset-37851fe0a4689c2c{ animation-play-state: paused }
  /* Wrappers de zoom au survol des cartes de l'accueil : le survol n'existe
     pas au doigt, et leur will-change promeut en couche À VIE quatre calques
     qui couvrent 100% du cadre (voir leur création dans app.js). */
  .or-cardzoom{ will-change: auto; transition: none }
  /* Cascade « 4ème accessoire à 1€ » : chaque produit entre une seule fois au
     scroll, mais son `will-change:transform` le promeut en couche retina À VIE.
     Sur accessoires, cette dizaine de couches 930×930 pesait le plus lourd de
     tout le site (arbre des couches). On retire will-change : la transition
     unique se joue très bien sans, et le produit se repeint ensuite dans le
     backing store du cadre au lieu de tenir sa propre couche. */
  .or-add-item{ will-change: auto }
}
