/* Parked-domain page.
 *
 * Committed to a dark palette rather than following the visitor's theme: the
 * WebGL scene behind the type is lit for a dark ground, and a light variant
 * would need a second scene, not a second colour set.
 *
 * No @font-face and no external stylesheet, so the Content-Security-Policy
 * stays at 'self' for both script and style with nothing inline.
 */

:root {
  --ink: #05070f;
  --ink-soft: #0a0f1e;
  --text: #e7ecf5;
  --muted: #7c8aa5;
  --accent: #38bdf8;
  --accent-2: #a78bfa;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
}

body {
  background: var(--ink);
  color: var(--text);
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}

/* The canvas is fixed and behind everything. Sized in JS, not CSS, because the
 * drawing buffer and the layout box have to agree or the scene renders blurry. */
#scene {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 0;
}

/* Fallback ground when WebGL is unavailable or fails to initialise. The page
 * must still look deliberate on a locked-down browser or a GPU-less client. */
body.no-webgl {
  background:
    radial-gradient(120% 90% at 50% 0%, #14224a 0%, transparent 60%),
    radial-gradient(100% 80% at 80% 100%, #2a1a4a 0%, transparent 55%),
    var(--ink);
}
body.no-webgl #scene { display: none; }

/* Two jobs, deliberately separated.
 *
 * The outer vignette darkens the frame edges. It is far gentler than the first
 * version, which used 0.55 alpha at 70% and 0.9 at the edge -- that flattened
 * the whole scene to near-black and wasted the starfield behind it.
 *
 * The scrim is a tight pool directly behind the type. Legibility over a moving
 * wireframe needs contrast exactly where the words are, not everywhere; doing it
 * with one big gradient is what forced the first version to be so heavy. */
.vignette {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(38% 26% at 50% 50%,
      rgba(5, 7, 15, 0.72) 0%, rgba(5, 7, 15, 0.45) 55%, transparent 100%),
    radial-gradient(85% 70% at 50% 45%,
      transparent 40%, rgba(5, 7, 15, 0.35) 82%, rgba(5, 7, 15, 0.7) 100%);
}

/* A narrow viewport wraps a long hostname onto three lines, and the scrim above
 * is sized for the one-line desktop case -- so the top and bottom of the text
 * block sit outside it, over the densest part of the wireframe. Widen and
 * heighten the pool rather than darkening it: the goal is coverage of the text,
 * not more ink. */
@media (max-width: 700px) {
  .vignette {
    background:
      radial-gradient(74% 34% at 50% 50%,
        rgba(5, 7, 15, 0.76) 0%, rgba(5, 7, 15, 0.5) 60%, transparent 100%),
      radial-gradient(110% 80% at 50% 45%,
        transparent 45%, rgba(5, 7, 15, 0.3) 85%, rgba(5, 7, 15, 0.6) 100%);
  }
}

main {
  position: relative;
  z-index: 2;
  min-height: 100vh;
  min-height: 100dvh; /* dvh keeps it centred when mobile browser chrome moves */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.9rem;
  padding: 2rem 1.5rem;
  text-align: center;
}

.eyebrow {
  margin: 0;
  font-size: clamp(0.66rem, 1.6vw, 0.78rem);
  font-weight: 500;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--muted);
}

h1 {
  margin: 0;
  /* clamp so a 6-character domain and a 30-character one both sit well without
   * a media query, and neither overflows a narrow phone. */
  font-size: clamp(1.85rem, 8vw, 5rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.05;
  /* Long domains break rather than overflowing the viewport. */
  overflow-wrap: anywhere;
  max-width: 22ch;
  background: linear-gradient(100deg, var(--text) 10%, var(--accent) 55%, var(--accent-2) 95%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* A gradient clipped to text is invisible if the clip is unsupported. Restore a
 * solid colour when background-clip: text is not available. */
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  h1 { color: var(--text); background: none; }
}

.tagline {
  margin: 0.2rem 0 0;
  max-width: 46ch;
  font-size: clamp(0.94rem, 2.1vw, 1.05rem);
  line-height: 1.6;
  color: var(--muted);
}

.contact { margin: 1.4rem 0 0; font-size: 0.92rem; }
.contact a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid rgba(56, 189, 248, 0.3);
  padding-bottom: 1px;
}
.contact a:hover, .contact a:focus-visible { border-bottom-color: var(--accent); }

/* Fade the type in once, so the page does not flash unstyled text before the
 * hostname is written into it. */
main > * {
  animation: rise 900ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}
main > :nth-child(2) { animation-delay: 90ms; }
main > :nth-child(3) { animation-delay: 180ms; }
main > :nth-child(4) { animation-delay: 260ms; }

@keyframes rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* Honour the setting rather than merely shortening the animation: the entrance
 * and the scene motion both stop. app.js checks the same query and renders a
 * single still frame. */
@media (prefers-reduced-motion: reduce) {
  main > * { animation: none; }
}
