* { box-sizing: border-box; margin: 0; }
@font-face {
  font-family: "Martian Mono";
  src: url("fonts/martian-mono.woff2") format("woff2");
  font-style: normal;
  font-weight: 100 800;
  font-display: swap;
}
html, body { height: 100%; }
/* Distance from the bottom of the window to the title block on desktop.
   The photo credit uses it too, so the two stay aligned. */
:root { --text-bottom: clamp(1.5rem, 6vh, 4.5rem); }
.stage { height: 100%; }
body {
  background: #0b0b0b;
  color: #f2f0ec;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.hero { position: relative; height: 100%; overflow: hidden; }
.hero img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 35%;
  display: block;
}
.hero::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,.85) 0%, rgba(0,0,0,.2) 40%, transparent 60%);
}
.text {
  position: absolute; z-index: 1;
  left: clamp(1.5rem, 5vw, 4.5rem); bottom: var(--text-bottom);
}
h1 {
  font-weight: 300; font-size: clamp(2.2rem, 6vw, 5rem);
  letter-spacing: -.02em; line-height: 1;
  font-family: Inter, sans-serif;
}
h1 b { font-weight: 700; }
p {
  margin-top: 1rem; font-size: .8rem;
  letter-spacing: .3em; text-transform: uppercase; opacity: .75;
  font-family: "Martian Mono", monospace;
}
/* Tagline items are separated by a wide gap instead of commas. Inside an
   item, the space is about half its natural width (a monospace space plus
   letter-spacing reads as a wide gap). A narrow screen wraps between items
   only, and a wrapped line starts flush left. */
.tagline {
  display: flex; flex-wrap: wrap; column-gap: 1.85em;
  letter-spacing: .25em; word-spacing: -.5em;
}
.tagline span { white-space: nowrap; }
.contact {
  position: absolute;
  top: calc(100% + .5rem);
  left: 0;
  width: min(32rem, calc(100vw - 2 * clamp(1.5rem, 5vw, 4.5rem)));
  height: 1rem;
  font-family: "Martian Mono", monospace;
  font-size: .75rem;
  line-height: 1.25;
  letter-spacing: .04em;
}
.contact-link, .contact-retry {
  border: 0;
  color: #c6c4c0;
  text-decoration: none;
  transition: color .2s ease;
}
.contact-link {
  display: inline-block;
  max-width: 100%;
  overflow-wrap: anywhere;
}
.contact[data-state="ready"] .contact-link {
  animation: contact-reveal 1.2s ease both;
}
.contact-retry {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}
.contact-link:hover, .contact-retry:hover { color: #f2f0ec; }
.contact-link:focus-visible, .contact-retry:focus-visible {
  outline: 1px solid currentColor;
  outline-offset: 4px;
}
.contact [hidden] { display: none; }
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
@keyframes contact-reveal {
  from { opacity: 0; }
  to { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .contact[data-state="ready"] .contact-link { animation: none; }
  .contact-link, .contact-retry { transition: none; }
}
@media (max-aspect-ratio: 1/1) {
  .hero { height: 80vh; height: 80svh; }
  .hero img {
    height: 100%;
    object-position: 50% 35%;
    transform: scale(1.06);
  }
  .hero::after {
    background: linear-gradient(to top, rgba(0,0,0,.82) 0%, rgba(0,0,0,.18) 42%, transparent 72%);
  }
  .text {
    left: clamp(1.25rem, 6vw, 2rem);
    bottom: clamp(1.5rem, 7vh, 4rem);
  }
  .contact {
    width: calc(100vw - 2 * clamp(1.25rem, 6vw, 2rem));
  }
}

@media (max-width: 708px) {
  .hero {
    --mobile-photo-height: 60svh;
    height: 100vh;
    height: 100svh;
    background: linear-gradient(to bottom, #0b0b0b 78%, #454440 100%);
  }
  .hero img {
    height: var(--mobile-photo-height);
    object-position: 60% 0%;
    transform: scale(1.01, 1.04);
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 96%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 0%, #000 96%, transparent 100%);
  }
  .hero::after {
    bottom: auto;
    height: calc(var(--mobile-photo-height) + 1rem);
    background: linear-gradient(to top, #0b0b0b 0%, rgba(11,11,11,.82) 10%, rgba(11,11,11,.18) 42%, transparent 72%);
  }
  /* Four scroll sections: photo, Aurelie, Steve, photo again. Each section
     has a snap point with scroll-snap-stop, so an ordinary swipe stops on the
     next section. This is best effort: a hard fling, End key or scrollbar
     drag can still skip one. founders.js reads the section from these markers.
     The tops are 0, 1/3, 2/3 and all of the 240svh scroll range. */
  html { scroll-snap-type: y mandatory; }
  .stage { position: relative; height: 340vh; height: 340svh; }
  .snaps { position: absolute; inset: 0; pointer-events: none; }
  .snaps i {
    position: absolute; left: 0; width: 1px; height: 1px;
    scroll-snap-align: start; scroll-snap-stop: always;
  }
  .snaps i:nth-child(2) { top: 80vh; top: 80svh; }
  .snaps i:nth-child(3) { top: 160vh; top: 160svh; }
  .snaps i:nth-child(4) { top: 240vh; top: 240svh; }
  .hero { position: sticky; top: 0; }
  .text {
    inset: 0;
  }
  .text h1 {
    position: absolute;
    left: clamp(1.25rem, 6vw, 2rem);
    bottom: calc(100svh - var(--mobile-photo-height) + 1rem);
  }
  .text p {
    font-size: clamp(.58rem, 2.5vw, .75rem);
    letter-spacing: .16em; line-height: 1.45;
    margin-top: 0;
  }
  .contact {
    position: static;
    width: auto; height: auto; min-height: 1rem;
    margin-top: .6rem;
  }
}

@media (min-width: 709px) and (min-aspect-ratio: 1/1) {
  .hero img {
    transform: scale(1, 1.04);
  }
}

/* Founder overlays. founders.js sets data-active="av" or "sl" on .hero:
   pointer position on desktop, scroll position on phones. */
.hero {
  --gutter: clamp(1.5rem, 5vw, 4.5rem); --ease-out: cubic-bezier(.2, .7, .2, 1);
  /* Screen position of the line between the founders; founders.js updates it. */
  --split: 50%;
  --dim: rgba(0,0,0,.35);
}
.shade {
  position: absolute; inset: 0; z-index: 1;
  pointer-events: none; opacity: 0;
  transition: opacity .3s ease;
}
/* Each shade darkens the text corner and lightly dims the other founder. */
.shade-av {
  background:
    linear-gradient(to top right, rgba(0,0,0,.82) 0%, rgba(0,0,0,.5) 28%, transparent 55%),
    linear-gradient(to right, transparent calc(var(--split) - 4rem), var(--dim) calc(var(--split) + 4rem));
}
.shade-sl {
  background:
    linear-gradient(to top left, rgba(0,0,0,.82) 0%, rgba(0,0,0,.5) 28%, transparent 55%),
    linear-gradient(to right, var(--dim) calc(var(--split) - 4rem), transparent calc(var(--split) + 4rem));
}
/* Founders share the row above the title, so their text sits at the same height. */
.text {
  z-index: 2; right: var(--gutter);
  display: grid; grid-template-columns: auto 1fr; align-items: end;
}
.text h1 { grid-area: 2 / 1 / 3 / 3; }
.text p { grid-area: 3 / 1 / 4 / 3; }
.founder { outline: none; margin-bottom: clamp(1.25rem, 3vh, 2rem); }
.founder-av { grid-area: 1 / 1; }
.founder-sl { grid-area: 1 / 2; justify-self: end; text-align: right; }
.founder .name {
  font-family: Inter, sans-serif; font-weight: 300;
  font-size: clamp(1.5rem, 2.8vw, 2.6rem);
  letter-spacing: -.02em; line-height: 1.05;
  white-space: nowrap;
  opacity: 0;
  transition: transform .3s ease-in, opacity .25s ease;
}
.founder .name b { font-weight: 700; }
/* Start just past the screen edge on the founder's side. */
.founder-av .name { transform: translateX(calc(-100% - var(--gutter) - 1rem)); }
.founder-sl .name { transform: translateX(calc(100% + var(--gutter) + 1rem)); }
.founder .roles {
  list-style: none; padding: 0;
  margin-top: .75rem;
  font-family: "Martian Mono", monospace;
  font-size: clamp(.62rem, .9vw, .74rem);
  letter-spacing: .25em; text-transform: uppercase;
  line-height: 2;
}
/* letter-spacing leaves a trailing gap; pull right-aligned lines back to the edge. */
.founder-sl .roles li { margin-right: -.25em; }
/* A wider gap between roles than between words. On very narrow screens a
   line breaks between roles, never inside one. */
.founder .roles .role { white-space: nowrap; }
/* A Martian Mono space is a full .7em cell, and letter-spacing adds to it, so
   words inside a role drift apart. Tighten only the spaces inside a role. */
.founder .roles .role { word-spacing: -.5em; }
.founder .roles .role + .role { margin-left: .9em; }
.founder .roles li {
  opacity: 0;
  transition: opacity .2s ease;
}
.founder:focus-visible .name {
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .2em;
}

.hero[data-active="av"] .shade-av,
.hero[data-active="sl"] .shade-sl { opacity: 1; transition: opacity .45s ease; }
.hero[data-active="av"] .founder-av .name,
.hero[data-active="sl"] .founder-sl .name {
  transform: none; opacity: 1;
  transition: transform .6s var(--ease-out), opacity .4s ease;
}
.hero[data-active="av"] .founder-av .roles li,
.hero[data-active="sl"] .founder-sl .roles li {
  opacity: .8;
  transition: opacity .45s ease calc(.25s + var(--i) * .09s);
}

.initials-av, .initials-sl { transition: opacity .4s ease; }
.hero[data-active="av"] .initials-sl,
.hero[data-active="sl"] .initials-av { opacity: .28; }

.scroll-cue { display: none; }

@media (max-width: 708px) {
  .shade { bottom: auto; height: var(--mobile-photo-height); }
  /* Text sits below the photo here, so the shade only dims the other founder. */
  .shade-av { background: linear-gradient(to right, transparent calc(var(--split) - 2.5rem), var(--dim) calc(var(--split) + 2.5rem)); }
  .shade-sl { background: linear-gradient(to right, var(--dim) calc(var(--split) - 2.5rem), transparent calc(var(--split) + 2.5rem)); }
  /* Below the photo, the tagline, contact line and founder text flow in order,
     so a wrapped tagline pushes the rest down. Both founders share the last
     cell and appear one at a time. The title stays absolutely positioned over
     the photo; its grid-area must be auto to keep the whole box as its
     containing block. */
  .text {
    right: 0;
    grid-template-columns: minmax(0, 1fr); align-content: start; align-items: start;
    padding: calc(var(--mobile-photo-height) + 1rem) clamp(1.25rem, 6vw, 2rem) 0;
  }
  .text h1 { grid-area: auto; }
  .text p { grid-area: 1 / 1; }
  .contact { grid-area: 2 / 1; }
  .founder-av, .founder-sl { grid-area: 3 / 1; margin: 1.5rem 0 0; }
  .founder .name { font-size: clamp(1.6rem, 8vw, 2.2rem); }
  .founder .roles { font-size: clamp(.56rem, 2.6vw, .64rem); letter-spacing: .15em; }
  .founder-sl .roles li { margin-right: -.15em; }
  .scroll-cue {
    display: block; position: absolute; z-index: 2;
    /* Raised to clear the photo credit in the bottom-right corner. */
    left: 50%; bottom: 2.75rem; transform: translateX(-50%);
    font-family: "Martian Mono", monospace; font-size: .6rem;
    letter-spacing: .3em; text-transform: uppercase; opacity: .55;
    transition: opacity .3s ease;
  }
  .scroll-cue::after {
    content: ""; display: block; width: 1px; height: 1.5rem;
    margin: .6rem auto 0; background: currentColor;
    animation: cue 1.8s ease-in-out infinite;
  }
  .hero[data-scrolled] .scroll-cue { opacity: 0; }
}
@keyframes cue {
  0%, 100% { transform: scaleY(.3); transform-origin: top; }
  50% { transform: scaleY(1); transform-origin: top; }
}

/* EN | FR switch. The bar between the labels acts like a toggle lever:
   it leans toward the current language and flips toward the one under the
   pointer. */
.lang {
  position: fixed; z-index: 10;
  top: clamp(1rem, 3vh, 2rem); right: clamp(1.5rem, 5vw, 4.5rem);
  display: flex; align-items: center;
  padding: .1rem .2rem;
  border: 1px solid rgba(255,255,255,.28); border-radius: 999px;
  background: rgba(255,255,255,.08);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  font-family: "Martian Mono", monospace; font-size: .68rem;
  letter-spacing: .2em;
  transition: background-color .3s ease, border-color .3s ease;
}
.lang:hover { background: rgba(255,255,255,.14); border-color: rgba(255,255,255,.45); }
.lang button {
  /* Extra left padding balances the trailing letter-spacing. */
  padding: .45rem .55rem .45rem calc(.55rem + .2em);
  border: 0; border-radius: 999px; background: none; cursor: pointer;
  font: inherit; letter-spacing: inherit;
  color: rgba(255,255,255,.5);
  transition: color .25s ease;
}
.lang button[aria-pressed="true"], .lang button:hover { color: #fff; }
.lang button:focus-visible { outline: 1px solid rgba(255,255,255,.8); outline-offset: -2px; }
.lang-bar {
  width: 1px; height: .95rem;
  background: rgba(255,255,255,.55);
  transform: rotate(var(--lean, 0deg));
  transition: transform .5s cubic-bezier(.34, 1.56, .64, 1);
}
.lang:has([data-lang="en"][aria-pressed="true"]) { --lean: -14deg; }
.lang:has([data-lang="fr"][aria-pressed="true"]) { --lean: 14deg; }
.lang:has([data-lang="en"]:hover) { --lean: -24deg; }
.lang:has([data-lang="fr"]:hover) { --lean: 24deg; }
@media (max-width: 708px) {
  .lang { right: clamp(1.25rem, 6vw, 2rem); top: 1rem; }
}

/* Photo credit, fixed above everything in the bottom-right corner: a small
   uppercase label over the name, right-aligned. Plain text with the same
   hover as the language labels; the whole block is one link. */
.credit {
  position: fixed; z-index: 10;
  right: clamp(1.5rem, 5vw, 4.5rem); bottom: clamp(.75rem, 2vh, 1.25rem);
  display: flex; flex-direction: column; align-items: flex-end; gap: .05rem;
  padding: .3rem 0;
  font-family: "Martian Mono", monospace; font-size: .55rem; letter-spacing: .1em;
  /* Monospace spaces plus letter-spacing leave wide gaps between words. */
  word-spacing: -.52em;
  line-height: 1.05;
  color: rgba(255,255,255,.5); text-decoration: none; white-space: nowrap;
  transition: color .25s ease;
}
.credit-label {
  font-size: .48rem; letter-spacing: .25em; text-transform: uppercase;
  /* letter-spacing leaves a trailing gap; pull the line back to the edge. */
  margin-right: -.25em;
}
.credit:hover, .credit:focus-visible { color: #fff; }
.credit:focus-visible { outline: 1px solid rgba(255,255,255,.8); outline-offset: 4px; }
@media (max-width: 708px) {
  .credit { right: clamp(1.25rem, 6vw, 2rem); bottom: .75rem; }
}
/* Landscape desktop: put the credit's last line on the same baseline as the
   contact email, which hangs .5rem below the title block. The 1.625rem offset
   was measured from the email and credit font sizes; recheck it if either
   changes. max() keeps the credit on screen in very short windows. */
@media (min-width: 709px) and (min-aspect-ratio: 1/1) {
  .credit { bottom: max(.25rem, calc(var(--text-bottom) - 1.625rem)); }
}

@media (prefers-reduced-motion: reduce) {
  /* Switch founder states instantly. !important beats the more specific
     active-state rules, including their transition delays. */
  .shade, .founder .name, .founder .roles li, .initials-av, .initials-sl {
    transition: none !important;
  }
  .lang-bar, .credit { transition: none; }
  .founder-av .name, .founder-sl .name { transform: none; }
  .scroll-cue::after { animation: none; }
}
