/* ============================================================
   Shared shell: tokens, reset, header, footer, buttons, layout.
   Page-specific styling goes in that page's own <style> block.
   ============================================================ */

/* Self-hosted, variable, one file per family. Never link fonts.googleapis.com. */
@font-face{
  font-family:'Gambetta';
  src:url('../fonts/gambetta-variable.woff2') format('woff2');
  font-weight:300 700; font-style:normal; font-display:swap;
}
@font-face{
  font-family:'Switzer';
  src:url('../fonts/switzer-variable.woff2') format('woff2');
  font-weight:100 900; font-style:normal; font-display:swap;
}
/* The display face. Headlines and section heads only — it has one weight and no
   lowercase worth using at text size. `block` rather than `swap`: a headline
   this large swapping from a fallback mid-read is worse than a short wait. */
@font-face{
  font-family:'Archivo Black';
  src:url('../fonts/archivo-black.woff2') format('woff2');
  font-weight:400; font-style:normal; font-display:block;
}

:root{
  --platre:   #D4DDF7;  /* the page ground: tinted toward the brand colour,
                           so the white blocks read as objects on a surface
                           rather than outlines drawn on paper */
  --vert:     #1140C4;  /* the brand colour: hero, process block, footer */
  --vert-f:   #0E35A3;  /* pressed states */
  --laiton:   #FFB627;  /* the accent. On the brand colour, never on the ground. */
  /* Translucent steps of the accent, declared rather than written inline as
     rgba(). A hex repeated by hand in eight rules is not a token — recolouring
     the site then misses whichever ones you forget. */
  --laiton-85: rgba(255,182,39,0.85);
  --laiton-75: rgba(255,182,39,0.75);
  --laiton-60: rgba(255,182,39,0.60);
  --laiton-55: rgba(255,182,39,0.55);
  --laiton-30: rgba(255,182,39,0.30);
  --laiton-10: rgba(255,182,39,0.10);
  --laiton-07: rgba(255,182,39,0.07);
  /* The six tile colours in How it works. Chosen together: each clears 3.4:1
     against the brand colour so it reads as a distinct shape, and carries ink
     text at 4.5:1. Picking them by eye put two of them below both. */
  --tuile-1:  #FF7AB6;
  --tuile-2:  #B2FF00;
  --tuile-3:  #FFB627;  /* the accent again: nothing blue or green sits on the brand colour */
  --tuile-4:  #FF871F;
  --tuile-5:  #FF837A;
  --tuile-6:  #F7E733;  /* 6.43:1 on the brand colour, 14.17:1 for ink */
  --craie:    #FFFFFF;  /* text on the brand colour */
  --craie-2:  rgba(255,255,255,0.78);  /* secondary */
  --craie-3:  rgba(255,255,255,0.68);  /* tertiary */
  --encre:    #121525;
  --encre-2:  #4A4F63;  /* secondary text on the ground */

  --font-head:'Gambetta', Georgia, 'Times New Roman', serif;   /* 404 only now */
  --font-display:'Archivo Black', 'Switzer', system-ui, sans-serif;
  --font-body:'Switzer', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --header-h:  78px;
  /* How deep the curved section edges cut. Declared here because two things
     need the same number: the curve itself, drawn in site.js, and the hero's
     height, which has to clear it so no curve shows before you scroll. Written
     twice they drift apart and the curve creeps back above the fold. */
  --courbe:    clamp(52px, 5.5vw, 96px);
  --section-y: 148px;   /* one vertical rhythm everywhere */
  --maxw:      1180px;
  --marge:     4.2vw;   /* the cream mount around the plaque */
}

*{box-sizing:border-box;}

/* The body is the brand blue and <main> carries the tint: Safari on iPhone
   paints its own toolbars in the body's background colour (theme-color is
   only a suggestion to it since Safari 26), and a tinted body gave the site
   pale bars under a blue footer. Every page wraps its content in <main>, and
   the blue sections paint their own ground, so nothing else moves. */
body{
  margin:0; background:var(--vert); color:var(--encre);
  font-family:var(--font-body); font-size:17px; line-height:1.65;
  -webkit-font-smoothing:antialiased;
  transition:opacity .24s ease;
}
main{background:var(--platre);}
/* Leaving for another page: site.js adds the class and follows the link a
   moment later, so the page fades to its blue and the next hero rises out of
   the same blue instead of cutting in. Cleared again on pageshow. */
html.quitte body{opacity:0;}
/* Arriving: the page fades in from that same blue over the first half second,
   so a change of page is one movement — out through the blue, in from it —
   with nothing cutting in. An animation rather than a resting state: it ends
   at full opacity by itself, whatever the script does. Fill mode backwards,
   not both: a finished animation that kept holding opacity would sit on top
   of the fade-out above and the page would cut away instead of fading. */
html.anime body{animation:arrivee .5s ease backwards;}
@keyframes arrivee{from{opacity:0;} to{opacity:1;}}
img{max-width:100%; display:block;}
/* An author `display` beats the browser's built-in [hidden]. Set once, globally. */
[hidden]{display:none !important;}

/* Editorial scale: the headline is set as a composition, not as running text —
   tight leading, negative tracking, and a hard cap on the measure. */
h1,h2,h3{margin:0 0 18px;}
h1{font-family:var(--font-head); font-weight:600;
   font-size:clamp(2.4rem,5.2vw,4.6rem); line-height:1.055; letter-spacing:-0.023em;}
/* Section heads sit close to headline size, the way the studio sites do —
   38px against a 74px h1 read as a label rather than as a heading. */
h2{font-family:var(--font-head); font-weight:600;
   font-size:clamp(2rem,3.9vw,3.3rem); line-height:1.08; letter-spacing:-0.026em;
   max-width:20ch;}
h3{font-family:var(--font-body); font-size:1.0625rem; font-weight:600; line-height:1.35;}
p{margin:0 0 18px; max-width:62ch;}
a{color:inherit;}
@media (max-width:640px){ body{font-size:16px;} }

.wrap{max-width:var(--maxw); margin:0 auto; padding:0 40px;}
.section{padding:var(--section-y) 0;}
section[id]{scroll-margin-top:calc(var(--header-h) + 16px);}
@media (max-width:640px){
  :root{--section-y:88px; --marge:22px;}
  .wrap{padding:0 22px;}
}

/* ---------- header ----------
   Absolute, not fixed: it belongs to the first screen and scrolls away with it.
   The hero reaches the top of the page, so the header sits on the brand colour
   and its text is set for that, not for the ground. */
header{
  position:absolute; top:0; left:0; right:0; z-index:30; height:var(--header-h);
  display:flex; align-items:center;
}
/* The header belongs to the first screen and scrolls away with it. Past that,
   scrolling up brings it back as a solid bar that slides in, and scrolling
   down slides it away again, so it never sits over what you are reading.
   site.js sets the classes; .instant covers the two hand-overs between the
   laid-out header and the bar, which must not animate. */
header.fixe{position:fixed; background:transparent; transform:translateY(-100%); transition:transform .38s cubic-bezier(.2,.7,.2,1);}
/* The bar looks the same wherever it is, at the top of the page or on its
   way back: the brand, the links, the language pill and the menu button are
   each the site's own object — a white pill with the 2px ink outline and ink
   text, the same thing as the buttons and the question cards — which reads
   on the blue sections and on the tint alike. Nothing switches as the ground
   changes underneath. */
header.fixe.visible{transform:none;}
header.instant{transition:none;}
@media (prefers-reduced-motion:reduce){ header.fixe{transition:none;} }
.header-inner{
  width:100%; margin:0 auto; padding:0 calc(var(--marge) + 22px);
  display:flex; align-items:center; justify-content:space-between; gap:24px;
}
.brand{
  position:relative; z-index:31;   /* above the phone menu panel, which is a child of this header */
  display:flex; align-items:center;
  text-decoration:none; color:var(--craie);   /* white: at the top of the page the header sits on the hero */
}
/* Once the header has become a floating bar it can pass over the tint as well
   as the blue, and white letters would vanish there. So the wordmark takes the
   same white pill the rest of the bar wears, and only then. */
header.fixe .brand{
  color:var(--encre);
  padding:6px 13px; margin:-8px -15px;
  border:2px solid var(--encre); border-radius:999px; background:var(--craie);
}
/* The wordmark is drawn, not set: five letterforms cut on one grid with a
   single stroke weight and a single 45-degree chamfer, the O sliced through.
   Inlined so it costs no request; the letters take the header's colour and the
   full stop stays gold, because on this site gold is the drawn line. */
.marque-solva{height:26px; width:auto; display:block;}
@media (max-width:860px){ .marque-solva{height:20px;} }   /* the phone header is tighter */
.header-right{display:flex; align-items:center; gap:22px;}
/* The links sit in the white pill; a link lights a tint pill of its own on
   hover, and the page you are on holds a gold one, as the language pills in
   the phone menu do. Set in the headline face, small, like the stickers. */
nav.links{
  display:flex; align-items:center; gap:4px;
  background:var(--craie); border:2px solid var(--encre); border-radius:999px; padding:4px 8px;
}
nav.links a{
  font-family:var(--font-display); font-size:13.5px; letter-spacing:0.005em;
  padding:7px 14px; border-radius:999px; text-decoration:none; color:var(--encre);
  transition:background .22s ease, color .22s ease;
}
nav.links a:hover{background:var(--platre);}
nav.links a.active{background:var(--laiton);}   /* the page you are on, set by site.js */
/* Language menu: a <details>, so it opens with no script at all. The list
   links to the equivalent page in each language, each on its own URL. The markup
   is commented out in the pages until those languages exist. */
.langues{position:relative; font-family:var(--font-display); font-size:13.5px; letter-spacing:0.005em; color:var(--encre);}
.langues summary{
  list-style:none; cursor:pointer; display:flex; align-items:center; gap:8px;
  padding:7px 13px 7px 15px; border-radius:999px; background:var(--craie); border:2px solid var(--encre);
  transition:background .22s ease;
}
.langues summary::-webkit-details-marker{display:none;}
.langues summary::after{
  content:""; width:6px; height:6px; border-right:2px solid currentColor; border-bottom:2px solid currentColor;
  transform:translateY(-2px) rotate(45deg); transition:transform .22s ease;
}
.langues[open] summary::after{transform:translateY(1px) rotate(225deg);}
.langues summary:hover,.langues[open] summary{background:var(--platre);}
.langues-menu{
  position:absolute; right:0; top:calc(100% + 8px); min-width:168px; margin:0; padding:6px; list-style:none;
  background:var(--craie); color:var(--encre); border:2px solid var(--encre); border-radius:18px;
  box-shadow:0 14px 34px rgba(12,46,141,0.28); z-index:5;
}
.langues-menu li{margin:0;}
.langues-menu a{
  display:flex; justify-content:space-between; align-items:center; gap:16px;
  padding:9px 12px; border-radius:12px; text-decoration:none; color:inherit; font-size:13.5px;
  transition:background .18s ease;
}
.langues-menu a:hover{background:var(--platre);}
.langues-menu a[aria-current="page"]{background:var(--vert); color:var(--craie);}
.langues-menu small{font-family:var(--font-body); font-weight:600; font-size:11px; opacity:.72;}
.langues-panneau{display:none;}
.menu-toggle{
  display:none; background:var(--craie); border:2px solid var(--encre); font-size:22px; cursor:pointer;
  color:var(--encre); padding:4px 6px; line-height:1; border-radius:999px;
  transition:transform .45s cubic-bezier(.19,1,.22,1);
}
@media (max-width:860px){
  /* The menu is the whole screen: the four links in the headline face, the
     language choice at the foot. The header stays on top of it (z-index 30
     over 20) so the brand and the cross remain; site.js swaps the hamburger
     for the cross, hides the language pill and locks the scroll while open. */
  nav.links{
    position:fixed; inset:0; background:var(--vert); border:0;
    border-radius:0; padding:calc(var(--header-h) + 28px) 22px 36px; z-index:20;
    flex-direction:column; align-items:flex-start; justify-content:flex-start; gap:6px;
    /* A curtain drawn down from the header, the links rising into it one
       after another and the language pills last; closing runs the other way,
       faster, and hides the panel from focus once it is up. */
    clip-path:inset(0 0 100% 0); visibility:hidden;
    transition:clip-path .4s cubic-bezier(.4,0,.2,1), visibility 0s .4s;
  }
  nav.links.open{clip-path:inset(0 0 0 0); visibility:visible; transition:clip-path .6s cubic-bezier(.19,1,.22,1), visibility 0s;}
  nav.links > a{opacity:0; transform:translateY(26px); transition:opacity .25s ease, transform .3s ease;}
  nav.links.open > a{opacity:1; transform:none; transition:opacity .5s ease, transform .8s cubic-bezier(.19,1,.22,1);}
  nav.links.open > a:nth-child(1){transition-delay:.16s;}
  nav.links.open > a:nth-child(2){transition-delay:.23s;}
  nav.links.open > a:nth-child(3){transition-delay:.30s;}
  nav.links.open > a:nth-child(4){transition-delay:.37s;}
  .langues-panneau{opacity:0; transition:opacity .2s ease;}
  nav.links.open .langues-panneau{opacity:1; transition:opacity .5s ease .5s;}
  html.menu-ouvert .menu-toggle{transform:rotate(90deg);}
  nav.links a{
    font-family:var(--font-display); text-transform:uppercase;
    font-size:clamp(2rem,9.5vw,2.8rem); line-height:1; letter-spacing:-0.02em;
    color:var(--craie); padding:10px 0; border-radius:0; background:none;
  }
  nav.links a:hover,nav.links a.active{background:none; color:var(--laiton);}
  .langues-panneau{display:flex; gap:10px; margin-top:auto; padding-top:28px; width:100%;}
  nav.links .langues-panneau a{
    font-size:15px; letter-spacing:0.02em; padding:9px 14px; border-radius:999px;
    border:2px solid rgba(255,255,255,0.35); color:var(--craie);
  }
  nav.links .langues-panneau a[aria-current]{background:var(--laiton); border-color:var(--laiton); color:var(--encre);}
  .menu-toggle{display:block; font-size:24px; width:40px; height:40px; padding:0; position:relative; z-index:31;}
  html.menu-ouvert .langues{display:none;}
  html.menu-ouvert{overflow:hidden;}
  .header-right{gap:12px;}   /* the language menu stays, beside the hamburger */
}
@media (prefers-reduced-motion:reduce){ nav.links,nav.links > a,.langues-panneau,.menu-toggle,body{transition:none;} html.anime body{animation:none;} }

/* ---------- buttons ----------
   A filled pill with a hard 2px outline. Same weight of line as the blocks and
   the tiles, so the whole page reads as one set of objects. On hover the gold
   fills the pill from the bottom up — the same upward movement as the hero
   copy arriving — carried by a pseudo-element so no markup changes. */
.btn{
  position:relative; isolation:isolate; overflow:hidden;
  display:inline-block; padding:17px 34px; border-radius:999px;
  border:2px solid var(--encre); cursor:pointer;
  font-family:inherit; font-size:15px; font-weight:700; letter-spacing:0.005em;
  text-decoration:none; background:var(--craie); color:var(--encre);
  transition:color .25s ease, border-color .25s ease;
}
.btn::before{
  content:""; position:absolute; inset:-2px; z-index:-1; background:var(--laiton);
  transform:translateY(101%); transition:transform .34s cubic-bezier(.2,.7,.2,1);
}
.btn:hover::before,.btn:focus-visible::before{transform:translateY(0);}
.btn:hover{color:var(--encre);}
.btn:active::before{background:#F0A81E;}
/* the second, quieter action: outlined in the accent on the brand colour */
.btn-ligne{
  background:none; color:var(--craie); border-color:var(--laiton);
}
.btn-ligne:hover{color:var(--encre);}
@media (prefers-reduced-motion:reduce){ .btn,.btn::before{transition:none;} }

/* On a phone every button is a size down — 14px, 47px tall — so a pill sits
   under a headline in weight rather than beside it; the hero sets that scale
   and the closing card, the form and the 404 follow it. Footer links get room
   to be tapped: a bare 18px line is under the 24px a finger needs. */
@media (max-width:900px){
  .btn{font-size:14px; line-height:1.25; padding:13px 24px;}
}
@media (max-width:640px){
  footer a{display:inline-block; padding:6px 0;}
}

/* ---------- footer ---------- */
footer{background:var(--vert); color:var(--craie-2); padding:72px 0 30px; position:relative; z-index:2;}
.footer-grid{
  max-width:var(--maxw); margin:0 auto; padding:0 40px 34px;
  display:grid; grid-template-columns:1.5fr 1fr 1fr; gap:44px;
  border-bottom:1px solid rgba(247,246,242,0.16);
}
@media (max-width:760px){.footer-grid{grid-template-columns:1fr; gap:32px;}}
footer h2{color:var(--craie); font-size:14px; margin:0 0 14px;
          font-family:var(--font-body); font-weight:600; letter-spacing:0.01em;}
footer p, footer a{font-size:14px; line-height:1.9; color:var(--craie-2); text-decoration:none;}
footer a:hover{color:var(--craie);}
.footer-bottom{
  max-width:var(--maxw); margin:0 auto; padding:24px 40px 0; font-size:13px;
  display:flex; justify-content:space-between; flex-wrap:wrap; gap:10px;
  color:var(--craie-3);
}
@media (max-width:640px){.footer-grid,.footer-bottom{padding-left:22px;padding-right:22px;}}

/* ---------- scrollbar ----------
   "Only the gold thing." A native scrollbar always owns a strip of its own
   beside the content and paints the canvas colour behind the thumb, so a
   thumb floating over the page has to be drawn: the native bar is hidden and
   site.js keeps a fixed gold pill at the right edge in step with the scroll,
   draggable. Native scrolling is never touched. Both halves are gated on the
   class the script sets, so with no script the browser's own bar stays; and
   only on hover-capable screens, since touch screens draw their own. */
html.defile{scrollbar-width:none;}
html.defile::-webkit-scrollbar{display:none;}
.defileur{
  position:fixed; top:0; right:5px; width:6px; z-index:40; border-radius:999px;
  background:var(--laiton); opacity:.92; cursor:grab; touch-action:none;
  transition:opacity .3s ease, width .2s ease, right .2s ease;
}
.defileur:hover,.defileur.saisi{width:9px; right:3.5px; opacity:1;}
.defileur.saisi{cursor:grabbing;}

/* ---------- focus visibility ---------- */
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible{
  outline:2px solid var(--laiton); outline-offset:3px;
}
/* ---------- smooth scrolling ----------
   Lenis (self-hosted, pinned) eases the wheel and trackpad; touch stays
   native. It is not started for people who ask for reduced motion, and if
   the script never runs the browser scrolls as it always did. No CSS
   scroll-behavior: it fights the script's own easing on anchor links. */
html{background:var(--vert);}   /* what shows when a phone overscrolls past the top or the bottom: blue, never white */
html.lenis, html.lenis body{height:auto;}
.lenis.lenis-smooth{scroll-behavior:auto !important;}
.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain;}
.lenis.lenis-stopped{overflow:hidden;}

/* ---------- motion shared by every page ----------
   Masks, the hero entrance, the scroll reveals, and their reduced-motion
   switches. Gated on .anime, which each page's head grants and takes back if
   site.js never claims it: text must never depend on an animation.
   The hero copy is the one entrance on the page: a 36px rise on a long
   expo-out ease, headline first, then the lead, then the buttons, while the
   line draws behind them. Everything further down arrives with a quieter
   18px rise on the same curve, so the hero is the only place the page moves
   this much, and nothing anywhere snaps into place. Gated on
   `.anime`, which the head script grants and takes back if site.js never
   claims it: text must never depend on an animation. */
/* Each headline line, then the lead, rises out of its own clipped box; the
   buttons follow with a plain rise. clip-path rather than overflow:hidden so
   the mask can hang past the line box (caps sit tight in a .93 line-height)
   without adding a pixel to the layout. */
.ligne{display:block; clip-path:inset(-.14em -50vw -.08em -50vw);}   /* clips only above and below: a word wider than its column must not lose its end */
.ligne > span{display:block;}
.anime .plaque .ligne > span{ animation:lever 1.6s cubic-bezier(.19,1,.22,1) backwards; }   /* long enough to be seen arriving, on the same curve */
@keyframes lever{ from{ transform:translateY(115%); } }
.anime .plaque h1 .ligne:nth-child(1) > span{ animation-delay:.1s; }
.anime .plaque h1 .ligne:nth-child(2) > span{ animation-delay:.3s; }
.anime .plaque .lead .ligne > span{ animation-delay:.62s; }
.anime .plaque .actions{ animation:monter 1.4s cubic-bezier(.19,1,.22,1) .82s backwards; }
@keyframes monter{ from{ opacity:0; transform:translateY(28px); } }
.anime .reveal,
.anime .reveal-groupe > *{ opacity:0; }
.anime .reveal.in-view,
.anime .reveal-groupe.in-view > *{ animation:surgir 1s cubic-bezier(.19,1,.22,1) both; }   /* the same long expo curve as the hero, so nothing on the page pops */
@keyframes surgir{
  from{ opacity:0; transform:translateY(18px); }
  to  { opacity:1; transform:none; }
}
.anime .reveal-groupe.in-view > :nth-child(2){ animation-delay:.07s; }
.anime .reveal-groupe.in-view > :nth-child(3){ animation-delay:.14s; }
.anime .reveal-groupe.in-view > :nth-child(4){ animation-delay:.21s; }
.anime .reveal-groupe.in-view > :nth-child(5){ animation-delay:.28s; }
.anime .reveal-groupe.in-view > :nth-child(n+6){ animation-delay:.35s; }
/* a heading block whose lines rise out of their masks when it scrolls into view */
.anime .reveal-lignes .ligne > span{ transform:translateY(115%); }
.anime .reveal-lignes.in-view .ligne > span{
  transform:none;   /* or the implicit end keyframe is the hidden state above */
  animation:lever .95s cubic-bezier(.19,1,.22,1) both;
  animation-delay:calc(var(--i, 0) * .07s);   /* after the shorthand, which would reset it; --i is the line's index in its block, set by site.js */
}
.anime .reveal-lignes .btn.reveal.in-view{ animation-delay:.3s; }
/* On a phone the text is simply there — headings, lines, groups, buttons —
   because every block fills the screen at that width and any wait before a
   heading read as blank space. What moves there are the objects: the step
   tiles and the question cards, tied to the scroll by site.js ("phones:
   arrivals tied to the scroll"), with their waiting states set on the page
   that has them. The timed animations stay off here. */
@media (max-width:900px){
  .anime .reveal,.anime .reveal-groupe > *{ opacity:1; }
  .anime .reveal-lignes .ligne > span{ transform:none; }
  .anime .reveal.in-view,.anime .reveal-groupe.in-view > *{ animation:none; }
  .anime .reveal-lignes.in-view .ligne > span{ animation:none; }
}
@media (prefers-reduced-motion:reduce){
  .anime .cartes .carte,.anime .etapes .marque{ opacity:1; transform:none; animation:none; }
  .anime .ligne > span,.anime .plaque .actions{ animation:none; }
  .anime .reveal-lignes .ligne > span{ transform:none; }
  .anime .reveal,.anime .reveal-groupe > *{ opacity:1; }
  .anime .reveal.in-view,.anime .reveal-groupe.in-view > *{ animation:none; }
}

/* ---------- the billboard ----------
   Decoration repeating a name that is already in the header and the footer,
   so it is hidden from screen readers rather than read out sixteen times.
   Two identical halves shifted by exactly 50% is what makes the loop seamless. */
.bandeau{
  background:var(--laiton); border-top:2px solid var(--encre);
  border-bottom:2px solid var(--encre);
  overflow:hidden; position:relative; z-index:2; padding:18px 0;
}
.bandeau-piste{display:flex; width:max-content; animation:defiler 26s linear infinite;}
.bandeau-piste span{
  /* The font-size is still what sets the rhythm: the side padding and the dots
     below are both in em, so one value keeps the whole band in proportion. */
  font-size:clamp(2rem,4.4vw,3.6rem); line-height:1;
  color:var(--encre); padding:0 .38em; white-space:nowrap;
  display:flex; align-items:center;
}
/* Height matches the cap height the type had: the viewBox is exactly the
   letters, so 0.73 of the font-size lands the mark at the same size. */
.bandeau-piste svg{display:block; height:clamp(1.46rem,3.2vw,2.63rem); width:auto;}
.bandeau-piste i{
  align-self:center; flex:none; width:.5em; height:.5em; border-radius:50%;
  background:var(--encre); font-size:clamp(2rem,4.4vw,3.6rem);
}
@keyframes defiler{ from{transform:translateX(0)} to{transform:translateX(-50%)} }
@media (prefers-reduced-motion:reduce){ .bandeau-piste{animation:none;} }

/* ---------- stickers ----------
   Used on the hero and the contact band; each page positions its own with
   .b1, .b2 ... and times the pops. */
/* The badges. Each carries something already true and already elsewhere on
   this page — the reference's are review counts and years trading, which
   would be inventing facts about the business. */
.pastille{position:absolute; z-index:3; pointer-events:none; transform:rotate(var(--incl,0deg));}
/* Three layers: .pastille places the sticker and pops it in; .corps carries
   its size and any ambient motion (a bob, a flutter); .forme is the shape,
   which can turn under the text without the words moving. Four silhouettes —
   spiked, scalloped, notched, and a bubble — all stickers on the same poster.
   The words are set in the headline face, small and in sentence case. */
.corps{
  position:relative; display:flex; align-items:center; justify-content:center; text-align:center;
  font-family:var(--font-display); font-weight:400; font-size:clamp(11px,.8vw,13px);
  line-height:1.22; color:var(--encre);
}
.corps > span{position:relative; z-index:1; display:block;}   /* a block, or the <b> inside splits it and leaves an empty line box */
.corps b{font-weight:inherit; display:block;}   /* one weight in this face: no faux bold */
.forme{position:absolute; inset:0; background:var(--craie);}
.p-etoile .corps,.p-sceau .corps{font-size:clamp(12.5px,.95vw,15px);}   /* the round ones have room, and turn */
.p-etoile .corps{padding:0 24px; width:clamp(128px,10.5vw,164px); height:clamp(128px,10.5vw,164px);}
.p-etoile .forme{
  background:var(--laiton);
  clip-path:polygon(50.0% 0.0%,60.1% 12.3%,75.0% 6.7%,77.6% 22.4%,93.3% 25.0%,87.7% 39.9%,100.0% 50.0%,87.7% 60.1%,93.3% 75.0%,77.6% 77.6%,75.0% 93.3%,60.1% 87.7%,50.0% 100.0%,39.9% 87.7%,25.0% 93.3%,22.4% 77.6%,6.7% 75.0%,12.3% 60.1%,0.0% 50.0%,12.3% 39.9%,6.7% 25.0%,22.4% 22.4%,25.0% 6.7%,39.9% 12.3%);
  animation:tourner 26s linear infinite;
}
.p-sceau .corps{padding:0 14px; width:clamp(106px,8.8vw,136px); height:clamp(106px,8.8vw,136px);}
.p-sceau .forme{background:var(--tuile-1); clip-path:polygon(99.0% 50.0%,97.9% 52.7%,95.2% 55.1%,92.4% 57.2%,90.9% 59.3%,91.3% 61.9%,92.9% 65.0%,94.3% 68.4%,94.1% 71.3%,92.0% 73.2%,88.5% 74.2%,85.1% 74.9%,82.8% 76.2%,82.1% 78.7%,82.2% 82.2%,82.0% 85.8%,80.6% 88.3%,77.8% 89.1%,74.2% 88.5%,70.8% 87.7%,68.2% 87.8%,66.5% 89.8%,65.0% 92.9%,63.3% 96.1%,60.9% 97.8%,58.0% 97.3%,55.1% 95.2%,52.4% 93.0%,50.0% 92.0%,47.6% 93.0%,44.9% 95.2%,42.0% 97.3%,39.1% 97.8%,36.7% 96.1%,35.0% 92.9%,33.5% 89.8%,31.8% 87.8%,29.2% 87.7%,25.8% 88.5%,22.2% 89.1%,19.4% 88.3%,18.0% 85.8%,17.8% 82.2%,17.9% 78.7%,17.2% 76.2%,14.9% 74.9%,11.5% 74.2%,8.0% 73.2%,5.9% 71.3%,5.7% 68.4%,7.1% 65.0%,8.7% 61.9%,9.1% 59.3%,7.6% 57.2%,4.8% 55.1%,2.1% 52.7%,1.0% 50.0%,2.1% 47.3%,4.8% 44.9%,7.6% 42.8%,9.1% 40.7%,8.7% 38.1%,7.1% 35.0%,5.7% 31.6%,5.9% 28.7%,8.0% 26.8%,11.5% 25.8%,14.9% 25.1%,17.2% 23.8%,17.9% 21.3%,17.8% 17.8%,18.0% 14.2%,19.4% 11.7%,22.2% 10.9%,25.8% 11.5%,29.2% 12.3%,31.8% 12.2%,33.5% 10.2%,35.0% 7.1%,36.7% 3.9%,39.1% 2.2%,42.0% 2.7%,44.9% 4.8%,47.6% 7.0%,50.0% 8.0%,52.4% 7.0%,55.1% 4.8%,58.0% 2.7%,60.9% 2.2%,63.3% 3.9%,65.0% 7.1%,66.5% 10.2%,68.2% 12.2%,70.8% 12.3%,74.2% 11.5%,77.8% 10.9%,80.6% 11.7%,82.0% 14.2%,82.2% 17.8%,82.1% 21.3%,82.8% 23.8%,85.1% 25.1%,88.5% 25.8%,92.0% 26.8%,94.1% 28.7%,94.3% 31.6%,92.9% 35.0%,91.3% 38.1%,90.9% 40.7%,92.4% 42.8%,95.2% 44.9%,97.9% 47.3%); animation:tourner 34s linear infinite reverse;}
@keyframes tourner{ to{ transform:rotate(360deg); } }
.p-fanion .corps{padding:17px 40px 17px 22px; transform-origin:0 50%; animation:ondoyer 4.4s ease-in-out infinite;}
.p-fanion .forme{background:var(--tuile-2); clip-path:polygon(0 0,100% 0,86% 50%,100% 100%,0 100%);}
@keyframes ondoyer{ from,to{ transform:rotate(-1.6deg); } 50%{ transform:rotate(1.6deg) translateY(-2px); } }
.p-bulle .corps{padding:19px 24px; animation:flotter 5.6s ease-in-out infinite;}
.p-bulle .forme{background:var(--tuile-5); border-radius:18px;}
.p-bulle .forme::after{
  content:""; position:absolute; left:24px; bottom:-8px; width:18px; height:18px;
  background:var(--tuile-5); border-radius:3px; transform:rotate(45deg);
}
@keyframes flotter{ 50%{ transform:translateY(-6px) rotate(1deg); } }
.anime .pastille{ animation:eclore .55s cubic-bezier(.2,.7,.3,1.35) backwards; }
@keyframes eclore{
  from{ opacity:0; transform:rotate(var(--incl,0deg)) scale(.35); }
  to  { opacity:1; transform:rotate(var(--incl,0deg)) scale(1); }
}
@media (prefers-reduced-motion:reduce){
  .anime .pastille,.pastille .forme,.pastille .corps{ animation:none; }
}
@media (max-width:900px){ .pastille{display:none;} }
