/* ==========================================================================
   Pronostik — landing page stylesheet
   --------------------------------------------------------------------------
   Contents
   1.  Tokens (colours, type, spacing, radii)
   2.  Base & reset
   3.  Layout utilities
   4.  Typography
   5.  Buttons & store badges
   6.  Header + navigation
   7.  Hero
   8.  Predictions section (pastel cards)
   9.  Match analysis section
   10. Our approach section
   11. Referral section
   12. Final call to action
   13. Footer
   14. Mobile CTA bar
   15. Secondary pages (contact, 404)
   16. Subscription page (prices, payment, FAQ)
   17. Download page (iPhone / Android)
   18. Subscription & account flow
   19. Reduced motion & print
   ========================================================================== */

/* ---------------------------------------------------------------- 1. TOKENS */
:root {
  /* Encre & gris neutres */
  --ink:          #0B0B0D;
  --ink-soft:     #1A1A1C;
  --grey-700:     #4E5159;
  --grey-500:     #70737D;
  --grey-400:     #8F939C;
  --line:         #EAEBEE;
  --line-strong:  #DDDFE4;
  --surface:      #FFFFFF;
  --surface-soft: #F6F7F8;
  --surface-sink: #F1F2F4;

  /* Subscription states: plenty of time, last week, last days. */
  --etat-vert:    #38A37E;
  --etat-orange:  #DE7E46;
  --etat-rouge:   #C44E52;

  /* Pending payment: amber, distinct from the orange of subscriptions
     nearing their end. Dark enough to stay readable at small sizes. */
  --ambre:        #B45309;
  --ambre-fond:   #FEF3C7;

  /* Pastels fonctionnels — une couleur = un usage */
  --foot:        #E4EEFD;  --foot-deep:   #CADFFA;  --foot-ink:   #14458F;
  --basket:      #FCE8DA;  --basket-deep: #FADCBB;  --basket-ink: #8E4315;
  --tennis:      #E3F2E5;  --tennis-deep: #C9E6CE;  --tennis-ink: #1F5C33;
  --other:       #FBF2D1;  --other-deep:  #F5E5AC;  --other-ink:  #6E540B;

  /* Typographie */
  --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --fs-display: clamp(2.25rem, 1.4rem + 3.2vw, 3.5rem);
  --fs-h2:      clamp(1.875rem, 1.4rem + 2vw, 3rem);
  --fs-h3:      clamp(1.125rem, 1.05rem + 0.35vw, 1.3125rem);
  --fs-lead:    clamp(1.0625rem, 1.01rem + 0.28vw, 1.1875rem);
  --fs-body:    1rem;
  --fs-sm:      0.9375rem;
  --fs-xs:      0.8125rem;
  --fs-eyebrow: 0.75rem;

  /* Vertical rhythm — 4 px scale */
  --space-section: clamp(4.5rem, 3rem + 6vw, 8rem);
  --gap-sm: 0.75rem;
  --gap:    1.25rem;
  --gap-lg: 2rem;

  /* Rayons & ombres */
  --r-sm: 10px;
  --r:    14px;
  --r-lg: 20px;
  --r-xl: 28px;
  --shadow-sm:  0 1px 2px rgba(11, 11, 13, .04), 0 2px 8px rgba(11, 11, 13, .04);
  --shadow-md:  0 2px 4px rgba(11, 11, 13, .03), 0 12px 32px rgba(11, 11, 13, .06);
  --shadow-cta: 0 1px 2px rgba(11, 11, 13, .18), 0 8px 24px rgba(11, 11, 13, .14);

  /* Divers */
  --container: 1200px;
  --header-h: 72px;
  --ease: cubic-bezier(.16, .84, .44, 1);
}

/* ------------------------------------------------------- 2. BASE & RESET */
*, *::before, *::after { box-sizing: border-box; }
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
body {
  margin: 0;
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--fs-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: 'cv11', 'ss01';
}
img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }

/* Must come before any display rule: a display: grid or flex would
   otherwise beat [hidden]'s default display:none, and the element would stay
   visible while the HTML declares it hidden. */
[hidden] { display: none !important; }
button { font: inherit; color: inherit; }
ul, ol { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, h4, p { margin: 0; }
:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
  border-radius: 4px;
}
::selection { background: var(--foot-deep); color: var(--ink); }

/* --------------------------------------------- 3. UTILITAIRES DE LAYOUT */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
}
.section { padding-block: var(--space-section); }
.section--soft { background: var(--surface-soft); }
.section--ink { background: var(--ink); color: #fff; }

/* Anchor offset for nav links under the sticky header */
[id] { scroll-margin-top: calc(var(--header-h) + var(--haut-bandeau, 0px) + 24px); }
.skip-link {
  position: absolute;
  left: 1rem; top: -100px;
  z-index: 100;
  padding: .75rem 1.25rem;
  background: var(--ink); color: #fff;
  border-radius: var(--r-sm);
  transition: top .2s var(--ease);
}
.skip-link:focus { top: 1rem; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ------------------------------------------------------- 4. TYPOGRAPHIE */
.eyebrow {
  display: inline-flex; align-items: center; gap: .5rem;
  margin-bottom: 1.25rem;
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--grey-500);
}
.eyebrow::before {
  content: '';
  width: 18px; height: 1px;
  background: var(--line-strong);
}
.section--ink .eyebrow { color: rgba(255, 255, 255, .62); }
.section--ink .eyebrow::before { background: rgba(255, 255, 255, .28); }
h1, .h1 {
  font-size: var(--fs-display);
  font-weight: 600;
  line-height: 1.04;
  letter-spacing: -.032em;
  text-wrap: balance;
}
h2, .h2 {
  font-size: var(--fs-h2);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -.028em;
  text-wrap: balance;
}
h3, .h3 {
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -.015em;
}
.lead {
  font-size: var(--fs-lead);
  line-height: 1.6;
  color: var(--grey-500);
  max-width: 56ch;
}
.section--ink .lead { color: rgba(255, 255, 255, .72); }
.section-head { max-width: 44rem; margin-bottom: clamp(2.5rem, 4vw, 4rem); }
.section-head .lead { margin-top: 1.25rem; }
.fineprint {
  font-size: var(--fs-xs);
  line-height: 1.55;
  color: var(--grey-400);
}

/* ------------------------------------------ 5. BOUTONS & BADGES DE STORE */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .8125rem 1.375rem;
  border: 1px solid transparent;
  border-radius: 999px;
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: -.01em;
  white-space: nowrap;
  cursor: pointer;
  transition: transform .18s var(--ease), background-color .18s var(--ease),
              border-color .18s var(--ease), box-shadow .18s var(--ease);
}
/* A disabled button must look disabled: otherwise the user taps it,
   nothing happens, and they think the site is broken. */
.btn:disabled {
  opacity: .35;
  cursor: not-allowed;
  transform: none;
}
.btn--primary {
  background: var(--ink); color: #fff;
  box-shadow: var(--shadow-cta);
}
.btn--primary:hover { background: #24242a; transform: translateY(-1px); }
.btn--primary:active { transform: translateY(0); }
.btn--ghost {
  background: transparent; color: var(--ink);
  border-color: var(--line-strong);
}
.btn--ghost:hover { border-color: var(--ink); background: var(--surface-soft); }
.section--ink .btn--ghost {
  color: #fff; border-color: rgba(255, 255, 255, .3);
}
.section--ink .btn--ghost:hover {
  border-color: rgba(255, 255, 255, .7); background: rgba(255, 255, 255, .08);
}

/* Visitor already signed in — <html data-connecte>, set at the top of the
   public pages before rendering. As on Netflix, we stop offering to create an
   account: "Créer mon compte" disappears everywhere and "Gérer mon compte"
   becomes the primary button. After "Déconnexion" the attribute is no longer
   set and everything returns to normal. */
html[data-connecte] [data-cta='compte'],
html[data-connecte] [data-si-deconnecte] { display: none !important; }
html[data-connecte] .btn[data-gerer] {
  background: var(--ink); color: #fff; border-color: transparent;
  box-shadow: var(--shadow-cta);
}
html[data-connecte] .btn[data-gerer]:hover { background: #24242a; transform: translateY(-1px); }
/* On a black ground the primary button is white: black, it would vanish. */
html[data-connecte] .section--ink .btn[data-gerer] {
  background: #fff; color: var(--ink); border-color: #fff; box-shadow: none;
}
html[data-connecte] .section--ink .btn[data-gerer]:hover { background: #E8E9EC; border-color: #E8E9EC; transform: none; }
/* The sentence above the button is gone: so is the gap it carried. */
html[data-connecte] .final-cta .hero__actions { margin-top: 2rem; }
/* Download inside the account area: a label, then the two paths side by
   side. Two buttons of equal weight — neither is "the right one", the user's
   phone decides. */
.tel-compte { margin-top: 1.75rem; }
.tel-compte__titre {
  font-size: var(--fs-xs); font-weight: 600; color: var(--grey-500);
  letter-spacing: .04em; text-transform: uppercase;
}
.tel-compte__voies { display: flex; flex-wrap: wrap; gap: .625rem; margin-top: .75rem; }
.tel-voie {
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .5625rem 1rem;
  border: 1px solid var(--line-strong); border-radius: 999px;
  font-size: var(--fs-sm); font-weight: 500; color: var(--grey-700);
  transition: border-color .18s var(--ease), color .18s var(--ease);
}
.tel-voie svg { width: 17px; height: 17px; flex: none; }
.tel-voie:hover { border-color: var(--ink); color: var(--ink); }

/* The labels carry their own white outline: legible on black as they are */



/* ------------------------------------------------ 6. EN-TÊTE + NAVIGATION */
.site-header {
  /* 0 when there is no invite bar — the variable is only set when one shows. */
  position: sticky; top: var(--haut-bandeau, 0px); z-index: 50;
  background: rgba(255, 255, 255, .82);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color .2s var(--ease), background-color .2s var(--ease);
}
.site-header[data-scrolled='true'] {
  border-bottom-color: var(--line);
  background: rgba(255, 255, 255, .92);
}
.site-header__inner {
  display: flex; align-items: center; justify-content: space-between; gap: 1.5rem;
  min-height: var(--header-h);
}
.brand { display: inline-flex; align-items: center; }
.brand img { height: 26px; width: auto; }
.nav { display: flex; align-items: center; gap: 2rem; }
.nav a {
  position: relative;
  white-space: nowrap;          /* a menu item must never wrap */
  font-size: var(--fs-sm);
  color: var(--grey-700);
  transition: color .16s var(--ease);
}
/* Between 900 and 1050 px the five items get cramped: tighten up */
@media (max-width: 1050px) { .nav { gap: 1.5rem; } }
.nav a:hover { color: var(--ink); }
.nav a::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -6px;
  height: 1.5px; background: var(--ink);
  transform: scaleX(0); transform-origin: left;
  transition: transform .22s var(--ease);
}
.nav a:hover::after { transform: scaleX(1); }

.site-header__actions { display: flex; align-items: center; gap: .75rem; }

.nav-toggle {
  display: none;
  width: 44px; height: 44px;
  margin-right: -4px;                  /* rules aligned with the content edge */
  align-items: center; justify-content: center;
  background: transparent;
  border: 0;
  cursor: pointer;
}
/* Deux traits horizontaux (comme visifoot.com) */
.nav-toggle__bar {
  position: relative;
  display: block; width: 36px; height: 10px;
}
.nav-toggle__bar::before, .nav-toggle__bar::after {
  content: ''; position: absolute; left: 0;
  width: 36px; height: 2px;
  background: var(--ink); border-radius: 2px;
  transition: transform .22s var(--ease), top .22s var(--ease);
}
.nav-toggle__bar::before { top: 0; }
.nav-toggle__bar::after { top: 8px; }
.nav-toggle[aria-expanded='true'] .nav-toggle__bar::before { top: 4px; transform: rotate(45deg); }
.nav-toggle[aria-expanded='true'] .nav-toggle__bar::after { top: 4px; transform: rotate(-45deg); }

/* Panneau de navigation mobile */
.mobile-nav {
  /* Le bandeau d'invitation, quand il est là, pousse l'en-tête vers le bas :
     le menu doit démarrer sous les DEUX, sinon son premier onglet passe
     dessous. --haut-bandeau vaut 0 quand il n'y a pas de bandeau. */
  position: fixed; inset: calc(var(--haut-bandeau, 0px) + var(--header-h)) 0 0;
  z-index: 40;
  display: flex; flex-direction: column; gap: .25rem;
  padding: 1.5rem clamp(1.25rem, 4vw, 2.5rem) 2rem;
  background: var(--surface);
  overflow-y: auto;
  opacity: 0; visibility: hidden;
  transform: translateY(-8px);
  transition: opacity .22s var(--ease), transform .22s var(--ease), visibility .22s;
}
.mobile-nav[data-open='true'] { opacity: 1; visibility: visible; transform: none; }
/* Every item carries a chevron: without it the list reads as text rather
   than navigation. One notch smaller than before, too — six lines set very
   large made a wall. */
.mobile-nav > a:not(.mobile-nav__dl) {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: .9375rem 0;
  font-size: 1.1875rem; font-weight: 600; letter-spacing: -.02em;
  border-bottom: 1px solid var(--line);
  transition: color .18s var(--ease);
}
.mobile-nav > a:not(.mobile-nav__dl)::after {
  content: '';
  flex: none; width: 8px; height: 8px;
  border-top: 2px solid var(--grey-400);
  border-right: 2px solid var(--grey-400);
  border-radius: 1px;
  transform: rotate(45deg);
}
/* The rule under the last item separates the navigation from the two
   actions that follow: it is deliberate, do not remove it. */
body[data-nav-open='true'] { overflow: hidden; }

@media (max-width: 900px) {
  /* On a phone both CTAs move into the menu and the hero, where they read
     far better than squeezed into a header bar. */
  .nav, .site-header__actions .btn { display: none; }
  .nav-toggle { display: inline-flex; }
}
/* Between 901 and 1100 px the two CTAs and the menu get cramped */


/* ---------------------------------------------------------------- 7. HERO */
.hero {
  position: relative;
  padding-block: clamp(3rem, 2rem + 4vw, 6rem) clamp(3.5rem, 2rem + 5vw, 7rem);
  overflow: clip;
}

/* Very light pastel wash — one only, unsaturated */
.hero::before {
  content: '';
  position: absolute; inset: -20% -10% auto auto;
  width: min(760px, 78vw); aspect-ratio: 1;
  background:
    radial-gradient(closest-side, rgba(196, 220, 252, .5), transparent 70%),
    radial-gradient(closest-side at 70% 60%, rgba(250, 215, 190, .34), transparent 70%);
  filter: blur(10px);
  pointer-events: none;
  z-index: 0;
}
.hero__inner {
  position: relative; z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(3rem, 5vw, 4.5rem);
  align-items: center;
}
.hero__title { margin-bottom: 1.5rem; }
.hero__title span { display: block; }
.hero__lead { max-width: 34rem; margin-bottom: 2.25rem; }
.hero__pill {
  display: inline-flex; align-items: center; gap: .5rem;
  margin-bottom: 1.75rem;
  padding: .4375rem .875rem .4375rem .6875rem;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-size: var(--fs-xs); font-weight: 500;
  color: var(--grey-700);
  box-shadow: var(--shadow-sm);
}
.hero__pill i {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--tennis-ink);
  box-shadow: 0 0 0 3px var(--tennis);
}

/* Mockups */
.hero__visual { position: relative; }
.hero__mockups {
  position: relative;
  max-width: 620px;
  margin-inline: auto;
  /* Fade to the bottom; the sides stay whole (margin built into the SVG) */
  -webkit-mask-image: linear-gradient(to bottom, #000 46%, transparent 88%);
          mask-image: linear-gradient(to bottom, #000 46%, transparent 88%);
}
.hero__mockups img { width: 100%; height: auto; }

/* Phone and tablet: less white between the phones and "Les pronostics" */
@media (max-width: 999px) {
  .hero { padding-bottom: 0; }
  .hero__mockups { margin-bottom: -2.5rem; }   /* the bottom of the image is transparent (gradient) */
  .hero + .section { padding-top: 3rem; }
}

@media (min-width: 1000px) {
  .hero__inner {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
    gap: clamp(2rem, 4vw, 4rem);
  }
}

/* ------------------------------------------- 8. PRONOSTICS (CARTES PASTEL) */
.sports {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap: clamp(1rem, 1.6vw, 1.5rem);
}
.sport-card {
  display: flex; flex-direction: column;
  min-height: 240px;
  padding: clamp(1.5rem, 2.2vw, 2rem);
  border-radius: var(--r-xl);
  border: 1px solid transparent;
  transition: transform .22s var(--ease), box-shadow .22s var(--ease);
}
.sport-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
.sport-card__icon {
  display: grid; place-items: center;
  width: 52px; height: 52px;
  background: rgba(255, 255, 255, .9);
  border-radius: 16px;
  box-shadow: 0 1px 2px rgba(11, 11, 13, .05);
}
.sport-card__icon svg { width: 28px; height: 28px; }
.sport-card h3 { margin-top: 2rem; }
.sport-card p {
  margin-top: .625rem;
  font-size: var(--fs-sm);
  color: var(--grey-700);
}
.sport-card__meta {
  margin-top: 1.25rem; padding-top: 1rem;
  border-top: 1px solid rgba(11, 11, 13, .09);
  font-size: var(--fs-xs); font-weight: 500;
  letter-spacing: .01em;
}
.sport-card--foot { background: var(--foot); }
.sport-card--foot   .sport-card__meta { color: var(--foot-ink); }
.sport-card--basket { background: var(--basket); }
.sport-card--basket .sport-card__meta { color: var(--basket-ink); }
.sport-card--tennis { background: var(--tennis); }
.sport-card--tennis .sport-card__meta { color: var(--tennis-ink); }
.sport-card--other { background: var(--other); }
.sport-card--other  .sport-card__meta { color: var(--other-ink); }

/* Headings aligned at the top, logo strip (or note) pinned to the bottom of each card */
.sport-card > p:not(.sport-card__meta) { margin-bottom: 1.25rem; }
.sport-card .logo-marquee, .sport-card .sport-card__meta { margin-top: auto; }

/* Logo strip scrolling at the bottom of the sport cards.
   The track holds the list twice: a -50% shift loops without a jolt. */
.logo-marquee {
  margin-top: 1.25rem; padding-top: 1rem;
  border-top: 1px solid rgba(11, 11, 13, .09);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
          mask-image: linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
}
.logo-marquee__track {
  display: flex; align-items: center;
  width: max-content;
  animation: logo-marquee 22s linear infinite;
}
.logo-marquee__track > * { flex: none; margin-right: 1.25rem; }
/* Same frame for all: tall logos and wide logos carry equal presence */
.logo-marquee img { width: 72px; height: 32px; object-fit: contain; }
/* Logo supplied on white: the white blends into the card's colour */
.logo-marquee img.is-multiply { mix-blend-mode: multiply; }
/* The logos are not there to be taken away: no selection, no drag and
   drop, and no long press offering "Save image". pointer-events on the image,
   not on the strip: the slow-down on hover keeps working. */
.logo-marquee { -webkit-user-select: none; user-select: none; }
.logo-marquee img {
  pointer-events: none;
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
}
/* On hover or touch the strip slows without stopping (main.js): a hard
   stop feels like something broke. */
@keyframes logo-marquee { from { transform: translateX(0); }to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .logo-marquee__track { animation: none; }
}

/* --------------------------------------------------------- 9. ANALYSES */
.analysis {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(2.5rem, 4vw, 4rem);
  align-items: center;
}
@media (min-width: 1000px) {
  .analysis { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(3rem, 6vw, 6rem); }
}
.pill {
  display: inline-flex; align-items: center; gap: .375rem;
  padding: .25rem .625rem;
  background: var(--other);
  border-radius: 999px;
  font-size: .6875rem; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--other-ink);
}
.analysis__intro .lead { margin-top: 1.25rem; }
.analysis__note { margin-top: 1.75rem; }
.analysis__list { display: grid; gap: .875rem; }
.analysis__item {
  display: grid; grid-template-columns: 48px minmax(0, 1fr);
  gap: 1.125rem; align-items: start;
  padding: clamp(1.25rem, 2vw, 1.625rem);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.analysis__item i {
  display: grid; place-items: center;
  width: 48px; height: 48px;
  background: var(--surface-sink); color: var(--grey-700);
  border-radius: 14px;
}
.analysis__item svg { width: 22px; height: 22px; }
.analysis__item h3 { font-size: 1.0625rem; padding-top: .125rem; }
.analysis__item p { margin-top: .3125rem; font-size: var(--fs-sm); color: var(--grey-500); }

/* ------------------------------------------------------ 10. NOTRE APPROCHE */
.approach { display: grid; gap: clamp(2rem, 3vw, 3rem); }
.statement {
  padding: clamp(2rem, 4vw, 3.5rem);
  background: var(--ink); color: #fff;
  border-radius: var(--r-xl);
}
.statement h2 { max-width: 30ch; }
.statement p {
  max-width: 58ch; margin-top: 1.5rem;
  font-size: var(--fs-lead); line-height: 1.6;
  color: rgba(255, 255, 255, .74);
}
.pillars {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: clamp(1rem, 1.6vw, 1.5rem);
}
.pillar {
  padding: clamp(1.5rem, 2vw, 1.875rem);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.pillar i {
  display: grid; place-items: center;
  width: 44px; height: 44px; margin-bottom: 1.25rem;
  border-radius: 14px;
}
.pillar i svg { width: 22px; height: 22px; }
.pillar:nth-child(1) i { background: var(--foot); color: var(--foot-ink); }
.pillar:nth-child(2) i { background: var(--tennis); color: var(--tennis-ink); }
.pillar:nth-child(3) i { background: var(--other); color: var(--other-ink); }
.pillar p { margin-top: .625rem; font-size: var(--fs-sm); color: var(--grey-500); }

/* --------------------------------------------------------- 11. PARRAINAGE */
/* Moins d'espace entre « Notre approche » et la carte Parrainage (deux sections blanches qui se suivent) */
#approche + #parrainage { padding-top: calc(var(--space-section) * .4); }
.referral {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(2rem, 3.5vw, 3.5rem);
  align-items: center;
  padding: clamp(1.75rem, 3vw, 3rem);
  background: var(--surface-soft);
  border-radius: var(--r-xl);
}
@media (min-width: 900px) {
  .referral { grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr); }
}
.steps { display: grid; gap: 1rem; margin-top: 1.75rem; }
.step { display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: .875rem; align-items: start; }
.step b {
  display: grid; place-items: center;
  width: 28px; height: 28px;
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: 50%;
  font-size: var(--fs-xs); font-weight: 600;
}
.step p { font-size: var(--fs-sm); color: var(--grey-700); padding-top: .1875rem; }

/* The TestFlight steps, inside the early-access dialog. No numbered bubble
   like elsewhere on the site: going through TestFlight is familiar to nobody,
   and a digit in a circle reads as a bullet as much as an order. The word
   "Étape" removes the doubt, and costs one line. */
.etapes-tf {
  display: grid; gap: 1.125rem;
  margin: 1.375rem 0 0; padding: 0;
  list-style: none;
}
.etapes-tf li { display: grid; gap: .25rem; }
/* The rank is a heading, plainly: nobody arrives here knowing TestFlight, so
   the order has to be readable before the words are. Set like a small section
   title — not the uppercase label used elsewhere, which reads as a category
   rather than as a step to follow. */
.etapes-tf__rang {
  font-size: var(--fs-h3); font-weight: 700;
  letter-spacing: -.02em; line-height: 1.2;
  color: var(--ink);
}
.etapes-tf span {
  font-size: var(--fs-sm); line-height: 1.55; color: var(--grey-700);
}
/* :not(.btn) is not a flourish — without it this rule wins over .btn--primary
   on both colour and underline, and the black button ends up with black text
   on a black ground: invisible, with nothing to signal it. */
.etapes-tf a:not(.btn) { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }
/* The step's own button: full width, so the two read as one ladder rather
   than as two links floating in the text. */
.etapes-tf__btn {
  justify-content: center;
  width: 100%; margin-top: .5rem;
}

/* A preview of an app screen rebuilt in HTML/CSS (phone frame) */
.app-demo {
  display: flex; flex-direction: column; align-items: center; gap: .875rem;
  margin: 0;
}
.app-demo__phone {
  position: relative;
  width: min(272px, 100%); height: 470px;
  padding: 9px;
  background: #0B0B0D;
  border: 2px solid #D9D6CF;
  border-radius: 46px;
  overflow: hidden;
  /* fade to the bottom, like the phones at the top of the page */
  -webkit-mask-image: linear-gradient(#000 86%, transparent 100%);
          mask-image: linear-gradient(#000 86%, transparent 100%);
}
.app-demo__island {
  position: absolute; z-index: 2;
  top: 19px; left: 50%;
  width: 76px; height: 22px; margin-left: -38px;
  background: #0B0B0D; border-radius: 999px;
}
.app-demo__screen {
  height: 100%;
  padding: 50px 13px 0;
  background: #fff;
  border-radius: 36px;
  text-align: left;
  color: #111;
}
.app-demo__caption { font-size: .75rem; color: var(--grey-500); text-align: center; }

/* Écran « Amis & Gains » (Football) */
.gain-bar {
  display: grid; grid-template-columns: 22px minmax(0, 1fr) 22px; align-items: center;
}
.gain-bar > svg { width: 20px; height: 20px; }
.gain-bar__sport {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  font-size: 1.1875rem; font-weight: 600; letter-spacing: -.02em;
}
.gain-bar__sport i {
  display: grid; place-items: center;
  width: 30px; height: 30px; border-radius: 50%;
  background: #CFE0F7;
}
.gain-bar__sport i img { width: 22px; height: 22px; }
.gain-bar__sport > svg { width: 14px; height: 14px; }
.gain-card {
  margin-top: 26px; padding: 4px 13px;
  background: #F1F1F1; border-radius: 20px;
}
.gain-card + .gain-card { margin-top: 12px; }
.gain-row {
  display: grid; grid-template-columns: minmax(0, 1fr) 50px; gap: 10px; align-items: center;
  padding: 12px 0;
}
.gain-row + .gain-row { border-top: 1px solid #E2E2E6; }
.gain-row b { display: block; font-size: 1.1875rem; font-weight: 700; line-height: 1.15; letter-spacing: -.015em; }
.gain-row span {
  display: flex; align-items: center; gap: 4px;
  margin-top: 6px; font-size: .8125rem;
}
.gain-row span svg { width: 12px; height: 12px; flex: none; }
.gain-row i {
  display: grid; place-items: center;
  width: 50px; height: 50px; border-radius: 12px;
  background: #CFE0F7;
}
.gain-row i.is-green { background: #CDEBDD; }
.gain-row i svg { width: 28px; height: 28px; }

/* ---------------------------------------------------------- 12. CTA FINAL */
.final-cta { text-align: center; }
.final-cta h2 { margin-inline: auto; max-width: 24ch; }
.final-cta .lead { margin: 1.25rem auto 2.5rem; }

/* ------------------------------------------------------- 13. PIED DE PAGE */
.site-footer {
  padding-block: clamp(3rem, 4vw, 4.5rem) 2rem;
  border-top: 1px solid var(--line);
}
.site-footer__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: clamp(2rem, 3vw, 3rem);
}
.site-footer__brand { max-width: 26rem; }
.site-footer__brand p { margin-top: 1rem; font-size: var(--fs-sm); color: var(--grey-500); }
.site-footer__title {
  margin-bottom: 1rem;
  font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--grey-400);
}
.site-footer li + li { margin-top: .625rem; }
.site-footer li a { font-size: var(--fs-sm); color: var(--grey-700); }
.site-footer li a:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.site-footer__bottom {
  display: flex; flex-wrap: wrap; gap: 1rem 2rem;
  align-items: center; justify-content: space-between;
  margin-top: clamp(2.5rem, 4vw, 3.5rem);
  padding-top: 1.75rem;
  border-top: 1px solid var(--line);
  font-size: var(--fs-xs); color: var(--grey-400);
}
.site-footer__legal { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem; }
.age-badge {
  display: inline-grid; place-items: center;
  min-width: 30px; height: 20px; padding-inline: .3125rem;
  border: 1.5px solid var(--grey-400); border-radius: 5px;
  font-size: .625rem; font-weight: 700; color: var(--grey-700);
}

/* ---------------------------------------------------- 14. BARRE CTA MOBILE */
.mobile-cta {
  position: fixed; left: 0; right: 0; bottom: 0;
  z-index: 30;
  display: none;
  gap: .75rem; align-items: center;
  padding: .75rem clamp(1rem, 4vw, 1.5rem);
  padding-bottom: calc(.75rem + env(safe-area-inset-bottom, 0px));
  background: rgba(255, 255, 255, .94);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--line);
  transform: translateY(120%);
  transition: transform .28s var(--ease);
}
.mobile-cta[data-visible='true'] { transform: none; }
.mobile-cta__icon { flex: none; }
.mobile-cta__icon img { width: 34px; height: 34px; border-radius: 8px; }
.mobile-cta p { flex: 1; min-width: 0; font-size: var(--fs-xs); line-height: 1.35; }
.mobile-cta p b { display: block; font-size: var(--fs-sm); font-weight: 600; letter-spacing: -.01em; }
.mobile-cta p span { display: block; color: var(--grey-500); }

/* Tight: on a 375 px screen the text on the left has only about 135 px.
   Every pixel the button gives back goes to it. */
.mobile-cta .btn { flex: none; padding: .625rem .875rem; }
.mobile-cta__close {
  display: grid; place-items: center;
  flex: none; width: 28px; height: 28px;
  margin-right: -.375rem;
  padding: 0;
  background: transparent; border: 0;
  color: var(--grey-400);
  cursor: pointer;
}
.mobile-cta__close svg { width: 15px; height: 15px; }
.mobile-cta__close:hover { color: var(--ink); }

@media (max-width: 760px) {
  .mobile-cta { display: flex; }
  body { padding-bottom: 0; }
  .site-footer { padding-bottom: 6.5rem; }
}

/* ------------------------------------------- 15. PAGES SECONDAIRES */
.page-head { padding-block: clamp(3rem, 5vw, 5.5rem) clamp(2rem, 3vw, 3rem); }
.page-head .lead { margin-top: 1.25rem; }
.contact-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
  padding-bottom: var(--space-section);
}
.contact-card {
  padding: clamp(1.5rem, 2.4vw, 2rem);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.contact-card i {
  display: grid; place-items: center;
  width: 44px; height: 44px; margin-bottom: 1.25rem;
  background: var(--foot); color: var(--foot-ink);
  border-radius: 14px;
}
.contact-card i svg { width: 22px; height: 22px; }
.contact-card p { margin-top: .5rem; font-size: var(--fs-sm); color: var(--grey-500); }
.contact-card a.contact-link {
  display: inline-block; margin-top: 1rem;
  font-weight: 600; letter-spacing: -.01em;
  text-decoration: underline; text-underline-offset: 4px;
  text-decoration-thickness: 1.5px;
  text-decoration-color: var(--line-strong);
}
.contact-card a.contact-link:hover { text-decoration-color: var(--ink); }
.error-page {
  display: grid; place-items: center;
  min-height: 70vh; text-align: center;
}
.error-page__code {
  font-size: clamp(4rem, 12vw, 8rem); font-weight: 600;
  letter-spacing: -.04em; line-height: 1;
}
.error-page .lead { margin: 1.25rem auto 2rem; }

/* ---------------------------------------------------- 16. PAGE ABONNEMENT */

/* The page strings short blocks together: tighter vertical rhythm */
.section--tight { padding-block: calc(var(--space-section) * .5); }
/* Section sitting against the page header: the header already has its
   bottom margin, and the two together pushed the subtitle too far from what it
   introduces. */
.section--sous-entete { padding-top: clamp(.75rem, 1.5vw, 1.5rem); }
.section--tight .section-head { margin-bottom: clamp(1.75rem, 2.5vw, 2.5rem); }
.btn--light { background: #fff; color: var(--ink); border-color: #fff; }
.btn--light:hover { background: #E8E9EC; border-color: #E8E9EC; }

/* ------------------------------------------------- 17. PAGE TÉLÉCHARGEMENT */

/* The two paths side by side: on Android the download happens here, on
   iPhone it goes through the App Store. The Android card is highlighted — it
   is the vast majority of users. */
.device-split {
  display: grid; gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr));
  align-items: start;
}
.device-card {
  display: flex; flex-direction: column; align-items: flex-start;
  padding: clamp(1.5rem, 3vw, 2rem);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
}

/* A card on its own: without this limit it stretches the full width of the
   screen and the button ends up lost in the middle of nowhere. */
.device-split--solo { grid-template-columns: minmax(0, 30rem); }
.device-card__kicker {
  font-size: var(--fs-eyebrow); font-weight: 600;
  letter-spacing: .09em; text-transform: uppercase; color: var(--grey-500);
}
.device-card__title {
  margin-top: .625rem;
  font-size: var(--fs-h3); font-weight: 700; letter-spacing: -.02em;
}
.device-card__text { margin-top: .375rem; font-size: var(--fs-sm); color: var(--grey-500); }
.device-card__dl { margin-top: 1.5rem; }
/* The Android glyph only fills the top of a 24 square: in a square box it
   looks half the size it is. The SVG viewBox is cropped to the drawing and the
   box follows its proportions (16 × 9).
   An explicit size is still essential: without it, an SVG with no width/height
   attributes falls back to 300 × 150 and blows the button apart. */
.device-card__dl svg { width: 28px; height: 16px; flex: none; }


/* — Les trois avertissements d'Android — */
.install-steps { display: grid; gap: .75rem; margin: 0; padding: 0; list-style: none; }
.install-step {
  display: grid; grid-template-columns: 32px minmax(0, 1fr); gap: 1rem;
  align-items: start;
  padding: 1.125rem 1.25rem;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
}
.install-step > b {
  display: grid; place-items: center;
  width: 32px; height: 32px;
  background: var(--ink); color: #fff;
  border-radius: 50%;
  font-size: var(--fs-sm); font-weight: 600;
}
/* The exact wording the phone shows, so it can be recognised */
.install-step__quote {
  font-size: 1.0625rem; font-weight: 600; letter-spacing: -.015em; line-height: 1.35;
}
.install-step__do { margin-top: .375rem; font-size: var(--fs-sm); color: var(--grey-700); }
.install-step__do strong { color: var(--ink); font-weight: 600; }

/* What follows the install is not one more step: it is what you do once
   inside the app. Outside the numbered list, therefore, so that "two steps"
   stays true. */
.install-apres {
  margin-top: 1.75rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
  font-size: var(--fs-sm);
  line-height: 1.6;
  color: var(--grey-500);
}

/* Android's three warnings, inside the install step */
.avertissements { display: grid; gap: .5rem; margin: .875rem 0 0; padding: 0; list-style: none; }
.avertissements li {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem .5rem;
  padding: .5rem .75rem;
  background: var(--surface-sink);
  border-radius: var(--r-sm);
  font-size: var(--fs-xs); color: var(--grey-500);
}
.avertissements q { font-style: normal; }
.avertissements strong { color: var(--ink); font-weight: 600; }



/* In the hero and the mobile menu, the pair goes full width */
.cta-paire { display: flex; flex-wrap: wrap; gap: .75rem; }
.hero__dl {
  display: inline-flex; align-items: center; gap: .375rem;
  font-size: var(--fs-sm); font-weight: 500; color: var(--grey-700);
  transition: gap .18s var(--ease), color .18s var(--ease);
}
.hero__dl svg { width: 15px; height: 15px; }

/* The two store badges. It is the HEIGHT that must match, never the width:
   the two files are drawn at slightly different ratios, and lining them up on
   width leaves one a hair taller than the other — the kind of half-pixel that
   reads as carelessness. */
.boutiques {
  display: flex; flex-wrap: wrap; gap: .75rem;
  margin: 1.75rem 0 0;
}
.boutiques--centre { justify-content: center; }
.boutique { display: block; border-radius: 9px; }
.boutique img { display: block; width: auto; height: 52px; }
.boutique:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }
@media (max-width: 420px) {
  .boutique img { height: 46px; }
}
.hero__dl:hover { gap: .625rem; color: var(--ink); }
/* On a phone the sticky bottom banner already offers "Télécharger" on
   arrival: the link under the buttons would duplicate it. Same breakpoint as
   the banner (760 px); on a computer, with no banner, the link stays. */
@media (max-width: 760px) { .hero__dl { display: none; } }
/* Downloading is an action, not a menu entry: it leaves the list and takes
   a frame. In light grey and small, it read as disabled. */
.mobile-nav__dl {
  display: flex; align-items: center; justify-content: center;
  margin-top: 1.5rem;
  padding: .9375rem 1.25rem;
  background: var(--surface-soft);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  font-size: 1rem; font-weight: 600; letter-spacing: -.01em; color: var(--ink);
  transition: border-color .18s var(--ease);
}
.mobile-nav__dl:hover { border-color: var(--grey-400); }
.site-footer__dl { display: grid; gap: .5rem; }
/* The two account actions after the navigation, side by side: they are two
   symmetrical outcomes — new on one side, returning on the other. Stacked,
   they would have implied a hierarchy that does not exist. */
.mobile-nav .cta-paire {
  display: flex; gap: .625rem;
  margin-top: 1.5rem;
}
.mobile-nav .cta-paire .btn {
  flex: 1; min-width: 0;
  padding-inline: .75rem;
  font-size: var(--fs-sm);
}
@media (max-width: 559px) {
  .cta-paire { display: grid; }
}

/* — Device detection modal — */
.modale {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: end center;
  padding: 1rem;
}
@media (min-width: 560px) { .modale { place-items: center; } }
/* On a phone, dialogs arrive from the bottom: that is where the thumb
   reaches the buttons, and it is the expected gesture when there is a choice
   to make. Those that merely announce something — payment in progress, account
   created — sit in the middle of the screen, like a phone alert: there is
   nothing to reach, only something to read. */
.modale--centre {
  place-items: center;
  /* Sur un écran court, une fenêtre centrée plus haute que la vitre serait
     rognée en haut ET en bas, sans rien pour le signaler. Elle défile. */
  overflow-y: auto;
}
.modale__fond {
  position: absolute; inset: 0;
  background: rgba(11, 11, 13, .8);
  animation: modale-fond .2s var(--ease);
}
.modale__boite {
  position: relative;
  width: 100%; max-width: 27rem;
  padding: clamp(1.5rem, 4vw, 2rem);
  background: var(--surface);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-md);
  animation: modale-boite .24s var(--ease);
}
@keyframes modale-fond { from { opacity: 0 } }
@keyframes modale-boite { from { opacity: 0; transform: translateY(12px) } }
.modale__titre {
  padding-right: 2rem;
  font-size: 1.3125rem; font-weight: 700; letter-spacing: -.025em; line-height: 1.25;
}
/* The heading takes focus on open, for screen readers: no outline, it is
   not something you act on (main.js, focusTitre). */
.modale__titre:focus { outline: none; }
.modale__texte { margin-top: .625rem; font-size: var(--fs-sm); line-height: 1.6; color: var(--grey-500); }

/* List dialog: the list scrolls, the heading stays. The height is capped so
   the bottom edge is always visible — otherwise nothing says there is more. */
.modale__boite--liste { display: flex; flex-direction: column; max-height: min(34rem, 84vh); }
.pays-recherche {
  appearance: none; -webkit-appearance: none;
  flex: none;
  width: 100%; height: 46px;
  margin-top: 1.125rem;
  padding-inline: .9375rem;
  background: var(--surface-sink);
  border: 1px solid transparent; border-radius: var(--r-sm);
  font: inherit; font-size: 1rem; color: var(--ink);
}
.pays-recherche::placeholder { color: var(--grey-400); }
.pays-recherche:focus { outline: none; border-color: var(--ink); background: var(--surface); }
.pays-recherche::-webkit-search-cancel-button { appearance: none; -webkit-appearance: none; }
.pays-vide { margin-top: 1.25rem; font-size: var(--fs-sm); color: var(--grey-500); }
.pays-liste {
  margin: .75rem -.5rem -.5rem; padding: 0 .5rem .5rem;
  list-style: none;
  overflow-y: auto;
}
.pays-liste__choix {
  appearance: none; -webkit-appearance: none;
  display: flex; align-items: center; gap: .875rem;
  width: 100%;
  padding: .6875rem .75rem;
  background: none; border: 0; border-radius: var(--r-sm);
  font: inherit; font-size: 1rem; color: var(--ink);
  text-align: left; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color .15s var(--ease);
}
/* Hover with a mouse only: with a finger, iPhone keeps the "hovered" state
   after the tap, and the row stayed grey. */
@media (hover: hover) {
  .pays-liste__choix:hover { background: var(--surface-soft); }
}
.pays-liste__choix[aria-selected='true'] { background: var(--surface-sink); font-weight: 600; }
.pays-liste__choix img { flex: none; width: 28px; height: 28px; border-radius: 50%; }

/* The country re-read before moving on. Set in a grey panel: it is the only
   thing to look at on this screen, and the background isolates it from the
   text around it. */
.pays-confirme {
  display: flex; align-items: center; gap: .75rem;
  margin-top: 1.125rem;
  padding: .875rem 1rem;
  background: var(--surface-soft);
  border: 1px solid var(--line);
  border-radius: var(--r);
  font-size: 1.125rem; font-weight: 600; letter-spacing: -.015em;
}
.pays-confirme img { flex: none; width: 34px; height: 34px; border-radius: 50%; }

/* For a country we do NOT serve, the flag is an emoji: we do not have its
   SVG, and downloading two hundred of them for one warning dialog would make
   no sense. Windows has no flag glyphs and will show the country's two
   letters — readable, so acceptable. */
.pays-confirme__drapeau { flex: none; font-size: 1.75rem; line-height: 1; }

/* Waiting dialog: nothing to close, nothing to choose. The heading has no
   button to avoid, so it takes the full width. */
.modale__boite--attente { text-align: center; }
.modale__boite--attente .modale__titre { padding-right: 0; }
.rouet {
  display: block; width: 28px; height: 28px; margin: 0 auto 1rem;
  border: 2.5px solid var(--line-strong);
  border-top-color: var(--ink);
  border-radius: 50%;
  animation: rouet .7s linear infinite;
}
@keyframes rouet { to { transform: rotate(360deg); } }
/* The motion is not the information: without it the circle remains, and the
   text already says what is happening. */
@media (prefers-reduced-motion: reduce) {
  .rouet { animation: none; border-top-color: var(--line-strong); }
}

/* Header of a screen devoted to one sport: its icon, then its name. */
.entete-sport { display: flex; align-items: center; gap: .875rem; }
.entete-sport img { flex: none; width: 46px; height: 46px; }
.modale__actions { display: grid; gap: .625rem; margin-top: 1.5rem; }

/* The two possible paths. The one matching the device is pre-selected, but
   the other is one tap away: a wrong guess must never trap anyone. */
.voies { display: grid; gap: .625rem; margin-top: 1.25rem; }
.voie {
  display: flex; align-items: flex-start; gap: .875rem;
  padding: .9375rem 1rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  cursor: pointer;
  /* On touch, iPhone washed the card grey: we remove that wash — the tick
     and the black frame are enough to show the choice. */
  -webkit-tap-highlight-color: transparent;
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
@media (hover: hover) {
  .voie:hover { border-color: var(--grey-400); }
}

/* La vraie case reste accessible au clavier mais invisible */
.voie__radio { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.voie__icone {
  display: grid; place-items: center;
  flex: none; width: 38px; height: 38px;
  background: var(--surface-sink); color: var(--grey-700);
  border-radius: 50%;
}
/* Android and Apple logos: solid, not outlined like the other icons,
   because it is their official shape that makes them recognisable. */
.voie__icone svg { width: 21px; height: 21px; }
.voie__texte { display: grid; gap: .1875rem; min-width: 0; flex: 1; }
.voie__texte b { font-size: var(--fs-sm); font-weight: 600; letter-spacing: -.01em; }
.voie__texte span { font-size: var(--fs-xs); line-height: 1.5; color: var(--grey-500); }
.voie__marque {
  position: relative;
  flex: none; width: 22px; height: 22px; margin-top: .125rem;
  border: 1.5px solid var(--line-strong);
  border-radius: 50%;
  transition: background-color .15s var(--ease), border-color .15s var(--ease);
}
.voie__marque::after {
  content: '';
  position: absolute; left: 7px; top: 4px;
  width: 5px; height: 9px;
  border-right: 2px solid #fff; border-bottom: 2px solid #fff;
  transform: rotate(45deg) scale(.4);
  opacity: 0;
  transition: opacity .15s var(--ease), transform .15s var(--ease);
}
.voie:has(.voie__radio:checked) { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
.voie:has(.voie__radio:checked) .voie__marque { background: var(--ink); border-color: var(--ink); }
.voie:has(.voie__radio:checked) .voie__marque::after { opacity: 1; transform: rotate(45deg) scale(1); }
.voie:has(.voie__radio:checked) .voie__icone { background: var(--foot); color: var(--foot-ink); }
.voie:has(.voie__radio:focus-visible) { outline: 2px solid var(--ink); outline-offset: 2px; }
.modale__actions .btn { width: 100%; }
.modale__fermer {
  position: absolute; top: .875rem; right: .875rem;
  display: grid; place-items: center;
  width: 32px; height: 32px; padding: 0;
  background: transparent; border: 0;
  color: var(--grey-400); cursor: pointer;
}
.modale__fermer svg { width: 17px; height: 17px; }
.modale__fermer:hover { color: var(--ink); }
body[data-modale='true'] { overflow: hidden; }

/* — Lightened header for the account pages: no navigation, no accidental
     exit from the flow. — */
.site-header--simple .site-header__inner { justify-content: space-between; }

/* Two different natures in the same slot: "J'ai déjà un compte" is a
   navigation link, "Déconnexion" is an action. */
.site-header__lien {
  appearance: none; -webkit-appearance: none;
  padding: 0; background: none; border: 0;
  font-size: var(--fs-sm); font-weight: 500; color: var(--grey-700);
  cursor: pointer;
  transition: color .18s var(--ease), border-color .18s var(--ease);
}
.site-header__lien:hover { color: var(--ink); }

/* The action carries a frame. The browser's was grey and differed from one
   system to the next: we redraw it in the site's colours. */
button.site-header__lien {
  padding: .4375rem .875rem;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
}
button.site-header__lien:hover { border-color: var(--grey-400); }

/* — Centred column of the account pages — */
.compte { padding-block: clamp(2rem, 5vw, 4rem) clamp(3rem, 6vw, 5rem); }
.compte__boite {
  width: 100%; max-width: 30rem;
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 5vw, 1.5rem);
}
.compte__titre {
  font-size: clamp(1.625rem, 1.3rem + 1.4vw, 2rem);
  font-weight: 700; letter-spacing: -.03em; line-height: 1.15;
  text-wrap: balance;
}
.compte__soustitre { margin-top: .625rem; font-size: var(--fs-sm); color: var(--grey-500); }
.compte__titre:focus-visible { outline: none; }

/* Step marker: it locates, it does not decorate. No progress bar — over two
   steps it would take more room than it gives. */
.etape-repere {
  display: flex; align-items: center; gap: .375rem;
  margin-bottom: .75rem;
  font-size: var(--fs-xs); font-weight: 500; letter-spacing: .01em;
  color: var(--grey-500);
}
.etape-repere__retour {
  appearance: none; -webkit-appearance: none;
  display: grid; place-items: center;
  flex: none; width: 26px; height: 26px; margin-left: -.25rem;
  padding: 0; background: none; border: 0; border-radius: 50%;
  color: var(--grey-500); cursor: pointer;
  transition: background-color .18s var(--ease), color .18s var(--ease);
}
.etape-repere__retour svg { width: 16px; height: 16px; }
.etape-repere__retour:hover { background: var(--surface-sink); color: var(--ink); }
/* The numbers in black: they carry the information, the words merely join
   it up. Same weight as the rest — colour alone is enough to lift them. */
.etape-repere b { color: var(--ink); font-weight: inherit; }

/* A step panel behaves like the form that contains it. */
.form__etape { display: grid; gap: 1.125rem; }

/* Referral code: collapsed, because most people do not have one. It stays
   inside the step and before the button — the code is recorded permanently
   when the account is created, asking afterwards would be too late. */
.parrain { display: grid; gap: .5rem; justify-items: start; }
.parrain__question { font-size: var(--fs-sm); color: var(--grey-500); }
.parrain__ouvrir {
  appearance: none; -webkit-appearance: none;
  padding: .4375rem .875rem;
  background: var(--surface);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  font: inherit; font-size: var(--fs-sm); font-weight: 500; color: var(--grey-700);
  cursor: pointer;
  transition: border-color .18s var(--ease), color .18s var(--ease);
}
.parrain__ouvrir:hover { border-color: var(--grey-400); color: var(--ink); }
.parrain [data-champ-parrain] { width: 100%; }
.compte__bas { margin-top: 1.75rem; font-size: var(--fs-sm); color: var(--grey-500); text-align: center; }

/* PROTOTYPE — remove along with the links it dresses. The dashed rule says
   "this does not belong to the site": impossible to forget once live. */
.apercu-demo {
  margin-top: 1.25rem; padding-top: 1.25rem;
  border-top: 1px dashed var(--line-strong);
  font-size: var(--fs-xs); color: var(--grey-400); text-align: center;
}
.apercu-demo a { color: var(--grey-500); text-decoration: underline; text-underline-offset: 3px; }
.apercu-demo a:hover { color: var(--ink); }
.compte__bas a { font-weight: 600; color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.compte__oubli {
  justify-self: start;
  font-size: var(--fs-sm); color: var(--grey-700);
  text-decoration: underline; text-underline-offset: 3px;
}
.compte__oubli:hover { color: var(--ink); }

/* — Formulaires — */
.form { display: grid; gap: 1.125rem; margin-top: 2rem; }
.form__duo { display: grid; gap: 1.125rem; grid-template-columns: 1fr 1fr; }
@media (max-width: 419px) { .form__duo { grid-template-columns: 1fr; } }
.form-champ { display: grid; gap: .4375rem; }
.form-champ > label {
  font-size: var(--fs-sm); font-weight: 600; letter-spacing: -.01em;
}
.form-champ > label span { font-weight: 400; color: var(--grey-400); }
.form-champ input[type='text'],
.form-champ input[type='email'],
.form-champ input[type='tel'],
.form-champ input[type='password'] {
  /* Without this reset, Safari draws its own frame inside ours: two rules
     instead of one. */
  appearance: none; -webkit-appearance: none;
  width: 100%;
  height: 52px;
  padding-inline: .9375rem;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  font: inherit; font-size: 1rem;
  color: var(--ink);
}
.form-champ input:focus { outline: none; border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
.form-champ[data-erreur='true'] input { border-color: #C6453F; }
.form-champ__aide { font-size: var(--fs-xs); color: var(--grey-500); }
.form-champ__erreur { font-size: var(--fs-xs); color: #C6453F; }
.form-champ__erreur[hidden] { display: none; }

/* Dialling code in front of the number.
   One frame for both, and a single rule between them: the border belongs to
   the container, never to the children. That is what avoids two abutting
   borders, which overlapped differently from browser to browser and doubled
   in thickness while typing. */
.form-champ__tel {
  position: relative;
  display: flex; align-items: stretch;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  overflow: hidden;
}
/* On focus the second rule is drawn OVER the content. Set as an inner
   shadow on the frame, it slipped under the dialling code's grey background:
   the rule looked thinner on that side. */
.form-champ__tel:focus-within { border-color: var(--ink); }
.form-champ__tel:focus-within::after {
  content: '';
  position: absolute; inset: 0;
  border-radius: calc(var(--r-sm) - 1px);
  box-shadow: inset 0 0 0 1px var(--ink);
  pointer-events: none;
}
.form-champ[data-erreur='true'] .form-champ__tel { border-color: #C6453F; }
.form-champ__indicatif {
  display: inline-flex; align-items: center; gap: .4375rem;
  flex: none;
  padding-inline: .75rem;
  background: var(--surface-soft);
  border-right: 1px solid var(--line-strong);
  font-size: 1rem; font-weight: 600;
}
.form-champ__indicatif img { flex: none; width: 20px; height: 20px; border-radius: 50%; }
.form-champ__indicatif b { font-weight: inherit; }
.form-champ__tel input[type='tel'] {
  background: transparent;
  border: 0; border-radius: 0;
}
.form-champ__tel input[type='tel']:focus { box-shadow: none; }

/* Country of residence: a button drawn like the neighbouring fields, so the
   form column stays of a piece. A <select> cannot show a flag, hence the
   dialog. */
.champ-pays {
  appearance: none; -webkit-appearance: none;
  display: flex; align-items: center; gap: .625rem;
  width: 100%; height: 52px;
  padding-inline: .9375rem;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  font: inherit; font-size: 1rem; color: var(--ink);
  text-align: left; cursor: pointer;
  transition: border-color .18s var(--ease);
}
.champ-pays:hover { border-color: var(--grey-400); }
.champ-pays img { flex: none; width: 26px; height: 26px; border-radius: 50%; }
/* Same weight as the country selected in the list: it is the same choice,
   it must not change appearance when the list closes. */
.champ-pays span { flex: 1; min-width: 0; font-weight: 600; }
.champ-pays svg { flex: none; width: 18px; height: 18px; color: var(--grey-400); }

/* Password field with a reveal button */
.form-champ__secret { position: relative; }
.form-champ__secret input { padding-right: 3rem; }
.form-champ__oeil {
  position: absolute; right: .3125rem; top: 50%;
  transform: translateY(-50%);
  display: grid; place-items: center;
  width: 40px; height: 40px; padding: 0;
  background: none; border: 0;
  color: var(--grey-400); cursor: pointer;
}
.form-champ__oeil svg { width: 20px; height: 20px; }
.form-champ__oeil:hover { color: var(--ink); }

/* Terms checkbox */
.form-case {
  display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: .75rem;
  align-items: start;
  font-size: var(--fs-sm); line-height: 1.5; color: var(--grey-700);
  cursor: pointer;
}
/* The box is drawn, not left to the browser: with accent-color, Safari
   filled the square on render and the box looked already ticked. Same visual
   language as the radios on the "Choisir la durée" page. */
.form-case input {
  appearance: none; -webkit-appearance: none;
  width: 20px; height: 20px; margin: 1px 0 0;
  background: var(--surface);
  border: 1.5px solid var(--line-strong); border-radius: 6px;
  cursor: pointer;
  transition: background-color .18s var(--ease), border-color .18s var(--ease);
}
.form-case input:hover { border-color: var(--grey-400); }
.form-case input:checked {
  border-color: var(--ink);
  background: var(--ink) center / 12px 12px no-repeat
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
}
.form-case input:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.form-case a { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }
.form__envoi { width: 100%; padding-block: 1rem; margin-top: .375rem; }

/* — Encart contextuel sous la connexion — */
.mobile-aide {
  margin-top: 2.5rem;
  padding: 1.25rem 1.375rem;
  background: var(--surface-soft);
  border-radius: var(--r);
}
.mobile-aide__titre { font-size: var(--fs-sm); font-weight: 600; letter-spacing: -.01em; }
.mobile-aide__liste { display: grid; gap: .875rem; margin: 1rem 0 0; }
.mobile-aide__liste dt {
  display: flex; align-items: center; gap: .4375rem;
  font-size: var(--fs-xs); font-weight: 600;
}
.mobile-aide__liste dt svg { flex: none; color: var(--ink); }
.mobile-aide__liste dd { margin: .125rem 0 0; font-size: var(--fs-xs); line-height: 1.55; color: var(--grey-500); }

/* ------------------------------ 20. ACCOUNT CREATED, MANAGING A SUBSCRIPTION
   On Mon abonnement. The "Ton compte est créé" dialog opens once only, right
   after sign-up. The panel saying where to manage the subscription on each
   kind of phone is permanent. */
.modale__boite--compte-cree { text-align: center; }
.modale__boite--compte-cree .modale__titre { padding-right: 0; }

.gerer-abo {
  display: grid; gap: 1rem;
  margin-bottom: 1.5rem;
  padding: 1.125rem 1.25rem;
  /* One shade below --surface-soft (#F6F7F8), without going as far as
     --surface-sink: the card stands out better against the page's white. */
  background: #F3F4F6;
  border-radius: var(--r);
}
.gerer-abo__voie { font-size: var(--fs-sm); line-height: 1.55; color: var(--grey-700); }
.gerer-abo__appareil {
  /* start, not center: these headings wrap to two lines on a narrow screen,
     and a centred icon then hangs in the gap between them instead of marking
     the line it belongs to. */
  display: flex; align-items: start; gap: .4375rem;
  margin-bottom: .25rem;
  font-weight: 600; color: var(--ink);
}
/* Nudged down by the half-leading of the first line, so the icon sits on the
   capitals rather than on the ascender line above them. */
.gerer-abo__appareil svg { flex: none; width: 16px; height: 16px; margin-top: .1875rem; }


/* A line under the header, when a friend arrives through a sponsor's link.
   It scrolls with the page: it is information, not an alert. */
.bandeau-invite {
  /* Above the header and stuck to the very top, like the announcement bar of
     an online shop: the friend keeps their sponsor's name in sight the whole
     way down, which is what the strip is for — it vouches for the product.
     The header is pushed down by exactly this bar's height, measured in
     main.js (--haut-bandeau): the bar can wrap to two lines on a narrow
     screen, so the offset cannot be a constant. */
  position: sticky; top: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .625rem 1rem;
  background: var(--other); color: var(--other-ink);
  font-size: var(--fs-xs); text-align: center;
}
.bandeau-invite svg { flex: none; width: 15px; height: 15px; }
.bandeau-invite b { font-weight: 600; }

/* What the account already gives, for free: value before the sale.
   On Mon abonnement, while no sport is active. */
.offre-gratuite {
  display: flex; align-items: center; gap: .875rem;
  margin-bottom: 1.5rem;
  padding: 1.125rem 1.25rem;
  /* The site's yellow (--other #FBF2D1, 84% saturation) brought down to
     66%: same hue, and above all the SAME LIGHTNESS — desaturating a yellow
     darkens it if you are not careful, so lightness was raised to match. */
  background: #F6EFD4;
  border: 1px solid #EEE2B0;
  border-radius: var(--r);
}
/* The circle turns white: on yellow, a yellow circle would vanish. */
.offre-gratuite__icone {
  display: grid; place-items: center;
  flex: none; width: 42px; height: 42px;
  background: var(--surface); color: var(--other-ink);
  border-radius: 50%;
}
.offre-gratuite__icone svg { width: 22px; height: 22px; }
.offre-gratuite__titre { font-size: 1.0625rem; font-weight: 600; letter-spacing: -.015em; }
/* Warm brown rather than grey: on a yellow ground, grey goes dull. */
.offre-gratuite__texte { margin-top: .125rem; font-size: var(--fs-xs); color: var(--other-ink); }

/* ------------------------------------------- 21. ESPACE CONNECTÉ */

/* Account navigation: three entries, no more. The brief explicitly forbids
   turning this into a dashboard. */
.compte-nav { border-bottom: 1px solid var(--line); }
.compte-nav__inner { display: flex; gap: 1.5rem; overflow-x: auto; scrollbar-width: none; }
.compte-nav__inner::-webkit-scrollbar { display: none; }
.compte-nav a {
  padding-block: 1rem;
  border-bottom: 2px solid transparent;
  font-size: var(--fs-sm); font-weight: 500;
  color: var(--grey-500);
  white-space: nowrap;
}
.compte-nav a:hover { color: var(--ink); }
.compte-nav a[aria-current='page'] { color: var(--ink); font-weight: 600; border-bottom-color: var(--ink); }
.espace { padding-block: clamp(1.75rem, 4vw, 2.75rem) clamp(3rem, 6vw, 4.5rem); }
.espace__inner { max-width: 44rem; }
.espace__titre {
  font-size: clamp(1.625rem, 1.3rem + 1.4vw, 2rem);
  font-weight: 700; letter-spacing: -.03em; line-height: 1.15;
}
.espace__tete { margin-bottom: clamp(1.75rem, 3vw, 2.25rem); }
.espace__note { margin-top: 2rem; font-size: var(--fs-xs); color: var(--grey-500); }
.espace__inner--etroit { max-width: 34rem; }

/* Two buttons side by side, full width on a phone */
.hero__actions { display: flex; flex-wrap: wrap; gap: .75rem; margin-bottom: 1.375rem; }
.final-cta .hero__actions { justify-content: center; margin-bottom: 0; }
@media (max-width: 479px) {
  .hero__actions { display: grid; }
  .hero__actions .btn { width: 100%; }
}

/* ----------------------------------------------- Legal pages (long text)
   A narrow column: beyond ~70 characters the eye loses the next line on the
   way back to the margin. This is the only place on the site where people
   really read paragraphs. */
.doc { padding-block: clamp(2rem, 5vw, 3.5rem) clamp(3rem, 6vw, 5rem); }
.doc__inner { max-width: 44rem; }
.doc__titre {
  font-size: clamp(1.75rem, 1.3rem + 1.8vw, 2.375rem);
  font-weight: 700; letter-spacing: -.03em; line-height: 1.15;
  text-wrap: balance;
}
.doc__maj {
  margin-top: .625rem; padding-bottom: 1.75rem;
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-sm); color: var(--grey-500);
}
.doc__inner h2 {
  margin-top: 2.5rem;
  font-size: 1.25rem; font-weight: 700; letter-spacing: -.02em;
}
.doc__inner h3 {
  margin-top: 1.75rem;
  font-size: 1.0625rem; font-weight: 600; letter-spacing: -.015em;
}
.doc__inner p { margin-top: .875rem; line-height: 1.7; color: var(--grey-700); }
.doc__inner b { color: var(--ink); font-weight: 600; }
.doc__inner ul { margin: .875rem 0 0; padding-left: 1.25rem; list-style: disc; }
.doc__inner li { margin-top: .4375rem; line-height: 1.7; color: var(--grey-700); }
/* The privacy policy's tables. The scrolling frame is only a safety net:
   nothing should overflow any more. position: relative keeps the header that
   is hidden on phones (below) inside the frame; without it, it escaped the
   dialog's text area and made it taller. */
.doc__inner > div:has(table) { position: relative; margin-top: 1.25rem; overflow-x: auto; }
.doc__inner table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}
.doc__inner th, .doc__inner td {
  padding: .75rem .875rem;
  border: 1px solid var(--line);
  text-align: left; vertical-align: top;
}
.doc__inner th { background: var(--surface-soft); font-weight: 600; }
.doc__inner td { color: var(--grey-700); }
/* On phones, two narrow columns broke every row into three or four pieces,
   or overflowed the screen. Each row becomes a stacked pair — the purpose,
   then its legal basis in grey — under the article heading, which already says
   what the table holds. The header is still read by screen readers. The text
   itself is unchanged. */
@media (max-width: 559px) {
  .doc__inner table, .doc__inner tbody, .doc__inner tr,
  .doc__inner th, .doc__inner td { display: block; }
  .doc__inner table { border-top: 1px solid var(--line); }
  .doc__inner tr { padding-block: .875rem; border-bottom: 1px solid var(--line); }
  .doc__inner tr:first-child {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap;
  }
  .doc__inner th, .doc__inner td { padding: 0; border: 0; }
  .doc__inner td:first-child { color: var(--ink); font-weight: 500; }
  .doc__inner td + td { margin-top: .25rem; }
}

/* The same text, read in a dialog during sign-up. Wider than the other
   dialogs: it is the only one where people read paragraphs.
   At the top, a fixed white bar carries the close cross: you can close at any
   time. The text scrolls beneath it to the bottom edge of the dialog; its
   margins scroll with it, so no band cuts it off at the bottom.
   min-width: 0: without it, wide content (a table) stretched the dialog past
   the screen, close cross included.
   88dvh: the height actually visible on a phone, browser bars excluded; 88vh
   remains for browsers that do not know it. */
.modale__boite--doc {
  display: flex; flex-direction: column;
  min-width: 0; max-width: 40rem;
  max-height: min(46rem, 88vh);
  max-height: min(46rem, 88dvh);
  padding: 0;
  overflow: hidden;
}
.doc-modale__barre {
  flex: none;
  display: flex; justify-content: flex-end;
  padding: .875rem .875rem 0;
}
.doc-modale__barre .modale__fermer { position: static; }
.doc-modale {
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0 clamp(1.5rem, 4vw, 2rem) clamp(1.5rem, 4vw, 2rem);
  outline: none;
}
.doc-modale .doc__titre { font-size: clamp(1.375rem, 1.1rem + 1vw, 1.625rem); }
.doc-modale .doc__maj { padding-bottom: 1.25rem; }
.doc-modale__attente { color: var(--grey-500); }

/* Verification code: six spaced digits, readable at a glance to copy from
   the e-mail. The letter-spacing adds a gap after the last digit, which the
   left indent offsets to keep the code centred. */
.form-champ input[type='text'].champ-code {
  text-align: center;
  padding-left: calc(.9375rem + .45em);
  font-size: 1.375rem; font-weight: 600; letter-spacing: .45em;
  font-variant-numeric: tabular-nums;
}
.form-champ input[type='text'].champ-code::placeholder { color: var(--line-strong); }

.renvoi { text-align: center; font-size: var(--fs-sm); }
.renvoi__bouton {
  appearance: none; -webkit-appearance: none;
  padding: 0; background: none; border: 0;
  font: inherit; font-weight: 600; color: var(--ink);
  text-decoration: underline; text-underline-offset: 3px;
  cursor: pointer;
}
.renvoi__attente { color: var(--grey-500); font-variant-numeric: tabular-nums; }

/* ----------------------------------------------------------------- History
   Same frame as the summary: a bordered list, rows separated by a rule. One
   block per month, to find a payment by its date without scrolling through
   everything. */
.historique { display: grid; gap: 1.75rem; }
.historique__titre-mois {
  margin-bottom: .625rem;
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--grey-500);
}
.historique__liste {
  margin: 0; padding: 0; list-style: none;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  overflow: hidden;
}

/* Tight margins: "Basketball 2 semaines" must fit on one line next to two
   icons and the amount, from 390 px wide. */
.paiement-ligne {
  display: flex; align-items: center; gap: .75rem;
  padding: 1rem;
}
.paiement-ligne + .paiement-ligne { border-top: 1px solid var(--line); }

/* Several sports in one payment: the icons overlap, ringed in white to stay
   legible over one another. */
.paiement-ligne__icones { flex: none; display: flex; }
.paiement-ligne__icones img {
  width: 40px; height: 40px; border-radius: 50%;
  box-shadow: 0 0 0 2px var(--surface);
}
.paiement-ligne__icones img + img { margin-left: -1.25rem; }

.paiement-ligne__corps { flex: 1; min-width: 0; display: grid; gap: .125rem; }
/* The sport in bold, its duration right after in regular weight; one sport
   per row when the payment covered several. */
.paiement-ligne__sports { font-size: var(--fs-sm); color: var(--grey-700); }
.paiement-ligne__sport { display: block; }
.paiement-ligne__sports b { font-weight: 600; color: var(--ink); }
.paiement-ligne__detail { font-size: var(--fs-xs); color: var(--grey-500); }

/* Amount and status right-aligned, row after row: that is the column people
   scan while comparing against their payment texts. */
.paiement-ligne__fin { flex: none; display: grid; gap: .125rem; justify-items: end; text-align: right; }
.paiement-ligne__montant {
  font-size: var(--fs-sm); font-weight: 600; letter-spacing: -.015em;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.paiement-ligne__statut { font-size: var(--fs-xs); color: var(--grey-500); white-space: nowrap; }

/* No money moved: the amount fades, the status takes the form-error colour
   — not the red of expiring subscriptions, which is reserved for time
   remaining. */
.paiement-ligne[data-etat='echoue'] .paiement-ligne__montant { color: var(--grey-400); font-weight: 500; }
.paiement-ligne[data-etat='echoue'] .paiement-ligne__statut { color: #C6453F; }
.paiement-ligne[data-etat='attente'] .paiement-ligne__statut { color: var(--ambre); font-weight: 500; }

.historique-vide {
  display: grid; gap: 1.25rem; justify-items: start;
  padding: 2rem 1.5rem;
  background: var(--surface-soft);
  border-radius: var(--r);
}
.historique-vide__texte { color: var(--grey-700); }

/* ---------------------------------------------------------------- Profile
   Blocks separated by a rule, not cards: this is one settings page, not a
   collection of objects.
   Every rule separating items on this page is #EBECED, a colour chosen by the
   client. */
.profil-bloc + .profil-bloc {
  margin-top: 2.25rem; padding-top: 2.25rem;
  border-top: 1px solid #EBECED;
}
.profil-bloc__titre {
  margin-bottom: 1.25rem;
  font-size: 1.125rem; font-weight: 700; letter-spacing: -.02em;
}
.profil-bloc .form { margin-top: 0; }

/* A read-only card, modelled on the app's "My profile" screen: a grey
   background and no field frames — nothing invites typing. Label on the left,
   value on the right. A long value (e-mail, first names) wraps rather than
   pushing the label aside. */
.fiche {
  margin: 0;
  padding-inline: 1rem;
  background: var(--surface-soft);
  border-radius: var(--r);
}
.fiche__ligne {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  padding-block: .9375rem;
  font-size: var(--fs-sm);
}
.fiche__ligne + .fiche__ligne { border-top: 1px solid #EBECED; }
.fiche dt { flex: none; color: var(--grey-500); }
.fiche dd {
  min-width: 0; margin: 0;
  font-weight: 500; text-align: right; overflow-wrap: anywhere;
}
.fiche dd img {
  display: inline-block; width: 20px; height: 20px;
  margin-right: .5rem; vertical-align: -5px;
  border-radius: 50%;
}

.profil-modifier { display: grid; justify-items: start; margin-top: 2rem; }
.profil-modifier__titre { font-weight: 600; letter-spacing: -.01em; }
.profil-modifier__texte { margin-top: .25rem; font-size: var(--fs-sm); line-height: 1.55; color: var(--grey-500); }
.profil-modifier .btn { margin-top: 1rem; }

.profil-envoi { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; margin-top: .25rem; }
.profil-confirme {
  display: inline-flex; align-items: center; gap: .375rem;
  font-size: var(--fs-sm); font-weight: 500; color: var(--etat-vert);
}
.profil-confirme::before { content: '✓'; font-weight: 700; }

.profil-ligne {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: .875rem 1rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
}
.profil-ligne__valeur { letter-spacing: .15em; color: var(--grey-500); }
.profil-bloc > .profil-confirme { margin-top: .75rem; }
.profil-mdp { gap: 1.125rem; }

button.lien-secondaire {
  appearance: none; -webkit-appearance: none;
  padding: 0; background: none; border: 0;
  font-family: inherit; cursor: pointer;
}

/* Deletion right at the bottom, as text: finding it must be possible,
   triggering it by accident must not. */
.profil-suppression {
  margin-top: 3rem; padding-top: 1.5rem;
  border-top: 1px solid #EBECED;
}
.profil-suppression__lien {
  appearance: none; -webkit-appearance: none;
  padding: 0; background: none; border: 0;
  font: inherit; font-size: var(--fs-sm); font-weight: 500; color: #C6453F;
  cursor: pointer;
}
.profil-suppression__lien:hover { text-decoration: underline; text-underline-offset: 3px; }

.btn--danger { background: #C6453F; color: #fff; }
.btn--danger:hover { background: #AD3A35; }

/* Status dot: the colour doubles the word, it never replaces it */
.pastille {
  flex: none; display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--grey-400);
}

/* The three state colours. They are composed in mon-abonnement.js
   ("'pastille pastille--' + shade"): no page spells them out in full, so do
   not assume they are unused. */
.pastille--verte { background: var(--etat-vert); }
.pastille--orange { background: var(--etat-orange); }
.pastille--rouge { background: var(--etat-rouge); }
.pastille--grise { background: var(--grey-400); }

/* — Back link, at the top of a secondary screen — */
.retour {
  display: inline-flex; align-items: center; gap: .375rem;
  margin-bottom: 1rem;
  font-size: var(--fs-sm); font-weight: 500; color: var(--grey-500);
  transition: gap .18s var(--ease), color .18s var(--ease);
}
.retour svg { width: 15px; height: 15px; flex: none; }
.retour:hover { gap: .625rem; color: var(--ink); }

/* — Duration choice —
   Four rows of equal weight. The price is on the right, aligned row after
   row: that is the column people scan to compare. */
/* No top margin: the form carries the gap below the heading. Both together
   left a 56 px hole under "Abonnement Football". */
.durees { display: grid; gap: .625rem; margin: 0; padding: 0; list-style: none; }
.duree {
  display: flex; align-items: center; gap: .875rem;
  padding: 1rem 1.125rem;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
@media (hover: hover) {
  .duree:hover { border-color: var(--grey-400); }
}
/* The doubled rule marks the chosen row without shifting anything: a
   thicker border would move the text at the moment of the tap. */
.duree:has(.duree__radio:checked) {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
}
.duree:has(.duree__radio:focus-visible) { outline: 2px solid var(--ink); outline-offset: 2px; }

/* The real radio button stays for keyboards and screen readers; it is the
   mark beside it that you see. */
.duree__radio { position: absolute; opacity: 0; width: 0; height: 0; }
.duree__marque {
  flex: none; display: grid; place-items: center;
  width: 20px; height: 20px;
  border: 1.5px solid var(--line-strong); border-radius: 50%;
  transition: border-color .18s var(--ease);
}
.duree__marque::after {
  content: ""; width: 10px; height: 10px; border-radius: 50%;
  background: var(--ink); transform: scale(0);
  transition: transform .18s var(--ease);
}
.duree__radio:checked ~ .duree__marque { border-color: var(--ink); }
.duree__radio:checked ~ .duree__marque::after { transform: scale(1); }
.duree__corps { flex: 1; min-width: 0; display: grid; gap: .0625rem; }
.duree__terme { font-size: 1.0625rem; font-weight: 600; letter-spacing: -.015em; }
.duree__note { font-size: var(--fs-xs); color: var(--grey-500); }

/* The highlighted plan carries its label on the border, above the row. It
   registers while scanning the list, before it is even read — which text
   inside the row does not. It also costs no height: the row stays the
   shortest of the four.

   The wording still comes from the reference list: compte.js provides it, and
   the highlight follows if it moves to another plan. */
.duree[data-populaire] { position: relative; margin-top: .5rem; }
.duree[data-populaire] .duree__note {
  position: absolute; top: -.5625rem; left: 1.125rem;
  padding: .1875rem .5rem;
  background: var(--ink); color: #fff;
  border-radius: 999px;
  font-size: .625rem; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; white-space: nowrap;
}
.duree__prix { flex: none; text-align: right; display: grid; gap: .0625rem; }
.duree__prix b { font-size: 1.0625rem; font-weight: 600; letter-spacing: -.015em; }
.duree__prix s { font-size: var(--fs-xs); color: var(--grey-400); }

/* — Summary —
   One row per sport: the icon, what is being taken, the price. Prices are
   right-aligned row after row — that is the column people add up by eye before
   reading the total. */
.recap {
  margin-top: 1.5rem; padding: 0; list-style: none;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  overflow: hidden;
}
.recap-ligne {
  display: flex; align-items: flex-start; gap: .875rem;
  padding: 1rem 1.125rem;
}
.recap-ligne + .recap-ligne { border-top: 1px solid var(--line); }
.recap-ligne__icone { flex: none; width: 34px; height: 34px; }
.recap-ligne__corps { flex: 1; min-width: 0; }
.recap-ligne__sport { font-size: var(--fs-sm); font-weight: 600; }
.recap-ligne__detail { margin-top: .0625rem; font-size: var(--fs-xs); color: var(--grey-500); }
.recap-ligne__prix {
  flex: none; font-size: var(--fs-sm); font-weight: 600; letter-spacing: -.015em;
}

/* Edit and remove: two quiet links, under the row they act on. Buttons
   would give them more weight than the choice itself. */
.recap-ligne__liens { display: flex; gap: .875rem; margin-top: .375rem; }
.recap-ligne__liens a {
  font-size: var(--fs-xs); color: var(--grey-500);
  text-decoration: underline; text-underline-offset: 3px;
}
.recap-ligne__liens a:hover { color: var(--ink); }

/* — Discovery offer —
   A suggestion, not an instruction: soft background, secondary button. It sits
   after the cart and before the total, where people do their sums — the moment
   when adding two thousand francs is still acceptable. */
.offre {
  display: flex; align-items: center; gap: .875rem;
  margin-top: .875rem; padding: .875rem 1rem;
  background: var(--surface-soft);
  border: 1px solid var(--line);
  border-radius: var(--r);
}
.offre__icone { flex: none; width: 40px; height: 40px; }
.offre__corps { flex: 1; min-width: 0; }
.offre__titre { font-size: var(--fs-sm); font-weight: 600; }
.offre__texte { margin-top: .0625rem; font-size: var(--fs-xs); color: var(--grey-500); }
.offre__action { flex: none; padding: .5rem 1rem; background: var(--surface); }

/* On a narrow screen the button moves under the text rather than crushing
   it: "Découvre aussi le Basketball" needs its width. */
@media (max-width: 400px) {
  .offre { flex-wrap: wrap; }
  .offre__action { width: 100%; }
}

.recap-ajout { margin-top: .875rem; font-size: var(--fs-sm); color: var(--grey-500); }
.recap-ajout a {
  font-weight: 600; color: var(--ink);
  text-decoration: underline; text-underline-offset: 3px;
}

/* The total stands out by a rule, not a colour: it is an amount to read,
   not an alert. */
.recap-total {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  margin-top: 1.25rem; padding-top: 1.125rem;
  border-top: 1px solid var(--line-strong);
  font-size: var(--fs-sm); font-weight: 500; color: var(--grey-700);
}
.recap-total b { font-size: 1.25rem; font-weight: 700; letter-spacing: -.025em; color: var(--ink); }

/* The payment button follows the total, with nothing in between. */
.recap-total + .form__envoi { margin-top: 1.5rem; }


/* — Payment return —
   One screen, four outcomes. Everything is centred: there is one thing to read
   and one thing to do. The colour lives in the mark, not the heading — a large
   red heading frightens before it has even been read. */
.issue { margin-top: clamp(1.5rem, 5vw, 3rem); text-align: center; }
.issue__marque {
  display: grid; place-items: center;
  width: 62px; height: 62px; margin: 0 auto 1.375rem;
  border-radius: 50%;
}
.issue__marque svg { width: 30px; height: 30px; display: none; }
.issue__marque[data-marque='ok']      [data-pour='ok'],
.issue__marque[data-marque='attente'] [data-pour='attente'],
.issue__marque[data-marque='echec']   [data-pour='echec'],
.issue__marque[data-marque='neutre']  [data-pour='neutre'] { display: block; }
.issue__marque[data-marque='ok'] { background: #E4F4EC; color: var(--etat-vert); }
/* The green tick animates on appearance: the circle arrives, then the
   stroke draws itself. Only the good news moves — waiting and failure stay
   still. "both" keeps the final state: even with animation off (reduced
   motion, older browser), the tick stays whole. */
@keyframes marque-rond {
  from { transform: scale(.7); opacity: 0 }
  60%  { transform: scale(1.06) }
  to   { transform: scale(1); opacity: 1 }
}
@keyframes marque-trait { from { stroke-dashoffset: 22 } to { stroke-dashoffset: 0 } }
.issue__marque[data-marque='ok'] { animation: marque-rond .42s var(--ease) both; }
.issue__marque[data-marque='ok'] [data-pour='ok'] path {
  stroke-dasharray: 22;
  animation: marque-trait .38s var(--ease) .22s both;
}
.issue__marque[data-marque='attente'] { background: var(--ambre-fond); color: var(--ambre); }
.issue__marque[data-marque='echec'] { background: #F8E3E4; color: var(--etat-rouge); }
.issue__marque[data-marque='neutre'] { background: var(--surface-sink); color: var(--grey-400); }
.issue__titre {
  font-size: clamp(1.5rem, 1.2rem + 1.3vw, 1.875rem);
  font-weight: 700; letter-spacing: -.03em; line-height: 1.2;
  text-wrap: balance;
}
.issue__texte {
  max-width: 26rem; margin: .75rem auto 0;
  font-size: var(--fs-sm); line-height: 1.6; color: var(--grey-500);
}
.issue__actions { display: grid; justify-items: center; gap: 1rem; margin-top: 2rem; }
.issue__actions .btn { width: 100%; max-width: 20rem; }
/* Paiement confirmé : les boutons iPhone et Android, centrés sous l'action. */
.issue__telecharger { margin-top: 2.5rem; }
.issue__telecharger .tel-compte__voies { justify-content: center; }
.lien-secondaire {
  font-size: var(--fs-sm); font-weight: 500; color: var(--grey-500);
  text-decoration: underline; text-underline-offset: 3px;
}
.lien-secondaire:hover { color: var(--ink); }

/* — Cartes de sport — */
.sports-abo { display: grid; gap: .75rem; margin: 0; padding: 0; list-style: none; }
.carte-sport {
  display: grid;
  grid-template-columns: 46px minmax(0, 1fr) auto;
  align-items: center; gap: .25rem 1rem;
  padding: 1.125rem 1.25rem;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
}

/* The icon brings its own coloured circle: the frame only gives it its
   size. Nothing to define here per sport. */
.carte-sport__icone {
  display: grid; place-items: center;
  width: 46px; height: 46px;
}
.carte-sport__icone img { width: 100%; height: 100%; }

/* While a sport is not open, its icon is desaturated. The day it opens,
   removing the --bientot class gives it its colours back. */
.carte-sport--bientot .carte-sport__icone img { filter: grayscale(1); }
.carte-sport__corps { display: grid; gap: .1875rem; min-width: 0; }
.carte-sport__nom { font-size: 1.0625rem; font-weight: 600; letter-spacing: -.015em; }

/* The state: a coloured dot and what is left. The colour lives in the dot,
   not the text — that is what you see from a distance. */
.carte-sport__statut {
  display: flex; align-items: center; gap: .4375rem;
  font-size: var(--fs-sm); font-weight: 500; color: var(--grey-700);
}
.carte-sport__action { flex: none; padding: .625rem 1.125rem; }
.carte-sport--bientot { background: var(--surface-soft); }
.carte-sport--bientot .carte-sport__nom { color: var(--grey-400); }

/* On a phone the action moves under the text rather than crushing it */
@media (max-width: 519px) {
  .carte-sport { grid-template-columns: 46px minmax(0, 1fr); }
  .carte-sport__action { grid-column: 1 / -1; width: 100%; margin-top: .875rem; }
}

/* — Payment awaiting the operator —
   A line, not a panel: there is nothing to do, only something to know. The
   clock carries the amber of pending payments. */
/* Amber panel: a pending payment is neither good news nor bad, it is a
   state. The background sets it apart from the rest of the page without
   alarming. Dark amber text rather than grey: on a warm ground, grey goes dull
   (measured contrast 5.8). */
.info-attente {
  display: flex; align-items: flex-start; gap: .625rem;
  margin-bottom: 1.25rem;
  padding: .875rem 1rem;
  background: var(--ambre-fond);
  border-radius: var(--r);
  font-size: var(--fs-sm); line-height: 1.5; color: #9A4507;
}
.info-attente svg { flex: none; width: 18px; height: 18px; margin-top: .125rem; color: var(--ambre); }
.info-attente b { font-weight: 600; }

/* ------------------------------------------ 21. MOUVEMENT RÉDUIT & IMPRESSION */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

@media print {
  .site-header, .mobile-cta, .mobile-nav { display: none !important; }
  body { color: #000; }
}
