/*
 * trouvailles.app — the waitlist page.
 *
 * The page is one screen and never scrolls: `.shell` is exactly the viewport
 * tall and clips. Everything below therefore has to earn its height, and the
 * hero's vertical rhythm is scaled on `vh`, not on `vw` — a width-based scale
 * is what pushes the button off the bottom of a short window, and the form
 * being reachable at 540px of height is the acceptance test for this file.
 */

:root {
  --ground: #08301f;
  --ink: #f7f3ea;
  --accent: #e07a2f;
  --accent-hover: #f08a3c;

  /* Only ever inside the phone mock — the page itself has one accent. */
  --app-green: #0a7a4a;
  --app-green-bright: #0fa464;
  --app-ink: #0f172a;
  --app-muted: #94a3b8;
  --app-line: #eef0f6;

  --sans: 'Plus Jakarta Sans Variable', 'Plus Jakarta Sans', system-ui,
    -apple-system, 'Segoe UI', Roboto, sans-serif;
  --serif: 'Newsreader Variable', Newsreader, Georgia, 'Times New Roman', serif;
}

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

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
}

/* `svh` rather than `vh`: on a phone the large viewport is taller than what is
   actually visible while the browser chrome is out, and a page that must not
   scroll cannot afford to be measured against height it does not have. */
.shell {
  height: 100vh;
  height: 100svh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ── Header ───────────────────────────────────────────────────────────────── */

.site-header {
  flex: none;
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  max-width: 1120px;
  margin: 0 auto;
  padding: 22px 32px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
}

.brand-mark {
  width: 42px;
  height: 42px;
  flex: none;
  object-fit: contain;
}

.brand-word {
  font-size: 1.08rem;
  font-weight: 800;
  letter-spacing: 0.08em;
}

.header-spacer {
  flex: 1;
}

.lang-nav {
  display: flex;
  align-items: center;
  gap: 4px;
}

.lang,
.lang-current {
  display: inline-flex;
  align-items: center;
  height: 32px;
  padding: 0 11px;
  border-radius: 9999px;
  font-size: 0.74rem;
  letter-spacing: 0.06em;
  text-decoration: none;
}

.lang-current {
  background: rgba(247, 243, 234, 0.12);
  font-weight: 800;
  color: var(--ink);
}

.lang {
  font-weight: 700;
  color: rgba(247, 243, 234, 0.55);
}

.lang:hover,
.lang:focus-visible {
  color: var(--ink);
}

/* ── Hero ─────────────────────────────────────────────────────────────────── */

/* The row is bounded (`minmax(0, 1fr)`) so the grid can never grow past the
   space the shell gives it — an `auto` row here is what would start a scroll. */
.hero {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
  grid-template-rows: minmax(0, 1fr);
  gap: 56px;
  align-items: center;
  width: 100%;
  max-width: 1120px;
  margin: 0 auto;
  padding: 8px 32px 32px;
}

.hero-copy {
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.kicker {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 0.74rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}

.kicker::before {
  content: '';
  width: 26px;
  height: 2px;
  flex: none;
  background: var(--accent);
}

.hero-h1 {
  margin: clamp(12px, 2.4vh, 22px) 0 0;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.8rem, 4.2vh + 0.9vw, 3.7rem);
  line-height: 0.98;
  letter-spacing: -0.02em;
  text-wrap: pretty;
}

.hero-h1 em {
  font-style: italic;
  color: var(--accent);
}

.hero-desc {
  margin: clamp(10px, 2.2vh, 24px) 0 0;
  max-width: 46ch;
  font-size: clamp(0.86rem, 1.9vh, 1.04rem);
  line-height: 1.55;
  color: rgba(247, 243, 234, 0.72);
  text-wrap: pretty;
}

.hero-desc + .hero-desc {
  margin-top: clamp(8px, 1.4vh, 14px);
}

.hero-compat {
  margin: clamp(10px, 2vh, 20px) 0 0;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 46ch;
  font-size: 0.8rem;
  line-height: 1.4;
  color: rgba(247, 243, 234, 0.78);
}

.hero-compat-icon {
  flex: none;
  width: 15px;
  height: 15px;
  background: rgba(247, 243, 234, 0.78);
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

/* ── Waitlist form ────────────────────────────────────────────────────────── */

.hero-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: clamp(14px, 3vh, 36px);
  max-width: 520px;
}

.wl-input {
  flex: 1;
  min-width: 260px;
  height: 58px;
  padding: 0 22px;
  border-radius: 9999px;
  background: rgba(247, 243, 234, 0.07);
  border: 1px solid rgba(247, 243, 234, 0.16);
  font: inherit;
  font-size: 0.92rem;
  color: var(--ink);
}

.wl-input::placeholder {
  color: rgba(247, 243, 234, 0.45);
}

.wl-input:focus {
  outline: none;
  border-color: var(--accent);
}

.wl-btn {
  height: 58px;
  padding: 0 28px;
  border: none;
  border-radius: 9999px;
  background: var(--accent);
  font: inherit;
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--ground);
  cursor: pointer;
}

.wl-btn:hover {
  background: var(--accent-hover);
}

.wl-btn:disabled {
  opacity: 0.6;
  cursor: default;
}

/* The honeypot. Off-screen rather than `display:none`, which some form fillers
   read as "skip me"; `tabindex="-1"` and `aria-hidden` keep it away from
   anyone navigating by keyboard or screen reader. */
.wl-trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* Replaces the form in place — there is no app shell here to hang a snackbar
   off, and the confirmation has to land where the eye already is.
   `:target` is what makes that work with JavaScript off: the API redirects a
   plain form post back to `#wl-ok` or `#wl-error`, the matching paragraph
   appears, and `:has()` takes the form away. The script path sets `hidden`
   instead and never touches the fragment. */
/* `.wl-status` below sets `display:flex`, which is a class selector and so
   outranks the user agent's `[hidden] { display: none }` — without this line
   both messages take up space on a page that has none to spare. */
.wl-status[hidden] {
  display: none;
}

.wl-status:target {
  display: flex;
}

.hero-copy:has(.wl-status:target) .hero-form {
  display: none;
}

.wl-status {
  margin-top: clamp(14px, 3vh, 36px);
  max-width: 520px;
  min-height: 58px;
  display: flex;
  align-items: center;
  padding: 16px 22px;
  border-radius: 18px;
  font-size: 0.92rem;
  line-height: 1.45;
}

.wl-status--ok {
  background: rgba(15, 164, 100, 0.14);
  border: 1px solid rgba(15, 164, 100, 0.4);
  color: var(--ink);
}

.wl-status--error {
  background: rgba(224, 122, 47, 0.12);
  border: 1px solid rgba(224, 122, 47, 0.45);
  color: var(--ink);
}

/* 62 % d'encre, et pas moins : c'est le plancher qui tient 4.5:1 sur le vert
   du fond. À 40 %, où cette ligne était, elle tombait sous 3:1 — et c'est la
   ligne qui dit à quoi on s'engage en laissant son adresse, donc celle qu'on
   peut le moins se permettre de rendre illisible. `check.mjs` mesure le
   rapport et échoue s'il redescend. */
.hero-note {
  margin: 12px 0 0;
  font-size: 0.76rem;
  color: rgba(247, 243, 234, 0.62);
}

/* ── The phone mock — the real « Mes espèces » screen, decorative ─────────── */

.hero-mock {
  min-height: 0;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.phone {
  width: 300px;
  flex: none;
  aspect-ratio: 9 / 19.6;
  padding: 11px;
  border-radius: 44px;
  background: #04190f;
  box-shadow:
    0 30px 70px rgba(4, 25, 15, 0.6),
    inset 0 0 0 1px rgba(247, 243, 234, 0.12);
}

.screen {
  height: 100%;
  display: flex;
  flex-direction: column;
  border-radius: 34px;
  overflow: hidden;
  background: #f6f7fb;
  color: var(--app-ink);
}

.screen-title-band {
  flex: none;
  padding: 20px 16px 6px;
  background: #fff;
}

.screen-title {
  margin: 0;
  font-size: 1.32rem;
  font-weight: 800;
  letter-spacing: -0.02em;
}

/* Four rows of ~119px inside roughly 504px. Anything added to the screen's
   chrome above or below comes straight out of the captions. */
.screen-grid {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  /* Quatre lignes égales, bornées : `align-content:start` laissait chaque
     ligne prendre la hauteur de son contenu, si bien qu'une carte portant une
     photographie plus haute que les autres décalait tout ce qui suit. */
  grid-auto-rows: minmax(0, 1fr);
  gap: 8px;
  padding: 14px 14px 8px;
  overflow: hidden;
}

.sp-card {
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid var(--app-line);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.05);
}

/* Landscape, because that is how the app stores photographs. */
.sp-media {
  position: relative;
  flex: none;
  width: 100%;
  aspect-ratio: 16 / 9;
  min-height: 0;
  overflow: hidden;
  background: linear-gradient(160deg, #eef7f1, #f7f4ec);
}

.sp-media--photo {
  background: #eef2f8;
}

/* Hors du flux : une image encore en cours de chargement n'a pas de hauteur
   que la boîte puisse honorer, la carte se rétracte, et la légende dessous se
   fait rogner. `object-position` est posé par carte, dans `mock.css` que génère
   `build.mjs` — le cadrage d'une photographie ne se devine pas d'ici. */
.sp-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}

.sp-silhouette {
  position: absolute;
  inset: 8px 16px;
  background-position: center;
  background-size: contain;
  background-repeat: no-repeat;
  opacity: 0.6;
}

.sp-caption {
  flex: none;
  padding: 7px 8px 8px;
}

.sp-name,
.sp-latin {
  margin: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sp-name {
  font-size: 0.75rem;
  font-weight: 800;
}

.sp-latin {
  margin-top: 2px;
  font-family: var(--serif);
  font-size: 0.68rem;
  font-style: italic;
  color: var(--app-muted);
}

.screen-nav {
  flex: none;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: 9px 16px 20px;
  background: #fff;
  border-top: 1px solid var(--app-line);
}

.nav-item {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
}

.nav-icon {
  width: 19px;
  height: 19px;
  background: var(--app-muted);
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

.nav-label {
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 0.46rem;
  font-weight: 700;
  color: var(--app-muted);
}

/* The icon is a mask over a solid fill, so its colour is a background; the
   label's is a text colour. Setting both on one rule painted the label green
   on green. */
.nav-item--active .nav-icon {
  background-color: var(--app-green);
}

.nav-item--active .nav-label {
  color: var(--app-green);
}

.nav-fab {
  width: 46px;
  height: 46px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  background: var(--app-green-bright);
  box-shadow: 0 6px 16px rgba(15, 164, 100, 0.35);
  margin-top: -16px;
}

.nav-fab .nav-icon {
  width: 20px;
  height: 20px;
  background: #fff;
}

/* ── Breakpoints ──────────────────────────────────────────────────────────── */

/* The mock is the first thing to go, in both directions. A 300 × 653 phone does
   not fit under either threshold, and the page's job is the sentence and the
   form — those get the full width instead. */
@media (max-height: 790px) {
  .hero {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
  }

  .hero-mock {
    display: none;
  }
}

@media (max-width: 900px) {
  .hero {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto;
    gap: 0;
    padding: 8px 22px 24px;
  }

  .hero-mock {
    display: none;
  }

  .site-header {
    padding: 18px 22px;
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
    animation: none !important;
  }
}

/* Narrow phones: the header is the one row that cannot wrap without eating
   height the hero needs, so the brand and the four language pills give up size
   instead. Measured down to 320px — see landing/check.mjs, which fails the
   build if either overflows. */
@media (max-width: 560px) {
  .site-header {
    padding: 14px 18px;
  }

  .brand-mark {
    width: 34px;
    height: 34px;
  }

  .brand-word {
    font-size: 0.95rem;
    letter-spacing: 0.04em;
  }

  .lang-nav {
    gap: 2px;
  }

  .lang,
  .lang-current {
    height: 28px;
    padding: 0 8px;
    font-size: 0.68rem;
    letter-spacing: 0.04em;
  }
}

@media (max-width: 400px) {
  .site-header {
    padding: 14px 14px;
  }

  .brand {
    gap: 7px;
  }

  .brand-word {
    font-size: 0.86rem;
    letter-spacing: 0.02em;
  }

  .lang,
  .lang-current {
    padding: 0 6px;
    font-size: 0.64rem;
  }

  /* At 320 x 568 with the German copy — the longest of the four — the clamps
     above still leave the note hanging 13px below the fold. The floor of the
     body scale drops here rather than everywhere, so the wider phones keep the
     size they read best at. */
  .hero-desc {
    font-size: clamp(0.8rem, 1.8vh, 0.95rem);
    line-height: 1.5;
  }

  .hero-form {
    margin-top: clamp(12px, 2.4vh, 24px);
  }

  .hero-note {
    font-size: 0.72rem;
  }

  .hero-compat {
    font-size: 0.72rem;
  }
}

/* Below this, even one line of the compat badge wrapping to two on a narrow
   phone pushes the note under the fold — same trade the mock already makes at
   max-height: 790px, dropped here because unlike the mock this line still
   reads fine as plain sign-up copy without it.
   620 and not 600: at 320px wide the German copy wraps far enough that the
   note still landed a few pixels under the fold between 601 and 609. The band
   is narrow, which is exactly why it needed measuring — `check.mjs` now pins
   both of its edges. */
@media (max-height: 620px) {
  .hero-compat {
    display: none;
  }
}
