/* Site public Sesame.
   Tokens : la palette de theme.ts (bg, surface, detail, text, dim, primary…), plus deux familles
   dérivées pour la direction artistique « la porte » : --night (le bg de theme.ts, assombri pour que
   la lumière ressorte) et --light-* / --ink (le cuivre --primary éclairci : l'intérieur de la porte).
   Aucune autre couleur que ces variables. Polices auto-hébergées (site/fonts, licence OFL). */

/* Fraunces en une seule instance fine (graisse 300, SOFT 40, WONK 0 épinglés) : proportions
   larges et œil bas, la lettre s'assoit. Seul l'axe optique reste variable, réglé par le
   navigateur sur la taille (font-optical-sizing: auto) : nerveux en petit, calme en grand. */
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("./fonts/fraunces.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: "Jost";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("./fonts/jost.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;
}

/* Ouverture de la porte : des nombres animables (sans @property, l'intro saute au lieu de glisser). */
@property --sx {
  syntax: "<number>";
  inherits: true;
  initial-value: 1;
}

@property --sy {
  syntax: "<number>";
  inherits: true;
  initial-value: 1;
}

:root {
  --bg: #201C18;
  --surface: #2C2723;
  --detail: #26221E;
  --text: #F5F2ED;
  --dim: #A79D91;
  --dim2: #8B8377;
  --line: rgba(255, 255, 255, 0.09);
  --line2: rgba(255, 255, 255, 0.18);
  --primary: #C27E4B;
  --primary-hover: #A5683B;
  --on-primary: #111111;
  --error: #D98A8A;

  --night: #15120F;
  --light-1: #F3D2AE;
  --light-2: #E7B184;
  --light-3: #D9975F;
  --ink: #1A1512;
  --ink-dim: #3A2A1C;
  --error-on-light: #6E1414;

  --display: "Fraunces", Georgia, "Times New Roman", serif;
  --sans: "Jost", "Avenir Next", Avenir, "Century Gothic", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .5 -.14'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  --gutter: 20px;
  --col: 1120px;

  color-scheme: dark;
}

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--night);
  color: var(--text);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-wrap: break-word;
}

/* Grain : la nuit n'est jamais un aplat. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 50;
  pointer-events: none;
  opacity: 0.08;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .9 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

h1,
h2,
h3,
p,
ol,
ul,
dl,
dd {
  margin: 0;
}

ol,
ul {
  padding: 0;
  list-style: none;
}

a {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--line2);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

a:hover {
  text-decoration-color: var(--text);
}

:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
  border-radius: 4px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Champ piège : hors écran, pas display:none (un robot le remplit, un humain ne le voit pas). */
.trap {
  position: absolute;
  left: -9999px;
}

.wrap {
  width: 100%;
  max-width: calc(var(--col) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ---------- La scène : une porte entrouverte dans la nuit ---------- */

.stage {
  background: var(--night);
}

/* site.js pose .scrolly quand la scène tient dans l'écran : le scroll ouvre alors la porte en grand. */
.scrolly .stage {
  height: 190vh;
  height: 190svh;
}

.scrolly .stage.is-open {
  background: var(--light-3);
}

.hero {
  --wm: clamp(5.25rem, 25vw, 17rem);
  --dw: clamp(104px, 14vw + 50px, 210px);
  --dt: clamp(36px, 7vh, 72px);
  --db: 28px;
  position: sticky;
  top: 0;
  display: grid;
  grid-template-rows: minmax(340px, 1fr) auto;
  min-height: 100vh;
  min-height: 100svh;
  overflow: hidden;
  container-type: inline-size;
  background: var(--night);
}

/* Faisceaux et poussière (site.js). --lx / --ly : où porte la lumière, de -0,5 à 0,5 autour de la porte. */
.rays {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: var(--glow, 1);
  animation: glow 1.8s ease 1.5s backwards;
}

.doorway {
  position: relative;
}

.haze {
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(150vw, 1200px);
  aspect-ratio: 1;
  transform: translate(calc(-50% + var(--lx, 0) * 22vw), calc(-50% + var(--ly, 0) * 16vh));
  background: radial-gradient(closest-side, color-mix(in srgb, var(--primary) 30%, transparent), color-mix(in srgb, var(--primary) 9%, transparent) 48%, transparent 72%);
  opacity: var(--glow, 1);
  animation: glow 1.4s ease 1.3s backwards;
}

/* La lumière de la porte qui tombe au sol, vers toi. */
.spill {
  position: absolute;
  left: 50%;
  top: calc(100% - var(--db));
  width: calc(var(--dw) * 3.4);
  height: 40vh;
  transform: translateX(-50%) skewX(calc(var(--lx, 0) * -50deg));
  transform-origin: 50% 0;
  filter: blur(16px);
  opacity: var(--glow, 1);
  animation: glow 1.4s ease 1.5s backwards;
}

/* Le trapèze est sur le pseudo-élément : un clip-path posé sur l'élément flouté couperait le flou net. */
.spill::before {
  content: "";
  position: absolute;
  inset: 0;
  clip-path: polygon(35.3% 0, 64.7% 0, 100% 100%, 0 100%);
  background: linear-gradient(180deg, color-mix(in srgb, var(--light-3) 34%, transparent), transparent 84%);
}

.wordmark {
  position: absolute;
  left: 50%;
  top: 47%;
  transform: translate(-50%, -50%);
  margin: 0;
  color: var(--text);
  font-family: var(--display);
  font-weight: 300;
  font-size: var(--wm);
  line-height: 1;
  letter-spacing: -0.015em;
  white-space: nowrap;
}

/* Le nom se saisit comme le code à six caractères : une lettre, un cran. */
.letters > span {
  animation: key 0.3s ease backwards;
}

.letters > span:nth-child(1) { animation-delay: 0.35s; }
.letters > span:nth-child(2) { animation-delay: 0.48s; }
.letters > span:nth-child(3) { animation-delay: 0.61s; }
.letters > span:nth-child(4) { animation-delay: 0.74s; }
.letters > span:nth-child(5) { animation-delay: 0.87s; }
.letters > span:nth-child(6) { animation-delay: 1s; }

.ticks {
  position: absolute;
  left: 50%;
  top: calc(100% + 0.08em);
  display: flex;
  gap: 8px;
  transform: translateX(-50%);
  color: var(--primary);
  opacity: 0;
  animation: ticks 2s linear backwards;
}

.ticks > i {
  width: clamp(14px, 1.6vw, 22px);
  height: 2px;
  background: currentColor;
  animation: tick 0.2s ease backwards;
}

.ticks > i:nth-child(1) { animation-delay: 0.35s; }
.ticks > i:nth-child(2) { animation-delay: 0.48s; }
.ticks > i:nth-child(3) { animation-delay: 0.61s; }
.ticks > i:nth-child(4) { animation-delay: 0.74s; }
.ticks > i:nth-child(5) { animation-delay: 0.87s; }
.ticks > i:nth-child(6) { animation-delay: 1s; }

/* La porte : un rectangle de lumière. Elle s'agrandit par transform, et son contenu (le même décor,
   en négatif) porte l'échelle inverse : les lettres s'inversent exactement là où passe la lumière. */
.door {
  position: absolute;
  left: calc(50% - var(--dw) / 2);
  width: var(--dw);
  top: var(--dt);
  bottom: var(--db);
  z-index: 2;
  overflow: hidden;
  pointer-events: none;
  background: linear-gradient(180deg, var(--light-1), var(--light-2) 46%, var(--light-3));
  transform: scale(var(--sx), var(--sy));
  animation: appear 0.5s ease 0.1s backwards, ajar 1.15s cubic-bezier(0.76, 0, 0.18, 1) 1.3s backwards;
}

.door-inner {
  position: absolute;
  left: calc(var(--dw) / 2 - 50vw);
  left: calc(var(--dw) / 2 - 50cqw);
  width: 100vw;
  width: 100cqw;
  top: calc(-1 * var(--dt));
  bottom: calc(-1 * var(--db));
  transform: scale(calc(1 / var(--sx)), calc(1 / var(--sy)));
  transform-origin: 50% calc(50% + (var(--dt) - var(--db)) / 2);
}

.door .wordmark,
.door .ticks {
  color: var(--ink);
}

.hero-copy {
  position: relative;
  z-index: 3;
  width: 100%;
  max-width: 41rem;
  margin-inline: auto;
  padding: 0 var(--gutter) clamp(24px, 5vh, 56px);
  text-align: center;
  opacity: var(--copy, 1);
  animation: rise 0.9s ease 1.75s backwards;
}

.hero-promise {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(1.75rem, 1.2rem + 2.5vw, 2.875rem);
  line-height: 1.08;
  letter-spacing: -0.012em;
  text-wrap: balance;
}

.hero-sub {
  max-width: 34em;
  margin: 14px auto 0;
  color: var(--dim);
  font-size: clamp(1rem, 0.95rem + 0.3vw, 1.125rem);
  line-height: 1.5;
  text-wrap: pretty;
}

.hero-cta {
  margin-top: clamp(18px, 3.4vh, 32px);
}

.hero-note {
  margin-top: 10px;
  color: var(--dim2);
  font-size: 0.9375rem;
}

/* Une fois l'intro jouée, site.js prend la main : plus d'animation, les variables suivent le scroll. */
.hero.is-live .door,
.hero.is-live .hero-copy,
.hero.is-live .haze,
.hero.is-live .spill,
.hero.is-live .rays,
.hero.is-live .letters > span,
.hero.is-live .ticks,
.hero.is-live .ticks > i {
  animation: none;
}

.hero.is-open .hero-copy {
  visibility: hidden;
}

@keyframes key {
  from { opacity: 0; }
}

@keyframes tick {
  from { opacity: 0.25; }
}

@keyframes ticks {
  0%, 62% { opacity: 1; }
  100% { opacity: 0; }
}

@keyframes appear {
  from { opacity: 0; }
}

@keyframes ajar {
  from { --sx: 0.014; }
}

@keyframes glow {
  from { opacity: 0; }
}

@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
}

/* ---------- Action ---------- */

.btn-primary,
.waitlist button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding: 0 28px;
  border: 0;
  border-radius: 999px;
  background: var(--primary);
  color: var(--on-primary);
  font: inherit;
  font-size: 1.0625rem;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.005em;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s ease;
  -webkit-tap-highlight-color: transparent;
}

.btn-primary:hover {
  background: var(--light-2);
}

.btn-primary:focus-visible,
.waitlist button:focus-visible {
  outline: 3px solid var(--primary);
  outline-offset: 3px;
  border-radius: 999px;
}

/* ---------- Préinscription : on a passé la porte, on est dans la lumière ---------- */

#preinscription {
  scroll-margin-top: 0;
}

.inside {
  position: relative;
  z-index: 4;
  padding-top: clamp(56px, 10vh, 112px);
  background: var(--light-3);
  color: var(--ink);
}

/* La lumière s'éteint en redescendant dans la nuit. */
.inside::after {
  content: "";
  display: block;
  height: 28vh;
  margin-top: clamp(56px, 9vh, 104px);
  background: linear-gradient(180deg, var(--light-3), var(--primary-hover) 26%, var(--night));
  background: linear-gradient(in oklab 180deg, var(--light-3), var(--night));
}

/* Scène active : la section remonte dans la porte grande ouverte (même lumière derrière) et vient se
   ranger juste sous le nom. --overlap est mesuré par site.js : la distance du bas du nom au bas de l'écran. */
.scrolly .inside {
  --ov: var(--overlap, 40vh);
  margin-top: calc(-1 * var(--ov));
  padding-top: 0;
  background: linear-gradient(180deg, transparent var(--ov), var(--light-3) var(--ov));
}

/* Le contenu occupe toute la zone transparente : le fondu vers la nuit commence là où le fond
   redevient opaque, donc sans raccord visible avec la lumière de la porte. */
.scrolly .inside-grid {
  min-height: var(--ov);
  align-content: start;
  padding-bottom: clamp(40px, 7vh, 88px);
}

.scrolly .inside::after {
  height: 44vh;
  margin-top: 0;
}

.inside-grid {
  display: grid;
  gap: clamp(24px, 5vw, 40px);
}

.inside h2 {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(2.5rem, 1.4rem + 5.4vw, 5rem);
  line-height: 0.98;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.inside :focus-visible {
  outline-color: var(--ink);
}

.inside a {
  color: var(--ink);
  text-decoration-color: color-mix(in srgb, var(--ink) 45%, transparent);
}

.inside a:hover {
  text-decoration-color: var(--ink);
}

.waitlist {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.waitlist input[type="email"] {
  width: 100%;
  min-width: 0;
  min-height: 56px;
  padding: 0 24px;
  background: var(--light-1);
  color: var(--ink);
  border: 1px solid color-mix(in srgb, var(--ink) 30%, transparent);
  border-radius: 999px;
  font: inherit;
  font-size: 1.0625rem; /* ≥ 16 px : en dessous, iOS zoome à la mise au point */
  -webkit-appearance: none;
  appearance: none;
  color-scheme: light;
}

.waitlist input[type="email"]::placeholder {
  color: var(--ink-dim);
  opacity: 0.75;
}

.waitlist input[type="email"]:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
  border-radius: 999px;
}

/* Remplissage automatique : sans ça, Chrome et Safari repeignent le champ. */
.waitlist input[type="email"]:-webkit-autofill {
  -webkit-text-fill-color: var(--ink);
  -webkit-box-shadow: 0 0 0 1000px var(--light-1) inset;
  caret-color: var(--ink);
}

.waitlist button {
  min-height: 56px;
  background: var(--ink);
  color: var(--light-1);
}

.waitlist button:hover {
  background: var(--night);
  color: var(--text);
}

.waitlist button:focus-visible {
  outline-color: var(--ink);
}

.waitlist button:disabled {
  cursor: default;
}

.waitlist [data-waitlist-status] {
  flex-basis: 100%;
  min-height: 1.55em; /* la ligne existe toujours : la zone aria-live n'apparaît pas, elle se remplit */
  padding-inline: 4px;
  font-size: 0.9375rem;
  color: var(--ink-dim);
}

.waitlist[data-state="sending"] button {
  opacity: 0.55;
}

.waitlist[data-state="error"] [data-waitlist-status] {
  color: var(--error-on-light);
  font-weight: 500;
}

.waitlist[data-state="success"] input,
.waitlist[data-state="success"] button {
  display: none;
}

.waitlist[data-state="success"] [data-waitlist-status] {
  padding: 0;
  color: var(--ink);
  font-family: var(--display);
  font-size: clamp(1.5rem, 4vw, 2rem);
  line-height: 1.15;
}

.fineprint {
  margin-top: 6px;
  color: var(--ink-dim);
  font-size: 0.9375rem;
  line-height: 1.5;
  max-width: 36em;
}

@media (min-width: 560px) {
  .waitlist {
    flex-direction: row;
    flex-wrap: wrap;
  }

  .waitlist input[type="email"] {
    flex: 1 1 0;
    width: auto;
  }

  .waitlist button {
    flex: 0 0 auto;
  }
}

@media (min-width: 900px) {
  .inside-grid {
    grid-template-columns: minmax(0, 6fr) minmax(0, 6fr);
    align-items: end;
    gap: 72px;
  }
}

/* ---------- Sections de nuit ---------- */

/* La lampe : dans la nuit, un halo cuivre suit le pointeur (site.js) et révèle filets et grain.
   Au tactile, c'est le scroll qui la promène. Sans JS ou en mouvement réduit : elle reste éteinte. */
.lit {
  position: relative;
  overflow: clip;
}

.lit > :not(.lamp) {
  position: relative;
}

/* .lamp couvre la section et s'estompe à ses bords (sinon le halo, coupé net par la section, fait une
   arête) ; le halo et les filets, eux, sont ses deux pseudo-éléments et suivent le pointeur. */
.lamp {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s ease;
  -webkit-mask-image: linear-gradient(180deg, transparent, var(--ink) 120px, var(--ink) calc(100% - 120px), transparent);
  mask-image: linear-gradient(180deg, transparent, var(--ink) 120px, var(--ink) calc(100% - 120px), transparent);
}

.lamp.on {
  opacity: 1;
}

.lamp::before,
.lamp::after {
  content: "";
  position: absolute;
  left: -420px;
  top: -420px;
  width: 840px;
  height: 840px;
  transform: translate3d(var(--mx, 0px), var(--my, 0px), 0);
}

.lamp::before {
  background: radial-gradient(closest-side, color-mix(in srgb, var(--primary) 22%, transparent), color-mix(in srgb, var(--primary) 8%, transparent) 44%, transparent);
}

/* Filets et grain restent fixes par rapport à la page : seule la lampe se déplace au-dessus. */
.lamp::after {
  background-image: repeating-linear-gradient(90deg, var(--line2) 0 1px, transparent 1px 96px), var(--grain);
  background-position: calc(420px - var(--mx, 0px)) 0, calc(420px - var(--mx, 0px)) calc(420px - var(--my, 0px));
  opacity: 0.7;
  -webkit-mask-image: radial-gradient(closest-side, var(--ink) 18%, transparent 90%);
  mask-image: radial-gradient(closest-side, var(--ink) 18%, transparent 90%);
}

/* Sur un écran étroit le halo couvre toute la largeur : les filets verticaux croisent
   les règles horizontales des listes et dessinent une grille. On garde le grain seul. */
@media (max-width: 599px) {
  .lamp::after {
    background-image: var(--grain);
    background-position: calc(420px - var(--mx, 0px)) calc(420px - var(--my, 0px));
  }
}

.block {
  padding-block: clamp(36px, 8vw, 88px);
}

.block > h2,
.how-head h2 {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(2.125rem, 1.4rem + 3.4vw, 3.5rem);
  line-height: 1.02;
  letter-spacing: -0.018em;
  margin-bottom: clamp(20px, 4vw, 32px);
  text-wrap: balance;
}

@media (min-width: 900px) {
  .split {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: 72px;
  }

  .split > h2 {
    position: sticky;
    top: 72px;
    align-self: start;
    margin-bottom: 0;
  }
}

/* ---------- Comment ça marche : trois scènes ---------- */

.how-grid {
  padding-block: clamp(36px, 8vw, 88px);
}

.how-progress {
  display: none;
}

.scene {
  position: relative;
  display: grid;
  gap: 20px;
  padding-block: clamp(28px, 6vw, 56px);
}

/* Les filets sont des pseudo-éléments : ils se tracent à l'entrée de la section (voir « Entrées »). */
.scene::before,
.facts > div::before,
.facts > div:last-child::after,
.foot::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 1px;
  background: var(--line);
  transform-origin: 0 50%;
}

.facts > div:last-child::after {
  top: auto;
  bottom: 0;
}

.scene-num {
  display: block;
  color: var(--primary);
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(6rem, 26vw, 8.5rem);
  line-height: 0.8;
  letter-spacing: -0.02em;
}

.scene-text h3 {
  font-size: clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem);
  line-height: 1.2;
  font-weight: 500;
  letter-spacing: -0.005em;
}

.scene-text p {
  margin-top: 8px;
  color: var(--dim);
  max-width: 35em;
}

/* Une mini-démonstration : un schéma d'écran, sans nom ni montant. État par défaut = état final ;
   site.js pose data-step sur la scène et .on sur chaque [data-at] atteint, le reste est en CSS. */
.demo {
  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  position: relative;
  width: 100%;
  max-width: 27.5rem;
  margin-inline: auto;
  padding: clamp(16px, 4.4vw, 28px);
  border: 1px solid var(--line2);
  border-radius: 24px;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  color: var(--text);
}

.demo-label {
  margin-bottom: 10px;
  color: var(--dim);
  font-size: 0.75rem;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.pill {
  display: block;
  width: 48px;
  height: 20px;
  border-radius: 10px;
  background: color-mix(in srgb, var(--primary) 42%, var(--surface));
}

/* Scène 1 : un club, un nombre de personnes, la fourchette, l'envoi. */
.picks {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}

.pick {
  display: grid;
  gap: 8px;
  padding: 7px 7px 10px;
  border: 1px solid var(--line2);
  border-radius: 14px;
  transition: border-color 0.4s ease, background-color 0.4s ease;
}

.pick::before {
  content: "";
  aspect-ratio: 2 / 1;
  border-radius: 8px;
  background-color: var(--surface);
  transition: background-color 0.4s ease;
}

.pick::after {
  content: "";
  width: 62%;
  height: 6px;
  border-radius: 3px;
  background: var(--line2);
}

.pick.is-choice {
  border-color: var(--primary);
  background-color: color-mix(in srgb, var(--primary) 12%, transparent);
}

.pick.is-choice::before {
  background-color: var(--light-3);
}

.scene[data-step] .pick.is-choice:not(.on) {
  border-color: var(--line2);
  background-color: transparent;
}

.scene[data-step] .pick.is-choice:not(.on)::before {
  background-color: var(--surface);
}

.demo-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 12px clamp(20px, 8vw, 48px);
  margin-top: 18px;
}

.stepper {
  display: flex;
  align-items: center;
  gap: 12px;
}

.step-btn {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--line2);
  border-radius: 50%;
  color: var(--dim);
  font-size: 1.25rem;
  line-height: 1;
  transition: border-color 0.3s ease, color 0.3s ease;
}

.scene[data-step="2"] .step-plus,
.scene[data-step="3"] .step-plus {
  border-color: var(--primary);
  color: var(--text);
}

.count {
  overflow: hidden;
  height: 1em;
  min-width: 1.1ch;
  /* Sans, comme les boutons − / + : le compteur est un contrôle, pas un titre. */
  font-family: var(--sans);
  font-size: 1.75rem;
  font-weight: 500;
  line-height: 1;
  text-align: center;
}

.count-strip {
  display: grid;
  transform: translateY(-2em);
  transition: transform 0.5s var(--ease);
}

.count-strip > b {
  height: 1em;
  font-weight: 500;
}

.scene[data-step="0"] .count-strip,
.scene[data-step="1"] .count-strip {
  transform: none;
}

.scene[data-step="2"] .count-strip {
  transform: translateY(-1em);
}

.range {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 36px;
  color: var(--dim);
  transition: opacity 0.5s ease, transform 0.6s var(--ease);
}

.scene[data-step] .range:not(.on) {
  opacity: 0;
  transform: translateX(-14px);
}

.demo-send {
  display: grid;
  place-items: center;
  min-height: 46px;
  margin-top: 18px;
  border-radius: 999px;
  background-color: var(--primary);
  box-shadow: inset 0 0 0 1px var(--primary);
  color: var(--on-primary);
  font-size: 1rem;
  font-weight: 500;
  transition: background-color 0.4s ease, color 0.4s ease, box-shadow 0.4s ease;
}

.scene[data-step] .demo-send:not(.on) {
  background-color: transparent;
  box-shadow: inset 0 0 0 1px var(--line2);
  color: var(--dim);
}

/* Scène 2 : les offres arrivent en liste ; l'une est choisie, les autres se rangent derrière elle,
   le chat s'ouvre dessous. Tout en transform / opacity : la boîte garde une hauteur fixe. */
.demo-offers {
  height: calc(224px + 2 * clamp(16px, 4.4vw, 28px));
}

.offers,
.chat {
  position: absolute;
  left: clamp(16px, 4.4vw, 28px);
  right: clamp(16px, 4.4vw, 28px);
  top: clamp(16px, 4.4vw, 28px);
}

.offer {
  --y: 0px;
  --s: 0.9;
  --o: 0.3;
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 12px;
  height: 64px;
  padding-inline: 14px 16px;
  border: 1px solid var(--line2);
  border-radius: 16px;
  background: var(--surface);
  color: var(--dim);
  opacity: var(--o);
  transform: translateY(var(--y)) scale(var(--s));
  transform-origin: 50% 0;
  transition: transform 0.7s var(--ease), opacity 0.5s ease, border-color 0.4s ease;
}

.offer:nth-child(3) {
  --y: 8px;
  --s: 0.95;
  --o: 0.55;
  z-index: 2;
}

.offer.is-choice {
  --y: 16px;
  --s: 1;
  --o: 1;
  z-index: 3;
  border-color: var(--primary);
}

.scene[data-step] .offers:not(.on) .offer {
  --s: 1;
  --o: 1;
  border-color: var(--line2);
}

.scene[data-step] .offers:not(.on) .offer:nth-child(2) {
  --y: 72px;
}

.scene[data-step] .offers:not(.on) .offer:nth-child(3) {
  --y: 144px;
}

.scene[data-step] .offers:not(.on) .offer:not(.on) {
  --o: 0;
  --s: 0.96;
}

.scene[data-step] .offers:not(.on) .offer:nth-child(1):not(.on) { --y: 40px; }
.scene[data-step] .offers:not(.on) .offer:nth-child(2):not(.on) { --y: 112px; }
.scene[data-step] .offers:not(.on) .offer:nth-child(3):not(.on) { --y: 184px; }

.avatar {
  flex: none;
  width: 36px;
  height: 36px;
  border: 1px solid var(--line2);
  border-radius: 50%;
  background: var(--detail);
  transition: border-color 0.4s ease, background-color 0.4s ease;
}

.offers.on .is-choice .avatar,
.scene:not([data-step]) .is-choice .avatar {
  border-color: var(--primary);
  background-color: color-mix(in srgb, var(--primary) 40%, var(--detail));
}

.offer-name {
  flex: 1 1 auto;
  color: var(--text);
  font-weight: 500;
}

.chat {
  top: calc(clamp(16px, 4.4vw, 28px) + 96px);
  display: grid;
  gap: 8px;
  transition: opacity 0.5s ease 0.15s, transform 0.7s var(--ease) 0.15s;
}

.chat .demo-label {
  margin-bottom: 2px;
}

.scene[data-step] .chat:not(.on) {
  opacity: 0;
  transform: translateY(22px);
  transition-delay: 0s;
}

.bubble {
  display: flex;
  align-items: center;
  gap: 5px;
  width: 62%;
  height: 30px;
  padding-inline: 14px;
  border-radius: 15px 15px 15px 4px;
  background: var(--surface);
}

.bubble.me {
  justify-self: end;
  width: 46%;
  border-radius: 15px 15px 4px 15px;
  background: color-mix(in srgb, var(--primary) 42%, var(--surface));
}

.bubble.typing {
  width: 58px;
}

.bubble.typing > b {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--dim);
  animation: dot 1.2s ease-in-out infinite;
}

.bubble.typing > b:nth-child(2) { animation-delay: 0.15s; }
.bubble.typing > b:nth-child(3) { animation-delay: 0.3s; }

@keyframes dot {
  0%, 60%, 100% { opacity: 0.35; transform: none; }
  30% { opacity: 1; transform: translateY(-3px); }
}

/* Scène 3 : le code à six caractères, saisi par le host — c'est lui qui déclenche le paiement. */
.code-slots {
  position: relative;
  display: flex;
  gap: clamp(5px, 1.6vw, 10px);
  overflow: hidden;
}

.code-slots > span {
  flex: 1 1 0;
  aspect-ratio: 4 / 5;
  display: grid;
  place-items: center;
  border: 1px solid var(--primary);
  border-radius: 12px;
  background: var(--bg);
  color: var(--text);
  font-size: clamp(1.375rem, 5.6vw, 2rem);
  font-weight: 500;
  transition: color 0.2s ease, border-color 0.4s ease;
}

/* À la validation, la lumière de la porte passe une fois sur le code. */
.code-slots::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 22%;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--light-1) 55%, transparent), transparent);
  opacity: 0;
  transform: translateX(-100%);
}

.code.on .code-slots::after {
  animation: sweep 0.9s ease-out 0.1s;
}

@keyframes sweep {
  0% { opacity: 1; transform: translateX(-100%); }
  100% { opacity: 1; transform: translateX(560%); }
}

.code .code-status {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 16px;
  color: var(--text);
  font-size: 0.9375rem;
}

.code-status::before {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--primary);
  transition: background-color 0.4s ease;
}

.code-wait {
  display: none;
}

.scene[data-step] .code:not(.on) .code-slots > span {
  border-color: var(--line2);
}

.scene[data-step] .code-slots > span:not(.on) {
  color: transparent;
}

.scene[data-step] .code:not(.on) .code-status {
  color: var(--dim);
}

.scene[data-step] .code:not(.on) .code-status::before {
  background: var(--dim2);
}

.scene[data-step] .code:not(.on) .code-wait {
  display: inline;
}

.scene[data-step] .code:not(.on) .code-ok {
  display: none;
}

@media (min-width: 900px) {
  .scene {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    grid-template-rows: auto auto;
    gap: 28px 72px;
    align-items: center;
  }

  .scene-num {
    align-self: end;
    font-size: clamp(11rem, 19vw, 17rem);
  }

  .scene-text {
    align-self: start;
  }

  .demo {
    grid-column: 2;
    grid-row: 1 / span 2;
    max-width: 31rem;
  }
}

/* Séquence épinglée (classe posée par site.js quand chaque scène tient dans l'écran). La section fait
   plusieurs écrans de haut, son contenu est collé par position: sticky : le scroll reste natif. */
.pinned .how {
  height: 370vh;
  height: 370svh;
}

.pinned .how-pin {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
}

.pinned .how-grid {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  gap: clamp(12px, 2.4vh, 28px);
  height: 100%;
  padding-block: clamp(16px, 3.4vh, 40px);
}

.pinned .how-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.pinned .how-head h2 {
  margin: 0;
  font-size: clamp(1.375rem, 1.1rem + 1.3vw, 2.25rem);
}

.pinned .how-progress {
  display: flex;
  gap: 6px;
}

.how-progress > i {
  position: relative;
  overflow: hidden;
  width: clamp(26px, 6vw, 56px);
  height: 2px;
  background: var(--line2);
}

.how-progress > i::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--primary);
  transform: scaleX(var(--f, 0));
  transform-origin: 0 50%;
}

.pinned .steps {
  display: grid;
  min-height: 0;
}

.pinned .scene {
  grid-area: 1 / 1;
  min-height: 0;
  padding-block: 0;
  align-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.35s ease;
}

.pinned .scene::before {
  display: none;
}

.pinned .scene.is-active {
  opacity: 1;
  pointer-events: auto;
  transition-delay: 0.1s;
}

.pinned .scene-num {
  font-size: clamp(4.5rem, 12vh, 8rem);
}

.pinned .scene-text p {
  font-size: 1rem;
  line-height: 1.5;
}

@media (min-width: 900px) {
  .pinned .scene-num {
    font-size: clamp(11rem, 36vh, 21rem);
  }

  .pinned .scene-text p {
    font-size: inherit;
    line-height: inherit;
  }
}

/* Disponibilité : des lignes typographiques, pas des cartes. */
.facts > div {
  position: relative;
  display: grid;
  gap: 4px;
  padding-block: clamp(16px, 3vw, 24px);
}

.facts dt {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(2rem, 1.3rem + 3.2vw, 3.25rem);
  line-height: 1.05;
  letter-spacing: -0.015em;
}

.facts dd {
  color: var(--dim);
}

@media (min-width: 560px) {
  .facts > div {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: baseline;
    gap: 24px;
  }
}

/* ---------- Entrées de section (site.js pose .reveal sur <html>, puis .in à l'arrivée) ---------- */

/* Titres : ligne à ligne. Chaque mot est dans un cache ; --l est son numéro de ligne. */
.reveal [data-reveal="lines"] .w {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  padding: 0.1em 0.06em 0.16em;
  margin: -0.1em -0.06em -0.16em;
}

.reveal [data-reveal="lines"] .w > span {
  display: inline-block;
  transform: translateY(118%);
  transition: transform 0.95s cubic-bezier(0.2, 0.8, 0.2, 1);
  transition-delay: calc(var(--l, 0) * 0.13s);
}

.reveal [data-reveal="lines"].in .w > span {
  transform: none;
}

/* Blocs : le filet se trace, le contenu monte. */
.reveal [data-reveal]::before,
.reveal .facts > [data-reveal]:last-child::after {
  transform: scaleX(0);
  transition: transform 1.2s cubic-bezier(0.2, 0.8, 0.2, 1);
}

.reveal [data-reveal].in::before,
.reveal .facts > [data-reveal].in:last-child::after {
  transform: none;
}

.reveal [data-reveal]:not([data-reveal="lines"]) > * {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.7s ease 0.12s, transform 0.85s cubic-bezier(0.2, 0.8, 0.2, 1) 0.12s;
}

.reveal [data-reveal]:not([data-reveal="lines"]).in > * {
  opacity: 1;
  transform: none;
}

/* Dans la séquence épinglée, ce sont les changements de scène qui animent. */
.pinned .steps .scene[data-scene] > * {
  opacity: 1;
  transform: none;
  transition: transform 0.7s cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* Le temps de la mesure (site.js), rien n'est décalé : on lit la vraie hauteur de chaque scène. */
.how.is-measuring .scene > * {
  transform: none !important;
  transition: none !important;
}

.pinned .scene:not(.is-active) .scene-num { transform: translateY(20%); }
.pinned .scene:not(.is-active) .scene-text { transform: translateY(26px); }
.pinned .scene:not(.is-active) .demo { transform: translateY(44px); }
.pinned .scene.is-past .scene-num { transform: translateY(-20%); }
.pinned .scene.is-past .scene-text { transform: translateY(-26px); }
.pinned .scene.is-past .demo { transform: translateY(-44px); }

/* ---------- Pages secondaires ---------- */

.back {
  padding-top: 28px;
}

.back a {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--dim);
  font-size: 1.25rem;
  line-height: 1;
  text-decoration: none;
}

.back a:hover {
  color: var(--text);
}

.back-mark {
  color: var(--text);
  font-family: var(--display);
  font-weight: 300;
  font-size: 1.75rem;
  line-height: 1;
  letter-spacing: -0.02em;
}

.page {
  padding-top: clamp(40px, 9vw, 96px);
  padding-bottom: clamp(40px, 9vw, 72px);
}

.page h1 {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(2.75rem, 1.6rem + 5.6vw, 5rem);
  line-height: 1;
  letter-spacing: -0.02em;
  margin-bottom: clamp(24px, 5vw, 44px);
  text-wrap: balance;
}

.prose {
  max-width: 36em;
}

.prose > * + * {
  margin-top: 18px;
}

.prose .lede {
  font-size: clamp(1.1875rem, 3vw, 1.375rem);
  line-height: 1.45;
}

.prose .muted {
  color: var(--dim);
}

.contact {
  border-top: 1px solid var(--line);
  margin-top: 28px;
}

.contact li {
  padding-block: 16px;
  border-bottom: 1px solid var(--line);
  color: var(--dim);
}

.contact a {
  font-weight: 500;
  overflow-wrap: anywhere;
}

.contact + p {
  margin-top: 28px;
}

.chapter {
  max-width: 36em;
  padding-block: 28px;
  border-top: 1px solid var(--line);
}

.chapter:last-of-type {
  padding-bottom: 0;
}

.chapter h2 {
  font-family: var(--display);
  font-weight: 300;
  font-size: 1.625rem;
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin-bottom: 12px;
}

.chapter p {
  color: var(--dim);
}

.chapter p + p,
.chapter ol + p {
  margin-top: 12px;
}

.chapter .strong {
  color: var(--text);
}

/* Pages légales (legal/, servies à la racine à côté de ce fichier) : même nuit, même lettre que le
   site, mais un document se lit — puces, numéros, tableaux et encadrés reviennent. Le texte
   courant est en --dim, ce qui compte (strong, liens) en --text : le relief du texte fait la lecture. */
.legal {
  max-width: 40em;
}

.legal .meta {
  color: var(--dim2);
  font-size: 0.9375rem;
}

.legal p,
.legal li,
.legal td {
  color: var(--dim);
}

.legal strong {
  color: var(--text);
  font-weight: 500;
}

.legal h2 {
  font-family: var(--display);
  font-weight: 300;
  font-size: 1.625rem;
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin-top: 44px;
  text-wrap: balance;
}

.legal h3 {
  margin-top: 24px;
  font-size: 1rem;
  font-weight: 500;
}

.legal h2 + *,
.legal h3 + * {
  margin-top: 12px;
}

.legal ul,
.legal ol {
  padding-left: 1.4em;
}

.legal ul {
  list-style: disc;
}

.legal ol {
  list-style: decimal;
}

.legal li::marker {
  color: var(--primary);
}

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

.legal .card,
.legal .key {
  padding: 18px 20px;
  border: 1px solid var(--line2);
  border-radius: 12px;
  background: var(--detail);
}

.legal .key {
  border-left: 2px solid var(--primary);
}

.legal .card > * + *,
.legal .key > * + * {
  margin-top: 12px;
}

.legal table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9375rem;
}

.legal th,
.legal td {
  padding: 10px 14px 10px 0;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}

.legal th {
  color: var(--dim2);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.legal .todo {
  padding: 1px 8px;
  border: 1px solid var(--primary);
  border-radius: 999px;
  color: var(--primary);
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

.legal .legal-end {
  margin-top: 44px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
  color: var(--dim2);
  font-size: 0.9375rem;
}

.numbered {
  counter-reset: n;
  color: var(--dim);
}

.numbered li {
  counter-increment: n;
  display: grid;
  grid-template-columns: 1.75rem 1fr;
  padding-block: 4px;
}

.numbered li::before {
  content: counter(n) ".";
  color: var(--primary);
  font-variant-numeric: tabular-nums;
}

/* ---------- Pied de page ---------- */

.foot {
  position: relative;
  margin-top: clamp(32px, 8vw, 72px);
  padding-block: 28px 44px;
  color: var(--dim);
  font-size: 0.9375rem;
}

.foot ul {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 22px;
}

.foot a {
  display: inline-block;
  padding-block: 6px; /* cible tactile confortable sans grossir le texte */
  color: var(--dim);
  text-decoration-color: var(--line);
}

.foot a:hover {
  color: var(--text);
}

.foot p {
  margin-top: 18px;
  color: var(--dim2);
}

/* Le final : le nom, une dernière fois, et la porte de lumière qui le traverse au scroll (site.js)
   pour s'arrêter en son centre, comme au début. Dans la porte, le même nom en négatif.
   Sans JS ou en mouvement réduit : la porte est déjà à sa place. */
.finale {
  --fw: clamp(44px, 12cqw, 176px);
  position: relative;
  overflow: hidden;
  container-type: inline-size;
  padding-top: clamp(8px, 3vw, 40px);
}

.foot-mark {
  overflow: hidden;
  height: 0.74em;
  color: var(--surface);
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(6rem, 31vw, 27rem);
  line-height: 0.86;
  letter-spacing: -0.015em;
  text-align: center;
  white-space: nowrap;
  user-select: none;
}

.finale-door {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: var(--fw);
  overflow: hidden;
  background: linear-gradient(180deg, var(--light-1), var(--light-2) 46%, var(--light-3));
  box-shadow: 0 0 clamp(24px, 7cqw, 96px) clamp(2px, 1cqw, 12px) color-mix(in srgb, var(--light-2) 42%, transparent);
  transform: translate3d(var(--fx, calc(50cqw - var(--fw) / 2)), 0, 0);
}

.finale-door .foot-mark {
  width: 100cqw;
  margin-top: clamp(8px, 3vw, 40px);
  color: var(--ink);
  transform: translate3d(calc(-1 * var(--fx, calc(50cqw - var(--fw) / 2))), 0, 0);
}

/* La lueur que la porte jette sur le nom, de part et d'autre. */
.finale::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: calc(var(--fw) * 7);
  pointer-events: none;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--primary) 36%, transparent), color-mix(in srgb, var(--primary) 12%, transparent) 45%, transparent);
  transform: translate3d(calc(var(--fx, calc(50cqw - var(--fw) / 2)) - var(--fw) * 3), 0, 0);
  mix-blend-mode: screen;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .door,
  .hero-copy,
  .haze,
  .spill,
  .rays,
  .letters > span,
  .ticks,
  .ticks > i,
  .bubble.typing > b,
  .code.on .code-slots::after {
    animation: none;
  }

  .btn-primary,
  .waitlist button,
  .lamp,
  .demo *,
  .demo *::before {
    transition: none;
  }
}
