/* Self-hosted (see fonts/LICENSE.txt) instead of linking Google Fonts.
   Linking them would send every visitor's IP to Google on page load. */
@font-face {
  font-family: "Press Start 2P";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src:
    url("fonts/press-start-2p-latin-400-normal.woff2") format("woff2"),
    url("fonts/press-start-2p-latin-400-normal.woff") format("woff");
}

/* The app's own two faces, copied from Plyr2-Client-Dev/src/assets/fonts so
   the site and the product are set in the same type rather than merely the
   same colours. VHS Gothic is the app's body face and Gamer is its display
   face, and they are used here for exactly those jobs. Self-hosted for the
   same reason Press Start 2P is: a webfont CDN would hand every visitor's IP
   to a third party on page load. */
@font-face {
  font-family: "VHS Gothic";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/vhs-gothic.ttf") format("truetype");
}

@font-face {
  font-family: "Gamer";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/Gamer.ttf") format("truetype");
}

/* The palette moved warm, and that is the whole visual argument of this
   revision. The old ground was #14141d, a blue-black, and blue-black plus a
   pixel font for every heading is the house style of a developer's side
   project. It is not what somebody deciding whether to date through this
   thing needs to see. Every base tone below now carries red in it, so the
   page reads as low light rather than as a terminal, and Press Start 2P is
   pulled back to the wordmark and the small eyebrow labels, where it is a
   brand mark instead of a body face.

   The brand colours themselves are untouched: magenta, gold and blue are
   still exactly the values the app ships, because the point is to warm the
   room, not to repaint the logo. */
:root {
  /* THE RAMP, AND WHY IT IS GREY.

     A previous revision of this file moved the ground warm — plum, coral and
     cream — on the theory that blue-black plus a pixel font reads as a
     developer's side project. The colours were nice and they were wrong,
     because none of them existed anywhere in the product. Somebody who
     clicked through landed in an app painted at a different temperature, and
     a marketing site whose job is to set an expectation had set the wrong
     one.

     So the ramp below is the app's. --grey-800, --grey-700, --grey-600 and
     --grey-500 are, value for value, $shell-top, $dark and the two raised
     surfaces App.scss already paints; --grey-900 is this site's own original
     ground. The four lighter rungs are new, and they are new for one reason:
     this page alternates dark and light bands and the app has never needed a
     light surface. They extend the same blue-grey hue upward. They do not
     introduce a second temperature, which is the whole point. */
  --grey-900: #14141d;
  --grey-800: #1c1d2b; /* app $shell-top */
  --grey-700: #272838; /* app $dark */
  --grey-600: #2f3049; /* app raised surface */
  --grey-500: #3a3b52; /* app raised surface, one rung up */
  --grey-400: #4b4d68; /* new: hairlines on dark */
  --grey-300: #6e7091; /* new: muted text on dark */
  --grey-200: #a9abc4; /* new: dim text on dark */
  --grey-100: #d5d7e4; /* new: hairlines on light */
  --grey-050: #eceef5; /* new: the light band surface */

  /* Untouched, and deliberately so: these are the app's accent values. */
  --purple: #7a3e6a;
  --magenta: #c13d88; /* app $pink */
  --gold: #f3de8a; /* app $yellow */
  --blue: #3d88c1; /* app $blue */
  --green: #3fbf60; /* app $green */
  --white: #f9f8f8; /* app $light */

  /* Roles, so the rest of the file names a job rather than a colour. */
  --bg-0: var(--grey-900);
  --bg-1: var(--grey-700);
  --bg-2: var(--grey-600);
  --hairline: var(--grey-400);

  /* The light bands. Cool, not cream: this is the top of the same ramp. */
  --surface-light: var(--grey-050);
  --surface-light-edge: var(--grey-100);
  --ink: var(--grey-900);
  --ink-soft: #53556e;

  --text-dim: var(--grey-200);
  --text-faint: var(--grey-300);

  --radius: 18px;
  --radius-sm: 12px;
  --radius-pill: 999px;

  /* One measure for every band, so the page has a spine. */
  --measure: 1080px;

  /* Gamer and VHS Gothic are the app's faces, used here for the app's jobs.
     Gamer is a display face and stops being legible somewhere around 1rem —
     that is a real finding from the signed-out screen, where it turned the
     card headings into a grey smear — so it is spent only on h1, the band
     titles and the big numerals. Anything a person reads a sentence of is
     VHS Gothic. Press Start 2P stays the wordmark and the eyebrow labels,
     and is also what the vendored snes.css chrome is drawn against. */
  --font-display: "Gamer", "VHS Gothic", "Segoe UI", sans-serif;
  --font-body: "VHS Gothic", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-pixel: "Press Start 2P", monospace;
}


* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  min-height: 100%;
  background: var(--bg-0);
  color: var(--white);
  font-family: var(--font-body);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

/* Only the wordmark. Everything that used to be set in the pixel face and is
   now a real heading is listed in .band-title below. */
.logo span {
  font-family: var(--font-pixel);
  line-height: 1.5;
}

/* --- floating pixel hearts background --- */

.hearts-bg {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

.heart {
  position: absolute;
  bottom: -10vh;
  left: var(--x);
  width: var(--size);
  height: calc(var(--size) * 24 / 28);
  color: var(--color);
  opacity: var(--opacity);
  animation: rise var(--duration) linear var(--delay) infinite;
  will-change: transform;
}

.heart > svg {
  display: block;
  width: 100%;
  height: 100%;
  animation: sway var(--sway-duration) ease-in-out var(--delay) infinite alternate;
}

@keyframes rise {
  from {
    transform: translateY(0);
  }
  to {
    transform: translateY(-130vh);
  }
}

@keyframes sway {
  from {
    transform: translateX(calc(var(--sway) * -1));
  }
  to {
    transform: translateX(var(--sway));
  }
}

/* --- band system ---
 * A marketing page is read in bands, not in one column, and the alternation
 * is what stops a long page reading as one undifferentiated wall. Dark, then
 * light, then dark: the light bands are where the page explains itself and
 * the dark ones are where it shows the product, which is also the order a
 * visitor asks for those two things in.
 */

.page {
  position: relative;
  z-index: 1;
}

.band {
  position: relative;
  padding: 4.5rem 1.5rem;
}

.band-inner {
  max-width: var(--measure);
  margin: 0 auto;
  text-align: center;
}

.band-dark {
  background: transparent;
}

/* The first thing in the viewport, so it gets the only gradient on the page
   that is doing scene-setting rather than separation. */
.hero {
  padding-top: 3.5rem;
  padding-bottom: 4rem;
  background: radial-gradient(
    ellipse 120% 90% at 50% -10%,
    var(--bg-2) 0%,
    var(--bg-1) 42%,
    var(--bg-0) 78%
  );
}

/* Cream, not white. White next to a plum ground is a light-leak; cream reads
   as paper, which is what the how-it-works and FAQ bands are pretending to
   be. */
.band-light {
  background: var(--surface-light);
  color: var(--ink);
}

.band-light .band-lede,
.band-light p {
  color: var(--ink-soft);
}

.band-light .band-title {
  color: var(--ink);
}

.band-light .eyebrow {
  color: #b8437f;
}

.band-card {
  background: linear-gradient(160deg, var(--grey-600) 0%, var(--grey-700) 70%, var(--grey-800) 100%);
}

/* Sits between a cream band and the transparent dark shots band, so it ramps
   down rather than across: grey-600 at the top picks up where .band-light
   leaves off, grey-800 at the bottom lands a rung above --bg-0 and lets the
   shots band read as a continuation. Purple rather than the pledge band's
   magenta on purpose. The two are both manifesto bands and would blur into
   one another if they were painted the same. */
.band-commit {
  background: linear-gradient(160deg, var(--grey-600) 0%, var(--purple) 55%, var(--grey-800) 100%);
}

.band-pledge {
  background: linear-gradient(135deg, var(--grey-600) 0%, var(--purple) 45%, var(--magenta) 100%);
}

.band-signup {
  background: linear-gradient(180deg, var(--bg-0) 0%, var(--grey-800) 100%);
}

/* --- section furniture --- */

/* The pixel face's remaining job on this page, and it is a good one: four or
   five words in caps above a heading, where a fixed-width bitmap face reads
   as a label and never has to wrap. */
.eyebrow {
  font-family: var(--font-pixel);
  font-size: 0.58rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0 0 1rem;
}

.band-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.55rem, 4vw, 2.35rem);
  line-height: 1.25;
  letter-spacing: 0.025em;
  margin: 0 0 1rem;
  color: var(--white);
}

.band-lede {
  max-width: 56ch;
  margin: 0 auto 2.5rem;
  font-size: 1.08rem;
  line-height: 1.65;
  color: var(--text-dim);
}

.band-foot {
  max-width: 56ch;
  margin: 2.25rem auto 0;
  font-size: 0.95rem;
  line-height: 1.65;
  color: var(--text-faint);
}

/* --- hero --- */

.hero .band-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
}

.logo {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 1.5rem;
}

.logo-heart {
  width: 1.6rem;
  height: 1.4rem;
  color: var(--magenta);
}

.logo span {
  font-size: 0.9rem;
  letter-spacing: 0.15em;
  color: var(--gold);
}

h1 {
  font-family: var(--font-display);
  /* Gamer ships one weight. Asking for 800 got a synthetic bold, which on a
     face this blocky just fattened every stem until the letters of "Find"
     touched — and negative tracking on top of that closed the last gap. The
     face is already heavy; it needs air, not weight. */
  font-weight: 400;
  font-size: clamp(2.4rem, 8vw, 4.2rem);
  line-height: 1.16;
  letter-spacing: 0.02em;
  margin: 0 0 1.1rem;
  color: var(--white);
}

/* The old h1 was pixel-set with a hard 3px magenta offset shadow, which is
   the exact look this page was asked to stop having. The name keeps its
   colour instead: a warm gradient across the two words, which is what every
   consumer app's hero does and what a bitmap drop shadow was standing in
   for. */
h1 {
  background: linear-gradient(105deg, var(--gold) 0%, var(--magenta) 55%, var(--blue) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.tagline {
  max-width: 34ch;
  margin: 0 0 0.9rem;
  font-family: var(--font-body);
  font-size: clamp(1.15rem, 3.4vw, 1.6rem);
  font-weight: 600;
  line-height: 1.35;
  color: var(--white);
}

/* --- the rotating word ---
 * A window exactly one line tall with a column of words behind it, stepped
 * up one line at a time. The fifth word is a copy of the first, so the
 * animation can run to the bottom of the stack and restart at the top with
 * nothing visibly jumping.
 *
 * Sized in em against its own line-height so it tracks the tagline's clamp
 * instead of needing a breakpoint per size, and coloured rather than boxed:
 * a highlighted pill here would compete with the CTA six inches below it.
 */
.rotator {
  /* Its own line, which is also how the big dating sites set this. Inline,
     the window has to be as wide as the longest word in the stack, so every
     shorter one left a hole before the rest of the sentence. On its own line
     the width stops mattering and the word gets to be the thing you look
     at. */
  display: block;
  position: relative;
  height: 1.5em;
  line-height: 1.5em;
  color: var(--gold);
}

/* This was a scrolling track inside an overflow:hidden window, and it was
   wrong in a way that took a screenshot to see: VHS Gothic paints ink past
   the bottom of its own line box, so the descender of the word above hung
   into the window and sat over the line as a stray gold tick. Widening the
   step did nothing, because the words tile the window exactly — the box was
   never the problem, the ink was. A cross-fade cannot have that bug at all:
   one word occupies the slot, the others are transparent, and nothing is
   clipped, so there is no edge for ink to cross. */
.rotator-track {
  display: block;
  position: relative;
  height: 1.5em;
}

.rotator-track > span {
  position: absolute;
  inset: 0;
  display: block;
  line-height: 1.5em;
  white-space: nowrap;
  opacity: 0;
  animation: rotate-words 11s infinite;
}

.rotator-track > span:nth-child(2) { animation-delay: 2.75s; }
.rotator-track > span:nth-child(3) { animation-delay: 5.5s; }
.rotator-track > span:nth-child(4) { animation-delay: 8.25s; }

@keyframes rotate-words {
  0% { opacity: 0; transform: translateY(0.28em); }
  3%, 25% { opacity: 1; transform: translateY(0); }
  28%, 100% { opacity: 0; transform: translateY(-0.28em); }
}


/* Motion for its own sake is the first thing to go. The track parks on the
   first word, which is why that word has to be a sentence that works alone. */
@media (prefers-reduced-motion: reduce) {
  .rotator-track > span {
    animation: none;
    opacity: 0;
  }

  .rotator-track > span:first-child {
    opacity: 1;
  }

  .heart,
  .heart > svg {
    animation: none;
  }
}

.hero-sub {
  max-width: 46ch;
  margin: 0 0 2rem;
  font-size: 1.05rem;
  line-height: 1.65;
  color: var(--text-dim);
}

/* --- buttons --- */

.cta-stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.85rem;
  width: 100%;
  max-width: 440px;
}

/* A pill, and that is the single loudest signal on the page that this is a
   consumer product. The old button was a square magenta block with a 4px
   offset shadow, which is a game-jam button: correct for the app's own
   chrome, wrong for the one control a stranger has to feel safe pressing. */
.btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.65rem;
  width: 100%;
  padding: 1.05rem 2rem;
  border: none;
  border-radius: var(--radius-pill);
  background: linear-gradient(100deg, var(--magenta) 0%, #8b4aa4 55%, var(--blue) 100%);
  color: #fff;
  font-family: var(--font-body);
  font-size: 1.08rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  text-decoration: none;
  box-shadow: 0 10px 28px rgba(193, 61, 136, 0.38);
  transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
}

.btn-primary:hover {
  transform: translateY(-2px);
  filter: brightness(1.06);
  box-shadow: 0 14px 34px rgba(193, 61, 136, 0.48);
}

.btn-primary:active {
  transform: translateY(0);
  box-shadow: 0 6px 18px rgba(193, 61, 136, 0.36);
}

.btn-primary:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 3px;
}

/* The one inside a light band, where it is a repeat of the hero's offer
   rather than the first ask, so it sizes itself to its label. */
.btn-inline {
  width: auto;
  margin-top: 2.75rem;
  padding: 0.9rem 2.1rem;
  font-size: 1rem;
}

.btn-heart {
  flex: none;
  width: 1.3rem;
  height: 1.15rem;
  color: rgba(255, 255, 255, 0.92);
}

.cta-note {
  margin: 0;
  max-width: 42ch;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--text-dim);
}

.cta-note strong {
  color: var(--gold);
  font-weight: 700;
}

/* Every dating site puts the returning user's door here, small, directly
   under the sign-up button. Leaving it out is how a landing page ends up
   with a support queue full of people who already have accounts. */
.cta-alt {
  margin: 0.2rem 0 0;
  font-size: 0.88rem;
  line-height: 1.7;
  color: var(--text-faint);
}

.cta-alt a {
  color: var(--white);
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.3);
  padding-bottom: 1px;
}

.cta-alt a:hover {
  color: var(--gold);
  border-bottom-color: var(--gold);
}

/* --- trust strip --- */

.trust-strip {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem 1.75rem;
  margin: 2.5rem 0 0;
  padding: 0;
  font-size: 0.9rem;
  color: var(--text-dim);
}

.trust-strip li {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}

.trust-mark {
  color: var(--green);
  font-weight: 700;
}

/* --- how it works --- */

.steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
  text-align: left;
}

.step {
  background: #fff;
  border: 1px solid var(--surface-light-edge);
  border-radius: var(--radius);
  padding: 2.25rem 1.5rem 1.6rem;
  position: relative;
  box-shadow: 0 8px 24px rgba(90, 40, 70, 0.07);
}

/* Numbered, because "how it works" without numbers is just three more
   feature cards. The circle overlaps the card's top edge so the sequence is
   legible before any of the text is read. */
.step-num {
  position: absolute;
  top: -1.1rem;
  left: 1.5rem;
  width: 2.2rem;
  height: 2.2rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: linear-gradient(140deg, var(--magenta), var(--blue));
  color: #fff;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 1.05rem;
  box-shadow: 0 6px 16px rgba(193, 61, 136, 0.3);
}

.step h3 {
  font-family: var(--font-body);
  font-size: 1.15rem;
  font-weight: 700;
  margin: 0.4rem 0 0.6rem;
  color: var(--ink);
}

.step p {
  margin: 0;
  font-size: 0.96rem;
  line-height: 1.62;
  color: var(--ink-soft);
}

/* --- the card band: stat row --- */

.stat-row {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
}

.stat {
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--radius);
  background: rgba(255, 255, 255, 0.04);
  padding: 1.5rem 0.75rem;
}

.stat strong {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 5vw, 2.6rem);
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0.05em;
  color: var(--gold);
}

.stat span {
  display: block;
  margin-top: 0.45rem;
  font-size: 0.85rem;
  color: var(--text-faint);
}

/* --- four tabs --- */

.tab-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.25rem;
  text-align: left;
}

.tab-item {
  background: #fff;
  border: 1px solid var(--surface-light-edge);
  border-radius: var(--radius);
  padding: 1.5rem 1.35rem;
  box-shadow: 0 8px 24px rgba(90, 40, 70, 0.07);
}

.tab-badge {
  display: inline-grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  margin-bottom: 0.9rem;
  border-radius: var(--radius-sm);
  background: linear-gradient(140deg, var(--grey-100), #c3c6d8);
  color: var(--magenta);
  font-family: var(--font-pixel);
  font-size: 0.6rem;
}

.tab-item h3 {
  font-family: var(--font-body);
  font-size: 1.05rem;
  font-weight: 700;
  margin: 0 0 0.5rem;
  color: var(--ink);
}

.tab-item p {
  margin: 0;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--ink-soft);
}

/* --- feature grid --- */

.feature-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem;
  text-align: left;
}

.feature {
  background: rgba(255, 255, 255, 0.045);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: var(--radius);
  padding: 1.6rem 1.5rem;
}

.feature-icon {
  width: 1.5rem;
  height: 1.3rem;
  color: var(--gold);
  margin-bottom: 0.8rem;
}

.feature h3 {
  font-family: var(--font-body);
  font-size: 1.08rem;
  font-weight: 700;
  margin: 0 0 0.6rem;
  color: var(--white);
}

.feature p {
  font-size: 0.94rem;
  line-height: 1.62;
  color: var(--text-dim);
  margin: 0;
}

/* --- the Player 2 rule --- */

.band-commit .eyebrow {
  color: var(--gold);
}

.commit-body {
  max-width: 58ch;
  margin: 0 auto 1.15rem;
  font-size: 1.08rem;
  line-height: 1.7;
  color: var(--white);
}

/* Gold on the one sentence the owner wants read if nothing else is. It is the
   only <strong> in the band, so this needs no more specificity than this. */
.commit-body strong {
  color: var(--gold);
  font-weight: inherit;
}

.commit-body-small {
  margin-top: 1.75rem;
  margin-bottom: 0;
  font-size: 0.95rem;
  color: rgba(255, 240, 248, 0.78);
}

/* --- pledge --- */

.band-pledge .eyebrow {
  color: var(--gold);
}

.pledge-body {
  max-width: 58ch;
  margin: 0 auto;
  font-size: 1.08rem;
  line-height: 1.7;
  color: var(--white);
}

.pledge-body-small {
  margin-top: 1.25rem;
  font-size: 0.95rem;
  color: rgba(255, 240, 248, 0.78);
}

/* --- faq --- */

.faq {
  max-width: 720px;
  margin: 0 auto;
  text-align: left;
}

.faq-item {
  background: #fff;
  border: 1px solid var(--surface-light-edge);
  border-radius: var(--radius-sm);
  margin-bottom: 0.75rem;
  overflow: hidden;
}

.faq-item summary {
  cursor: pointer;
  list-style: none;
  padding: 1.1rem 3rem 1.1rem 1.35rem;
  font-family: var(--font-body);
  font-size: 1.02rem;
  font-weight: 700;
  color: var(--ink);
  position: relative;
}

.faq-item summary::-webkit-details-marker {
  display: none;
}

/* Drawn rather than shipped as an icon, and rotated on open, so the control
   says which way it goes without a second asset or a line of script. */
.faq-item summary::after {
  content: "";
  position: absolute;
  right: 1.35rem;
  top: 1.45rem;
  width: 0.55rem;
  height: 0.55rem;
  border-right: 2px solid var(--magenta);
  border-bottom: 2px solid var(--magenta);
  transform: rotate(45deg);
  transition: transform 0.2s ease;
}

.faq-item[open] summary::after {
  transform: rotate(-135deg);
  top: 1.6rem;
}

.faq-item p {
  margin: 0;
  padding: 0 1.35rem 1.25rem;
  font-size: 0.96rem;
  line-height: 1.65;
  color: var(--ink-soft);
}

/* --- sign-up band --- */

.band-signup .cta-stack {
  margin: 0 auto;
}

.store-badges {
  display: flex;
  gap: 0.7rem;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 2rem;
}

.store-badge {
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--radius-pill);
  color: var(--text-faint);
  font-size: 0.82rem;
  padding: 0.55rem 1.1rem;
}

/* The badges in that row that go somewhere. Gold so they are not skimmed
   past as another greyed-out "coming soon". */
.store-badge-live {
  border-color: rgba(243, 222, 138, 0.55);
  color: var(--gold);
  text-decoration: none;
}

.store-badge-live:hover {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--ink);
}

/* --- waitlist --- */

/* Demoted, on purpose. It used to sit directly under the headline as the
   page's main ask, which was right when the app did not exist yet. The app
   is live, the button above is the ask, and this is now the fallback for
   somebody the live build cannot serve today. */
.waitlist-block {
  max-width: 460px;
  margin: 3rem auto 0;
  padding: 1.75rem 1.5rem;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: var(--radius);
  background: rgba(255, 255, 255, 0.035);
}

.waitlist-intro {
  margin: 0 0 1.25rem;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--text-faint);
}

.waitlist {
  display: flex;
  gap: 0.6rem;
  width: 100%;
  flex-wrap: wrap;
  justify-content: center;
}

.waitlist input[type="email"] {
  flex: 1 1 200px;
  padding: 0.85rem 1.15rem;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(0, 0, 0, 0.25);
  color: var(--white);
  font-size: 1rem;
  outline: none;
}

.waitlist input[type="email"]::placeholder {
  color: var(--grey-300);
}

.waitlist input[type="email"]:focus {
  border-color: var(--gold);
}

.waitlist button {
  padding: 0.85rem 1.5rem;
  border: none;
  border-radius: var(--radius-pill);
  background: linear-gradient(100deg, var(--magenta), var(--blue));
  color: #fff;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.98rem;
  cursor: pointer;
  transition: filter 0.15s ease, transform 0.15s ease;
}

.waitlist button:hover:not(:disabled) {
  filter: brightness(1.07);
}

.waitlist button:active:not(:disabled) {
  transform: translateY(1px);
}

.waitlist button:disabled {
  opacity: 0.6;
  cursor: default;
}

/* --- snes.css radio & checkbox chrome, vendored from snes.css v1.0.1 ---
 * .snes-radio/.snes-checkbox below pull in the framework's real box-shadow
 * pixel-art glyphs, copied verbatim so the dot/checkmark art isn't retyped
 * by hand. Colors and font-family are overridden to this site's own
 * palette and body font, same reasoning as the client app's
 * snes-local.scss: Press Start 2P reads fine for the short headings it's
 * already used for, not for full-sentence form labels. */

.platform-radio {
  flex: 1 1 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
}

.platform-radio-label {
  margin: 0;
  font-size: 0.78rem;
  color: #a9a6c0;
}

.snes-radio {
  display: flex;
  flex-direction: row;
  gap: 1.5rem;
  cursor: pointer;
}

.snes-radio input {
  display: none;
}

.snes-radio input:checked ~ .snes-radio__item__content::before {
  visibility: visible;
}

.snes-radio__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  cursor: pointer;
}

.snes-radio__item__content {
  display: flex;
  align-items: center;
  gap: calc(0.9em + 16px / 2);
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  font-size: 0.9rem;
  color: #d9d5e8;
}

.snes-radio__item__content::before {
  display: block;
  visibility: hidden;
  color: var(--magenta);
  transform: translateY(calc(-13em / 13));
  margin: 0.6875em 0.875em;
  content: "";
  width: 0.125em;
  height: 0.125em;
  box-shadow: 0.375em 0.125em color-mix(in srgb, currentColor, black 30%),0.5em 0.125em color-mix(in srgb, currentColor, black 30%),0.625em 0.125em color-mix(in srgb, currentColor, black 30%),0.75em 0.125em color-mix(in srgb, currentColor, black 30%),0.875em 0.125em color-mix(in srgb, currentColor, black 30%),1em 0.125em color-mix(in srgb, currentColor, black 30%),1.125em 0.125em color-mix(in srgb, currentColor, black 30%),1.25em 0.125em color-mix(in srgb, currentColor, black 30%),1.375em 0.125em color-mix(in srgb, currentColor, black 30%),1.5em 0.125em color-mix(in srgb, currentColor, black 70%),1.625em 0.125em color-mix(in srgb, currentColor, black 70%),1.75em 0.125em color-mix(in srgb, currentColor, black 70%),0.25em 0.25em color-mix(in srgb, currentColor, black 30%),0.375em 0.25em currentColor,0.5em 0.25em color-mix(in srgb, currentColor, white 55%),0.625em 0.25em color-mix(in srgb, currentColor, white 55%),0.75em 0.25em #ffffff,0.875em 0.25em #ffffff,1em 0.25em #ffffff,1.125em 0.25em #ffffff,1.25em 0.25em color-mix(in srgb, currentColor, white 55%),1.375em 0.25em color-mix(in srgb, currentColor, white 55%),1.5em 0.25em color-mix(in srgb, currentColor, white 55%),1.625em 0.25em currentColor,1.75em 0.25em color-mix(in srgb, currentColor, black 30%),1.875em 0.25em color-mix(in srgb, currentColor, black 70%),0.125em 0.375em color-mix(in srgb, currentColor, black 30%),0.25em 0.375em currentColor,0.375em 0.375em color-mix(in srgb, currentColor, white 55%),0.5em 0.375em color-mix(in srgb, currentColor, white 55%),0.625em 0.375em #ffffff,0.75em 0.375em #ffffff,0.875em 0.375em #ffffff,1em 0.375em #ffffff,1.125em 0.375em #ffffff,1.25em 0.375em #ffffff,1.375em 0.375em color-mix(in srgb, currentColor, white 55%),1.5em 0.375em color-mix(in srgb, currentColor, white 55%),1.625em 0.375em color-mix(in srgb, currentColor, white 55%),1.75em 0.375em currentColor,1.875em 0.375em color-mix(in srgb, currentColor, black 30%),2em 0.375em color-mix(in srgb, currentColor, black 70%),0.125em 0.5em color-mix(in srgb, currentColor, black 70%),0.25em 0.5em currentColor,0.375em 0.5em color-mix(in srgb, currentColor, black 30%),0.5em 0.5em color-mix(in srgb, currentColor, black 30%),0.625em 0.5em currentColor,0.75em 0.5em currentColor,0.875em 0.5em currentColor,1em 0.5em currentColor,1.125em 0.5em currentColor,1.25em 0.5em currentColor,1.375em 0.5em currentColor,1.5em 0.5em currentColor,1.625em 0.5em color-mix(in srgb, currentColor, black 30%),1.75em 0.5em color-mix(in srgb, currentColor, black 30%),1.875em 0.5em currentColor,2em 0.5em #000000,0.125em 0.625em color-mix(in srgb, currentColor, black 70%),0.25em 0.625em currentColor,0.375em 0.625em color-mix(in srgb, currentColor, black 30%),0.5em 0.625em color-mix(in srgb, currentColor, black 70%),0.625em 0.625em currentColor,0.75em 0.625em currentColor,0.875em 0.625em currentColor,1em 0.625em color-mix(in srgb, currentColor, black 30%),1.125em 0.625em color-mix(in srgb, currentColor, black 30%),1.25em 0.625em color-mix(in srgb, currentColor, black 30%),1.375em 0.625em color-mix(in srgb, currentColor, black 70%),1.5em 0.625em color-mix(in srgb, currentColor, black 70%),1.625em 0.625em color-mix(in srgb, currentColor, black 30%),1.75em 0.625em color-mix(in srgb, currentColor, black 30%),1.875em 0.625em currentColor,2em 0.625em #000000,0.125em 0.75em color-mix(in srgb, currentColor, black 70%),0.25em 0.75em color-mix(in srgb, currentColor, black 30%),0.375em 0.75em currentColor,0.5em 0.75em color-mix(in srgb, currentColor, black 70%),0.625em 0.75em color-mix(in srgb, currentColor, black 30%),0.75em 0.75em color-mix(in srgb, currentColor, white 55%),0.875em 0.75em color-mix(in srgb, currentColor, white 55%),1em 0.75em color-mix(in srgb, currentColor, black 30%),1.125em 0.75em color-mix(in srgb, currentColor, black 30%),1.25em 0.75em color-mix(in srgb, currentColor, black 70%),1.375em 0.75em color-mix(in srgb, currentColor, black 70%),1.5em 0.75em color-mix(in srgb, currentColor, black 70%),1.625em 0.75em color-mix(in srgb, currentColor, black 70%),1.75em 0.75em currentColor,1.875em 0.75em color-mix(in srgb, currentColor, black 30%),2em 0.75em #000000,0.25em 0.875em color-mix(in srgb, currentColor, black 70%),0.375em 0.875em currentColor,0.5em 0.875em color-mix(in srgb, currentColor, black 30%),0.625em 0.875em color-mix(in srgb, currentColor, black 70%),0.75em 0.875em currentColor,0.875em 0.875em color-mix(in srgb, currentColor, white 55%),1em 0.875em currentColor,1.125em 0.875em color-mix(in srgb, currentColor, black 30%),1.25em 0.875em color-mix(in srgb, currentColor, black 70%),1.375em 0.875em color-mix(in srgb, currentColor, black 70%),1.5em 0.875em color-mix(in srgb, currentColor, black 70%),1.625em 0.875em currentColor,1.75em 0.875em color-mix(in srgb, currentColor, black 30%),1.875em 0.875em #000000,0.375em 1em #000000,0.5em 1em currentColor,0.625em 1em color-mix(in srgb, currentColor, black 30%),0.75em 1em color-mix(in srgb, currentColor, black 30%),0.875em 1em currentColor,1em 1em currentColor,1.125em 1em color-mix(in srgb, currentColor, black 70%),1.25em 1em color-mix(in srgb, currentColor, black 70%),1.375em 1em color-mix(in srgb, currentColor, black 70%),1.5em 1em currentColor,1.625em 1em color-mix(in srgb, currentColor, black 30%),1.75em 1em #000000,0.5em 1.125em #000000,0.625em 1.125em currentColor,0.75em 1.125em color-mix(in srgb, currentColor, black 30%),0.875em 1.125em currentColor,1em 1.125em currentColor,1.125em 1.125em color-mix(in srgb, currentColor, black 70%),1.25em 1.125em color-mix(in srgb, currentColor, black 70%),1.375em 1.125em currentColor,1.5em 1.125em color-mix(in srgb, currentColor, black 30%),1.625em 1.125em #000000,0.625em 1.25em #000000,0.75em 1.25em currentColor,0.875em 1.25em color-mix(in srgb, currentColor, black 30%),1em 1.25em currentColor,1.125em 1.25em color-mix(in srgb, currentColor, black 30%),1.25em 1.25em currentColor,1.375em 1.25em color-mix(in srgb, currentColor, black 30%),1.5em 1.25em #000000,0.75em 1.375em #000000,0.875em 1.375em currentColor,1em 1.375em currentColor,1.125em 1.375em currentColor,1.25em 1.375em color-mix(in srgb, currentColor, black 30%),1.375em 1.375em #000000,0.875em 1.5em #000000,1em 1.5em currentColor,1.125em 1.5em color-mix(in srgb, currentColor, black 30%),1.25em 1.5em #000000,1em 1.625em #000000,1.125em 1.625em #000000;
}

.snes-radio__item__content:hover {
  color: var(--white);
}

.snes-checkbox {
  flex: 1 1 100%;
  display: flex;
  justify-content: center;
}

.snes-checkbox input {
  display: none;
}

.snes-checkbox input:checked ~ .snes-checkbox__item__content::before {
  margin: 0.6875em 0.8125em;
  content: "";
  width: 0.125em;
  height: 0.125em;
  box-shadow: 0.375em 0.25em #000000,0.5em 0.25em #000000,0.625em 0.25em #000000,0.75em 0.25em #000000,0.875em 0.25em #000000,1em 0.25em #000000,1.125em 0.25em #000000,1.25em 0.25em #000000,1.5em 0.25em #000000,1.625em 0.25em #000000,1.75em 0.25em #000000,0.25em 0.375em #000000,0.375em 0.375em color-mix(in srgb, currentColor, white 55%),0.5em 0.375em color-mix(in srgb, currentColor, white 55%),0.625em 0.375em color-mix(in srgb, currentColor, white 55%),0.75em 0.375em color-mix(in srgb, currentColor, white 55%),0.875em 0.375em color-mix(in srgb, currentColor, white 55%),1em 0.375em color-mix(in srgb, currentColor, white 55%),1.125em 0.375em currentColor,1.25em 0.375em currentColor,1.375em 0.375em #000000,1.5em 0.375em #ffffff,1.625em 0.375em #ffffff,1.75em 0.375em #ffffff,1.875em 0.375em #000000,0.125em 0.5em #000000,0.25em 0.5em color-mix(in srgb, currentColor, white 55%),0.375em 0.5em currentColor,0.5em 0.5em #000000,0.625em 0.5em #000000,0.75em 0.5em currentColor,0.875em 0.5em currentColor,1em 0.5em currentColor,1.125em 0.5em currentColor,1.25em 0.5em #000000,1.375em 0.5em #ffffff,1.5em 0.5em #ffffff,1.625em 0.5em #ffffff,1.75em 0.5em #ffffff,1.875em 0.5em #000000,0.125em 0.625em #000000,0.25em 0.625em currentColor,0.375em 0.625em #000000,0.5em 0.625em #ffffff,0.625em 0.625em #ffffff,0.75em 0.625em #000000,0.875em 0.625em currentColor,1em 0.625em currentColor,1.125em 0.625em #000000,1.25em 0.625em #ffffff,1.375em 0.625em #ffffff,1.5em 0.625em #ffffff,1.625em 0.625em #ffffff,1.75em 0.625em #000000,0.125em 0.75em #000000,0.25em 0.75em currentColor,0.375em 0.75em #000000,0.5em 0.75em #ffffff,0.625em 0.75em #ffffff,0.75em 0.75em #ffffff,0.875em 0.75em #000000,1em 0.75em #000000,1.125em 0.75em #ffffff,1.25em 0.75em #ffffff,1.375em 0.75em #ffffff,1.5em 0.75em #ffffff,1.625em 0.75em #000000,0.125em 0.875em #000000,0.25em 0.875em currentColor,0.375em 0.875em #000000,0.5em 0.875em #ffffff,0.625em 0.875em #ffffff,0.75em 0.875em #ffffff,0.875em 0.875em #ffffff,1em 0.875em #ffffff,1.125em 0.875em #ffffff,1.25em 0.875em #ffffff,1.375em 0.875em #ffffff,1.5em 0.875em #000000,0.125em 1em #000000,0.25em 1em currentColor,0.375em 1em currentColor,0.5em 1em #000000,0.625em 1em #ffffff,0.75em 1em #ffffff,0.875em 1em #ffffff,1em 1em #ffffff,1.125em 1em #ffffff,1.25em 1em #ffffff,1.375em 1em #000000,1.5em 1em #000000,0.125em 1.125em #000000,0.25em 1.125em currentColor,0.375em 1.125em currentColor,0.5em 1.125em currentColor,0.625em 1.125em #000000,0.75em 1.125em #ffffff,0.875em 1.125em #ffffff,1em 1.125em #ffffff,1.125em 1.125em #ffffff,1.25em 1.125em #000000,1.375em 1.125em currentColor,1.5em 1.125em #000000,0.125em 1.25em #000000,0.25em 1.25em currentColor,0.375em 1.25em currentColor,0.5em 1.25em currentColor,0.625em 1.25em currentColor,0.75em 1.25em #000000,0.875em 1.25em #ffffff,1em 1.25em #ffffff,1.125em 1.25em #000000,1.25em 1.25em currentColor,1.375em 1.25em currentColor,1.5em 1.25em #000000,0.125em 1.375em #000000,0.25em 1.375em currentColor,0.375em 1.375em currentColor,0.5em 1.375em currentColor,0.625em 1.375em currentColor,0.75em 1.375em currentColor,0.875em 1.375em #000000,1em 1.375em #000000,1.125em 1.375em currentColor,1.25em 1.375em currentColor,1.375em 1.375em color-mix(in srgb, currentColor, black 35%),1.5em 1.375em #000000,0.25em 1.5em #000000,0.375em 1.5em currentColor,0.5em 1.5em currentColor,0.625em 1.5em color-mix(in srgb, currentColor, black 35%),0.75em 1.5em color-mix(in srgb, currentColor, black 35%),0.875em 1.5em color-mix(in srgb, currentColor, black 35%),1em 1.5em color-mix(in srgb, currentColor, black 35%),1.125em 1.5em color-mix(in srgb, currentColor, black 35%),1.25em 1.5em color-mix(in srgb, currentColor, black 35%),1.375em 1.5em #000000,0.375em 1.625em #000000,0.5em 1.625em #000000,0.625em 1.625em #000000,0.75em 1.625em #000000,0.875em 1.625em #000000,1em 1.625em #000000,1.125em 1.625em #000000,1.25em 1.625em #000000;
}

.snes-checkbox__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  cursor: pointer;
}

.snes-checkbox__item__content {
  display: flex;
  align-items: center;
  gap: calc(0.9em + 15px / 2);
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  font-size: 0.85rem;
  color: #a9a6c0;
}

.snes-checkbox__item__content::before {
  display: block;
  color: var(--magenta);
  transform: translateY(calc(-14em / 13));
  margin: 0.6875em 0.8125em;
  content: "";
  width: 0.125em;
  height: 0.125em;
  box-shadow: 0.375em 0.25em #000000,0.5em 0.25em #000000,0.625em 0.25em #000000,0.75em 0.25em #000000,0.875em 0.25em #000000,1em 0.25em #000000,1.125em 0.25em #000000,1.25em 0.25em #000000,1.5em 0.25em #000000,1.625em 0.25em #000000,1.75em 0.25em #000000,0.25em 0.375em #000000,0.375em 0.375em color-mix(in srgb, currentColor, white 55%),0.5em 0.375em color-mix(in srgb, currentColor, white 55%),0.625em 0.375em color-mix(in srgb, currentColor, white 55%),0.75em 0.375em color-mix(in srgb, currentColor, white 55%),0.875em 0.375em color-mix(in srgb, currentColor, white 55%),1em 0.375em color-mix(in srgb, currentColor, white 55%),1.125em 0.375em currentColor,1.25em 0.375em currentColor,1.375em 0.375em #000000,1.5em 0.375em #ffffff,1.625em 0.375em #ffffff,1.75em 0.375em #ffffff,1.875em 0.375em #000000,0.125em 0.5em #000000,0.25em 0.5em color-mix(in srgb, currentColor, white 55%),0.375em 0.5em currentColor,0.5em 0.5em #000000,0.625em 0.5em #000000,0.75em 0.5em currentColor,0.875em 0.5em currentColor,1em 0.5em currentColor,1.125em 0.5em currentColor,1.25em 0.5em #000000,1.375em 0.5em #ffffff,1.5em 0.5em #ffffff,1.625em 0.5em #ffffff,1.75em 0.5em #ffffff,1.875em 0.5em #000000,0.125em 0.625em #000000,0.25em 0.625em currentColor,0.375em 0.625em #000000,0.5em 0.625em #ffffff,0.625em 0.625em #ffffff,0.75em 0.625em #000000,0.875em 0.625em currentColor,1em 0.625em currentColor,1.125em 0.625em #000000,1.25em 0.625em #ffffff,1.375em 0.625em #ffffff,1.5em 0.625em #ffffff,1.625em 0.625em #ffffff,1.75em 0.625em #000000,0.125em 0.75em #000000,0.25em 0.75em currentColor,0.375em 0.75em #000000,0.5em 0.75em #ffffff,0.625em 0.75em #ffffff,0.75em 0.75em #ffffff,0.875em 0.75em #000000,1em 0.75em #000000,1.125em 0.75em #ffffff,1.25em 0.75em #ffffff,1.375em 0.75em #ffffff,1.5em 0.75em #ffffff,1.625em 0.75em #000000,0.125em 0.875em #000000,0.25em 0.875em currentColor,0.375em 0.875em #000000,0.5em 0.875em #ffffff,0.625em 0.875em #ffffff,0.75em 0.875em #ffffff,0.875em 0.875em #ffffff,1em 0.875em #ffffff,1.125em 0.875em #ffffff,1.25em 0.875em #ffffff,1.375em 0.875em #ffffff,1.5em 0.875em #000000,0.125em 1em #000000,0.25em 1em currentColor,0.375em 1em currentColor,0.5em 1em #000000,0.625em 1em #ffffff,0.75em 1em #ffffff,0.875em 1em #ffffff,1em 1em #ffffff,1.125em 1em #ffffff,1.25em 1em #ffffff,1.375em 1em #000000,1.5em 1em #000000,0.125em 1.125em #000000,0.25em 1.125em currentColor,0.375em 1.125em currentColor,0.5em 1.125em currentColor,0.625em 1.125em #000000,0.75em 1.125em #ffffff,0.875em 1.125em #ffffff,1em 1.125em #ffffff,1.125em 1.125em #ffffff,1.25em 1.125em #000000,1.375em 1.125em currentColor,1.5em 1.125em #000000,0.125em 1.25em #000000,0.25em 1.25em currentColor,0.375em 1.25em currentColor,0.5em 1.25em currentColor,0.625em 1.25em currentColor,0.75em 1.25em #000000,0.875em 1.25em #ffffff,1em 1.25em #ffffff,1.125em 1.25em #000000,1.25em 1.25em currentColor,1.375em 1.25em currentColor,1.5em 1.25em #000000,0.125em 1.375em #000000,0.25em 1.375em currentColor,0.375em 1.375em currentColor,0.5em 1.375em currentColor,0.625em 1.375em currentColor,0.75em 1.375em currentColor,0.875em 1.375em #000000,1em 1.375em #000000,1.125em 1.375em currentColor,1.25em 1.375em currentColor,1.375em 1.375em color-mix(in srgb, currentColor, black 35%),1.5em 1.375em #000000,0.25em 1.5em #000000,0.375em 1.5em currentColor,0.5em 1.5em currentColor,0.625em 1.5em color-mix(in srgb, currentColor, black 35%),0.75em 1.5em color-mix(in srgb, currentColor, black 35%),0.875em 1.5em color-mix(in srgb, currentColor, black 35%),1em 1.5em color-mix(in srgb, currentColor, black 35%),1.125em 1.5em color-mix(in srgb, currentColor, black 35%),1.25em 1.5em color-mix(in srgb, currentColor, black 35%),1.375em 1.5em #000000,0.375em 1.625em #000000,0.5em 1.625em #000000,0.625em 1.625em #000000,0.75em 1.625em #000000,0.875em 1.625em #000000,1em 1.625em #000000,1.125em 1.625em #000000,1.25em 1.625em #000000;
}

.snes-checkbox__item__content:hover {
  color: var(--white);
}
.waitlist-status {
  min-height: 1.4em;
  font-size: 0.9rem;
  margin: 0.75rem 0 0;
}

.waitlist-status.ok {
  color: var(--green);
}

.waitlist-status.err {
  color: #e6493f;
}

/* --- feature screenshots ---
 * Each shot is a real capture of the running app with a caption laid over
 * the bottom of it. Three stacked layers, in this order:
 *
 *   .shot-img    the screenshot
 *   .shot-fade   a gradient from the card's own --fade colour at the bottom
 *                to transparent partway up, so the caption has something
 *                opaque to sit on and the top of the screen stays readable
 *   .shot-grain  pixel noise, masked to a band centred on the fade's
 *                transition
 *
 * The grain is the reason the fade doesn't look like a mistake. A smooth
 * ramp across a pixel-art UI reads as a compression artefact — the eye
 * looks for the banding and finds it. Breaking the transition with noise at
 * the same scale as the art turns the ramp into a deliberate edge. It's
 * masked rather than applied flat so the screenshot itself stays clean:
 * grain over the whole image would be grain over somebody's profile card.
 *
 * The noise tile is 96px of white pixels at random alpha, drawn at 3x with
 * image-rendering: pixelated so each source pixel lands as a 3px square
 * rather than being smoothed back into a grey wash by the scaler.
 */

.shot-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  /* Two across, not four. The page is capped at 780px and these are
     phone-shaped: four columns puts each screenshot at ~180px, where the
     UI in it stops being legible and the caption under it is four words to
     a line. Two is 370px, which is close enough to a real phone that the
     shot reads as one. */
  grid-template-columns: repeat(2, 1fr);
  gap: 1.2rem;
}

/* Held to roughly the width the old 780px page gave these. The band around
   them is 1080px wide now, and two columns of that is a 526px phone, at which
   size the caption's own gradient is taller than a real handset and the shot
   stops reading as a screenshot. After the rule above, not before it: that
   one sets `margin: 0`, which was quietly undoing the centring. */
.shot-grid {
  max-width: 740px;
  margin-left: auto;
  margin-right: auto;
}

.shot {
  position: relative;
  /* Own stacking context, so the absolutely positioned layers below can't
     escape past the border or over the section that follows. */
  isolation: isolate;
  overflow: hidden;
  border: 2px solid #3a3a52;
  background: var(--bg-1);
  text-align: left;
}

.shot-img {
  display: block;
  width: 100%;
  height: auto;
}

.shot-fade,
.shot-grain {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* Solid for the bottom 38% (the caption's floor), then gone by 72%. The two
   figures are also what the grain mask below is aimed at — change one and
   the band stops sitting on the seam. */
.shot-fade {
  background: linear-gradient(
    to top,
    var(--fade) 0%,
    var(--fade) 27%,
    color-mix(in srgb, var(--fade) 45%, transparent) 41%,
    transparent 56%
  );
}

.shot-grain {
  background-image: url("shots/noise.png");
  background-size: 288px 288px;
  image-rendering: pixelated;
  opacity: 0.4;
  /* Centred on the fade's own transition (27%-56% above), and narrower than
     it: the band is meant to hide the seam, not to frost the screenshot. */
  -webkit-mask-image: linear-gradient(
    to top,
    transparent 22%,
    #000 33%,
    #000 44%,
    transparent 58%
  );
  mask-image: linear-gradient(
    to top,
    transparent 22%,
    #000 33%,
    #000 44%,
    transparent 58%
  );
}

/* Without a mask the tile would cover the whole screenshot, which is worse
   than no grain at all. */
@supports not (
  (mask-image: linear-gradient(#000, #000)) or
    (-webkit-mask-image: linear-gradient(#000, #000))
) {
  .shot-grain {
    display: none;
  }
}

.shot-copy {
  position: absolute;
  inset: auto 0 0 0;
  padding: 1.1rem 1.1rem 1.25rem;
}

.shot-copy h3 {
  font-family: "Press Start 2P", monospace;
  font-size: 0.74rem;
  line-height: 1.5;
  margin: 0 0 0.55rem;
  color: var(--white);
}

.shot-copy p {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.5;
  /* Not pure white: at this size, over a saturated ground, it vibrates. */
  color: #f1eef7;
}

@media (max-width: 460px) {
  .shot-grid {
    grid-template-columns: 1fr;
    max-width: 340px;
    margin: 0 auto;
  }
}

/* --- footer ---
 * Widened into columns. A one-line footer with three links in it is a
 * personal site; a consumer product's footer is where somebody goes looking
 * for the company, and the shape itself is part of what says this is one.
 */

.footer {
  background: var(--grey-900);
  padding: 3.5rem 1.5rem 2.5rem;
  color: var(--text-faint);
  font-size: 0.85rem;
}

.footer-top {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: 2rem;
  text-align: left;
  padding-bottom: 2.5rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.logo-sm {
  margin-bottom: 0.85rem;
}

.footer-pitch {
  margin: 0;
  max-width: 34ch;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--text-faint);
}

.footer-col {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

/* An <h2> because these are real section headings in the document outline,
   sized down to look like the labels they are. */
.footer-head {
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0 0 0.15rem;
}

/* Deliberately brighter than the copyright line beneath. These are links App
   Review has to be able to find, and a reviewer scanning a footer should not
   have to hunt for them in grey. */
.footer-col a {
  color: var(--text-dim);
  text-decoration: none;
  width: fit-content;
}

.footer-col a:hover {
  color: var(--gold);
}

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.5rem 1.5rem;
  padding-top: 1.75rem;
  font-size: 0.8rem;
  color: #6f6d85;
}

.footer-bottom p {
  margin: 0;
}

.footer-credit a {
  color: #6f6d85;
  text-decoration: underline;
}

.footer-credit a:hover {
  color: var(--text-dim);
}

/* --- responsive ---
 * Three collapses, in the order the columns stop working: four across to two
 * on a tablet, then everything to one on a phone.
 */

@media (max-width: 900px) {
  .stat-row,
  .tab-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .feature-grid,
  .steps {
    grid-template-columns: repeat(2, 1fr);
  }

  .footer-top {
    grid-template-columns: 1fr 1fr;
  }

  .footer-brand {
    grid-column: 1 / -1;
  }
}

@media (max-width: 640px) {
  .band {
    padding: 3.25rem 1.25rem;
  }

  .steps,
  .feature-grid {
    grid-template-columns: 1fr;
  }

  /* The numbered badge overlaps the card above it, so a single column needs
     more gap than a row does or the circles land on the previous card. */
  .steps {
    gap: 2.25rem;
  }

  .tab-grid {
    gap: 1rem;
  }

  .footer-top {
    grid-template-columns: 1fr;
  }

  .footer-bottom {
    justify-content: flex-start;
  }
}

@media (max-width: 420px) {
  .stat-row {
    grid-template-columns: 1fr 1fr;
  }

  .btn-primary {
    font-size: 0.98rem;
    padding: 1rem 1.4rem;
  }
}

/* The half-sentence after the rotating word, on its own line under it. */
.tagline-tail {
  display: block;
}
