/*
 * Eloqutix waitlist signup — DIA-88.
 *
 * The tokens below are lifted from the Dart design system, which is the source
 * of truth: packages/eloqutix_design_system/lib/tokens/{colors,typography,
 * geometry}.dart. They are named exactly as the design names them
 * (`--cadence-color-gold`, `--cadence-font-fredoka`, `--cadence-radius-pill`),
 * so the page and the artboards can be read side by side.
 *
 * The Cadence React mirror was read to build this and is deliberately not
 * shipped: it is a second source of truth that drifts from the Dart, and
 * shipping it would turn that drift into a production defect instead of a
 * design-review one.
 *
 * **The font sizes here are the design's, not the design system's.** The system
 * floors at 14px and the design overrides five components up to 16px and 17px,
 * because below 16px mobile browsers zoom the page on focus and break the
 * layout. That is FR12, and re-using a system default anywhere below 16px
 * reintroduces exactly the bug it exists to prevent.
 *
 * There is no build step. This file is served as written.
 */

/* --------------------------------------------------------------------------
   Faces
   Self-hosted from packages/eloqutix_design_system/lib/fonts, converted to
   WOFF2. Nothing is fetched from Google Fonts, and keeping it that way is
   worth more than it was: App Check was configured on 2026-09-11, so the page
   does now reach three Google hosts when a visitor presses the join button,
   and FR11's "no banner is needed" is an argument rather than a fact. Every
   request this stylesheet does NOT add is one fewer thing that argument has to
   carry. See site/appcheck.js.

   Fredoka and Nunito are variable fonts, so one file covers every weight.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "Fredoka";
  src: url("fonts/Fredoka.woff2") format("woff2-variations");
  font-weight: 300 700;
  font-display: swap;
}

@font-face {
  font-family: "Nunito";
  src: url("fonts/Nunito.woff2") format("woff2-variations");
  font-weight: 200 1000;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Mono";
  src: url("fonts/IBMPlexMono-Medium.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   Tokens
   -------------------------------------------------------------------------- */

:root {
  --cadence-font-fredoka: "Fredoka", "Trebuchet MS", "Segoe UI", sans-serif;
  --cadence-font-nunito: "Nunito", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --cadence-font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --cadence-color-stage: #07031a;
  --cadence-color-magenta: #ff2e88;
  --cadence-color-magenta-pressed: #a80c56;
  --cadence-color-cyan: #22e3ff;
  --cadence-color-gold: #ffc53d;
  --cadence-color-lime: #7cff5a;
  --cadence-color-heart: #ff3b5c;

  --cadence-color-text-primary: #ffffff;
  --cadence-color-text-bright: #d8cff5;
  --cadence-color-text-secondary: #b9aee4;
  --cadence-color-text-tertiary: #8e7fc4;
  --cadence-color-text-quaternary: #6a5d9b;
  --cadence-color-ink-on-light: #1a0940;

  --cadence-color-surface: rgba(255, 255, 255, 0.05);
  --cadence-color-field: rgba(255, 255, 255, 0.07);

  --cadence-radius-md: 12px;
  --cadence-radius-lg: 16px;
  --cadence-radius-xl: 18px;
  --cadence-radius-xxl: 20px;
  --cadence-radius-pill: 999px;

  /* The desktop backdrop, which is CadenceBackdrops.payoff. */
  --cadence-backdrop: radial-gradient(
    circle 900px at 50% 4%,
    #4a1a8c 0%,
    #170a38 46%,
    var(--cadence-color-stage) 100%
  );

  /*
   * Type, at desktop. The phone sizes are the same names, narrowed below.
   *
   * The reading sizes are one step above the design's, because the column is
   * one step wider than the design's: see the note on `main`. The display
   * sizes (the name, the state headings) are the design's, unchanged — they
   * are set in Fredoka at a size chosen for presence rather than for measure,
   * and nothing about the width argues for moving them.
   */
  --size-name: 64px;
  --size-headline: 30px;
  --size-lead: 20px;
  --size-state-head: 34px;
  --size-state-body: 20px;
  --size-body: 18px;
  --size-benefit-title: 20px;
  --size-section: 24px;
  --form-width: 460px;
  --stack-gap: 16px;
}

/* --------------------------------------------------------------------------
   Page
   -------------------------------------------------------------------------- */

* {
  box-sizing: border-box;
}

html {
  /* The stage has to reach past the content, or a short state (the confirmed
     one) leaves the browser's own background showing under it. */
  background: var(--cadence-color-stage);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--cadence-backdrop) no-repeat;
  background-attachment: fixed;
  font-family: var(--cadence-font-nunito);
  font-weight: 700;
  color: var(--cadence-color-text-primary);
  -webkit-font-smoothing: antialiased;
}

/*
 * The column is 800px of content, not the design's 560.
 *
 * The artboards were drawn at 560 because the design system is a 402px phone
 * app and that was the honest widening of it. On a real desktop it read as a
 * phone screenshot with the rest of the screen left over around it, which is
 * what UAT found on 2026-09-03. The owner set the width.
 *
 * **The body size goes up with it, and that is not decoration.** Line length
 * is a function of both, and 800px at the design's 18px is around 87
 * characters a line, well past the roughly 75 where reading starts to cost.
 * At 20px it is back to about 78. So the column and the type widen together:
 * taking the width without the size would have bought screen coverage with
 * readability, on a page whose whole job is to be read once. Anything that
 * changes one of these two numbers has to look at the other.
 */
main {
  width: 100%;
  max-width: 840px;
  margin: 0 auto;
  padding: 48px 20px;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* A state that is not the current one is not hidden with `display:none` on a
   class, because `hidden` is the thing assistive technology already agrees
   about and needs no CSS to be correct if this file fails to load. */
[hidden] {
  display: none !important;
}

/* --------------------------------------------------------------------------
   Masthead and lead
   -------------------------------------------------------------------------- */

.name {
  font-family: var(--cadence-font-fredoka);
  font-weight: 600;
  font-size: var(--size-name);
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--cadence-color-text-primary);
  margin: 0;
}

.headline {
  font-family: var(--cadence-font-fredoka);
  font-weight: 500;
  font-size: var(--size-headline);
  line-height: 1.22;
  color: var(--cadence-color-text-bright);
  text-wrap: pretty;
  max-width: 30ch;
  margin: 14px 0 0;
}

.lead {
  font-size: var(--size-lead);
  line-height: 1.5;
  color: var(--cadence-color-text-secondary);
  text-wrap: pretty;
  margin: 14px 0 0;
}

/* --------------------------------------------------------------------------
   Benefits
   -------------------------------------------------------------------------- */

.benefits {
  list-style: none;
  margin: 18px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.benefit {
  display: flex;
  gap: 12px;
}

.benefit::before,
.removal .points li::before {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  margin-top: 9px;
  border-radius: var(--cadence-radius-pill);
  background: var(--cadence-color-gold);
}

.benefit b {
  display: block;
  font-family: var(--cadence-font-fredoka);
  font-weight: 600;
  font-size: var(--size-benefit-title);
  line-height: 1.25;
  color: var(--cadence-color-text-bright);
  margin-bottom: 3px;
}

.benefit span {
  font-size: var(--size-body);
  line-height: 1.42;
  color: var(--cadence-color-text-secondary);
  text-wrap: pretty;
}

.mechanism {
  font-size: var(--size-body);
  line-height: 1.42;
  color: var(--cadence-color-text-tertiary);
  text-wrap: pretty;
  margin: 14px 0 0;
}

/* --------------------------------------------------------------------------
   The cited callout

   The kit has no citation treatment, so this is `surface` with a gold left
   rule. It is one of the three things in this design that did not already
   exist.
   -------------------------------------------------------------------------- */

.citation {
  margin: 14px 0 0;
  padding: 13px 15px;
  border-radius: var(--cadence-radius-md);
  background: var(--cadence-color-surface);
  border-left: 3px solid var(--cadence-color-gold);
}

.citation p {
  margin: 0;
  font-size: var(--size-body);
  line-height: 1.42;
  color: var(--cadence-color-text-bright);
  text-wrap: pretty;
}

.citation cite {
  display: block;
  margin-top: 4px;
  font-family: var(--cadence-font-mono);
  font-weight: 500;
  font-style: normal;
  font-size: var(--size-body);
  line-height: 1.3;
  color: var(--cadence-color-text-quaternary);
}

/* --------------------------------------------------------------------------
   CadenceSpeechBubble
   -------------------------------------------------------------------------- */

.bubble-row {
  margin-top: 18px;
  display: flex;
  align-items: flex-end;
  gap: 9px;
}

.bubble-row .vinny {
  flex: none;
  width: auto;
  height: 74px;
}

.bubble {
  flex: 1;
  margin-bottom: 6px;
  padding: 13px 15px;
  background: var(--cadence-color-text-primary);
  /* Three round corners and one tucked into the tail. */
  border-radius: var(--cadence-radius-xl) var(--cadence-radius-xl)
    var(--cadence-radius-xl) 4px;
  font-size: var(--size-body);
  font-weight: 800;
  line-height: 1.4;
  color: var(--cadence-color-ink-on-light);
}

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

.ask {
  font-size: var(--size-body);
  line-height: 1.45;
  color: var(--cadence-color-text-secondary);
  text-wrap: pretty;
  margin: 18px 0 0;
}

/*
 * The form does not follow the column.
 *
 * At the design's 560 the field and the button were the full width of the
 * page and looked right. At 800 they do not: a single-line email field two
 * thirds of a screen wide reads as a mistake, and a button that wide stops
 * looking like a button. Everything above it is prose, which wants the
 * column; this is one short input and one control, which want to look like
 * what they are. So the reading column widened and the form did not.
 */
form {
  margin-top: 14px;
  max-width: var(--form-width);
}

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

/* The honeypot. Off-screen rather than `display:none`, because a bot that
   parses styles skips a hidden field and fills this one. */
.trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
}

/* CadenceTextField. The focus ring is drawn on the wrapper so it can sit
   outside the 2px cyan border without changing the field's size. */
.field {
  border-radius: var(--cadence-radius-xl);
  transition: box-shadow 180ms ease-out;
}

.field:focus-within {
  box-shadow: 0 0 0 3px rgba(34, 227, 255, 0.34), 0 0 30px rgba(34, 227, 255, 0.28);
}

.field input {
  display: block;
  width: 100%;
  padding: 20px 18px;
  background: var(--cadence-color-field);
  border: 2px solid var(--cadence-color-cyan);
  border-radius: var(--cadence-radius-xl);
  box-shadow: 0 0 24px rgba(34, 227, 255, 0.22);
  font-family: var(--cadence-font-nunito);
  /* 17px, and never lower: below 16 a mobile browser zooms on focus. */
  font-size: 17px;
  font-weight: 800;
  line-height: 1.2;
  color: var(--cadence-color-text-primary);
  caret-color: var(--cadence-color-cyan);
  outline: none;
}

.field input::placeholder {
  color: var(--cadence-color-text-tertiary);
  opacity: 1;
}

/* D4/M4: the address stays readable while it is being sent. */
.field.is-locked {
  opacity: 0.42;
  filter: saturate(0.5);
}

/* CadenceBanner, tinted heart-red. Sits directly above the button, where the
   press happened. */
.banner {
  margin-top: 14px;
  padding: 13px 15px;
  border-radius: var(--cadence-radius-lg);
  background: color-mix(in srgb, var(--cadence-color-heart) 10%, transparent);
  border: 1.5px solid color-mix(in srgb, var(--cadence-color-heart) 30%, transparent);
  font-size: var(--size-body);
  font-weight: 800;
  line-height: 1.4;
  color: #ff9baa;
}

/* CadencePushButton. The lip is a solid bottom edge with no blur, and the glow
   is the accent bleeding onto the stage: the system's two shadow ideas, and
   mixing them is what makes a screen look muddled. */
.push {
  margin-top: 16px;
  padding-bottom: 7px;
}

/* The anchor is the "take me to the form" link on the cold /inbox screen. It
   is the same step in the same flow as the submit button, so it is the same
   shape rather than a lesser one. Only the button can be disabled, so
   `:disabled` below stays button-only. */
.push button,
.push a {
  display: block;
  width: 100%;
  box-sizing: border-box;
  text-align: center;
  text-decoration: none;
  padding: 16px 18px;
  background: var(--cadence-color-magenta);
  border: 0;
  border-radius: var(--cadence-radius-xxl);
  box-shadow: 0 7px 0 var(--cadence-color-magenta-pressed),
    0 10px 32px rgba(255, 46, 136, 0.45);
  font-family: var(--cadence-font-fredoka);
  font-weight: 600;
  font-size: 19px;
  line-height: 1;
  color: var(--cadence-color-text-primary);
  cursor: pointer;
  transition: transform 90ms cubic-bezier(0.33, 1, 0.68, 1), box-shadow 90ms
    cubic-bezier(0.33, 1, 0.68, 1);
}

.push button:active:not(:disabled),
.push a:active {
  transform: translateY(6px);
  box-shadow: 0 1px 0 var(--cadence-color-magenta-pressed),
    0 4px 32px rgba(255, 46, 136, 0.45);
}

.push button:disabled {
  opacity: 0.45;
  cursor: default;
}

.push button:focus-visible,
.push a:focus-visible {
  outline: 3px solid var(--cadence-color-cyan);
  outline-offset: 4px;
}

/* --------------------------------------------------------------------------
   The post-submit states
   -------------------------------------------------------------------------- */

.state {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: var(--stack-gap);
}

/* `#signup` joins them: `show()` focuses whichever panel it draws, and the
   back button out of /inbox draws this one. The focus is programmatic rather
   than something the visitor did, so a ring around the whole panel would point
   at nothing they were looking for. */
.state:focus,
#signup:focus {
  outline: none;
}

.state .name {
  margin-bottom: 0;
}

.state h1,
.removal h1 {
  font-family: var(--cadence-font-fredoka);
  font-weight: 500;
  font-size: var(--size-state-head);
  line-height: 1.2;
  color: var(--cadence-color-text-bright);
  margin: 0;
}

/*
 * `:where()` and not `.state p`, and this is load-bearing rather than taste.
 *
 * Two of the paragraphs inside a state are not body copy: `.name` and
 * `.bubble`. A plain `.state p` selector (0,1,1) outranks both single class
 * selectors (0,1,0) and silently repaints them: the masthead drops from 64px
 * to body size, and Vinny's speech bubble turns lilac-on-white. `:where()`
 * contributes nothing to specificity, so this is the default the two component
 * classes override rather than the rule that beats them. `.removal` has a
 * `.name` paragraph of its own, so the same holds there.
 */
:where(.state, .removal) p {
  font-size: var(--size-state-body);
  line-height: 1.5;
  color: var(--cadence-color-text-secondary);
  text-wrap: pretty;
  margin: 0;
}

.state .gold {
  font-weight: 800;
  color: var(--cadence-color-gold);
}

.confirmed-head {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* The one lime mark in the whole flow. */
.tick {
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: var(--cadence-radius-pill);
  border: 2px solid var(--cadence-color-lime);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* --------------------------------------------------------------------------
   The request-removal page (request-removal.html)

   Everything here is scoped under `.removal`, the class on that page's
   <body>, so none of it reaches the waitlist page. Each piece is built from a
   rule above: the h1 and body paragraphs share `.state`'s rules, the steps and
   points are `.benefits` with a numeral or the gold dot, the section heading
   is `.state h1` at `--size-section`, and the button is `.push a`.
   -------------------------------------------------------------------------- */

.removal main {
  gap: var(--stack-gap);
}

.removal h1 {
  text-wrap: pretty;
}

.removal h2 {
  font-family: var(--cadence-font-fredoka);
  font-weight: 500;
  font-size: var(--size-section);
  line-height: 1.25;
  color: var(--cadence-color-text-bright);
  margin: 28px 0 0;
}

.removal .steps,
.removal .points {
  list-style: none;
  margin: 4px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.removal .steps li,
.removal .points li {
  display: flex;
  gap: 12px;
}

.removal .steps .num {
  flex: none;
  width: 18px;
  font-family: var(--cadence-font-fredoka);
  font-weight: 600;
  font-size: var(--size-benefit-title);
  line-height: 1.42;
  color: var(--cadence-color-gold);
}

.removal .steps span:not(.num):not(.addr),
.removal .points span {
  font-size: var(--size-body);
  line-height: 1.42;
  color: var(--cadence-color-text-secondary);
  text-wrap: pretty;
}

/* Plain text rather than a link, so it can be selected and copied by anyone
   whose device has no mail app for the button to open. */
.removal .addr {
  font-weight: 800;
  color: var(--cadence-color-text-primary);
  overflow-wrap: anywhere;
}

.removal .push {
  margin-top: 18px;
  max-width: var(--form-width);
}

/* Uppercase here rather than in the markup, so a screen reader reads words. */
.removal .push a {
  text-transform: uppercase;
}

.removal footer {
  margin-top: 40px;
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  font-size: var(--size-body);
  line-height: 1.42;
  color: var(--cadence-color-text-tertiary);
}

.removal footer a {
  color: var(--cadence-color-text-bright);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.removal footer a:focus-visible {
  outline: 3px solid var(--cadence-color-cyan);
  outline-offset: 4px;
}

/* --------------------------------------------------------------------------
   Phone
   The same copy in one narrower column, per M1-M7. Nothing is hidden and
   nothing reflows into a different order: only the type scale changes.
   -------------------------------------------------------------------------- */

@media (max-width: 600px) {
  :root {
    --size-name: 44px;
    --size-headline: 22px;
    --size-lead: 16px;
    --size-state-head: 26px;
    --size-state-body: 16px;
    --size-body: 16px;
    --size-benefit-title: 18px;
    --size-section: 20px;
    /* On a phone the column is already this narrow: the form fills it. */
    --form-width: 100%;
    --stack-gap: 14px;
    --cadence-backdrop: radial-gradient(
      circle 360px at 50% 8%,
      #4a1a8c 0%,
      #170a38 50%,
      var(--cadence-color-stage) 100%
    );
  }

  main {
    padding: 40px 20px;
  }

  .headline {
    line-height: 1.24;
    margin-top: 10px;
  }

  .lead {
    line-height: 1.45;
    margin-top: 10px;
  }
}

/* Vinny bobs in the app. He does not here: the page is read once, and a mascot
   moving under a form is a distraction rather than a personality. Kept as an
   explicit note so nobody adds the animation back thinking it was forgotten. */
@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition: none !important;
  }
}
