/*
  Gander — coming soon.

  Ported from Waitlist.dc.html. The design carried its styles as inline
  attributes on each element; they are collected here so the markup stays
  readable, with the values kept verbatim — the clamp() ramps, the
  cubic-bezier(0.16, 1, 0.3, 1) easing, the greys and the type scale are all
  the design's own.
*/

/*
  FK Grotesk, self-hosted from the design's own files. `font-display: swap`
  matches the source: the page renders immediately in the fallback and swaps
  when the face lands, which matters here because the headline is the first
  thing on screen.
*/
@font-face {
  font-family: 'FK Grotesk';
  src: url('/assets/fonts/FK-Grotesk-300-normal.ttf') format('truetype');
  font-weight: 300;
  font-display: swap;
}
@font-face {
  font-family: 'FK Grotesk';
  src: url('/assets/fonts/FK-Grotesk-400-normal.ttf') format('truetype');
  font-weight: 400 600;
  font-display: swap;
}
@font-face {
  font-family: 'FK Grotesk Mono';
  src: url('/assets/fonts/FK-Grotesk-Mono-400-normal.ttf') format('truetype');
  font-weight: 400 500;
  font-display: swap;
}

:root {
  --ink: #000000;
  --paper: #ffffff;
  --grey: #9b9b9b;   /* Eyebrow, fine print. */
  --rule: #c6c6c6;   /* The line under an input. */
  --ghost: #cecece;  /* Placeholder text. */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

* { box-sizing: border-box; }

/*
  `hidden` has to beat the layout rules in this file.
  
  The UA sheet's `[hidden] { display: none }` loses to any author rule that
  sets `display` — `.form { display: flex }` did exactly that, so hiding the
  form on success left it sitting under the confirmation message.
*/
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--paper);
}

body {
  font-family: 'FK Grotesk', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}

::selection { background: #000; color: #fff; }

input { font: inherit; }
input::placeholder { color: var(--ghost); }

/*
  The design fixes the shell at `height: 100svh` with `overflow: hidden`, which
  is right for its single-field form. This build asks two more questions, and
  on a short viewport those extra fields would be clipped with no way to reach
  them — so the height is a MINIMUM and the page may scroll in the rare case it
  has to. On every normal screen it still fills exactly one viewport and never
  scrolls, which is the intent.
*/
.shell {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  background: var(--paper);
}

/* ---------------------------------------------------------------- header */

.header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: clamp(20px, 3.4vw, 26px) clamp(20px, 4vw, 32px);
  flex: none;
}

.wordmark {
  height: clamp(15px, 3.4vw, 20px);
  width: auto;
  display: block;
}

.eyebrow,
.hint {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--grey);
  line-height: 1.2;
}

/* ------------------------------------------------------------------ main */

.main {
  flex: 1 1 auto;
  min-height: fit-content;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: 20px clamp(20px, 4vw, 32px);
  text-align: center;
  animation: gander-up 560ms var(--ease) both;
}

.headline {
  max-width: 17ch;
  margin: 0;
  font-size: clamp(30px, 6.4vw, 60px);
  line-height: 1.04;
  letter-spacing: -0.03em;
  font-weight: 300;
  text-wrap: pretty;
}

.done {
  margin: 30px 0 0;
  font-size: 16px;
  line-height: 1.6;
  letter-spacing: -0.004em;
  animation: gander-up 500ms var(--ease) both;
}

/* ------------------------------------------------------------------ form */

.form {
  margin-top: clamp(26px, 4vw, 34px);
  width: 100%;
  max-width: 400px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
}

/* An input and (optionally) the button, sharing one rule beneath them. */
.field {
  display: flex;
  align-items: center;
  gap: 10px;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 11px;
}

.field input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  font-size: 16px; /* Under 16px iOS zooms the page on focus. */
  line-height: 1.4;
  letter-spacing: -0.004em;
  color: var(--ink);
  padding: 0;
}

/*
  The rule is the only affordance an input has here, so focus has to move it —
  a focus ring would be foreign to this design, but leaving focus invisible
  would be worse. The line goes black and doubles in weight without shifting
  layout, because the extra pixel is drawn as a box-shadow rather than a border.
*/
.field:focus-within {
  border-bottom-color: var(--ink);
  box-shadow: 0 1px 0 0 var(--ink);
}

.submit {
  flex: none;
  border: 0;
  cursor: pointer;
  background: var(--ink);
  color: var(--paper);
  border-radius: 999px;
  padding: 11px 18px;
  min-height: 44px; /* Comfortable touch target. */
  font-size: 13px;
  letter-spacing: 0.01em;
  white-space: nowrap;
  font-family: inherit;
  transition: opacity 160ms var(--ease), transform 120ms var(--ease);
}

.submit:hover { opacity: 0.6; }
.submit:active { transform: scale(0.98); }
.submit:disabled { opacity: 0.4; cursor: default; transform: none; }

.submit:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

.hint {
  margin: 0;
  text-align: left;
}

/* The error is the design's own signal on this line: it turns black. */
.hint.is-error { color: var(--ink); }

/*
  Step two.

  grid-template-rows 0fr -> 1fr animates to the content's real height; a
  max-height guess would either clip on a wrapped field or lag on a tall one.
*/
.more {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows 340ms var(--ease), opacity 240ms var(--ease),
    margin-bottom 340ms var(--ease);
}

/*
  A zero-height flex child still earns a gap from the form, which would push
  the fine print 12px further down than the design puts it. Cancelling the gap
  while collapsed keeps step one pixel-identical to Waitlist.dc.html, and the
  margin animates back to zero in step with the panel opening.
*/
.more:not(.is-open) { margin-bottom: -12px; }

.more-inner {
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.more.is-open {
  grid-template-rows: 1fr;
  opacity: 1;
}

/* The email is banked; it stays legible as confirmation but is no longer live. */
#email:read-only { color: var(--grey); }

/* ------------------------------------------------------------------- arc */

/*
  A window onto the top of a large circle. The cards are positioned at the
  circle's centre and pushed outward by translateY(-radius), so `overflow:
  hidden` here crops everything but the crown of the arch. Height and radius
  are set from JS, which owns the responsive geometry.
*/
.arc {
  position: relative;
  flex: none;
  height: 300px;
  overflow: hidden;
  perspective: 1600px;
  cursor: grab;
  touch-action: pan-y; /* Vertical scrolling still belongs to the page. */
}

.arc.is-dragging { cursor: grabbing; }

.arc-card {
  position: absolute;
  left: 50%;
  top: 1052px; /* Replaced by JS as radius + apex; a sane value pre-hydration. */
  width: 178px;
  height: 238px;
  transform-style: preserve-3d;
  will-change: transform, opacity;
}

.arc-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 14px;
  display: block;
  box-shadow: 0 40px 40px -20px rgba(0, 0, 0, 0.04);
  /* The arc is draggable; without this the browser drags the image instead. */
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}

/* ---------------------------------------------------------------- motion */

@keyframes gander-up {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    transition-duration: 1ms !important;
  }
}

/* ------------------------------------------------------------- honeypot */

/*
  Positioned off-screen rather than display:none — some bots skip fields that
  are obviously not rendered. aria-hidden and tabindex="-1" in the markup keep
  it away from real users.
*/
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
