/* Unveiled — Copyright (c) 2026 Andre Prior // PushingPandas // a.prior@pushingpandas.io
   All rights reserved. No distribution, modification, or sale without written consent. */

/* GeistPixel family — five LED-matrix variants self-hosted under
   /assets/fonts/. Each variant is a different cell shape:
   Circle (dots), Grid, Line, Square, Triangle. Each declared as an
   independent font-family so CSS consumers can pick by name. The
   wordmark uses Circle by default per the mock. font-display: swap
   so the page is readable while the woff2 streams. */
@font-face {
  font-family: "GeistPixel Circle";
  src: url("/assets/fonts/GeistPixel-Circle.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "GeistPixel Grid";
  src: url("/assets/fonts/GeistPixel-Grid.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "GeistPixel Line";
  src: url("/assets/fonts/GeistPixel-Line.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "GeistPixel Square";
  src: url("/assets/fonts/GeistPixel-Square.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "GeistPixel Triangle";
  src: url("/assets/fonts/GeistPixel-Triangle.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
/* Geist Mono — 9 static weights self-hosted under /assets/fonts/.
   Each weight is its own woff2 (no variable font); browser picks
   the right file from the family stack via font-weight. */
@font-face {
  font-family: "Geist Mono";
  src: url("/assets/fonts/GeistMono-Thin.woff2") format("woff2");
  font-weight: 100;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/assets/fonts/GeistMono-ExtraLight.woff2") format("woff2");
  font-weight: 200;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/assets/fonts/GeistMono-Light.woff2") format("woff2");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/assets/fonts/GeistMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/assets/fonts/GeistMono-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/assets/fonts/GeistMono-SemiBold.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/assets/fonts/GeistMono-Bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/assets/fonts/GeistMono-ExtraBold.woff2") format("woff2");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/assets/fonts/GeistMono-Black.woff2") format("woff2");
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background: #000;
  color: #f6f8fc;
  /* Geist Mono is the canonical body face for the marketing teaser.
     Only the wordmark overrides this (GeistPixel Circle). Everything
     else — season, byline, signup label, footer, status messages —
     inherits this stack. */
  font-family: "Geist Mono", ui-monospace, "JetBrains Mono", Consolas,
    monospace;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

body {
  /* Let actual content drive page height — the original 180vh was
     padding the footer halfway down a void. Parallax (sky.js) still
     reacts to whatever scroll the content induces; with the planet
     + signup pill + footer we land ~110vh, just enough to see the
     star layers shift. */
  min-height: 100vh;
}

/* Star canvas sits ABOVE the planet (z-index 10) with screen blend
   mode — black canvas pixels become transparent against whatever is
   behind, so only the bright star dots are visible. Net effect: the
   field hovers over the entire page including the planet rectangle,
   killing the "pasted-on box" feel from the previous render.
   pointer-events: none so it doesn't intercept clicks/hovers. */
#sky {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  display: block;
  z-index: 10;
  pointer-events: none;
  mix-blend-mode: screen;
}

/* No z-index here: main needs to share the page's stacking context
   so the planet img's own mix-blend-mode resolves against the
   #000 body background instead of an isolated layer. Otherwise the
   planet's near-black PNG pixels would render as a slightly-darker
   rectangle. */
main {
  max-width: 1100px;
  margin: 0 auto;
  padding: 9vh 6vw 8vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.wordmark {
  /* GeistPixel Circle is the canonical wordmark face. Fallbacks
     stay monospaced so a font-loading hiccup still reads as
     dot-matrix-adjacent, never like a serif title. */
  font-family: "GeistPixel Circle", ui-monospace, "JetBrains Mono",
    Consolas, monospace;
  font-weight: 500;
  font-size: clamp(58px, 9vw, 124px);
  letter-spacing: 4px;
  margin: 0;
  line-height: 1;
  color: #f6f8fc;
  /* Subtle backlit glow so the dots feel emissive against the black
     background, like an LED matrix at low power. */
  text-shadow: 0 0 18px rgba(255, 255, 255, 0.18),
    0 0 48px rgba(180, 200, 255, 0.08);
  cursor: default;
  /* hover triggers a one-shot CRT glitch — chromatic split + jitter
     + brief skew, ~480ms then back to rest. steps() (vs cubic-bezier)
     keeps the motion staccato so it reads as digital corruption,
     not a smooth zoom. */
}

/* Three glitch variants. glitch.js picks one at random on each
   trigger (auto every 4-10 s, plus hover) so the wordmark never
   reads the same way twice in a row. All return to a clean rest
   pose so they can stack visually with the static text-shadow.
   - A: chromatic split + skew + filter swings (the original)
   - B: short vertical jitter, minimal colour
   - C: long, slow chromatic-only pulse, no motion */
@keyframes wordmark-glitch-a {
  0% {
    transform: translate(0, 0) skew(0deg);
    text-shadow: 0 0 18px rgba(255, 255, 255, 0.18),
      0 0 48px rgba(180, 200, 255, 0.08);
    filter: none;
  }
  8% {
    transform: translate(-3px, 1px) skewX(-4deg);
    text-shadow: 3px 0 0 rgba(255, 60, 90, 0.85),
      -3px 0 0 rgba(60, 200, 255, 0.85);
    filter: contrast(1.4);
  }
  16% {
    transform: translate(3px, -2px);
    text-shadow: -2px 0 0 rgba(255, 60, 90, 0.85),
      2px 0 0 rgba(60, 200, 255, 0.85);
    filter: hue-rotate(40deg);
  }
  26% {
    transform: translate(-2px, 2px) skewX(2deg);
    text-shadow: 2px 0 0 rgba(255, 220, 80, 0.7),
      -2px 0 0 rgba(120, 90, 255, 0.7);
    filter: invert(0.1);
  }
  38% {
    transform: translate(2px, 0);
    text-shadow: 4px 0 0 rgba(255, 60, 90, 0.55),
      -4px 0 0 rgba(60, 200, 255, 0.55);
    filter: brightness(1.3);
  }
  52% {
    transform: translate(-1px, -1px) skewX(-1deg);
    text-shadow: -3px 0 0 rgba(255, 60, 90, 0.7),
      3px 0 0 rgba(60, 200, 255, 0.7);
    filter: hue-rotate(-30deg);
  }
  68% {
    transform: translate(2px, 1px);
    text-shadow: 1px 0 0 rgba(255, 255, 255, 0.9),
      -1px 0 0 rgba(140, 200, 255, 0.9);
    filter: contrast(1.2);
  }
  82% {
    transform: translate(-1px, 0);
    text-shadow: -1px 0 0 rgba(255, 60, 90, 0.4),
      1px 0 0 rgba(60, 200, 255, 0.4),
      0 0 18px rgba(255, 255, 255, 0.18);
    filter: none;
  }
  100% {
    transform: translate(0, 0) skew(0deg);
    text-shadow: 0 0 18px rgba(255, 255, 255, 0.18),
      0 0 48px rgba(180, 200, 255, 0.08);
    filter: none;
  }
}

/* Variant B — short, sharp vertical jitter. ~260 ms / 8 steps. No
   skew, minimal chromatic kick, just a brief shudder. */
@keyframes wordmark-glitch-b {
  0% {
    transform: translate(0, 0);
    text-shadow: 0 0 18px rgba(255, 255, 255, 0.18),
      0 0 48px rgba(180, 200, 255, 0.08);
  }
  20% {
    transform: translate(0, -2px);
  }
  40% {
    transform: translate(0, 3px);
    text-shadow: 1px 0 0 rgba(255, 60, 90, 0.65),
      -1px 0 0 rgba(60, 200, 255, 0.65);
  }
  60% {
    transform: translate(0, -1px);
  }
  80% {
    transform: translate(0, 1px);
  }
  100% {
    transform: translate(0, 0);
    text-shadow: 0 0 18px rgba(255, 255, 255, 0.18),
      0 0 48px rgba(180, 200, 255, 0.08);
  }
}

/* Variant C — slow chromatic pulse, no motion at all. ~700 ms,
   ease-out so it ramps in and falls back gently. Reads as a quiet
   signal-loss flicker rather than a rough glitch. */
@keyframes wordmark-glitch-c {
  0% {
    text-shadow: 0 0 18px rgba(255, 255, 255, 0.18),
      0 0 48px rgba(180, 200, 255, 0.08);
  }
  35% {
    text-shadow: 4px 0 0 rgba(255, 60, 90, 0.45),
      -4px 0 0 rgba(60, 200, 255, 0.45),
      0 0 18px rgba(255, 255, 255, 0.18);
  }
  60% {
    text-shadow: 2px 0 0 rgba(255, 220, 80, 0.4),
      -2px 0 0 rgba(120, 90, 255, 0.4),
      0 0 18px rgba(255, 255, 255, 0.18);
  }
  100% {
    text-shadow: 0 0 18px rgba(255, 255, 255, 0.18),
      0 0 48px rgba(180, 200, 255, 0.08);
  }
}

.wordmark.glitching-a {
  animation: wordmark-glitch-a 0.48s steps(12) 1;
}
.wordmark.glitching-b {
  animation: wordmark-glitch-b 0.26s steps(8) 1;
}
.wordmark.glitching-c {
  animation: wordmark-glitch-c 0.7s ease-out 1;
}

@media (prefers-reduced-motion: reduce) {
  .wordmark.glitching-a,
  .wordmark.glitching-b,
  .wordmark.glitching-c {
    animation: none;
  }
}

.season {
  font-family: "Geist Mono", ui-monospace, "JetBrains Mono", Consolas,
    monospace;
  font-size: clamp(13px, 1.7vw, 18px);
  letter-spacing: 4px;
  color: rgba(246, 248, 252, 0.85);
  margin: 0;
  font-weight: 400;
}

.planet {
  /* Top margin tightened (6vh → 2vh) per Andre's tweak — planet
     sits closer to the subtitle. Bottom is 0 because the byline
     uses its own negative margin-top to overlap the PNG's empty
     bottom padding. */
  margin: 2vh 0 0;
  width: min(82vw, 980px);
  display: flex;
  justify-content: center;
}

.planet img {
  width: 100%;
  height: auto;
  display: block;
  /* `screen` blend kills the rectangle: every near-black pixel in
     the PNG resolves to the body's #000 sky and disappears, while
     white ring highlights stay crisp. Combined with the canvas
     overlay above, stars render OVER the planet too — there's no
     visible image boundary anymore. drop-shadow is intentionally
     omitted: any halo would re-introduce a rectangular footprint. */
  mix-blend-mode: screen;
}

.byline {
  font-family: "Geist Mono", ui-monospace, "JetBrains Mono", Consolas,
    monospace;
  font-size: clamp(13px, 1.6vw, 16px);
  letter-spacing: 1px;
  color: rgba(246, 248, 252, 0.78);
  /* Pull the line up into the planet image's empty bottom padding
     (PNG has ~25-30% dead space below the visible planet), then
     bump it back down two line-heights per Andre's tweak. The
     `lh` unit equals one line-height of the element, so the calc
     is self-consistent if the font-size changes. */
  margin: calc(-10vh + 2lh) auto 0;
  max-width: 720px;
  line-height: 1.55;
}

footer {
  /* Same stacking-context rule as main — no z-index, no positioning.
     The canvas overlays at z-index 10 with screen blend; footer text
     stays in the page flow and remains readable because text colour
     is light grey on #000 page bg, untouched by the overlay. */
  max-width: 1100px;
  margin: 0 auto;
  padding: 6vh 6vw 4vh;
  font-size: 11px;
  letter-spacing: 1px;
  color: rgba(246, 248, 252, 0.4);
  display: flex;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
}

footer a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: rgba(246, 248, 252, 0.2);
}

footer a:hover {
  color: rgba(246, 248, 252, 0.85);
  text-decoration-color: rgba(246, 248, 252, 0.5);
}

footer .dot {
  opacity: 0.5;
}

/* Structured footer — used by the marketing splash + timeline. Nav
   row of word-marked socials on top, copy + Pushing Pandas link
   below. Same muted Geist Mono palette as the rest of the page so
   the footer reads as quiet metadata, not a recruitment banner. */
.site-footer {
  flex-direction: column;
  align-items: center;
  gap: 14px;
  text-transform: uppercase;
  letter-spacing: 1.6px;
}
.site-footer__nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 0 10px;
  font-size: 11px;
}
.site-footer__nav a {
  color: rgba(246, 248, 252, 0.55);
  text-decoration: none;
  padding: 4px 6px;
  transition: color 160ms ease;
}
.site-footer__nav a:hover {
  color: #f6f8fc;
}
.site-footer__nav .sep {
  color: rgba(246, 248, 252, 0.18);
  user-select: none;
}
.site-footer__copy {
  font-size: 11px;
  color: rgba(246, 248, 252, 0.4);
}
.site-footer__brand {
  text-decoration: none;
  color: rgba(246, 248, 252, 0.7);
  border-bottom: 1px dotted rgba(246, 248, 252, 0.3);
  padding-bottom: 1px;
  transition: color 160ms ease, border-color 160ms ease;
}
.site-footer__brand:hover {
  color: #f6f8fc;
  border-bottom-color: rgba(246, 248, 252, 0.7);
}

/* ───────── Newsletter signup ───────── */

/* @property registers the angle as a real animatable angle type so
   the conic-gradient interpolates smoothly. Without it browsers
   treat custom-prop values as opaque strings and skip the
   transition between keyframes — the glow would jump in 1deg
   integer ticks instead of gliding around the pill. */
@property --glow-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

.signup {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  width: min(340px, 92vw);
  margin: 6vh auto 0;
}

.signup__label {
  font-family: "Geist Mono", ui-monospace, "JetBrains Mono", Consolas,
    monospace;
  font-size: 11px;
  letter-spacing: 4px;
  text-transform: uppercase;
  color: rgba(246, 248, 252, 0.55);
}

/* The visible pill. The cyan ring is NOT a real CSS border — it's a
   conic-gradient painted into ::before, masked down to a 1px outer
   ring via the standard "two masks + composite-exclude" trick. The
   gradient is 95% transparent except for a bright wedge near
   --glow-angle; rotating that custom property animates the wedge
   around the pill, reading as a single point of light running the
   line. */
.signup__field {
  position: relative;
  display: flex;
  align-items: stretch;
  width: 100%;
  border-radius: 999px;
  background: #0a0d12;
  isolation: isolate;
}

/* Outer halo — same wedge, blurred, sits just outside the pill.
   Sells the glow as emissive instead of a flat outline. */
.signup__field::after {
  content: "";
  position: absolute;
  inset: -8px;
  border-radius: inherit;
  background: conic-gradient(
    from var(--glow-angle),
    rgba(255, 255, 255, 0.85) 0deg,
    rgba(255, 255, 255, 0.35) 14deg,
    transparent 50deg,
    transparent 360deg
  );
  filter: blur(14px);
  opacity: 0.55;
  pointer-events: none;
  z-index: 0;
  animation: signup-orbit 4.2s linear infinite;
}

/* The 1px ring itself. The double-mask is the canonical
   "gradient border" trick: two opaque masks (full-area and
   content-box), composite EXCLUDE keeps only the padding region. */
.signup__field::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: conic-gradient(
    from var(--glow-angle),
    rgba(255, 255, 255, 1) 0deg,
    rgba(255, 255, 255, 0.55) 10deg,
    transparent 38deg,
    transparent 360deg
  );
  -webkit-mask: linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
  z-index: 1;
  animation: signup-orbit 4.2s linear infinite;
}

@keyframes signup-orbit {
  to {
    --glow-angle: 360deg;
  }
}

/* Speed the orbit up while the field has focus — small reward for
   engaging with it, also signals "you're in". */
.signup__field:focus-within::before,
.signup__field:focus-within::after {
  animation-duration: 2.2s;
}

.signup__input,
.signup__submit {
  position: relative;
  z-index: 2;
  background: transparent;
  border: none;
  outline: none;
  color: #f6f8fc;
  font-family: "Geist Mono", ui-monospace, "JetBrains Mono", Consolas,
    monospace;
}

.signup__input {
  flex: 1;
  min-width: 0;
  font-size: 14px;
  letter-spacing: 2px;
  padding: 16px 4px 16px 22px;
  border-radius: 999px 0 0 999px;
}

.signup__input::placeholder {
  color: rgba(246, 248, 252, 0.28);
  letter-spacing: 1.5px;
}

.signup__input::selection {
  background: rgba(255, 255, 255, 0.25);
}

.signup__submit {
  font-size: 18px;
  color: rgba(255, 255, 255, 0.85);
  padding: 0 22px;
  cursor: pointer;
  border-radius: 0 999px 999px 0;
  transition: color 160ms ease, transform 160ms ease;
}

.signup__submit:hover {
  color: rgb(255, 255, 255);
  transform: translateX(2px);
}

.signup__submit:active {
  transform: translateX(0);
}

.signup__submit:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  transform: none;
}

.signup__status {
  font-family: "Geist Mono", ui-monospace, "JetBrains Mono", Consolas,
    monospace;
  font-size: 11px;
  letter-spacing: 2px;
  color: rgba(246, 248, 252, 0.55);
  min-height: 1.4em;
  margin: 0;
}

.signup__status.is-error {
  color: rgba(255, 110, 130, 0.9);
}

.signup__status.is-success {
  color: rgba(255, 255, 255, 0.9);
}

/* Reduced-motion honoured the same way as the wordmark glitch:
   freeze the gradient at angle 0 — the field still reads as a
   glowing pill, just static. */
@media (prefers-reduced-motion: reduce) {
  .signup__field::before,
  .signup__field::after {
    animation: none;
  }
}

@media (max-width: 600px) {
  .wordmark {
    letter-spacing: 2px;
  }
  main {
    padding: 6vh 5vw 6vh;
  }
  .signup__input {
    font-size: 13px;
    padding: 14px 4px 14px 18px;
  }
  .signup__submit {
    padding: 0 18px;
  }
}

/* ───────── Sign-in pill + glass dialog ───────── */

/* The pill in the top-right corner. Uses the same conic-gradient
   ring trick as .signup__field below, but at a smaller, denser
   scale so the orbiting wedge reads as a quicker pulse — the pill
   is small enough that a slow orbit would feel sluggish. Sits at
   z-index 30 so it stays above the parallax sky (z=10) without
   competing with the dialog itself (z=100). */
/* Header pills — Timeline + About sit to the left of the login pill
   on the splash. Same fixed-top placement so all three pills read
   as a top-right nav cluster. Less ornament than the login pill
   (no orbiting halo) so they stay secondary affordances.
   .timeline-pill--about positions the About variant further left
   so it doesn't collide with the Timeline pill. */
.timeline-pill {
  position: fixed;
  top: 22px;
  right: 156px;
  z-index: 30;

  display: inline-flex;
  align-items: center;
  padding: 10px 18px;
  background: rgba(10, 13, 18, 0.5);
  border: 0;
  border-radius: 999px;
  color: rgba(246, 248, 252, 0.92);
  text-decoration: none;
  font-family: "Geist Mono", ui-monospace, "JetBrains Mono", Consolas,
    monospace;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 3px;
  text-transform: uppercase;
  cursor: pointer;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: transform 160ms ease, background 160ms ease;
}
.timeline-pill:hover {
  background: rgba(20, 24, 32, 0.85);
  transform: translateY(-1px);
}
/* About variant — same .timeline-pill skin, positioned further
   left so it sits next to the Timeline pill without overlapping. */
.timeline-pill--about {
  right: 270px;
}
@media (max-width: 480px) {
  /* On narrow viewports, stack pills vertically to keep tap targets
     finger-friendly. The login pill stays anchored top-right; the
     other pills drop below it. */
  .timeline-pill {
    right: 22px;
    top: 70px;
  }
  .timeline-pill--about {
    right: 22px;
    top: 116px;
  }
}

.login-pill {
  position: fixed;
  top: 22px;
  right: 22px;
  z-index: 30;

  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px 18px;
  background: rgba(10, 13, 18, 0.65);
  border: 0;
  border-radius: 999px;
  color: #f6f8fc;
  font-family: "Geist Mono", ui-monospace, "JetBrains Mono", Consolas,
    monospace;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 3px;
  text-transform: uppercase;
  cursor: pointer;
  isolation: isolate;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: transform 160ms ease, background 160ms ease;
}
.login-pill:hover {
  background: rgba(10, 13, 18, 0.85);
  transform: translateY(-1px);
}
.login-pill__arrow {
  display: inline-block;
  font-size: 14px;
  font-weight: 600;
  transition: transform 160ms ease;
}
.login-pill:hover .login-pill__arrow {
  transform: translateX(3px);
}

/* Outer halo — same conic wedge as .signup__field::after, smaller
   blur so the bloom feels concentrated around the pill rather than
   diffuse like a glow on a bigger element. */
.login-pill::after {
  content: "";
  position: absolute;
  inset: -6px;
  border-radius: inherit;
  background: conic-gradient(
    from var(--glow-angle),
    rgba(255, 255, 255, 0.85) 0deg,
    rgba(255, 255, 255, 0.35) 14deg,
    transparent 50deg,
    transparent 360deg
  );
  filter: blur(10px);
  opacity: 0.5;
  pointer-events: none;
  z-index: -1;
  animation: signup-orbit 4.2s linear infinite;
}
/* The 1px ring — same double-mask gradient-border trick as the
   newsletter pill so the two elements feel like siblings. */
.login-pill::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: conic-gradient(
    from var(--glow-angle),
    rgba(255, 255, 255, 1) 0deg,
    rgba(255, 255, 255, 0.55) 10deg,
    transparent 38deg,
    transparent 360deg
  );
  -webkit-mask: linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
  z-index: 1;
  animation: signup-orbit 4.2s linear infinite;
}

/* Native <dialog>. Reset the user-agent box, paint our own backdrop
   pseudo-element with backdrop-filter so the planet/stars stay
   visible under a frosted layer. */
.login-dialog {
  border: 0;
  padding: 0;
  background: transparent;
  color: #f6f8fc;
  max-width: none;
  max-height: none;
  width: 100vw;
  height: 100vh;
  inset: 0;
  margin: 0;
  z-index: 100;
}
.login-dialog::backdrop {
  background: rgba(2, 4, 9, 0.45);
  backdrop-filter: blur(14px) saturate(1.1);
  -webkit-backdrop-filter: blur(14px) saturate(1.1);
}
.login-dialog[open] {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* The actual card. backdrop-filter inside the card too — combined
   with the dialog's ::backdrop the planet bleeds through with two
   layers of blur for a real "frosted pane on top of a frosted wall"
   feel. The cyan hairline border keeps it console-themed. */
.login-card {
  position: relative;
  width: min(420px, 92vw);
  padding: 36px 32px 28px;
  background: rgba(10, 14, 22, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 18px;
  backdrop-filter: blur(28px) saturate(1.4);
  -webkit-backdrop-filter: blur(28px) saturate(1.4);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.06) inset,
    0 24px 64px rgba(0, 0, 0, 0.55),
    0 0 0 1px rgba(90, 185, 255, 0.08);
  display: flex;
  flex-direction: column;
  gap: 14px;
  /* Glossy top-edge highlight — pseudo-elements paint a faint
     diagonal sheen so the card reads as glass under light. */
  overflow: hidden;
  animation: login-card-in 220ms ease-out both;
}
.login-card::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.12) 0%,
    rgba(255, 255, 255, 0) 35%,
    rgba(255, 255, 255, 0) 65%,
    rgba(255, 255, 255, 0.06) 100%
  );
  pointer-events: none;
  border-radius: inherit;
}
@keyframes login-card-in {
  from {
    opacity: 0;
    transform: translateY(8px) scale(0.985);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.login-card__close {
  position: absolute;
  top: 12px;
  right: 14px;
  background: transparent;
  border: 0;
  color: rgba(246, 248, 252, 0.55);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  transition: color 120ms ease;
}
.login-card__close:hover {
  color: #f6f8fc;
}

.login-card__title {
  font-family: "GeistPixel Circle", ui-monospace, monospace;
  font-weight: 500;
  font-size: 24px;
  letter-spacing: 3px;
  margin: 0 0 0 4px;
  color: #f6f8fc;
  text-shadow: 0 0 18px rgba(255, 255, 255, 0.18),
    0 0 48px rgba(180, 200, 255, 0.08);
}
.login-card__hint {
  margin: 0 0 6px 4px;
  font-family: "Geist Mono", monospace;
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: rgba(246, 248, 252, 0.5);
}
.login-card__field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.login-card__label {
  font-family: "Geist Mono", monospace;
  font-size: 10px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: rgba(246, 248, 252, 0.6);
  margin-left: 4px;
}
.login-card__field input {
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: #f6f8fc;
  padding: 12px 14px;
  font-family: "Geist Mono", monospace;
  font-size: 14px;
  letter-spacing: 1.5px;
  border-radius: 10px;
  outline: none;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}
.login-card__field input::placeholder {
  color: rgba(246, 248, 252, 0.3);
}
.login-card__field input:focus {
  border-color: rgba(255, 255, 255, 0.4);
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.08);
}
.login-card__submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: 6px;
  padding: 13px 22px;
  background: rgba(255, 255, 255, 0.92);
  color: #061427;
  border: 0;
  border-radius: 999px;
  font-family: "Geist Mono", monospace;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 3px;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 120ms ease, transform 120ms ease;
}
.login-card__submit:hover {
  background: #ffffff;
  transform: translateY(-1px);
}
.login-card__submit-arrow {
  font-size: 14px;
  transition: transform 120ms ease;
}
.login-card__submit:hover .login-card__submit-arrow {
  transform: translateX(3px);
}
.login-card__status {
  min-height: 1.4em;
  margin: 0 0 0 4px;
  font-family: "Geist Mono", monospace;
  font-size: 11px;
  letter-spacing: 1.5px;
  color: rgba(246, 248, 252, 0.6);
}

@media (max-width: 520px) {
  .login-pill {
    top: 14px;
    right: 14px;
    padding: 8px 14px;
    font-size: 11px;
    letter-spacing: 2px;
  }
  .login-card {
    padding: 28px 22px 22px;
    border-radius: 14px;
  }
  .login-card__title {
    font-size: 20px;
  }
}
