/*
 * Le site public de Liftz : une présentation et les pages que la Play Console
 * exige (confidentialité, conditions, suppression de compte).
 *
 * Il reprend la charte de l'application et non une charte « web » : mêmes
 * couleurs (src/theme/variables.css), même police, mêmes cartes que les
 * réglages et l'accueil (.glass-card, .settings-title, .ob-row, .ob-icon),
 * même halo rouge en haut d'écran. Les valeurs sont recopiées, pas importées :
 * le site est servi seul, sans le build de l'application. Une couleur changée
 * dans variables.css se change donc ici aussi.
 *
 * Aucun script, aucune ressource tierce : la police est servie par le site
 * lui-même. La politique de confidentialité dit que Liftz ne mesure rien, la
 * page qui la publie ne doit pas la contredire en appelant Google Fonts.
 */

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/fonts/inter.woff2') format('woff2');
}

/* ==========================================================================
   JETONS — recopiés de src/theme/variables.css
   ========================================================================== */

:root {
  color-scheme: light dark;

  --app-radius-2xs: 6px;
  --app-radius-xs: 10px;
  --app-radius-sm: 14px;
  --app-radius-md: 18px;
  --app-radius-lg: 24px;
  --app-radius-full: 999px;

  --app-space-xs: 4px;
  --app-space-sm: 8px;
  --app-space-md: 14px;
  --app-space-lg: 20px;
  --app-space-xl: 28px;

  /* Le vocabulaire de mouvement de l'app (variables.css, docs/motion), recopié
     tel quel : le site bouge au même rythme que l'application qu'il montre.
     Pas de `--app-ease-overshoot` : la direction des vidéos refuse le rebond,
     le site la suit */
  --app-motion-press: 90ms;
  --app-motion-fast: 160ms;
  --app-motion-base: 240ms;
  --app-motion-slow: 400ms;
  --app-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --app-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --app-ease-sheet: cubic-bezier(0.32, 0.72, 0, 1);
  --app-spring-snappy: 470ms
    linear(
      0,
      0.0306,
      0.1082,
      0.2143,
      0.3344,
      0.4573,
      0.575,
      0.6824,
      0.7763,
      0.8552,
      0.919,
      0.9686,
      1.0052,
      1.0307,
      1.0468,
      1.0554,
      1.0583,
      1.0569,
      1.0527,
      1.0466,
      1.0397,
      1.0325,
      1.0256,
      1.0193,
      1.0137,
      1.009,
      1.0051,
      1.0021,
      0.9999,
      0.9984,
      0.9974,
      0.9968,
      0.9966,
      0.9967,
      0.9969,
      0.9972,
      0.9976,
      0.9981,
      0.9985,
      0.9988,
      1
    );
  --app-spring-gentle: 510ms
    linear(
      0,
      0.0125,
      0.0451,
      0.0919,
      0.1478,
      0.2093,
      0.2733,
      0.3378,
      0.4009,
      0.4617,
      0.5192,
      0.573,
      0.6227,
      0.6683,
      0.7098,
      0.7472,
      0.7807,
      0.8107,
      0.8372,
      0.8606,
      0.8811,
      0.8991,
      0.9147,
      0.9282,
      0.9399,
      0.9499,
      0.9585,
      0.9658,
      0.972,
      0.9772,
      0.9816,
      0.9852,
      0.9883,
      0.9908,
      0.9929,
      0.9946,
      0.996,
      0.9971,
      0.998,
      0.9987,
      1
    );
  --app-transition-fast: var(--app-motion-fast) var(--app-ease-out);
  --app-transition: var(--app-motion-base) var(--app-ease-out);

  --app-shadow-md:
    0 6px 20px rgba(0, 0, 0, 0.06), 0 2px 6px rgba(0, 0, 0, 0.04);

  --ion-background-color: #ffffff;
  --ion-text-color: #111111;
  --ion-text-color-rgb: 17, 17, 17;
  --ion-color-primary: #c0283f;
  --ion-color-primary-rgb: 192, 40, 63;
  --ion-color-primary-shade: #a92337;
  --ion-color-secondary: #5b8cff;
  --ion-color-secondary-rgb: 91, 140, 255;
  --ion-color-tertiary: #8b5cf6;
  --ion-color-tertiary-rgb: 139, 92, 246;
  --ion-color-success: #22c55e;
  --ion-color-success-rgb: 34, 197, 94;
  --ion-color-warning: #f59e0b;
  --ion-color-warning-rgb: 245, 158, 11;
  --ion-color-danger: #de3039;
  --ion-color-danger-rgb: 225, 29, 72;
  --ion-color-medium: #6b7280;

  --app-card-background: rgba(255, 255, 255, 0.95);
  --app-border-color: rgba(0, 0, 0, 0.08);
  --toolbar-background: rgba(255, 255, 255, 0.82);
  --tool-hairline: rgba(var(--ion-text-color-rgb), 0.08);
  --tool-fill: rgba(var(--ion-text-color-rgb), 0.05);

  /*
   * Les couleurs de l'application servent de fond et d'icône ; en texte sur
   * fond blanc, plusieurs passent sous le contraste de 4,5:1 qu'un texte courant
   * demande (le jaune des pastilles Pro à 2,1:1, le vert des « Gratuit » à
   * 2,3:1, le blanc sur l'orange des boutons à 2,6:1). Le thème clair a donc
   * ses teintes de texte, plus sombres ; le sombre garde celles de l'app.
   *
   * Le rouge est celui de l'app depuis la 0.11.0 (#c0283f, #d43b53 en sombre) :
   * il tient 5,8:1 en texte sur blanc, `--text-primary` du clair est donc lui.
   *
   * Les boutons pleins sont un aplat de ce rouge, comme dans l'app : le blanc
   * y tient 5,8:1 en clair et 4,6:1 en sombre (le dégradé vers l'orange tombait
   * à 2,6:1). Le survol passe à `--ion-color-primary-shade`, plus sombre, qui
   * ne fait que remonter le contraste. `--button-gradient` reste celui des
   * titres `.accent`, du grand texte.
   */
  --text-primary: #c0283f;
  --text-success: #166534;
  --text-warning: #b45309;
  --text-secondary: #1d4ed8;
  --button-gradient: linear-gradient(135deg, #c0283f, #c93a1f);
}

@media (prefers-color-scheme: dark) {
  :root {
    --app-shadow-md:
      0 6px 20px rgba(0, 0, 0, 0.4), 0 2px 6px rgba(0, 0, 0, 0.3);

    --ion-background-color: #000000;
    --ion-text-color: #f5f5f5;
    --ion-text-color-rgb: 245, 245, 245;
    --ion-color-primary: #d43b53;
    --ion-color-primary-rgb: 212, 59, 83;
    --ion-color-primary-shade: #bb3449;
    --ion-color-secondary: #7aa2ff;
    --ion-color-secondary-rgb: 122, 162, 255;
    --ion-color-tertiary: #9b7bff;
    --ion-color-tertiary-rgb: 155, 123, 255;
    --ion-color-success: #30d158;
    --ion-color-success-rgb: 48, 209, 88;
    --ion-color-warning: #ffb020;
    --ion-color-warning-rgb: 255, 176, 32;
    --ion-color-danger: #df3c3c;
    --ion-color-danger-rgb: 239, 68, 68;
    --ion-color-medium: #8f96a3;

    --app-card-background: rgba(20, 20, 20, 0.92);
    --app-border-color: rgba(255, 255, 255, 0.08);
    --toolbar-background: rgba(0, 0, 0, 0.72);

    --text-primary: #ff4961;
    --text-success: #30d158;
    --text-warning: #ffb020;
    --text-secondary: #7aa2ff;
    --button-gradient: linear-gradient(135deg, #ff4961, #ff7b54);
  }
}

/* Un navigateur sans `linear()` (Safari avant 17.2) rejetterait la transition
   entière : il reçoit la courbe de sortie, comme la WebView de l'app */
@supports not (transition-timing-function: linear(0, 1)) {
  :root {
    --app-spring-snappy: 280ms var(--app-ease-out);
    --app-spring-gentle: 380ms var(--app-ease-out);
  }
}

/* ==========================================================================
   BASE
   ========================================================================== */

* {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  /* Le rectangle bleu que Chrome Android pose sur tout ce qu'on touche : les
     boutons ont leur propre retour (:active), le clavier garde :focus-visible */
  -webkit-tap-highlight-color: transparent;
}

/* Le filet contre le défilement horizontal : l'overflow-x du body passe au
   viewport, que les navigateurs mobiles laissent quand même dézoomer.
   « clip » coupe sans créer de conteneur de défilement, la topbar reste
   collante */
main {
  overflow-x: clip;
}

body {
  margin: 0;
  min-height: 100vh;
  color: var(--ion-text-color);
  font-family:
    'Inter',
    system-ui,
    -apple-system,
    'Segoe UI',
    Roboto,
    sans-serif;
  font-size: 15px;
  line-height: 1.6;
  overflow-x: hidden;
}

/*
 * Le halo de ion-app (variables.css et motion.css de l'app), à l'identique :
 * un dégradé fixe en haut de l'écran, et deux voiles de la même teinte qui
 * respirent par-dessus. Le voile seul, sans le dégradé de base, se voyait à
 * peine depuis que le rouge est celui de l'app, plus sombre. Comme dans l'app,
 * les voiles n'existent qu'en mouvement : avec le mouvement réduit, reste le
 * dégradé. `fixed` le garde en haut de l'écran pendant le défilement ; iOS,
 * qui l'ignore, le laisse en haut de la page.
 */
body {
  background:
    radial-gradient(
        circle at top,
        rgba(var(--ion-color-primary-rgb), 0.12),
        transparent 40%
      )
      fixed,
    var(--ion-background-color);
}

@media (prefers-reduced-motion: no-preference) {
  /* Débordants des trois côtés : un voile qui dérive ne montre jamais son bord */
  body::before,
  body::after {
    content: '';
    position: fixed;
    inset: -8% -30% auto;
    height: 62%;
    z-index: -1;
    pointer-events: none;
    will-change: transform, opacity;
  }

  /* Le souffle : la masse du halo, qui enfle et se penche */
  body::before {
    background: radial-gradient(
      70% 80% at 50% 6%,
      rgba(var(--ion-color-primary-rgb), 0.09),
      transparent 72%
    );
    animation:
      glow-breathe 13s ease-in-out infinite,
      glow-pulse 4.7s ease-in-out infinite;
  }

  /* Le second foyer, décentré, plus faible et plus lent : son décalage avec le
     premier empêche de lire une pulsation régulière */
  body::after {
    background: radial-gradient(
      50% 65% at 38% 2%,
      rgba(var(--ion-color-primary-rgb), 0.06),
      transparent 74%
    );
    animation:
      glow-drift 19s ease-in-out infinite,
      glow-pulse-slow 6.3s ease-in-out infinite;
  }

  @keyframes glow-breathe {
    0% {
      transform: translate3d(0, 0, 0) scale(1, 1);
    }

    27% {
      transform: translate3d(-5%, 2%, 0) scale(1.12, 1.06);
    }

    52% {
      transform: translate3d(3%, -1%, 0) scale(0.96, 1.16);
    }

    78% {
      transform: translate3d(6%, 3%, 0) scale(1.2, 1.02);
    }

    100% {
      transform: translate3d(0, 0, 0) scale(1, 1);
    }
  }

  @keyframes glow-drift {
    0% {
      transform: translate3d(0, 0, 0) scale(1.06, 1);
    }

    33% {
      transform: translate3d(7%, 2%, 0) scale(0.94, 1.14);
    }

    61% {
      transform: translate3d(-6%, 4%, 0) scale(1.22, 0.98);
    }

    100% {
      transform: translate3d(0, 0, 0) scale(1.06, 1);
    }
  }

  /* La montée est plus courte que la retombée, comme une braise qu'on souffle */
  @keyframes glow-pulse {
    0% {
      opacity: 0.15;
    }

    38% {
      opacity: 1;
    }

    71% {
      opacity: 0.45;
    }

    100% {
      opacity: 0.15;
    }
  }

  @keyframes glow-pulse-slow {
    0% {
      opacity: 0.1;
    }

    44% {
      opacity: 0.85;
    }

    68% {
      opacity: 0.35;
    }

    100% {
      opacity: 0.1;
    }
  }
}

a {
  color: var(--text-primary);
  text-underline-offset: 2px;
}

a:focus-visible,
.button:focus-visible {
  outline: 2px solid var(--ion-color-primary);
  outline-offset: 3px;
  border-radius: var(--app-radius-2xs);
}

strong {
  font-weight: 600;
}

.icon {
  width: 1em;
  height: 1em;
  flex: 0 0 auto;
}

/* ==========================================================================
   BARRE DU HAUT — ion-toolbar + ion-title
   ========================================================================== */

/*
 * Remplie, la barre est presque opaque : au taux de l'app (72 % en sombre), un
 * grand titre rouge ou blanc qui passait dessous se lisait à travers, flou, et
 * la barre paraissait cassée. Le flou reste pour le peu qui passe encore.
 */
.topbar {
  --topbar-fill: color-mix(
    in srgb,
    var(--ion-background-color) 94%,
    transparent
  );
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--toolbar-background);
  /* Écrit en entier : par une variable, un navigateur sans color-mix() perdait
     le fond au lieu de garder celui de la ligne du dessus */
  background: color-mix(in srgb, var(--ion-background-color) 94%, transparent);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  backdrop-filter: saturate(180%) blur(18px);
  border-bottom: 1px solid var(--tool-hairline);
}

/* En haut de page, la barre est transparente, comme l'en-tête à grand titre de
   l'app : remplie, elle couvrait la partie la plus rouge du halo. Elle se
   remplit sur les 80 premiers pixels de défilement, sans script ; un
   navigateur sans `animation-timeline` la garde remplie */
@supports (animation-timeline: scroll()) {
  .topbar {
    animation: topbar-fill linear both;
    animation-timeline: scroll(root);
    animation-range: 0 80px;
  }

  @keyframes topbar-fill {
    from {
      background-color: transparent;
      border-bottom-color: transparent;
      -webkit-backdrop-filter: none;
      backdrop-filter: none;
    }

    /* Écrite : laissée implicite, Chrome finissait sur une barre vide */
    to {
      background-color: var(--topbar-fill);
      border-bottom-color: var(--tool-hairline);
      -webkit-backdrop-filter: saturate(180%) blur(18px);
      backdrop-filter: saturate(180%) blur(18px);
    }
  }
}

/*
 * D'une page du site à l'autre (accueil, nouveautés, langue, pages légales) :
 * la barre du haut reste en place et seul le contenu change, comme un onglet
 * de l'app, au lieu d'un écran blanc puis d'une page qui se repeint. Sans
 * script : le navigateur fait la transition entre deux documents. Une page
 * ouverte par une ancre (#tarifs) n'est pas une navigation, rien ne joue.
 * Un navigateur qui ne connaît pas la règle navigue comme avant.
 */
@media (prefers-reduced-motion: no-preference) {
  @view-transition {
    navigation: auto;
  }

  .topbar {
    view-transition-name: topbar;
  }

  /* L'ancienne page s'efface vite, la nouvelle se pose : ce qui part, on l'a
     déjà lu (la règle des listes de l'app, MotionUtil) */
  ::view-transition-old(root) {
    animation: page-leave var(--app-motion-fast) var(--app-ease-out) both;
  }

  ::view-transition-new(root) {
    animation: page-enter var(--app-motion-base) var(--app-ease-out) both;
  }

  ::view-transition-group(topbar) {
    animation-duration: var(--app-motion-base);
  }

  @keyframes page-leave {
    to {
      opacity: 0;
    }
  }

  @keyframes page-enter {
    from {
      opacity: 0;
      transform: translateY(12px);
    }
  }
}

.topbar-inner {
  display: flex;
  align-items: center;
  gap: var(--app-space-md);
  max-width: 1040px;
  min-height: 56px;
  margin: 0 auto;
  padding: 0 16px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-right: auto;
  color: var(--ion-text-color);
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.04em;
  text-decoration: none;
}

.brand img {
  width: 30px;
  height: 30px;
  border-radius: var(--app-radius-2xs);
  border: 1px solid var(--app-border-color);
}

.topnav {
  display: none;
  gap: var(--app-space-lg);
}

.topnav a {
  color: var(--ion-color-medium);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  transition: color var(--app-transition-fast);
}

.topnav a:hover,
.topnav a[aria-current='page'] {
  color: var(--ion-text-color);
}

/* La pastille de langue de l'accueil de l'application */
.lang {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 14px;
  border-radius: var(--app-radius-full);
  border: 1px solid var(--app-border-color);
  background: var(--app-card-background);
  color: var(--ion-text-color);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  transition:
    border-color var(--app-transition-fast),
    background-color var(--app-transition-fast);
}

@media (min-width: 768px) {
  .topnav {
    display: flex;
  }
}

/* ==========================================================================
   PAGE — gabarit des réglages
   ========================================================================== */

.page {
  max-width: 720px;
  margin: 0 auto;
  padding: var(--app-space-xl) 16px 48px;
}

.page-head {
  margin: 0 12px var(--app-space-xl);
}

.page-head h1 {
  margin: 0;
  font-size: 30px;
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.04em;
}

.page-head p {
  margin: var(--app-space-sm) 0 0;
  color: var(--ion-color-medium);
  font-size: 14px;
}

.section {
  margin-bottom: var(--app-space-xl);
}

/* .settings-title */
.section-title {
  margin: 0 0 8px 12px;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ion-color-medium);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* .glass-card */
.card {
  background: var(--app-card-background);
  border: 1px solid var(--app-border-color);
  border-radius: var(--app-radius-lg);
  box-shadow: var(--app-shadow-md);
  overflow: hidden;
}

.card + .card {
  margin-top: var(--app-space-md);
}

.card-body {
  padding: 16px 20px;
}

.card-body > :first-child {
  margin-top: 0;
}

.card-body > :last-child {
  margin-bottom: 0;
}

.card-body + .card-body {
  border-top: 1px solid var(--tool-hairline);
}

.card-body h3 {
  margin: 0 0 4px;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.card-body p,
.card-body ul {
  margin: 0 0 10px;
}

.card-body ul {
  padding-left: 20px;
}

.card-body li + li {
  margin-top: 6px;
}

.muted {
  color: var(--ion-color-medium);
}

/* Une fiche « données / pourquoi / chez qui » */
/* Au téléphone, l'intitulé passe au-dessus de sa valeur : sur deux colonnes,
   la valeur n'avait plus que la moitié d'un écran déjà étroit */
.facts {
  display: grid;
  grid-template-columns: 1fr;
  margin: 10px 0 0;
  font-size: 14px;
  line-height: 1.5;
}

.facts dt {
  margin-top: 10px;
  color: var(--ion-color-medium);
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.facts dt:first-child {
  margin-top: 0;
}

.facts dd {
  margin: 2px 0 0;
}

@media (min-width: 560px) {
  .facts {
    grid-template-columns: 110px 1fr;
    gap: 6px 14px;
  }

  .facts dt {
    margin-top: 0;
    padding-top: 2px;
  }

  .facts dd {
    margin: 0;
  }
}

/* ==========================================================================
   RANGÉES — .ob-row / .settings-item
   ========================================================================== */

.row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 58px;
  padding: 10px 16px;
  color: inherit;
  text-decoration: none;
}

.row + .row {
  border-top: 1px solid var(--tool-hairline);
}

a.row {
  transition: background-color var(--app-transition-fast);
}

a.row:hover {
  background: var(--tool-fill);
}

.row-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}

.row-title {
  line-height: 1.35;
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.row-hint {
  font-size: 13px;
  line-height: 1.45;
  color: var(--ion-color-medium);
}

.chevron {
  font-size: 13px;
  color: var(--ion-color-medium);
}

/* .ob-icon / .settings-icon */
.tile {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  border-radius: var(--app-radius-xs);
  font-size: 16px;
  color: var(--ion-color-medium);
  background-color: var(--tool-fill);
}

.tile.primary {
  color: var(--text-primary);
  background-color: rgba(var(--ion-color-primary-rgb), 0.14);
}

/* Les chiffres et icônes des tuiles prennent la teinte de texte du thème : en
   clair, le bleu de l'app sur son voile ne tenait que 2,7:1 sous un chiffre */
.tile.secondary {
  color: var(--text-secondary);
  background-color: rgba(var(--ion-color-secondary-rgb), 0.14);
}

.tile.tertiary {
  color: var(--ion-color-tertiary);
  background-color: rgba(var(--ion-color-tertiary-rgb), 0.14);
}

.tile.success {
  color: var(--text-success);
  background-color: rgba(var(--ion-color-success-rgb), 0.14);
}

.tile.warning {
  color: var(--text-warning);
  background-color: rgba(var(--ion-color-warning-rgb), 0.14);
}

.tile.danger {
  color: var(--ion-color-danger);
  background-color: rgba(var(--ion-color-danger-rgb), 0.14);
}

.tile.step {
  font-size: 15px;
  font-weight: 800;
}

/* ==========================================================================
   BOUTON — ion-button.button-solid
   ========================================================================== */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 50px;
  padding: 0 26px;
  border-radius: var(--app-radius-md);
  background: var(--ion-color-primary);
  box-shadow: 0 5px 12px rgba(var(--ion-color-primary-rgb), 0.22);
  color: #ffffff;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.02em;
  text-decoration: none;
  transition:
    transform var(--app-transition-fast),
    background-color var(--app-transition-fast);
}

/* Le survol ne change que la couleur. `hover: hover` : un téléphone garderait
   l'état survolé après l'appui */
@media (hover: hover) {
  .button:hover {
    background: var(--ion-color-primary-shade);
  }

  .lang:hover {
    border-color: rgba(var(--ion-text-color-rgb), 0.24);
    /* Un voile sur la couleur de la carte : seul, ce fond assombrissait le
       bouton en sombre au lieu de l'éclairer */
    background-image: linear-gradient(
      rgba(var(--ion-text-color-rgb), 0.08),
      rgba(var(--ion-text-color-rgb), 0.08)
    );
  }
}

.button:active {
  transform: scale(0.98);
}

.button-note {
  margin: 10px 0 0;
  font-size: 13px;
  color: var(--ion-color-medium);
}

/* ==========================================================================
   ACCUEIL — .ob-brand, élargi pour l'ordinateur
   ========================================================================== */

.home {
  max-width: 1040px;
}

.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--app-space-sm);
  padding: 24px 0 8px;
  text-align: center;
}

.hero-mark {
  width: 80px;
  height: 80px;
  margin-bottom: var(--app-space-xs);
  border-radius: var(--app-radius-md);
  border: 1px solid var(--app-border-color);
  box-shadow: var(--app-shadow-md);
}

.hero h1 {
  margin: 0;
  font-size: 44px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.05em;
}

.tagline {
  max-width: 30ch;
  margin: 4px 0 20px;
  font-size: 17px;
  line-height: 1.5;
  color: var(--ion-color-medium);
}

.grid {
  display: grid;
  gap: var(--app-space-md);
  margin-top: 40px;
}

.grid .card + .card {
  margin-top: 0;
}

.grid .section {
  margin-bottom: 0;
}

@media (min-width: 768px) {
  .page {
    padding-top: 48px;
  }

  .hero {
    padding-top: 40px;
  }

  .hero-mark {
    width: 96px;
    height: 96px;
    border-radius: var(--app-radius-lg);
  }

  .hero h1 {
    font-size: 60px;
  }

  .tagline {
    font-size: 19px;
  }

  .grid {
    grid-template-columns: 1fr 1fr;
    gap: var(--app-space-lg);
    margin-top: 56px;
  }

  .grid .span-2 {
    grid-column: 1 / -1;
  }
}

/* ==========================================================================
   TESTEURS — la page du test fermé (fr/testeurs, testers)
   ========================================================================== */

/* Un bouton pleine largeur sous chaque étape : on lit ces pages au téléphone,
   à la salle, et une cible étroite ratée fait abandonner avant la fin. Sur un
   écran large, il garde sa taille : une barre rouge de 640 px criait */
.step-action {
  padding: 0 16px 16px 68px;
}

@media (max-width: 560px) {
  .step-action .button {
    width: 100%;
  }
}

/* L'étape 3 est celle où l'on croit à une panne : Google met quelques minutes
   à publier l'accès, et le Play Store répond « introuvable » d'ici là. Un
   encart orange, au-dessus du bouton, se lit avant d'appuyer et pas après */
.step-notice {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 0 16px 14px 68px;
  padding: 12px 14px;
  border: 1px solid rgba(var(--ion-color-warning-rgb), 0.5);
  border-radius: var(--app-radius-sm);
  background-color: rgba(var(--ion-color-warning-rgb), 0.14);
  font-size: 14px;
  line-height: 1.4;
  color: var(--ion-text-color);
}

.step-notice .icon {
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 1px;
  color: var(--text-warning);
}

.step-notice strong {
  color: var(--text-warning);
}

@media (max-width: 420px) {
  .step-notice {
    margin-left: 16px;
  }
}

/* Le numéro reste à hauteur du titre quand l'explication court sur plusieurs
   lignes ; centré, il flottait au milieu de la carte */
.step-card .row,
.rows-top .row {
  align-items: flex-start;
}

/* Les étapes sont la raison de la page : leur titre se lit comme un titre,
   pas comme une légende de section */
.step-title {
  margin-bottom: 12px;
  font-size: 20px;
  font-weight: 800;
  color: var(--ion-text-color);
  text-transform: none;
  letter-spacing: -0.03em;
}

.page-head .chips {
  flex-wrap: wrap;
  margin-top: 12px;
}

.faq + .faq {
  border-top: 1px solid var(--tool-hairline);
}

.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 52px;
  padding: 12px 16px;
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  cursor: pointer;
  list-style: none;
}

.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary::after {
  content: '+';
  flex: 0 0 auto;
  color: var(--ion-color-medium);
  font-size: 18px;
  font-weight: 500;
}

.faq[open] summary::after {
  content: '−';
}

.faq p {
  margin: 0;
  padding: 0 16px 14px;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ion-color-medium);
}

.faq a {
  color: var(--text-primary);
}

/* Un iPhone ne peut pas rejoindre le test : le script du <head> pose
   .is-ios, et l'avis remplace les étapes. Sans script, les étapes restent */
.ios-only,
.is-ios .android-only {
  display: none;
}

.is-ios .ios-only {
  display: block;
}

.thanks {
  margin: 0 12px;
  text-align: center;
  font-size: 14px;
  color: var(--ion-color-medium);
}

@media (max-width: 420px) {
  .step-action {
    padding-left: 16px;
  }
}

/* ==========================================================================
   FLYER — fr/flyer, flyer : montré sur un téléphone en salle, ou imprimé en A6
   ========================================================================== */

/* Tout tient sur un écran de téléphone sans défiler : on le tend à quelqu'un
   pour qu'il scanne, il n'a rien à chercher */
.flyer {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(8px, 1.6svh, 16px);
  max-width: 420px;
  min-height: 100svh;
  margin: 0 auto;
  padding: 20px 16px;
  text-align: center;
}

.flyer-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 20px;
  font-weight: 800;
  letter-spacing: -0.03em;
}

.flyer-brand img {
  width: 34px;
  height: 34px;
  border-radius: var(--app-radius-2xs);
}

.flyer h1 {
  margin: 0;
  font-size: clamp(32px, 5.4svh, 44px);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.05em;
}

.flyer h1 span {
  display: block;
  color: var(--text-primary);
}

.flyer-lead {
  max-width: 32ch;
  margin: 0;
  font-size: 14px;
  line-height: 1.45;
  color: var(--ion-color-medium);
}

/* Les pastilles du flyer, reprises sur la page des testeurs */
.chips {
  display: flex;
  gap: 6px;
}

.chips span {
  padding: 3px 11px;
  border-radius: var(--app-radius-full);
  background: rgba(var(--ion-color-primary-rgb), 0.14);
  color: var(--text-primary);
  font-size: 13px;
  font-weight: 700;
}

/* Le fond d'un QR code reste blanc dans les deux thèmes : un code clair sur
   fond sombre, beaucoup d'appareils photo ne le lisent pas */
.flyer-qr {
  width: min(76vw, 34svh, 300px);
  padding: 8px;
  border-radius: var(--app-radius-md);
  background: #ffffff;
  box-shadow: var(--app-shadow-md);
}

.flyer-qr img {
  display: block;
  width: 100%;
  height: auto;
}

.flyer-scan {
  margin: 0;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.35;
}

.flyer-scan small {
  display: block;
  font-size: 14px;
  font-weight: 400;
  color: var(--ion-color-medium);
}

.flyer-scan strong {
  color: var(--ion-text-color);
}

.flyer-steps {
  display: flex;
  gap: 10px;
  width: 100%;
  margin: 0;
  padding: 12px 0 0;
  border-top: 1px solid var(--tool-hairline);
  list-style: none;
  font-size: 13px;
  line-height: 1.3;
  text-align: left;
}

.flyer-steps li {
  display: flex;
  flex: 1;
  gap: 6px;
}

.flyer-steps b {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: var(--app-radius-2xs);
  background: rgba(var(--ion-color-primary-rgb), 0.14);
  color: var(--text-primary);
  font-size: 12px;
}

/* Une cible de 44 px, dont les marges négatives rendent la hauteur : sans
   elles, le flyer ne tenait plus sur un écran de 640 px */
.flyer-lang {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin: -10px 0;
  padding: 0 12px;
  font-size: 12.5px;
  color: var(--ion-color-medium);
}

/* Imprimé : une page A6 sans le halo ni le lien de langue. Le PDF à
   distribuer (store/testeurs/flyer.pdf) est tiré de cette page par Chrome */
@media print {
  @page {
    size: 105mm 148mm;
    margin: 0;
  }

  body::before,
  body::after,
  .flyer-lang {
    display: none;
  }

  body {
    background: none;
  }

  /* Rangé depuis le haut, avec 10 mm en bas : centré, le contenu débordait
     de 3 mm sur la marge du bas, là où une imprimante de bureau n'imprime pas */
  .flyer {
    justify-content: flex-start;
    width: 105mm;
    height: 148mm;
    min-height: 0;
    padding: 9mm 9mm 10mm;
    gap: 2.4mm;
  }

  .flyer h1 {
    font-size: 32px;
  }

  .flyer-qr {
    width: 46mm;
    box-shadow: none;
    border: 1px solid var(--tool-hairline);
  }

  /* Le papier se lit de près : les tailles de l'écran, faites pour un
     téléphone tendu à bout de bras, ne tenaient pas dans l'A6 */
  .flyer-lead {
    font-size: 13px;
  }

  .flyer-scan {
    font-size: 15px;
  }

  .flyer-scan small {
    font-size: 12.5px;
  }

  .flyer-steps {
    font-size: 12px;
  }

  /* Les voiles des pastilles et des numéros sont des fonds : sans cela,
     Chrome ne les imprime que si « graphiques d'arrière-plan » est coché */
  .chips span,
  .flyer-steps b,
  .flyer-qr {
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
  }

  .flyer-steps {
    margin-top: auto;
  }
}

/* ==========================================================================
   PIED DE PAGE
   ========================================================================== */

.footer {
  border-top: 1px solid var(--tool-hairline);
}

.footer-inner {
  max-width: 1040px;
  margin: 0 auto;
  padding: 24px 16px calc(32px + env(safe-area-inset-bottom, 0px));
  color: var(--ion-color-medium);
  font-size: 13px;
}

.footer nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0 20px;
  margin-bottom: 12px;
}

/* Une cible de doigt entière : 21 px de haut, séparés de 10, se touchaient l'un pour l'autre */
.footer nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--ion-text-color);
  font-weight: 500;
  text-decoration: none;
}

.footer nav a:hover {
  color: var(--text-primary);
}

.footer p {
  margin: 0;
}
