/* ==========================================================================
   Splitscreen — auth & onboarding
   The product is a split screen, so the frame is one: an ink pane carrying the
   argument, a bone pane carrying the work. Onboarding reuses the same frame
   with the step list in the left pane instead of the pitch.
   Depends on base.css for tokens and app.css for buttons.
   ========================================================================== */

html, body { height: 100%; }
/* `clip`, not `hidden`. Both paint the same, but `hidden` still makes body a
   scroll CONTAINER — it just has no scrollbar. So an anchor jump, or focus
   moving to something near the bottom, scrolls the body and drags the whole
   fixed-height frame off the top of the window, with no way to scroll it back.
   `clip` creates no scrollport at all, so the browser scrolls the pane that is
   actually scrollable instead. */
body { overflow: hidden; }
body { overflow: clip; }

.auth {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
  /* same reasoning as .app — an auto row would size to the taller pane's
     content and neither side would ever scroll */
  grid-template-rows: minmax(0, 1fr);
  height: 100dvh;
  overflow: hidden;
}

.auth__aside, .auth__main { min-height: 0; }
/* Narrow: drop the ink pane and let the page itself scroll, rather than
   trapping a long form inside a 100dvh pane on a small screen. */
@media (max-width: 900px) {
  .auth {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto;
    height: auto;
    min-height: 100dvh;
    overflow: visible;
  }
  .auth__aside { display: none; }
  .auth__main { overflow: visible; }
  html, body { height: auto; }
  body { overflow: auto; }
}

/* ==========================================================================
   Left pane — ink
   ========================================================================== */

.auth__aside {
  background: var(--band);
  color: var(--bone);
  border-right: 1px solid var(--line);
  padding: clamp(2rem, 4vw, 3.4rem);
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: 2rem;
  overflow-y: auto;
  scrollbar-width: thin;
}

.auth__brand {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
  color: #fff;
}
.auth__brand img { width: 34px; height: 34px; border-radius: 8px; }

.auth__pitch { align-self: center; max-width: 30rem; }

.auth__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.2rem, 3.6vw, 3.4rem);
  line-height: 0.98;
  letter-spacing: -0.035em;
  margin: 0 0 1.4rem;
}
.auth__title .w1 { color: #6E86EE; display: block; width: fit-content; }
.auth__title .w2 { color: #FF8E76; display: block; width: fit-content; }

.auth__lede {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.05rem, 1.5vw, 1.3rem);
  line-height: 1.3;
  letter-spacing: -0.014em;
  color: var(--bone-2);
  margin: 0 0 2rem;
  max-width: 24ch;
}

/* the three rooms, stated as three rooms */
.auth__rooms { display: grid; gap: 0.9rem; }
.auth__room {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.9rem;
  align-items: start;
  padding-left: 0.9rem;
  border-left: 3px solid var(--c);
}
.auth__room:nth-child(1) { --c: var(--p1); }
.auth__room:nth-child(2) { --c: #14A882; }
.auth__room:nth-child(3) { --c: var(--p2); }

.auth__room b {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.98rem;
  letter-spacing: -0.01em;
  color: #fff;
  display: block;
  margin-bottom: 0.16rem;
}
.auth__room span { font-size: 0.86rem; line-height: 1.45; color: var(--bone-3); }

.auth__foot {
  font-family: var(--font-body);
  font-size: 0.690rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: #6B717B;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.4rem;
}

/* ---------- step rail, onboarding only ---------- */
.stepper { display: grid; gap: 0.15rem; align-self: center; width: 100%; max-width: 24rem; }

.stepper__item {
  display: grid;
  grid-template-columns: 1.9rem minmax(0, 1fr);
  gap: 0.85rem;
  align-items: baseline;
  padding: 0.72rem 0.5rem 0.72rem 0;
  border-top: 1px solid #2A2E35;
  color: #6B717B;
}
.stepper__item:first-child { border-top: 0; }
.stepper__n { font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.08em; }
.stepper__t {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 0.98rem;
  letter-spacing: -0.01em;
  line-height: 1.25;
}
.stepper__item em {
  display: block;
  font-style: normal;
  font-size: 0.78rem;
  color: #6B717B;
  margin-top: 0.15rem;
  line-height: 1.4;
}

.stepper__item.is-done { color: #9AA1AC; }
.stepper__item.is-done .stepper__n { color: #14A882; }
.stepper__item.is-done .stepper__t { color: #9AA1AC; }

.stepper__item.is-now { color: #fff; }
.stepper__item.is-now .stepper__n { color: var(--p2); }
.stepper__item.is-now .stepper__t { color: #fff; }
.stepper__item.is-now em { color: var(--bone-3); }

/* ==========================================================================
   Right pane — the form
   ========================================================================== */

.auth__main {
  background: var(--void);
  padding: clamp(1.6rem, 3vw, 3rem) clamp(1.3rem, 3vw, 3rem);
  overflow-y: auto;
  scrollbar-width: thin;
  display: grid;
  /* A centred form in a SCROLLING pane, which is a trap: once the form is
     taller than the pane, `center` splits the overflow evenly above and below,
     and the half above sits at a negative scroll offset. Nothing can scroll to
     negative, so the top of the form is simply unreachable — step 4 lost the
     first two rows of games, and zooming out "fixed" it only by shrinking the
     form back inside the pane.

     `safe` drops the alignment to `start` the moment the content overflows, so
     a short form still centres and a long one is scrollable from its first
     line. The plain value stays as the fallback for anything that does not
     understand the keyword, which is no worse than today. */
  align-content: center;
  align-content: safe center;
  justify-items: start;
}

.form { width: 100%; max-width: 26rem; }
.form--wide { max-width: 34rem; }

.form__eyebrow {
  font-family: var(--font-body);
  font-size: 0.700rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--ink-3);
  display: flex;
  align-items: center;
  gap: 0.6em;
  margin-bottom: 0.85rem;
}
.form__eyebrow::before { content: ''; width: 1.5em; height: 2px; background: var(--room); flex: none; }

.form__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.65rem, 2.4vw, 2.15rem);
  letter-spacing: -0.028em;
  line-height: 1.06;
  margin: 0 0 0.6rem;
}
.form__sub {
  color: var(--ink-2);
  font-size: 0.94rem;
  line-height: 1.55;
  margin: 0 0 1.7rem;
  max-width: 42ch;
}

/* ---------- fields ---------- */
.field { display: grid; gap: 0.38rem; margin-bottom: 1.05rem; }

/* Three fields on one line. A day, a time and how long it runs are one thought
   — stacked as three full-width rows they read as three unrelated questions.
   Collapses on a narrow pane, where three columns would each be too small to
   aim a thumb at. */
.form__grid3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 0.7rem; }
@media (max-width: 560px) { .form__grid3 { grid-template-columns: 1fr; } }

.field__label {
  font-family: var(--font-body);
  font-size: 0.700rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--ink-3);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.8rem;
}
.field__label i { font-style: normal; color: var(--ink-4); text-transform: none; letter-spacing: 0.04em; }

/* Typed one by one rather than `.field input`, so a checkbox or a radio does
   not get a text field's box. The cost is that a type missing from this list
   falls back to the browser's own control — which on a dark page means a white
   input, and is exactly what `url` did until clips added one. */
.field input[type="text"],
.field input[type="email"],
.field input[type="password"],
.field input[type="url"],
.field input[type="search"],
.field input[type="tel"],
.field input[type="number"],
.field input[type="date"],
.field input[type="time"],
.field select,
.field textarea {
  width: 100%;
  font: inherit;
  font-size: 0.95rem;
  color: var(--ink);
  padding: 0.62em 0.8em;
  border-radius: 7px;
  border: 1px solid var(--line-hard);
  background: var(--paper);
  transition: border-color 0.22s var(--ease);
}
.field textarea { resize: vertical; min-height: 4.4em; line-height: 1.5; }
.field select { appearance: none; padding-right: 2.2em; cursor: pointer; }

.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--room);
  box-shadow: 0 0 0 3px var(--room-wash);
}
.field input::placeholder, .field textarea::placeholder { color: var(--ink-4); }

.field__hint { font-size: 0.78rem; color: var(--ink-3); line-height: 1.45; }

.field__err {
  font-size: 0.8rem;
  color: var(--p2-ink);
  line-height: 1.4;
  display: flex;
  gap: 0.4em;
  align-items: baseline;
}
.field__err::before { content: '—'; color: var(--p2); }
.field--bad input, .field--bad select, .field--bad textarea { border-color: var(--p2); }

.field__row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.8rem; }

/* ---------- choice cards: games, intent, mic, platform ---------- */
.choices { display: grid; gap: 0.55rem; margin-bottom: 1.15rem; }

/* Spacing between cards comes from the grid's gap, so a pair of .choice labels
   dropped in as bare siblings — which is how the Privacy switches were written
   — get none at all and sit welded together. The `:not` keeps this off the
   grid itself, where a margin would be added to the gap rather than replace
   it. Belt and braces: the group above is the right fix, this is what stops
   the next one being wrong and nobody noticing. */
:not(.choices) > .choice + .choice { margin-top: 0.55rem; }
.choices--2 { grid-template-columns: 1fr 1fr; }
.choices--3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 560px) { .choices--2, .choices--3 { grid-template-columns: 1fr; } }

/* The room toggles carry a title *and* a line of description, so they are
   roughly twice the height of a mic or platform card. At the default gap the
   three of them read as one ruled block rather than three separate decisions,
   which is the wrong impression for the only choices on the page that open and
   close whole sections of the product. Wider gap, this stack only. */
.choices--rooms { gap: 0.9rem; }

.choice {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.7rem;
  align-items: start;
  padding: 0.85rem 0.95rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--paper);
  cursor: pointer;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
}
.choice:hover { border-color: var(--line-hard); }
/* The card is UI, not prose. Without this any text placed directly in it picks
   up body's 1.62 and sets its own leading from a 16px strut. */
.choice { line-height: 1.45; }
.choice input { position: absolute; opacity: 0; pointer-events: none; }

.choice__box {
  width: 18px; height: 18px;
  border-radius: 5px;
  border: 1.5px solid var(--line-hard);
  background: var(--paper);
  flex: none;
  margin-top: 0.1rem;
  display: grid;
  place-items: center;
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease);
}
.choice__box svg { width: 12px; height: 12px; color: #fff; opacity: 0; }

.choice__t {
  font-weight: 500;
  font-size: 0.92rem;
  line-height: 1.3;
  display: flex;
  align-items: center;
  gap: 0.45rem;
}
/* `display: block` is not cosmetic here, it is what makes the two lines below
   it do anything at all.

   The description is a <span>, and its parent is a block whose strut comes
   from the inherited prose line-height — 1.62 at the card's 16px, so every
   line box was ~26px tall no matter what this rule asked for. A 13px
   description was being set on 26px leading: the reason these cards read as
   airy and disconnected. `margin-top` was ignored for the same reason, since
   vertical margins do nothing on an inline box.

   As a block it establishes its own line boxes, so 1.42 is the leading that
   actually gets used — about 18px — and the gap under the title is real. */
.choice__d {
  display: block;
  font-size: 0.79rem;
  color: var(--ink-3);
  line-height: 1.42;
  margin-top: 0.2rem;
  /* The same cap every other description in the product carries — `p` gets
     --measure (66ch) from base.css and .a-act__d, which is this component's
     twin, sets 60ch. This one was exempt for the same reason its line-height
     was ignored: it is a <span>, so none of the paragraph defaults ever
     reached it, and in a full-width card the text ran past 100 characters a
     line. Nothing else in the product asks that of anybody. */
  max-width: 60ch;
}

.choice:has(input:checked) { border-color: var(--pick, var(--room)); background: var(--room-wash); }
.choice:has(input:checked) .choice__box { background: var(--pick, var(--room)); border-color: var(--pick, var(--room)); }
.choice:has(input:checked) .choice__box svg { opacity: 1; }
.choice:has(input:focus-visible) { outline: 2px solid var(--room); outline-offset: 2px; }

/* per-pillar tint so intent choices carry their room's colour */
.choice--p1 { --pick: var(--p1); }
.choice--p2 { --pick: var(--p2); }
.choice--p3 { --pick: var(--p3); }

/* small square that stands in for a game icon */
.choice__mark {
  width: 24px; height: 24px;
  border-radius: 5px;
  display: grid;
  place-items: center;
  background: var(--mk, var(--mk-ink));
  color: #fff;
  font-family: var(--font-mono);
  font-size: 0.58rem;
  font-weight: 500;
  flex: none;
}

/* ---------- actions ---------- */
.form__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.7rem;
  margin-top: 1.5rem;
  padding-top: 1.3rem;
  border-top: 1px solid var(--line);
}
.form__actions .grow { flex: 1 1 auto; }

/* The assent line under the signup button. Deliberately not the faintest ink
   on the page: terms nobody can read are terms nobody agreed to, and this one
   carries the removal clause. Sits inside the form, under the actions rule. */
.form__legal {
  margin: 0.9rem 0 0;
  font-size: 0.79rem;
  line-height: 1.5;
  color: var(--ink-2);
}
.form__legal a { color: var(--p1-ink); font-weight: 500; text-decoration: underline; text-underline-offset: 2px; }
.form__legal a:hover { color: var(--ink); }

.form__alt {
  margin-top: 1.4rem;
  font-size: 0.87rem;
  color: var(--ink-2);
}
.form__alt a { color: var(--p1-ink); font-weight: 500; text-underline-offset: 2px; }
.form__alt a:hover { color: var(--ink); }

.form__meta {
  font-family: var(--font-body);
  font-size: 0.690rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--ink-4);
  margin-bottom: 1rem;
}

/* remember-me / inline checkbox */
.check {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.87rem;
  color: var(--ink-2);
  cursor: pointer;
}
.check input { width: 15px; height: 15px; accent-color: var(--p1); cursor: pointer; }

/* status banner (password reset sent, etc.) */
.status {
  padding: 0.75rem 0.95rem;
  border-radius: var(--radius-sm);
  background: var(--p3-wash);
  border-left: 3px solid var(--p3);
  color: var(--p3-ink);
  font-size: 0.86rem;
  line-height: 1.45;
  margin-bottom: 1.3rem;
}

/* a note that explains why a field is being asked for */
.why {
  padding: 0.8rem 0.95rem;
  border-radius: var(--radius-sm);
  background: var(--gold-wash);
  border-left: 3px solid var(--gold);
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--ink-2);
  margin-bottom: 1.3rem;
}
.why b { color: var(--ink); font-weight: 600; }
.why--safe { background: var(--p3-wash); border-left-color: var(--p3); }
.why--risk { background: var(--p2-wash); border-left-color: var(--p2); }

/* Gender is asked only when dating is switched on, because the regional
   balance metric is the only thing that uses it. No JS — the checkbox state
   drives it directly, and the server still enforces required_if so this cannot
   be bypassed by unchecking. */
.field--dating { display: none; }
form:has(#intent_dating:checked) .field--dating { display: grid; }

/* a game choice that would exceed the five-game cap */
.choice.is-capped { opacity: 0.45; cursor: not-allowed; }

/* Progress line above the form, for the narrow layout only — on desktop the
   step rail in the left pane already says where you are, and showing both
   states it twice. */
.miniprog { display: none; }

@media (max-width: 900px) {
  .miniprog {
    display: block;
    font-family: var(--font-body);
    font-size: 0.690rem;
  font-weight: 500;
    letter-spacing: 0.01em;
    color: var(--ink-3);
    margin-bottom: 0.9rem;
  }
}

/* ==========================================================================
   Liveness — the camera panel on step 2
   ========================================================================== */

.live__stage {
  position: relative;
  aspect-ratio: 4 / 3;
  max-width: 22rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--paper-2);
  overflow: hidden;
  margin-bottom: 0.9rem;
}
.live__stage video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* mirrored, because a preview that moves the wrong way is a preview nobody
     can aim */
  transform: scaleX(-1);
}
.live__idle {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  color: var(--ink-4);
  font-size: 0.78rem;
}
.live__idle svg { width: 20px; height: 20px; }

.live__msg { font-size: 0.82rem; line-height: 1.5; color: var(--ink-2); margin: 0 0 0.9rem; min-height: 1.2em; }
.live__msg--warn { color: var(--p2-ink); }

/* one prompt: the question it answers, then the answer, read as a pair */
.prompt-slot {
  border-left: 2px solid var(--line-hard);
  padding-left: 0.9rem;
  margin-bottom: 1.3rem;
}
.prompt-slot.field--bad { border-left-color: var(--p2); }
.prompt-slot .field:last-child { margin-bottom: 0; }
