/*
 * Front door.
 *
 * A photograph of a real room, used as a background with the copy on its dark
 * side. Two rules make that work rather than fight:
 *
 *   1. The scrim is directional. It is opaque over the left third, where the
 *      words sit, and clears over the speaker. A uniform wash would have to be
 *      strong enough everywhere to make the text legible, which flattens the
 *      photo to a grey rectangle.
 *   2. The photo is cropped per device. The desktop file is a landscape band
 *      (1152x720, 13KB) and the phone file is a portrait band (780x980, 10KB),
 *      so neither device downloads pixels it will never show.
 *
 * On a phone the photo drops to a band at the foot, fading up into the canvas.
 * Full height it put her face behind the Join button.
 */

/*
 * The landing is always dark, so its palette is pinned.
 *
 * The hero is a photograph behind a dark scrim, so this copy sits on a dark
 * surface in both themes. Inheriting the theme's ink painted #18181b on
 * near-black in light mode: the headline, the wordmark and "Sign in" all
 * disappeared. This is the same rule the audience viewer already follows for
 * its deck surface — a surface that is always dark pins its own colours instead
 * of taking ones that flip.
 *
 * Declared on the shell rather than read from the theme. landing.css loads
 * after app.css, so at equal specificity these win over
 * :root[data-theme="light"], and every child that uses a token — the topbar,
 * the headline, both buttons — comes along.
 */
.shell.landing {
  --bg: #0b0b0c;
  --surface: #16161a;
  --surface-2: #1c1c1f;
  --border: #2a2a2e;
  --border-strong: #3a3a40;
  --text: #f4f4f5;
  --text-muted: #a1a1a8;
  --text-faint: #80808a;
  --accent: #4ade80;
  --accent-ink: #04140a;
  --accent-dim: #1e5f38;

  /*
   * The re-declared tokens only reach children that ask for them. app.css sets
   * `body { color: var(--text) }`, and that computes once on <body>, which is
   * outside this subtree — the headline and the wordmark inherit that finished
   * colour, not the variable. Declaring it here resets the inherited value for
   * everything below.
   */
  color: var(--text);
}

.landing {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

/*
 * Fixed behind everything on desktop. The copy sits above it via its own
 * stacking context, so the shell does not need one — a z-index on the shell
 * would trap the fixed layers inside it and paint the photo over the scrim.
 */
.landing-photo {
  position: fixed;
  inset: 0;
  z-index: 0;
  background: var(--bg);
  overflow: hidden;
}

.landing-photo img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  /* Right of centre and above centre: keeps her in the right third and her head
     clear of the header. */
  object-position: 64% 30%;
}

/*
 * Two gradients: one across, one down.
 *
 * The horizontal one is the load-bearing scrim. The vertical one only darkens
 * the header strip and seats the buttons at the foot so they do not float on a
 * bright patch of wall.
 */
.landing-scrim {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(
      90deg,
      rgba(11, 11, 12, 0.86) 0%,
      rgba(11, 11, 12, 0.74) 26%,
      rgba(11, 11, 12, 0.34) 48%,
      rgba(11, 11, 12, 0.04) 70%,
      rgba(11, 11, 12, 0) 100%
    ),
    linear-gradient(
      180deg,
      rgba(11, 11, 12, 0.42) 0%,
      rgba(11, 11, 12, 0.06) 18%,
      rgba(11, 11, 12, 0) 55%,
      rgba(11, 11, 12, 0.55) 100%
    );
}

.shell.landing {
  position: relative;
  /*
   * Paint the pinned canvas, and do not rely on the photograph to paint it.
   *
   * On desktop the photo is fixed and covers the viewport, so the page's own
   * background was never visible. On a phone the photo becomes a band below the
   * copy instead, and the copy was then sitting on whatever the theme painted the
   * page — near-white in light mode — while its text stayed the pinned #f4f4f5.
   * The headline, the subhead and "or" were all invisible on a phone with the
   * light theme on, which is a supported choice, not an edge case.
   */
  background: var(--bg);
}

/* ------------------------------------------------------------------- copy */

.landing-main {
  position: relative;
  z-index: 2;
  width: min(1120px, calc(100% - 2 * var(--space-5)));
  margin: 0 auto;
  min-height: calc(100dvh - 57px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 0 clamp(40px, 8vh, 96px);
}

/* Half the width: the other half belongs to her. */
.landing-copy {
  max-width: min(620px, 50vw);
}

.landing-intro h1 {
  font-size: clamp(40px, 6.4vw, 84px);
  font-weight: 620;
  letter-spacing: -0.05em;
  line-height: 0.96;
  margin: 0 0 var(--space-5);
  max-width: 12ch;
}

.landing-intro p {
  margin: 0;
  font-size: clamp(16px, 1.5vw, 20px);
  line-height: 1.45;
  color: var(--text-muted);
  max-width: 30ch;
}

.landing-actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
  padding-top: var(--space-6);
  /* Lifted off the page's hairline: over a photograph the border token vanishes. */
  border-top: 1px solid rgba(255, 255, 255, 0.16);
}

.landing-join-btn,
.landing-present-btn {
  flex: none;
  height: 52px;
  padding: 0 var(--space-6);
}

.landing-or {
  font-size: 13px;
  color: var(--text-faint);
}

/*
 * The brand sign-off.
 *
 * 40px is the floor for the reflection — below it the mirrored letterforms stop
 * resolving. The margin is generous because this is a colophon, not content.
 */
.landing-sign {
  margin-top: clamp(40px, 7vh, 72px);
}

.landing-sign .wm {
  font-size: 40px;
}

@media (max-width: 860px) {
  /*
   * Dropped on a phone, where the sign-off landed immediately above the photo
   * band as a bare wordmark with no reflection to explain it. It read as a
   * stray logo rather than a signature.
   */
  .landing-sign {
    display: none;
  }
}

/* ---------------------------------------------------------------- phones */

@media (max-width: 860px) {
  /*
   * In the flow, under the copy, taking whatever height is left. A fixed
   * 58vh band overlapped the buttons on a short screen and put her face behind
   * them; this cannot, at any phone height.
   */
  .landing-photo {
    position: relative;
    inset: auto;
    flex: 1 1 auto;
    min-height: 190px;
    width: 100%;
  }

  .landing-photo img {
    position: absolute;
    inset: 0;
    /*
     * Anchored to the top of the band, not the middle.
     *
     * The band's height is whatever the copy leaves, so it grows on a tall
     * phone. Centring her in it pushed her to 60% of the band with dead wall
     * above; anchoring the asset's top to the band's top keeps her near the
     * ceiling at every phone height.
     */
    object-position: 62% 0%;
  }

  /*
   * Blend the band's own top edge into the canvas.
   *
   * This replaced a tall scrim fade. The fade was doing two jobs at once —
   * hiding the seam and darkening the top of the photo — and the second half
   * put a dead black strip above her. Fading only the first ~90px does the seam
   * and nothing else.
   */
  .landing-photo::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    /* Short, because her head is only ~9% down the crop. */
    height: 34px;
    z-index: 1;
    background: linear-gradient(180deg, var(--bg) 0%, rgba(11, 11, 12, 0) 100%);
  }

  /* Nothing overlaps the words on a phone, so no scrim is needed at all. */
  .landing-scrim {
    display: none;
  }

  .landing-copy {
    max-width: none;
  }

  /*
   * Both selectors carry the extra class deliberately.
   *
   * app.css sets `.shell > main { flex: 1 }`, which outranks a bare
   * `.landing-main` (0-1-1 beats 0-1-0). The copy kept growing to fill the
   * phone, so the band sat at its 190px minimum with a 233px void above it —
   * the dead space above her head. Matching the specificity lets the band take
   * the leftover height instead.
   */
  .shell.landing .landing-main {
    flex: none;
    justify-content: flex-start;
    min-height: 0;
    padding: clamp(16px, 4vh, 40px) 0 var(--space-5);
  }

  .shell.landing .landing-photo {
    flex: 1 1 auto;
  }

  .landing-intro h1 {
    max-width: 14ch;
  }

  .landing-actions {
    flex-direction: column;
    align-items: stretch;
  }

  .landing-join-btn,
  .landing-present-btn {
    width: 100%;
    height: 48px;
  }

  .landing-or {
    text-align: center;
  }
}

/* Join dialog */

.landing-join-dialog {
  max-width: 400px;
  width: calc(100% - 2 * var(--space-4));
  padding: 0;
}

.landing-join-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-5);
}

.landing-join-head h2 {
  margin: 0;
}

.landing-join-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
}

.landing-join-actions .btn {
  min-width: 88px;
}

@media (prefers-reduced-motion: no-preference) {
  .landing-copy {
    animation: landing-in 560ms cubic-bezier(0.32, 0.72, 0, 1) both;
  }
}

@keyframes landing-in {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .landing-copy {
    animation: none;
  }
}
