/* ─────────────────────────────────────────────────────────────────────────
   gloss · /lp/:slug/apply - the conversational early-access flow

   Deliberately self-contained. It does NOT import styles.css: this page has
   one job, and coupling it to the 58 KB homepage sheet means every future
   homepage refactor can silently break the only form a referral partner
   ever sees. Palette and type below mirror styles.css :root exactly.

   Treatment note: the homepage goes light on desktop (--canvas) and dark on
   mobile. This page stays dark at every width on purpose. It is the invite,
   not the pitch, and the photography carries it.
   ───────────────────────────────────────────────────────────────────────── */

:root {
  --deep: #0a0e1a;
  --canvas: #f8f6f2;
  --bone: #f0ede6;
  --violet: #5a50e4;
  --violet-rich: #3a287f;
  --violet-deep: #2d1b69;
  --warm-border: #e4e0d8;
  --text-muted: #747890;
  --error: #ef4444;

  --font-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-h1: 'Zilla Slab', Georgia, serif;
  --font-logo: 'Syne', system-ui, sans-serif;

  /* One easing for everything that moves. Overshoot-free, decelerating,
     the motion equivalent of the brand's terse sentences. */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --step-dur: 460ms;

  --ink: #ffffff;
  --ink-soft: rgba(255, 255, 255, 0.68);
  --ink-faint: rgba(255, 255, 255, 0.42);
  --hairline: rgba(255, 255, 255, 0.16);
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--deep);
  color: var(--ink);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  overflow-x: clip;
}

body {
  /* svh, not vh: iOS Safari's collapsing URL bar makes 100vh taller than the
     visible viewport, which pushed the submit button under the chrome. */
  min-height: 100svh;
}

a {
  color: inherit;
}

.apply {
  position: relative;
  z-index: 1;
  min-height: 100svh;
  display: grid;
  grid-template-rows: auto auto 1fr auto;
  /* Notch and home-indicator safe. viewport-fit=cover is set in the meta. */
  padding: env(safe-area-inset-top) env(safe-area-inset-right)
    env(safe-area-inset-bottom) env(safe-area-inset-left);
}

/* ── Background: two cross-fading photographic layers ──────────────────── */

.bg {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.bg__layer {
  position: absolute;
  inset: 0;
  background-position: 62% center;
  background-size: cover;
  background-repeat: no-repeat;
  opacity: 0;
  /* Slower in than out: the incoming photograph arrives, it does not cut. */
  transition: opacity 900ms var(--ease);
  will-change: opacity, transform;
}

.bg__layer.is-active {
  opacity: 1;
  animation: kenBurns 26s ease-out forwards;
}

@keyframes kenBurns {
  from {
    transform: scale(1.04) translate3d(0, 0, 0);
  }
  to {
    transform: scale(1.15) translate3d(-1.4%, -1%, 0);
  }
}

/* The scrim is the whole reason the type is readable over photography. Four
   stacked gradients, in paint order:
     1. radial pool anchored left, where the question sits
     2. horizontal falloff so the right edge keeps the picture
     3. vertical seal top and bottom, for the topbar and the footnote
     4. a violet wash so the photo reads as brand, not as stock */
.bg__scrim {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(
      ellipse 118% 100% at 6% 50%,
      rgba(10, 14, 26, 0.97) 0%,
      rgba(10, 14, 26, 0.93) 32%,
      rgba(10, 14, 26, 0.6) 58%,
      rgba(10, 14, 26, 0.16) 82%,
      rgba(10, 14, 26, 0) 100%
    ),
    linear-gradient(
      90deg,
      rgba(10, 14, 26, 0.98) 0%,
      rgba(10, 14, 26, 0.86) 36%,
      rgba(10, 14, 26, 0.4) 66%,
      rgba(10, 14, 26, 0.04) 100%
    ),
    linear-gradient(
      180deg,
      rgba(10, 14, 26, 0.86) 0%,
      rgba(10, 14, 26, 0.22) 28%,
      rgba(10, 14, 26, 0.3) 68%,
      rgba(10, 14, 26, 0.94) 100%
    ),
    linear-gradient(135deg, rgba(45, 27, 105, 0.5) 0%, rgba(45, 27, 105, 0) 58%);
}

/* Photographic grain. Kills the banding that big soft gradients produce on
   8-bit panels and stops the scrim reading as flat CSS. */
.bg__grain {
  position: absolute;
  inset: -50%;
  opacity: 0.055;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Phones: the type has nowhere to hide, so seal the picture much harder and
   pull the focal point back toward centre. */
@media (max-width: 900px) {
  .bg__layer {
    background-position: 68% center;
  }

  .bg__scrim {
    background:
      linear-gradient(
        180deg,
        rgba(10, 14, 26, 0.9) 0%,
        rgba(10, 14, 26, 0.55) 24%,
        rgba(10, 14, 26, 0.82) 52%,
        rgba(10, 14, 26, 0.97) 78%,
        rgba(10, 14, 26, 1) 100%
      ),
      linear-gradient(135deg, rgba(45, 27, 105, 0.45) 0%, rgba(45, 27, 105, 0) 62%);
  }
}

/* ── Top bar ───────────────────────────────────────────────────────────── */

.topbar {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 24px clamp(20px, 5vw, 64px) 0;
}

.topbar__logo {
  font-family: var(--font-logo);
  font-weight: 700;
  font-size: 1.25rem;
  letter-spacing: -0.02em;
  text-decoration: none;
  color: var(--ink);
}

.topbar__dot {
  color: var(--violet);
}

.topbar__ref {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* ── Progress rail ─────────────────────────────────────────────────────── */

.rail {
  height: 2px;
  margin: 22px clamp(20px, 5vw, 64px) 0;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 2px;
  overflow: hidden;
}

.rail__fill {
  height: 100%;
  width: 0%;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--violet-rich), var(--violet));
  box-shadow: 0 0 14px rgba(90, 80, 228, 0.7);
  transition: width 620ms var(--ease);
}

/* ── Stage and step stack ──────────────────────────────────────────────── */

.stage {
  display: flex;
  align-items: center;
  padding: clamp(28px, 6vh, 72px) clamp(20px, 5vw, 64px);
}

/* ── The walkthrough demo ───────────────────────────────────────────────
   Beside the questions, not inside them, so it plays straight through the whole form
   instead of restarting on every answer. It is on every screen at every width: the
   element is mounted once at stage level, and only the direction changes. */
@media (min-width: 901px) {
  .stage {
    display: grid;
    /* the panel is the second column, so it reads after the question on a screen
       reader even though the markup puts it first for the phone stack */
    grid-template-columns: minmax(0, 1fr) auto;
    grid-auto-flow: dense;
    gap: clamp(32px, 5vw, 88px);
    align-items: center;
  }

  .demo {
    grid-column: 2;
  }
}

.demo {
  /* height-driven: its natural 372x760 would otherwise set the row height and push
     the questions around */
  height: clamp(380px, 62vh, 620px);
  /* Same device treatment as the marketing hero's .phone--mobile: a dark bezel with
     a generous radius and a deep drop shadow, scaled to this panel's height rather
     than to a 375px viewport. 44/800 of the height keeps the corner proportional. */
  border-radius: calc(clamp(380px, 62vh, 620px) * 0.055);
  border: 3px solid var(--deep);
  background: var(--deep);
  overflow: hidden;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6), inset 0 0 0 1px rgba(255, 255, 255, 0.03);
  line-height: 0;
}

.demo__video {
  display: block;
  height: 100%;
  width: auto;
  /* Promote to its own compositing layer. Without this the video does not paint at all
     in some renderers: the element is there, laid out, playing, topmost at its own
     centre, and the panel still shows as an empty dark rectangle. Every earlier version
     that happened to look fine had a filter or a transform on it, which was promoting it
     by accident, so removing that property made the phone vanish. Verified by toggling
     this one line in the live page. */
  transform: translateZ(0);
  /* The recording is the phone screen and nothing else: its corner pixels are the
     storefront's own background, not a device shell. So it needs no scaling to hide an
     edge, and any scale here is a straight crop of the walkthrough. The bezel above is
     the only device chrome. */
  object-fit: contain;
}

.flow {
  position: relative;
  width: 100%;
  max-width: 46rem;
  /* a step with a storefront beside it needs a wider track than a bare
     question does; :has keeps the widening tied to the step, not the page */

  /* Steps share one grid cell so they can cross-fade over each other. The
     min-height stops short steps from collapsing the layout between
     questions, which read as the page flinching. */
  display: grid;
  grid-template-areas: 'step';
  min-height: clamp(340px, 44vh, 480px);
  align-items: center;
}

.step {
  grid-area: step;
  outline: none;
}

.step[hidden] {
  display: none;
}

/* Steps animate as a unit, then their children stagger in behind. Doing the
   stagger with nth-child delays rather than per-element classes keeps the
   engine in JS free of any knowledge of a step's internal markup. */
.step.is-entering > * {
  animation: stepIn var(--step-dur) var(--ease) both;
}

.step.is-entering > *:nth-child(1) { animation-delay: 40ms; }
.step.is-entering > *:nth-child(2) { animation-delay: 90ms; }
.step.is-entering > *:nth-child(3) { animation-delay: 140ms; }
.step.is-entering > *:nth-child(4) { animation-delay: 185ms; }
.step.is-entering > *:nth-child(5) { animation-delay: 225ms; }
.step.is-entering > *:nth-child(6) { animation-delay: 260ms; }
.step.is-entering > *:nth-child(7) { animation-delay: 290ms; }
.step.is-entering > *:nth-child(8) { animation-delay: 315ms; }

.step.is-leaving {
  animation: stepOut 260ms var(--ease) both;
  pointer-events: none;
}

/* Going backwards mirrors the axis, so "Back" physically feels like reversing
   rather than like another new question arriving. */
.step.is-entering.is-reverse > * {
  animation-name: stepInReverse;
}

.step.is-leaving.is-reverse {
  animation-name: stepOutReverse;
}

@keyframes stepIn {
  from { opacity: 0; transform: translate3d(0, 26px, 0); }
  to { opacity: 1; transform: none; }
}

@keyframes stepInReverse {
  from { opacity: 0; transform: translate3d(0, -26px, 0); }
  to { opacity: 1; transform: none; }
}

@keyframes stepOut {
  from { opacity: 1; transform: none; }
  to { opacity: 0; transform: translate3d(0, -22px, 0); }
}

@keyframes stepOutReverse {
  from { opacity: 1; transform: none; }
  to { opacity: 0; transform: translate3d(0, 22px, 0); }
}

/* ── Step contents ─────────────────────────────────────────────────────── */

.step__eyebrow {
  margin: 0 0 18px;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--violet);
}

.step__count {
  margin: 0 0 20px;
  font-family: var(--font-logo);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.step__count-sep {
  color: rgba(255, 255, 255, 0.22);
  margin: 0 2px;
}

.step__headline {
  margin: 0 0 22px;
  font-family: var(--font-h1);
  font-weight: 400;
  font-size: clamp(2rem, 1.2rem + 3.4vw, 3.5rem);
  /* 1.06 was set for plain type. The accent is a filled box now, so at that leading a
     highlighted phrase on the second line paints over the glyphs on the first. Just
     enough air for the box to clear them, without loosening the display rhythm. */
  line-height: 1.18;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

/* The headline runs large, so the accent's padding scales with it and only needs to be
   a hairline vertically to read as a highlight. */
.step__headline .accent {
  padding-block: 0.02em;
}

/* The violet lands on the payoff word, never on the subject. */
/* A highlight, not coloured ink. Violet type on a dark photographic plate was not
   legible: the text stays white and the violet goes behind it, where it can carry the
   emphasis without costing contrast. box-decoration-break keeps the pad and the radius
   on every line when the phrase wraps, instead of only the first and last. */
.accent {
  color: var(--ink);
  background: rgba(90, 80, 228, 0.45);
  padding: 0.06em 0.22em;
  margin: 0 -0.04em;
  border-radius: 4px;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* Questions carry the same display voice as the headline, one size down. A
   <legend> needs the display/padding reset or it inherits fieldset quirks. */
.step__prompt {
  display: block;
  float: none;
  width: 100%;
  padding: 0;
  margin: 0 0 12px;
  font-family: var(--font-h1);
  font-weight: 400;
  font-size: clamp(1.625rem, 1.1rem + 2.2vw, 2.625rem);
  line-height: 1.14;
  letter-spacing: -0.012em;
  text-wrap: balance;
  color: var(--ink);
}

.step__body {
  margin: 0 0 16px;
  max-width: 34rem;
  font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
  line-height: 1.62;
  color: var(--ink-soft);
}

.step__body--quiet {
  color: var(--ink-faint);
  font-size: 0.9375rem;
}

/* Standing context on the first question, in place of the welcome screen that
   used to carry it. Set below the question in the visual hierarchy on purpose:
   it is there to be caught, not to be read before answering. The violet rule
   marks it as the page talking rather than the page asking. */
/* No left accent bar. The emphasis is carried by type: the block sits a step
   up in size from the hint below it, and the one phrase that matters is set
   in .accent. A coloured edge is not used to mark anything here. */
.step__promise {
  margin: 0 0 28px;
  max-width: 33rem;
  font-size: clamp(0.9375rem, 0.9rem + 0.2vw, 1.0625rem);
  line-height: 1.6;
  color: var(--ink-soft);
}

/* The ad's own hook, carried onto the screen it sent the visitor to. Display
   font and full-strength ink so it reads as the headline they tapped, with the
   promise body continuing underneath at reading weight. Same relationship as
   the ad: hook large, support small. */
.promise__echo {
  display: block;
  margin: 0 0 12px;
  max-width: 30rem;
  font-family: var(--font-h1);
  font-size: clamp(1.125rem, 1rem + 0.7vw, 1.5rem);
  line-height: 1.25;
  color: var(--ink);
}

.step__hint {
  margin: 0 0 30px;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--ink-faint);
}

/* ── The answer line ───────────────────────────────────────────────────── */

/* The password field on the close screen. It is the second of a pair, so it is
   set a step down from the email above it: same rule, smaller voice. Reusing
   .step__input at full size would give the screen two equal headlines and
   neither would read as the answer to the question. */
.step__input--sm {
  font-size: clamp(1rem, 0.9rem + 0.5vw, 1.25rem);
  padding-bottom: 12px;
}

/* Labels the second field without competing with .step__prompt above it. */
.step__sublabel {
  display: block;
  margin: 18px 0 0;
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}

.step__input {
  display: block;
  width: 100%;
  margin: 0 0 10px;
  padding: 8px 2px 16px;
  font-family: var(--font-sans);
  font-size: clamp(1.25rem, 1rem + 1.2vw, 1.875rem);
  font-weight: 300;
  line-height: 1.3;
  color: var(--ink);
  background-color: transparent;
  border: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: 0;
  caret-color: var(--violet);
  outline: none;
  -webkit-appearance: none;
  appearance: none;
  /* The focus underline is a background layer, not a pseudo-element: <input>
     cannot host ::after, and a wrapper div would break the label/for pairing
     that makes iOS autofill land in the right field. */
  background-image: linear-gradient(var(--violet), var(--violet));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 2px;
  transition: background-size 520ms var(--ease), box-shadow 300ms var(--ease);
}

.step__input::placeholder {
  color: rgba(255, 255, 255, 0.26);
  font-weight: 300;
}

.step__input:focus {
  background-size: 100% 2px;
  box-shadow: 0 18px 44px -26px rgba(90, 80, 228, 0.95);
}

.step__input:-webkit-autofill,
.step__input:-webkit-autofill:focus {
  /* Chrome paints its own pale-yellow fill and near-black text over the dark
     canvas, which made autofilled answers unreadable. There is no way to unset
     it, so overwrite with an inset shadow the size of the field. */
  -webkit-text-fill-color: var(--ink);
  -webkit-box-shadow: 0 0 0 1000px var(--deep) inset;
  caret-color: var(--violet);
}

.step__error {
  margin: 0 0 18px;
  font-size: 0.875rem;
  font-weight: 500;
  color: #ff8a8a;
}

.step__error[hidden] {
  display: none;
}

.step__legal {
  margin: 26px 0 0;
  font-size: 0.75rem;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.32);
}

.step__legal a {
  color: rgba(255, 255, 255, 0.5);
  text-underline-offset: 3px;
}

/* ── Buttons ───────────────────────────────────────────────────────────── */

.step__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  margin-top: 4px;
}

.cta {
  display: inline-block;
  padding: 15px 34px;
  background: var(--violet);
  color: #fff;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 0.9375rem;
  line-height: 1;
  text-decoration: none;
  border: none;
  border-radius: 9999px;
  box-shadow: 0 10px 30px rgba(90, 80, 228, 0.36);
  cursor: pointer;
  transition: background 200ms, color 200ms, transform 200ms;
}

.cta:hover {
  background: #fff;
  color: var(--violet);
  transform: scale(1.04);
}

.cta:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 3px;
}

.cta:disabled,
.cta:disabled:hover {
  background: rgba(120, 122, 138, 0.55);
  color: rgba(255, 255, 255, 0.7);
  box-shadow: none;
  transform: none;
  cursor: not-allowed;
}

.cta--ghost {
  background: transparent;
  color: var(--ink-soft);
  border: 1px solid var(--hairline);
  box-shadow: none;
  font-weight: 600;
}

.cta--ghost:hover {
  background: rgba(255, 255, 255, 0.08);
  color: var(--ink);
  transform: none;
}

/* ── Footnote ──────────────────────────────────────────────────────────── */

.footnote {
  padding: 0 clamp(20px, 5vw, 64px) 24px;
  font-size: 0.75rem;
  color: rgba(255, 255, 255, 0.3);
}

.footnote p {
  margin: 0;
}

.footnote a {
  color: rgba(255, 255, 255, 0.45);
  text-underline-offset: 3px;
}

/* ── Utilities ─────────────────────────────────────────────────────────── */

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

/* Honeypot. Off-canvas rather than display:none or type=hidden, both of which
   bots skip. A person never reaches it; a form-filling bot fills it. */
.hp-field {
  position: absolute;
  left: -9999px;
  top: 0;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ── Reduced motion ────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .bg__layer.is-active {
    animation: none;
    transform: scale(1.04);
  }

  .step.is-entering > *,
  .step.is-leaving {
    animation-duration: 1ms;
    animation-delay: 0ms;
  }

  .step__input,
  .rail__fill,
  .cta {
    transition-duration: 1ms;
  }

  .cta:hover {
    transform: none;
  }
}

/* ── Phones: keep the answer line above the keyboard ───────────────────── */
/* An on-screen keyboard takes roughly 40% of the viewport, and this layout
   fits the screen exactly, so there is no scroll room for the browser to lift
   a focused field back into view. Stop centring the conversation and let it
   sit high instead. Must stay AFTER the .stage and .flow base rules: it is the
   same specificity, so source order is what decides it. */
@media (max-width: 900px) {
  .stage {
    /* The panel stacks above the question rather than beside it. Its height is the
       whole budget question here: the input still has to clear the on-screen keyboard,
       so this is checked against the fold, not chosen by eye. */
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: clamp(12px, 2vh, 22px);
    padding-top: clamp(2px, 0.4vh, 4px);
  }

  /* The chrome above the phone was costing 94px before anything worth looking at: 24px
     of topbar padding, 22px above the progress rail, 21px of stage padding. Trimmed, and
     the phone takes the space back rather than the page just sitting higher. */
  .topbar {
    padding-top: 6px;
  }

  .rail {
    margin-top: 6px;
  }

  /* The panel sits inside the active step on a phone, between the question and the
     write-up, so the step becomes a flex column and everything is ordered explicitly.
     What the visitor needs in order to answer is above it; the argument is below, there
     to be read or skipped rather than waded through. */
  .step {
    display: flex;
    flex-direction: column;
  }

  .step__count { order: 1; }
  .step__prompt { order: 2; }
  .step__hint { order: 3; }
  .step__input { order: 4; }
  .step__error { order: 5; }
  .step__actions { order: 6; }
  .step__legal { order: 7; }
  .step .demo { order: 8; margin-top: 16px; }
  .step__promise { order: 9; margin: 12px 0 0; }

  .demo {
    height: clamp(250px, 40vh, 350px);
    border-radius: 24px;
    align-self: center;
  }

  .flow {
    min-height: 0;
  }

  .step__promise {
    margin-bottom: 20px;
  }

  .step__hint {
    margin-bottom: 20px;
  }

  .step__count {
    margin-bottom: 14px;
  }
}

/* ── Wide screens ──────────────────────────────────────────────────────── */

@media (min-width: 1100px) {
  .stage {
    /* Hold the conversation inside the scrim's dark pool and leave the right
       of the frame to the photograph. */
    padding-right: clamp(64px, 34vw, 640px);
  }

  .flow {
    max-width: 40rem;
  }
}

/* Short phones. The on-screen keyboard costs the same pixels whatever the screen
   height, so on a 640px viewport it is the panel that has to give, not the question.
   Without this Continue sits 30px under the fold on a 360x640. */
@media (max-width: 900px) and (max-height: 720px) {
  .demo {
    height: clamp(130px, 21vh, 170px);
    border-radius: 14px;
  }
}
