/* Vendored Archivo (latin subset, 700/800/900) — the condensed,
   heavy display voice. Self-hosted, no CDN. font-display:swap so the
   system fallback paints instantly and Archivo swaps in when ready. */
@font-face {
  font-family: "Archivo"; font-style: normal; font-weight: 700;
  font-display: swap;
  src: url("/static/landing/fonts/archivo-700.woff2") format("woff2");
}
@font-face {
  font-family: "Archivo"; font-style: normal; font-weight: 800;
  font-display: swap;
  src: url("/static/landing/fonts/archivo-800.woff2") format("woff2");
}
@font-face {
  font-family: "Archivo"; font-style: normal; font-weight: 900;
  font-display: swap;
  src: url("/static/landing/fonts/archivo-900.woff2") format("woff2");
}

/* ============================================================
   VMWG — landing page ("Nachtbau" design system, phase 1)
   Raw, dark, isometric, Gotham-at-night. Monochrome concrete +
   one indigo accent; green/red only ever as data. Beveled, never
   rounded — the inverse of the app's squircle grid (the product is
   soft/usable; the frontage is hard/raw).
   ============================================================ */

:root {
  /* DARK (default; also data-theme="dark") — "Nachtbau", Gotham-at-night */
  --void: #0a0a0b;
  --concrete: #16161a;
  --rebar: #27272a;
  --smoke: #71717a;
  --bone: #fafafa;
  --signal: #4f46e5;
  --signal-bright: #6d64f0;
  --on-signal: #fafafa;            /* text on the indigo button — light in both themes */
  --under: #16a34a;
  --over: #dc2626;
  --hair: rgba(255, 255, 255, .06);  /* blueprint grid — visible on the void */
  --grain: .035;                     /* film-grain opacity */
  --void-0: rgba(10, 10, 11, 0);     /* transparent void — same RGB, for clean fades */

  /* 'Archivo' used if vendored/installed; otherwise a condensed
     system fallback so the display voice stays narrow + heavy
     without a CDN web-font. */
  --display: "Archivo", "Arial Narrow", "Helvetica Neue", system-ui, sans-serif;
  --mono: ui-monospace, "JetBrains Mono", "SF Mono", Menlo, monospace;
}

/* LIGHT ("Tagbau") — raw concrete in daylight / blueprint on paper.
   Same indigo accent; green/red stay data-only. Selected via the
   data-theme attribute the head script sets (system pref or saved
   choice) and the top-bar toggle flips. */
:root[data-theme="light"] {
  --void: #f1f1f4;
  --concrete: #ffffff;
  --rebar: #d4d4d8;
  --smoke: #52525b;
  --bone: #18181b;
  --signal: #4f46e5;
  --signal-bright: #4f46e5;
  --under: #15803d;
  --over: #c2261d;
  --hair: rgba(24, 24, 27, .05);
  --grain: .02;
  --void-0: rgba(241, 241, 244, 0);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--void);
  color: var(--bone);
  font-family: var(--mono);
  -webkit-font-smoothing: antialiased;
  scroll-behavior: smooth;
  transition: background-color .35s ease, color .35s ease;
}

/* Film grain + faint blueprint grid over the whole page. The grain
   is a tiled SVG noise data-URI at low opacity; the grid is two
   repeating-linear-gradients on the iso diagonal. Both pointer-
   events:none so they never eat clicks. */
body::before {
  content: "";
  position: fixed; inset: 0; z-index: 1; pointer-events: none;
  background-image:
    repeating-linear-gradient(30deg,  var(--hair) 0 1px, transparent 1px 80px),
    repeating-linear-gradient(-30deg, var(--hair) 0 1px, transparent 1px 80px);
}
body::after {
  content: "";
  position: fixed; inset: 0; z-index: 2; pointer-events: none; opacity: var(--grain);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

.wrap { position: relative; z-index: 3; }

/* ---------- top bar ---------- */
.vmwg-top {
  position: absolute; top: 0; left: 0; right: 0; z-index: 10;
  display: flex; align-items: center; justify-content: space-between;
  padding: 22px 28px;
}
.vmwg-logo { display: flex; align-items: center; gap: 10px; }
.vmwg-logo svg { width: 26px; height: 30px; display: block; }
.vmwg-logo .word {
  font-family: var(--display);
  font-weight: 800; font-size: 22px; letter-spacing: .04em;
  text-transform: uppercase;
}
.vmwg-top .controls { display: flex; align-items: center; gap: 12px; }
.vmwg-top .signin {
  font-family: var(--mono); font-size: 13px; color: var(--smoke);
  text-decoration: none; border: 1px solid var(--rebar);
  padding: 8px 14px; transition: color .15s, border-color .15s;
}
.vmwg-top .signin:hover { color: var(--bone); border-color: var(--smoke); }

/* light/dark toggle — shows the icon for the theme you'll switch TO */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 34px; padding: 0; cursor: pointer;
  background: transparent; color: var(--smoke); border: 1px solid var(--rebar);
  transition: color .15s, border-color .15s;
}
.theme-toggle:hover { color: var(--bone); border-color: var(--smoke); }
.theme-toggle svg { width: 16px; height: 16px; display: block; }
.theme-toggle .i-sun  { display: block; }   /* dark mode → offer sun (go light) */
.theme-toggle .i-moon { display: none; }
:root[data-theme="light"] .theme-toggle .i-sun  { display: none; }
:root[data-theme="light"] .theme-toggle .i-moon { display: block; }  /* light mode → offer moon */

/* ---------- hero: split layout — copy LEFT, extruded kiez RIGHT ---------- */
.hero {
  position: relative; min-height: 100vh;
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  align-items: center; gap: 40px;
  padding: 96px 48px 64px;
  overflow: hidden;
}
.hero-copy { position: relative; z-index: 2; order: 1; max-width: 600px; }

/* right column: the 3D scene / SVG poster stage. The canvas + SVG
   absolutely fill this cell, so the scene lives on the right and never
   bleeds under the copy. */
.hero-stage {
  position: relative; order: 2; align-self: stretch;
  min-height: min(78vh, 760px);
}
.hero-art {
  position: absolute; inset: 0; z-index: 0;
  display: flex; align-items: center; justify-content: center;
  opacity: 0; transform: translateY(18px);
  animation: rise 1.1s cubic-bezier(.16,1,.3,1) .15s forwards;
}
.hero-art svg { width: 100%; height: 100%; object-fit: contain; }
/* the poster is a dark cityscape; smart-invert it for the light page
   (keeps the indigo accents roughly intact). It's only the brief
   first-paint / no-WebGL fallback — the canvas paints the real scene. */
:root[data-theme="light"] .hero-art svg { filter: invert(1) hue-rotate(180deg); }

/* Three.js stage: sits over the SVG poster, hidden until hero.js boots.
   When the canvas is live, <body> gets .canvas-live and we cross-fade:
   SVG out, canvas in. If hero.js never boots (no-WebGL / reduced-motion
   / mobile / JS off), .canvas-live is never added and the SVG stays —
   so the poster IS the fallback. */
.hero-canvas {
  position: absolute; inset: 0; z-index: 1;
  opacity: 0; transition: opacity 1.1s ease .2s;
  pointer-events: none;
}
.hero-canvas canvas { width: 100% !important; height: 100% !important; display: block; }
body.canvas-live .hero-canvas { opacity: 1; }
body.canvas-live .hero-art {
  opacity: 0 !important; animation: none !important;
  transition: opacity .8s ease;
}
/* soft seam: an all-edge vignette fades the scene into the page on every
   side, so the (zoomed, edge-clipped) kiez melts out instead of ending in
   a hard rectangle — and it blends toward the copy whatever the layout.
   var(--void-0) is the transparent-but-same-RGB void, so the fade stays
   clean in light mode (no gray halo). */
.hero-stage::after {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: radial-gradient(125% 120% at 50% 46%,
    var(--void-0) 46%, var(--void) 88%);
}

/* headline + kicker removed per design — the promoted lede carries the
   left column; the logo top-left carries the brand. */
.hero .lede {
  font-family: var(--display); font-weight: 700;
  font-size: clamp(24px, 3.4vw, 42px); line-height: 1.1;
  letter-spacing: -.01em; color: var(--bone);
  max-width: 20ch; margin: 0 0 38px;
}
.hero .cta-row { display: flex; gap: 14px; flex-wrap: wrap; align-items: center; }

/* extruded CTA: hard offset shadow, presses down on hover */
.btn {
  font-family: var(--display); font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; font-size: 14px;
  padding: 14px 22px; border: 0; cursor: pointer; text-decoration: none;
  display: inline-block; transition: transform .1s, box-shadow .1s;
}
.btn-primary {
  background: var(--signal); color: var(--on-signal);
  box-shadow: 5px 5px 0 0 #1e1b4b;
}
.btn-primary:hover { transform: translate(2px, 2px); box-shadow: 3px 3px 0 0 #1e1b4b; }
.btn-primary:active { transform: translate(5px, 5px); box-shadow: 0 0 0 0 #1e1b4b; }
.btn-ghost {
  color: var(--smoke); border: 1px solid var(--rebar); background: transparent;
  font-family: var(--mono); font-weight: 500; letter-spacing: .02em;
}
.btn-ghost:hover { color: var(--bone); border-color: var(--smoke); }

/* ---------- access form ----------
   Inline in the hero, revealed by the Request-access CTA. Lives in the
   left copy column now, so it's left-aligned (not centered). */
.access { max-width: 420px; margin: 2px 0 0; }
.access[hidden] { display: none; }
/* Vertical stack now that the form qualifies the applicant (email +
   intent dropdown + optional reason + submit) rather than just email. */
.access form { display: flex; flex-direction: column; gap: 8px; }
.access input, .access select {
  width: 100%; box-sizing: border-box;
  background: var(--concrete); border: 1px solid var(--rebar); color: var(--bone);
  font-family: var(--mono); font-size: 15px; padding: 13px 15px; outline: none;
}
.access input:focus, .access select:focus { border-color: var(--smoke); }
.access input::placeholder { color: #52525b; }
/* The reason field carries the longest placeholder ("…(optional)"); drop a
   couple px so it isn't clipped at the form's max width. */
.access input[name="reason"] { font-size: 13px; }
/* Native select on the dark concrete: kill the default chrome + draw our
   own caret so the closed control matches the inputs. The empty
   placeholder option shows muted; a real choice shows in --bone. */
.access select {
  appearance: none; -webkit-appearance: none; cursor: pointer; color: #52525b;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' fill='none' stroke='%2352525b' stroke-width='1.5'/></svg>");
  background-repeat: no-repeat; background-position: right 14px center;
  padding-right: 34px;
}
.access select:valid { color: var(--bone); }
.access select option { color: #18181b; }
.access .btn-primary { box-shadow: none; width: 100%; }
.access .msg { min-height: 18px; margin-top: 12px; font-size: 13px; color: var(--smoke); }
.access .msg.ok { color: var(--under); }
.access .msg.err { color: var(--over); }

@keyframes rise { to { opacity: 1; transform: none; } }

/* respect reduced motion: kill the extrude/rise, show end state */
@media (prefers-reduced-motion: reduce) {
  .hero-art { animation: none; opacity: 1; transform: none; }
  html { scroll-behavior: auto; }
  /* belt-and-braces: hero.js already refuses to boot under reduced
     motion, but never reveal the canvas even if .canvas-live leaks in. */
  .hero-canvas { display: none !important; }
  body.canvas-live .hero-art { opacity: 1 !important; }
}

/* below the split breakpoint, stack vertically: copy on top, scene
   below — no clash. Set wide (980px) so the two columns only ever sit
   side-by-side when there's comfortable room; narrower than that the
   2-col gets pinched, so we stack instead (the WebGL scene still boots
   ≥800px and renders full-width below the copy; under 800px the stage
   shows the SVG poster). */
@media (max-width: 980px) {
  .hero {
    grid-template-columns: 1fr;
    align-content: start;            /* pack rows from the top — no mid gap */
    padding: 96px 22px 56px; gap: 24px;
  }
  /* scene ABOVE the copy when stacked (visual-first mobile hero) */
  .hero-stage { order: 1; min-height: 42vh; }
  .hero-copy { order: 2; max-width: none; }
  .hero .lede { max-width: 22ch; }
  .vmwg-top { padding: 16px; }
}
