/* ------------------------------------------------------------- landing v2 --
 * The waitlist page's own sheet: same product and same demo as the design it
 * replaced, different argument about how to sell it. Loaded *after* styles.css
 * and only over index.html. (The name is historical — this was the second of
 * two designs, and it is the one that shipped. landing-v1.html is the other.)
 *
 * v1 is the app's own design system turned into a web page: light by default,
 * a contained column, system greys, the accent spent sparingly. It reads as
 * honest and quiet, which is what it is.
 *
 * This one reads as the product instead. Music discovery is a thing you do at
 * night, on a phone, looking at album art — so the page is dark, the phone is
 * the centrepiece rather than an illustration beside the copy, and the artwork's
 * own colour is allowed to light the room. Everything is centred and stacked:
 * a poster, not a brochure.
 *
 * What it does NOT change is the demo. The deck, the five screens, the signup
 * field and the success card are the same markup as v1, lifted whole, so a fix
 * to any of them lands on both pages. Only the room around them is new.
 */

/* Dark by art direction, not by preference: this page has no theme switch, so
   the palette is declared here rather than left to [data-theme]. Violet-tinted
   rather than the app's true black, which is what separates it at a glance from
   v1 in dark mode. */
body.v2 {
  color-scheme: dark;

  /* Stated once and spent twice: the bar is this tall, and the hero is a
     viewport minus the bar. The two have to agree — see .v2-hero. */
  --nav-h: 68px;

  --bg: #07060c;
  --bg-0: rgba(7, 6, 12, 0);
  --bg-blur: rgba(10, 9, 18, 0.72);
  --surface: #131120;
  --surface-2: #1c1a2e;
  --text: #ffffff;
  --text-dim: rgba(235, 235, 245, 0.62);
  --text-faint: rgba(235, 235, 245, 0.38);
  --separator: rgba(255, 255, 255, 0.14);
  --hairline: rgba(255, 255, 255, 0.1);
  --chip-fill: rgba(255, 255, 255, 0.1);
  --accent-wash: rgba(97, 85, 245, 0.18);
  --post-scrim: rgba(0, 0, 0, 0.4);
  --rating-empty: rgba(255, 255, 255, 0.24);
  --btn: #f5f5f5;
  --btn-fg: #12101c;
  --lift: none;

  background: var(--bg);
  color: var(--text);
}

/* The aurora. Two soft accent fields, fixed, sitting under everything — the
   page's only ornament and the reason a black page doesn't read as an empty
   one. Fixed rather than scrolled so the light stays put and the content moves
   through it. */
.v2-aurora {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(70% 55% at 50% -10%, rgba(97, 85, 245, 0.3), transparent 70%),
    radial-gradient(50% 40% at 88% 22%, rgba(168, 85, 247, 0.16), transparent 70%),
    radial-gradient(45% 35% at 8% 42%, rgba(14, 165, 233, 0.1), transparent 70%);
}

.v2-wrap { max-width: 1120px; margin: 0 auto; padding: 0 24px; }

/* -- Nav ------------------------------------------------------------------- */
.v2-nav {
  position: sticky;
  top: 0;
  z-index: 50;
  border-bottom: 1px solid transparent;
  transition: background 0.25s, border-color 0.25s, backdrop-filter 0.25s;
}
.v2-nav.is-stuck {
  background: var(--bg-blur);
  -webkit-backdrop-filter: var(--glass);
  backdrop-filter: var(--glass);
  border-bottom-color: var(--hairline);
}
/* A stated height rather than padding around whatever the brand happens to
   measure, because the hero subtracts this number and the two drifting apart is
   what puts the phone back in the corner. */
.v2-nav .v2-wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--nav-h);
}

/* The bar's right-hand end: the language button, and the ask when it is up. */
.nav-actions { display: inline-flex; align-items: center; gap: 10px; }

/* -- The language picker --------------------------------------------------- */
/* Quiet, and next to the ask rather than in the footer: a visitor who can't read
   the page has to be able to find the way out of it from the first screen, and
   the footer is six thousand pixels away.

   A <select> wearing the ask's shape at the ask's height, so the pair reads as
   one control group, and none of its colour: the accent belongs to the thing the
   page wants pressed. appearance: none takes the platform's own well off it; the
   chevron below is put back by hand, and it is chevron.down's own path from the
   sprite in index.html rather than a second arrow that nearly matches.

   The closed control sizes itself to the longest name in the list, so the row
   does not move when the reader changes language. That is worth more here than
   the twenty pixels a fixed width would save: the ask sits immediately beside
   it.

   color-scheme is the whole reason the open list looks like it belongs to this
   page. Without it the browser draws the menu on white — the one part of this
   control the page does not get to style, handed the wrong palette.

   [hidden] said out loud for the same reason .nav-cta says it — i18n.js unhides
   this once it is ready to answer, and the author display above would otherwise
   beat the UA stylesheet's. */
.lang-select[hidden] { display: none; }
.lang-select {
  display: inline-flex;
  align-items: center;
  height: 34px;
  padding: 0 30px 0 13px;
  border: none;
  box-shadow: inset 0 0 0 1px var(--separator);
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.06);
  color: var(--text-dim);
  color-scheme: dark;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 34px;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M4.4 8.35 12 16.45l7.6-8.1' fill='none' stroke='%23fff' stroke-opacity='.6' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 13px 13px;
  transition: color var(--t-press), background-color var(--t-press);
}
.lang-select:hover { color: var(--text); background-color: rgba(255, 255, 255, 0.1); }
.lang-select:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 1px var(--separator), 0 0 0 3px var(--bg), 0 0 0 5px var(--accent);
}
/* Firefox draws the options with the control's own colours, and --text-dim on a
   dark menu is the one place this control is read rather than glanced at. */
.lang-select option { color: var(--text); background: var(--bg); }

/* -- The travelling mark --------------------------------------------------- */
/* One logo for the whole page. It starts large and centred in the hero and ends
   in the bar's brand slot, and the flight between the two is the page's scroll.
   Two logos cross-fading would have been easier and reads as two logos; this is
   the same object moving, which is the point.

   Fixed to the viewport because it has to leave the hero to land in a bar that
   is itself fixed there. Positioned by transform only — width and height are
   written too, but the movement is one composited property. */
.flying-mark {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 60;
  filter: drop-shadow(0 4px 14px rgba(0, 0, 0, 0.35));
  will-change: transform;
  pointer-events: none;
}
/* The hero's copy of the slot: reserves the space and nothing else. */
.hero-mark {
  width: 76px;
  height: 76px;
  margin: 0 auto 26px;
}
.hero-mark > i { display: none; }
/* The bar's. Sized to the icon the mark shrinks to, so the row's layout is
   settled before the mark ever arrives. */
.brand-slot { display: block; width: 30px; height: 30px; flex-shrink: 0; }
.brand-slot > i { display: none; }
/* The wordmark arrives with the mark rather than sitting in an empty bar.
   Everything about how it is *set* is in styles.css with the face itself,
   because the privacy page and v1 carry the same bar and want the same
   wordmark; only its arrival belongs to this page. */
.v2-nav .brand-name { opacity: var(--mark-landed, 0); transition: opacity 0.2s var(--ease-out); }

/* Nothing flies. The logo simply sits in both places, which is what those two
   boxes were reserving all along. */
@media (prefers-reduced-motion: reduce) {
  .flying-mark { display: none; }
  .hero-mark > i,
  .brand-slot > i { display: block; width: 100%; height: 100%; }
  .v2-nav .brand-name { opacity: 1; }
}

/* -- Hero ------------------------------------------------------------------ */
/* Centred and stacked: eyebrow, headline, one line of prose, the field. v1 puts
   the copy in a column beside the phone; here it is a poster and the phone is
   what you see when you look past it. */
/* One viewport exactly, less the bar above it, with the poster centred in what
   that leaves. The height is the point: the hero used to end wherever its copy
   ran out, which left a band of nothing under the field and then the top corner
   of the phone poking into the bottom right of the screen — a device cropped by
   the fold on the side it doesn't sit on, which reads as a rendering fault
   rather than as something to scroll towards. Ending the hero *at* the fold puts
   the reel's first frame cleanly below it, and the phone rises into an empty
   stage instead of arriving already half cut off.

   svh, not vh: on a phone vh is the toolbar-hidden height, so a hero sized in it
   overflows the screen you actually get on arrival. The vh line above is for
   anything that doesn't know the newer unit. Padding stays as the floor for
   viewports too short to centre in. */
.v2-hero {
  position: relative;
  text-align: center;
  min-height: calc(100vh - var(--nav-h));
  min-height: calc(100svh - var(--nav-h));
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: clamp(40px, 6vw, 72px) 0;
}

/* The scroll cue, at the bottom of the hero and out of the flow — in it, it
   would push the poster off centre to make room for itself.

   It bobs rather than sits still. A static arrow on a page that fills the screen
   exactly reads as decoration; the movement is the whole of what makes it an
   instruction. The travel is small and the cycle slow, because this has to
   survive being looked at for as long as somebody reads the headline above it.

   The transform is spent on centring, so the bob is on the glyph inside — two
   transforms on one element and the animation would win the centring too. */
.v2-scroll-cue {
  position: absolute;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%);
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  /* --text-dim, not --text-faint. Faint is 0.38 alpha and the bob takes it to
     0.27 at the bottom of the cycle, which on this background is a smudge — and
     a signal nobody registers is not a signal. Semibold for the same reason:
     the arrow is 22px of mostly one thin line. */
  color: var(--text-dim);
  transition: color 0.2s var(--ease-out);
}
.v2-scroll-cue:hover,
.v2-scroll-cue:focus-visible { color: var(--text); }
.v2-scroll-cue svg { width: 22px; height: 22px; }

@media (prefers-reduced-motion: no-preference) {
  .v2-scroll-cue svg { animation: v2-cue-bob 2.4s ease-in-out infinite; }
}
@keyframes v2-cue-bob {
  0%, 100% { transform: translateY(0); opacity: 0.7; }
  50% { transform: translateY(7px); opacity: 1; }
}

/* Below the fold on a viewport too short to centre the poster in: the hero has
   grown past one screen by then, so an arrow pinned to its bottom edge is
   pointing at something from a place nobody can see. The page scrolls on its
   own evidence at that height — the copy is already cut off. */
@media (max-height: 620px) {
  .v2-scroll-cue { display: none; }
}
.v2-eyebrow {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 22px;
}
/* The one piece of type on the page allowed to be loud. */
.v2-title {
  font-size: clamp(40px, 6.6vw, 78px);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -0.035em;
  margin: 0 auto 24px;
  max-width: 14ch;
  text-wrap: balance;
}
.v2-title span { color: var(--text-dim); }
/* The last sentence is the promise, so it wears the brand's colour. */
.v2-title .tog { color: var(--accent); }
.v2-sub {
  font-size: clamp(16px, 1.6vw, 19px);
  line-height: 1.5;
  color: var(--text-dim);
  max-width: 60ch;
  margin: 0 auto clamp(28px, 4vw, 40px);
  text-wrap: pretty;
}

/* The field, centred and given the room a hero field wants. Scoped to the page
   rather than to the hero because the closing band asks the same question in the
   same shape, and the two asks should not be two designs. */
.v2 .form { display: flex; flex-direction: column; align-items: center; margin-bottom: 0; }
/* [hidden] needs saying out loud, the way styles.css says it for .success-card
   and .nav-cta: app.js hides a form by setting the attribute, and the author
   `display` on the line above beats the UA stylesheet's `display: none`. Without
   this the confirmation card arrives *underneath* a field still asking to be
   filled in, and the page congratulates and solicits in the same breath. */
.v2 .form[hidden] { display: none; }
.v2 .field { width: 100%; max-width: 470px; background: rgba(255, 255, 255, 0.06); border-color: var(--separator); }
.v2 .field:focus-within { border-color: rgba(255, 255, 255, 0.5); }
.v2 .form-msg,
.v2 .reassure { text-align: center; }
.v2 .success-card { margin: 0 auto; }

/* -- The reel -------------------------------------------------------------- */
/* The scroll-driven demonstration. The track is tall — that height is the length
   of the tour — and the stage inside it sticks, so the page scrolls past a phone
   that stays put. landing-v2.js sets --turn, --rise and --grow as you go, and
   swaps the screen at each step.

   The phone runs at natural scale here rather than v1's 0.85: it is the subject
   rather than a sample, and at 1:1 the deck's drag needs no compensation. */
/* `clip`, not `hidden`: the phone's glow is deliberately wider than the phone
   and on a narrow screen it reached 116px past the column, which the document
   answered with a horizontal scrollbar. `hidden` would fix that and break the
   stage inside — a sticky element sticks within its nearest scroll container,
   and `hidden` would make this section one. `clip` clips without becoming a
   scrollport, so the glow stops at the screen edge and the stage still sticks
   to the viewport. */
/* The track's height IS the pace of the demonstration: landing-v2.js divides
   (height - viewport) by the five steps, so this number alone decides how far
   you scroll per screen. At 460vh that was 72vh a screen — under one flick on a
   trackpad, which meant an ordinary scroll went straight past two or three of
   them and the reel read as a flicker rather than a walkthrough. 760 puts each
   screen at about 1.3 viewports, so every one of them has to be scrolled to and
   arrives on its own. */
.v2-reel { position: relative; height: 760vh; overflow-x: clip; }
.v2-reel-stage {
  position: sticky;
  top: 0;
  /* svh, for the reason the hero says it: on a phone vh is the height the
     screen has once the browser's own toolbar has scrolled away, and the
     toolbar is showing for most of the way down this reel. The stage is where
     the caption sits — at the bottom of it, under the phone — so a stage sized
     in vh puts the last line of every caption behind the toolbar. The vh line
     above it is for anything that doesn't know the newer unit.

     landing-v2.js measures this element rather than the window now, so the two
     agree whatever unit is in force here. */
  height: 100vh;
  height: 100svh;
  display: grid;
  /* The phone's track is stated, not `auto`. An auto track sizes to its item
     and the item's width is a percentage of the track, which is circular: the
     panel collapsed to 278 and rendered at 0.37 where a phone is 0.46.
     395 is the panel's own width, drawn at 1px = 1pt like everything in it.

     Stated *times the scale*, though, because `zoom` shrinks the phone's layout
     box along with its paint: a fixed 395 track held a 324px phone at 0.82 and
     left 71px of dead gap beside it, widening as the phone got smaller. This is
     not the circularity above — that was an `auto` track sizing to a percentage
     item. Here the track is definite before the item is laid out, the percentage
     resolves against it in the containing block's own space, and `zoom` scales
     the result. One pass, no feedback. */
  grid-template-columns: minmax(0, 1fr) calc(395px * var(--phone-fit, 1));
  align-items: center;
  /* Named, because the caption's column has to subtract it too — see the
     padding on .v2-reel-copy. */
  --reel-gap: clamp(32px, 6vw, 96px);
  gap: var(--reel-gap);
  max-width: 1120px;
  margin: 0 auto;
  /* The top inset keeps the phone clear of the bar, which is sticky too and sits
     over this; the bottom one holds the caption, which now hangs out of the
     phone's flow. One shorthand, not a longhand a later shorthand resets.

     48 + 40 rather than 72 + 0: the phone is 92pt taller than it was, and these
     two are exactly the 88 that fit() in landing-v2.js reserves — every pixel
     here is a pixel the phone can't have, so the two have to agree. Change one,
     change the other. */
  padding: 48px 24px 40px;
  /* The turn is a real rotation, so the stage needs somewhere to rotate in. */
  perspective: 1600px;
}

/* The captions. All five are laid on top of each other in one grid cell and the
   current one is faded up, so the block never changes height and the phone never
   moves because a sentence got longer. */
.v2-reel-copy {
  display: grid;
  /* Room for the second phone, which reaches back into this column.
     .v2-reel-aside is absolute to the phone's column at right: 100% and tucked
     168 behind it, so what sticks out to the left of the gap is over the
     caption — and it is drawn after the caption, so it is over it in the other
     sense too. A sentence that ran into it lost its last word behind glass.

     The reach: 395 wide and 854 tall at 0.84 of the phone's own scale, less the
     168 it is tucked by, plus what turning it 5 degrees adds — half the height
     times sin 5°, on this side. Written out rather than as one number so it
     stays true if the aside's scale or angle change. 16 more keeps the words off
     the glass, and max() means a viewport where the phone is small enough not to
     reach at all gives the column its full width back.

     Reserved on every step rather than only on the one that draws the aside:
     these five captions share one box, so a width that changed with the step
     would re-wrap all five and re-measure the phone, mid-scroll. */
  padding-right: max(
    0px,
    calc(
      (395px * 0.84 + 854px * 0.84 * 0.0872 / 2) * var(--phone-fit, 1) - 168px -
        var(--reel-gap, 0px) + 16px
    )
  );
}
.v2-reel-kicker {
  grid-area: 1 / 1;
  align-self: start;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--accent);
  transform: translateY(-96px);
}
.v2-reel-step {
  grid-area: 1 / 1;
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.45s var(--ease-out), transform 0.45s var(--ease-out);
  pointer-events: none;
}
.v2-reel-step.is-on { opacity: 1; transform: none; }
/* The caption grows further than it used to on a wide screen. Both clamps used
   to cap around a 1300px viewport — 44 and 18 — and everything past that got a
   bigger phone beside type that had stopped growing, in a column that is nearly
   700px wide at 1920 and was carrying one short line across the middle of it.
   The stage is capped at 1120 and the copy takes what the phone doesn't, so
   there is no width here to run out of; these cap where the column would start
   taking a third line rather than where the viewport ends.

   Only over 900px. Stacked, the caption sits under the phone and competes with
   it for one screen's height — see the override at the bottom of this file. */
.v2-reel-step b {
  display: block;
  font-size: clamp(26px, 3.6vw, 60px);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.03em;
  margin-bottom: 14px;
  text-wrap: balance;
}
.v2-reel-step span {
  display: block;
  font-size: clamp(15px, 1.6vw, 23px);
  line-height: 1.55;
  color: var(--text-dim);
  max-width: 40ch;
  text-wrap: pretty;
}

/* The phone, and the light it stands in. */
.v2-reel-phone { position: relative; display: flex; justify-content: center; width: 100%; }
.v2-reel-phone::before {
  content: "";
  position: absolute;
  inset: -12% -34%;
  background: radial-gradient(closest-side, rgba(97, 85, 245, 0.36), transparent);
  filter: blur(14px);
  pointer-events: none;
}
/* A definite width, which the phone needs and this layout doesn't otherwise
   give it. Every step from .hero-demo down is `width: 100%` against a parent
   that is itself auto — on v1 the demo sits in a grid track, so those
   percentages have something to resolve against; centred in a flex row here
   they have nothing, and the panel collapsed to its own content at 256. */
.v2-reel-phone .hero-demo { position: relative; width: 100%; }
.v2-reel-phone .appview { --phone-scale: var(--phone-fit, 1); }
.v2-reel-phone .phone {
  transform: rotateY(var(--turn, 0deg)) translateY(var(--rise, 0px)) scale(var(--grow, 1));
  transform-origin: 50% 55%;
  box-shadow: 0 40px 90px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(255, 255, 255, 0.06);
  will-change: transform;
}
/* Only while it is actually moving. A card you can't drag straight is worse
   than one you can't drag at all, and mid-turn the cursor and the card no
   longer agree about distance. */
.v2-reel-stage.is-turning .phone { pointer-events: none; }
/* -- The second phone ------------------------------------------------------ */
/* Aya's handset, behind and to the left of the one the reel is driving, and only
   while the chat step is on screen. It is the one step whose subject is two
   people rather than one, and a single phone can only ever show half of that.
   Everything else on this page argues the app is worth having; this argues
   somebody is on the other end of it.

   Absolute, so it costs the layout nothing and fit() keeps budgeting for one
   phone. Scaled with the same --phone-fit the real one uses, times its own 0.84,
   so the pair keeps its relationship at every viewport height. */
.v2-reel-aside {
  position: absolute;
  top: 50%;
  right: 100%;
  z-index: 0;
  /* Stated, not shrink-to-fit. .phone is `width: 100%; max-width: 395px`, and a
     percentage against an auto-width absolute parent is the same circular
     measurement that collapsed the near phone to 256 — see .v2-reel-phone
     .hero-demo. Here it collapsed the whole handset to a sliver. */
  width: 395px;
  margin-right: -168px;                       /* tucked behind the near phone */
  transform-origin: 100% 50%;
  transform: translateY(-50%) scale(calc(var(--phone-fit, 1) * 0.84)) rotate(-5deg) translateX(48px);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-out), visibility 0s linear 0.5s;
}
.v2-reel-stage.is-duo .v2-reel-aside {
  opacity: 1;
  visibility: visible;
  transform: translateY(-50%) scale(calc(var(--phone-fit, 1) * 0.84)) rotate(-5deg) translateX(0);
  transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-out), visibility 0s;
}
/* -- Whose phone is whose ---------------------------------------------------
 * Two handsets running the same screen is the one picture that cannot caption
 * itself: identical layout, identical sleeve, and the only difference is which
 * name is in the sentence. So each says who is holding it, out loud, on the
 * device rather than in it — page chrome, in the page's own type, so it never
 * reads as something the app draws.
 *
 * They straddle the phone's top edge. There is no reliable room above a phone
 * that is fitted to the viewport — fit() sizes it to consume exactly what is
 * there — but the top 22 of the screen is empty by design (see --safe-top), so
 * half on and half off costs nothing either way.
 *
 * They splay outward, away from where the two phones overlap: the near one's
 * tag to its right, the far one's to its left, so neither sits in the seam.
 */
.v2-phone-tag {
  position: absolute;
  top: -14px;
  z-index: 4;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 14px 5px 5px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
  color: var(--text);
  background: var(--bg-blur);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  backdrop-filter: saturate(180%) blur(18px);
  box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.14), 0 8px 22px rgba(0, 0, 0, 0.5);
  /* In step with the phone they name — see .v2-reel-stage.is-duo below. */
  opacity: 0;
  visibility: hidden;
  transform: translateY(6px);
  transition: opacity 0.45s var(--ease-out), transform 0.45s var(--ease-out),
    visibility 0s linear 0.45s;
}
.v2-phone-tag.is-you { right: 14px; }
.v2-phone-tag.is-them { left: 14px; }
.v2-reel-stage.is-duo .v2-phone-tag {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition: opacity 0.45s var(--ease-out) 0.12s, transform 0.45s var(--ease-out) 0.12s,
    visibility 0s;
}
/* The far tag rides with its phone, so it takes the same scale and tilt. */
.v2-reel-aside .v2-phone-tag { top: -18px; }

/* Held back from the near phone so the eye still knows which one it is reading:
   a shade darker, and the glow it would otherwise cast is the near phone's job. */
.phone-aside {
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.05);
  filter: brightness(0.78) saturate(0.9);
}
/* Under 1180 the copy column has no room to give: the aside would sit on top of
   the caption rather than beside it, so it stands down and the step goes back to
   one phone. */
@media (max-width: 1180px) {
  .v2-reel-aside { display: none; }
}

/* Out of the phone's flow. It is Apple's attribution, so it stays on the page and
   stays legible, but 46px of it under an 852pt panel was costing about five
   points of scale on every viewport — and at these type sizes the scale is what
   legibility rides on. Absolute, so fit() in landing-v2.js budgets for the phone
   alone; the stage's own bottom padding is what keeps it off the viewport edge.
   Not scaled with the phone either: it is the page talking, not the app. */
.v2-reel-phone .demo-caption {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-top: 10px;
  width: max-content;
  max-width: 100%;
  color: var(--text-faint);
}

@media (max-width: 900px) {
  /* Stacked, the phone leads and the caption sits under it. The track shortens
     with it — it keeps the desktop's pacing in proportion but not its absolute
     length, because a thumb covers less ground per flick than a trackpad and
     five steps at the desktop's stride is a long way to scroll on a phone.

     And the caption gives up its body copy. Phone and caption are competing for
     one screen's height here, and at four lines of text the phone lost — 236 of
     a 390 viewport, small and marooned in its own margins. On a screen this size
     the phone *is* the message and the headline is enough to say which part of
     it you are looking at. */
  .v2-reel { height: 620vh; }
  .v2-reel-step span { display: none; }
  .v2-reel-step b { font-size: clamp(20px, 5.2vw, 26px); margin-bottom: 0; }
  .v2-reel-stage {
    /* One column at full width, with both items centred in it. It used to be
       stated at the phone's own scale — calc(395px * --phone-fit) — which was
       right for the phone and wrong for the caption underneath, because the
       caption is in the same column: on a 375 that made it 227 wide, and every
       headline longer than the English one broke across two lines inside it.
       "Trouvez-la ensemble." is not a long sentence; it was being read through a
       slot two thirds the width of the screen.

       The phone doesn't mind the change. Its 395 lives on .phone rather than on
       the track — that is where 1px = 1pt is declared, and the note this replaces
       was about the column being *narrower* than 395, which squeezed the panel
       and quietly rescaled the app. Wider is free: .v2-reel-phone centres it, and
       --phone-fit still does all the shrinking. */
    grid-template-columns: 1fr;
    justify-items: center;
    justify-content: center;
    align-content: center;
    /* The caption hangs in this gap — it is out of the phone's flow — so the gap
       has to clear the whole of it: 10 of margin under the phone and about 24 of
       line. At the 26 this was, the attribution ran into the headline under it
       on every handset. 40 is that plus air, and it is the one place on a short
       screen where taking room off the phone buys something. */
    gap: 40px;
    text-align: center;
    /* padding-top is written by fit(), which sets it from the bar's real height.
       The gutters come in so a 395pt panel has somewhere to go on a 375 screen.

       The bottom one carries the safe-area inset, because the caption is the
       last thing in the stage and on a handset the last 34 of the screen belong
       to the home indicator. svh keeps the caption clear of the browser's
       toolbar; this keeps it clear of the system's own bar under that. fit()
       reads this padding rather than assuming it, so the phone gives up the
       pixels and the caption keeps them. */
    padding-right: 14px;
    padding-bottom: calc(20px + env(safe-area-inset-bottom, 0px));
    padding-left: 14px;
  }
  /* No second phone down here — it is display: none below — so the column owes
     it nothing and the caption gets the whole width back. */
  .v2-reel-copy { order: 2; padding-right: 0; }
  .v2-reel-kicker { transform: none; position: absolute; opacity: 0; }
  .v2-reel-step span { max-width: 46ch; margin: 0 auto; }
  .v2-reel-phone { order: 1; }
}

/* -- Section furniture ----------------------------------------------------- */
.v2-section { padding: clamp(56px, 8vw, 96px) 0; border-top: 1px solid var(--hairline); }
.v2-kicker {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 18px;
}

/* The genre marquee, on the dark. */
.v2 .marquee { margin: 0; padding: clamp(28px, 4vw, 40px) 0; border-top: 1px solid var(--hairline); }
.v2 .marquee span {
  color: var(--text-dim);
  background: rgba(255, 255, 255, 0.05);
  border-color: var(--hairline);
}

/* -- Pull quote ------------------------------------------------------------ */
/* v1 sets this as a paragraph. Here it is the argument, at the size of one. */
.v2-pull {
  text-align: center;
  font-size: clamp(30px, 4.6vw, 58px);
  font-weight: 600;
  line-height: 1.18;
  letter-spacing: -0.025em;
  max-width: 30ch;
  margin: 0 auto;
  text-wrap: balance;
}
.v2-pull strong { font-weight: 600; color: var(--text-dim); display: block; }
/* The coda, under the claim rather than beside it. Dimmed and a size down for
   the same reason <strong> above it is dimmed: the middle line is the argument,
   and these two are the setup and the sign-off. */
.v2-pull-coda {
  display: block;
  margin-top: 0.5em;
  font-size: 0.62em;
  color: var(--text-dim);
}

/* -- FAQ ------------------------------------------------------------------- */
/* The same rows as v1 — one surface, hairline-divided, the open one wearing the
   accent — on a panel that belongs to this page's palette. */
.v2 .faq { background: rgba(255, 255, 255, 0.04); border-color: var(--hairline); box-shadow: none; }
.v2 .faq-head { font-size: clamp(22px, 2.6vw, 30px); }

/* -- Closing --------------------------------------------------------------- */
/* One band, the accent's own light behind it, and the ask in the middle. */
.v2-close {
  position: relative;
  text-align: center;
  /* Less room at the foot than the head: the footer lives in here now and
     brings padding of its own. */
  padding: clamp(72px, 10vw, 120px) 24px clamp(24px, 3vw, 40px);
  border-top: 1px solid var(--hairline);
  overflow: hidden;
}
.v2-close::before {
  content: "";
  position: absolute;
  inset: 0;
  /* Anchored above the band's foot, not on it. Centred at 100% the light was
     at its brightest exactly where `overflow: hidden` cut it, so the band ended
     on a hard bright line with the footer's own hairline just under it. Pulled
     up to 68%, the glow peaks behind the ask and is spent before the edge, and
     the footer sits in what's left of it. */
  background: radial-gradient(72% 108% at 50% 68%, rgba(97, 85, 245, 0.3), transparent 72%);
  pointer-events: none;
}
.v2-close > * { position: relative; }
.v2-close h2 {
  font-size: clamp(28px, 4.4vw, 52px);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.03em;
  max-width: 18ch;
  margin: 0 auto 28px;
  text-wrap: balance;
}

/* -- Footer ---------------------------------------------------------------- */
.v2-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  font-size: 13px;
  color: var(--text-faint);
  /* No rule over it. The distance from the ask is the separation, and inside
     the band a hairline would only be drawing the join we came to hide. */
  margin-top: clamp(56px, 8vw, 88px);
  padding: 0;
}
/* The band already holds the page's gutter; this wrap would double it. */
.v2-close .v2-wrap { padding-left: 0; padding-right: 0; }
.v2-footer a { color: var(--text-faint); text-decoration: none; }
.v2-footer a:hover { color: var(--accent); }
/* Privacy and the social mark travel together at the right-hand end, so the
   footer stays two things across rather than three spread thin. */
.v2-footer-links { display: inline-flex; align-items: center; gap: 18px; }
.v2-social { display: inline-flex; color: var(--text-faint); transition: color var(--t-quick); }
.v2-social .ic { width: 17px; height: 17px; }
a.v2-social:hover { color: var(--accent); }

@media (max-width: 560px) {
  .v2-wrap { padding: 0 18px; }
  .v2-title { max-width: none; }
  /* Brand, language and ask on one narrow row. The ask is the wider of the two
     controls and the one that must not shrink, so the giving is done here. */
  .nav-actions { gap: 8px; }
  .lang-select { padding: 0 28px 0 11px; font-size: 12.5px; }
}

/* The ask's two labels. The offer everywhere there is room for it, and the verb
   where there isn't. Never both: they are one button's text, chosen by how much
   bar there is, and a language whose short form is its long form simply says it
   twice in the markup and shows it once.

   560 rather than the 460 the wordmark yields at, and the number is the longest
   ask rather than the English one: between those two widths the bar has its
   wordmark back, and "Accesso anticipato" beside four codes was reaching within
   five pixels of the edge on it. One width for every language, because a bar
   that rearranged itself on the way through Italian and not through French
   would be a layout with an opinion about the reader's language. */
.cta-brief { display: none; }
@media (max-width: 560px) {
  .cta-full { display: none; }
  .cta-brief { display: inline; }
}

/* The smallest phones still in use are 320 across, and there the row closes up
   rather than letting the ask hang over the edge. Every pixel here was measured
   against the longest short label in any language, which is Rejoindre — English
   is nowhere near the binding constraint on this row. */
@media (max-width: 380px) {
  .nav-actions { gap: 6px; }
  .lang-select { padding: 0 26px 0 10px; background-position: right 8px center; }
}

/* Below about 430 the bar has three things and room for two: the wordmark, the
   language, and the ask come to 428 of the 375 a phone gives. The wordmark is
   what yields, and only while the ask is actually up — through the hero and the
   closing band, where the ask is hidden because a field is on screen, the bar
   keeps its name. The mark itself never goes: it is still the brand, and it is
   still what the hero's logo flies into.

   :has() is what makes "while the ask is up" expressible in CSS at all, and a
   browser too old for it simply keeps the wordmark, which is where this started. */
@media (max-width: 460px) {
  .v2-nav .v2-wrap:has(#nav-cta:not([hidden])) .brand-name { display: none; }
}

/* -- Right to left ----------------------------------------------------------
 * Arabic. i18n.js writes dir on <html> beside lang, and almost nothing here has
 * to answer it: every row on this page is a flex or a grid, and those turn
 * round on their own. What is below is the short list of places where a
 * physical edge was named — left or right rather than start or end — because
 * naming the edge was the clearer thing to write everywhere else.
 *
 * Two things deliberately do NOT turn round, and both are stated rather than
 * inherited: the phone, which carries dir="ltr" in the markup for the same
 * reason it is never translated, and the genre marquee, which is a strip of
 * English words scrolling one way by design and is aria-hidden anyway.
 *
 * Logical properties would have replaced most of this with nothing at all. They
 * are not used because the rest of the sheet is physical and half a sheet in
 * each idiom is worse than one whole sheet in either — if that ever changes,
 * this block is what disappears. */

/* The picker's chevron is painted on rather than drawn, so it sits at whichever
   edge the background says. The padding follows it: the three widths below are
   the three the picker already has, mirrored. */
[dir="rtl"] .lang-select {
  padding: 0 13px 0 30px;
  background-position: left 10px center;
}
@media (max-width: 560px) {
  [dir="rtl"] .lang-select { padding: 0 11px 0 28px; }
}
@media (max-width: 380px) {
  [dir="rtl"] .lang-select { padding: 0 10px 0 26px; background-position: left 8px center; }
}

/* The FAQ chevron is pushed to the far end of its row by an auto margin, and an
   auto margin is the one flex idiom that still has to name a side. */
[dir="rtl"] .faq summary .ic { margin-left: 0; margin-right: auto; }

/* The reel's column and the second phone. The grid puts the copy on the right
   and the phone on the left on its own; what it can't know is that the aside is
   absolutely positioned against the phone's own column, so its edge, its tuck,
   its origin and the direction it leans and slides in from are all named here.
   The reservation in the caption column is the same expression as the one it
   mirrors — see the note above it — moved to the other side. */
[dir="rtl"] .v2-reel-copy {
  padding-right: 0;
  padding-left: max(
    0px,
    calc(
      (395px * 0.84 + 854px * 0.84 * 0.0872 / 2) * var(--phone-fit, 1) - 168px -
        var(--reel-gap, 0px) + 16px
    )
  );
}
[dir="rtl"] .v2-reel-aside {
  right: auto;
  left: 100%;
  margin-right: 0;
  margin-left: -168px;
  transform-origin: 0 50%;
  transform: translateY(-50%) scale(calc(var(--phone-fit, 1) * 0.84)) rotate(5deg) translateX(-48px);
}
[dir="rtl"] .v2-reel-stage.is-duo .v2-reel-aside {
  transform: translateY(-50%) scale(calc(var(--phone-fit, 1) * 0.84)) rotate(5deg) translateX(0);
}
@media (max-width: 900px) {
  /* One column down here and no aside in it, so the reservation goes back —
     the same zeroing the left-to-right rule does, on the other side. */
  [dir="rtl"] .v2-reel-copy { padding-left: 0; }
}

/* Whose phone is whose. Each tag stands at its own handset's *exposed* edge —
   the near one's away from the pair, the far one's on the sliver of it that is
   actually showing — and which edge that is depends on which side the aside
   comes in from. Mirrored, the two swap sides; left where the tag says right is
   the one thing here that isn't cosmetic, because it hides the far tag behind
   the near phone entirely. The padding goes with them: the tag is tight against
   its avatar and open at the word, and dir has already moved the avatar. */
[dir="rtl"] .v2-phone-tag { padding: 5px 5px 5px 14px; }
[dir="rtl"] .v2-phone-tag.is-you { right: auto; left: 14px; }
[dir="rtl"] .v2-phone-tag.is-them { left: auto; right: 14px; }

/* The two arrows that mean "onward" — the bar's ask and the field's — are drawn
   pointing right, and onward is the other way here. Turned rather than swapped
   for a second symbol: the sheet holds one arrow and this is the same arrow,
   which is also what keeps it in step if the drawing ever changes. The scroll
   cue is not in this list; it points down, and down is down. */
[dir="rtl"] .nav-cta .ic,
[dir="rtl"] .field button .ic { transform: scaleX(-1); }

/* An email address reads left to right in every language. Aligned to the end
   so it still starts at the edge the reader's eye starts at, next to the
   envelope, rather than stranded across the field. */
[dir="rtl"] input[type="email"] { direction: ltr; text-align: right; }

/* English words on a track that runs one way. Decorative, and hidden from
   assistive technology, so it keeps the direction it was drawn in. */
[dir="rtl"] .marquee { direction: ltr; }
