:root {
  --bg: #04070f;
  --blue: #208bff;
  --blue-soft: #7cc0ff;
  --text: #ffffff;
  --muted: rgba(255, 255, 255, 0.58);
  --faint: rgba(255, 255, 255, 0.34);
  --hair: rgba(255, 255, 255, 0.12);
  --sans: "Inter", system-ui, -apple-system, sans-serif;
  --display: "Space Grotesk", "Inter", system-ui, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, monospace;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
}

body.is-locked {
  overflow: hidden;
  height: 100vh;
}

/* Lenis requirements */
html.lenis,
html.lenis body {
  height: auto;
}
.lenis.lenis-smooth {
  scroll-behavior: auto !important;
}

a {
  color: inherit;
  text-decoration: none;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: #fff;
  color: #000;
  padding: 10px 16px;
}
.skip-link:focus {
  left: 12px;
  top: 12px;
}

/* --------------------------------------------------------------- stage */

.stage {
  position: fixed;
  inset: 0;
  z-index: 1;
  opacity: 0;
  transition: opacity 1.2s ease;
}
.stage.is-ready {
  opacity: 1;
}
#gl {
  display: block;
  width: 100%;
  height: 100%;
}

/* Darkens the frame edges so copy always has contrast to sit on. */
.stage__vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(circle at 50% 45%, rgba(4, 7, 15, 0) 30%, rgba(4, 7, 15, 0.72) 100%),
    linear-gradient(to bottom, rgba(4, 7, 15, 0.75) 0%, rgba(4, 7, 15, 0) 22%);
}

/* ------------------------------------------------------------- preloader */

.preloader {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
  background: var(--bg);
  transition: opacity 0.7s ease;
}
.preloader.is-done {
  opacity: 0;
  pointer-events: none;
}
.preloader__mark img {
  height: 84px;
  width: auto;
  filter: drop-shadow(0 0 26px rgba(32, 139, 255, 0.65));
  animation: pulse 2.6s ease-in-out infinite;
}
@keyframes pulse {
  0%,
  100% {
    opacity: 0.75;
    transform: scale(1);
  }
  50% {
    opacity: 1;
    transform: scale(1.05);
  }
}
.preloader__copy {
  margin: 0;
  text-align: center;
  font-weight: 200;
  font-size: clamp(15px, 2vw, 20px);
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.8);
}
.preloader__track {
  width: min(240px, 50vw);
  height: 1px;
  background: rgba(255, 255, 255, 0.15);
  overflow: hidden;
}
.preloader__track span {
  display: block;
  height: 100%;
  background: var(--blue);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s ease;
}
.preloader__status {
  margin: 0;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--faint);
}

/* ----------------------------------------------------------------- intro */

.intro {
  position: fixed;
  inset: 0;
  z-index: 110;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.8s ease;
  background: radial-gradient(circle at 50% 50%, rgba(4, 7, 15, 0.35) 0%, rgba(4, 7, 15, 0.9) 75%);
}
.intro.is-visible {
  opacity: 1;
  pointer-events: auto;
}
.intro.is-done {
  opacity: 0;
  pointer-events: none;
}
.intro__line {
  margin: 0;
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(30px, 5.6vw, 68px);
  letter-spacing: -0.02em;
  opacity: 0;
  transform: translateY(14px);
  animation: introLine 1.1s ease forwards;
}
.intro__line--1 {
  animation-delay: 0.4s;
}
.intro__line--2 {
  color: var(--blue-soft);
  animation-delay: 2.6s;
}
/* Each line lands and then holds. The couplet used to decay to 0.18 and sit
   there as ghost type over the hero; the overlay's own fade-out is what should
   clear it, so the line animation ends at full strength. */
@keyframes introLine {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.intro__skip {
  position: absolute;
  bottom: 42px;
  background: none;
  border: 0;
  cursor: pointer;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--faint);
  transition: color 0.3s ease;
}
.intro__skip:hover {
  color: #fff;
}

/* The intro is a beat of its own. Its backdrop is deliberately translucent so
   the particle stage still reads through it, which meant scene 01's headline
   and the page chrome sat live underneath the couplet — two blocks of type in
   the same place, reading as one jumbled slide. Everything but the stage stays
   down until the intro clears, then fades up together. */
body.is-intro main,
body.is-intro .chrome,
body.is-intro .counter {
  opacity: 0;
}

/* ---------------------------------------------------------------- chrome */

.chrome {
  position: fixed;
  z-index: 60;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 22px clamp(18px, 4vw, 46px);
  transition: opacity 0.9s ease;
}
.chrome--top {
  top: 0;
}
.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--display);
  font-weight: 400;
  font-size: 15px;
  letter-spacing: 0.02em;
}
/* The mark is a crest — taller than it is wide — so it has to be sized off its
   height to sit level with the wordmark beside it. Sizing by width squashed the
   old lockup into a 26x6 smear. */
.brand img {
  height: 26px;
  width: auto;
}
.chrome__nav {
  display: flex;
  gap: 26px;
  font-size: 12px;
  font-weight: 300;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}
.chrome__nav a:hover {
  color: #fff;
}
/* Current page. A span rather than a link to itself, so the item is present
   in every nav — the row stops sliding sideways as you move between pages —
   without offering a click that goes nowhere. */
.chrome__nav .is-current {
  color: #fff;
}

.counter {
  position: fixed;
  z-index: 60;
  right: clamp(18px, 4vw, 46px);
  bottom: 34px;
  transition: opacity 0.9s ease;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 18px;
  border: 1px solid var(--hair);
  border-radius: 999px;
  background: rgba(4, 10, 24, 0.45);
  backdrop-filter: blur(10px);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
}
.counter__index {
  color: var(--faint);
}
.counter__label {
  color: var(--blue-soft);
}

/* ---------------------------------------------------------------- scenes */

main {
  position: relative;
  z-index: 10;
  transition: opacity 0.9s ease;
}

.scene {
  min-height: 145vh;
  display: flex;
  align-items: center;
  padding: 0 clamp(20px, 6vw, 90px);
  pointer-events: none;
}
.scene__inner {
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  will-change: transform, opacity;
}
.scene__inner--center {
  text-align: center;
  max-width: 900px;
}
.scene__inner--left {
  max-width: 620px;
  margin: 0;
}

.eyebrow {
  margin: 0 0 18px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--blue);
}

.display {
  margin: 0 0 20px;
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(46px, 9vw, 116px);
  line-height: 1.02;
  letter-spacing: -0.035em;
}
.display--small {
  font-size: clamp(36px, 6.4vw, 82px);
}
.headline {
  margin: 0 0 22px;
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(34px, 5.6vw, 72px);
  line-height: 1.06;
  letter-spacing: -0.03em;
}
.headline em,
.display em {
  font-style: normal;
  color: var(--blue-soft);
}
.lede {
  margin: 0 auto 44px;
  max-width: 620px;
  font-weight: 200;
  font-size: clamp(15px, 1.8vw, 20px);
  line-height: 1.7;
  color: var(--muted);
}
.body {
  margin: 0 0 18px;
  font-weight: 200;
  font-size: clamp(15px, 1.5vw, 18px);
  line-height: 1.8;
  color: rgba(255, 255, 255, 0.76);
}
.body--muted {
  color: var(--muted);
  font-size: clamp(14px, 1.4vw, 17px);
}

.hint {
  margin: 46px 0 0;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--faint);
  animation: bob 2.4s ease-in-out infinite;
}
@keyframes bob {
  0%,
  100% {
    transform: translateY(0);
    opacity: 0.4;
  }
  50% {
    transform: translateY(5px);
    opacity: 0.9;
  }
}

/* doors */

.doors {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 16px;
  max-width: 780px;
  margin: 0 auto;
}
.door {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  min-height: 170px;
  padding: 26px;
  border: 1px solid var(--hair);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.015);
  backdrop-filter: blur(3px);
  text-align: left;
  transition:
    border-color 0.4s ease,
    background 0.4s ease,
    box-shadow 0.4s ease,
    opacity 0.4s ease,
    transform 0.4s ease;
}
.door:hover {
  border-color: rgba(255, 255, 255, 0.28);
  background: rgba(255, 255, 255, 0.05);
  transform: translateY(-3px);
  /* The particle field collapses into this rectangle on hover, so the card has
     to look like it is actually holding something rather than sitting in front
     of it. */
  box-shadow:
    inset 0 0 44px rgba(72, 156, 255, 0.16),
    0 0 34px rgba(22, 104, 216, 0.16);
}
/* Pull focus to the one being fed. */
.is-gathering .door:not(:hover) {
  opacity: 0.5;
}
.door__tag {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--faint);
}
.door__title {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(24px, 3vw, 36px);
  letter-spacing: -0.01em;
}
.door__arrow {
  margin-top: auto;
  color: var(--blue-soft);
  transition: transform 0.4s ease;
}
.door:hover .door__arrow {
  transform: translateX(6px);
}

/* tags */

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
}
.tags li {
  padding: 7px 14px;
  border: 1px solid var(--hair);
  border-radius: 999px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

/* split */

.split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 28px;
  margin-top: 44px;
  text-align: left;
}
.split__col {
  padding: 26px 24px;
  border-top: 1px solid var(--hair);
}
.split__num {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.24em;
  color: var(--blue);
}
.split__col h3 {
  margin: 14px 0 10px;
  font-family: var(--display);
  font-weight: 300;
  font-size: 22px;
}
.split__col p {
  margin: 0 0 16px;
  font-weight: 200;
  font-size: 15px;
  line-height: 1.7;
  color: var(--muted);
}
.link {
  font-size: 13px;
  font-weight: 300;
  color: var(--blue-soft);
}
.link:hover {
  color: #fff;
}
/* Standalone follow-on link under a list or a card grid. `.link` is inline and
   had only ever been used inside a flex column, so on its own it butts straight
   up against the block above it. */
.link--block {
  display: inline-block;
  margin-top: 24px;
}

/* services list */

.services {
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--hair);
}
.services li {
  border-bottom: 1px solid var(--hair);
}
.services a {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 15px 0 15px 16px;
  border-left: 1px solid transparent;
  transition:
    border-color 0.3s ease,
    padding-left 0.3s ease;
}
.services a:hover {
  border-left-color: var(--blue);
  padding-left: 24px;
}
.services b {
  font-family: var(--display);
  font-weight: 400;
  font-size: 17px;
}
.services span {
  font-size: 13px;
  font-weight: 200;
  line-height: 1.6;
  color: var(--faint);
}

/* product cards */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 16px;
  margin-top: 40px;
  text-align: left;
}
.card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 26px 24px;
  border: 1px solid var(--hair);
  border-radius: 16px;
  /* Opaque enough to stay readable when the particle shape passes behind. */
  background: rgba(6, 12, 26, 0.82);
  backdrop-filter: blur(8px);
  transition:
    border-color 0.4s ease,
    transform 0.4s ease,
    background 0.4s ease;
}
.card:hover {
  border-color: rgba(32, 139, 255, 0.55);
  background: rgba(32, 139, 255, 0.06);
  transform: translateY(-4px);
}
.card--lead {
  grid-row: span 2;
}
.card__tag {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--blue);
}
.card h3 {
  margin: 0;
  font-family: var(--display);
  font-weight: 300;
  font-size: 22px;
  letter-spacing: -0.01em;
}
.card sup {
  font-size: 11px;
  opacity: 0.7;
}
.card p {
  margin: 0;
  font-size: 14px;
  font-weight: 200;
  line-height: 1.7;
  color: var(--muted);
}
.card__cta {
  margin-top: auto;
  padding-top: 14px;
  font-size: 13px;
  color: var(--blue-soft);
}

/* actions + footer */

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: center;
  margin-top: 34px;
}
.btn {
  padding: 14px 30px;
  border: 1px solid var(--hair);
  border-radius: 999px;
  font-size: 14px;
  font-weight: 300;
  transition:
    background 0.35s ease,
    border-color 0.35s ease,
    color 0.35s ease;
}
.btn:hover {
  border-color: rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.08);
}
.btn--primary {
  background: var(--blue);
  border-color: var(--blue);
  color: #fff;
}
.btn--primary:hover {
  background: #46a3ff;
  border-color: #46a3ff;
}

/* The credits roll. Four real destinations at the end of the experience, so the
   scroll resolves into navigation instead of a dead end with a mailto. */
.sitemap {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 1px;
  max-width: 780px;
  margin: 54px auto 0;
  background: var(--hair);
  border: 1px solid var(--hair);
  border-radius: 14px;
  overflow: hidden;
}
.sitemap a {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 20px 18px;
  background: rgba(4, 8, 18, 0.6);
  font-family: var(--display);
  font-weight: 400;
  font-size: 15px;
  text-align: left;
  transition:
    background 0.35s ease,
    color 0.35s ease;
}
.sitemap a:hover {
  background: rgba(255, 255, 255, 0.06);
}
.sitemap a span {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--faint);
}

.footer {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
  margin-top: 70px;
  font-size: 12px;
  font-weight: 200;
  color: var(--faint);
}
.footer__sep {
  opacity: 0.5;
}
.footer a:hover {
  color: #fff;
}

/* --------------------------------------------------- fallbacks + motion */

@media (max-width: 720px) {
  .chrome__nav {
    display: none;
  }
  .scene {
    min-height: 130vh;
  }
  .card--lead {
    grid-row: auto;
  }
}

/* No WebGL: drop the cinematic layer, keep a readable dark page. */
html.no-webgl .stage,
html.no-webgl .counter {
  display: none;
}
html.no-webgl body {
  background: linear-gradient(160deg, #04070f 0%, #0a1a35 100%);
}
html.no-webgl .scene {
  min-height: auto;
  padding-top: 90px;
  padding-bottom: 90px;
}
html.no-webgl .scene__inner {
  opacity: 1 !important;
  transform: none !important;
  pointer-events: auto !important;
}

@media (prefers-reduced-motion: reduce) {
  .preloader__mark img,
  .hint {
    animation: none;
  }
  .scene {
    min-height: 100vh;
  }
  * {
    transition-duration: 0.01ms !important;
  }
}

/* --------------------------------------------------- mobile menu */

.chrome__menu {
  display: none;
  position: relative;
  width: 40px;
  height: 40px;
  margin: -8px -8px -8px 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  cursor: pointer;
}
.chrome__menu span {
  position: absolute;
  left: 10px;
  width: 20px;
  height: 1px;
  background: currentColor;
  transition:
    transform 0.3s ease,
    opacity 0.2s ease;
}
.chrome__menu span:nth-child(1) {
  top: 15px;
}
.chrome__menu span:nth-child(2) {
  top: 20px;
}
.chrome__menu span:nth-child(3) {
  top: 25px;
}
body.nav-open .chrome__menu span:nth-child(1) {
  transform: translateY(5px) rotate(45deg);
}
body.nav-open .chrome__menu span:nth-child(2) {
  opacity: 0;
}
body.nav-open .chrome__menu span:nth-child(3) {
  transform: translateY(-5px) rotate(-45deg);
}

@media (max-width: 720px) {
  .chrome__menu {
    display: block;
  }
  /* Overrides the older rule that hid the nav outright with nothing to
     replace it. The nav still collapses — it just becomes an overlay. */
  .chrome__nav {
    position: fixed;
    inset: 0;
    z-index: 90;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    padding: 0 34px;
    background: rgba(4, 7, 15, 0.96);
    backdrop-filter: blur(14px);
    font-size: 22px;
    letter-spacing: 0.02em;
    text-transform: none;
    color: #fff;
    opacity: 0;
    pointer-events: none;
    transform: translateY(-8px);
    transition:
      opacity 0.28s ease,
      transform 0.28s ease;
  }
  .chrome__nav a,
  .chrome__nav .is-current {
    padding: 13px 0;
    border-bottom: 1px solid var(--hair);
    font-family: var(--display);
    font-weight: 300;
  }
  .chrome__nav a:last-child,
  .chrome__nav .is-current:last-child {
    border-bottom: 0;
  }
  body.nav-open .chrome__nav {
    opacity: 1;
    pointer-events: auto;
    transform: none;
  }
  body.nav-open {
    overflow: hidden;
  }
  .chrome--top {
    z-index: 100;
  }
  /* The overlay is a child of the header, so lifting the header alone does
     nothing — the logo and the close button have to clear it themselves. */
  .chrome--top .brand,
  .chrome__menu {
    position: relative;
    z-index: 95;
  }
}

/* --------------------------------------------------------------- horizon
 *
 * The closing scene. The dune field is the particle cloud itself (uTerrain in
 * particles.js), so there is no canvas or background here — only the type that
 * sits on it. The scene aligns to the bottom because a landscape wants its
 * horizon high and its wordmark low, which is how the old site framed it. */
.scene--horizon {
  min-height: 100vh;
  align-items: flex-end;
  padding-bottom: clamp(28px, 6vh, 70px);
}
.scene__inner--horizon {
  max-width: 1240px;
}

.horizon__links {
  display: flex;
  flex-wrap: wrap;
  gap: 10px clamp(18px, 3vw, 34px);
  padding-bottom: clamp(18px, 3vw, 30px);
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
}
.horizon__links a {
  position: relative;
  padding-bottom: 3px;
  transition: color 200ms ease;
}
.horizon__links a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 100%;
  bottom: 0;
  height: 1px;
  background: var(--blue-soft);
  transition: right 260ms ease;
}
.horizon__links a:hover,
.horizon__links a:focus-visible {
  color: #fff;
}
.horizon__links a:hover::after,
.horizon__links a:focus-visible::after {
  right: 0;
}

/* Closing lockup. Matches .terrafoot__lockup on the content pages so the film
   and the rest of the site sign off identically. */
.horizon__lockup {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  color: #fff;
}
.horizon__lockup img {
  width: auto;
  height: 34px;
  display: block;
}
.horizon__lockup span {
  font-family: var(--display);
  font-weight: 300;
  font-size: 20px;
  letter-spacing: 0.02em;
}

.horizon__legal {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  padding-top: clamp(10px, 1.6vw, 18px);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--faint);
}
.horizon__legal a:hover {
  color: var(--blue-soft);
}
.horizon__sep {
  opacity: 0.4;
}

@media (max-width: 720px) {
  /* Clear the scene counter pill, which is pinned bottom-right. */
  .scene--horizon {
    padding-bottom: 96px;
  }
  .horizon__links {
    gap: 8px 18px;
    font-size: 9.5px;
  }
  .horizon__legal {
    font-size: 9px;
    letter-spacing: 0.18em;
  }
}

/* The horizon drives stage opacity from scroll position, frame by frame. The
   reveal transition has to come off or every step lags a second behind. */
.stage.is-horizon {
  transition: none;
}
