/* Devote Democracy: www.devotedemocracy.com
 *
 * Fluid sizes interpolate between a 320px and a 1512px wide viewport, the same
 * range the Flutter site used ("mobileDesktopInterpolation"):
 *   clamp(MIN, calc(MIN + (MAX - MIN) * (100vw - 320px) / 1192), MAX)
 */

/* ------------------------------------------------------------------ fonts */

@font-face { font-family: 'Recoleta'; src: url('/fonts/recoleta-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Recoleta'; src: url('/fonts/recoleta-500.woff2') format('woff2'); font-weight: 500; font-display: swap; }
@font-face { font-family: 'Recoleta'; src: url('/fonts/recoleta-600.woff2') format('woff2'); font-weight: 600; font-display: swap; }
@font-face { font-family: 'Recoleta'; src: url('/fonts/recoleta-700.woff2') format('woff2'); font-weight: 700; font-display: swap; }
@font-face { font-family: 'Raleway'; src: url('/fonts/raleway-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Raleway'; src: url('/fonts/raleway-500.woff2') format('woff2'); font-weight: 500; font-display: swap; }
@font-face { font-family: 'Raleway'; src: url('/fonts/raleway-600.woff2') format('woff2'); font-weight: 600 700; font-display: swap; }
@font-face { font-family: 'Poppins'; src: url('/fonts/poppins-300.woff2') format('woff2'); font-weight: 300 400; font-display: swap; }
@font-face { font-family: 'Poppins'; src: url('/fonts/poppins-500.woff2') format('woff2'); font-weight: 500 600; font-display: swap; }
/* The headline face is subset to the few letters the site sets in it. */
@font-face { font-family: 'Bebas Neue'; src: url('/fonts/bebas-neue-700.woff2') format('woff2'); font-weight: 400 700; font-display: block; }

/* ------------------------------------------------------------------ tokens */

:root {
  --blue: #0277bd;
  --blue-dark: #015c93;
  --red: #e57373;          /* Material red[300], the donate accent */
  --red-strong: #d64545;   /* filled red with white text (passes contrast) */
  --beige: #f5f5dc;
  --cream: #f9f9d8;
  --yellow: #fff59d;       /* yellow[200] */
  --yellow-strong: #fff176;/* yellow[300] */
  --segment-bg: #e5e5ea;
  --grey-100: #f5f5f5;
  --grey-300: #e0e0e0;
  --grey-600: #6b6b6b;
  --grey-700: #616161;
  --grey-800: #424242;
  --grey-900: #212121;
  --white: #fff;
  --black: #000;

  --font-display: 'Bebas Neue', Impact, 'Arial Narrow', sans-serif;
  --font-title: 'Recoleta', Georgia, 'Times New Roman', serif;
  --font-body: 'Raleway', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-ui: 'Poppins', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --fluid: calc((100vw - 320px) / 1192);   /* 0 at 320px, 1 at 1512px (a length; multiply by a number of px) */
  --gutter: clamp(16px, calc(9.5vw - 15px), 160px);
  --nav-top: 40px;
  --nav-raise: 26px;
  --pill-shadow: 0 5px 10px 5px rgb(0 0 0 / 0.05);
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
}

/* ------------------------------------------------------------------ base */

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 100px;
}

body {
  margin: 0;
  background: var(--white);
  color: var(--grey-900);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img, video, svg { display: block; max-width: 100%; }
img { height: auto; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
a { color: var(--blue); }
h1, h2, h3, p { margin: 0; }
ul, ol { margin: 0; padding: 0; }
fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }

.icon { width: 1em; height: 1em; flex: none; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}

.skip-link {
  position: fixed;
  top: 8px; left: 8px;
  z-index: 200;
  padding: 10px 16px;
  border-radius: 8px;
  background: var(--white);
  color: var(--blue);
  font-weight: 600;
  transform: translateY(-150%);
  transition: transform 0.2s var(--ease);
}
.skip-link:focus { transform: none; }

:focus-visible { outline: 3px solid var(--blue); outline-offset: 3px; }
.waitlist :focus-visible,
.site-footer :focus-visible { outline-color: var(--yellow); }

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  position: relative;
  min-height: 50px;
  padding: 10px 28px;
  border: 0;
  border-radius: 10px;
  font-family: var(--font-body);
  font-size: clamp(18px, calc(18px + 7 * var(--fluid)), 25px);
  text-decoration: none;
  transition: background-color 0.2s, transform 0.1s;
}
.button:active { transform: translateY(1px); }
.button--blue { background: var(--blue); color: var(--white); }
.button--blue:hover { background: var(--blue-dark); }

/* A spinner shown while a form submits ([aria-busy=true] on the button). */
.spinner {
  display: none;
  width: 1.4em; height: 1.4em;
  border: 3px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
[aria-busy='true'] .spinner { display: block; }
[aria-busy='true'] > .icon,
[aria-busy='true'] > .button__text,
[aria-busy='true'] > .pay-button__text,
[aria-busy='true'] > img { opacity: 0; }
[aria-busy='true'] .spinner { position: absolute; }
@keyframes spin { to { transform: rotate(360deg); } }

.field-error {
  min-height: 0;
  color: #b71c1c;
  font-size: 15px;
  font-weight: 500;
}
.field-error:empty { display: none; }

/* The coins beside "Donate": every few seconds they shake and swell. */
.coin-nudge { animation: coin-nudge 5.6s ease-in-out 4s infinite; transform-origin: 50% 60%; }
@keyframes coin-nudge {
  0%, 72%, 100% { transform: none; }
  75% { transform: translateX(-2px) rotate(-10deg) scale(1.2); }
  78% { transform: translateX(2px) rotate(10deg) scale(1.35); }
  81% { transform: translateX(-2px) rotate(-8deg) scale(1.5); }
  84% { transform: translateX(1px) rotate(5deg) scale(1.5); }
  92% { transform: scale(1.15); }
}

/* Chunky rounded scrollbars for the FAQ panes, after the Flutter site's: a
 * wide white handle in a grey track. */
.scroll-area { scrollbar-gutter: stable; }
@supports not selector(::-webkit-scrollbar) {
  .scroll-area { scrollbar-color: var(--white) var(--grey-300); }
}
.scroll-area::-webkit-scrollbar { width: 22px; height: 22px; }
.scroll-area::-webkit-scrollbar-track { background: var(--grey-300); border-radius: 22px; }
.scroll-area::-webkit-scrollbar-thumb { min-height: 48px; background: var(--white); border: 3px solid var(--grey-300); border-radius: 22px; box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.04); }
.scroll-area::-webkit-scrollbar-thumb:hover { background: #fafafa; }

/* ------------------------------------------------------------------ navigation */

.site-nav {
  position: fixed;
  inset: 0 0 auto;
  z-index: 50;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: var(--nav-top) var(--gutter) 0;
  pointer-events: none;
  transition: transform 0.5s var(--ease);
}
.site-nav > * { pointer-events: auto; }
.site-nav.is-raised { transform: translateY(calc(-1 * var(--nav-raise))); }

.nav-pill {
  display: grid;
  place-items: center;
  min-width: 50px;
  height: 50px;
  padding: 0 15px;
  border: 0;
  border-radius: 50px;
  background: var(--white);
  color: var(--black);
  box-shadow: var(--pill-shadow);
  transition: background-color 0.2s;
}
.nav-pill:hover { background: #ececec; }
.nav-pill .icon { width: 25px; height: 25px; }
/* The ballot box with its shadow (from the CMS media library). */
.devote-logo { width: 40px; height: auto; }
/* The shadow falls to the left, so the box itself is centred at 67.5% of the
 * image: shift it back so the box, not the picture, sits in the middle. */
.nav-home { width: 60px; padding: 0; }
.nav-home .devote-logo { transform: translateX(-17.5%); }

.nav-middle {
  display: flex;
  align-items: center;
  height: 55px;
  padding: 0 3px;
  border-radius: 50px;
  background: var(--white);
  box-shadow: var(--pill-shadow);
}

.nav-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 45px;
  padding: 0 35px;
  border-radius: 50px;
  color: var(--black);
  font-family: var(--font-title);
  font-size: 20px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 0.2s;
}
.nav-link:hover { background: rgb(0 0 0 / 0.08); }
.nav-link[aria-current='page'] { background: rgb(0 0 0 / 0.06); }
.nav-link--donate { color: var(--blue); }
.nav-link .coin-nudge { width: 20px; transition: transform 0.3s; }

/* Each label is two stacked labels: the poster-style one shown over the hero
 * and the serif one shown everywhere else. They cross-fade. */
.nav-link, .nav-link__stack { display: inline-grid; grid-auto-flow: column; align-items: center; }
.nav-link__stack { display: inline-grid; grid-auto-flow: row; }
.nav-link > .nav-label, .nav-link__stack > .nav-label { grid-area: 1 / 1; }
.nav-label { transition: opacity 0.3s; }
.nav-label--display {
  justify-self: center;
  padding-top: 3px;
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 0.02em;
  opacity: 0;
}
[data-nav-style='display'] .site-nav:not(.is-past-hero) .nav-label--display { opacity: 1; }
[data-nav-style='display'] .site-nav:not(.is-past-hero) .nav-label--text { opacity: 0; }
[data-nav-style='display'] .site-nav:not(.is-past-hero) .nav-link--donate .coin-nudge { translate: 4px 0; }

@media (max-width: 949px) {
  .nav-link--waitlist, .nav-link--contact { display: none; }
  .nav-link { padding: 0 20px; }
}

/* ------------------------------------------------------------------ drawer */

.drawer {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  overflow: hidden;
}
.drawer::backdrop { background: rgb(0 0 0 / 0.45); transition: opacity 0.3s; }
.drawer[open]::backdrop { opacity: 1; }
.drawer.is-closing::backdrop { opacity: 0; }

.drawer__panel {
  position: absolute;
  inset: 0 auto 0 0;
  display: flex;
  flex-direction: column;
  width: min(300px, 85vw);
  background: var(--white);
  transform: none;
  transition: transform 0.3s var(--ease);
}
.drawer.is-closing .drawer__panel { transform: translateX(-100%); }
@starting-style {
  .drawer[open] .drawer__panel { transform: translateX(-100%); }
  .drawer[open]::backdrop { opacity: 0; }
}

.drawer__close {
  position: absolute;
  top: var(--nav-top);
  right: var(--gutter);
}
@media (max-width: 420px) {
  .drawer__close { top: auto; bottom: 24px; }
}

.drawer__brand {
  display: flex;
  align-items: center;
  gap: 15px;
  padding: 32px 36px 20px;
  color: rgb(0 0 0 / 0.87);
  font-family: var(--font-title);
  font-size: 30px;
  font-weight: 500;
  text-decoration: none;
}

.drawer__scroll { flex: 1; overflow-y: auto; padding: 10px 40px 20px; }
.drawer__title {
  margin: 0 0 10px;
  color: var(--blue);
  font-family: var(--font-ui);
  font-size: 16px;
  font-weight: 500;
  text-transform: uppercase;
}
.drawer__scroll ul { list-style: none; margin-bottom: 40px; }
.drawer__scroll li { margin-bottom: 3px; }
.drawer__scroll a,
.drawer__subscription {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 0;
  border: 0;
  background: none;
  color: rgb(0 0 0 / 0.87);
  font-family: var(--font-ui);
  font-size: 20px;
  font-weight: 300;
  text-decoration: none;
  transition: color 0.15s;
}
.drawer__scroll a:hover { color: var(--blue); text-shadow: 0.3px 0 currentColor, -0.3px 0 currentColor; }
.drawer__subscription:hover { color: var(--red); }
.drawer__scroll .drawer__donate { color: var(--blue); font-weight: 500; }
.drawer__donate:hover { text-decoration: underline; }
.drawer__donate .coin-nudge { width: 20px; animation-play-state: paused; }
.drawer__donate:hover .coin-nudge { animation: coin-nudge 1.6s ease-in-out; }

.drawer__socials {
  display: flex;
  flex-wrap: wrap;
  gap: 20px 30px;
  padding: 16px 30px 8px;
  list-style: none;
}
.drawer__socials .social span { display: none; }
.drawer__socials .social { color: var(--blue); font-size: 25px; }
.drawer__socials .social:hover { color: rgb(0 0 0 / 0.87); }
.drawer__socials .social--soon { color: rgb(2 119 189 / 0.25); }
.drawer__legal {
  padding: 8px 30px 24px;
  font-family: var(--font-ui);
  font-size: 13px;
  text-align: center;
}
.drawer__legal a { color: rgb(0 0 0 / 0.87); text-decoration: none; }
.drawer__legal a:hover { color: var(--blue); }

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

.hero {
  --hero-gutter: clamp(16px, calc(30px + 50 * var(--fluid)), 80px);
  --hero-top: clamp(110px, calc(110px + 10 * var(--fluid)), 120px);
  /* Bebas Neue, artificially fattened: a stroke drawn outside each letter and
   * tighter spacing make the letters touch, and the lines nearly do. */
  --title-tracking: -0.015em;
  --title-fatten: 0.05em;
  --fit-wide: 3.58;      /* "DEMOCRACY": 3.69em of advances, minus 9 x the tracking */
  --fit-narrow: 1.93;    /* "CRACY": 1.98em, minus 5 x the tracking */
  --title-line: 0.77;
  --hero-bottom: clamp(100px, calc(100px + 90 * var(--fluid)), 190px);
  --hero-min: clamp(560px, 100vh, 920px);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--black);
}
@supports (height: 100svh) {
  .hero { --hero-min: clamp(560px, 100svh, 920px); }
}

/* The knockout copy and the visible copy of the headline get the same box
 * (full hero height, same padding, centred), so they always line up. */
.hero__knockout,
.hero__front {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-top: var(--hero-top);
  padding-bottom: var(--hero-bottom);
}

.hero__media { position: absolute; inset: 0; z-index: 0; }
.hero__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #3c3c3c url('/img/democracy-now-poster.webp') center / cover;
}
/* The Flutter site lifted the footage with a pale, grainy wash. */
.hero__wash { position: absolute; inset: 0; background: rgb(255 255 255 / 0.3); }

/* Black with white letters, multiplied over the video: the black hides the
 * footage and the letters let it through. At 90% opacity the dark part keeps
 * a faint glimpse of the crowd. */
.hero__knockout {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--black);
  color: var(--white);
  mix-blend-mode: multiply;
  opacity: 0.9;
}

.hero__grain {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: url('/img/concrete-wall-2.webp') 0 0 / 160px;
  opacity: 0.35;
  pointer-events: none;
}

.hero__front {
  position: relative;
  z-index: 4;
  min-height: var(--hero-min);
}

.hero__inner {
  width: 100%;
  container-type: inline-size;
  max-width: 1800px;
  margin-inline: auto;
  padding-inline: var(--hero-gutter);
}

.hero__title {
  /* With a line height below the cap height, the caps (plus the stroke) rise
   * about 0.09em above the first line box: this keeps them below the nav. */
  margin: 0.1em 0 0;
  font-family: var(--font-display);
  /* As wide as the column allows, but short enough that the headline and
   * ticket fit the first screen (two lines, plus the hero's top and bottom). */
  font-size: max(120px, min(calc(100cqi / var(--fit-wide)), calc((100vh - 310px) / (2 * var(--title-line)))));
  font-size: max(120px, min(calc(100cqi / var(--fit-wide)), calc((100svh - 310px) / (2 * var(--title-line)))));
  font-weight: 700;
  line-height: var(--title-line);
  letter-spacing: var(--title-tracking);
  text-transform: uppercase;
}
/* The stroke only paints; it never moves the layout, so both copies still
 * line up. */
.hero__knockout .hero__title {
  -webkit-text-stroke: var(--title-fatten) currentColor;
  paint-order: stroke fill;
}
.hero__front .hero__title { color: transparent; }
.hero__line { display: flex; align-items: center; }
.hero__line--2 { flex-wrap: wrap; column-gap: 0.12em; }
.hero__now { flex: none; }

/* The ticket's box is set by CSS alone, so it lays out identically in the
 * knockout layer (where the slot is empty) and the front layer. Beside "NOW!"
 * it's sized in the headline's own em: at most 1.6em wide, so never taller
 * than a line (0.69em), and it always fits in the space "NOW!" leaves. */
.hero__ticket-slot {
  flex: 0 1 1.6em;
  max-width: min(1.6em, 420px);
  margin-inline: auto;
  aspect-ratio: 780 / 336;
  line-height: 0;
}
.hero__ticket {
  display: block;
  width: 100%;
  border-radius: 6px;
  transition: opacity 0.2s, transform 0.2s var(--ease);
}
.hero__ticket:hover { opacity: 0.8; transform: rotate(-1.5deg) scale(1.02); }
.hero__ticket img { width: 100%; }

@container (max-width: 560px) {
  /* Three lines and the ticket underneath. Filling the width wins; only very
   * short screens shrink it. */
  .hero__title { font-size: max(96px, min(calc(100cqi / var(--fit-narrow)), calc((100svh - 250px) / (3 * var(--title-line))))); }
  .hero__line--1 { flex-direction: column; align-items: flex-start; }
  /* On phones "NOW!" leaves no room, so the ticket gets its own row. */
  .hero__line--2 { row-gap: 28px; }
  .hero__ticket-slot { flex-basis: 100%; max-width: min(100%, 340px); }
}

/* Three crowds of silhouettes along the bottom, moving at different speeds as
 * the hero scrolls away (--p goes 0 to 1). */
.hero__crowd { position: absolute; inset: auto 0 0; z-index: 3; height: 0; }
.crowd {
  position: absolute;
  left: 50%;
  width: max(100%, 1210px);
  max-width: none;
  transform: translate3d(-50%, calc(var(--p, 0) * var(--shift)), 0);
  will-change: transform;
}
.crowd--far  { bottom: -40px; --shift: -40%; opacity: 0.1; }
.crowd--mid  { bottom: -55px; --shift: -20%; opacity: 0.3; }
.crowd--near { bottom: -6px;  --shift: 5%; }

/* ------------------------------------------------------------------ mission */

.mission {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: 4vw;
  padding: 60px var(--gutter) 0;
}
.mission__art img { width: 100%; max-width: 600px; margin-inline: auto; }
.mission__text { max-width: 560px; justify-self: center; text-align: center; }
.mission h2 {
  margin-bottom: 20px;
  color: var(--grey-800);
  font-family: var(--font-title);
  font-size: clamp(40px, calc(40px + 25 * var(--fluid)), 65px);
  font-weight: 500;
  line-height: 1.15;
}
.mission__lead {
  max-width: 13em;
  margin: 0 auto 30px;
  color: var(--grey-800);
  font-family: var(--font-title);
  font-size: clamp(19px, calc(19px + 6 * var(--fluid)), 25px);
  font-weight: 500;
  line-height: 1.35;
}
.mission__body {
  color: var(--grey-600);
  font-size: clamp(16px, calc(16px + 4 * var(--fluid)), 20px);
  text-align: justify;
}
@media (min-width: 1400px) { .mission__art img { max-width: 760px; } }
@media (max-width: 949px) {
  .mission { grid-template-columns: 1fr; padding-top: 30px; gap: 30px; }
  .mission__text { order: -1; }
  .mission__art img { max-width: min(600px, 80%); }
}

/* ------------------------------------------------------------------ app preview */

.app {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: 4vw;
  padding: clamp(150px, calc(150px + 50 * var(--fluid)), 200px) var(--gutter) clamp(120px, 18vw, 300px);
  overflow-x: clip;
}
.app__copy { display: flex; flex-direction: column; align-items: center; text-align: center; }

.segmented {
  position: relative;
  display: inline-grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  padding: 2px;
  border-radius: 50px;
  background: var(--segment-bg);
}
.segmented__thumb {
  position: absolute;
  top: 2px; bottom: 2px; left: 2px;
  width: calc((100% - 4px) / var(--count, 3));
  border-radius: 50px;
  background: rgb(2 119 189 / 0.92);
  box-shadow: 0 2px 4px 1px rgb(0 0 0 / 0.3);
  transform: translateX(calc(var(--index, 0) * 100%));
  transition: transform 0.35s var(--ease);
}
.segmented--red { --count: 2; }
.segmented--red .segmented__thumb { background: var(--red-strong); }
.segmented__option {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  min-height: 35px;
  padding: 0 16px;
  border: 0;
  border-radius: 50px;
  background: none;
  color: rgb(0 0 0 / 0.87);
  font-family: var(--font-ui);
  font-size: clamp(15px, calc(15px + 2 * var(--fluid)), 17px);
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: color 0.25s;
}
.segmented__option[aria-selected='true'],
.segmented__option:has(input:checked) { color: var(--white); }
.segmented__option input { position: absolute; opacity: 0; pointer-events: none; }
.segmented__option:has(input:focus-visible) { outline: 3px solid var(--blue); outline-offset: 2px; }

/* All three panels share one grid cell, so the column keeps the height of the
 * longest and nothing jumps when you switch. */
.audience__panels { display: grid; margin-top: 30px; }
.audience__panel { grid-area: 1 / 1; transition: opacity 0.3s; }
.audience__panel[hidden] { display: block; visibility: hidden; opacity: 0; }
.audience__title {
  margin-bottom: 15px;
  color: var(--grey-900);
  font-family: var(--font-title);
  font-size: clamp(27px, calc(27px + 8 * var(--fluid)), 35px);
  font-weight: 500;
}
.audience__text {
  max-width: 600px;
  color: var(--grey-600);
  font-size: clamp(16px, calc(16px + 2 * var(--fluid)), 18px);
  text-align: justify;
}

/* The phone flies in as the section scrolls up (--q goes 0 to 1). */
.app__phone { display: grid; place-items: center; }
.phone {
  --q: 1;
  position: relative;
  height: min(600px, 150vw);
  aspect-ratio: 600 / 1229;
  transform:
    translate(calc((1 - var(--q)) * -50%), calc((1 - var(--q)) * 20%))
    scale(calc(1 + 0.8 * (1 - var(--q))));
  will-change: transform;
}
.phone__screens {
  position: absolute;
  inset: 0;
  overflow: hidden;
  clip-path: inset(2.8% 4.6% 1.7% 4.6% round 8% / 4%);
  perspective: 1400px;
}
.phone__screen {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: translateX(calc(var(--offset, 0) * 100%)) rotateY(calc(var(--offset, 0) * -14deg));
  transition: transform 0.6s var(--ease);
}
.phone__frame { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }

@media (max-width: 949px) {
  .app { grid-template-columns: 1fr; gap: 30px; }
  .app__phone { order: -1; }
  .phone {
    height: min(520px, 125vw);
    transform: translateY(calc((1 - var(--q)) * 20%)) scale(calc(1 + 0.6 * (1 - var(--q))));
  }
}

/* ------------------------------------------------------------------ FAQs */

.faqs {
  --faq-pad: clamp(8px, calc(8px + 0.075 * (100vw - 320px)), 10vw);
  padding: 0 var(--faq-pad) 50px;
  background: linear-gradient(var(--white) 250px, var(--blue) 250px);
}
.faqs__card {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-areas: 'qt at' 'q a';
  column-gap: clamp(20px, 3vw, 40px);
  max-width: 1500px;
  margin-inline: auto;
  padding: 30px clamp(14px, 2.5vw, 36px) 40px;
  border: 5px solid var(--blue);
  border-radius: 20px;
  background: var(--white);
}
.faqs__title, .faqs__ans-title {
  margin-bottom: 20px;
  color: var(--grey-900);
  font-family: var(--font-title);
  font-size: clamp(40px, calc(40px + 10 * var(--fluid)), 50px);
  font-weight: 600;
  line-height: 1.1;
}
.faqs__title { grid-area: qt; }
.faqs__ans-title { grid-area: at; }

.faqs__questions {
  grid-area: q;
  display: flex;
  flex-direction: column;
  gap: 20px;
  height: 550px;
  padding-right: 20px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.faq-q {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 60px;
  padding: 10px 20px 10px 26px;
  border: 2px solid var(--grey-300);
  border-radius: 10px;
  background: var(--grey-100);
  color: var(--grey-800);
  font-family: var(--font-body);
  font-size: clamp(15px, calc(15px + 3 * var(--fluid)), 18px);
  font-weight: 600;
  line-height: 1.3;
  text-align: left;
  transition: background-color 0.2s, color 0.2s, border-color 0.2s;
}
.faq-q:hover { border-color: #c7c7c7; background: #ececec; }
.faq-q .icon { margin-left: auto; width: 22px; height: 22px; color: var(--grey-700); transition: transform 0.4s var(--ease); }
.faq-q[aria-selected='true'] { border-color: var(--blue); background: var(--blue); color: var(--white); }
.faq-q[aria-selected='true'] .icon { color: var(--white); transform: rotate(60deg); }

.faqs__answer {
  grid-area: a;
  display: flex;
  flex-direction: column;
  height: 550px;
  padding: 30px 10px 30px clamp(20px, 4vw, 60px);
  border-radius: 20px;
  background: var(--beige);
}
.faqs__star { width: 30px; height: 30px; margin-bottom: 20px; color: var(--grey-700); }
.faqs__answers { flex: 1; padding-right: clamp(16px, 3.5vw, 50px); overflow-y: auto; overscroll-behavior: contain; }
.faq-a {
  color: var(--grey-800);
  font-size: clamp(15px, calc(15px + 5 * var(--fluid)), 20px);
  text-align: justify;
  animation: fade-up 0.35s var(--ease);
}
.faq-a p, .faq-a ol, .faq-a ul { margin-bottom: 1em; }
.faq-a ol, .faq-a ul { padding-left: 1.3em; text-align: left; }
.faq-a li + li { margin-top: 0.5em; }
.faq-a:focus-visible { outline-offset: -3px; }
@keyframes fade-up { from { opacity: 0; transform: translateY(6px); } }

@media (max-width: 949px) {
  .faqs__card { grid-template-columns: 1fr; grid-template-areas: 'qt' 'a' 'q'; }
  .faqs__ans-title { display: none; }
  .faqs__answer { height: 400px; padding: 24px 6px 24px 20px; }
  .faqs__questions {
    display: grid;
    grid-auto-flow: column;
    grid-template-rows: repeat(2, auto);
    grid-auto-columns: min(80%, 360px);
    gap: 15px;
    height: auto;
    margin-top: 20px;
    padding: 0 0 12px;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
  }
  .faq-q { scroll-snap-align: start; }
}

/* ------------------------------------------------------------------ waitlist */

.waitlist {
  --c: 0;
  --plane-w: clamp(100px, calc(100px + 100 * var(--fluid)), 200px);
  /* Where the field ends: 78% of the row on wide screens, the row minus the
   * send button on narrow ones. The plane hangs from its right end. */
  --field-end: 78%;
  padding: 80px var(--gutter) 30px;
  background: var(--blue);
  color: var(--white);
  overflow-x: clip;
}
.waitlist__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 4px 25px;
  /* Stop before the paper-plane man (field end + 30px overhang - his width),
   * so the heading wraps onto more lines rather than running under him. */
  max-width: calc(var(--field-end) + 30px - var(--plane-w) - 16px);
}
.waitlist h2 {
  font-family: var(--font-title);
  font-size: clamp(35px, calc(35px + 15 * var(--fluid)), 50px);
  font-weight: 500;
  line-height: 1.15;
}
.waitlist__kicker {
  padding-bottom: 0.6em;
  color: var(--yellow);
  font-size: clamp(18px, calc(18px + 2 * var(--fluid)), 20px);
  font-weight: 500;
}

.waitlist__row { display: flex; align-items: center; gap: clamp(5px, calc(5px + 15 * var(--fluid)), 20px); margin-top: 20px; }
.waitlist__field { position: relative; flex: 0 1 78%; }
.waitlist__field input {
  position: relative;
  z-index: 1;
  width: 100%;
  height: clamp(60px, calc(60px + 10 * var(--fluid)), 72px);
  padding: 0 20px;
  border: 3px solid transparent;
  border-radius: 10px;
  background: var(--white);
  color: var(--grey-600);
  font-size: clamp(18px, calc(18px + 10 * var(--fluid)), 28px);
  font-weight: 500;
}
.waitlist__field input::placeholder { color: #8a8a8a; }
.waitlist__field input:focus-visible { outline: 3px solid var(--yellow); outline-offset: 2px; }
.waitlist__form.is-invalid input { border-color: var(--red); }

.waitlist__plane {
  position: absolute;
  z-index: 0;
  right: -30px;
  top: clamp(-150px, calc(-75px - 75 * var(--fluid)), -75px);
  width: var(--plane-w);
  pointer-events: none;
}
.waitlist__cloud { position: absolute; z-index: 0; pointer-events: none; will-change: transform; }
.waitlist__cloud--1 {
  top: -150px; right: -200px; width: 100px;
  transform: translateX(calc((-5 + 6 * var(--c)) * 100%)) scale(calc(1 - 0.2 * var(--c)));
}
.waitlist__cloud--2 {
  top: -100px; right: -100px; width: 80px;
  transform: translate(calc((1 - 6 * var(--c)) * 100%), calc(var(--c) * -100%)) scale(calc(0.7 + 0.8 * var(--c)));
}
.waitlist__cloud--3 {
  top: 0; right: -100px; width: 50px;
  transform: translateY(calc(var(--c) * -300%)) scale(calc(1 + 0.1 * var(--c)));
}

.waitlist__send {
  position: relative;
  display: grid;
  place-items: center;
  width: 60px;
  height: 60px;
  flex: none;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--white);
  transition: background-color 0.2s, color 0.2s;
}
.waitlist__send .icon { width: 40px; height: 40px; transition: transform 0.25s var(--ease); }
.waitlist__send:hover { background: rgb(255 255 255 / 0.12); }
.waitlist__send:hover .icon { transform: translateX(3px) rotate(-8deg); }
.waitlist__form.is-invalid .waitlist__send { color: #ffcdd2; }
.waitlist .field-error { margin-top: 10px; color: #ffe0e0; }
/* Turnstile: empty unless Cloudflare asks the visitor to click. */
.waitlist__bot-check:not(:empty) { margin-top: 16px; }

.check {
  display: inline-flex;
  align-items: center;
  gap: 20px;
  margin: 40px 0 50px;
  font-size: 20px;
  font-weight: 500;
  cursor: pointer;
}
.check input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.check__box {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex: none;
  border: 2px solid var(--white);
  border-radius: 5px;
  background: var(--white);
  color: #ef5350;
}
.check__box .icon { width: 20px; height: 20px; opacity: 0; transform: scale(0.4); transition: opacity 0.15s, transform 0.2s var(--ease); }
.check input:checked + .check__box .icon { opacity: 1; transform: none; }
.check input:focus-visible + .check__box { outline: 3px solid var(--yellow); outline-offset: 2px; }
.check a { color: var(--white); }

@media (max-width: 949px) {
  .waitlist { --field-end: calc(100% - 60px - clamp(5px, calc(5px + 15 * var(--fluid)), 20px)); }
  .waitlist__head { flex-direction: column; align-items: flex-start; }
  .waitlist__kicker { padding-bottom: 0; }
  .waitlist__field { flex: 1 1 auto; }
  .check { font-size: 17px; gap: 14px; }
}

/* ------------------------------------------------------------------ mini donate */

.mini-donate {
  display: flex;
  justify-content: center;
  padding: 10px var(--gutter) 70px;
  background: var(--blue);
  border-bottom: 0.5px solid rgb(255 255 255 / 0.1);
}
.mini-donate__link {
  display: flex;
  align-items: center;
  gap: 30px;
  padding: 12px 24px;
  border-radius: 16px;
  color: var(--white);
  text-decoration: none;
  transition: background-color 0.2s;
}
.mini-donate__link:hover { background: rgb(255 255 255 / 0.08); }
.mini-donate__jar { position: relative; width: clamp(69px, calc(69px + 14 * var(--fluid)), 83px); }
.mini-donate__tip { position: relative; width: 100%; animation: jar-wiggle 5.6s ease-in-out 4s infinite; transform-origin: 50% 90%; }
.mini-donate__shadow { position: absolute; left: -8px; bottom: -4px; width: 135%; max-width: none; }
.mini-donate__text { display: flex; flex-direction: column; align-items: center; gap: 5px; text-align: center; }
.mini-donate__title { font-family: var(--font-title); font-size: clamp(25px, calc(25px + 7 * var(--fluid)), 32px); font-weight: 500; }
.mini-donate__desc { font-size: clamp(16px, calc(16px + 2 * var(--fluid)), 18px); }
@keyframes jar-wiggle {
  0%, 70%, 100% { transform: none; }
  73% { transform: rotate(-6deg) scale(1.05); }
  76% { transform: rotate(6deg) scale(1.1); }
  79% { transform: rotate(-5deg) scale(1.1); }
  82% { transform: rotate(4deg) scale(1.1); }
  90% { transform: scale(1.02); }
}

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

.site-footer { padding-top: 60px; background: var(--blue); color: var(--white); }
.footer__cols {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 50px 10vw;
  padding-inline: 7vw;
}
.footer__col h2 { margin-bottom: 20px; font-family: var(--font-title); font-size: 22px; font-weight: 500; }
.footer__col--center { text-align: center; }
.footer__col ul { display: grid; gap: 5px; list-style: none; }
.footer__col a,
.footer__col button,
.footer__col p,
.footer__col .social {
  padding: 0;
  border: 0;
  background: none;
  color: var(--white);
  font-family: var(--font-body);
  font-size: 18px;
  text-decoration: none;
}
.footer__col a:hover, .footer__col button:hover { color: var(--yellow); text-decoration: underline; text-underline-offset: 3px; }
.footer__col button:hover { color: #ffcdd2; }
.footer__col .footer__donate { display: inline-flex; align-items: center; gap: 15px; color: var(--yellow-strong); font-weight: 600; }
.footer__donate .coin-nudge { width: 25px; }
.social { display: inline-flex; align-items: center; gap: 8px; }
.social .icon { width: 20px; height: 20px; }
.footer__col .social--soon { opacity: 0.5; cursor: default; }
.footer__copy { padding: 60px 16px 10px; font-size: clamp(12px, calc(12px + 2 * var(--fluid)), 14px); text-align: center; }
.footer__art { width: 100%; }

/* ------------------------------------------------------------------ toasts and dialogs */

.toast-region {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: grid;
  place-items: center;
  padding: 16px;
  pointer-events: none;
}
.toast,
.modal__card {
  position: relative;
  width: min(400px, calc(100vw - 32px));
  padding: 30px 35px;
  border-radius: 10px;
  background: linear-gradient(135deg, var(--white), var(--cream));
  box-shadow: 10px 10px 40px 20px rgb(0 0 0 / 0.1);
  color: rgb(0 0 0 / 0.87);
}
.toast { grid-area: 1 / 1; pointer-events: auto; animation: toast-in 0.35s var(--ease); }
.toast.is-leaving { animation: toast-out 0.25s var(--ease) forwards; }
.toast__art, .modal__art { width: 90px; height: auto; margin-bottom: 10px; }
.toast__art--wide { width: 150px; }
.toast h2, .modal h2 { margin-bottom: 10px; font-family: var(--font-title); font-size: 28px; font-weight: 700; line-height: 1.2; }
.toast__subtitle { margin-bottom: 10px; color: var(--grey-700); font-size: 20px; font-weight: 600; }
.toast__message, .modal p { color: var(--grey-600); font-size: 18px; }
.toast__close, .modal__close {
  position: absolute;
  top: 18px;
  right: 18px;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--black);
}
.toast__close:hover, .modal__close:hover { background: rgb(0 0 0 / 0.06); }
.toast__close .icon, .modal__close .icon { width: 20px; height: 20px; }
/* Slide only, no fade-in: if a background tab freezes animations, the card
 * still shows. */
@keyframes toast-in { from { transform: translateY(16px) scale(0.97); } }
@keyframes toast-out { to { opacity: 0; transform: translateY(10px) scale(0.98); } }

.modal { padding: 0; border: 0; background: none; overflow: visible; }
.modal::backdrop { background: rgb(0 0 0 / 0.45); }
.modal[open] .modal__card { animation: toast-in 0.3s var(--ease); }
.modal p { margin-bottom: 16px; }
.modal .button { width: 100%; margin-top: 6px; }

/* ------------------------------------------------------------------ header crowd backdrop */

/* The line drawing of a crowd behind the donate, contact and legal headers.
 * A real <img> (not a CSS background) so phones get the 1400px file and big
 * screens the 2400px one. */
.crowd-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
}

/* ------------------------------------------------------------------ donate page */

.donate-hero {
  --hero-h: clamp(220px, calc(220px + 200 * var(--fluid)), 420px);
  --base-w: clamp(270px, calc(270px + 430 * var(--fluid)), 700px);
  position: relative;
  height: var(--hero-h);
  margin-bottom: calc(100px + var(--base-w) / 1.5548 - var(--hero-h));
  background: var(--red);
}
.donate-hero__bg { position: absolute; inset: 0; overflow: hidden; opacity: 0.2; }

/* The illustration is laid out on the base picture's own box (700 x 450 at
 * full size): every piece is placed in % of it, so it all scales together. */
.donate-stage {
  position: absolute;
  top: 100px;
  left: 50%;
  width: var(--base-w);
  aspect-ratio: 1400 / 899;
  transform: translateX(-50%);
}
.donate-stage__base { position: relative; z-index: 1; width: 100%; }
.ds { position: absolute; z-index: 2; max-width: none; }
.ds--arm { z-index: 0; left: 55.7%; top: -3.55%; width: 12.4%; transform-origin: 95% 60%; animation: toss-arm 4s infinite; }
.ds--heart { z-index: 0; left: 53.7%; top: -2.9%; width: 5.7%; animation: toss-heart 4s infinite; }
.ds--coin { left: 55.7%; top: 54.9%; width: 10%; }
.ds--female-arm { left: 51.9%; top: 63.8%; width: 5.7%; }
.ds--arm-heart { left: 85.7%; top: 33.3%; width: 20%; transform-origin: 20% 80%; animation: rock 2s ease-in-out infinite; }
.ds--cloud1 { z-index: 0; left: -10%; top: 20%; width: 14.3%; animation: pulse 4s ease-in-out infinite; }
.ds--cloud2 { z-index: 0; left: 18.6%; top: 0; width: 21.4%; animation: drift 4s ease-in-out infinite; }
.ds--cloud3 { z-index: 0; left: 50%; top: -22%; width: 15.7%; }
.ds--cloud4 { z-index: 0; left: 82.9%; top: 2.2%; width: 7.1%; animation: sway 4s ease-in-out infinite; }
.ds--cloud5 { z-index: 0; left: 90%; top: 12.2%; width: 20%; animation: drift-far 40s ease-in-out infinite; }

/* The man on the heart tosses a small heart up and catches it. His arm and
 * the heart sit behind the picture (z-index 0), so only the part reaching out
 * past his body shows. */
/* The arm swings from the shoulder: down to catch (-14deg), a quick flick up
 * to throw (-2deg; any higher and the shoulder end shows above his head). The
 * heart sits in the hand from 45% to 58%, leaves it at the top of the flick
 * and falls back. */
@keyframes toss-arm {
  0% { transform: rotate(-2deg); animation-timing-function: ease-in-out; }
  45%, 58% { transform: rotate(-14deg); animation-timing-function: cubic-bezier(0.5, 0, 0.3, 1); }
  68%, 100% { transform: rotate(-2deg); }
}
@keyframes toss-heart {
  0% { transform: translateY(-260%); animation-timing-function: cubic-bezier(0.5, 0, 1, 1); }
  45%, 58% { transform: translateY(0); animation-timing-function: cubic-bezier(0.5, 0, 0.3, 1); }
  68% { transform: translateY(-45%); animation-timing-function: cubic-bezier(0, 0, 0.4, 1); }
  100% { transform: translateY(-260%); }
}
@keyframes rock { 50% { transform: translateY(5%) rotate(3.6deg); } }
@keyframes pulse { 50% { transform: scale(1.1); } }
@keyframes drift { 50% { transform: translate(-10%, 10%) scale(1.1); } }
@keyframes sway { 50% { transform: translateX(-20%); } }
@keyframes drift-far { 50% { transform: translateX(200%) scale(1.1); } }

.donate-intro { max-width: 1180px; margin-inline: auto; padding: 0 var(--gutter); text-align: center; }
.donate-intro h1 {
  padding-block: clamp(30px, calc(30px + 10 * var(--fluid)), 40px);
  color: rgb(0 0 0 / 0.87);
  font-family: var(--font-title);
  font-size: clamp(40px, calc(40px + 30 * var(--fluid)), 70px);
  font-weight: 700;
  line-height: 1.1;
}
.donate-intro p {
  margin-bottom: 1.2em;
  color: rgb(0 0 0 / 0.87);
  font-size: clamp(16px, calc(16px + 9 * var(--fluid)), 25px);
}
.donate-intro .donate-intro__note { font-size: 0.85em; color: var(--grey-700); }

.donate-main {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: 3vw;
  margin-top: clamp(40px, calc(40px + 40 * var(--fluid)), 80px);
  padding-inline: 5vw;
  overflow-x: clip;
}
.donate-form {
  padding: clamp(20px, calc(20px + 20 * var(--fluid)), 40px) clamp(12px, 2.5vw, 36px);
  border: 5px solid var(--red);
  border-radius: 20px;
  text-align: center;
}
.donate-form__group + .donate-form__group { margin-top: clamp(30px, calc(30px + 30 * var(--fluid)), 60px); }
.donate-form__title {
  display: block;
  width: 100%;
  margin-bottom: 20px;
  padding: 0;
  color: var(--grey-800);
  font-family: var(--font-title);
  font-size: clamp(25px, calc(25px + 10 * var(--fluid)), 35px);
  font-weight: 600;
  line-height: 1.25;
}
.donate-form__title--small { font-size: clamp(22px, calc(22px + 8 * var(--fluid)), 30px); }

.amounts { display: flex; flex-wrap: wrap; justify-content: center; gap: clamp(10px, calc(10px + 10 * var(--fluid)), 20px); }
.amount {
  position: relative;
  padding: clamp(10px, calc(10px + 5 * var(--fluid)), 15px) clamp(22px, calc(22px + 18 * var(--fluid)), 40px);
  border-radius: 10px;
  background: var(--grey-100);
  color: var(--grey-800);
  font-size: clamp(19px, calc(19px + 6 * var(--fluid)), 25px);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background-color 0.2s, color 0.2s, transform 0.15s;
}
.amount:hover { background: #ebebeb; }
.amount:active { transform: scale(0.97); }
.amount input { position: absolute; opacity: 0; pointer-events: none; }
.amount:has(input:checked) { background: var(--red-strong); color: var(--white); }
.amount:has(input:focus-visible) { outline: 3px solid var(--red-strong); outline-offset: 3px; }

.other-amount {
  position: relative;
  display: flex;
  align-items: center;
  height: clamp(50px, calc(50px + 20 * var(--fluid)), 70px);
  margin-top: 40px;
  border-radius: 10px;
  background: var(--grey-100);
  font-size: clamp(20px, calc(20px + 5 * var(--fluid)), 25px);
}
.other-amount__symbol { padding-left: 20px; color: var(--grey-600); }
.other-amount input {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0 20px 0 8px;
  border: 0;
  border-radius: 10px;
  background: none;
  color: var(--grey-800);
}
.other-amount input:focus-visible { outline: none; }
.other-amount:focus-within { outline: 3px solid var(--red-strong); outline-offset: 2px; }
.other-amount.is-active { box-shadow: inset 0 0 0 2px var(--red-strong); }
.donate-form .field-error { margin-top: 8px; }

.currency { display: flex; align-items: center; justify-content: center; gap: 10px; margin-top: 16px; color: var(--grey-600); font-size: 15px; }
.currency select {
  padding: 6px 30px 6px 12px;
  border: 1px solid var(--grey-300);
  border-radius: 8px;
  background: var(--white) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23616161' d='M7 10l5 5 5-5z'/%3E%3C/svg%3E") right 6px center / 20px no-repeat;
  appearance: none;
}

.pay-button {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: 100%;
  max-width: 400px;
  height: 60px;
  margin-top: clamp(30px, calc(30px + 30 * var(--fluid)), 60px);
  border: 0;
  border-radius: 10px;
  background: var(--blue);
  color: var(--white);
  font-family: var(--font-body);
  font-size: clamp(18px, calc(18px + 6 * var(--fluid)), 24px);
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.2);
  transition: background-color 0.2s;
}
.pay-button:hover { background: var(--blue-dark); }
.pay-button img { width: clamp(35px, calc(35px + 15 * var(--fluid)), 50px); }
.pay-button[aria-busy='true'] { background: var(--grey-300); color: var(--blue); }
.donate-form__note { margin-top: 12px; color: var(--grey-600); font-size: 14px; }

/* The jar: as it scrolls into view it shrinks from a giant over the form into
 * place (--j, 0 to 1), then an arm reaches in (--arm) and drops the heart
 * (--drop) through the opening. The geometry, in px from the stage's bottom:
 * the jar spans 30-235, the heart starts at 366 (well clear of the rim) and
 * falls 290px to land among the others. */
.jar-stage {
  --j: 1; --arm: 1; --drop: 1;
  --jar-zoom: 3.5;          /* start scale - 1; JS sets it per layout */
  --jar-shift-x: -22vw;     /* where the giant jar starts: over the form */
  --jar-shift-y: -10%;
  position: relative;
  z-index: 2;               /* in front of the form while it's big */
  height: 560px;
}
.jar {
  position: absolute;
  left: calc(50% - 100px);
  bottom: 30px;
  width: 200px;
  aspect-ratio: 2108 / 2155;
  transform:
    translate(calc((1 - var(--j)) * var(--jar-shift-x)), calc((1 - var(--j)) * var(--jar-shift-y)))
    scale(calc(1 + var(--jar-zoom) * (1 - var(--j))));
  will-change: transform;
}
.jar img { position: absolute; max-width: none; }
.jar--body { z-index: 1; }
.jar--rim { z-index: 3; pointer-events: none; }
.jar__base { inset: 0; width: 100%; }
.jar__top { left: 15.75%; top: 4px; width: 68.5%; }
.jar__top-top { left: 15.75%; top: 0; width: 65%; }

.jar-stage__arm {
  position: absolute;
  z-index: 2;
  left: calc(50% - 11px);
  bottom: 366px;
  width: 500px;
  transform: translateX(calc((1 - var(--arm)) * 110vw));
  will-change: transform;
}
.jar-stage__long-arm { position: relative; z-index: 1; width: 100%; max-width: none; }
.jar-stage__heart {
  position: absolute;
  z-index: 0;
  left: -5.8%;
  top: 60.3%;
  width: 16%;
  max-width: none;
  transform: translateY(calc(var(--drop) * 290px)) scale(calc(1 - 0.3 * var(--drop)));
}
.jar-stage__thumb { position: absolute; z-index: 2; left: -1.4%; top: 60.3%; width: 26%; max-width: none; }

@media (max-width: 949px) {
  .donate-main { grid-template-columns: 1fr; padding-inline: 5vw; }
  /* Stacked: the jar starts as wide as the screen and drops in from above. */
  .jar-stage { --jar-shift-x: 0px; --jar-shift-y: -80%; }
  .jar-stage__arm { width: clamp(350px, 60vw, 500px); }
}

.manage { padding: 50px 16px; text-align: center; }
.manage__link {
  padding: 4px 8px;
  border: 0;
  background: none;
  color: var(--red-strong);
  font-family: var(--font-body);
  font-size: clamp(20px, calc(20px + 20 * var(--fluid)), 40px);
  font-weight: 500;
}
.manage__link:hover { text-decoration: underline; text-underline-offset: 6px; }
.thank-you { padding: 0 10vw; }
.thank-you img { width: 100%; }

/* ------------------------------------------------------------------ contact page */

.contact-hero { position: relative; height: 350px; overflow: hidden; background: var(--blue); }
.contact-hero .crowd-bg { opacity: 0.1; }

.contact-card {
  position: relative;
  z-index: 2;
  max-width: 1400px;
  margin: -180px clamp(8px, calc(8px + 0.08 * (100vw - 320px)), 10vw) 0;
  padding: 40px clamp(16px, 5vw, 70px) 40px;
  border: 5px solid var(--blue);
  border-radius: 20px;
  background: var(--white);
}
@media (min-width: 1560px) { .contact-card { margin-inline: auto; } }
.contact-card h1 {
  margin-bottom: 20px;
  color: var(--grey-800);
  font-family: var(--font-title);
  font-size: clamp(35px, calc(35px + 15 * var(--fluid)), 50px);
  font-weight: 600;
}
.contact-card > p {
  margin-bottom: clamp(10px, calc(10px + 10 * var(--fluid)), 20px);
  color: var(--grey-800);
  font-size: clamp(16px, calc(16px + 6 * var(--fluid)), 22px);
  text-align: justify;
}

.contact-form { display: grid; gap: clamp(10px, calc(10px + 10 * var(--fluid)), 20px); margin-top: 40px; }
.contact-form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 2vw; }
@media (max-width: 949px) { .contact-form__row { grid-template-columns: 1fr; gap: inherit; } }
.field input, .field select, .field textarea {
  width: 100%;
  padding: 15px;
  border: 3px solid transparent;
  border-radius: 10px;
  background: var(--grey-100);
  color: var(--grey-800);
  font-family: var(--font-body);
  font-size: clamp(17px, calc(17px + 8 * var(--fluid)), 25px);
}
.field textarea { resize: vertical; min-height: 10lh; }
.field select {
  appearance: none;
  background: var(--grey-100) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23424242' d='M7 10l5 5 5-5z'/%3E%3C/svg%3E") right 12px center / 30px no-repeat;
}
.field select:invalid { color: #8a8a8a; }
.field ::placeholder { color: #8a8a8a; }
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible { outline: none; border-color: var(--blue); }
.field.is-invalid input, .field.is-invalid select, .field.is-invalid textarea { border-color: var(--red); }
.field .field-error { margin-top: 6px; }
.contact-form__submit { justify-self: center; width: min(300px, 100%); min-height: clamp(50px, calc(50px + 10 * var(--fluid)), 60px); margin-top: 10px; }

/* Under the card: paper clouds hang on strings from the card's bottom edge,
 * the bank of paper-cut clouds starts just below the lowest of them (370px
 * down), then 100px of blue runs into the footer. The pigeon flies across as the sky scrolls into
 * view (--s, 0 to 1). The x positions follow the Flutter site's curves; JS
 * sets them on resize (--x), and the % values are the fallback. */
.sky {
  --s: 0;
  --bank-h: calc(100vw * 498 / 2379);
  --bank-top: 370px;
  position: relative;
  z-index: 1; /* below the card, so the strings start behind it */
  height: calc(var(--bank-top) + var(--bank-h) + 95px);
  overflow-x: clip;
  background: linear-gradient(var(--white) calc(var(--bank-top) + var(--bank-h) / 2), var(--blue) calc(var(--bank-top) + var(--bank-h) / 2));
}
.paper-cloud {
  position: absolute;
  z-index: 2;
  top: 0;
  left: var(--x);
  width: 200px;
  max-width: none;
  transform-origin: 50% 0;
}
.paper-cloud--1 { --x: 15%; z-index: 2; animation: sway 3s ease-in-out infinite; }
.paper-cloud--2 { --x: 33%; top: -8px; z-index: 4; animation: bob 3.5s ease-in-out infinite; }
.paper-cloud--3 { --x: 52%; z-index: 4; animation: sway-back 3.5s ease-in-out infinite; }
.paper-cloud--4 { --x: 72.75%; top: -1px; z-index: 2; animation: swing 3.5s ease-in-out infinite; }
@media (max-width: 710px) { .paper-cloud--3 { display: none; } }
@media (max-width: 910px) { .paper-cloud--4 { display: none; } }
@keyframes sway { 50% { transform: translateX(5%); } }
@keyframes sway-back { 57% { transform: translateX(-5%); } }
@keyframes bob { 57% { transform: translateY(2.3%) scaleY(1.05); } }
@keyframes swing { 0%, 100% { transform: rotate(1.8deg); } 57% { transform: rotate(-1.8deg); } }

.sky__pigeon {
  position: absolute;
  z-index: 3;
  top: 120px;
  left: -200px;
  width: 250px;
  max-width: none;
  transform: translateX(calc(var(--s) * 1750px)) scaleX(var(--flip, 1));
  will-change: transform;
}
.sky__clouds {
  position: absolute;
  z-index: 1;
  left: 0;
  top: var(--bank-top);
  width: 100%;
  max-width: none;
  transform: translateY(calc((1 - var(--s)) * -20%));
}

/* ------------------------------------------------------------------ legal pages */

.doc-hero {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 420px;
  padding: 150px var(--gutter) 120px;
  background: var(--blue);
  text-align: center;
}
.doc-hero__bg { position: absolute; inset: 0; overflow: hidden; opacity: 0.1; }
.doc-hero__title {
  position: relative;
  color: var(--white);
  font-family: var(--font-title);
  font-size: clamp(48px, calc(48px + 32 * var(--fluid)), 80px);
  font-weight: 700;
  line-height: 1.05;
}
.doc-hero__tear { position: absolute; z-index: 2; left: 0; bottom: 0; width: 100%; max-width: none; pointer-events: none; }

/* The document's paper reaches up under the top torn edge and down under the
 * bottom one, masked to each tear's shape, so the texture runs right up to the
 * white edge (tools/assets.py: build_tears). The edges sit on top. Tear
 * heights are their pictures' aspect ratios, in the page's width. */
.legal-doc { container-type: inline-size; }
.legal-doc .legal {
  --tear-top: calc(100cqw * 245 / 1600);
  --tear-bottom: calc(100cqw * 285 / 1600);
  z-index: 1;
  margin-block: calc(-1 * var(--tear-top)) calc(-1 * var(--tear-bottom));
  padding-top: calc(var(--tear-top) + 20px);
  padding-bottom: calc(var(--tear-bottom) + 40px);
  -webkit-mask-image: url('/img/top_torn_paper_mask.webp'), linear-gradient(#000 0 0), url('/img/bottom_torn_paper_mask.webp');
  mask-image: url('/img/top_torn_paper_mask.webp'), linear-gradient(#000 0 0), url('/img/bottom_torn_paper_mask.webp');
  -webkit-mask-position: top, 0 calc(var(--tear-top) - 2px), bottom;
  mask-position: top, 0 calc(var(--tear-top) - 2px), bottom;
  -webkit-mask-size: 100% var(--tear-top), 100% calc(100% - var(--tear-top) - var(--tear-bottom) + 4px), 100% var(--tear-bottom);
  mask-size: 100% var(--tear-top), 100% calc(100% - var(--tear-top) - var(--tear-bottom) + 4px), 100% var(--tear-bottom);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

.legal {
  position: relative;
  padding: 20px max(var(--gutter), calc((100vw - 900px) / 2)) 40px;
  background: var(--beige) url('/img/paper_texture.png') 0 0 / 300px;
  background-blend-mode: multiply;
  color: rgb(0 0 0 / 0.87);
}
.legal__meta { margin: 10px 0 40px; color: var(--grey-600); font-size: clamp(16px, calc(16px + 4 * var(--fluid)), 20px); text-align: center; }
.legal__meta:empty { display: none; }
.prose { font-size: clamp(16px, calc(16px + 3 * var(--fluid)), 19px); line-height: 1.65; }
.prose p, .prose ul, .prose ol { margin-bottom: 1em; }
.prose ul, .prose ol { padding-left: 1.4em; }
.prose li { margin-bottom: 0.35em; }
.prose a { color: var(--blue); text-underline-offset: 2px; }
.prose strong { font-weight: 600; }
.legal__intro { margin-bottom: 40px; }
.legal__toc {
  margin: 0 auto 60px;
  padding: 24px clamp(18px, 3vw, 36px);
  border-radius: 14px;
  background: rgb(255 255 255 / 0.55);
}
.legal__toc h2 {
  margin-bottom: 12px;
  color: var(--grey-800);
  font-family: var(--font-title);
  font-size: clamp(22px, calc(22px + 8 * var(--fluid)), 30px);
  font-weight: 600;
}
.legal__toc ol { columns: 2 300px; column-gap: 40px; padding-left: 1.6em; }
.legal__toc li { margin-bottom: 6px; break-inside: avoid; color: var(--grey-600); }
.legal__toc a { color: var(--grey-800); font-family: var(--font-title); font-size: 18px; font-weight: 500; text-decoration: none; }
.legal__toc a:hover { color: var(--blue); text-decoration: underline; }
.legal__section { margin-bottom: 40px; scroll-margin-top: 100px; }
.legal__section h2 {
  margin-bottom: 16px;
  color: var(--grey-800);
  font-family: var(--font-title);
  font-size: clamp(24px, calc(24px + 10 * var(--fluid)), 34px);
  font-weight: 600;
  line-height: 1.2;
}
.legal__section:target h2 { color: var(--blue); }
.legal__number { color: var(--grey-600); }
.legal__subsection h3 { margin: 24px 0 8px; color: var(--grey-700); font-size: clamp(18px, calc(18px + 4 * var(--fluid)), 22px); font-weight: 600; }
.legal__loading { color: var(--grey-600); text-align: center; }
.legal.is-updated .legal__meta::after { content: ' · updated just now'; color: var(--blue); }

.doc-foot { position: relative; background: var(--blue); padding-top: 120px; }
.doc-foot img { position: absolute; z-index: 2; top: 0; left: 0; width: 100%; max-width: none; }

/* ------------------------------------------------------------------ 404 */

.not-found { display: grid; justify-items: center; gap: 18px; padding: 170px var(--gutter) 100px; text-align: center; }
.not-found h1 { font-family: var(--font-title); font-size: clamp(32px, 5vw, 50px); font-weight: 700; }
.not-found p { color: var(--grey-600); font-size: 20px; }

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

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