/* Primitives carried over from frontend/src/styles/theme.css. Copied rather
   than imported: that file is Tailwind v4 and importing it would reintroduce a
   build step this site deliberately doesn't have. */
:root {
  --brand-500: #0076f1;
  --brand-600: #0063d1;
  --brand-700: #0050a8;

  --neutral-0: #ffffff;
  --neutral-50: #f5f8fc;
  --neutral-200: #e6ebf2;
  --neutral-300: #d3dbe6;
  --neutral-500: #5b6b80;
  --neutral-900: #0f1b2d;

  /* Widened to give the headline room to sit at 44px on one line. The lede and
     the CTA carry their own narrower max-widths, so only the headline uses it. */
  --measure: 38rem;
}

/* One variable file covers 300-900, so the headline, body, and the 600-weight
   form labels all come from a single 20KB download. The axis genuinely starts
   at 300, not 100; declaring a wider range would invite the browser to
   synthesise weights the font doesn't contain. */
@font-face {
  font-family: "Figtree";
  src: url("/fonts/figtree-variable.woff2") format("woff2");
  font-weight: 300 900;
  font-style: normal;
  /* Paints immediately in the fallback, swaps when the file lands, so text can
     never be invisible while the font loads. */
  font-display: swap;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  /* Reserve the scrollbar gutter permanently. Opening the CTA makes the page
     taller than the viewport, and without this the arriving scrollbar narrows
     the viewport by ~15px and shunts all centred content sideways. Also keeps
     this page and the scrolling privacy page horizontally aligned. */
  scrollbar-gutter: stable;
}

body {
  margin: 0;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3rem;
  padding: 3rem 1.5rem 1.5rem;

  /* Three washes anchored to the edges rather than one centred blob: asymmetry
     reads as composed instead of accidental. Grain sits over them. The grain is
     not only decoration — a wash this wide and this flat bands on large
     displays, rendering the falloff as stepped rings, and noise dithers the
     steps away. Inline SVG, so a few hundred bytes and no extra request. */
  background-color: var(--neutral-50);
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.038'/%3E%3C/svg%3E"),
    radial-gradient(
      48% 42% at 10% 6%,
      color-mix(in srgb, var(--brand-500) 11%, transparent),
      transparent 70%
    ),
    radial-gradient(
      44% 44% at 92% 22%,
      color-mix(in srgb, var(--brand-500) 8%, transparent),
      transparent 72%
    ),
    radial-gradient(
      70% 46% at 55% 104%,
      color-mix(in srgb, var(--brand-500) 7%, transparent),
      transparent 70%
    );
  background-repeat: repeat, no-repeat, no-repeat, no-repeat;

  color: var(--neutral-900);
  /* Figtree runs the whole page. A sans headline over a system-sans body would
     put two similar-but-different sans faces side by side, which reads as a
     mistake in a way a decisive serif/sans contrast does not. */
  font-family:
    "Figtree", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
    Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* The graph band across the foot of the page. A pseudo-element rather than
   markup, so all three pages get it without touching their HTML. Absolutely
   positioned, which also takes it out of body's flex flow — as a normal
   ::after it would become a flex item and push the layout around.

   Regenerate with: node tools/generate-dag-background.mjs */
body::after {
  content: "";
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 44%;
  background-image: url("/dag-band.svg");
  background-size: cover;
  background-position: center bottom;
  background-repeat: no-repeat;
  opacity: 0.1;
  /* Anchored bottom-centre so it fades upward and outward at once, rather than
     cutting a hard edge under the CTA. */
  -webkit-mask-image: radial-gradient(88% 118% at 50% 100%, #000 28%, transparent 84%);
  mask-image: radial-gradient(88% 118% at 50% 100%, #000 28%, transparent 84%);
  pointer-events: none;
  z-index: 0;
}

/* Top-anchored rather than centred. Opening the CTA adds ~290px of form, and a
   centred block absorbs half of that in each direction, so the logo, headline
   and lede would jump ~145px up on expand and back down on the confirmation
   swap. Anchoring the top means the form grows downward into space that was
   empty anyway and nothing above the button ever moves.

   The offset is what stops this reading as "pinned to the top": at 16vh the
   block sits in the upper-middle rather than jammed against the edge, and it
   clears the graph band, which owns the bottom 44%. The 14rem cap keeps tall
   displays from stranding the block near the top without pushing the expanded
   form off a 900px-tall screen, which is the tightest height where it still
   fits without scrolling. */
main {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  text-align: center;
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  padding-top: clamp(2rem, 16vh, 14rem);
}

.logo {
  width: 290px;
  max-width: 70%;
  height: auto;
  margin-bottom: 3rem;
}

/* "Scale your research revenue." measures 567px at 44px against the 608px
   --measure, clearing by 41px. Keep any copy change under that budget or the
   hero wraps: the same line was 593px at 46px, which does not fit. */
h1 {
  margin: 0;
  font-weight: 400;
  /* Floor is 1.5rem, not 1.625rem: at 26px the line clears an iPhone 14 by 7px,
     which is inside the margin where real rendering can differ from metrics.
     24px clears every common phone at 360px and up. */
  font-size: clamp(1.5rem, 5.5vw, 2.75rem);
  line-height: 1.12;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

/* 30rem, not 28rem: the lede measures 446px, which clears 28rem by only 2px.
   30rem gives it 34px of slack so it stays on one line. */
.lede {
  margin: 1.25rem auto 0;
  max-width: 30rem;
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--neutral-500);
  text-wrap: pretty;
}

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

.cta {
  margin-top: 2.5rem;
  width: 100%;
  max-width: 25rem;
}

.cta summary {
  display: inline-block;
  cursor: pointer;
  padding: 0.75rem 1.5rem;
  border: 1px solid transparent;
  border-radius: 0.5rem;
  background: var(--brand-600);
  color: var(--neutral-0);
  font-size: 0.9375rem;
  font-weight: 600;
  transition:
    background 0.15s ease,
    color 0.15s ease,
    border-color 0.15s ease;
}

.cta summary::-webkit-details-marker {
  display: none;
}
.cta summary {
  list-style: none;
}

.cta summary:hover {
  background: var(--brand-500);
}

/* Open, the summary steps down to a ghost toggle so it doesn't compete with
   Send for primary-button status. */
.cta[open] summary {
  background: transparent;
  color: var(--neutral-500);
  border-color: var(--neutral-300);
  font-weight: 500;
}

.cta[open] summary:hover {
  color: var(--neutral-900);
  border-color: var(--neutral-500);
}

form {
  margin-top: 1.5rem;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  animation: reveal-up 0.3s ease-out both;
}

label {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--neutral-900);
}

label + input,
label + textarea {
  margin-bottom: 0.875rem;
}

input,
textarea {
  width: 100%;
  padding: 0.625rem 0.75rem;
  border: 1px solid var(--neutral-300);
  border-radius: 0.5rem;
  background: var(--neutral-0);
  color: var(--neutral-900);
  font: inherit;
  font-size: 0.9375rem;
}

textarea {
  resize: vertical;
  min-height: 5.5rem;
}

input:focus,
textarea:focus {
  outline: none;
  border-color: var(--brand-500);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-500) 20%, transparent);
}

.hint {
  margin: -0.5rem 0 1rem;
  font-size: 0.75rem;
  color: var(--neutral-500);
}

button[type="submit"] {
  align-self: flex-start;
  padding: 0.75rem 1.5rem;
  border: none;
  border-radius: 0.5rem;
  background: var(--brand-600);
  color: var(--neutral-0);
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease;
}

button[type="submit"]:hover {
  background: var(--brand-500);
}

/* Confirmation, swapped in where the CTA was. Sized to sit in roughly the same
   optical space as the button so the block does not jump on success. */
.sent,
.senderr {
  margin: 2.5rem auto 0;
  max-width: 24rem;
  padding: 0.75rem 1.25rem;
  border-radius: 0.5rem;
  font-size: 0.9375rem;
  line-height: 1.5;
  animation: reveal-up 0.3s ease-out both;
}

.sent {
  border: 1px solid color-mix(in srgb, var(--brand-500) 30%, transparent);
  background: color-mix(in srgb, var(--brand-500) 7%, var(--neutral-0));
  color: var(--neutral-900);
  font-weight: 600;
}

.senderr {
  border: 1px solid var(--neutral-300);
  background: var(--neutral-0);
  color: var(--neutral-500);
}

[hidden] {
  display: none !important;
}

/* Honeypot. Positioned off-screen rather than [hidden] so that bots which skip
   hidden inputs still fill it in. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ---- footer ----------------------------------------------------------- */

/* Sits inside the band's territory, so it needs to stack above it. */
footer {
  position: relative;
  z-index: 1;
  flex-shrink: 0;
  font-size: 0.8125rem;
  color: var(--neutral-500);
}

footer a {
  color: inherit;
  text-decoration-color: var(--neutral-300);
  text-underline-offset: 0.2em;
}

footer a:hover {
  color: var(--neutral-900);
}

.sep {
  margin: 0 0.5rem;
  color: var(--neutral-300);
}

/* ---- prose (thanks / privacy) ----------------------------------------- */

.prose {
  text-align: left;
  max-width: var(--measure);
  line-height: 1.65;
  color: var(--neutral-900);
}

.prose h1 {
  font-size: clamp(1.75rem, 5vw, 2.25rem);
  margin-bottom: 1.5rem;
  text-align: left;
}

.prose h2 {
  font-size: 1rem;
  margin: 2rem 0 0.5rem;
}

.prose p {
  margin: 0 0 1rem;
  color: var(--neutral-500);
}

.prose a {
  color: var(--brand-700);
}

.back {
  display: inline-block;
  margin-top: 1.5rem;
  font-size: 0.875rem;
  color: var(--brand-700);
}

/* ---- shared ------------------------------------------------------------ */

:focus-visible {
  outline: 2px solid var(--brand-500);
  outline-offset: 2px;
}

@keyframes reveal-up {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* At 320px the headline measures 268px against 272px of content width. Buying
   the margin back from the padding keeps it on one line without shrinking the
   type on every small screen. */
@media (max-width: 380px) {
  body {
    padding-inline: 1rem;
  }
}

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