/* ROOFTOP QUEST — the landing screen.
 *
 * Owned by src/ui/landing.js. Everything here is prefixed .ld- and every colour,
 * space and radius comes from assets/theme.css; if a value below is a raw number
 * it is a geometry decision (a swatch is 30px) and not a colour.
 *
 * The screen floats over a live 3D orbit of the course, so:
 *
 *  - the root has no opaque background. The legibility comes from two gradients
 *    — one from the left behind the copy, one from the bottom behind the footer
 *    — which keep cream text readable over a sky that runs cyan to hot pink
 *    without ever looking like a modal.
 *  - backdrop-filter is expensive over a canvas that is repainting every frame,
 *    so only .card surfaces get it (theme.css does that) and there are exactly
 *    two of them: the customiser and the how-to panel. Chips, the segmented
 *    control and the footer use flat translucent fills instead.
 */

/* ==================================================================== shell */

.ld {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: var(--s-4);
  padding: var(--gutter);
  overflow-y: auto;
  overscroll-behavior: contain;

  /* Left scrim for the copy, bottom scrim for the footer. Both stop well short
   * of the right edge so the course stays visible where the eye is not reading. */
  background:
    linear-gradient(100deg,
      rgba(18, 14, 32, 0.76) 0%,
      rgba(18, 14, 32, 0.5) 34%,
      rgba(18, 14, 32, 0.12) 62%,
      rgba(18, 14, 32, 0) 78%),
    linear-gradient(0deg,
      rgba(18, 14, 32, 0.6) 0%,
      rgba(18, 14, 32, 0.16) 22%,
      rgba(18, 14, 32, 0) 44%);
}

/* TRAP: `.ld` sets display:grid, which beats the user-agent `[hidden]` rule on
 * specificity. Without this line landing.hide() does nothing at all and the
 * title sits over the whole race. */
.ld[hidden] { display: none; }

/* The entry animation is replayed by removing and re-adding .is-shown, so every
 * animated part must live under it — see show() in src/ui/landing.js. */
.ld.is-shown .ld__top { animation: ps-drop-in var(--dur-3) var(--ease-out) both; }
.ld.is-shown .ld-hero { animation: ps-rise-in var(--dur-4) var(--ease-out) both; }
.ld.is-shown .ld-look { animation: ps-rise-in var(--dur-4) 90ms var(--ease-out) both; }
.ld.is-shown .ld__foot { animation: ps-fade-in var(--dur-4) 160ms var(--ease-out) both; }

/* theme.css sizes `.icon`, but src/ui/icons.js emits `.ico`. That is not a typo
 * in either file — `.icon` is the wrapper-span contract — but nothing the icon
 * set produces matches it, so the landing sizes `.ico` itself. Without this
 * every glyph falls back to its 1em presentation attribute and the round
 * buttons get a 15px icon in a 44px circle. */
.ld .ico {
  display: block;
  flex: 0 0 auto;
  width: var(--icon-size);
  height: var(--icon-size);
  color: inherit;
}

/* ============================================================ top: brand row */

.ld__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
}

.ld-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  color: var(--c-cream);
}

/* The house mark is the same glyph every racer wears, just fattened. Stroke
 * weight is the only difference — a second, heavier copy of the path would be
 * one more thing to keep in step with icons.js. */
.ld-brand__mark {
  --icon-size: 34px;
  color: var(--c-green);
  stroke-width: 2.4;
  filter: drop-shadow(0 2px 0 rgba(18, 14, 32, 0.55));
}

.ld-brand__word {
  font-family: var(--display);
  font-size: var(--fs-xl);
  font-weight: var(--fw-black);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-shadow: var(--sh-text);
}

.ld-tools { display: flex; gap: var(--s-2); }

/* ================================================================ the middle
 *
 * Two columns: the copy sits vertically centred on the left, the customiser
 * pins to the bottom-right corner. Below 900px both fall into one column and
 * the card follows the copy in the flow. */

/* TRAP: No `min-height: 0` on this row. It lets the row shrink under its own
 * content, and because the items are centred in it the hero then overflows in
 * BOTH directions — on a phone the eyebrow ends up printed across the brand
 * lockup. Left alone, the row grows, the grid gets taller than the viewport and
 * `.ld` scrolls, which is what should happen. */
.ld__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s-6);
}

/* ------------------------------------------------------------------- hero */

.ld-hero {
  align-self: center;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-4);
  max-width: 46rem;
}

.ld-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  margin: 0;
  font-size: var(--fs-2xs);
  font-weight: var(--fw-black);
  letter-spacing: var(--tr-caps);
  text-transform: uppercase;
  color: var(--c-text-dim);
}

.ld-eyebrow--sm { color: var(--c-text-mute); }

.ld-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--c-green);
  box-shadow: 0 0 0 4px rgba(92, 192, 106, 0.2);
  animation: ps-pulse 2.4s var(--ease-out) infinite;
}

/* ------------------------------------------------------------------ title */

.ld-title {
  /* Tilted from the left so the two lines stay a lockup rather than a stack of
   * separately-rotated words. */
  transform: rotate(-2deg);
  transform-origin: 0 50%;
  margin: calc(var(--s-1) * -1) 0 var(--s-1);
  font-family: var(--display);
  font-size: clamp(2.75rem, 12vw, 8rem);
  font-weight: var(--fw-black);
  line-height: 0.86;
  letter-spacing: var(--tr-title);
  text-transform: uppercase;
}

.ld-title__line {
  position: relative;
  display: block;
  width: max-content;
  max-width: 100%;
}

/* The dark outline. A duplicate of the line painted underneath in stroke-only
 * form, rather than paint-order on the line itself — the "!" is a differently
 * coloured child span, and paint-order would need its own stroke to match,
 * which shows as a seam between the E and the bang at display size.
 *
 * z-index -1 puts it behind the real glyphs but still above .ld's own gradient,
 * because a negative-z child paints after the stacking context's background. */
.ld-title__line::before {
  content: attr(data-text);
  position: absolute;
  left: 0;
  top: 0;
  z-index: -1;
  color: transparent;
  -webkit-text-stroke: 0.085em var(--c-ink-2);
  text-shadow: 0 0.05em 0 var(--c-ink-2);
  pointer-events: none;
}

.ld-title__line--a { color: var(--c-cream); }
.ld-title__line--b { color: var(--c-green); margin-left: 0.06em; }
.ld-title__bang { color: var(--c-pink-hot); }

/* ------------------------------------------------------------------ blurb */

.ld-blurb {
  max-width: 34ch;
  font-size: var(--fs-lg);
  line-height: 1.42;
  color: var(--c-text-dim);
  text-shadow: 0 1px 2px rgba(18, 14, 32, 0.45);
}

/* ------------------------------------------------------------------ stats */

.ld-stats {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}

.ld-stat { color: var(--c-text); }
.ld-stat .ico { color: var(--c-green); }

/* -------------------------------------------------------- segmented toggle */

.ld-seg {
  display: inline-flex;
  gap: var(--s-1);
  padding: var(--s-1);
  border-radius: var(--r-pill);
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  box-shadow: var(--sh-1);
}

.ld-seg__b {
  padding: var(--s-2) var(--s-5);
  border-radius: var(--r-pill);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-black);
  letter-spacing: var(--tr-caps);
  text-transform: uppercase;
  color: var(--c-text-mute);
  white-space: nowrap;
  transition:
    color var(--dur-1) var(--ease-out),
    background-color var(--dur-2) var(--ease-out);
}

.ld-seg__b:hover { color: var(--c-text); }

.ld-seg__b.is-on {
  background: var(--c-cream);
  color: var(--c-text-on-light);
  box-shadow: var(--sh-1);
}

/* -------------------------------------------------------------------- CTA */

.ld-go {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-4) var(--s-5);
  margin-top: var(--s-1);
}

.ld-cta { padding-right: var(--s-6); }

.ld-cta__arrow {
  margin-left: var(--s-1);
  transition: transform var(--dur-2) var(--ease-pop);
}

.ld-cta:hover .ld-cta__arrow { transform: translateX(4px); }

.ld-help {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  --icon-size: 18px;
  padding: var(--s-2) 0;
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  color: var(--c-text-dim);
  border-bottom: 2px solid transparent;
  transition: color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}

.ld-help:hover { color: var(--c-cream); border-bottom-color: var(--c-line-strong); }

/* ============================================================== customiser */

.ld-look {
  align-self: end;
  justify-self: end;
  width: min(340px, 100%);
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.ld-look__label {
  margin-top: var(--s-1);
  color: var(--c-cream);
  font-size: var(--fs-xs);
}

.ld-look .t-label { margin-top: var(--s-2); }

.ld-name {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  --icon-size: 18px;
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-md);
  background: rgba(18, 14, 32, 0.5);
  border: 1px solid var(--c-line-strong);
  transition: border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}

.ld-name:focus-within { border-color: var(--c-green); box-shadow: var(--ring); }
.ld-name__ico { color: var(--c-green); }

.ld-name__input {
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;
  font-size: var(--fs-md);
  font-weight: var(--fw-black);
  letter-spacing: var(--tr-tight);
  color: var(--c-cream);
}

.ld-name__input::placeholder { color: var(--c-text-mute); font-weight: var(--fw-mid); }
.ld-name__input:focus-visible { box-shadow: none; }

/* --------------------------------------------------------------- swatches */

.ld-sw {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}

.ld-sw__b {
  position: relative;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--sw);
  /* The darker half of the pair from shared/course.js, used as the rim. Two
   * pastels side by side need that edge or the row reads as one smear. */
  border: 2px solid var(--sw-edge);
  box-shadow: 0 2px 0 rgba(18, 14, 32, 0.4);
  transition: transform var(--dur-1) var(--ease-pop), box-shadow var(--dur-1) var(--ease-out);
}

.ld-sw__b:hover { transform: translateY(-2px); }
.ld-sw__b:active { transform: translateY(1px); box-shadow: none; }

/* The roof swatch is a roof: the ridge colour caps the top third. */
.ld-sw__b--roof {
  border-radius: var(--r-xs);
  background: linear-gradient(180deg, var(--sw-edge) 0 34%, var(--sw) 34% 100%);
}

.ld-sw__b.is-on {
  box-shadow: 0 0 0 3px var(--c-cream), 0 3px 0 rgba(18, 14, 32, 0.4);
}

/* The tick is in the DOM from the first paint and only ever changes opacity —
 * selecting a swatch must not touch innerHTML in a click handler. */
.ld-sw__tick {
  --icon-size: 18px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%) scale(0.4);
  opacity: 0;
  color: var(--c-ink-2);
  stroke-width: 3.2;
  transition: opacity var(--dur-1) var(--ease-out), transform var(--dur-2) var(--ease-pop);
}

.ld-sw__b.is-on .ld-sw__tick { opacity: 1; transform: translate(-50%, -50%) scale(1); }

/* =================================================================== footer */

.ld__foot {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--s-3);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-black);
  letter-spacing: var(--tr-caps);
  text-transform: uppercase;
  color: var(--c-text-mute);
}

.ld-foot__tag { justify-self: start; }
.ld-foot__tag b { color: var(--c-cream); font-weight: var(--fw-black); }
.ld-foot__sep { margin: 0 var(--s-2); color: var(--c-green); }
.ld-foot__line { justify-self: center; text-align: center; }

.ld-foot__keys {
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  --icon-size: 16px;
  font-size: inherit;
  font-weight: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: var(--c-text-dim);
  transition: color var(--dur-1) var(--ease-out);
}

.ld-foot__keys:hover { color: var(--c-cream); }

/* =============================================================== how to play */

.ld-how {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  place-items: center;
  padding: var(--gutter);
}

/* Same trap as .ld above: this rule is what makes `hidden` work on a grid. */
.ld-how[hidden] { display: none; }

.ld-how__scrim {
  position: absolute;
  inset: 0;
  background: rgba(18, 14, 32, 0.62);
  animation: ps-fade-in var(--dur-2) var(--ease-out) both;
}

.ld-how__panel {
  position: relative;
  width: min(520px, 100%);
  max-height: min(80vh, 660px);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  animation: ps-pop-in var(--dur-3) var(--ease-pop) both;
}

.ld-how__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
}

.ld-how__x {
  --icon-size: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--c-surface-3);
  color: var(--c-text-dim);
  transition: color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}

.ld-how__x:hover { color: var(--c-text); background: var(--c-line); }

.ld-how__lede { font-size: var(--fs-sm); color: var(--c-text-dim); }

.ld-keys {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}

.ld-zones {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.ld-zone {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
}

.ld-zone__n {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: var(--r-xs);
  background: var(--c-green-deep);
  color: var(--c-cream);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-black);
  font-variant-numeric: tabular-nums;
}

.ld-zone__txt { display: flex; flex-direction: column; }

.ld-zone__name {
  font-size: var(--fs-xs);
  font-weight: var(--fw-black);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: var(--c-cream);
}

.ld-zone__hint { font-size: var(--fs-sm); color: var(--c-text-dim); }

/* =============================================================== responsive
 *
 * One breakpoint moves the customiser out of the corner and into the flow;
 * everything else is already fluid (the title clamps, the chips wrap). */

@media (max-width: 900px) {
  .ld { gap: var(--s-5); }

  /* Stacked, the copy plus the card is taller than a phone, so start it under
   * the brand row and let the overlay scroll rather than centring a column
   * that does not fit. */
  .ld__body {
    grid-template-columns: minmax(0, 1fr);
    align-content: start;
    gap: var(--s-5);
    padding-block: var(--s-4);
  }

  .ld-look {
    align-self: start;
    justify-self: start;
    width: min(420px, 100%);
  }

  .ld-hero { max-width: none; }

  /* The centre line is the first thing to go: on a phone the tag and the
   * controls button are the only two that earn their width. */
  .ld-foot__line { display: none; }
  .ld__foot { grid-template-columns: 1fr auto; }
}

@media (max-width: 520px) {
  .ld-brand__mark { --icon-size: 28px; }
  .ld-brand__word { font-size: var(--fs-lg); }
  .ld-tool { width: 38px; height: 38px; --icon-size: 18px; }
  .ld-blurb { font-size: var(--fs-md); }
  .ld-cta { width: 100%; }
  .ld-go { gap: var(--s-3); }
  .ld-seg__b { padding: var(--s-2) var(--s-4); }
  .ld-zone__hint { font-size: var(--fs-xs); }
}

/* The swatch row is the thing that breaks first: eight 30px circles plus gaps
 * do not fit a card inside a 12px gutter, so they shrink rather than wrap into
 * a ragged 7-and-1. 26 + 6 x 7 clears 320px, which is the narrowest phone worth
 * caring about — measure before nudging either number. */
@media (max-width: 400px) {
  .ld-sw__b { width: 26px; height: 26px; }
  .ld-sw { gap: 6px; }
  .ld-sw__tick { --icon-size: 16px; }
  .ld-foot__tag { font-size: var(--fs-3xs); }
}
