/* ─────────────────────────────────────────────────────────────────────────
   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);
}

.flow {
  position: relative;
  width: 100%;
  max-width: 46rem;
  /* 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);
  line-height: 1.06;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

/* The violet lands on the payoff word, never on the subject. */
.accent {
  color: var(--violet);
}

/* 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. */
.step__promise {
  margin: 0 0 28px;
  max-width: 33rem;
  padding-left: 15px;
  border-left: 2px solid rgba(90, 80, 228, 0.55);
  font-size: clamp(0.9375rem, 0.9rem + 0.2vw, 1.0625rem);
  line-height: 1.6;
  color: var(--ink-soft);
}

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

.step__hint--key {
  margin: 0;
  font-size: 0.8125rem;
  color: rgba(255, 255, 255, 0.34);
}

kbd {
  font-family: var(--font-sans);
  font-size: 0.75rem;
  font-weight: 600;
  padding: 2px 6px;
  border-radius: 4px;
  border: 1px solid var(--hairline);
  background: rgba(255, 255, 255, 0.06);
  color: var(--ink-soft);
}

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

.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;
}

/* ── Channel chips ─────────────────────────────────────────────────────── */

.channels {
  margin: 0 0 30px;
  padding: 0;
  border: 0;
  min-width: 0;
}

.channels__grid {
  display: grid;
  /* 12rem, not 9.5rem: with the keycap showing, a chip spends 68px on chrome
     (16 pad + 24 cap + 12 gap + 16 pad), and the longest label,
     "WooCommerce", needs 115px. 9.5rem gave four 152px columns at this width,
     leaving 84px of label space, so the word wrapped mid-way and that row of
     chips grew to 68px while the next row stayed 54px. 12rem yields three
     ~206px columns: 138px of label space, every label on one line, every chip
     the same height. The narrow override below drops this back down, since
     without the keycap the chip needs 36px less. */
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  gap: 10px;
  margin-top: 6px;
}

.chip {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border: 1px solid var(--hairline);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.045);
  cursor: pointer;
  user-select: none;
  transition: border-color 220ms var(--ease), background 220ms var(--ease),
    transform 220ms var(--ease);
}

.chip:hover {
  border-color: rgba(255, 255, 255, 0.34);
  transform: translateY(-2px);
}

.chip input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
}

.chip__key {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.08);
  font-family: var(--font-logo);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--ink-faint);
  transition: background 220ms var(--ease), color 220ms var(--ease);
}

.chip__label {
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--ink-soft);
  transition: color 220ms var(--ease);
  /* Never break a label across lines. A product name split as "WooCommer /
     ce" reads as a rendering fault. The column width below is sized from the
     longest label instead, so this never needs to wrap or overflow. If a
     longer label is ever added, widen the grid minmax rather than letting
     this wrap. */
  white-space: nowrap;
}

/* `.is-on` is set by apply.js alongside :has(). Belt and braces: :has() is
   unsupported in the older WKWebView builds that Facebook and Instagram's
   in-app browsers still ship, which is exactly where this traffic lands. */
.chip.is-on,
.chip:has(input:checked) {
  border-color: var(--violet);
  background: rgba(90, 80, 228, 0.2);
}

.chip.is-on .chip__key,
.chip:has(input:checked) .chip__key {
  background: var(--violet);
  color: #fff;
}

.chip.is-on .chip__label,
.chip:has(input:checked) .chip__label {
  color: var(--ink);
}

.chip:focus-within {
  outline: 2px solid var(--violet);
  outline-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,
  .chip {
    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 {
    align-items: flex-start;
    padding-top: clamp(12px, 2.5vh, 28px);
  }

  .flow {
    min-height: 0;
  }

  .step__promise {
    margin-bottom: 20px;
  }

  .step__hint {
    margin-bottom: 20px;
  }

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

/* ── Chips: drop the keycaps where there is no keyboard ────────────────── */
/* The numerals are a shortcut affordance for physical keyboards. On a touch
   device there is nothing to press them with, so they are dead ink AND they
   cost 36px of the chip's inner width (24px cap + 12px gap). At 375px the
   chip has 163px, "WooCommerce" needs 115px, and the chrome needs 68px, so
   the label spilled past the border. Removing the cap gives 131px of room for
   a 115px label and fixes the overflow by deleting the cause.
   Width clause included so a narrow desktop window gets the same treatment. */
@media (pointer: coarse), (max-width: 620px) {
  .chip__key {
    display: none;
  }

  .chip {
    gap: 0;
  }

  /* Back down from the 12rem base. With no keycap a chip spends only 32px on
     chrome, so a 152px column leaves 130px for the 115px "WooCommerce" and
     two columns still fit at 375px. Without this the 12rem base forces a
     single column and the six chips stack into six rows. */
  .channels__grid {
    grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  }

  /* "tap a number, then Enter" is instructions for hardware that is not there. */
  .channels + .step__actions .step__hint--key {
    display: none;
  }
}

/* ── 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;
  }
}
