/*
 * Le site de Numerology, dans la langue d'exe.cute : le dépôt « exe.cute
 * website », v3/css/tokens.css et docs/v3-direction.md. Encre et os, un seul
 * bleu qui sert de ponctuation (un point, une pastille) et presque jamais de
 * surface ; trois familles aux rôles stricts — Hanken Grotesk pour le texte,
 * Instrument Serif en italique pour un seul fragment par bloc, DM Mono pour
 * la couche « instrument » (sur-titre, navigation, pied, méta). Une seule
 * langue de survol : le cadre pointillé de 1 px. Le texte est calé sur la
 * gouttière gauche, avec beaucoup d'air ; aucune image inventée.
 *
 * Un seul thème, le sombre d'exe.cute, repris à l'identique : exe.cute n'en
 * a pas d'autre (tokens.css et v3-direction.md, question ouverte 4). Un thème
 * clair serait une décision de marque, à prendre pour exe-cute.me et pour ce
 * site ensemble. Le violet de l'app ne vit plus que dans son icône.
 *
 * Chaque paire texte / fond est mesurée par `npm test` et `npm run check`
 * (verifierContrastes, scripts/lib/verifications.mjs) ; le ratio de chacune
 * est écrit à côté de sa couleur. Un jeton posé sous du texte s'ajoute à
 * PAIRES. Les jetons de PAIRES s'écrivent en hex littéral, sous un nom sans
 * chiffre, dans l'unique bloc « :root » ; aucune règle prefers-color-scheme :
 * un second thème échapperait au contrôle. Tout autre réglage racine se pose
 * sur html.
 *
 * Aucune ressource externe et aucun script : les polices (licence OFL,
 * assets/polices) sont servies avec le site, et tout ce qui bouge est en CSS.
 * L'état de base est toujours l'état final, visible : seules les keyframes
 * cachent, dans leur `from`. Réduire les animations les coupe toutes.
 *
 * Ordre : polices, jetons, base, en-tête et pied, contenu, composants,
 * accueil, assistance, projet et marqueurs, mouvement, contraste forcé,
 * impression.
 */

/* ——— Polices : sous-ensembles latin et latin-ext, @fontsource 5.3.0 ———
   Une page en français ne charge que les fichiers latin. Instrument Serif
   n'est chargée que là où un <em> la demande. */

@font-face {
  font-family: "Hanken Grotesk";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("polices/hanken-grotesk-latin-ext-300-normal.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Hanken Grotesk";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("polices/hanken-grotesk-latin-300-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Hanken Grotesk";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("polices/hanken-grotesk-latin-ext-400-normal.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Hanken Grotesk";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("polices/hanken-grotesk-latin-400-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Hanken Grotesk";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("polices/hanken-grotesk-latin-ext-500-normal.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Hanken Grotesk";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("polices/hanken-grotesk-latin-500-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Instrument Serif";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("polices/instrument-serif-latin-ext-400-italic.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Instrument Serif";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("polices/instrument-serif-latin-400-italic.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "DM Mono";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("polices/dm-mono-latin-ext-300-normal.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "DM Mono";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("polices/dm-mono-latin-300-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "DM Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("polices/dm-mono-latin-ext-400-normal.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "DM Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("polices/dm-mono-latin-400-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ——— Jetons ———
   Ceux d'exe.cute (v3/css/tokens.css). Ratios WCAG, sur --fond puis sur
   --surface, calculés avec la formule de verifications.mjs. 4,5:1 pour tout
   texte ; 3:1 pour un repère graphique (pastille, cadre de survol). */

:root {
  --fond: #0B0B0D;            /* l'encre */
  --surface: #101013;         /* le « sol relevé » d'exe.cute */
  --texte: #ECEBE6;           /* l'os : 16,47 / 15,91 */
  --texte-discret: #A9A8A5;   /* l'os à 70 %, aplati : 8,27 / 7,99 */
  --lien: #5778F3;            /* l'accent lisible en petit : 5,04 / 4,87 */
  --accent: #3D64F5;          /* 4,06 / 3,93 : grand texte et décor seulement */
  --bordure: #262627;         /* l'os à 12 % : filets seulement, jamais de texte */
  --cadre-survol: #70706F;    /* l'os à 45 % : 3,97 / 3,83 (3:1 exigé) */
  --bouton-fond: #3455D0;     /* l'accent profond d'exe.cute */
  --bouton-texte: #ECEBE6;    /* 5,24 sur --bouton-fond */
  --selection-fond: #3455D0;
  --selection-texte: #ECEBE6; /* 5,24 sur --selection-fond */
  --attention-texte: #FCD34D; /* 10,77 sur --attention-fond : le brouillon seulement */
  --attention-fond: #2B2312;
  --attention-bord: #FCD34D;
  --marqueur-fond: #4A3A12;   /* --texte dessus : 9,23 */
  /* Le champ de l'accueil : l'encre et le bleu profond du shader « soie »
     d'exe.cute (js/gl/field.js). Décor seul, jamais sous du texte. */
  --champ-encre: #0B0B0D;
  --champ-profond: #171F61;
  /* La plaque de verre de l'en-tête collant, celle d'exe.cute (chrome.css),
     hors du contrôle des paires : verifierPlaque la mesure à part, voir
     .entete::before. */
  --plaque: rgba(11, 11, 13, 0.82);
  /* La seule ombre d'exe.cute, la lueur de la pastille. */
  --lueur: 0 0 12px rgba(61, 100, 245, 0.8);

  --sans: "Hanken Grotesk", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --serif: "Instrument Serif", "Times New Roman", Georgia, serif;
  --mono: "DM Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  --gouttiere: clamp(20px, 4.5vw, 72px);
  --barre: clamp(56px, 7vh, 84px);
  --cadre: 90rem;             /* largeur maximale de la page, gouttières comprises */
  --mesure: 40rem;            /* 70 à 75 signes à 17 px */
  --section: clamp(3.5rem, 2rem + 6vh, 7.5rem);
  --interieur-carte: clamp(1.25rem, 1rem + 1vw, 2rem);
  --rayon: 0;

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-std: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-quart: cubic-bezier(0.165, 0.84, 0.44, 1);
  --ease-cubic: cubic-bezier(0.215, 0.61, 0.355, 1);
}

/* ——— Base ——— */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  color-scheme: dark;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  font-synthesis: none;
  background: var(--fond);
}

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--fond);
  color: var(--texte);
  font-family: var(--sans);
  font-weight: 400;
  font-size: 1.0625rem; /* 17 px, le corps de texte d'iOS : la lecture longue des pages légales */
  line-height: 1.6;
  overflow-wrap: break-word;
  hyphens: auto;
  text-rendering: optimizeLegibility;
}

::selection {
  background: var(--selection-fond);
  color: var(--selection-texte);
}

img,
svg {
  display: block;
  max-width: 100%;
}

/* Les liens de la prose restent soulignés (WCAG 1.4.1) : la couleur seule
   ne suffit pas à les distinguer du texte. */
a {
  color: var(--lien);
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

a:hover {
  text-decoration-thickness: 2px;
}

/* Le focus en --texte : 16,47:1 sur --fond. */
:focus-visible {
  outline: 2px solid var(--texte);
  outline-offset: 4px;
}

main:focus {
  outline: none;
}

h1,
h2,
h3 {
  hyphens: manual;
  text-wrap: balance;
}

h1 {
  font-weight: 300;
  font-size: clamp(2.25rem, 1.5rem + 3vw, 3.5rem);
  line-height: 1.05;
  letter-spacing: -0.03em;
  margin: 0.5rem 0 1.25rem;
}

h2 {
  font-weight: 300;
  font-size: clamp(1.5rem, 1.25rem + 1vw, 2rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 3rem 0 0.75rem;
}

h3 {
  font-weight: 500;
  font-size: 1.125rem;
  line-height: 1.4;
  margin: 2rem 0 0.375rem;
}

/* Le fragment mis en relief : Instrument Serif en italique, un par bloc. */
em {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
}

h1 em,
h2 em,
h3 em {
  font-size: 1.06em;
  letter-spacing: -0.02em;
}

strong {
  font-weight: 500;
}

p,
ul,
ol,
dl {
  margin: 0.875rem 0;
}

p,
li,
dd {
  text-wrap: pretty;
}

ul,
ol {
  padding-left: 1.25rem;
}

li + li {
  margin-top: 0.375rem;
}

/* La couche « instrument » : DM Mono, 13 px au moins (exe.cute descend à
   11,84 px). Jamais de minuscules forcées sur une phrase : elle porte iPhone
   ou EXE.CUTE, et les minuscules voulues s'écrivent dans la source. */
.instrument,
.surtitre,
.mise-a-jour {
  font-family: var(--mono);
  font-weight: 400;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  color: var(--texte-discret);
  hyphens: manual;
}

.evitement {
  position: absolute;
  left: var(--gouttiere);
  top: -4rem;
  z-index: 60; /* au-dessus de l'en-tête collant */
  padding: 0.625rem 1rem;
  background: var(--texte);
  color: var(--fond);
  font-family: var(--mono);
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-decoration: none;
}

.evitement:focus {
  top: 0.75rem;
}

/* Le cadre pointillé : la seule langue de survol d'exe.cute (base.css,
   .frame), pour ce qui n'est pas de la prose — la marque, la navigation, le
   pied, le bouton. Au survol, un pointillé de 1 px ; au clavier, un trait
   plein de 2 px en --texte, qui tient 16,47:1 et ne se confond pas avec lui. */
.cadre {
  position: relative;
  text-decoration: none;
}

.cadre::before {
  content: "";
  position: absolute;
  inset: -0.5em -0.6em;
  border: 1px dotted transparent;
  pointer-events: none;
  transition: border-color 0.2s var(--ease-std);
}

@media (hover: hover) and (min-width: 1024px) {
  .cadre:hover::before {
    border-color: var(--cadre-survol);
  }
}

.cadre:focus-visible {
  outline: none;
}

.cadre:focus-visible::before {
  border: 2px solid var(--texte);
}

/* La flèche d'un lien qui quitte le site : dessinée, parce que ↗ n'est ni
   dans le sous-ensemble latin ni dans latin-ext. */
.fleche {
  display: inline-block;
  flex: none;
  width: 0.75em;
  height: 0.75em;
  transition: transform 0.5s var(--ease-out);
}

a:hover .fleche {
  transform: translateX(4px);
}

/* ——— En-tête ———
   Une seule barre : la marque à gauche, la navigation à droite. Collante à
   partir de 48rem, sous une plaque de verre ; en dessous, dans le flux, et la
   navigation passe sous la marque. */

.entete {
  position: relative;
  border-bottom: 1px solid var(--bordure);
}

.entete-interieur {
  max-width: var(--cadre);
  margin: 0 auto;
  min-height: var(--barre);
  padding: 0.5rem var(--gouttiere);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 0.25rem 2rem;
}

/* La signature de l'app : l'icône, « Numerology », et dessous, dans la couche
   instrument, « par exe.cute ». Le nom accessible se lit tel quel. Pas de
   point bleu : comme le logotype de l'en-tête d'exe.cute, la signature n'a
   qu'une couleur. Un point en --lien passait sous 4,5:1 au-dessus de l'icône
   de l'app, qui défile sous la plaque sur l'accueil (4,49 sur son violet,
   3,46 sur ses traits clairs) ; le bleu reste au titre, en grand. */
.marque {
  display: inline-grid;
  grid-template-columns: auto auto;
  align-content: center;
  align-items: center;
  column-gap: 0.75rem;
  min-height: 2.75rem;
  color: var(--texte);
}

/* La cible fait déjà 44 px : le cadre la serre en hauteur, pour ne jamais
   toucher le haut de la fenêtre quand la barre est basse. */
.marque::before {
  inset: -0.25rem -0.6em;
}

.marque img {
  grid-row: 1 / span 2;
  width: 2rem;
  height: 2rem;
}

.marque-nom {
  align-self: end;
  font-weight: 500;
  font-size: 1.125rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.marque-par {
  align-self: start;
  font-family: var(--mono);
  font-size: 0.8125rem;
  line-height: 1.35;
  letter-spacing: 0.04em;
  color: var(--texte-discret);
}

.navigation ul,
.pied-navigation ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0 1.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.navigation li + li,
.pied-navigation li + li {
  margin-top: 0;
}

/* À 375 px (iPhone SE, iPhone mini), la colonne fait 335 px : les trois liens
   de l'en-tête en font 291, et deux écarts de 1,5rem les portaient à 339 —
   « conditions » passait seul à la ligne. À 1,25rem, 331 : une ligne. */
@media (max-width: 24rem) {
  .navigation ul {
    column-gap: 1.25rem;
  }
}

/* Une cible de 44 px de haut ; le cadre, lui, entoure le mot. */
.navigation a,
.pied-navigation a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  font-family: var(--mono);
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-transform: lowercase; /* aucun nom propre dans ces liens */
  color: var(--texte-discret);
  text-decoration: none;
  transition: color 0.4s var(--ease-out);
}

.navigation a::before,
.pied-navigation a::before,
.pied-logo::before {
  inset: 0.45rem -0.6em;
}

.navigation a:hover,
.navigation a:focus-visible,
.navigation a[aria-current="page"],
.pied-navigation a:hover,
.pied-navigation a:focus-visible,
.pied-navigation a[aria-current="page"] {
  color: var(--texte);
}

/* La page courante : la couleur, et une pastille, pour que la forme double
   la couleur. */
.navigation a[aria-current="page"]::after,
.pied-navigation a[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: -0.85rem;
  top: 50%;
  width: 5px;
  height: 5px;
  margin-top: -2.5px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: var(--lueur);
}

@media (min-width: 48rem) {
  html {
    /* Ni une ancre (#premium, #contact…) ni un focus ne passent sous
       l'en-tête collant (WCAG 2.4.11). */
    scroll-padding-top: calc(var(--barre) + 1rem);
  }

  .entete {
    position: sticky;
    top: 0;
    z-index: 50;
  }

  /* La plaque vit sur sa propre couche : un voile de --plaque et le flou
     d'arrière-plan d'exe.cute (chrome.css). Pire cas mesuré, les traits
     clairs de l'icône de l'app, qui défile dessous sur l'accueil :
     --texte-discret y tient 5,12. */
  .entete::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: var(--plaque);
    -webkit-backdrop-filter: blur(16px) saturate(1.35);
    backdrop-filter: blur(16px) saturate(1.35);
  }

  .entete-interieur {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
  }
}

/* Sans flou d'arrière-plan, ou quand on demande moins de transparence, la
   plaque devient opaque. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .entete::before {
    background: var(--fond);
  }
}

@media (prefers-reduced-transparency: reduce) {
  .entete::before {
    background: var(--fond);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* ——— Pied ———
   La rangée d'exe.cute, « marque · devise · © » : le logotype et la phrase
   de l'éditeur, les liens d'information, puis le ©. */

.pied {
  margin-top: auto;
  border-top: 1px solid var(--bordure);
  font-family: var(--mono);
  font-size: 0.8125rem;
  line-height: 1.6;
  letter-spacing: 0.04em;
  color: var(--texte-discret);
  hyphens: manual;
}

.pied-interieur {
  max-width: var(--cadre);
  margin: 0 auto;
  padding: clamp(40px, 8vh, 96px) var(--gouttiere) clamp(24px, 4vh, 48px);
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.5rem 3rem;
}

.pied p {
  margin: 0;
}

.pied-signature {
  flex: 1 1 22rem;
  display: grid;
  justify-items: start;
  gap: 0.5rem;
}

.pied-navigation {
  flex: 0 1 auto;
}

.pied-copyright {
  flex: 1 1 100%;
}

/* Le logotype d'exe.cute, 18 px de haut, comme dans son propre pied. */
.pied-logo {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.75rem;
  color: var(--texte-discret);
}

.pied-logo img {
  width: auto;
  height: 18px;
  opacity: 0.85;
  transition: opacity 0.4s var(--ease-out);
}

a.pied-logo:hover img {
  opacity: 1;
}

/* ——— Contenu ———
   Le cadre de la page, gouttières comprises ; le texte se cale sur la
   gouttière gauche, à la mesure de lecture. */

.contenu {
  width: 100%;
  max-width: var(--cadre);
  margin: 0 auto;
  padding: clamp(2rem, 4vh, 4rem) var(--gouttiere) clamp(4rem, 10vh, 8rem);
}

.contenu-texte > * {
  max-width: var(--mesure);
}

.contenu-texte > .tableau,
.contenu-texte > .en-bref,
.contenu-texte > .contact {
  max-width: 56rem;
}

.chapeau {
  font-weight: 300;
  font-size: clamp(1.1875rem, 1.05rem + 0.6vw, 1.375rem);
  line-height: 1.5;
  color: var(--texte-discret);
}

.mise-a-jour {
  margin: 0 0 1.5rem;
}

.discret {
  font-size: 0.9375rem;
  color: var(--texte-discret);
}

/* Un chemin dans l'app : Réglages › Aide › … Il peut passer à la ligne —
   un chemin long ne doit jamais élargir la page sur un téléphone. */
.chemin {
  font-weight: 500;
}

/* ——— Composants ——— */

.carte {
  background: var(--surface);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  padding: var(--interieur-carte);
}

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

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

.en-bref {
  margin: 1.5rem 0 2.5rem;
}

.en-bref h2 {
  margin-top: 0;
}

.bouton {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  min-height: 2.75rem;
  padding: 0.75rem 1.25rem;
  background: var(--bouton-fond);
  color: var(--bouton-texte);
  font-weight: 500;
  font-size: 1rem;
  line-height: 1.25;
}

.bouton.cadre::before {
  inset: -0.375rem;
}

/* La coche devient la pastille d'exe.cute. */
.liste-coche {
  list-style: none;
  padding: 0;
}

.liste-coche li {
  position: relative;
  padding-left: 1.25rem;
}

.liste-coche li + li {
  margin-top: 0.875rem;
}

.liste-coche li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.7em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
}

.liste-coche span {
  display: block;
  color: var(--texte-discret);
  font-size: 0.9375rem;
}

/* Les tableaux défilent dans leur cadre, jamais la page. Le cadre se prend
   au clavier (tabindex="0" dans la page) : les flèches font alors défiler
   les colonnes de droite. */
.tableau {
  overflow-x: auto;
  margin: 1.25rem 0;
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  background: var(--surface);
}

table {
  width: 100%;
  min-width: 34rem;
  margin: 0;
  border-collapse: collapse;
  font-size: 0.9375rem;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
}

th,
td {
  padding: 0.75rem 0.875rem;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--bordure);
}

/* Le dernier rang du corps seulement : la rangée d'en-tête garde son filet. */
tbody tr:last-child > * {
  border-bottom: none;
}

th {
  font-family: var(--mono);
  font-weight: 400;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  color: var(--texte-discret);
  hyphens: manual;
}

dl.coordonnees {
  display: grid;
  grid-template-columns: minmax(9rem, max-content) 1fr;
  align-items: baseline;
  gap: 0.5rem 1.5rem;
}

dl.coordonnees dt {
  font-family: var(--mono);
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  color: var(--texte-discret);
  hyphens: manual;
}

dl.coordonnees dd {
  margin: 0;
}

@media (max-width: 34rem) {
  dl.coordonnees {
    grid-template-columns: 1fr;
    gap: 0;
  }

  dl.coordonnees dd {
    margin-bottom: 0.75rem;
  }
}

/* ——— Accueil ———
   La langue d'exe.cute, la voix de Numerology : chaque section porte son
   index dans la couche instrument (« 01 · le calcul »), comme le « 00 · hero »
   du studio — sauf qu'ici les nombres sont le sujet. Pas de cartes : des
   filets, des colonnes, et beaucoup d'air. */

.index-section {
  margin: 0 0 clamp(1.5rem, 4vh, 2.75rem);
  font-family: var(--mono);
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  color: var(--texte-discret);
  hyphens: manual;
}

.section {
  margin-top: var(--section);
  padding-top: clamp(1.75rem, 4vh, 3rem);
  border-top: 1px solid var(--bordure);
}

/* Un titre de section tient sur une ligne dès que la place le permet : il ne
   se coupe jamais pour laisser de la place à un voisin. */
.section > h2,
.section-tete h2 {
  margin: 0;
  font-size: clamp(2rem, 1.4rem + 2.6vw, 3.75rem);
  line-height: 1.02;
  letter-spacing: -0.03em;
  text-wrap: balance;
}

/* Le titre en haut, puis son paragraphe ; à partir de 64rem, le paragraphe
   passe à droite et s'aligne sur la base du titre. */
.section-tete {
  display: grid;
  gap: 1.25rem clamp(3rem, 8vw, 8rem);
  align-items: end;
}

.section-tete p {
  max-width: 36rem;
  margin: 0;
  color: var(--texte-discret);
}

@media (min-width: 64rem) {
  .section-tete {
    grid-template-columns: max-content minmax(0, 1fr);
  }

  .section-tete p {
    justify-self: end;
  }
}

/* La suite d'une section : un lien à part, après son contenu, jamais coincé
   à côté d'un titre. */
.suite {
  margin: clamp(2rem, 5vh, 3rem) 0 0;
}

.suite a {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  min-height: 2.75rem;
  font-family: var(--mono);
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  color: var(--texte);
}

.suite a::before {
  inset: 0.45rem -0.6em;
}

/* Le héros : une colonne de texte calée à gauche, et l'icône à droite à
   partir de 52rem (dessous, sur un téléphone). */
.accroche {
  display: grid;
  align-items: center;
  gap: clamp(2.5rem, 5vw, 4rem);
  padding-top: clamp(1rem, 4vh, 3.5rem);
}

@media (min-width: 52rem) {
  .accroche {
    grid-template-columns: 1.15fr 0.85fr;
    min-height: min(46rem, calc(100dvh - var(--barre) - 4rem));
    align-content: center;
  }
}

.accroche-texte > p {
  max-width: 34rem;
}

/* Le chapeau dit ce qu'est l'app ; la phrase suivante le précise, un cran
   plus bas : jamais plus forte que lui. */
.accroche .chapeau {
  color: var(--texte);
}

.accroche-texte > .chapeau + p {
  color: var(--texte-discret);
}

/* « Bientôt sur l'App Store » : une étiquette, pas une phrase en gras. */
.disponibilite strong {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0 1.125rem;
  border: 1px solid var(--cadre-survol);
  border-radius: 999px;
  font-weight: 500;
  font-size: 0.9375rem;
}

/* Le sur-titre, précédé de la pastille d'exe.cute (.eyebrow__dot). */
.surtitre {
  margin: 0 0 clamp(1.25rem, 3vh, 2.5rem);
  letter-spacing: 0.14em;
}

.surtitre::before {
  content: "";
  display: inline-block;
  width: 5px;
  height: 5px;
  margin-right: 0.9em;
  border-radius: 50%;
  vertical-align: middle;
  transform: translateY(-1px);
  background: var(--accent);
  box-shadow: var(--lueur);
}

.accroche h1 {
  margin: 0 0 clamp(1.25rem, 3vh, 2rem);
  font-size: max(2.9rem, min(7rem, 12.5vh, 15vw));
  line-height: 0.98;
  letter-spacing: -0.035em;
}

@media (min-width: 52rem) {
  .accroche h1 {
    /* Dans sa colonne de 1,15fr, le mot doit tenir sur une ligne. */
    font-size: max(2.9rem, min(7rem, 12.5vh, 8vw));
  }
}

/* La boîte de ligne d'exe.cute (.line) : la ligne monte dedans à l'arrivée.
   Le retrait du bas laisse leur place aux jambages du g et du y. */
.ligne {
  display: block;
  overflow: hidden;
  padding: 0.06em 0 0.2em;
  margin: -0.02em 0 -0.14em;
}

.ligne-interieur {
  display: block;
}

/* Le point bleu, la ponctuation devenue la marque d'exe.cute : en grand,
   --accent tient 4,06:1, au-dessus des 3:1 du grand texte. */
.accroche h1 .point {
  display: inline-block;
  color: var(--accent);
  transform-origin: 50% 78%;
}

.disponibilite {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.5rem;
  margin-top: 2rem;
}

.disponibilite p {
  margin: 0;
}

/* Le champ remplace l'orbe : le champ « soie » d'exe.cute, figé, sous sa
   trame de points de 4 px, ouverte autour de l'icône. Décor seul
   (aria-hidden) ; la trame ne passe jamais sous du texte. */
@property --ouverture {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 34%;
}

/* Un disque, pas un carré : le champ s'éteint dans le fond par ses bords, et
   la page n'a plus aucune arête qu'elle n'a pas voulue. */
.champ {
  --cellule: 4px;
  position: relative;
  display: grid;
  place-items: center;
  justify-self: center;
  width: min(100%, 16rem);
  aspect-ratio: 1;
  overflow: hidden;
  isolation: isolate;
  border-radius: 50%;
  background: var(--champ-encre);
  -webkit-mask-image: radial-gradient(closest-side, #000 62%, transparent 100%);
  mask-image: radial-gradient(closest-side, #000 62%, transparent 100%);
}

@media (min-width: 52rem) {
  .champ {
    justify-self: end;
    width: min(100%, 30rem);
  }
}

/* Sous 1,5 dppx, une cellule de 6 px : la trame de 4 px y fait du moiré. */
@media (max-resolution: 1.49dppx) {
  .champ {
    --cellule: 6px;
  }
}

.champ::before {
  content: "";
  position: absolute;
  inset: -20%;
  z-index: -2;
  background:
    radial-gradient(40% 50% at 30% 40%, rgba(61, 100, 245, 0.35), transparent 70%),
    radial-gradient(28% 34% at 34% 42%, rgba(79, 107, 255, 0.4), transparent 70%),
    radial-gradient(35% 45% at 70% 65%, rgba(236, 235, 230, 0.12), transparent 70%),
    radial-gradient(70% 70% at 45% 50%, var(--champ-profond), transparent 75%),
    var(--champ-encre);
  filter: blur(40px);
}

.champ::after {
  --ouverture: 34%;
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    radial-gradient(circle, var(--champ-encre) 45%, transparent 46%),
    radial-gradient(circle, var(--champ-encre) 25%, transparent 26%);
  background-size: var(--cellule) var(--cellule);
  background-position: 0 0, calc(var(--cellule) / 2) calc(var(--cellule) / 2);
  -webkit-mask-image: radial-gradient(circle at 50% 50%, transparent var(--ouverture), #000 calc(var(--ouverture) + 18%));
  mask-image: radial-gradient(circle at 50% 50%, transparent var(--ouverture), #000 calc(var(--ouverture) + 18%));
}

/* L'icône comme sur l'écran d'accueil d'un iPhone : posée, avec une ombre
   teintée de son violet. Le SVG porte déjà ses coins arrondis. */
.champ img {
  width: 40%;
  height: auto;
  filter: drop-shadow(0 18px 40px rgba(23, 31, 97, 0.9));
}

/* La table pythagoricienne : la signature de Numerology, là où exe.cute a
   son mot en verre. Neuf colonnes, les chiffres en tête dans le grand corps
   léger du titre, les lettres dans la couche instrument. Des filets d'un
   point entre les cases, rien d'autre. */
.grille-tableau {
  --case: clamp(2rem, 7.4vw, 6.5rem);
  display: grid;
  grid-template-columns: repeat(9, minmax(0, 1fr));
  margin-top: clamp(2.5rem, 6vh, 4.5rem);
  border-top: 1px solid var(--bordure);
  border-left: 1px solid var(--bordure);
  font-family: var(--mono);
  font-size: clamp(0.8125rem, 0.6rem + 0.8vw, 1.125rem);
  letter-spacing: 0.04em;
  color: var(--texte-discret);
}

/* En flex, pas en grille : le point du 9 reste sur sa ligne. */
.grille-tableau > span {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: calc(var(--case) * 0.62);
  border-right: 1px solid var(--bordure);
  border-bottom: 1px solid var(--bordure);
  transition: color 0.4s var(--ease-out), background-color 0.4s var(--ease-out);
}

.grille-tableau > .grille-chiffre {
  min-height: var(--case);
  font-family: var(--sans);
  font-weight: 300;
  font-size: clamp(1.5rem, 0.6rem + 3.6vw, 4.5rem);
  letter-spacing: -0.03em;
  color: var(--texte);
}

/* Le 9 ferme la table : il porte le point bleu d'exe.cute, en grand. */
.grille-tableau > .grille-chiffre:nth-child(9)::after {
  content: ".";
  color: var(--accent);
}

@media (hover: hover) and (min-width: 1024px) {
  .grille-tableau > span:not(.grille-chiffre, .grille-vide):hover {
    color: var(--texte);
    background-color: var(--surface);
  }
}

/* Sur un téléphone, neuf colonnes font 38 px : des cases plus hautes, pour
   que la table se lise et se touche comme une grille, pas comme une ligne. */
@media (max-width: 40rem) {
  .grille-tableau > span {
    min-height: 2.5rem;
  }

  .grille-tableau > .grille-chiffre {
    min-height: 3.25rem;
  }
}

/* Deux formules côte à côte, séparées par un filet vertical. */
.offre {
  display: grid;
  gap: 3rem;
  margin-top: clamp(2.5rem, 6vh, 4.5rem);
}

@media (min-width: 52rem) {
  .offre {
    grid-template-columns: 1fr 1fr;
    gap: 0;
  }

  .formule + .formule {
    padding-left: clamp(2rem, 5vw, 5rem);
    border-left: 1px solid var(--bordure);
  }

  .formule:first-child {
    padding-right: clamp(2rem, 5vw, 5rem);
  }
}

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

/* Les titres de l'offre et des engagements, sur le modèle des piliers. */
.offre h3,
.engagements h3 {
  margin: 0 0 0.5rem;
  font-weight: 300;
  font-size: clamp(1.625rem, 1.2rem + 1.4vw, 2.25rem);
  line-height: 1.1;
  letter-spacing: -0.025em;
}

.offre h3 {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.offre h3 svg {
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  color: var(--accent);
}

/* Une liste numérotée en DM Mono, « 01 », « 02 »… : le compte d'exe.cute,
   et des nombres, puisque c'est le sujet. */
.liste-index {
  counter-reset: index;
  list-style: none;
  margin: 1.75rem 0;
  padding: 0;
  border-top: 1px solid var(--bordure);
}

.liste-index li {
  counter-increment: index;
  display: grid;
  grid-template-columns: 2.75rem 1fr;
  column-gap: 0.5rem;
  margin: 0;
  padding: 1rem 0;
  border-bottom: 1px solid var(--bordure);
}

.liste-index li::before {
  content: counter(index, decimal-leading-zero);
  grid-row: 1 / span 2;
  padding-top: 0.2em;
  font-family: var(--mono);
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  color: var(--texte-discret);
}

.liste-index strong {
  font-weight: 500;
}

.liste-index span {
  color: var(--texte-discret);
  font-size: 0.9375rem;
}

/* Trois piliers : un filet, et de l'air. */
.engagements {
  display: grid;
  gap: 2.5rem clamp(1.5rem, 4vw, 4rem);
  margin: clamp(2.5rem, 6vh, 4.5rem) 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 46rem) {
  .engagements {
    grid-template-columns: repeat(3, 1fr);
  }
}

.engagements li + li {
  margin-top: 0;
}

.pilier {
  padding-top: 1.25rem;
  border-top: 1px solid var(--texte-discret);
}

.pilier p {
  margin-bottom: 0;
  color: var(--texte-discret);
}

.avertissement > p:last-child {
  max-width: var(--mesure);
  margin-top: 1.5rem;
  font-size: clamp(1.0625rem, 0.95rem + 0.4vw, 1.25rem);
  line-height: 1.6;
  color: var(--texte-discret);
}

/* La clôture : l'adresse en grand, comme celle d'exe.cute (closing__mail),
   centrée sous sa question. */
.cloture {
  display: grid;
  justify-items: center;
  margin-top: var(--section);
  padding: clamp(3rem, 10vh, 7rem) 0 0;
  border-top: 1px solid var(--bordure);
  text-align: center;
}

.cloture .surtitre {
  margin: 0 0 1.5rem;
  font-weight: 400;
  font-size: 0.8125rem;
  line-height: 1.6;
  letter-spacing: 0.14em;
}

.cloture-adresse {
  max-width: 100%;
  font-family: var(--mono);
  font-weight: 300;
  font-size: clamp(1.25rem, 5.2vw, 3.5rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--texte);
  text-decoration: none;
  overflow-wrap: anywhere;
  hyphens: manual;
}

.cloture-adresse:hover {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

.cloture > .discret {
  margin-top: 1.5rem;
}

/* ——— Assistance ——— */

.contact {
  margin: 1.5rem 0 1.25rem;
}

/* L'adresse en grand, comme celle d'exe.cute (closing__mail) : DM Mono 300,
   sur une ligne à elle. La taille suit la largeur du téléphone pour que
   l'adresse tienne sur une ligne dès 320 px ; elle passe à la ligne sinon,
   jamais de défilement horizontal. */
.contact .adresse {
  display: block;
  width: fit-content;
  max-width: 100%;
  margin-top: 0.5rem;
  font-family: var(--mono);
  font-weight: 300;
  font-size: clamp(1.125rem, 6.4vw - 0.3rem, 3rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  overflow-wrap: anywhere;
  hyphens: manual;
}

/* ——— Projet et marqueurs : le brouillon seulement ——— */

.bandeau-projet {
  margin: 0 0 1.5rem;
  padding: 0.875rem 1.125rem;
  border: 1px solid var(--attention-bord);
  border-left-width: 4px;
  border-radius: var(--rayon);
  background: var(--attention-fond);
  color: var(--attention-texte);
}

.bandeau-projet p {
  margin: 0;
}

mark.marqueur {
  padding: 0 0.25em;
  border-radius: var(--rayon);
  outline: 1px dashed var(--attention-bord);
  background: var(--marqueur-fond);
  color: var(--texte);
}

/* ——— Mouvement ———
   L'entrée du héros, sur l'accueil seulement et une fois : les keyframes
   d'exe.cute (hero.css : heroLineIn, heroFade, heroFadeUp, heroDotLand),
   délais resserrés faute de chargeur. Aucune entrée sur les pages de
   lecture, où l'on arrive pour lire. L'état de base est l'état final : une
   animation que le navigateur ne joue pas laisse la page entière. */

@keyframes accroche-ligne {
  from {
    transform: translateY(115%);
  }

  to {
    transform: translateY(0);
  }
}

@keyframes accroche-fondu {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

@keyframes accroche-montee {
  from {
    opacity: 0;
    transform: translateY(14px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Il arrive petit, dépasse de 7 % et se pose. Pas de rebond. */
@keyframes accroche-point {
  0% {
    opacity: 0;
    transform: scale(0.34);
  }

  55% {
    opacity: 1;
    transform: scale(1.07);
  }

  100% {
    opacity: 1;
    transform: scale(1);
  }
}

/* La trame se retire autour de l'icône : l'ouverture d'exe.cute, ici
   jouée une fois. Sans @property, la valeur saute d'un coup, sans dommage. */
@keyframes champ-ouverture {
  from {
    --ouverture: 0%;
  }

  to {
    --ouverture: 34%;
  }
}

.surtitre::before {
  animation: accroche-fondu 420ms var(--ease-cubic) both;
}

.accroche .ligne-interieur {
  animation: accroche-ligne 1500ms var(--ease-quart) 80ms both;
}

.accroche-texte > p:not(.surtitre) {
  animation: accroche-montee 1100ms var(--ease-cubic) 400ms both;
}

.disponibilite {
  animation: accroche-fondu 900ms var(--ease-cubic) 600ms both;
}

.accroche h1 .point {
  animation: accroche-point 440ms var(--ease-cubic) 1100ms both;
}

.champ::after {
  animation: champ-ouverture 900ms var(--ease-out) 200ms both;
}

/* Un fondu enchaîné d'une page à l'autre : même origine, aucune requête. */
@view-transition {
  navigation: auto;
}

@media (prefers-reduced-motion: reduce) {
  @view-transition {
    navigation: none;
  }

  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }

  a:hover .fleche {
    transform: none;
  }
}

/* ——— Contraste forcé (Windows) ———
   Le champ et sa trame sont du décor : ils sortent, et la page revient au
   texte sur le fond du système (exe.cute, base.css). */

@media (forced-colors: active) {
  .champ {
    background: Canvas;
  }

  .champ::before,
  .champ::after {
    display: none;
  }

  .entete::before {
    background: Canvas;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  .cadre:hover::before {
    border-color: CanvasText;
  }

  .cadre:focus-visible::before {
    border-color: Highlight;
  }

  :focus-visible {
    outline-color: Highlight;
  }

  ::selection {
    background: Highlight;
    color: HighlightText;
  }

  .surtitre::before,
  .liste-coche li::before,
  .navigation a[aria-current="page"]::after,
  .pied-navigation a[aria-current="page"]::after {
    forced-color-adjust: none;
    background: CanvasText;
    box-shadow: none;
  }

  .bouton {
    border: 1px solid LinkText;
  }
}

/* ——— Impression : les pages légales se lisent aussi sur papier ——— */

@media print {
  body {
    --fond: #FFFFFF;
    --surface: #FFFFFF;
    --texte: #000000;
    --texte-discret: #333333;
    --lien: #000000;
    --accent: #000000;
    --bordure: #999999;
    --lueur: none;
    background: #FFFFFF;
    color: #000000;
  }

  .entete {
    position: static;
  }

  .entete::before,
  .navigation,
  .evitement,
  .pied-navigation,
  .champ {
    display: none;
  }

  .accroche {
    grid-template-columns: 1fr;
  }

  .carte,
  .tableau {
    background: none;
  }

  /* Le logotype blanc d'exe.cute, en noir sur le papier. */
  .pied-logo img {
    filter: invert(1);
    opacity: 1;
  }
}
