/* jenfoxuwu — "Cyber Candy"
   Tokens, the capsule + halo box language, the sparkle signature, and the
   lander. Written mobile-first: 99% of traffic is a phone in an in-app
   browser. */

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

@font-face {
  font-family: 'Baloo 2';
  src: url('/assets/fonts/Baloo2-var.woff2') format('woff2');
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Nunito';
  src: url('/assets/fonts/Nunito-var.woff2') format('woff2');
  font-weight: 300 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Space Mono';
  src: url('/assets/fonts/SpaceMono-700.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

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

:root {
  --void: #0b0614;
  --ultra: #1a0b2e;
  --bubble: #ff3ea5;
  --shock: #ff7bd5;
  --cyber: #00e5ff;
  --lilac: #b57bff;
  --zap: #fff36b;
  --milk: #f4ecff;
  --muted: rgba(244, 236, 255, 0.62);
  --dim: #9d8fb8;
  --hairline: rgba(181, 123, 255, 0.3);

  --f-display: 'Baloo 2', 'Trebuchet MS', ui-rounded, system-ui, sans-serif;
  --f-body: 'Nunito', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --f-mono: 'Space Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  /* The capsule. One number drives every rounded box on the site. */
  --r: 999px;
  --r-card: 20px;

  --pad: 22px;
  --measure: 34rem;
  color-scheme: dark;
}

/* Konami easter egg. Flipping two custom properties re-tints the entire site,
   because every accent below is expressed in terms of them rather than in raw
   hex. Nothing else has to know the mode exists. */
body.overdrive {
  --bubble: #00e5ff;
  --shock: #7bfcff;
  --cyber: #ff3ea5;
  --lilac: #6bff9e;
}

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

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--void);
  color: var(--milk);
  font-family: var(--f-body);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Holographic sheen. A very slow, very faint conic sweep — the candy-coated
   equivalent of film grain. Fixed and non-interactive, one compositor layer,
   no per-frame paint cost because only the rotation animates. */
body::after {
  content: '';
  position: fixed;
  inset: -50%;
  z-index: 60;
  pointer-events: none;
  opacity: 0.05;
  mix-blend-mode: screen;
  background: conic-gradient(
    from 0deg,
    #ff3ea5,
    #b57bff,
    #00e5ff,
    #fff36b,
    #ff3ea5
  );
  animation: holo 44s linear infinite;
  will-change: transform;
}
@keyframes holo {
  to {
    transform: rotate(1turn);
  }
}

::selection {
  background: var(--bubble);
  color: #fff;
}

a {
  color: var(--cyber);
}

:focus-visible {
  outline: 2px solid var(--cyber);
  outline-offset: 3px;
  border-radius: 4px;
}

.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;
}

/* ----------------------------------------------------------- sparkle ---- */
/* The signature. A gradient hairline with a four-point star riding along it,
   twinkling as it goes. Under every page title and nowhere else, so it reads as
   a mark rather than as decoration. */

.sparkle {
  position: relative;
  width: 92px;
  height: 16px;
  margin: 12px auto 0;
  flex: none;
}
.sparkle i {
  position: absolute;
  inset: 7px 0 auto 0;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(
    90deg,
    transparent,
    var(--bubble) 25%,
    var(--lilac) 50%,
    var(--cyber) 75%,
    transparent
  );
}
/* The star is one element: a square with two conic pinches, which gives a
   four-point twinkle without an SVG or a second node. */
.sparkle b {
  position: absolute;
  top: 2px;
  left: 0;
  width: 12px;
  height: 12px;
  background: var(--zap);
  filter: drop-shadow(0 0 6px var(--zap));
  clip-path: polygon(
    50% 0%, 60% 40%, 100% 50%, 60% 60%,
    50% 100%, 40% 60%, 0% 50%, 40% 40%
  );
  animation: twinkle 6s ease-in-out infinite;
}
@keyframes twinkle {
  0%   { left: 4px;  transform: scale(0.5) rotate(0deg);    opacity: 0; }
  12%  { opacity: 1; }
  50%  { transform: scale(1) rotate(180deg); }
  88%  { opacity: 1; }
  100% { left: 76px; transform: scale(0.5) rotate(360deg);  opacity: 0; }
}

/* ------------------------------------------------------------ buttons ---- */
/* Two layers: the outer element paints the gradient rim and the halo, .face
   paints the fill. Both are capsules, and because .face is inset by 2px the gap
   between them becomes an even border the whole way around the curve — which a
   single border plus a background gradient cannot do. */

.btn {
  display: block;
  width: 100%;
  max-width: 460px;
  margin: 0 auto;
  padding: 2px;
  border-radius: var(--r);
  text-decoration: none;
  border: 0;
  font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.16s ease, box-shadow 0.16s ease, filter 0.16s ease;
}

.btn .face {
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
  min-height: 68px;
  padding: 0 24px;
  border-radius: var(--r);
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 1.08rem;
  letter-spacing: 0.06em;
  text-align: center;
}

/* Candy gloss: a specular band across the top of the fill. */
.btn .face::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 50%;
  border-radius: var(--r) var(--r) 40% 40% / var(--r) var(--r) 12px 12px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0));
  pointer-events: none;
}

/* Each glow is declared twice: a literal rgba first, then the color-mix version
   that follows whatever --bubble/--cyber currently are. Browsers without
   color-mix() drop the second declaration and keep the first, so they lose the
   overdrive re-tint but never the glow itself. */
.btn-vip {
  background: linear-gradient(120deg, var(--shock), var(--bubble) 45%, var(--lilac));
  box-shadow: 0 6px 26px -4px rgba(255, 62, 165, 0.7);
  box-shadow: 0 6px 26px -4px color-mix(in srgb, var(--bubble) 70%, transparent);
}
.btn-vip .face {
  background: linear-gradient(168deg, var(--shock) 0%, var(--bubble) 52%, #c4157a 100%);
  color: #fff;
  text-shadow: 0 1px 6px rgba(120, 0, 60, 0.45);
}

.btn-tiktok {
  background: linear-gradient(120deg, var(--cyber), var(--lilac));
  box-shadow: 0 6px 24px -6px rgba(0, 229, 255, 0.55);
  box-shadow: 0 6px 24px -6px color-mix(in srgb, var(--cyber) 55%, transparent);
}
.btn-tiktok .face {
  background: rgba(11, 6, 20, 0.82);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: var(--milk);
}

/* A press state, not a hover state — there is no hover on a phone. */
.btn:active {
  transform: scale(0.978);
}
.btn-vip:active {
  box-shadow: 0 2px 34px -2px rgba(255, 62, 165, 0.9);
  box-shadow: 0 2px 34px -2px color-mix(in srgb, var(--bubble) 90%, transparent);
}

@media (hover: hover) and (pointer: fine) {
  .btn:hover {
    transform: translateY(-2px);
  }
  .btn-vip:hover {
    box-shadow: 0 12px 34px -4px rgba(255, 62, 165, 0.85);
    box-shadow: 0 12px 34px -4px color-mix(in srgb, var(--bubble) 85%, transparent);
  }
  .btn-tiktok:hover {
    box-shadow: 0 12px 30px -6px rgba(0, 229, 255, 0.75);
    box-shadow: 0 12px 30px -6px color-mix(in srgb, var(--cyber) 75%, transparent);
  }
}

/* ------------------------------------------------------------- lander ---- */

.stage {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  min-height: calc(var(--vh, 1vh) * 100);
}

.video-panel {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background: var(--void);
}
.video-panel video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* This clip is bright — white tile, hard ceiling lights — so the scrim has to
   work considerably harder than a dark one would. Two jobs: kill enough of the
   top that the live counter stays legible, then ramp to near-solid from the
   midpoint down so the display type and the buttons sit on real ground rather
   than on a lit bathroom wall. The tinted radial at the bottom is what stops
   that ramp reading as a plain grey fade. */
.scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(
      180deg,
      rgba(11, 6, 20, 0.9) 0%,
      rgba(11, 6, 20, 0.42) 12%,
      rgba(11, 6, 20, 0.28) 24%,
      /* Her face sits around a third of the way down. Darkening from here keeps
         it clear above while giving the name somewhere to land. */
      rgba(11, 6, 20, 0.62) 42%,
      rgba(11, 6, 20, 0.9) 58%,
      rgba(11, 6, 20, 0.98) 72%,
      var(--void) 100%
    ),
    radial-gradient(130% 62% at 50% 100%, rgba(255, 62, 165, 0.34), transparent 68%),
    radial-gradient(90% 44% at 8% 84%, rgba(0, 229, 255, 0.16), transparent 70%);
}

#unmute-btn {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 14px);
  right: 14px;
  z-index: 3;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 1px solid var(--hairline);
  border-radius: 50%;
  background: rgba(11, 6, 20, 0.6);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: var(--milk);
  font-family: var(--f-mono);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
#unmute-btn[data-on='true'] {
  border-color: var(--cyber);
  color: var(--cyber);
  box-shadow: 0 0 14px -2px var(--cyber);
}

.link-panel {
  position: relative;
  z-index: 2;
  min-height: 100vh;
  min-height: 100dvh;
  min-height: calc(var(--vh, 1vh) * 100);
  display: flex;
  flex-direction: column;
  /* Bottom-weighted on mobile: keeps her face visible, puts the CTAs where a
     thumb already is, and lets the scrim do the contrast work. */
  justify-content: flex-end;
  align-items: center;
  gap: 0;
  padding: 0 var(--pad) calc(env(safe-area-inset-bottom, 0px) + 28px);
  text-align: center;
}

/* ------------------------------------------------------- hit counter ---- */
/* The Y2K odometer. Same honest /live number as anywhere else — it just looks
   like a visitor counter from 2003, because that is funnier. */

/* `display: flex` on a class beats the UA's `[hidden] { display: none }`, so
   without this the element stays laid out when the counter suppresses itself
   and a lone pulsing dot floats at the top of the page with no number beside
   it. Every `hidden` toggle in the markup needs its display rule neutralised
   the same way — see also .quiz-back below. */
.live[hidden] {
  display: none;
}

.live {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 auto;
  padding: calc(env(safe-area-inset-top, 0px) + 16px) 0 0;
  font-family: var(--f-mono);
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  color: var(--muted);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.9);
}
.live i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--cyber);
  box-shadow: 0 0 10px var(--cyber);
  animation: pulse 2.4s ease-in-out infinite;
}
.live .odo {
  display: inline-block;
  padding: 2px 7px;
  border-radius: 5px;
  background: rgba(11, 6, 20, 0.72);
  border: 1px solid var(--hairline);
  color: var(--zap);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.14em;
}
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.25; }
}

.name {
  font-family: var(--f-display);
  font-weight: 800;
  font-size: clamp(2.9rem, 15vw, 5.4rem);
  line-height: 0.95;
  letter-spacing: -0.015em;
  margin: 0;
  background: linear-gradient(174deg, #fff 8%, var(--shock) 48%, var(--lilac) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* drop-shadow rather than text-shadow: text-shadow paints behind the glyph
     box, which a transparent gradient-filled glyph does not have. */
  filter: drop-shadow(0 2px 18px rgba(255, 62, 165, 0.5))
    drop-shadow(0 1px 3px rgba(0, 0, 0, 0.8));
}

.tagline {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-height: 1.5em;
  margin: 14px 0 24px;
  font-family: var(--f-mono);
  font-size: 0.76rem;
  letter-spacing: 0.04em;
  color: var(--muted);
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.95);
}
.tagline .caret {
  display: inline-block;
  width: 2px;
  height: 1.05em;
  background: var(--bubble);
  box-shadow: 0 0 8px var(--bubble);
  animation: caret 1.05s steps(1) infinite;
}
@keyframes caret {
  0%, 50%   { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}

.links {
  display: flex;
  flex-direction: column;
  gap: 13px;
  width: 100%;
  max-width: 460px;
}

.sub-links {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 18px;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: lowercase;
}
.sub-links a {
  color: var(--muted);
  text-decoration: none;
  /* 14px of vertical padding on a ~20px line box clears the 48px tap-target
     floor. The underline is drawn by a pseudo-element rather than the border,
     so the padding can grow the target without pushing the rule away from the
     text. */
  padding: 14px 8px;
  position: relative;
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.95);
}
.sub-links a::after {
  content: '';
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: 11px;
  height: 2px;
  border-radius: 2px;
  background: transparent;
  transition: background 0.16s ease;
}
.sub-links a:active,
.sub-links a:hover {
  color: var(--milk);
}
.sub-links a:active::after,
.sub-links a:hover::after {
  background: var(--bubble);
}
.sub-links span {
  color: var(--lilac);
  opacity: 0.55;
}

/* Sparkle canvas. A cursor trail is dead weight on a phone, so on touch this is
   what the trail becomes — see script.js, which binds by pointer type rather
   than by screen width. */
#fx {
  position: fixed;
  inset: 0;
  z-index: 50;
  pointer-events: none;
}

/* ------------------------------------------------------ custom cursor ---- */
/* Fine pointers only. The element is inert and purely decorative — the real
   system cursor is left alone on anything interactive, so nobody ever loses
   track of what they are about to click. */

#cursor {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 55;
  width: 18px;
  height: 18px;
  margin: -9px 0 0 -9px;
  pointer-events: none;
  background: var(--zap);
  filter: drop-shadow(0 0 8px var(--bubble));
  clip-path: polygon(
    50% 0%, 60% 40%, 100% 50%, 60% 60%,
    50% 100%, 40% 60%, 0% 50%, 40% 40%
  );
  opacity: 0;
  transition: opacity 0.2s ease, transform 0.12s ease;
}
#cursor.on {
  opacity: 1;
}
#cursor.tap {
  transform: scale(1.7) rotate(35deg);
}

/* --------------------------------------------------------- sticky CTA ---- */
/* On the long pages the CTA scrolls away and conversion dies with it. This pins
   after roughly a screen of scroll, inside the home-indicator inset. */

.sticky-cta {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
  padding: 12px var(--pad) calc(env(safe-area-inset-bottom, 0px) + 12px);
  background: linear-gradient(180deg, rgba(11, 6, 20, 0), rgba(11, 6, 20, 0.96) 44%);
  transform: translateY(140%);
  transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}
.sticky-cta.on {
  transform: translateY(0);
  pointer-events: auto;
}
.sticky-cta .btn .face {
  min-height: 54px;
  font-size: 1rem;
}

/* ------------------------------------------------------------ desktop ---- */

@media (min-width: 769px) {
  .stage {
    display: grid;
    grid-template-columns: 42% 58%;
  }
  .video-panel {
    position: fixed;
    inset: 0 58% 0 0;
  }
  /* Full-height panel, so the scrim only needs to protect the unmute control
     rather than carry text contrast. */
  .scrim {
    background:
      linear-gradient(
        180deg,
        rgba(11, 6, 20, 0.62) 0%,
        rgba(11, 6, 20, 0) 24%,
        rgba(11, 6, 20, 0) 74%,
        rgba(11, 6, 20, 0.7) 100%
      ),
      radial-gradient(80% 40% at 50% 100%, rgba(255, 62, 165, 0.28), transparent 70%);
  }
  #unmute-btn {
    top: auto;
    bottom: 20px;
    right: 20px;
  }
  .link-panel {
    grid-column: 2;
    justify-content: center;
    padding: 40px;
  }
  .live {
    position: absolute;
    top: 26px;
    margin: 0;
    padding-top: 0;
  }
  .name,
  .tagline,
  .sub-links a,
  .live {
    text-shadow: none;
  }
  .sticky-cta {
    display: none; /* the CTA is always in view on a desktop layout */
  }
}

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

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  body::after {
    animation: none;
  }
  .sparkle b {
    left: 40px;
    opacity: 1;
    transform: scale(1);
  }
  .tagline .caret {
    display: none;
  }
  .sticky-cta {
    transition: none;
  }
  #fx,
  #cursor {
    display: none;
  }
}
