/* ===========================================================================
   officialskylarmaexo — Angel Chrome
   Base sheet: tokens, reset, fonts, the halo, the buttons, the lander.
   Loaded on every page. doc.css and quiz.css layer on top.
   Mobile is the design; desktop is the adaptation.
   ========================================================================= */

/* Registering the angle makes it interpolable, which is what lets the
   specular sweep on a button rotate on press instead of jumping. Browsers
   without @property simply get the end state with no transition. */
@property --sweep {
  syntax: "<angle>";
  inherits: false;
  initial-value: 200deg;
}

@font-face {
  font-family: "Syne";
  src: url("/assets/fonts/Syne-var.woff2") format("woff2-variations");
  font-weight: 400 800;
  font-display: swap;
}
@font-face {
  font-family: "Manrope";
  src: url("/assets/fonts/Manrope-var.woff2") format("woff2-variations");
  font-weight: 200 800;
  font-display: swap;
}
@font-face {
  font-family: "DM Mono";
  src: url("/assets/fonts/DMMono-500.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
}

:root {
  --void: #060912;
  --deep: #0d1426;
  --chrome: #cfd8e8;
  --iris: #b8a6ff;
  --halo: #8fd4ff;
  --blush: #ffc2dd;
  --pearl: #fdfbff;

  --muted: rgba(253, 251, 255, 0.6);
  --faint: rgba(253, 251, 255, 0.38);
  --hair: rgba(207, 216, 232, 0.16);

  /* The one gradient the whole site is built from. Every rim, every halo,
     every rule is a slice of this sweep, which is what makes the chrome read
     as one material rather than as several unrelated accents. */
  --rim: conic-gradient(
    from var(--sweep),
    var(--halo) 0deg,
    var(--pearl) 70deg,
    var(--chrome) 140deg,
    var(--iris) 215deg,
    var(--halo) 300deg,
    var(--halo) 360deg
  );

  --display: "Syne", "Trebuchet MS", sans-serif;
  --body: "Manrope", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "DM Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  --pad: 20px;
  --r-lg: 24px;
  --r-md: 18px;
  --r-sm: 12px;

  /* Set by script.js from window.innerHeight. The last resort in the height
     chain below — iOS Safari before 15.4 has neither dvh nor an honest vh. */
  --vh: 1vh;
}

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

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

body {
  margin: 0;
  background: var(--void);
  color: var(--pearl);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

a {
  color: var(--halo);
  text-decoration-color: rgba(143, 212, 255, 0.4);
  text-underline-offset: 3px;
}

img,
video,
svg {
  display: block;
  max-width: 100%;
}

button {
  font: inherit;
  color: inherit;
}

/* A class that sets display outranks the user agent's [hidden] rule, so
   anything toggled with the attribute needs this to actually disappear.
   A missing rule here once left a pulsing dot on the page with no number
   beside it. A test asserts every hidden-toggled class has one. */
[hidden] {
  display: none !important;
}

:focus-visible {
  outline: 2px solid var(--halo);
  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;
}

/* ------------------------------------------------------------- the halo ---
   The signature. An elliptical ring carrying the rim sweep, produced by
   masking a gradient with a radial ellipse so only the outer band survives.
   A border cannot do this: a border follows the box, and an ellipse is not a
   box. It appears above page titles and behind the wordmark, nowhere else. */

/* The mask needs THREE zones, not two: transparent inside, opaque across the
   3px band, transparent again outside. A radial-gradient continues its last
   stop colour forever past 100%, so stopping at the opaque band leaves the
   whole rest of the box painted — a filled rectangle with an ellipse punched
   out of it. The explicit transparent stop at 100% is what closes it. */
.halo {
  position: relative;
  width: 168px;
  height: 54px;
  margin: 0 auto;
  background: var(--rim);
  -webkit-mask: radial-gradient(
    ellipse closest-side at 50% 50%,
    #0000 calc(100% - 4px),
    #000 calc(100% - 3.4px),
    #000 calc(100% - 0.6px),
    #0000 100%
  );
  mask: radial-gradient(
    ellipse closest-side at 50% 50%,
    #0000 calc(100% - 4px),
    #000 calc(100% - 3.4px),
    #000 calc(100% - 0.6px),
    #0000 100%
  );
  /* filter runs after the mask, so drop-shadow traces the ring's own alpha and
     the glow is ring-shaped. The previous approach — a blurred radial behind
     it — painted the interior too, which on a flat dark panel read as a grey
     disc rather than a halo. */
  filter: drop-shadow(0 0 9px rgba(143, 212, 255, 0.55))
    drop-shadow(0 0 22px rgba(184, 166, 255, 0.28));
}

.halo-wrap {
  position: relative;
  display: grid;
  place-items: center;
}

/* Above a page title, smaller and quieter. */
.halo-rule {
  width: 118px;
  height: 34px;
  margin: 0 auto 14px;
  opacity: 0.85;
}

/* ------------------------------------------------------------- buttons ---
   Two layers. The outer element paints the rim gradient and the outer bloom;
   the inner .face paints the fill. The 2px gap between them is an even border
   the whole way round the curve — a single border plus a background gradient
   cannot produce that, because the border paints inside the same box. */

.btn {
  position: relative;
  display: block;
  width: 100%;
  padding: 2px;
  border: 0;
  border-radius: var(--r-lg);
  background: var(--rim);
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.18s ease, --sweep 0.5s ease, filter 0.18s ease;
}

.btn .face {
  display: grid;
  place-items: center;
  min-height: 62px;
  padding: 12px 22px;
  border-radius: calc(var(--r-lg) - 2px);
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.06rem;
  letter-spacing: 0.01em;
  text-align: center;
}

.btn:active {
  transform: scale(0.985);
  --sweep: 340deg;
}

/* VIP is the only filled element on the page. A bright chrome slab against a
   midnight ground is the strongest contrast available here, and the paid link
   is the one that has to win the eye. */
.btn-vip .face {
  background: linear-gradient(160deg, var(--pearl) 0%, var(--chrome) 52%, #a9bcd8 100%);
  color: #0a1020;
}

.btn-vip {
  box-shadow:
    0 10px 34px -10px rgba(255, 194, 221, 0.5),
    0 2px 10px -4px rgba(143, 212, 255, 0.4);
}

.btn-vip:active {
  filter: brightness(1.06);
}

/* TikTok is a hairline. Deliberately quiet — it is the free destination. */
.btn-tiktok {
  background: rgba(143, 212, 255, 0.34);
  box-shadow: none;
}

.btn-tiktok .face {
  background: rgba(10, 16, 32, 0.72);
  color: var(--pearl);
  font-weight: 600;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

.btn-tiktok:active {
  background: rgba(143, 212, 255, 0.6);
}

/* --------------------------------------------------------- micro labels ---
   DM Mono, tracked out, uppercase. Used for eyebrows and counters — anything
   that is data about the page rather than the page's own voice. */

.micro {
  font-family: var(--mono);
  font-weight: 500;
  font-size: 0.66rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--faint);
}

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

.stage {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  min-height: calc(var(--vh) * 100);
  display: flex;
  flex-direction: column;
  isolation: isolate;
}

.video-layer {
  position: fixed;
  inset: 0;
  z-index: -2;
  overflow: hidden;
  background: var(--void);
}

.video-layer video,
.video-layer img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Darkens only the top and bottom, so the controls and the type stay legible
   against any frame of the clip while the middle of the video stays clear. */
.scrim {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    linear-gradient(
      to bottom,
      rgba(6, 9, 18, 0.88) 0%,
      rgba(6, 9, 18, 0.4) 20%,
      rgba(6, 9, 18, 0.52) 42%,
      rgba(6, 9, 18, 0.88) 66%,
      rgba(6, 9, 18, 0.97) 100%
    ),
    radial-gradient(ellipse 120% 60% at 50% 108%, rgba(255, 194, 221, 0.14), transparent 70%);
}

.particles {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.wrap {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 460px;
  margin: 0 auto;
  padding: calc(env(safe-area-inset-top) + 18px) var(--pad)
    calc(env(safe-area-inset-bottom) + 22px);
  flex: 1;
  display: flex;
  flex-direction: column;
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  min-height: 44px;
}

.sound {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 44px;
  padding: 0 15px;
  border: 1px solid var(--hair);
  border-radius: 999px;
  background: rgba(6, 9, 18, 0.5);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: var(--muted);
  cursor: pointer;
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.sound:active {
  color: var(--pearl);
  border-color: rgba(143, 212, 255, 0.5);
}

/* The wordmark wears the halo. The ring sits behind the name with the lower
   arc passing under the type, so it reads as a halo above a head rather than
   as an ellipse that happens to be nearby. This is the page's one bold move;
   everything else stays quiet. */
.crown {
  margin-top: auto;
  padding-bottom: 6px;
  text-align: center;
  /* The measuring context for the wordmark above. Without this, its cqw units
     resolve against the viewport and the sizing bug comes straight back. */
  container-type: inline-size;
}

/* The ring floats above the name with a clear gap. It used to overlap by 13px,
   which put the eyebrow exactly on the ring's bottom arc and struck the
   letters through. A halo sits above a head; it does not intersect it. */
.crown .halo-wrap {
  margin-bottom: 6px;
}

.name {
  position: relative;
  margin: 0;
  line-height: 1;
}

.name-pre {
  display: block;
  margin-bottom: 4px;
  font-family: var(--mono);
  font-weight: 500;
  font-size: 0.64rem;
  letter-spacing: 0.34em;
  text-indent: 0.34em; /* balances the trailing letter-space when centred */
  text-transform: uppercase;
  color: rgba(253, 251, 255, 0.52);
}

.name-main {
  display: block;
  font-family: var(--display);
  font-weight: 800;
  /* The wordmark is a fixed 11-character string on one line, so its width is a
     known multiple of the font size — 9.94x with this face and tracking.

     It must be sized against its COLUMN, not the viewport. The two are not the
     same: the column is capped at 460px on mobile and is 60% minus padding on
     desktop, so a 100vw-based size overflowed everywhere between about 490px
     and 1050px and truncated the name to "skylarmae". Container units measure
     the thing that actually constrains it, and stay correct if the padding or
     the column width is ever changed.

     The first declaration is the fallback for engines without container
     queries; its cap is low enough to survive the narrowest column the desktop
     layout produces. Engines that understand cqw discard it for the second. */
  font-size: min(2rem, calc((100vw - 44px) / 10.1));
  font-size: min(2.75rem, calc((100cqw - 8px) / 10.1));
  line-height: 1.02;
  letter-spacing: -0.035em;
  white-space: nowrap;
  background: linear-gradient(178deg, var(--pearl) 24%, #b9c6dd 94%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 0 26px rgba(143, 212, 255, 0.28));
}

.tagline {
  min-height: 1.6em;
  margin: 12px 0 0;
  color: var(--muted);
  font-size: 0.98rem;
}

.caret {
  color: var(--halo);
  font-weight: 300;
}

.links {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 30px;
}

.nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 20px;
}

.nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 15px;
  border: 1px solid var(--hair);
  border-radius: 999px;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  text-decoration: none;
}

.nav a:active {
  color: var(--pearl);
  border-color: rgba(143, 212, 255, 0.5);
}

.foot {
  margin-top: 22px;
  padding-top: 4px;
  text-align: center;
}

/* The live counter. Hides itself below two rather than showing something
   sad, and hides silently when the database is unreachable. It never shows
   an invented number. */
.counter {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--halo);
  box-shadow: 0 0 9px var(--halo);
  animation: pulse 2.4s ease-in-out infinite;
}

@keyframes pulse {
  0%,
  100% {
    opacity: 0.35;
  }
  50% {
    opacity: 1;
  }
}

/* --------------------------------------------------- sticky VIP bar ------
   For the scroll-heavy pages only. The lander's CTA is already on screen, so
   it does not get one. */

.sticky-vip {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
  padding: 10px var(--pad) calc(env(safe-area-inset-bottom) + 10px);
  background: linear-gradient(to top, rgba(6, 9, 18, 0.97) 62%, rgba(6, 9, 18, 0));
  transform: translateY(120%);
  transition: transform 0.28s ease;
  pointer-events: none;
}

.sticky-vip.on {
  transform: translateY(0);
  pointer-events: auto;
}

.sticky-vip .btn {
  max-width: 460px;
  margin: 0 auto;
}

.sticky-vip .face {
  min-height: 52px;
  font-size: 1rem;
}

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

@media (min-width: 768px) {
  .stage {
    flex-direction: row;
  }

  .video-layer {
    position: fixed;
    right: auto;
    width: 40%;
  }

  .video-layer::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(to right, transparent 62%, var(--void) 100%);
  }

  .scrim {
    left: 0;
    width: 40%;
    background: linear-gradient(
      to bottom,
      rgba(6, 9, 18, 0.6) 0%,
      rgba(6, 9, 18, 0.12) 40%,
      rgba(6, 9, 18, 0.7) 100%
    );
  }

  .wrap {
    margin-left: 40%;
    max-width: none;
    width: 60%;
    padding: 40px min(7vw, 76px);
    justify-content: center;
  }

  .crown {
    margin-top: 0;
    text-align: left;
  }

  .crown .halo-wrap {
    place-items: center start;
  }

  .crown .halo {
    margin-left: 6px;
  }

  .links,
  .nav {
    max-width: 420px;
  }

  .nav {
    justify-content: flex-start;
  }

  .foot {
    text-align: left;
  }

  .topbar {
    position: fixed;
    top: 16px;
    left: 16px;
    z-index: 5;
  }

  /* Pointer devices get a real hover; touch devices never see these rules. */
  .btn:hover {
    --sweep: 320deg;
    filter: brightness(1.05);
  }

  .nav a:hover,
  .sound:hover {
    color: var(--pearl);
    border-color: rgba(143, 212, 255, 0.5);
  }
}

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

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

  .dot {
    opacity: 0.9;
  }

  .particles {
    display: none;
  }
}
