/* Panenkam waitlist page. Colours, sizes and fonts come from tokens.css (design/tokens.json): the
   Floodlight dark palette, with lime as the only accent. Written for a phone first; wider screens add
   columns. Nothing here names a colour: tools/tests/test_tokens.py fails on a literal. */

*, *::before, *::after { box-sizing: border-box; }
/* `hidden` must win over the display rules below. */
[hidden] { display: none !important; }

html {
  background: var(--bg);
  color: var(--text);
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  scroll-behavior: smooth;
  scroll-padding-top: var(--space-5);
  /* How long one change of the headline's word takes; public/rotator.js holds the same figure. */
  --rot-ms: 420ms;
}

body {
  margin: 0;
  min-height: 100svh;
  font: 400 var(--site-field)/1.55 var(--font-body);
  /* One soft floodlight over the top of the page, from the wallpaper tokens. */
  background:
    radial-gradient(90% 60% at 88% -12%, var(--wall-glow-c), transparent 70%),
    radial-gradient(60% 40% at 6% -8%, var(--wall-glow-b), transparent 72%)
    var(--bg);
  background-repeat: no-repeat;
  background-size: 100% 150svh;
  overflow-wrap: break-word;
}

h1, h2, h3, p, ul, figure { margin: 0; }
ul { padding: 0; list-style: none; }
a { color: inherit; text-underline-offset: 0.18em; text-decoration-thickness: 1px; }
a:hover { text-decoration-thickness: 2px; }
:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 3px; border-radius: var(--space-1); }

.wrap {
  width: min(100% - 2 * var(--site-gutter), var(--site-page));
  margin-inline: auto;
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

.skip {
  position: absolute; left: var(--space-3); top: var(--space-3); z-index: 2;
  padding: var(--space-3) var(--space-4); border-radius: var(--radius-sm);
  background: var(--accent-fill); color: var(--on-accent); font-weight: 600;
  transform: translateY(-200%);
}
.skip:focus { transform: none; }

/* ---------- buttons ---------- */

.button {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap); padding: 0 var(--space-5);
  border: 0; border-radius: var(--radius-sm);
  background: var(--accent-fill); color: var(--on-accent);
  font: 700 var(--type-label)/1 var(--font-display); letter-spacing: 0.06em; text-transform: uppercase;
  text-decoration: none; white-space: nowrap; cursor: pointer; touch-action: manipulation;
  transition: background-color 120ms ease, transform 120ms ease;
}
.button:hover { background: color-mix(in srgb, var(--accent-fill) 86%, var(--text)); }
.button:active { transform: scale(0.98); }
/* While a signup is being sent the button stays focusable (aria-disabled), so focus is not lost. */
.button[disabled], .button[aria-disabled="true"] {
  background: var(--disabled-fill); color: var(--disabled-ink); cursor: default; transform: none;
}
.button.small { min-height: var(--tap-sm); padding: 0 var(--space-4); font-size: var(--type-label-s); }

.quiet {
  display: inline-flex; align-items: center; gap: var(--space-2);
  min-height: var(--tap-sm); padding: 0 var(--space-3);
  border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--muted);
  font: 500 var(--site-small)/1 var(--font-body); cursor: pointer; touch-action: manipulation;
}
.quiet:hover { color: var(--text); background: var(--pressed-scrim); }
/* Two bars while it is moving (press to pause); a triangle once paused (press to play). */
.motion-glyph {
  width: var(--space-3); height: var(--space-3);
  border-inline: var(--space-1) solid currentColor;
}
.quiet[data-paused] .motion-glyph {
  border-inline: 0; background: currentColor; clip-path: polygon(0 0, 100% 50%, 0 100%);
}

/* ---------- top bar ---------- */

.top {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  padding-block: calc(var(--space-4) + env(safe-area-inset-top)) var(--space-4);
}
.brand { display: inline-flex; align-items: center; gap: var(--space-3); min-height: var(--tap-sm); text-decoration: none; }
/* The Chip: a Panenka's flight in primary ink and the ball in lime, as on the app icon. */
.chip { width: var(--space-6); height: auto; flex: none; overflow: visible; }
.chip-curve { fill: none; stroke: var(--text); stroke-width: 95.7; stroke-linecap: round; }
.chip-ball { fill: var(--accent); }
.wordmark {
  font: 850 var(--type-label)/1 var(--font-display); font-stretch: 125%;
  letter-spacing: 0.1em; text-transform: uppercase;
}
/* On a narrow phone the hero's own button is one thumb away; a second one up here only crowds the name. */
.top-join { display: none; }

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

.hero { padding-block: clamp(var(--space-6), 9vw, var(--site-section-min)) var(--space-6); }
.eyebrow {
  margin-bottom: var(--space-4);
  font: 500 var(--type-label-s)/1.3 var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--muted);
}
.tagline {
  /* Part rem, part viewport, so the headline answers to the reader's text size as well as the window. */
  font: 800 clamp(var(--site-hero-min), 1.25rem + 7.4vw, var(--site-hero-max))/0.98 var(--font-display);
  letter-spacing: -0.035em;
}
.tagline .line { display: block; }

/* The changing word. It is the last thing on its line, so the room kept for the longest word is empty
   space to its right, never a gap in the sentence. */
.rot {
  display: inline-grid; position: relative; vertical-align: baseline;
  color: var(--accent);
  /* Room for descenders inside the clip, given back to the line outside it. */
  padding-block: 0.12em; margin-block: -0.12em;
  overflow: hidden;
}
/* Before the script runs (and when it never does): the word itself, and an unseen copy of the widest.
   In Archivo at this weight the widest of the five is "match" itself, measured in a browser; if the words
   or the font change, measure again and name the widest in data-longest. */
.rot::after {
  content: attr(data-longest); grid-area: 1 / 1; visibility: hidden; height: 0; overflow: hidden;
}
.rot-stage { grid-area: 1 / 1; display: grid; }
.rot-word {
  grid-area: 1 / 1;
  transform: translateY(115%); opacity: 0;
  transition: transform var(--rot-ms) cubic-bezier(0.2, 0.7, 0.2, 1), opacity calc(var(--rot-ms) * 0.7) ease;
}
.rot-word.is-on { transform: none; opacity: 1; }
.rot-word.is-out { transform: translateY(-115%); opacity: 0; }
.rot-word.is-reset { transition: none; }
/* A word on its way out is drawn from an attribute, so the page's text holds one word at a time and the
   sentence reads right to anything that reads text: copy and paste, translation, reader view. */
.rot-word[data-word]::before { content: attr(data-word); }

.lead {
  max-width: var(--site-measure); margin-top: var(--space-5);
  font: 400 clamp(var(--site-lead-min), 0.95rem + 0.8vw, var(--site-lead-max))/1.45 var(--font-body);
}
.hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) var(--space-4); margin-top: var(--space-6); }

/* ---------- demo clip ---------- */

.demo-frame {
  position: relative; overflow: hidden;
  /* A phone gets the tall cut, kept to a phone's width so it reads as a screen and not a wall. */
  aspect-ratio: 9 / 16; width: min(100%, 21rem); margin-inline: auto;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface);
}
.demo.has-clip .demo-frame { background: var(--video-backdrop); }
/* Until there is a clip the tall frame is kept small, so a phone is not handed a screenful of nothing. */
.demo:not(.has-clip) .demo-frame { width: min(100%, 15rem); }
/* Only one cut exists: keep its shape at every width (these also outrank the wider-screen rule below). */
.demo.only-wide .demo-frame { aspect-ratio: 16 / 9; width: 100%; }
.demo.has-clip.only-tall .demo-frame { aspect-ratio: 9 / 16; width: min(100%, 21rem); }
.demo video { display: block; width: 100%; height: 100%; object-fit: cover; }

.demo-placeholder { position: absolute; inset: 0; display: grid; place-items: center; }
.pitch { position: absolute; inset: 0; width: 100%; height: 100%; }
.pitch-wide { display: none; }
.pitch-line { fill: none; stroke: var(--border); stroke-width: 1; vector-effect: non-scaling-stroke; }
.follow-frame { fill: none; stroke: var(--accent); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.follow-ball { fill: var(--accent); }
/* The follow view drifts across the pitch with the ball, slowly. Only once the script has turned motion
   on, because the script is also what offers the button that pauses it. */
[data-motion="on"] .follow { animation: follow-tall 14s ease-in-out infinite alternate; }
@keyframes follow-tall { from { transform: translateY(-46%); } to { transform: translateY(6%); } }
@keyframes follow-wide { from { transform: translateX(-46%); } to { transform: translateX(6%); } }
.demo-note {
  position: absolute; inset: auto var(--space-4) var(--space-4); display: flex; flex-direction: column; gap: var(--space-2);
  font-size: var(--site-small); line-height: 1.4; color: var(--muted);
}
.demo-tag {
  font: 500 var(--type-label-s)/1 var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent);
}

/* ---------- the points ---------- */

.points { padding-block: var(--site-section-min) 0; }
.point-list { display: grid; gap: var(--space-5); }
.point-list li { padding-top: var(--space-5); border-top: 1px solid var(--border); }
.point-list h3 { font: 700 var(--type-display-m)/1.15 var(--font-display); letter-spacing: -0.01em; text-wrap: balance; }
.point-list p { margin-top: var(--space-2); color: var(--muted); }
.sports {
  margin-top: var(--space-6);
  font: 500 var(--type-label-s)/1.3 var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--muted);
}

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

.join { display: grid; gap: var(--space-6); padding-block: var(--site-section-min); }
.join-copy h2 {
  font: 800 clamp(var(--site-heading-min), 1rem + 3vw, var(--site-heading-max))/1.02 var(--font-display);
  letter-spacing: -0.025em;
}
.join-copy p { max-width: var(--site-measure); margin-top: var(--space-3); color: var(--muted); }
.join-copy .founding { color: var(--text); font-weight: 600; }

form { display: grid; gap: var(--space-5); }
.field-row { display: grid; gap: var(--space-5); }
.field { min-width: 0; }
.field label { display: block; margin-bottom: var(--space-2); font: 600 var(--type-body)/1.35 var(--font-body); }
.optional { margin-left: var(--space-1); font-weight: 400; color: var(--muted); }

input[type="email"], input[type="text"], select {
  display: block; width: 100%; min-height: var(--tap); padding: 0 var(--space-4);
  border: 1.5px solid var(--border); border-radius: var(--radius-sm);
  background: var(--bg); color: var(--text);
  font: 400 var(--site-field)/1.2 var(--font-body);
  transition: border-color 120ms ease;
}
input[type="email"]:hover, input[type="text"]:hover, select:hover { border-color: var(--muted); }
input:focus-visible, select:focus-visible { outline-offset: 2px; border-radius: var(--radius-sm); }
[aria-invalid="true"] { border-color: var(--bad) !important; }

/* A select draws its own arrow, so the browser's is taken away. */
.select { position: relative; display: block; }
.select select { appearance: none; -webkit-appearance: none; padding-right: calc(var(--space-6) + var(--space-4)); cursor: pointer; }
.select::after {
  content: ""; position: absolute; right: var(--space-4); top: 50%;
  width: var(--space-2); height: var(--space-2);
  border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted);
  transform: translateY(-70%) rotate(45deg); pointer-events: none;
}

.hint { margin-top: var(--space-2); font-size: var(--site-small); line-height: 1.4; color: var(--muted); }
.field-error { margin-top: var(--space-2); font-size: var(--site-small); line-height: 1.4; font-weight: 600; color: var(--bad); }
.form-error {
  padding: var(--space-3) var(--space-4); border: 1px solid var(--bad); border-radius: var(--radius-sm);
  box-shadow: inset 4px 0 0 var(--bad); color: var(--bad); font-weight: 600;
}

.check { display: grid; grid-template-columns: auto 1fr; column-gap: var(--space-3); align-items: start; }
.check input {
  width: var(--space-6); height: var(--space-6); margin: 0; accent-color: var(--accent-fill); cursor: pointer;
}
.check label { margin: 0; font-weight: 400; line-height: 1.45; cursor: pointer; }
.check .hint, .check .field-error { grid-column: 2; }

/* The honeypot: out of sight, out of the tab order, out of the accessibility tree. */
.hp { position: absolute; left: -200vw; width: 1px; height: 1px; overflow: hidden; }

form .button { justify-self: start; min-width: min(100%, 16rem); }
form[aria-busy="true"] { cursor: progress; }

.joined {
  padding: var(--space-5); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: inset 4px 0 0 var(--accent-fill); background: var(--surface);
}
.joined h3 { font: 800 var(--type-display-l)/1.1 var(--font-display); letter-spacing: -0.02em; }
.joined p { margin-top: var(--space-2); color: var(--muted); }
.joined:focus-visible { outline-offset: 4px; border-radius: var(--radius); }

/* ---------- foot ---------- */

.foot {
  display: grid; gap: var(--space-3);
  padding-block: var(--space-6) calc(var(--space-6) + env(safe-area-inset-bottom));
  border-top: 1px solid var(--border);
  font-size: var(--site-small); line-height: 1.5; color: var(--muted);
}
.foot p { max-width: var(--site-measure); }
.foot a { color: var(--text); }
.foot-mark {
  margin-top: var(--space-3);
  font: 850 var(--type-label-s)/1 var(--font-display); font-stretch: 125%; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text);
}

/* ---------- the short pages: privacy, thanks, sorry, not found ---------- */

.page { padding-block: var(--space-6) var(--site-section-min); }
.page h1 {
  font: 800 clamp(var(--site-heading-min), 1rem + 3.6vw, var(--site-heading-max))/1.02 var(--font-display);
  letter-spacing: -0.025em;
}
.page h2 { margin-top: var(--space-6); font: 700 var(--type-display-m)/1.2 var(--font-display); }
.page p, .page ul { max-width: var(--site-measure); margin-top: var(--space-3); }
.page ul { padding-left: var(--space-5); list-style: disc; }
.page li + li { margin-top: var(--space-2); }
.page .button { margin-top: var(--space-5); }
.draft {
  margin-bottom: var(--space-5); padding: var(--space-3) var(--space-4); border: 1px solid var(--warn); border-radius: var(--radius-sm);
  box-shadow: inset 4px 0 0 var(--warn); color: var(--warn); font-weight: 600;
}
.todo { color: var(--warn); font-weight: 600; }
.updated { color: var(--muted); font-size: var(--site-small); }

/* ---------- wider screens ---------- */

@media (min-width: 30rem) {
  .top-join { display: inline-flex; }
}

@media (min-width: 40rem) {
  .wrap { width: min(100% - 2 * var(--site-gutter-wide), var(--site-page)); }
  /* The wide cut of the clip from here up. */
  .demo-frame, .demo:not(.has-clip) .demo-frame { aspect-ratio: 16 / 9; width: 100%; }
  .pitch-wide { display: block; }
  .pitch-tall { display: none; }
  [data-motion="on"] .follow { animation-name: follow-wide; }
  .demo-note { flex-direction: row; align-items: baseline; gap: var(--space-3); inset: auto var(--space-5) var(--space-5); }
  /* Side by side, with the labels, controls, hints and errors of a pair on shared rows, so a label that
     wraps does not push its control out of line with its neighbour's. */
  .field-row { grid-template-columns: 1fr 1fr; grid-template-rows: repeat(4, auto); row-gap: 0; }
  .field-row .field { display: grid; grid-template-rows: subgrid; grid-row: span 4; }
  .field-row label { grid-row: 1; align-self: end; }
  .field-row .select { grid-row: 2; }
  .field-row .hint { grid-row: 3; }
  .field-row .field-error { grid-row: 4; }
}

@media (min-width: 56rem) {
  .point-list { grid-template-columns: repeat(3, 1fr); gap: var(--site-gutter-wide); }
  .points { padding-top: var(--site-section-max); }
  .join { grid-template-columns: 5fr 7fr; gap: var(--site-gutter-wide); padding-block: var(--site-section-max); }
  .join-copy { position: sticky; top: var(--space-6); align-self: start; }
}

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

/* Paused by the visitor (the button under the headline), reduced motion asked for, or no script: the
   frame never starts, because its animation is only set under [data-motion="on"] above. */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .rot-word, .button, input, select { transition: none; }
}
