/* ==========================================================================
   Permit Approve — permitapprove.com
   Header replicated to goldsand.fi's exact proportions (1440px reference):
   serif headline 48px/1.05/-0.02em, grey wordmark logo, warm-beige pill,
   two-pill CTA (light input + black button, 48px tall). Warm-neutral palette.
   ========================================================================== */

:root {
  --bg:         #ffffff;   /* goldsand: pure white */
  --bg-2:       #f5f4f1;
  --ink:        #121111;   /* warm near-black */
  --ink-soft:   #4a4744;   /* subhead */
  --muted:      #616161;   /* logo / quiet text */
  --muted-2:    #8a8783;
  --pill-bg:    #edebe7;   /* warm beige pill */
  --field-bg:   #f5f5f5;   /* input pill */
  --accent:     #111111;   /* button */
  --accent-ink: #ffffff;
  --line:       rgba(18, 17, 17, 0.10);

  --font-serif: "Fraunces", Georgia, "Times New Roman", serif;
  --font-sans:  "General Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono:  "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; overflow-x: hidden; }
body {
  font-family: var(--font-sans);
  color: var(--ink);
  background: var(--bg);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
a { color: inherit; }

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

/* ============ NAV — centered grey wordmark (no icon, like goldsand) ============
   Absolute, not fixed: the logo scrolls away with the hero. */
.nav {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.75rem 1.5rem;
}
.logo { display: inline-flex; align-items: center; gap: 0.5rem; text-decoration: none; }
/* Horizontal logo lockup (mark + wordmark) as one transparent PNG. Fixed height, width auto from the
   1827×452 intrinsic ratio (the width/height attrs on the <img> reserve space so there's no layout shift). */
.logo-img { display: block; height: 64px; width: auto; }
.logo-mark { display: block; flex-shrink: 0; }
.logo-name {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 1rem;          /* 16px */
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: #1d1b19;
}

/* ============ HERO — centered, goldsand proportions ============ */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  text-align: center;
  padding: 8.25rem 1.5rem 4rem;   /* hero content top offset (5.5rem base, nudged +44px down) */
  background: transparent;
  z-index: 2;
}
.hero-inner { width: 100%; max-width: 640px; }

.dot { color: #62626266; margin: 0 0.4em; }

h1 {
  font-family: var(--font-serif);
  font-optical-sizing: auto;
  font-weight: 450;
  font-size: 3rem;   /* FIXED 48px on desktop — never width-scales, so the hero block height (and the
                        planet's position relative to it) stays put as the window resizes. Mobile
                        breakpoint sets its own size below. */
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--ink);
  max-width: 600px;
  margin: 0 auto;
}

.sub {
  margin: 0.85rem auto 0;
  max-width: 420px;
  font-size: clamp(1rem, 1.3vw, 1.125rem);  /* ~18px */
  font-weight: 500;
  color: #626262;
  line-height: 1.45;
}

/* ============ CTA — two pills: light input + black button ============ */
.signup { display: flex; justify-content: center; margin: 2.4rem 0 0; }
.field-group {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  max-width: 420px;
}
.field-group input[type="email"] {
  flex: 1 1 auto;
  min-width: 0;
  height: 48px;
  border: 1px solid rgba(18, 17, 17, 0.12);
  background: #f1efea;                     /* warm beige (a touch lighter than the old pill) */
  border-radius: 999px;
  padding: 0 20px;
  font-family: var(--font-sans);
  font-size: 0.95rem;
  color: var(--ink);
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.field-group input[type="email"]:focus { outline: none; border-color: rgba(18, 17, 17, 0.42); box-shadow: 0 0 0 2px rgba(18, 17, 17, 0.10); }
.field-group input[type="email"]::placeholder { color: var(--muted-2); font-weight: 500; }
.btn {
  flex: 0 0 auto;
  height: 48px;
  font-family: var(--font-sans);
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--accent-ink);
  background: var(--accent);
  border: none;
  border-radius: 999px;
  padding: 0 22px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.18s ease, transform 0.18s ease;
}
.btn:hover { background: #2a2a2a; }
.btn:active { transform: translateY(1px); }

/* ============ MICROCOPY (single grey line, goldsand-style) ============ */
.microcopy {
  margin: 1.25rem auto 0;        /* ~4px closer to the input than before */
  font-size: 0.875rem;        /* 14px, matching goldsand */
  font-weight: 500;
  color: #62626280;           /* #626262 @ 50% */
}
.globe-noscript { margin: 1.4rem auto 0; max-width: 460px; color: var(--muted); font-size: 0.95rem; }

/* ============ PLANET (prototype) — fixed globe, top anchored below the content ============
   JS sets translateY so the globe's TOP edge sits a fixed gap below the hero content
   and never rises into it (clamped). Default keeps it low until JS runs. */
.globe-pin {
  position: fixed;
  top: 0;
  left: 50%;
  /* --earth scales the canvas (and therefore the planet's on-screen size). COVER-keyed to the LARGER
     viewport axis (vmax = max(vw,vh)), NOT height alone. The disc radius is R ∝ canvasHeight ∝ --earth,
     so keying to height made the disc's WIDTH fill depend on aspect: a wide window saw ~84% of the
     disc width (globe limb + ocean creeping in, America small), a tall window only ~43% (America
     filling the frame). vmax makes the disc cover the frame by the same ratio on whichever axis binds,
     so landscape frames like portrait. The script's vertical placement is now anchored on AMERICA's
     real on-screen latitude (not the disc centre), so the bigger wide-screen disc doesn't drag the
     country off-position. Must stay in lock-step with measure(): D = min(1.65·max(vw,vh), 2400). Cap
     4500px covers a maximised 2560-wide screen; GPU memory is bounded by MAX_BACKING in the script
     (it clamps the WebGL pixelRatio), NOT by this cap, so cover-keying holds across real windows. */
  --earth: min(165vmax, 4500px);
  --pad: calc(var(--earth) * 0.40);
  height: calc(var(--earth) + var(--pad) * 2);
  width:  max(calc(var(--earth) + var(--pad) * 2), 112vw);
  z-index: 1;
  pointer-events: none;
  transform: translate(-50%, 80vh);
  will-change: transform, opacity;
}
.globe-pin #globe, .globe-pin canvas { width: 100% !important; height: 100% !important; display: block; }
/* canvas on top of the halo; the WebGL canvas is transparent except the planet, so the halo shows
   through around the disc. */
.globe-pin #globe { position: relative; z-index: 1; }

/* Soft atmosphere halo — a CSS radial-gradient that lives BEHIND the WebGL canvas (globe.gl's own
   showAtmosphere is off). JS sizes it every frame to 3× the planet's on-screen radius, so the disc
   rim lands at ~1/1.5 = 67% of this circle's radius. No hard rim: the glow peaks just outside the
   disc and fades to nothing by the circle edge, so where it runs past the screen edge the fall-off
   is already ~0 — the old left/right "glow cut-off" is gone. Tune the rgba peak/stops to taste. */
.globe-halo {
  position: absolute;
  top: 50%; left: 50%;
  width: 10px; height: 10px;       /* placeholder — JS overwrites width/height each frame */
  transform: translate(-50%, -50%);
  border-radius: 50%;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(circle closest-side,
    rgba(186, 200, 219, 0)    58%,
    rgba(186, 200, 219, 0.30) 68%,
    rgba(186, 200, 219, 0.12) 82%,
    rgba(186, 200, 219, 0)    100%);
}

/* ============ GLOBE SPEECH BUBBLES (sprite-people popups) ============
   globe.gl positions .globe-bubble (CSS2D) centered on the city point; the card sits ABOVE the
   figure with a downward tail. Card opacity is driven per scroll-frame by the choreography (no CSS
   transition — it would lag the per-frame updates). Far-side hiding is globe.gl's job (it toggles
   visibility on .globe-bubble). Non-interactive for now — hover/click is deferred. */
.globe-bubble { position: relative; pointer-events: none; }
/* the little standing person, anchored on the city point (feet at the point, growing up).
   Pure CSS — head + torso as pseudo-elements on a plain div — so it always paints (no SVG/namespace
   pitfalls). currentColor sets both shapes; --live/--cold tint it. JS drives opacity per beat. */
.globe-person {
  position: absolute;
  left: 50%;
  bottom: 2px;
  transform: translateX(-50%);
  width: 18px; height: 30px;
  opacity: 0;                   /* JS animates per beat */
  filter: drop-shadow(0 1px 2px rgba(18, 17, 17, 0.35));
}
.globe-person::before {         /* head */
  content: "";
  position: absolute;
  top: 0; left: 50%;
  transform: translateX(-50%);
  width: 10px; height: 10px;
  border-radius: 50%;
  background: currentColor;
}
.globe-person::after {          /* torso */
  content: "";
  position: absolute;
  bottom: 0; left: 50%;
  transform: translateX(-50%);
  width: 18px; height: 18px;
  border-radius: 9px 9px 5px 5px;
  background: currentColor;
}
.globe-person--live { color: #0050bf; }
.globe-person--cold { color: #aab0b8; }
.globe-bubble-card {
  position: absolute;
  left: 50%;
  bottom: 38px;                 /* clears the person's head; tail points down to the figure */
  transform: translateX(-50%);
  white-space: nowrap;
  background: #fffdf9;          /* warm near-white, matches the palette */
  border: 1px solid rgba(18, 17, 17, 0.12);
  box-shadow: 0 6px 20px rgba(18, 17, 17, 0.10);
  border-radius: 12px;
  padding: 7px 12px;
  font-family: var(--font-sans);
  font-size: 0.8rem;            /* ~13px */
  font-weight: 500;
  line-height: 1.25;
  color: var(--ink);
  opacity: 0;                   /* JS animates per beat */
}
.globe-bubble-card::after {     /* tail pointing down toward the figure */
  content: "";
  position: absolute;
  left: 50%;
  bottom: -5px;
  width: 10px; height: 10px;
  transform: translateX(-50%) rotate(45deg);
  background: #fffdf9;
  border-right: 1px solid rgba(18, 17, 17, 0.12);
  border-bottom: 1px solid rgba(18, 17, 17, 0.12);
}
@media (max-width: 540px) {
  /* smaller, tighter bubbles + figures on phones (JS also caps to one bubble at a time) */
  .globe-person { width: 14px; height: 23px; }
  .globe-person::before { width: 8px; height: 8px; }
  .globe-person::after  { width: 14px; height: 14px; }
  .globe-bubble-card { font-size: 0.72rem; padding: 6px 10px; bottom: 30px; }
}

/* Scroll spacer: room for two heading beats, the planet advance, then the long, gentle
   explore opening (CENTER_END ~4.0vh) plus a dwell before the footer fade. */
.planet-scene { position: relative; height: 440vh; z-index: 2; pointer-events: none; }

/* Stat that flies up from behind the planet and settles as the top heading.
   Position / opacity / blur are driven by JS on scroll (default hidden). */
.stat-fly {
  position: fixed;
  top: 0;
  left: 50%;
  z-index: 0;                 /* starts BEHIND the globe (z 1); JS flips it to 4 once it clears the apex */
  width: 100%;
  max-width: 600px;
  padding: 0 1.5rem;
  text-align: center;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, 64vh);
  will-change: transform, opacity, filter;
}
.stat-line {
  font-family: var(--font-serif);
  font-optical-sizing: auto;
  font-weight: 450;
  font-size: clamp(1.4rem, 2.7vw, 2.1rem);
  line-height: 1.12;
  letter-spacing: -0.02em;
  color: var(--ink);
}

/* ============ FOOTER (kept; restyled next pass) ============ */
.site-footer {
  position: relative;
  z-index: 3;
  background: var(--bg-2);
  border-top: 1px solid var(--line);
  padding: clamp(4rem, 9vw, 7rem) 1.5rem clamp(2.5rem, 5vw, 4rem);
}
.footer-inner { max-width: 560px; margin: 0 auto; text-align: center; }
.site-footer h2 {
  font-family: var(--font-serif);
  font-optical-sizing: auto;
  font-weight: 560;
  font-size: clamp(1.8rem, 4vw, 2.4rem);
  line-height: 1.08;
  letter-spacing: -0.02em;
}
.footer-sub { margin-top: 0.7rem; color: var(--ink-soft); font-size: 1rem; }
.site-footer .signup { margin-top: 1.6rem; }
.footer-note { margin-top: 1.1rem; font-size: 0.85rem; color: var(--muted); }

.fine-print {
  margin-top: 3.5rem;
  padding-top: 1.8rem;
  border-top: 1px solid var(--line);
  text-align: left;
  color: var(--muted);
  font-size: 0.8rem;
  line-height: 1.55;
}
.fine-print p { margin-bottom: 0.7rem; }
.fine-print a { color: var(--ink-soft); }
.fine-row {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 1.2rem;
  color: var(--ink-soft);
}
.logo-name { display: inline; }

/* ============ BOTTOM PROGRESSIVE BLUR ============
   A stack of backdrop-filter layers, each with more blur and a mask band shifted lower, so the
   blur RAMPS smoothly from ~0 at the top of the strip to heavy at the bottom edge — no hard line
   where blurred meets sharp (the layered progressive-blur technique). */
.bottom-blur {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  height: 120px;
  z-index: 40;
  pointer-events: none;
}
.bottom-blur > div { position: absolute; inset: 0; }
.bottom-blur > div:nth-child(1) { -webkit-backdrop-filter: blur(0.5px); backdrop-filter: blur(0.5px);
  -webkit-mask: linear-gradient(to bottom, transparent 0%,    #000 16.7%, #000 33.3%, transparent 50%);
          mask: linear-gradient(to bottom, transparent 0%,    #000 16.7%, #000 33.3%, transparent 50%); }
.bottom-blur > div:nth-child(2) { -webkit-backdrop-filter: blur(1px);   backdrop-filter: blur(1px);
  -webkit-mask: linear-gradient(to bottom, transparent 16.7%, #000 33.3%, #000 50%,   transparent 66.7%);
          mask: linear-gradient(to bottom, transparent 16.7%, #000 33.3%, #000 50%,   transparent 66.7%); }
.bottom-blur > div:nth-child(3) { -webkit-backdrop-filter: blur(2px);   backdrop-filter: blur(2px);
  -webkit-mask: linear-gradient(to bottom, transparent 33.3%, #000 50%,   #000 66.7%, transparent 83.3%);
          mask: linear-gradient(to bottom, transparent 33.3%, #000 50%,   #000 66.7%, transparent 83.3%); }
.bottom-blur > div:nth-child(4) { -webkit-backdrop-filter: blur(4px);   backdrop-filter: blur(4px);
  -webkit-mask: linear-gradient(to bottom, transparent 50%,   #000 66.7%, #000 83.3%, transparent 100%);
          mask: linear-gradient(to bottom, transparent 50%,   #000 66.7%, #000 83.3%, transparent 100%); }
.bottom-blur > div:nth-child(5) { -webkit-backdrop-filter: blur(8px);   backdrop-filter: blur(8px);
  -webkit-mask: linear-gradient(to bottom, transparent 66.7%, #000 83.3%, #000 100%);
          mask: linear-gradient(to bottom, transparent 66.7%, #000 83.3%, #000 100%); }
.bottom-blur > div:nth-child(6) { -webkit-backdrop-filter: blur(16px);  backdrop-filter: blur(16px);
  -webkit-mask: linear-gradient(to bottom, transparent 83.3%, #000 100%);
          mask: linear-gradient(to bottom, transparent 83.3%, #000 100%); }

/* ============ RESPONSIVE ============ */
@media (max-width: 540px) {
  .nav { padding: 1.4rem 1.3rem; }
  .hero { padding: 4.5rem 1.3rem 8rem; }
  h1 { font-size: clamp(2rem, 9vw, 2.5rem); }
  .sub { font-size: 1.05rem; }
  .field-group { flex-direction: column; gap: 10px; }
  .field-group input[type="email"] { width: 100%; }
  .btn { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .planet-scene { height: 70vh; }
}
