/* ==========================================================================
   Poppins, self hosted.

   Served from this domain rather than fonts.googleapis.com so no visitor IP
   is sent to Google. A German court (LG Munchen I, 2022) held that embedding
   Google Fonts without consent breaches the GDPR, and self hosting removes
   the question entirely. It is also one fewer network round trip.
   ========================================================================== */

@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('assets/fonts/poppins-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('assets/fonts/poppins-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('assets/fonts/poppins-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('assets/fonts/poppins-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('assets/fonts/poppins-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('assets/fonts/poppins-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ==========================================================================
   Pink Paradox App — Landing page
   --------------------------------------------------------------------------
   Design tokens MEASURED from https://www.pinkparadox.band (not invented):
     ink        #231A20   body text colour
     pink       #F82588   accent / buttons
     surfaces   #FFFFFF and #000000, alternating full-bleed sections
     type       Poppins, weight 500 headings
     buttons    border-radius 300px (full pill)

   Skills applied:
     landing-page-design  — structure, Part B visual system, tagline reveal
     ui-ux-pro-max        — Dark Mode (OLED) style, Righteous/Poppins pairing,
                            Feature-Rich Showcase pattern, Complex motion tier
     scrollcraft / animate— IntersectionObserver reveals, no scroll listeners
     high-end-visual-design, interfaces-that-feel — states and polish
   ========================================================================== */

:root {
  /* --- Brand, measured from the live site --- */
  --ink: #231A20;
  --pink: #F82588;              /* brand accent, as measured on the site */
  --pink-ink: #DF217A;          /* same hue, darkened to 4.53:1 with white text */
  --white: #FFFFFF;

  --ink-50: rgba(35, 26, 32, 0.5);
  --ink-28: rgba(35, 26, 32, 0.28);
  --ink-12: rgba(35, 26, 32, 0.12);
  --pink-12: rgba(248, 37, 136, 0.24);
  --pink-24: rgba(248, 37, 136, 0.24);

  /* --- Dark surfaces (landing-page-design B4 approved list) --- */
  --d-000: #000000;
  --d-200: #181818;
  --d-300: #1F1F1F;
  --d-400: #272727;

  --on-dark: rgba(255, 255, 255, 0.66);
  --on-dark-dim: rgba(255, 255, 255, 0.52);
  --hairline: rgba(255, 255, 255, 0.10);

  /* --- Spacing scale (B2). Nothing between, nothing outside. --- */
  --s-25: 2px;   --s-50: 4px;   --s-75: 8px;   --s-100: 12px;
  --s-200: 16px; --s-300: 24px; --s-400: 32px; --s-500: 40px;
  --s-600: 48px; --s-700: 64px; --s-800: 80px; --s-900: 96px;

  /* --- Radius --- */
  --r-lg: 8px; --r-xl: 12px; --r-2xl: 16px; --r-3xl: 24px;
  --r-pill: 300px;                    /* measured from the site's buttons */

  /* --- Motion (B7 fluid dynamics + pro-max Complex tier) --- */
  --ease: cubic-bezier(0.32, 0.72, 0, 1);
  --dur: 700ms;
  --dur-slow: 900ms;
}

/* ==========================================================================
   Base
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  /* Chrome paints the scrollbar channel from the canvas background, which it
     takes from <html> when <html> has one, and from <body> otherwise. Without
     this the body's white ran up the side of every dark section as a white
     stripe beside the bar. */
  background: var(--d-000);
}

body {
  margin: 0;
  background: var(--white);
  color: var(--ink);
  font-family: Poppins, system-ui, sans-serif;
  font-size: 16px;
  line-height: 24px;
  overflow-x: hidden;
  text-wrap: pretty;
  -webkit-font-smoothing: antialiased;
}

img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
p { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }
h1, h2, h3 { margin: 0; font-weight: 500; text-wrap: balance; }
button, a[role="button"] { cursor: pointer; }

/* Visible focus ring — accessibility requirement, never removed (B9). */
:focus-visible {
  outline: 3px solid var(--pink);
  outline-offset: 3px;
  border-radius: var(--r-lg);
}

.skip {
  position: absolute;
  left: var(--s-200);
  top: -100px;
  z-index: 200;
  padding: var(--s-100) var(--s-300);
  border-radius: var(--r-pill);
  background: var(--pink-ink);
  color: var(--white);
  font-size: 14px;
  line-height: 20px;
  font-weight: 600;
  transition: top var(--dur) var(--ease);
}
.skip:focus { top: var(--s-200); }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================================
   Layout primitives
   ========================================================================== */

.wrap { width: min(1180px, 100% - 48px); margin-inline: auto; }

.section { position: relative; padding-block: var(--s-900); }
@media (max-width: 700px) { .section { padding-block: var(--s-700); } }

.section--dark { background: var(--d-000); color: var(--white); }
.section--ink  { background: var(--d-200); color: var(--white); }

.eyebrow {
  margin-bottom: var(--s-200);
  /* Darker hue so small uppercase text clears 4.5:1 on the white sections. */
  color: var(--pink-ink);
  font-size: 12px;
  line-height: 16px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

/* On black the bright brand pink already clears AA, so use it there. */
.section--dark .eyebrow,
.section--ink .eyebrow { color: var(--pink); }

.h2 { font-size: 48px; line-height: 1; letter-spacing: -0.02em; }
@media (max-width: 700px) { .h2 { font-size: 36px; line-height: 40px; } }

.lede {
  max-width: 680px;
  margin-top: var(--s-300);
  color: var(--ink-50);
  font-size: 18px;
  line-height: 28px;
}
.section--dark .lede,
.section--ink .lede { color: var(--on-dark); }

/* ==========================================================================
   Buttons — pill shape and pink fill measured from the live site
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-75);
  min-height: 44px;                    /* pro-max: 44px touch target */
  padding: var(--s-100) var(--s-400);
  border: 0;
  border-radius: var(--r-pill);
  font-family: inherit;
  font-size: 16px;
  line-height: 24px;
  font-weight: 600;
  letter-spacing: 0.01em;
  will-change: transform;
  transition:
    transform var(--dur) var(--ease),
    background-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease),
    color var(--dur) var(--ease);
}

.btn--primary {
  background: var(--pink-ink);
  color: var(--white);
  box-shadow: 0 6px 20px rgba(248, 37, 136, 0.24);
}
.btn--primary:hover {
  transform: translateY(-2px) scale(1.02);
  box-shadow: 0 10px 28px rgba(248, 37, 136, 0.24);
}
.btn--primary:active { transform: scale(0.98); }

.btn--ghost {
  background: transparent;
  color: var(--white);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.28);
}
.btn--ghost:hover {
  transform: translateY(-2px);
  background: rgba(255, 255, 255, 0.08);
}
.btn--ghost:active { transform: scale(0.98); }

.btn--dark {
  background: var(--ink);
  color: var(--white);
}
.btn--dark:hover { transform: translateY(-2px); background: #000; }
.btn--dark:active { transform: scale(0.98); }

.btn--sm {
  min-height: 44px;
  padding: var(--s-75) var(--s-300);
  font-size: 14px;
  line-height: 20px;
}

/* ==========================================================================
   Fluid island nav (B7)
   ========================================================================== */

.nav {
  position: fixed;
  inset-inline: 0;
  top: var(--s-300);
  z-index: 100;
  display: flex;
  justify-content: center;
  pointer-events: none;
}

.nav__pill {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: var(--s-300);
  width: max-content;
  max-width: calc(100vw - 32px);
  padding: var(--s-75) var(--s-75) var(--s-75) var(--s-300);
  border-radius: var(--r-pill);
  background: rgba(0, 0, 0, 0.58);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.12),
    0 12px 40px rgba(0, 0, 0, 0.28);
  transition: background-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.nav__brand {
  display: flex;
  min-height: 44px;
  align-items: center;
  gap: var(--s-75);
  color: var(--white);
  font-size: 14px;
  line-height: 20px;
  font-weight: 600;
}
.nav__brand img { width: 24px; height: 24px; border-radius: var(--r-lg); }

.nav__links { display: flex; gap: var(--s-300); }
.nav__links a {
  display: flex;
  min-height: 44px;
  align-items: center;
  color: rgba(255, 255, 255, 0.72);
  font-size: 14px;
  line-height: 20px;
  font-weight: 500;
  transition: color var(--dur) var(--ease);
}
.nav__links a:hover,
.nav__links a[aria-current="page"] { color: var(--white); }

.nav__burger {
  position: relative;
  display: none;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
}
.nav__burger span {
  position: absolute;
  left: 12px;
  width: 20px;
  height: 2px;
  border-radius: 2px;
  background: var(--white);
  transition: transform var(--dur) var(--ease);
}
.nav__burger span:nth-child(1) { top: 18px; }
.nav__burger span:nth-child(2) { top: 26px; }
/* Lines morph into an X — they never simply disappear (B7). */
body.menu-open .nav__burger span:nth-child(1) { transform: translateY(4px) rotate(45deg); }
body.menu-open .nav__burger span:nth-child(2) { transform: translateY(-4px) rotate(-45deg); }

.menu {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-300);
  background: rgba(0, 0, 0, 0.80);
  backdrop-filter: blur(48px);
  -webkit-backdrop-filter: blur(48px);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur) var(--ease), visibility var(--dur) var(--ease);
}
body.menu-open .menu { opacity: 1; visibility: visible; }

.menu a {
  color: var(--white);
  font-size: 36px;
  line-height: 40px;
  font-weight: 500;
  opacity: 0;
  transform: translateY(48px);
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
}
/* The call to action rises with the links, so it is styled alongside them
   rather than inheriting the link rule it no longer matches. */
.menu__cta {
  margin-top: var(--s-200);
  padding: 16px 32px;
  font-size: 18px;
  line-height: 24px;
  opacity: 0;
  transform: translateY(48px);
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
}

body.menu-open .menu a,
body.menu-open .menu__cta { opacity: 1; transform: translateY(0); }
body.menu-open .menu > :nth-child(1) { transition-delay: 100ms; }
body.menu-open .menu > :nth-child(2) { transition-delay: 150ms; }
body.menu-open .menu > :nth-child(3) { transition-delay: 200ms; }
body.menu-open .menu > :nth-child(4) { transition-delay: 250ms; }
body.menu-open .menu > :nth-child(5) { transition-delay: 300ms; }
body.menu-open .menu > :nth-child(6) { transition-delay: 350ms; }

@media (max-width: 900px) {
  .nav__links { display: none; }
  .nav__burger { display: block; }
  .nav__pill > .btn { display: none; }
}

/* ==========================================================================
   Hero — WebGL canvas behind, 3D phone in front
   ========================================================================== */

.hero {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 100svh;
  padding-block: var(--s-900) var(--s-900);   /* symmetric, so the copy sits centred */
  background: var(--d-000);
  color: var(--white);
  overflow: hidden;
}

#hero-canvas {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: block;
  width: 100%;
  height: 100%;
}

/* Decorative layer only — never parallaxes text (pro-max parallax rule). */
.hero__vignette {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(ellipse 90% 70% at 50% 45%,
              transparent 28%, rgba(0, 0, 0, 0.86) 100%);
}

.hero__inner {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: var(--s-700);
  align-items: center;
}

.hero__copy { max-width: 680px; }        /* B5: hero copy capped at 680px */

.hero h1 {
  font-size: 64px;
  line-height: 1.05;
  font-weight: 600;                    /* semibold, overrides the h1-h3 base of 500 */
  letter-spacing: -0.03em;
  color: var(--white);
}

.hero__sub {
  max-width: 680px;
  margin-top: var(--s-300);
  color: var(--on-dark);
  font-size: 18px;
  line-height: 28px;
}

.hero__cta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-200);
  margin-top: var(--s-500);
}

.hero__proof {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-300);
  margin-top: var(--s-400);
  color: var(--on-dark-dim);
  font-size: 14px;
  line-height: 20px;
}
.hero__proof strong { color: var(--white); font-weight: 600; }
.hero__proof span { display: inline-flex; align-items: center; gap: var(--s-75); }

.dot { width: 4px; height: 4px; border-radius: 50%; background: var(--pink); }

@media (max-width: 960px) {
  .hero__inner { grid-template-columns: 1fr; gap: var(--s-600); text-align: center; }
  .hero__copy { margin-inline: auto; }
  .hero__cta, .hero__proof { justify-content: center; }
  .hero h1 { font-size: 48px; }
}
@media (max-width: 480px) {
  .hero h1 { font-size: 36px; line-height: 40px; }
}

/* --- The 3D phone --- */

.phone-stage { display: flex; justify-content: center; perspective: 1400px; }

.phone {
  position: relative;
  --bezel: 10px;                       /* the frame around the display */
  --status: 26px;                      /* the Android status bar strip */

  width: min(300px, 72vw);
  /* Derived from the screenshot so the whole capture fits, including the
     app's bottom tab bar. 750x1624 is the screenshot's own size; if the
     captures ever change, update those two numbers.
       screen width  = width - 2 * bezel
       screen height = screen width / shot + status
       phone height  = screen height + 2 * bezel */
  height: calc(
    (min(300px, 72vw) - 2 * var(--bezel)) * 1624 / 750
    + var(--status) + 2 * var(--bezel)
  );
  padding: var(--bezel);               /* the bezel itself */
  border-radius: 42px;
  background: linear-gradient(150deg, #3A3A3E 0%, #131316 38%, #232327 70%, #0C0C0E 100%);
  transform: rotateY(-16deg) rotateX(6deg);
  transform-style: preserve-3d;
  will-change: transform;
  box-shadow:
    /* the machined edge of the frame */
    inset 0 0 0 1px rgba(255, 255, 255, 0.22),
    inset 0 0 0 3px rgba(0, 0, 0, 0.85),
    0 48px 96px rgba(0, 0, 0, 0.72),
    0 0 80px var(--pink-24);
  transition: transform var(--dur-slow) var(--ease);
}

/* The display. Slightly tighter radius than the body, per the nested-radius
   rule: inner = outer minus the gap. */
.phone__screen {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 32px;
  overflow: hidden;
  background: var(--white);
}
.phone__screen img {
  position: absolute;
  inset: var(--status) 0 0 0;          /* clears the status bar only */
  z-index: 1;                          /* above the screen, below the overlays */
  /* A replaced element needs explicit width and height to fill its inset box;
     with them unset it falls back to its intrinsic 750x1624 and overflows. */
  width: 100%;
  height: calc(100% - var(--status));
  object-fit: cover;
  object-position: top;
}

/* Punch-hole selfie camera, centred at the top of the display. */
.phone__camera {
  position: absolute;
  z-index: 3;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #05050A;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.14),
    0 0 4px rgba(0, 0, 0, 0.6);
}

/* Side buttons on the right edge, sitting behind the body in 3D. */
.phone__btn {
  position: absolute;
  right: -3px;
  width: 3px;
  border-radius: 0 2px 2px 0;
  background: linear-gradient(180deg, #35353A, #131316);
}
.phone__btn--power { top: 26%; height: 9%; }
.phone__btn--vol   { top: 40%; height: 15%; }

/* --- Android system UI, drawn over the screenshot --- */

.phone__status {
  position: absolute;
  inset: 0 0 auto 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 26px;
  padding: 0 14px 0 16px;
  color: var(--ink);
  /* Matches the app's white header so the bar reads as part of the screen. */
  background: #FFFFFF;
  font-size: 11px;
  line-height: 1;
  font-weight: 600;
  letter-spacing: 0.01em;
}
.phone__time { font-variant-numeric: tabular-nums; }
.phone__icons { display: flex; align-items: center; gap: 4px; }
.phone__icons svg { display: block; }

/* Screen reflection. Real phone glass shows a hard specular streak from the
   key light plus a broad, soft sheen across the rest of the panel, so this is
   two layers rather than one flat wash. It sits above the system bars and the
   screenshot, and follows the phone's rounded screen corners.

   --gx / --gy are written by the tilt loop in main.js, so the highlight
   sweeps as the phone turns instead of staying painted in place. */
.phone__glare {
  --gx: 50%;
  --gy: 50%;

  position: absolute;
  inset: 10px;                         /* the display area, inside the bezel */
  z-index: 4;
  pointer-events: none;
  border-radius: 32px;
  mix-blend-mode: screen;
  background:
    /* the hard diagonal streak, anchored to the moving highlight point */
    linear-gradient(112deg,
      transparent calc(var(--gx) - 38%),
      rgba(255, 255, 255, 0.30) calc(var(--gx) - 26%),
      rgba(255, 255, 255, 0.10) calc(var(--gx) - 19%),
      transparent calc(var(--gx) - 10%)),
    /* a second, thinner streak just behind it, as real glass gives */
    linear-gradient(112deg,
      transparent calc(var(--gx) - 6%),
      rgba(255, 255, 255, 0.12) var(--gx),
      transparent calc(var(--gx) + 6%)),
    /* broad sheen, tinted by the hero's pink key, tracking the same point */
    radial-gradient(120% 80% at var(--gx) calc(var(--gy) - 60%),
      rgba(255, 255, 255, 0.20) 0%,
      rgba(248, 37, 136, 0.24) 38%,
      transparent 70%);
}

/* A faint dark vignette on the glass keeps the panel from looking flat and
   sells the curve at the edges of the screen. */
.phone__screen::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;                          /* over the image, under the system bars */
  pointer-events: none;
  border-radius: inherit;
  background: radial-gradient(130% 100% at 50% 50%,
    transparent 68%, rgba(0, 0, 0, 0.16) 100%);
}

/* ==========================================================================
   Scroll reveal (B7) — driven by IntersectionObserver, never a scroll listener
   ========================================================================== */

.reveal {
  opacity: 0;
  transform: translateY(64px);
  filter: blur(12px);
  transition:
    opacity var(--dur-slow) var(--ease),
    transform var(--dur-slow) var(--ease),
    filter var(--dur-slow) var(--ease);
}
.reveal.is-in { opacity: 1; transform: translateY(0); filter: blur(0); }

.reveal[data-delay="1"] { transition-delay: 100ms; }
.reveal[data-delay="2"] { transition-delay: 200ms; }
.reveal[data-delay="3"] { transition-delay: 300ms; }
.reveal[data-delay="4"] { transition-delay: 400ms; }
.reveal[data-delay="5"] { transition-delay: 500ms; }

/* ==========================================================================
   Marquee
   ========================================================================== */

.marquee {
  display: flex;
  padding-block: var(--s-200);
  background: var(--pink-ink);
  color: var(--white);
  overflow: hidden;
  user-select: none;
}
.marquee__track {
  display: flex;
  flex-shrink: 0;
  gap: var(--s-500);
  padding-right: var(--s-500);
  white-space: nowrap;
  font-size: 14px;
  line-height: 20px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  animation: marquee 50s linear infinite;
}
@keyframes marquee { to { transform: translateX(-100%); } }

/* ==========================================================================
   Feature cards — pattern: Feature-Rich Showcase
   ========================================================================== */

.grid-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-300);
  margin-top: var(--s-600);
}
@media (max-width: 960px) { .grid-3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) { .grid-3 { grid-template-columns: 1fr; } }

.card {
  padding: var(--s-400);
  border-radius: var(--r-3xl);
  background: var(--d-200);
  box-shadow: inset 0 0 0 1px var(--hairline);
  transition:
    transform var(--dur) var(--ease),
    background-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}
.card:hover {
  transform: translateY(-6px);
  background: var(--d-300);
  box-shadow: inset 0 0 0 1px var(--pink-24), 0 24px 56px rgba(0, 0, 0, 0.5);
}

/* Nested radius: outer 24px minus 32px padding is below the 32px gap rule,
   so the icon tile keeps its own 16px step (B3). */
.card__icon {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  margin-bottom: var(--s-300);
  border-radius: var(--r-2xl);
  background: var(--pink-12);
  color: var(--pink);
}
.card h3 { font-size: 20px; line-height: 28px; font-weight: 600; }
.card p {
  margin-top: var(--s-75);
  color: rgba(255, 255, 255, 0.58);
  font-size: 14px;
  line-height: 20px;
}

/* Centred call to action sitting under a section's card grid. */
.section-cta {
  display: flex;
  justify-content: center;
  margin-top: var(--s-600);
}

/* A short white break between two dark sections, so the page does not run as
   one long black block. Shallower than a full section: it is a beat, not a
   chapter. The copy itself uses the .tagline styling, so both white sections
   read the same. */
.section--tight { padding-block: var(--s-700); }
@media (max-width: 700px) { .section--tight { padding-block: var(--s-600); } }

/* ==========================================================================
   Tagline reveal (B11) — words light up one at a time, in reading order
   ========================================================================== */

.tagline { max-width: 900px; margin-inline: auto; text-align: center; }
.tagline p {
  font-size: 48px;
  line-height: 1.12;
  font-weight: 500;
  letter-spacing: -0.02em;
}
.tagline .word {
  color: var(--ink-28);
  transition: color var(--dur) var(--ease);
}
.tagline .word.lit { color: var(--ink); }
.tagline .word.accent.lit { color: var(--pink); }

@media (max-width: 780px) { .tagline p { font-size: 30px; line-height: 36px; } }

/* ==========================================================================
   How it works
   ========================================================================== */

.steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-500);
  margin-top: var(--s-600);
  counter-reset: step;
}
@media (max-width: 780px) { .steps { grid-template-columns: 1fr; } }

.step { counter-increment: step; }
.step__n {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-bottom: var(--s-300);
  border-radius: var(--r-pill);
  background: var(--pink-ink);
  color: var(--white);
  font-size: 16px;
  font-weight: 600;
}
.step__n::before { content: counter(step); }
.step h3 { font-size: 20px; line-height: 28px; font-weight: 600; }
.step p { margin-top: var(--s-75); color: var(--ink-50); }

/* ==========================================================================
   Tiers
   ========================================================================== */

.tiers {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-300);
  margin-top: var(--s-600);
}
@media (max-width: 780px) { .tiers { grid-template-columns: 1fr; } }

.tier {
  padding: var(--s-500);
  border-radius: var(--r-3xl);
  background: var(--white);
  color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink-12);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.tier:hover {
  transform: translateY(-6px);
  box-shadow: inset 0 0 0 1px var(--pink);
}

.tier--roach {
  background: var(--d-000);
  color: var(--white);
  box-shadow: inset 0 0 0 1px var(--pink-24);
}
.tier--roach:hover {
  box-shadow: inset 0 0 0 1px var(--pink);
}

.tier h3 { font-size: 24px; line-height: 32px; font-weight: 600; }
.tier__note { margin-top: var(--s-50); color: var(--ink-50); font-size: 14px; line-height: 20px; }
.tier--roach .tier__note { color: rgba(255, 255, 255, 0.55); }

.tier ul { display: grid; gap: var(--s-100); margin-top: var(--s-400); }
.tier li {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: var(--s-100);
  align-items: start;
}
.tier li svg { margin-top: 3px; color: var(--pink); }
.tier .btn { width: 100%; margin-top: var(--s-400); }

.badge {
  display: inline-block;
  margin-bottom: var(--s-200);
  padding: var(--s-25) var(--s-100);
  border-radius: var(--r-pill);
  background: var(--pink-ink);
  color: var(--white);
  font-size: 12px;
  line-height: 16px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* ==========================================================================
   Band
   ========================================================================== */

.band {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--s-200);
  margin-top: var(--s-600);
}
@media (max-width: 900px) { .band { grid-template-columns: repeat(2, 1fr); } }

.member {
  margin: 0;
  border-radius: var(--r-2xl);
  overflow: hidden;
  background: var(--d-200);
  box-shadow: inset 0 0 0 1px var(--hairline);
  transition: transform var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.member:hover { transform: translateY(-6px); background: var(--d-300); }

.member__crop {
  position: relative;
  overflow: hidden;                    /* contains any per-member zoom */
  aspect-ratio: 2 / 3;                 /* portrait crop, owned by the box */
}

.member img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The sources are taller than 2:3 and the faces sit in the upper third, so
     pull the crop window up: dead centre would cut them off at the chin. */
  object-position: 50% 18%;
  display: block;
  filter: grayscale(0.2) contrast(1.05);
  transition: filter var(--dur) var(--ease);
}
.member:hover img { filter: grayscale(0) contrast(1.05); }

/* Alessia is shot further from the camera than the rest, so she reads as
   distant in the row. Wrapping the image in its own clipping box lets the
   zoom happen inside the card, without transform pushing the caption out. */
.member--alessia .member__crop { overflow: hidden; }
.member--alessia .member__crop img {
  transform: scale(1.30);
  transform-origin: 50% 16%;
}

.member figcaption { padding: var(--s-200) var(--s-300) var(--s-300); }
.member strong { display: block; font-size: 16px; line-height: 24px; font-weight: 600; }
.member span { color: rgba(255, 255, 255, 0.55); font-size: 14px; line-height: 20px; }

/* ==========================================================================
   FAQ
   ========================================================================== */

.faq { margin-top: var(--s-600); }

.faq details {
  margin-bottom: var(--s-100);
  padding: var(--s-300);
  border-radius: var(--r-2xl);
  box-shadow: inset 0 0 0 1px var(--ink-12);
  transition: box-shadow var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.faq details[open] {
  background: rgba(248, 37, 136, 0.24);
  box-shadow: inset 0 0 0 1px var(--pink-24);
}

.faq summary {
  display: flex;
  min-height: 44px;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-200);
  list-style: none;
  font-size: 18px;
  line-height: 28px;
  font-weight: 600;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "";
  flex: none;
  width: 12px;
  height: 12px;
  border-right: 2px solid var(--pink);
  border-bottom: 2px solid var(--pink);
  transform: rotate(45deg);
  transition: transform var(--dur) var(--ease);
}
.faq details[open] summary::after { transform: rotate(-135deg); }
.faq p {
  max-width: 78ch;                     /* keeps answers readable at full width */
  margin-top: var(--s-200);
  color: var(--ink-50);
}

/* ==========================================================================
   Final CTA and footer
   ========================================================================== */

.final { text-align: center; }
.final .h2 { max-width: 680px; margin-inline: auto; }
.final .lede { margin-inline: auto; }
.final__cta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--s-200);
  margin-top: var(--s-500);
}

.footer {
  padding-block: var(--s-600);
  background: var(--d-000);
  color: rgba(255, 255, 255, 0.55);
  font-size: 14px;
  line-height: 20px;
}
.footer__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-300);
}
.footer nav { display: flex; flex-wrap: wrap; gap: var(--s-300); }
.footer a {
  display: inline-flex;
  min-height: 44px;
  align-items: center;
  transition: color var(--dur) var(--ease);
}
.footer a:hover { color: var(--pink); }

/* ==========================================================================
   Reduced motion — render the readable final state immediately
   ========================================================================== */

@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;
  }

  .reveal { opacity: 1; transform: none; filter: none; }
  .tagline .word { color: var(--ink); }
  .marquee__track { animation: none; }
}

/* ==========================================================================
   Apply dialog
   ========================================================================== */

.modal {
  width: min(520px, calc(100vw - 32px));
  padding: 0;
  border: 0;
  border-radius: var(--r-3xl);
  background: var(--d-200);
  color: var(--white);
  box-shadow:
    inset 0 0 0 1px var(--hairline),
    0 48px 96px rgba(0, 0, 0, 0.72);
}
.modal::backdrop {
  background: rgba(0, 0, 0, 0.72);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.modal__panel { position: relative; padding: var(--s-600); }
@media (max-width: 520px) { .modal__panel { padding: var(--s-400); } }

.modal__close {
  position: absolute;
  top: var(--s-200);
  right: var(--s-200);
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--on-dark);
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.modal__close:hover { background: rgba(255, 255, 255, 0.08); color: var(--white); }

.modal__title {
  margin: 0;
  font-size: 30px;
  line-height: 36px;
  font-weight: 600;
  letter-spacing: -0.02em;
}
.modal__lede {
  margin-top: var(--s-200);
  color: var(--on-dark);
  font-size: 16px;
  line-height: 24px;
}

/* --- form controls --- */

.field { display: block; margin-top: var(--s-400); }
.field__label {
  display: block;
  margin-bottom: var(--s-75);
  font-size: 14px;
  line-height: 20px;
  font-weight: 600;
}
.field__input {
  width: 100%;
  min-height: 48px;
  padding: var(--s-100) var(--s-200);
  border: 0;
  border-radius: var(--r-xl);
  background: var(--d-400);
  color: var(--white);
  font: inherit;
  box-shadow: inset 0 0 0 1px var(--hairline);
  transition: box-shadow var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.field__input::placeholder { color: rgba(255, 255, 255, 0.38); }
.field__input:hover { background: #2E2E2E; }
.field__input:focus {
  outline: 0;
  box-shadow: inset 0 0 0 2px var(--pink);
}
.field__input[aria-invalid="true"] { box-shadow: inset 0 0 0 2px #FF6B6B; }

.field__help {
  display: block;
  margin-top: var(--s-75);
  color: var(--on-dark-dim);
  font-size: 13px;
  line-height: 18px;
}
.field__error {
  display: block;
  margin-top: var(--s-75);
  color: #FF8A8A;
  font-size: 13px;
  line-height: 18px;
  font-weight: 500;
}

.check {
  display: grid;
  grid-template-columns: 22px 1fr;
  gap: var(--s-100);
  align-items: start;
  margin-top: var(--s-300);
  font-size: 14px;
  line-height: 20px;
  color: var(--on-dark);
  cursor: pointer;
}

/* Custom control. `accent-color` only tints the OS default, which still looks
   like a system widget; drawing it here keeps it on brand in every browser.
   The input stays in the DOM and focusable, just visually replaced. */
.check input {
  appearance: none;
  -webkit-appearance: none;
  width: 22px;
  height: 22px;
  margin: 0;
  border-radius: var(--r-lg);
  background: var(--d-400);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.22);
  cursor: pointer;
  display: grid;
  place-content: center;
  transition:
    background-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease),
    transform var(--dur) var(--ease);
}

/* The tick, drawn with a rotated L so there is no image to load. It scales in
   from nothing, so checking the box has a bit of physicality. */
.check input::before {
  content: "";
  width: 10px;
  height: 6px;
  border-left: 2px solid var(--white);
  border-bottom: 2px solid var(--white);
  border-radius: 1px;
  transform: rotate(-45deg) scale(0);
  transform-origin: center;
  transition: transform var(--dur) var(--ease);
  margin-top: -2px;
}

.check input:hover { background: #323236; }

.check input:checked {
  background: var(--pink);
  box-shadow: inset 0 0 0 1px var(--pink), 0 2px 8px rgba(248, 37, 136, 0.24);
}
.check input:checked::before { transform: rotate(-45deg) scale(1); }

.check input:active { transform: scale(0.92); }

/* Keyboard focus has to stay obvious once the native control is gone. */
.check input:focus-visible {
  outline: 3px solid var(--pink);
  outline-offset: 3px;
}

.modal__submit { width: 100%; margin-top: var(--s-400); }
.modal__submit[disabled] { opacity: 0.6; cursor: progress; }

.modal__fineprint {
  margin-top: var(--s-200);
  color: var(--on-dark-dim);
  font-size: 13px;
  line-height: 18px;
  text-align: center;
}

.modal__tick {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  margin-bottom: var(--s-300);
  border-radius: var(--r-pill);
  background: var(--pink-12);
  color: var(--pink);
}

/* ==========================================================================
   Policy dialogs
   ========================================================================== */

/* Wider and scrollable: these are documents, not a short form. */
.modal--doc {
  width: min(760px, calc(100vw - 32px));
  max-height: min(86vh, 900px);
}
/* A scrollbar is painted in its scroller's padding box, which border-radius
   does not clip, so the rail used to run straight through the dialog's rounded
   corners.

   The panel clips instead, and the scroller sits flush against its inner edge:
   the panel drops its own horizontal padding and hands it to the scrolling
   .doc, so the bar rides the edge of the card while the text stays inset. The
   panel's overflow:hidden then trims the rail to the rounded shape. */
/* Every dialog is capped so it can never outgrow the viewport. */
.modal { max-height: min(86vh, 900px); }

/* Two shapes of dialog, so two ways of scrolling.

   In the policy dialogs the panel is a wrapper around a .doc, so the panel
   clips and .doc scrolls. In the apply dialog the <form> IS the panel, with no
   inner wrapper, so that panel has to scroll itself.

   Either way the scroller drops its right padding and hands it to the content,
   which puts the bar against the card's edge with the text still inset. */
/* The panel only clips. ALL padding moves inside the scroller, so the first and
   last lines scroll fully into view instead of hiding behind a fixed band at
   the top and bottom of the card. */
.modal--doc .modal__panel {
  max-height: inherit;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: inherit;
  padding: 0;
}

.modal--doc .doc {
  flex: 1 1 auto;
  min-height: 0;                       /* lets a flex child actually shrink */
  overflow-y: auto;
  overscroll-behavior: contain;        /* stops the page behind scrolling too */
  padding: var(--s-600);
}

/* The apply dialog: the form is the panel, so it scrolls itself. */
/* The apply dialog. Its <form> IS the panel, with no wrapper between the panel
   and the content, so it cannot clip and scroll the way the policy dialogs do.

   Matching them exactly: the panel drops its own padding and becomes a
   clipping flex column, and each step inside is the scroller carrying that
   padding. The bar then sits against the card edge and runs the full height of
   the card, with the content inset, identical to privacy and terms. */
.modal:not(.modal--doc) .modal__panel {
  max-height: inherit;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: inherit;
  padding: 0;
}

.modal:not(.modal--doc) .modal__step {
  flex: 1 1 auto;
  min-height: 0;                       /* lets a flex child actually shrink */
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--s-600);
}

@media (max-width: 520px) {
  .modal--doc .doc,
  .modal:not(.modal--doc) .modal__step { padding: var(--s-400); }
}

/* The close button sits above the scrolling area rather than inside it. */
.modal:not(.modal--doc) .modal__close {
  z-index: 2;
}


.doc__meta {
  margin-top: var(--s-75);
  color: var(--on-dark-dim);
  font-size: 13px;
  line-height: 18px;
}
.doc h3 {
  margin-top: var(--s-400);
  font-size: 18px;
  line-height: 26px;
  font-weight: 600;
  color: var(--white);
}
.doc p,
.doc li {
  margin-top: var(--s-100);
  color: var(--on-dark);
  font-size: 15px;
  line-height: 24px;
}
.doc ul {
  margin-top: var(--s-100);
  padding-left: var(--s-300);
  list-style: disc;
}
.doc li { margin-top: var(--s-50); }
.doc a { color: var(--pink); text-decoration: underline; }
.doc a:hover { color: var(--white); }

/* Footer buttons that need to look exactly like the links beside them. */
.footer__link {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  display: inline-flex;
  min-height: 44px;
  align-items: center;
  transition: color var(--dur) var(--ease);
}
.footer__link:hover { color: var(--pink); }

/* ==========================================================================
   Scrollbars

   Deliberately WebKit only. Setting `scrollbar-width` puts Chrome on its
   NATIVE scrollbar, which ignores every ::-webkit- rule, arrows included, so
   that property is not used anywhere on this page.

   The result is a bare pink handle: no rail, no arrows, no corner.
   ========================================================================== */

::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

/* Inside the dialogs the track is transparent so only the handle shows on the
   card. */
::-webkit-scrollbar-track,
::-webkit-scrollbar-track-piece,
::-webkit-scrollbar-corner {
  background: transparent;
}

/* The handle. */
::-webkit-scrollbar-thumb {
  background: var(--pink);
  border-radius: var(--r-pill);
}

/* No stepper arrows. With the native scrollbar out of the way this is the rule
   that actually removes them. */
::-webkit-scrollbar-button {
  display: none;
}

/* The bar itself is held 48px clear of the top and bottom of the card, while
   the content still scrolls the full height behind it. margin on the track is
   what insets the bar; padding would inset the content instead. */
.modal--doc .doc::-webkit-scrollbar-track,
.modal:not(.modal--doc) .modal__step::-webkit-scrollbar-track {
  margin-block: var(--s-600);
}
@media (max-width: 520px) {
  .modal--doc .doc::-webkit-scrollbar-track,
  .modal:not(.modal--doc) .modal__step::-webkit-scrollbar-track {
    margin-block: var(--s-400);
  }
}

/* The honeypot must be genuinely invisible but still submitted, so it is
   moved off screen rather than display:none, which some bots detect. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.cf-turnstile { margin-top: var(--s-300); }

/* ==========================================================================
   Roaches section
   --------------------------------------------------------------------------
   Heading and subtitle on the left, mockup on the right, then the perks as a
   plain single column list underneath. No card around them: the panel was
   competing with the tier cards elsewhere on the page and adding height for
   nothing.
   ========================================================================== */

.roaches__split {
  display: grid;
  /* Mockup column first, so the phone sits on the left and the copy plus
     perks on the right. The wider track goes to the text. */
  grid-template-columns: 0.95fr 1.05fr;
  gap: var(--s-700);
  align-items: center;
}

/* The phone carries a permanent 3D rotation and a scroll-driven translate, so
   what it paints never matches the box the grid lays out. Centring that box
   therefore leaves the mockup visibly low.

   Instead the stage stretches to the full row height and becomes the
   positioning context, and the phone is taken out of flow and pinned to the
   stage's true middle with top: 50% and a translate. Because the tilt script
   overwrites `transform`, the correction lives on `top` and `margin-top`
   rather than in the transform, so the two never fight. */
/* The phone stays in normal flow, so it creates the height rather than the
   stage having to guess it. The frame is simply the phone plus a symmetric
   padding: equal air above and below by construction, at any viewport,
   whatever the copy column does.

   The tilt paints beyond the phone's layout box, so the padding clears that
   overhang too. */
.roaches__split .phone-stage {
  align-self: center;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Split rather than symmetric: the rotateX tilt paints the phone lower than
     its layout box, so a shade more room on top and less beneath is what makes
     the glass sit centred, which is what the eye actually judges. */
  padding-top: 20px;
  padding-bottom: 28px;
}

/* The heading stays first in the markup for reading order and screen
   readers; only the visual columns swap. */
.roaches__split > :first-child { order: 2; }
.roaches__split .phone-stage   { order: 1; }

.perks {
  margin: var(--s-400) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--s-200);
}

.perks li {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: var(--s-200);
  align-items: start;
  font-size: 16px;
  line-height: 24px;
  color: var(--on-dark);
}
.perks li svg { margin-top: 3px; color: var(--pink); }
.perks strong { color: var(--white); font-weight: 600; }

@media (max-width: 940px) {
  .roaches__split {
    grid-template-columns: 1fr;
    gap: 0;                            /* spacing handled per item below */
  }
  /* Mockup first when stacked too, so the screen leads and the copy plus
     perks follow underneath. The margin sits on the phone rather than the
     grid gap, so the 3D overhang is cleared as well. */
  .roaches__split .phone-stage {
    order: 1;
    align-self: auto;
    margin-bottom: 96px;
  }
  .roaches__split > :first-child { order: 2; }

  .perks { margin-top: var(--s-300); }
}
