/* Eyland — feuille de style du hub. Direction artistique « L'île ».
 *
 * SIX RÈGLES. Tout le reste en découle, et rien ne doit les contredire.
 *
 * 1. UNE SEULE PRIMITIVE GÉOMÉTRIQUE : l'arc du logo, à toutes les échelles.
 *    L'horizon, les séparateurs de section et le filet lumineux sur l'arête
 *    haute des blocs sont le même signe, agrandi ou réduit.
 *
 * 2. UNE SEULE SOURCE DE LUMIÈRE : le disque. Tout ce qui s'éclaire s'éclaire
 *    depuis lui, et depuis le même côté. C'est cette cohérence qui fabrique la
 *    profondeur — pas les ombres portées, qu'on n'emploie nulle part.
 *
 * 3. LE CIEL EST TRAMÉ, PAS FLOUTÉ. Tramage ordonné sur une palette choisie à
 *    la main, plus un bruit haché qui casse les frontières. C'est la signature
 *    de la marque, et c'est ce qu'aucun générateur ne produit. Ne jamais poser
 *    de backdrop-filter par-dessus : un flou écrase le grain et il ne reste
 *    qu'un dégradé de plus.
 *
 * 4. UNE SEULE TEINTE DE CIEL, UNE SEULE LUMIÈRE CHAUDE. Le violet, le
 *    turquoise et l'orange à poids égal, c'était LA signature du gabarit
 *    générique. Les couleurs des apps n'apparaissent que sur leur propre bloc.
 *
 * 5. CIEL EN HAUT, TERRE EN BAS. Sous l'arc, tout est opaque et mat : le
 *    contenu est POSÉ sur l'île. Aucune surface en verre, aucune transparence
 *    sur le contenu.
 *
 * 6. LES ÉTOILES TOURNENT AUTOUR D'UN PÔLE, comme un vrai ciel. Pas de
 *    scintillement aléatoire.
 *
 * SEULE ENTORSE ASSUMÉE : le halo qui suit le curseur est une deuxième source
 * de lumière, ce qui contredit la règle 2. Il est teinté chaud et gardé très
 * faible pour se lire comme une lampe qu'on promène, pas comme un second
 * soleil. C'est un choix, pas un oubli.
 *
 * PERF : aucune animation ne touche autre chose que transform ou opacity.
 * Le ciel est peint UNE fois dans un canvas puis seulement translaté, ce qui
 * coûte zéro repaint par frame.
 */

/* ------------------------------------------------------------------ polices */

/* Auto-hébergées, sous-ensemble latin, licence OFL. Aucune requête vers un
 * tiers : la page de confidentialité promet qu'il n'y en a aucune, et une
 * feuille Google Fonts en CDN la rendrait fausse. 167 Ko au total. */

@font-face {
  font-family: "Fraunces";
  src: url("/fonts/fraunces-var.woff2") format("woff2");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Instrument Sans";
  src: url("/fonts/instrument-sans-var.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
/* Une seule graisse de mono : aucun élément n'emploie le 500, et le charger
   coûtait 10 Ko pour rien. Ne pas rajouter la seconde « par symétrie » sans
   avoir d'abord un élément qui la demande. */
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/ibm-plex-mono-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ------------------------------------------------------------------- tokens */

:root {
  --night: #04070C;

  /* Position du soleil : SOURCE DE VÉRITÉ UNIQUE. Le CSS place le disque, le
     script relit ces deux valeurs pour centrer le halo tramé. Toujours
     exprimer --sun-y en vh, le script en dépend. */
  --sun-x: 73%;
  --sun-y: 46vh;

  /* La terre : plus neutre et plus chaude que le ciel, pour qu'on sente qu'on
     a changé de matière en passant l'arc. */
  --land: #0A0C0E;
  --land-2: #141719;
  --land-3: #1B1F21;
  --rule: #2E3538;
  --rule-hi: #454E4A;

  --light: #F0BC84;      /* la lumière, unique */
  --light-dim: #8A6A4E;
  --disc: #FCF6EC;

  --text: #EDE9E1;
  --text-2: #A9A79F;
  /* Plancher de contraste : #8C8A81 donne 5,4:1 sur la terre. Ce token porte
     les métadonnées, les numéros de section et le pied de page — du texte
     qu'on lit, pas de la décoration. Ne jamais l'assombrir sans refaire le
     calcul : la version précédente du site avait déjà ce défaut. */
  --text-3: #8C8A81;

  /* Empruntées aux apps, et employées UNIQUEMENT sur leur propre bloc. */
  --cleo: #E0865C;
  --keyfall: #8F7DFF;
  --mixbar: #4A8FE0;

  --ease: cubic-bezier(.22, 1, .36, 1);
  --measure: 1120px;
  --pad: clamp(20px, 5vw, 44px);
}

/* --------------------------------------------------------------------- base */

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

html {
  background: var(--night);
  scroll-behavior: smooth;
  scroll-padding-top: 88px;
}

body {
  /* Surtout PAS de fond ici : le ciel est un enfant du body à z-index négatif,
     et un fond opaque posé sur le body passerait par-dessus. La couleur
     appartient à <html>, peinte avant. */
  background: transparent;
  color: var(--text);
  font-family: "Instrument Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-size: 17px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

/* Fraunces est une variable font : son axe opsz DOIT suivre la taille réelle
   de rendu. Réglé une fois pour toutes à 144, on applique des déliés dessinés
   pour du 144 points à des titres de 19 px, et c'est illisible. La valeur par
   défaut est donc celle du TEXTE ; les grandes tailles la remontent, une par
   une, là où elles sont définies. WONK, qui donne les terminaisons biscornues,
   ne sert que sur le wordmark : du caractère à 200 px, du bruit à 19 px. */
h1, h2, h3 {
  font-family: Fraunces, Georgia, "Times New Roman", serif;
  font-weight: 600;
  line-height: 1.06;
  letter-spacing: -.025em;
  margin: 0;
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 20;
}

p { margin: 0; }
a { color: inherit; text-decoration: none; }

::selection { background: var(--light); color: var(--night); }
:focus-visible { outline: 2px solid var(--light); outline-offset: 4px; border-radius: 4px; }

.wrap {
  width: 100%;
  max-width: var(--measure);
  margin: 0 auto;
  padding-inline: var(--pad);
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  padding: 12px 18px;
  background: var(--text);
  color: var(--night);
  font-weight: 600;
  border-radius: 0 0 8px 0;
  z-index: 100;
}
.skip:focus { left: 0; }

/* ---------------------------------------------------------------------- ciel */

/* Le dégradé CSS tient le ciel immédiatement, et sans JavaScript du tout. Le
   canvas tramé se peint après le premier rendu et se fond par-dessus : la page
   reste juste si le script ne tourne jamais. */
.sky {
  position: fixed;
  inset: 0;
  z-index: -3;
  overflow: hidden;
  pointer-events: none;
  background: linear-gradient(to bottom,
    #04070C 0%, #061019 34%, #0A1F31 62%, #123246 84%, #1E4657 100%);
}

#dither {
  position: absolute;
  left: 50%;
  top: 0;
  width: 100vw;
  height: 160vh;
  transform: translate(-50%, 0);
  image-rendering: pixelated;
  will-change: transform;
  opacity: 0;
  transition: opacity .45s ease-out;
}
#dither.on { opacity: 1; }

/* Les étoiles vivent sur un carré bien plus grand que l'écran, centré sur un
   pôle hors champ : la rotation ne découvre jamais de coin vide. */
#stars {
  position: absolute;
  left: 50%;
  top: 0;
  width: 190vmax;
  height: 190vmax;
  transform-origin: 50% 50%;
  animation: pole 150s linear infinite;
  will-change: transform;
  opacity: .8;
}
@keyframes pole {
  from { transform: translate(-50%, -58%) rotate(0); }
  to   { transform: translate(-50%, -58%) rotate(360deg); }
}

/* ------------------------------------------------------------------ le disque */

/* Source de lumière unique, et l'œil du nom. Trois principes tenus ici, et
   chacun a coûté une version pour être trouvé :
   — le noyau n'a AUCUN bord net, il se dissout en alpha dans le bloom. Un
     cercle à bord franc se lit comme une pastille quoi qu'on mette dedans ;
   — la chaleur est dans la RETOMBÉE, pas dans le disque. Un astre est blanc au
     centre et chaud autour ; l'inverse fait autocollant ;
   — aucun cercle tracé. Une couronne à bordure visible, et l'ensemble redevient
     une cible. */
.disc {
  position: absolute;
  left: var(--sun-x);
  top: var(--sun-y);
  width: 88px;
  height: 88px;
  margin-left: -44px;
  margin-top: -44px;
  will-change: transform;
}
.disc span { position: absolute; border-radius: 50%; }

.disc .corona {
  inset: -360% -520%;
  background: radial-gradient(ellipse at center,
    rgba(240, 188, 132, .085) 0%, rgba(240, 188, 132, .048) 19%,
    rgba(240, 188, 132, .020) 38%, rgba(240, 188, 132, .006) 58%,
    rgba(240, 188, 132, 0) 78%);
  animation: breathe 13s ease-in-out infinite;
  will-change: transform;
}
@keyframes breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.055); } }

/* La zone chaude dense, entre le noyau et la couronne : c'est elle qui fait la
   continuité. Sans elle, on saute d'un disque plein à un halo lointain et l'œil
   lit deux objets au lieu d'une lumière. */
.disc .bloom {
  inset: -130% -190%;
  background: radial-gradient(ellipse at center,
    rgba(255, 241, 217, .26) 0%, rgba(249, 216, 168, .145) 23%,
    rgba(240, 188, 132, .058) 45%, rgba(240, 188, 132, .016) 64%,
    rgba(240, 188, 132, 0) 80%);
}
.disc .core {
  inset: 0;
  background: radial-gradient(circle,
    #FFFFFF 0%, #FFFDF7 30%, rgba(255, 249, 235, .93) 54%,
    rgba(253, 234, 201, .56) 74%, rgba(248, 215, 166, .19) 89%,
    rgba(240, 188, 132, 0) 100%);
}
/* L'iris ne se trouve qu'en s'approchant, et c'est tout l'intérêt du clin
   d'œil au nom. Un assombrissement diffus, jamais un anneau. */
.disc .iris {
  inset: 20%;
  background: radial-gradient(circle,
    rgba(146, 96, 46, .10) 0%, rgba(146, 96, 46, .045) 44%, rgba(146, 96, 46, 0) 72%);
}

/* Un seul élément, transform et opacity, une fois toutes les dix secondes. */
.shoot {
  position: absolute;
  width: 190px;
  height: 1px;
  left: 0;
  top: 0;
  opacity: 0;
  background: linear-gradient(90deg, rgba(252, 246, 236, 0), rgba(252, 246, 236, .9));
  will-change: transform, opacity;
}

/* ---------------------------------------------------------- halo du curseur */

/* Fixé au-dessus de la terre mais sous la nav : la lampe passe aussi sur le
   contenu, pas seulement sur le ciel. Teinté chaud, jamais blanc. */
.spotlight {
  position: fixed;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  transition: opacity .7s var(--ease);
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 30%),
    rgba(240, 188, 132, .075), rgba(240, 188, 132, .028) 40%, transparent 68%);
}
@media (hover: hover) and (pointer: fine) {
  body.pointer-in .spotlight { opacity: 1; }
}

/* ------------------------------------------------------------------ horizon */

/* L'arc du logo à l'échelle de la page. Il sépare deux matières : au-dessus
   c'est atmosphérique, en dessous c'est opaque. Le liseré s'allume sous la
   lumière, à 73 %, jamais au centre. */
.horizon { position: relative; z-index: 1; margin-top: -1px; line-height: 0; }
.horizon svg { display: block; width: 100%; height: clamp(90px, 13vw, 170px); }

/* -------------------------------------------------------------------- terre */

/* min-height : la terre est le dernier bloc du document et le ciel est fixe.
   Sans garantie de hauteur, dès que le document ne remplit pas le dernier
   écran, le ciel repasse sous le pied de page. */
.land {
  position: relative;
  z-index: 1;
  background: var(--land);
  min-height: 100vh;
  /* flow-root : si le premier bloc de contenu portait un jour une marge haute
     plutôt qu'un padding, elle remonterait hors de .land par effondrement de
     marges et pousserait toute la terre vers le bas — le ciel fixe
     apparaîtrait alors dans la fente, sous l'arc. C'est arrivé sur le site de
     Cléo. Coût nul, et ça n'arrivera pas ici. */
  display: flow-root;
}
/* Pas de ::before sur .land : le liseré de l'horizon est tracé par le stroke
   du SVG, qui SUIT la courbe. Un trait droit posé au bas du bloc passerait
   ~51 px sous l'arc et se verrait en ligne franche sur toute la largeur.
   Une seule primitive, tracée une seule fois — c'est la règle 1. */
/* ---------------------------------------------------------------------- nav */

/* Aucun backdrop-filter : un flou ici écraserait le tramage du ciel, qui est
   toute la signature. Un voile en dégradé suffit à tenir la lisibilité et il
   laisse le grain intact dessous. */
.nav {
  position: sticky;
  top: 0;
  z-index: 40;
  background: linear-gradient(to bottom,
    rgba(4, 7, 12, .80), rgba(4, 7, 12, .42) 62%, rgba(4, 7, 12, 0));
}
.nav .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding-block: 16px;
}
.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: Fraunces, Georgia, serif;
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -.02em;
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 20;
  white-space: nowrap;
}
.brand svg { width: 26px; height: 26px; color: var(--light); transition: transform .6s var(--ease); }
.brand:hover svg { transform: rotate(-10deg) scale(1.06); }

.links { display: flex; align-items: center; gap: clamp(14px, 2.4vw, 26px); font-size: 14px; color: var(--text-2); }
.links a { transition: color .25s var(--ease); white-space: nowrap; }
.links a:hover { color: var(--text); }
.links .en {
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  letter-spacing: .12em;
  color: var(--text);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 3px 8px;
}
.links .en:hover { border-color: var(--light-dim); }

/* --------------------------------------------------------------------- hero */

.hero {
  position: relative;
  z-index: 1;
  min-height: 92vh;
  display: flex;
  align-items: flex-end;
  padding-bottom: 11vh;
}
.hero .wrap { width: 100%; }

/* Pas de pastille au-dessus du titre. Elle ne disait rien que le colophon ne
   dise mieux, et un micro-label en capitales espacées posé au-dessus d'un H1
   est le réflexe le plus reconnaissable du gabarit générique. */
.wordmark {
  font-size: clamp(72px, 15.5vw, 206px);
  line-height: .82;
  letter-spacing: -.045em;
  margin: 0 0 clamp(34px, 7vh, 64px);
  color: var(--text);
  font-variation-settings: "SOFT" 0, "WONK" 1, "opsz" 144;
}
.tagline {
  font-size: clamp(19px, 2.2vw, 25px);
  line-height: 1.35;
  max-width: 23ch;
  font-family: Fraunces, Georgia, serif;
  font-weight: 400;
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 26;
}
.tagline .dim { color: var(--text-2); }

.colophon {
  display: flex;
  flex-wrap: wrap;
  margin-top: 34px;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px;
  letter-spacing: .05em;
  color: var(--text-2);
  text-transform: uppercase;
}
.colophon span {
  padding-right: 20px;
  margin-right: 20px;
  border-right: 1px solid var(--rule);
  margin-bottom: 6px;
}
.colophon span:last-child { border-right: 0; margin-right: 0; padding-right: 0; }

.scroll-cue {
  position: absolute;
  left: var(--pad);
  bottom: 26px;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-3);
}
.scroll-cue .rail { display: block; width: 36px; height: 1px; background: var(--rule-hi); position: relative; overflow: hidden; }
.scroll-cue .rail::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--light);
  transform: translateX(-100%);
  animation: rail 2.8s var(--ease) infinite;
}
@keyframes rail { 0% { transform: translateX(-100%); } 55%, 100% { transform: translateX(100%); } }
.scroll-cue:hover { color: var(--text-2); }

/* ------------------------------------------------------------------ section */

section { padding-block: clamp(58px, 8vw, 104px); }

.sechead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  margin-bottom: clamp(32px, 4.5vw, 52px);
}
.sechead h2 {
  font-size: clamp(29px, 4vw, 46px);
  max-width: 24ch;
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 48;
}
.sechead .num {
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--text-3);
  white-space: nowrap;
}

/* Séparateur : un arc, jamais un trait droit. */
.arcsep { display: block; width: 100%; height: 30px; color: var(--rule); }

/* -------------------------------------------------------- bloc « définition » */

/* Premier bloc de contenu sous l'horizon, et il DOIT le rester : c'est ce que
   les moteurs IA extraient quand on leur demande ce qu'est Eyland. Ton
   volontairement neutre et factuel, à ne pas réécrire en publicité. */
#definition, #definition-en { padding-block: clamp(48px, 6vw, 76px); }
.answer-block { max-width: 62ch; position: relative; padding-left: 22px; }
.answer-block::before {
  content: "";
  position: absolute;
  left: 0; top: 6px; bottom: 6px;
  width: 1px;
  background: linear-gradient(to bottom, var(--light), rgba(240, 188, 132, .06));
}
.answer-block h2 { font-size: clamp(21px, 2.4vw, 27px); margin-bottom: 14px; font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 28; }
.answer-block p { color: var(--text-2); }
.answer-block strong { color: var(--text); font-weight: 500; }

/* --------------------------------------------------------------------- apps */

/* Les blocs sont posés sur la terre : opaques, mats, jamais en verre. La
   lumière vient toujours du même côté — un seul filet clair sur l'arête haute,
   et rien en bas. C'est la règle 2 qui fabrique la profondeur. */
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(288px, 1fr)); gap: 18px; }

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--land-2);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 26px 26px 22px;
  overflow: hidden;
  transition: transform .5s var(--ease), border-color .5s var(--ease), background .5s var(--ease);
}
/* La lumière atteint l'arête haute du bloc quand il entre dans le champ : le
   filet se dessine depuis la droite, du côté du disque. Une révélation qui dit
   quelque chose de la scène, au lieu du fondu échelonné à quatre-vingt-dix
   millisecondes d'écart qui est le tic du gabarit générique. */
.card::before {
  content: "";
  position: absolute;
  left: 8%; right: 8%; top: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent 4%, var(--t, var(--light)) 74%, transparent);
  opacity: .42;
  transform-origin: right center;
  transition: opacity .5s var(--ease);
}
.js .card::before { transform: scaleX(0); transition: transform 1.1s var(--ease), opacity .5s var(--ease); }
.js .card.lit::before { transform: scaleX(1); }

.card:hover { transform: translateY(-3px); border-color: var(--rule-hi); background: var(--land-3); }
.card:hover::before { opacity: 1; }

.card .ico {
  width: 38px; height: 38px;
  border: 1px solid var(--t);
  border-radius: 6px;
  color: var(--t);
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 24px;
  flex: none;
}
.card .ico svg { width: 19px; height: 19px; }
.card h3 { font-size: 26px; margin-bottom: 10px; font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 28; }
.card p { font-size: 14.5px; color: var(--text-2); margin-bottom: 24px; max-width: 38ch; flex: 1; }
.card .foot {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  border-top: 1px solid var(--rule);
  padding-top: 14px;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-3);
}
/* La flèche est un SVG et non le caractère « → » : U+2192 n'est pas dans le
   sous-ensemble latin des polices auto-hébergées, il serait rendu par une
   police de repli au milieu d'un mot. */
.card .go { display: inline-flex; align-items: center; gap: 6px; color: var(--t); text-transform: none; letter-spacing: .02em; }
.card .go svg { width: 13px; height: 13px; flex: none; transition: transform .4s var(--ease); }
.card:hover .go svg { transform: translateX(3px); }

/* Volontairement sans nom : c'est un bloc de ton, pas une fiche produit. Ce
   n'est pas un lien et il n'annonce aucune date. */
.card.soon { opacity: .74; }
.card.soon .ico { border-style: dashed; }

/* ------------------------------------------------------------------ atelier */

.creed {
  font-family: Fraunces, Georgia, serif;
  font-weight: 400;
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 40;
  font-size: clamp(24px, 3.6vw, 40px);
  line-height: 1.3;
  max-width: 26ch;
  margin-bottom: clamp(40px, 6vw, 70px);
}

/* Pas de cartes ici : des colonnes tenues par un filet haut, numérotées. Un
   principe se lit, il ne se vend pas. */
.principles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: clamp(26px, 4vw, 52px);
  counter-reset: p;
}
.principle { position: relative; padding-top: 24px; border-top: 1px solid var(--rule); counter-increment: p; }
.principle::before {
  content: "0" counter(p);
  position: absolute; top: -1px; left: 0;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10.5px;
  letter-spacing: .14em;
  color: var(--text-3);
  transform: translateY(-160%);
}
.principle::after {
  content: "";
  position: absolute; top: -1px; left: 0;
  width: 34px; height: 1px;
  background: var(--light);
  transform-origin: left center;
  transition: transform 1s var(--ease);
}
.js .principle::after { transform: scaleX(0); }
.js .principle.lit::after { transform: scaleX(1); }
.principle h3 { font-size: 19px; margin-bottom: 10px; max-width: 22ch; font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 20; }
.principle p { font-size: 14.5px; color: var(--text-2); }

/* ----------------------------------------------------------------- missions */

/* Décision d'origine tenue : PAS de cartes ici. Des cartes mettraient une offre
   commerciale au même niveau visuel que le travail montré au-dessus, et c'est
   exactement l'effet plaquette qu'on évite. Pas de bouton d'appel à l'action
   non plus : l'adresse est déjà en gros juste en dessous.
   C'est aussi la seule section qui vouvoie — le reste tutoie l'utilisateur des
   apps, ici on s'adresse à un client. Si ça change un jour, c'est tout ou rien,
   pas un mélange plus fin. */
.missions-lede {
  font-family: Fraunces, Georgia, serif;
  font-weight: 400;
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 30;
  font-size: clamp(20px, 2.8vw, 29px);
  line-height: 1.42;
  max-width: 33ch;
  margin-bottom: clamp(34px, 5vw, 58px);
}
.missions-lede .dim { color: var(--text-2); }

.crafts { display: grid; grid-template-columns: 1fr; gap: clamp(22px, 3vw, 34px); max-width: 64ch; }
.craft { position: relative; padding-left: 26px; }
.craft::before {
  content: "";
  position: absolute; left: 0; top: .62em;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--t);
  box-shadow: 0 0 12px 1px var(--t);
  opacity: .9;
}
.craft h3 { font-size: 18px; margin-bottom: 6px; font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 20; }
.craft p { font-size: 14.5px; color: var(--text-2); }
.missions-note { margin-top: clamp(32px, 4.5vw, 50px); font-size: 14.5px; color: var(--text-3); max-width: 56ch; }

/* ---------------------------------------------------------------------- FAQ */

/* ⚠️ Ces quatre questions/réponses sont dupliquées dans le JSON-LD FAQPage de
   chaque page. Toute modification ici doit être reportée là-bas, MOT POUR MOT :
   un FAQPage qui décrit des Q/R absentes de la page est du spam structuré aux
   yeux de Google. */
.faq { max-width: 76ch; border-top: 1px solid var(--rule); }
.faq details { border-bottom: 1px solid var(--rule); }
.faq summary {
  list-style: none;
  cursor: pointer;
  padding: 20px 34px 20px 0;
  position: relative;
  font-family: Fraunces, Georgia, serif;
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -.015em;
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 20;
  transition: color .3s var(--ease);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--light); }
.faq summary::after {
  content: "";
  position: absolute; right: 6px; top: 50%;
  width: 9px; height: 9px;
  border-right: 1px solid var(--text-3);
  border-bottom: 1px solid var(--text-3);
  transform: translateY(-70%) rotate(45deg);
  transition: transform .35s var(--ease);
}
.faq details[open] summary::after { transform: translateY(-30%) rotate(-135deg); }
.faq .faq-body { padding: 0 0 22px; color: var(--text-2); font-size: 15px; max-width: 64ch; }

/* ------------------------------------------------------------------ contact */

.contact-line { max-width: 52ch; color: var(--text-2); margin-bottom: clamp(28px, 4vw, 44px); }

/* Un seul soulignement, dans la lumière. L'ancienne version employait un
   dégradé Cléo → KeyFall : ce serait rouvrir la porte à la triade. */
.mailto {
  display: inline-block;
  font-family: Fraunces, Georgia, serif;
  font-weight: 600;
  letter-spacing: -.03em;
  font-size: clamp(28px, 5.6vw, 62px);
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 60;
  background-image: linear-gradient(90deg, var(--light), var(--light));
  background-size: 0% 1px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size .55s var(--ease), color .4s var(--ease);
  word-break: break-word;
}
.mailto:hover { background-size: 100% 1px; color: var(--light); }

/* ------------------------------------------------------------------- footer */

footer .wrap {
  padding-block: 26px 44px;
  border-top: 1px solid var(--rule);
  display: flex;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  letter-spacing: .05em;
  color: var(--text-3);
}
.foot-links { display: flex; gap: 20px; flex-wrap: wrap; }
.foot-links a { transition: color .25s var(--ease); }
.foot-links a:hover { color: var(--text-2); }

/* ------------------------------------------------------------ pages légales */

/* Même scène, en plus court : un ciel réduit qui porte le titre, l'arc, puis la
   terre. Ce sont des documents, pas la porte d'entrée — mais ils appartiennent
   à la même île. */
.page-legal { --sun-x: 78%; --sun-y: 26vh; }
.page-legal .disc { width: 64px; height: 64px; margin-left: -32px; margin-top: -32px; }
.hero-lite { min-height: 48vh; padding-bottom: 6vh; }
.hero-lite h1 {
  font-size: clamp(34px, 6vw, 62px);
  letter-spacing: -.035em;
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 60;
  max-width: 18ch;
  margin-bottom: 16px;
}
.back-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: clamp(24px, 4vh, 44px);
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-2);
  transition: color .25s var(--ease);
}
.back-link svg { width: 14px; height: 14px; transition: transform .4s var(--ease); }
.back-link:hover { color: var(--text); }
.back-link:hover svg { transform: translateX(-3px); }
.updated { color: var(--text-2); max-width: 62ch; font-size: 15px; }

.legal { padding-block: clamp(48px, 7vw, 88px); max-width: 74ch; }
.legal h2 {
  font-size: clamp(20px, 2.4vw, 25px);
  margin: clamp(34px, 4.5vw, 52px) 0 12px;
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 26;
  padding-top: 22px;
  border-top: 1px solid var(--rule);
}
.legal h2:first-of-type { margin-top: 0; }
.legal p { color: var(--text-2); margin-bottom: 8px; }
.legal a:not(.back-link) {
  color: var(--text);
  background-image: linear-gradient(90deg, var(--light-dim), var(--light-dim));
  background-size: 100% 1px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size .35s var(--ease), color .3s var(--ease);
}
.legal a:not(.back-link):hover { color: var(--light); background-image: linear-gradient(90deg, var(--light), var(--light)); }
.legal ul { color: var(--text-2); padding-left: 20px; margin: 0 0 8px; }
.legal li { margin-bottom: 6px; }

/* --------------------------------------------------------------- responsive */

@media (max-width: 900px) {
  .principles { gap: 32px; }
  .sechead { margin-bottom: 32px; }
}

@media (max-width: 640px) {
  /* Décision reprise de la feuille précédente, et elle tient toujours : sur
     375 px, marque + deux liens + bascule ne tiennent pas sur une ligne en
     anglais. On garde le lien vers les produits et la bascule, le reste se
     parcourt au défilement — c'est un one-pager. Sans ça, la nav passe à deux
     lignes et mange 113 px de hauteur. */
  .nav .wrap { flex-wrap: nowrap; }
  .links .nav-more { display: none; }
  .links { gap: 16px; }

  /* Le repère de défilement passait sous la ligne de flottaison une fois la nav
     et le colophon empilés : il ne repérait plus rien. */
  .scroll-cue { display: none; }

  /* Le soleil traversait l'accroche et le colophon : illisible. Il remonte dans
     le ciel libre au-dessus du titre, et le hero reprend de la hauteur pour
     qu'il reste du ciel à regarder. */
  :root { --sun-x: 70%; --sun-y: 27vh; }
  .disc { width: 70px; height: 70px; margin-left: -35px; margin-top: -35px; }
  .hero { min-height: 88vh; padding-top: 78px; padding-bottom: 44px; }

  .page-legal { --sun-x: 74%; --sun-y: 22vh; }
  .hero-lite { min-height: 42vh; padding-top: 70px; }

  .colophon { margin-top: 26px; font-size: 11px; }
  .colophon span { padding-right: 14px; margin-right: 14px; }
  .card { padding: 24px 22px 20px; }
  .card .foot { flex-direction: column; align-items: flex-start; gap: 8px; }
  .answer-block { padding-left: 18px; }
  .faq summary { font-size: 17.5px; padding-right: 28px; }
  footer .wrap { padding-block: 22px 36px; }
}

/* Le mouvement réduit coupe tout, et les états « avant révélation » sont
   conditionnés à la classe .js posée par le script : sans JavaScript, la page
   reste entièrement lisible et rien n'est masqué. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  #stars { animation: none; }
  .shoot, .spotlight { display: none; }
  .disc .corona { animation: none; }
  .scroll-cue .rail::after { animation: none; transform: none; }
  .js .card::before, .js .principle::after { transform: none !important; }
  * { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}
